Skip to content

feat(swarm): Wave 2 CI config + Wave 5 Rust splits + version regression guard#367

Merged
d-oit merged 7 commits into
mainfrom
fix/nightly-bridge-pr
May 13, 2026
Merged

feat(swarm): Wave 2 CI config + Wave 5 Rust splits + version regression guard#367
d-oit merged 7 commits into
mainfrom
fix/nightly-bridge-pr

Conversation

@d-oit
Copy link
Copy Markdown
Owner

@d-oit d-oit commented May 13, 2026

Summary

Swarm execution of Wave 2 (CI config fixes) and Wave 5 (Rust file splits + dedup) from GOAP plan, plus permanent fix for version regression (PR #270 root cause).

Wave 2 — CI Config Fixes

  • Fix coverage upload condition (literal 3.12)
  • Gitleaks: trim branches to [main], pin checkout to v6.0.2
  • Add flake8 to CI lint deps
  • Shellcheck severity warningerror
  • duckduckgo-searchddgs
  • Add Python 3.13 classifier + black/ruff target-version
  • AGENTS.md Playwright command includes all 3 projects
  • markdownlint: fix config format, suppress noisy rules, exclude skill refs

Wave 5 — Rust File Splits + Dedup

  • config.rs: 712→383 lines — split into config/{mod,defaults,parsing}.rs
  • semantic_cache.rs: 1056→4 files (max 401 lines) — split into {mod,ops,synthesis,tests}.rs
  • Extract duplicate build_budget() from query.rs/url.rs into cascade.rs
  • Remove dead Profile::is_provider_allowed() + max_hops()
  • cargo test: 52 passed (base) + 60 with --features semantic-cache
  • pytest -m "not live": 178 passed

Version Regression Guard (permanent fix for PR #270)

  • Root cause: Commit c283dfa (PR Fix semantic cache sqlite-vec compatibility and re-enable tests #270) merged old branch over v0.3.3, reverting all 4 manifests to 0.3.1
  • Fix: 3-layer defense:
    1. release.sh now calls sync_versions.py --set (handles all 4 files including cli.rs)
    2. CI validate-version job enforces manifest >= latest git tag on every PR
    3. Quality gate warns on version regression locally pre-commit

Version

  • All manifests synced to 0.3.4 (next patch after latest tag v0.3.3)

do-ops885 added 2 commits May 13, 2026 18:58
The nightly-bridge workflow was pushing format fixups directly to main,
which violates branch protection rules (no direct pushes, required status
checks). Switch to creating a PR via gh CLI on a dated branch instead.

Also fix the underlying formatting drift in tests/test_routing_foundation.py
that caused nightly to produce a diff every run.
Wave 2 (CI Config):
- Fix coverage upload condition, gitleaks branches, checkout pin
- Add flake8 to CI lint, fix shellcheck severity
- Update duckduckgo-search to ddgs, add 3.13 classifier
- Update AGENTS.md Playwright command to all 3 projects

Wave 5 (Rust Splits + Dedup):
- Split config.rs into config/{mod,defaults,parsing}.rs (712→383 lines)
- Split semantic_cache.rs into 4 submodules (1056→max 401 lines)
- Extract duplicate build_budget() to cascade.rs
- Remove dead Profile::is_provider_allowed() + max_hops()

Version Regression Guard:
- release.sh now uses sync_versions.py --set instead of raw sed
- CI validate-version job enforces manifest >= latest git tag
- Quality gate warns on version regression pre-commit
- Docs: AGENTS.md, agents-docs/RELEASES.md updated
- markdownlint: fix config format, suppress noisy rules, exclude skill refs

Version: 0.3.4 (sync after drift from PR #270)
@vercel
Copy link
Copy Markdown

vercel Bot commented May 13, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
do-web-doc-resolover Ready Ready Preview, Comment May 13, 2026 7:07pm

@deepsource-io
Copy link
Copy Markdown

deepsource-io Bot commented May 13, 2026

DeepSource Code Review

We reviewed changes in 6d9314e...73cded2 on this pull request. Below is the summary for the review, and you can see the individual issues we found as inline review comments.

See full review on DeepSource ↗

Code Review Summary

Analyzer Status Updated (UTC) Details
JavaScript May 13, 2026 6:14p.m. Review ↗
Python May 13, 2026 6:14p.m. Review ↗
Rust May 13, 2026 6:14p.m. Review ↗
Shell May 13, 2026 6:14p.m. Review ↗

Important

AI Review is run only on demand for your team. We're only showing results of static analysis review right now. To trigger AI Review, comment @deepsourcebot review on this thread.

@deepsource-io
Copy link
Copy Markdown

deepsource-io Bot commented May 13, 2026

DeepSource Code Review

We reviewed changes in 6d9314e...6645693 on this pull request. Below is the summary for the review, and you can see the individual issues we found as inline review comments.

See full review on DeepSource ↗

Important

Some issues found as part of this review are outside of the diff in this pull request and aren't shown in the inline review comments due to GitHub's API limitations. You can see those issues on the DeepSource dashboard.

PR Report Card

Overall Grade   Security  

Reliability  

Complexity  

Hygiene  

Code Review Summary

Analyzer Status Updated (UTC) Details
JavaScript May 13, 2026 7:07p.m. Review ↗
Python May 13, 2026 7:07p.m. Review ↗
Rust May 13, 2026 7:07p.m. Review ↗
Shell May 13, 2026 7:07p.m. Review ↗

Important

AI Review is run only on demand for your team. We're only showing results of static analysis review right now. To trigger AI Review, comment @deepsourcebot review on this thread.

Comment thread cli/src/config/mod.rs
}

/// Merge another config into self, overriding only set values
pub fn merge(&mut self, other: Config) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

`fn merge` has a cyclomatic complexity of 33 with "very-high" risk


A function with high cyclomatic complexity can be hard to understand and
maintain. Cyclomatic complexity is a software metric that measures the number of
independent paths through a function. A higher cyclomatic complexity indicates
that the function has more decision points and is more complex.

Comment thread cli/src/config/parsing.rs

use super::Config;

pub fn apply_env_overrides(config: &mut Config) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

`fn apply_env_overrides` has a cyclomatic complexity of 56 with "critical" risk


A function with high cyclomatic complexity can be hard to understand and
maintain. Cyclomatic complexity is a software metric that measures the number of
independent paths through a function. A higher cyclomatic complexity indicates
that the function has more decision points and is more complex.

Comment thread cli/src/config/parsing.rs
use super::Config;

pub fn apply_env_overrides(config: &mut Config) {
if let Ok(config_path) = env::var("DO_WDR_CONFIG") {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using `env::var` with a string literal


Calls to the std::env functions that use string literals instead of a
static strings can lead to bugs due to spelling errors.

Comment thread cli/src/config/parsing.rs
}
}

if let Ok(val) = env::var("DO_WDR_MAX_CHARS") {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using `env::var` with a string literal


Calls to the std::env functions that use string literals instead of a
static strings can lead to bugs due to spelling errors.

Comment thread cli/src/config/parsing.rs
config.max_chars = v;
}
}
if let Ok(val) = env::var("DO_WDR_MIN_CHARS") {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using `env::var` with a string literal


Calls to the std::env functions that use string literals instead of a
static strings can lead to bugs due to spelling errors.

Comment thread cli/src/config/parsing.rs
if let Ok(val) = env::var("DO_WDR_SEMANTIC_CACHE__ENABLED") {
config.semantic_cache.enabled = val.parse().unwrap_or(false);
}
if let Ok(val) = env::var("DO_WDR_SEMANTIC_CACHE__PATH") {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using `env::var` with a string literal


Calls to the std::env functions that use string literals instead of a
static strings can lead to bugs due to spelling errors.

Comment thread cli/src/config/parsing.rs
if let Ok(val) = env::var("DO_WDR_SEMANTIC_CACHE__PATH") {
config.semantic_cache.path = val;
}
if let Ok(val) = env::var("DO_WDR_SEMANTIC_CACHE__THRESHOLD") {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using `env::var` with a string literal


Calls to the std::env functions that use string literals instead of a
static strings can lead to bugs due to spelling errors.

Comment thread cli/src/config/parsing.rs
if let Ok(val) = env::var("DO_WDR_SEMANTIC_CACHE__THRESHOLD") {
config.semantic_cache.threshold = val.parse().unwrap_or(0.85);
}
if let Ok(val) = env::var("DO_WDR_SEMANTIC_CACHE__MAX_ENTRIES") {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using `env::var` with a string literal


Calls to the std::env functions that use string literals instead of a
static strings can lead to bugs due to spelling errors.

Comment thread cli/src/resolver/query.rs Outdated
fn default() -> Self {
Self::new()
}
fn default() -> Self { Self::new() }
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found call returning `Self` in `default()`


The default() function in the Default trait is used to create
a default instance of the type. While implementing this, if a function
call returns the same type, it could possibly create an infinite loop
by calling default() itself.

Ok(CacheStats {
entries: 0,
hit_rate: 0.0,
path: String::new(),
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empty call to `new()`


The new() function is used to initialise an object with specific data.
If no arguments are passed, the behaviour is identical to default().

@codacy-production
Copy link
Copy Markdown
Contributor

codacy-production Bot commented May 13, 2026

Not up to standards ⛔

🔴 Issues 2 minor

Alerts:
⚠ 2 issues (≤ 0 issues of at least minor severity)

Results:
2 new issues

Category Results
CodeStyle 2 minor

View in Codacy

🟢 Metrics 210 complexity · 15 duplication

Metric Results
Complexity 210
Duplication 15

View in Codacy

AI Reviewer: first review requested successfully. AI can make mistakes. Always validate suggestions.

Run reviewer

TIP This summary will be updated as you push new changes.

Copy link
Copy Markdown
Contributor

@codacy-production codacy-production Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements critical version safety infrastructure and refactors the Rust CLI configuration. However, the current implementation is not up to standards due to a high-severity logic error in configuration defaults where quality thresholds are inverted, and a security regression in the URL resolver.

While the goal of splitting large Rust files was achieved, the resulting modules (specifically ops.rs and parsing.rs) exhibit high cyclomatic complexity and significant code duplication without corresponding test coverage. Furthermore, architectural requirements for cache observability (ADR-014) have been ignored, as the stats implementation still returns hardcoded zeros. These issues must be addressed to ensure system reliability and security.

About this PR

  • The PR fails to implement real-time statistics for the Semantic Cache as required by ADR-014 (C9). Hardcoded return values remain in the codebase, hindering system observability.
  • The modification to quality_gate.sh that appends || true to the markdownlint command effectively silences the documentation quality gate. This contradicts the intent of ADR-013 to enforce documentation standards.
1 comment outside of the diff
cli/src/resolver/cascade.rs

line 11 🟡 MEDIUM RISK
Including ftp:// and ftps:// in url_patterns contradicts the security policy established in ADR-012 (Wave 3, S2), which requires is_url() to reject these schemes.

Test suggestions

  • Verify the CI 'validate-version' script correctly identifies and blocks version regressions using 'sort -V'.
  • Ensure the Rust semantic cache functionality remains intact after splitting into multiple files (ops.rs, synthesis.rs, etc.).
  • Verify 'sync_versions.py --set' updates the version string in cli/src/cli.rs in addition to the standard manifests.
  • Check that the nightly-bridge workflow successfully creates a PR using the GitHub CLI (gh pr create).
  • Add unit tests for apply_env_overrides in cli/src/config/parsing.rs to validate environment variable precedence.
  • Add unit tests for SemanticCache in cli/src/semantic_cache/ops.rs to cover normalized query logic and TTL expiration.
Prompt proposal for missing tests
Consider implementing these tests if applicable:
1. Add unit tests for `apply_env_overrides` in `cli/src/config/parsing.rs` to validate environment variable precedence.
2. Add unit tests for `SemanticCache` in `cli/src/semantic_cache/ops.rs` to cover normalized query logic and TTL expiration.

TIP Improve review quality by adding custom instructions
TIP How was this review? Give us feedback

Comment on lines +10 to +45
pub fn routing_profile_defaults(name: &str) -> RoutingProfileConfig {
match name {
"free" => RoutingProfileConfig {
max_provider_attempts: 3,
max_paid_attempts: 0,
max_total_latency_ms: 6_000,
quality_threshold: 0.70,
min_free_quality_to_skip_paid: 0.70,
allow_paid: false,
},
"fast" => RoutingProfileConfig {
max_provider_attempts: 2,
max_paid_attempts: 1,
max_total_latency_ms: 4_000,
quality_threshold: 0.60,
min_free_quality_to_skip_paid: 0.70,
allow_paid: true,
},
"quality" => RoutingProfileConfig {
max_provider_attempts: 6,
max_paid_attempts: 3,
max_total_latency_ms: 15_000,
quality_threshold: 0.55,
min_free_quality_to_skip_paid: 0.75,
allow_paid: true,
},
_ => RoutingProfileConfig {
max_provider_attempts: 4,
max_paid_attempts: 1,
max_total_latency_ms: 9_000,
quality_threshold: 0.65,
min_free_quality_to_skip_paid: 0.70,
allow_paid: true,
},
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 HIGH RISK

The quality_threshold values across profiles seem inverted. Currently, the 'Quality' profile (0.55) is more lenient than the 'Free' profile (0.70). A quality-focused profile should typically have a higher threshold to ensure better results are sought before terminating the cascade.

Comment thread cli/src/config/parsing.rs

use super::Config;

pub fn apply_env_overrides(config: &mut Config) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 MEDIUM RISK

Suggestion: The apply_env_overrides function is highly repetitive and complex due to the volume of environment variables being manually parsed (+56 complexity). Consider refactoring to a declarative approach, such as a table-driven mapping, and ensure unit tests are added as this file currently has no coverage.

@d-oit d-oit merged commit dcb0f94 into main May 13, 2026
36 of 38 checks passed
@d-oit d-oit deleted the fix/nightly-bridge-pr branch May 13, 2026 19:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants