fix(features): gate 6 items on streamable-http/async + add lint-ci-no-default regression guard (Phase 8e, closes #295)#296
Merged
Conversation
…-default regression guard (Phase 8e, refs #295) Post-Phase-8 audit found that `cargo check --workspace --no-default-features` (playbook §996, the second of the four required Phase 8 validations) was never run during Phase 8. Doing so reveals 6 items reachable only when feature X is on but not themselves `#[cfg(feature = "X")]`-gated. Under strict CI (`-D warnings`) all 6 would have hard-failed. Source fixes (3 surgical cfg/cfg_attr annotations, zero behavior change in default + --all-features configs): * `uffs-mcp::McpStats::{avg_tool_latency_us,to_json}` → `#[cfg(feature = "streamable-http")]` (both only called by `http.rs`'s `/status` endpoint). * `uffs-client::daemon_ctl::keepalive_send_blocking` → `#[cfg(feature = "async")]` (only called by `connect_keepalive`, itself `async`-gated in `lib.rs`). * 3 `#[expect(clippy::cognitive_complexity, …)]` in `uffs-mcp::lib.rs` + `handler/mod.rs` → `#[cfg_attr(feature = "streamable-http", expect(…))]` (the lint score only crosses threshold when streamable-http is on; the conditional expect preserves the strict check when it actually triggers without leaving an unfulfilled expect when it doesn't). Regression guard: * New `lint-ci-no-default` gate added to `scripts/ci/gates.toml`: `cargo clippy --workspace --all-targets --no-default-features --no-deps -- -D warnings`. Mirrors `lint-ci` in flag stack + strictness; differs only in `--no-default-features` vs `--all-features`. Together the pair enforces the additivity invariant. * `just lint-ci-no-default` recipe added to `just/test.just`. * `pr-fast.yml::clippy-no-default` job added (mirrors `clippy` job). * Registered in `required.needs:` + aggregator table. * Pre-push hook regenerated via `just gen-hooks` (auto from manifest). * All 4 drift detectors green: gates-drift, hooks-drift, workflow-drift, fast-drift. Documentation: * `dependency_policy.md` §2: 5-tool table → 6-tool table; new paragraph explaining the additivity invariant the pair establishes. * `dependency_policy.md` §10: 8e decisions-log row. * `trait_policy.md:193`: Phase 7f TBD → #291 (Phase 8 follow-up #1). Adherence to the 5-rule contract: * **Rule 1** (no suppression hacks): zero `#[allow]` added. All 6 fixes are minimum-correct `#[cfg]` annotations that express the actual reachability; the 3 `expect`s become conditional rather than absolute. * **Rule 2** (surgical, correct fixes): 3 source files touched with 9 attribute lines added; no logic change. * **Rule 3** (preserve behavior + contracts): default + --all-features binary surface unchanged. All API contracts preserved. * **Rule 4** (improve tests, don't dodge them): new CI gate gives the whole workspace structural feature-additivity verification it lacked. * **Rule 5** (document & commit well): this commit message + 2 policy-doc updates + 4-line decisions-log entries explain the why, the what, and the guard against regression.
githubrobbi
added a commit
that referenced
this pull request
May 19, 2026
The Phase 7g decisions-log row in `trait_policy.md:194` read 'this PR' at the time of authoring (when PR #290 was open). After PR #290 merged the placeholder needed backfilling to '#290' to match the surrounding rows (#288/#289/#291). Companion to Phase 8e (PR #296), which already backfilled the sibling 'TBD' placeholder on row 193 (Phase 7f -> #291). This 1-line edit completes the decisions-log hygiene pass for Phase 7.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #295. Companion to the closed Phase-8 issue #195.
Post-Phase-8 audit found that
cargo check --workspace --no-default-features(playbook §996, the second of the four required Phase 8 validations) was never run during Phase 8. Doing so reveals 6 items reachable only when feature X is on but not themselves#[cfg(feature = "X")]-gated. Under strict CI (-D warnings) all 6 hard-fail. CI today runs only--all-featuresconfigurations which mask the dead-code + unfulfilled-expect warnings these gaps emit.Fixes
Source (3 surgical cfg/cfg_attr annotations, zero behavior change)
uffs-mcp::McpStats::avg_tool_latency_us#[cfg(feature = "streamable-http")]http.rs::/statusuffs-mcp::McpStats::to_json#[cfg(feature = "streamable-http")]http.rs::/statusuffs-client::daemon_ctl::keepalive_send_blocking#[cfg(feature = "async")]connect_keepalive(itselfasync-gated)uffs-mcp::lib.rs::run_mcp_server_with_config#[expect(cognitive_complexity)]#[cfg_attr(feature = "streamable-http", expect(…))]uffs-mcp::handler/mod.rs::on_roots_list_changedsameuffs-mcp::handler/mod.rs::call_toolsameRegression guard (new
lint-ci-no-defaultgate)scripts/ci/gates.toml: new[[gate]]block; mirrorslint-ciin flag stack +-D warningsstrictness; differs only in--no-default-featuresvs--all-features. Tiers:pre-push+pr-fast.just/test.just: newlint-ci-no-defaultrecipe.scripts/hooks/_lint_pre_push.sh: regenerated viajust gen-hooks(auto from manifest)..github/workflows/pr-fast.yml: newclippy-no-defaultjob, registered inrequired.needs:+ aggregator table.gates-drift(27 gates),hooks-drift,workflow-drift,fast-drift.Together
lint-ci(--all-features) +lint-ci-no-default(--no-default-features) establish the additivity invariant: everypub/pub(crate)item reachable only with feature X must compile cleanly both with feature X off AND with all features on.Documentation
docs/architecture/code-quality/dependency_policy.md§2: 5-tool table → 6-tool table; new paragraph explaining the additivity invariant.docs/architecture/code-quality/dependency_policy.md§10: 8e decisions-log row.docs/architecture/code-quality/trait_policy.md:193: Phase 7fTBD→#291(closes Phase 8 follow-up Bump the cargo group across 1 directory with 2 updates #1).Verification
cargo clippy --workspace --all-features -D warningscargo clippy --workspace --no-default-features -D warningscargo clippy -p uffs-client --no-default-features -D warningscargo clippy -p uffs-mcp --no-default-features -D warningscargo clippy -p uffs-cli --features mcp-http-probe -D warningsPre-push gate: full 24-gate run green in 106 s (
lint-ci-no-defaultfires in ~1 s warm).5-rule contract adherence
#[allow]added. All 6 fixes are minimum-correct#[cfg]annotations expressing actual reachability. The 3expects become conditional rather than blanket — they preserve the strict check when triggered, no unfulfilled-expect when not.--all-featuresbinary surface byte-identical. All API contracts preserved.Follow-ups
This closes Phase 8 follow-up #1 (
trait_policy.mdTBD) and addresses the audit-finding gap (cargo tree --workspace -e featuressnapshot is local-only baseline; not in scope for this PR).