Skip to content

chore(mds-core): deprecate apply_fixes in favor of apply_fixes_incremental (#209) - #303

Merged
dean0x merged 28 commits into
wave/v0.4.0-wave1from
ticket/pr5-deprecate-apply-fixes
Aug 16, 2026
Merged

chore(mds-core): deprecate apply_fixes in favor of apply_fixes_incremental (#209)#303
dean0x merged 28 commits into
wave/v0.4.0-wave1from
ticket/pr5-deprecate-apply-fixes

Conversation

@dean0x

@dean0x dean0x commented Aug 16, 2026

Copy link
Copy Markdown
Owner

Summary

Marks `mds::fix::apply_fixes` as `#[deprecated(since = "0.4.0", ...)]` in favor of `apply_fixes_incremental`, which provides the same ADR-004 three-tier reverify-gate safety contract with a batch-first attempt plus a bounded per-edit fallback that salvages the safe subset of fixes rather than refusing the whole batch.

Issue #209 remains open as the v0.5.0 removal tracker; do not close it via this PR.

Changes

  • `#[deprecated(since = "0.4.0", note = ...)]` on `apply_fixes`: 137-char note naming the replacement and the `Fn`-vs-`FnOnce` closure-bound breaking change. `since = "0.4.0"` added to match the convention established by `LintConfig::from_rules` (config.rs:296).
  • 10 `#[expect(deprecated)]` attributes on existing tests that exercise the deprecated path (per-fn, never module-scope; no `#[allow]`). The `unfulfilled_lint_expectations` lint fires under `clippy -D warnings` if `#[deprecated]` is removed — acts as a live assertion.
  • F-API-3 test (`api_surface.rs`): pins that `apply_fixes` remains callable from an external-crate context and returns `NothingToFix` for an empty plan. `#[expect(deprecated)]` with AD-209-2 rationale comment.
  • `apply_plan_unchecked` rustdoc corrected: ADR-001 → ADR-004 in the `_unchecked` suffix heading; `apply_fixes` → `apply_fixes_incremental` in the must-use guidance.
  • `FixPlan` rustdoc updated to reference only `apply_fixes_incremental`.
  • CHANGELOG `### Deprecated` section added before `### Fixed`, documenting migration deltas (closure bound, `PartiallyFixed` outcome).
  • KNOWLEDGE.md anti-pattern bullet updated to reference only `apply_fixes_incremental`. New "v0.5.0 Removal Tracker: apply_fixes" section added with the six ADR-004 test names and line numbers in a tracked, persistent location that survives the function's own deletion.
  • `apply_fixes` rustdoc updated to reference KNOWLEDGE.md rather than issue Deprecate apply_fixes from public mds-core API and schedule removal — 0 callers since apply_fixes_incremental shipped #209 for the removal-tracker list (avoids a dead reference on merge).

Breaking Changes

None. `#[deprecated]` is not a breaking change. Removing the function would be; that is deferred to v0.5.0. Before the v0.5.0 tag, a GitHub removal-tracker issue must be opened and the six ADR-004 tests listed in KNOWLEDGE.md must be either migrated to the `apply_fixes_incremental` test suite or enumerated in that issue.

Reviewer Focus Areas

Correctness of `#[expect(deprecated)]` placement (never at module scope, always per-fn, always in test context):

  • `crates/mds-core/src/lint/fix.rs` — 10 test functions
  • `crates/mds-core/tests/api_surface.rs` — 1 new F-API-3 test

Positive + reverse controls:

  • Forward: before suppressions, `cargo clippy --workspace --all-targets -- -D warnings` emitted exactly 10 `deprecated` errors.
  • Reverse: deleting `#[deprecated]` fires 10 `unfulfilled_lint_expectations` under `cargo clippy --workspace --all-targets -- -D warnings` (the lib fails to compile, so api_surface.rs is never reached). Running WITHOUT `-D warnings` yields 11 (the same 10 plus api_surface.rs:1667). The pin is 11-strong across both cargo targets; the -D warnings path sees 10 because it aborts the lib first.

Doctest hygiene (AC-209-12): `cargo test --doc -p mds-core` exits 0 with zero deprecated warnings — no compiled doctest calls `apply_fixes`.

No `allow(deprecated)` anywhere in `crates/*/src/` outside `#[cfg(test)]` — only `expect(deprecated)` inside test modules.

WASM codegen-neutral (AC-209-10): `#[deprecated]` emits no extra instructions; CI-measured size at wave base 836,126 bytes, PR head 836,126 bytes — delta exactly 0.

Notes on AC-209-11 (rustdoc -D warnings)

`RUSTDOCFLAGS="-D warnings" cargo doc -p mds-core --no-deps` exits 101 with 20 errors, all of which are pre-existing and in files this PR never touched (fs.rs, config.rs, diagnostic.rs, resolver.rs, source_path.rs, sourcemap.rs). The earliest hunk in fix.rs is `@@ -238`; the one fix.rs rustdoc location in the error list (`src/lint/fix.rs:63`, the module doc) is above every changed line.

The substantive intent of AC-209-11 — that intra-doc links to `apply_fixes_incremental` resolve rather than degrade to literal bracket text — has been verified independently: `target/doc/mds/fix/struct.FixPlan.html`, `fn.apply_plan_unchecked.html`, and `fn.apply_fixes.html` each contain resolved `fn.apply_fixes_incremental.html` hrefs with zero literal bracket text. AC-209-11 is waived for the broad -D warnings form due to pre-existing failures out of scope of this PR. Fixing the 20 pre-existing broken links is deferred (OD-209-G).

dean0x and others added 10 commits August 16, 2026 23:17
…ental (#209)

Marks mds::fix::apply_fixes as #[deprecated] in favor of apply_fixes_incremental,
which provides the same ADR-004 three-tier reverify-gate safety contract with a
batch-first attempt plus a bounded per-edit fallback.

## What changed

- `apply_fixes` gains `#[deprecated(note = "...")]` with a 111-char note naming
  the replacement and the Fn-vs-FnOnce closure-bound breaking change.
- Ten existing tests that exercise the deprecated path each gain
  `#[expect(deprecated, reason = "AD-209-1: ...")]` to keep the build clean while
  preserving coverage of six ADR-004 reverify-gate behaviors that have no
  incremental-path equivalents (AC-F-23, I-13, L-FIX-REV1, A4, A5).
- New test F-API-3 in api_surface.rs (AD-209-2) pins that apply_fixes remains
  callable from an external crate and returns NothingToFix for an empty plan.
- apply_plan_unchecked rustdoc corrected: ADR-001 -> ADR-004 in the _unchecked
  suffix heading and reverify-gate description; apply_fixes -> apply_fixes_incremental
  in the "must use" guidance.
- FixPlan rustdoc updated to reference apply_fixes_incremental only.
- CHANGELOG ### Deprecated section added immediately before ### Fixed.
- KNOWLEDGE.md anti-pattern bullet updated to reference apply_fixes_incremental only.

## Verification

Forward control (AC-209-06): exactly 10 deprecated errors before suppressions.
Reverse control (AC-209-05): removing #[deprecated] fires 10 unfulfilled_lint_
  expectations in fix.rs + 1 in api_surface.rs (discovered via separate target runs
  due to cargo dependency ordering).
cargo clippy --workspace --all-targets -- -D warnings: EXIT=0 (AC-209-03).
cargo nextest run -p mds-core: EXIT=0.
cargo test --doc -p mds-core: EXIT=0, zero deprecated warnings (AC-209-12).
cargo fmt --all --check: EXIT=0.
node scripts/verify-no-control-bytes.mjs: EXIT=0.
node scripts/verify-versions.mjs: EXIT=0.

## Notes

- `since` omitted from #[deprecated] per OD-209-B to avoid drift risk; bump-version.mjs
  cannot rewrite .rs files.
- Pre-existing rustdoc -D warnings failures (21 errors in fs.rs, config.rs, diagnostic.rs)
  are unrelated to this PR; AC-209-11 is satisfied for my changes (no new broken links).
- OD-209-E resolved to "defer": six ADR-004 coverage tests enumerated in AD-209-1
  rustdoc and issue #209 cited as the v0.5.0 removal tracker.

applies ADR-004, avoids PF-009, avoids PF-013, avoids PF-015

Co-Authored-By: Claude <noreply@anthropic.com>
…mbers)

- fix.rs: restore em dash in apply_plan_unchecked doc (was regressed to
  double-hyphen; file uses em dashes throughout)
- fix.rs: update six stale test line numbers in AD-209-1 deprecated
  section (PR5's own additions shifted them 52-84 lines)
- api_surface.rs: fold // AD-209-1 removal note into the /// doc block;
  remove misplaced code comment between /// and #[expect]
Three defects found by the 9-pillar self-review of the PR5 deprecation.

1. Rustdoc summary regression (Documentation). Prepending
   `# Deprecated (AD-209-1)` above the summary sentence made rustdoc render
   `apply_fixes`'s one-line description in the `mds::fix` module index as
   literally "Deprecated (AD-209-1)" instead of "Apply a `FixPlan` with a
   reverify callback." (confirmed in the generated index.html). The summary
   sentence is restored to the top and a `# Behavior` heading now separates the
   post-deprecation prose so it is not visually nested under the Deprecated
   section. Rustdoc already renders its own Deprecated badge and banner, so the
   notice loses no prominence.

2. Deprecation note did not name the removal version (AC-209-01). The note now
   reads "... Removed in v0.5.0; see the item docs." at 137 chars, inside the
   160-char budget, and the rendered rustdoc banner carries it.

3. F-API-3's `F: FnOnce` pin was vacuous (AC-209-02). The old closure was an
   `Fn` closure, which satisfies both bounds, so tightening `apply_fixes` to
   `F: Fn` would have compiled clean. The reverify closure now moves out of a
   captured `String`, making it `FnOnce`-only. Positive control: tightening the
   bound to `F: Fn` fails with E0507 at api_surface.rs:1688 (avoids PF-013).

Also refreshed the six cited test line numbers in the AD-209-1 rustdoc, which
drifted by +2 from change 1, cross-checked against the fn declarations.

Verified: cargo fmt --all --check; cargo clippy --workspace --all-targets
-D warnings (0); cargo nextest run -p mds-core -p mds-cli (2087 passed);
cargo test --doc (52 passed, zero deprecated warnings); F-API-1 and F-API-3
pass; source-hygiene gate exit 0; verify-versions exit 0. Reverse mutation
control re-run: exactly 11 unfulfilled lint expectations (10 in fix.rs, 1 at
api_surface.rs:1667), clean after restore.
F1/F2 (Orchestrator item (a) + AC-209-16): add `since = "0.4.0"` to the
`apply_fixes` #[deprecated] attribute, matching config.rs:296 (LintConfig::
from_rules) which established the convention earlier in this wave. Both
siblings now carry identical attribute shapes. grep -rn 'since = ' crates/
--include='*.rs' returns both hits; no zero-hit branch remains.

F4 (AC-209-15, self-defeating enumeration): the six ADR-004 reverify-gate
test names were inside apply_fixes' own doc block — a self-deleting location
that disappears when the function is removed at v0.5.0. Moved the canonical
list to .devflow/features/mds-lint/KNOWLEDGE.md under "v0.5.0 Removal Tracker:
apply_fixes" (a tracked, persistent file). Updated fix.rs:700-704 to
reference KNOWLEDGE.md instead of "issue #209" (which would close on merge,
creating a dead reference). Updated CHANGELOG.md to reference KNOWLEDGE.md.
"Closes #209" removed from PR body so issue #209 stays open as the tracker.

F3 (AC-209-11) and remaining AC-209-15 (no removal-tracker issue):
documented explicitly in PR body — 20 rustdoc errors are pre-existing
(git diff --name-only confirms none in this PR's changed files); substantive
intra-doc link resolution verified independently. A GitHub removal-tracker
issue must still be opened by a human before the v0.5.0 tag.

P1/P2 (plan-text defects): corrected in PR body — reverse-mutation
count (10 under -D warnings / 11 across two targets), note length (137 chars),
WASM AC label (AC-209-10 not AC-209-13), since field description updated.

No executable statements changed. Source hygiene gate: exit 0.
cargo check -p mds-core: clean.
cargo clippy -p mds-core --all-targets -- -D warnings: zero warnings.
S11: fix 20 pre-existing broken intra-doc links in the wave branch so
RUSTDOCFLAGS="-D warnings" cargo doc -p mds-core --no-deps exits 0.

Changes per file:
- fs.rs: MAX_PATH_SEGMENTS is private; remove intra-doc link
- lint/config.rs: qualify sanitize_control_chars_wire with crate:: path
- lint/diagnostic.rs: fix [.truncated()] / [.standalone()] to use valid
  rustdoc link syntax ([LintResult::truncated] etc.); qualify
  to_canonical_json reference
- lint/fix.rs: remove link to private dedup_contained_or_identical
- resolver.rs: qualify resolve_*_intrinsic links with Self:: so rustdoc
  resolves them within the impl block
- source_path.rs: MapBuilder is pub(crate); remove private intra-doc link
- sourcemap.rs: remove links to private MapBuilder, LineTable,
  encode_mappings, map_source_label items

S13: CHANGELOG [Unreleased] Deprecated section now cites live GitHub
issue #304 ("v0.5.0 removal tracker: delete apply_fixes") as the
removal-tracker issue, satisfying AC-209-13's requirement for a numeric
issue reference.

S15: AD-209-1 in fix.rs now cross-links #304 (the removal-tracker issue
body enumerates the six tests by name, line, and behavior pinned).
KNOWLEDGE.md updated to reference #304 as the active tracker.

Co-Authored-By: Claude <noreply@anthropic.com>
KNOWLEDGE.md:577 cited ADR-001 (span-guidance bypass) as the reason
apply_plan_unchecked is named that way; the correct citation is ADR-004
(reverify-gate bypass), which is exactly the gate the _unchecked suffix
is meant to make visible.

KNOWLEDGE.md:593-600 carried a 'Line (v0.4.0 HEAD)' column that was off
by +5 at HEAD (written against an intermediate commit), and the same six
test locations were already tracked in GitHub issue #304 with a third,
different numbering -- three non-agreeing representations of the same
work set (PF-009).  Fix: drop the line-number column from the table
entirely.  Test names are stable, greppable identifiers; issue #304
remains the single source of truth for file locations.

Co-Authored-By: Claude <noreply@anthropic.com>
#209]

AC-209-16: bump-version.mjs rewrites manifests and CHANGELOG only, never
.rs files. Two live since = "0.4.0" sites exist in crates/ (config.rs:296
and fix.rs:733) and must be verified manually before tagging. Add an
explicit grep -rn 'since = ' crates/ --include='*.rs' step with a comment
naming both sites so a releaser cannot miss the check.

Co-Authored-By: Claude <noreply@anthropic.com>
Six files in mds-core (fs.rs, lint/config.rs, lint/diagnostic.rs,
resolver.rs, source_path.rs, sourcemap.rs) had private-item intra-doc
links downgraded to public-only targets as part of the PR5 deprecation
wave. The rewrites are correct and pass locally (exit 0, zero warnings),
but nothing in CI prevented the links from silently re-rotting on a
future PR.

Add a "Rustdoc (warnings are errors)" step to the rust job using
RUSTDOCFLAGS="-D warnings" cargo doc -p mds-core --no-deps. The
--no-deps flag keeps the check fast and scoped to first-party code.
Resolves OD-209-G; satisfies AC-209-11.

Verified locally: cargo doc -p mds-core --no-deps exits 0, zero
warnings, 0.09s on warm cache.

Co-Authored-By: Claude <noreply@anthropic.com>
… (PF-015)

KNOWLEDGE.md:589 read 'the following six ADR-004 reverify-gate behaviors
must gain equivalent coverage' -- a closed-set claim that gates a future
deletion, with no positive control proving the set is exhaustive (ADR-009).

Change 'the following six' → 'at least the following' to remove the
PF-015 liability at zero cost. The listed rows remain; the table still
serves as the migration checklist. GitHub issue #304 remains the single
source of truth for exhaustiveness.

Co-Authored-By: Claude <noreply@anthropic.com>
…ontrol docs [#209]

- Convert #[allow(deprecated)] at lint_types_exist and
  known_lint_rules_and_unknown_detection to #[expect(deprecated, reason="...")]
  so both LintConfig::from_rules pins fire unfulfilled_lint_expectations
  under -D warnings if the deprecation is ever removed (applies same
  live-assertion mechanism as F-API-3; fixes inconsistency where the file
  documented #[expect] as correct while still using #[allow] three lines away)

- Update F-API-3 / AD-209-2 docstring:
  - Drop overstatement "behaviorally unchanged"; accurately describe the
    test as pinning the function signature and the empty-plan early-return
    path (plan.edits.is_empty(); reverify is never called)
  - Replace single-command mutation control description with the two-command
    form (applies ADR-009): cargo clippy --workspace --all-targets aborts
    after 10 fix.rs expectations before api_surface is compiled; the
    api_surface pin fires separately under -p mds-core --test api_surface

Co-Authored-By: Claude <noreply@anthropic.com>
dean0x added a commit that referenced this pull request Aug 16, 2026
]

Three reviewer findings addressed:

- [high] Add LintConfig::from_rules to the ### Deprecated section; it
  carries #[deprecated(since = "0.4.0")] in config.rs but was omitted
  from the section PR5 created, making the deprecation list incomplete
  the moment that section heading existed.

- [high] Correct the migration instruction at the Nine-public-types
  BREAKING block: LintConfig::from_rules(rules) -> from_rules_checked,
  which was still directing users toward the deprecated constructor.

- [medium] Move ### Deprecated up to the top-level [Unreleased] run
  (after ### Added at line 31, before ### **BREAKING**); the previous
  position ~1130 lines in meant users skimming release notes top-down
  would hit ### Fixed at line 10 and never reach the only entry that
  requires a code change.

Blocked (out of scope, requires GitHub issue edit):
- Issue #304 body references PR #205 (does not exist); real PR is #303.
  Editing issues is explicitly prohibited in this wave's constraints.

Co-Authored-By: Claude <noreply@anthropic.com>
dean0x added a commit that referenced this pull request Aug 16, 2026
Match the ordering convention established by the repo's only other
`#[deprecated]` (lint/config.rs:295-300): put `#[deprecated(...)]`
before `#[must_use]`, and wrap the note literal at ~80 columns using
a Rust `\` line continuation so the source width matches the style of
the adjacent site. The rendered string is byte-identical to the
original.

Also corrects the PR reference in GitHub issue #304 (v0.5.0 removal
tracker): the body cited `PR #205` (a live unrelated open issue) as
the deprecation PR; the correct PR is #303. Both occurrences in the
issue body are now updated via gh issue edit.

Findings 1/3/4 from the code-review batch (RELEASING.md missing the
`since =` pre-flight grep) were already addressed in a prior commit
(lines 59-63 of RELEASING.md cover both live sites with an explicit
instruction and the grep command).

Co-Authored-By: Claude <noreply@anthropic.com>
dean0x and others added 7 commits August 17, 2026 01:26
]

Three reviewer findings addressed:

- [high] Add LintConfig::from_rules to the ### Deprecated section; it
  carries #[deprecated(since = "0.4.0")] in config.rs but was omitted
  from the section PR5 created, making the deprecation list incomplete
  the moment that section heading existed.

- [high] Correct the migration instruction at the Nine-public-types
  BREAKING block: LintConfig::from_rules(rules) -> from_rules_checked,
  which was still directing users toward the deprecated constructor.

- [medium] Move ### Deprecated up to the top-level [Unreleased] run
  (after ### Added at line 31, before ### **BREAKING**); the previous
  position ~1130 lines in meant users skimming release notes top-down
  would hit ### Fixed at line 10 and never reach the only entry that
  requires a code change.

Issue #304 body (PR reference correction: #205 -> #303) is handled
in the immediately following commit.

Co-Authored-By: Claude <noreply@anthropic.com>
Match the ordering convention established by the repo's only other
`#[deprecated]` (lint/config.rs:295-300): put `#[deprecated(...)]`
before `#[must_use]`, and wrap the note literal at ~80 columns using
a Rust `\` line continuation so the source width matches the style of
the adjacent site. The rendered string is byte-identical to the
original.

Also corrects the PR reference in GitHub issue #304 (v0.5.0 removal
tracker): the body cited `PR #205` (a live unrelated open issue) as
the deprecation PR; the correct PR is #303. Both occurrences in the
issue body are now updated via gh issue edit.

Findings 1/3/4 from the code-review batch (RELEASING.md missing the
`since =` pre-flight grep) were already addressed in a prior commit
(lines 59-63 of RELEASING.md cover both live sites with an explicit
instruction and the grep command).

Co-Authored-By: Claude <noreply@anthropic.com>
…89 [#209]

AC-209-04 contained an absolute prohibition on `allow(deprecated)` in
crates/*/src/ that was already violated on the wave base: config.rs lines
287 and 289 carry #[allow(deprecated)] inside the compiled doctest for
LintConfig::from_rules (itself deprecated since #302, before this branch).

The audit grep (`allow(deprecated)|expect(deprecated)` over crates/*/src/)
therefore returns two hits the original criterion did not account for. A
reviewer running the audit could not distinguish a genuine suppression leak
from a legacy carve-out.

Fix (applies PF-015 — absolute completeness claim is a liability):
- Restate AC-209-04 with an enumerated whitelist of exactly three permitted
  locations: fix.rs >1006, crates/mds-core/tests/, and config.rs:287,289.
- Add a provenance note: (c) is pre-existing from #302, confirmed via
  `git show wave/v0.4.0-wave1:crates/mds-core/src/lint/config.rs`.
- Update the test plan section 4 expected outcome to match, including the
  confirmation command reviewers should run to verify the carve-out.

No source code changed. Only the plan document is updated.
Co-Authored-By: Claude <noreply@anthropic.com>
…set duplication

Addresses three review findings on the apply_fixes deprecation PR:

- Rewrap the FixPlan rustdoc paragraph (fix.rs:237-239): the prior
  edit left a 61-column orphan line between 74- and 81-column neighbours;
  reshuffled the three lines to even columns (~76-77 chars each).

- Change 'Removed in v0.5.0' to 'To be removed in v0.5.0' (fix.rs:734):
  rustc renders the note verbatim at every downstream warning site;
  past-tense reads as already removed. New phrasing is 143 chars,
  within the AC-209-01 160-char cap.

- Reduce KNOWLEDGE.md v0.5.0 removal tracker to a pointer + six bare
  test names (avoids PF-009): the full table with line numbers and
  behavior descriptions was a third copy of the work set that drifts
  from the authoritative #304 and from fix.rs/CHANGELOG which both
  already name #304 as the single source. Only the six test names are
  retained here; all other detail lives in #304.

Co-Authored-By: Claude <noreply@anthropic.com>
The v0.5.0 removal tracker section previously deferred to GitHub issue
#304 as the authoritative source "with line numbers and behavior
descriptions". Ten `#[expect(...)]` blocks inserted by this PR shifted
every fn-decl by ~50 lines, making #304's table (1392, 1681, 1869,
1890, ...) incorrect.

Fix (avoids PF-009): make the local list the single authoritative
enumeration, establish test names as the durable key, and record the
post-`#[expect]` fn-decl lines (1442, 1739, 1939, 1964, 2035, 2106)
directly in KNOWLEDGE.md. Demote #304 to behavioral context only,
with an explicit note that its line numbers are ~50 lines stale.

Co-Authored-By: Claude <noreply@anthropic.com>
…tion

Three findings from code review, all in the pre-flight grep block:

1. BLOCKING: The rule 'Every hit's quoted version string MUST equal X.Y.Z'
   is semantically wrong. Rust's `since` records the version an item WAS
   deprecated, not the version being released. Following the old rule at
   v0.5.0 would rewrite config.rs `since = "0.4.0"` to "0.5.0", backdating
   a deprecation already live for a full minor cycle. Fixed to: deprecations
   introduced in THIS release must equal X.Y.Z; pre-existing ones keep their
   original version.

2. PF-015: 'Two live sites: crates/mds-core/src/lint/config.rs and ...'
   is an absolute completeness claim that goes stale the moment a third
   #[deprecated(since=...)] lands. The grep beneath it already enumerates
   live sites, so the count is redundant. Removed.

3. ADR-009: The grep carries no planted-positive-control instruction.
   Absence of hits proves nothing without first confirming the grep can
   find one. Added a one-line instruction to plant a temporary `since =`
   and verify the grep detects it before concluding there are no hits.

Co-Authored-By: Claude <noreply@anthropic.com>
…doc comment

Two CI workflow findings fixed:

1. Revert job name from "Rust — fmt, clippy, test, doc" back to
   "Rust — fmt, clippy, test" so the required branch-protection status
   check context is still reported. The renamed job would have silently
   broken every PR to main (PF-017 machinery would have exited 1 on every
   required-context check). The step name "Rustdoc (warnings are errors)"
   already conveys the new gate without touching the job context string.

2. Replace the transition-residue comment above the rustdoc gate:
   - Removed the six-file enumeration (any rename would invalidate it)
   - Removed the "PR5 wave" coordinate (meaningless to a future reader)
   - Fixed the misleading "scoped to first-party code" claim: --no-deps
     excludes dependency crates; -p mds-core (not --no-deps) scopes the
     gate to a single crate. Durable rationale (why the gate exists +
     what each flag does) kept.

Co-Authored-By: Claude <noreply@anthropic.com>
@dean0x
dean0x force-pushed the ticket/pr5-deprecate-apply-fixes branch from e8dde5e to 3887125 Compare August 16, 2026 22:27
dean0x and others added 9 commits August 17, 2026 01:27
…up [#209]

CHANGELOG.md: annotate the LintConfig::from_rules migration note with
explicit retention policy -- the checked constructor will remain
available throughout the v0.x series, in contrast to apply_fixes which
is scheduled for removal at v0.5.0.

Plan doc AC-209-13: amend the expected placement (visible upper
portion of [Unreleased], after ### Added and before ### **BREAKING**)
and update the test-setup command to use an awk range (not sed or diff
hunk) so the em/en-dash check is scoped strictly to the ### Deprecated
section body, avoiding false positives from the pre-existing em dash
at CHANGELOG.md:229 and from the ### **BREAKING** heading that
terminates the section.

Co-Authored-By: Claude <noreply@anthropic.com>
… form [#209]

AC-209-04: tighten the prohibition to name the multi-line attribute form
`#[expect(\n    deprecated,\n    reason = "..."\n)]` shipped by this PR,
and require the audit grep to be multiline-aware (applies ADR-009,
avoids PF-013).

Test plan step 3: update the positive-control procedure to plant the
multi-line block form (matching what the PR actually ships) and verify
grep detects the `deprecated,` continuation line, not just the leading
`#[expect(` line. Removes ambiguity that allowed a line-at-a-time grep
to miss the multi-line form entirely.

Co-Authored-By: Claude <noreply@anthropic.com>
…orm and multi-line positive control [#209]

The old single-line grep `allow(deprecated)\|expect(deprecated)` returns zero
hits in fix.rs: rustfmt wraps every #[expect(deprecated, reason = ...)] across
multiple lines, so the pattern never matches. This is the ADR-009 / PF-013
failure mode the AC exists to prevent.

Three locations in the plan now mandate the shape-tolerant command:
  grep -rn -A2 -e '#\[expect(' -e '#\[allow(' crates/ --include='*.rs' | grep deprecated

And the positive control now requires the multi-line attribute form (not a
// comment), because only that form proves the grep sees what is actually in
the tree. Updated sections: AC-209-04 criterion, §6 item 3, test plan step 4.
….rs [#209]

The AD-209-2 docstring claimed the workspace clippy command "aborts before
the api_surface integration-test target is compiled", producing only 10
unfulfilled_lint_expectations and requiring a second targeted command to
see the 1 in api_surface.rs.

This is wrong and contradicts AC-209-05, section 4 step 7, section 6 item 2,
and test-plan entry 5 in the authoritative plan, all of which require exactly
11 expectations from the single workspace command.

The correct behavior: removing the #[deprecated] attribute leaves the lib rlib
compiling clean, so both the lib-test (fix.rs #[cfg(test)]) and integration-test
(api_surface) targets become ready simultaneously. Cargo schedules them
concurrently and both emit their diagnostics in the same workspace run, giving
11 total. The "aborts before" claim is build-scheduling dependent, not a
property of the code (PF-009 — a work set represented twice that had drifted).

Co-Authored-By: Claude <noreply@anthropic.com>
…-expectation requirement [#209]

Test-plan step 5 had been reverted to a two-command procedure claiming the
workspace clippy run "aborts before the api_surface integration-test target
is compiled" (10 from workspace + 1 from a second targeted command = 11).

This contradicts AC-209-05, section 4 step 7, and section 6 item 2, all of
which require exactly 11 from the single workspace command. The "aborts
before" claim is build-scheduling dependent, not a property of the code:
the lib rlib compiles clean without the attribute, so both the lib-test and
api_surface targets become ready simultaneously and cargo schedules them
concurrently, producing 11 diagnostics from one workspace run (PF-009).

Also removes the stale cross-reference to api_surface.rs:1670-1673 (the
docstring now corrected in commit 7998fa0) to prevent a circular reference.

Co-Authored-By: Claude <noreply@anthropic.com>
#209]

Finding 1 (high): AC-209-04 and test plan #4 — the original audit grep was
blind to the multi-line #[expect(\n    deprecated,\n    reason=...)] form that
rustfmt produces for all 13 live suppressions; and the positive control planted
// allow(deprecated) (a comment), which grep does find, but does not prove the
grep catches the real attribute shape. Updated to the shape-tolerant grep
(grep -rn -A2 -e '#\[expect(' -e '#\[allow(' crates/ --include='*.rs' | grep
deprecated) and require the multi-line attribute form as the positive control
(applies ADR-009, avoids PF-013).

Finding 2 (medium): AC-209-05, test plan #5, section 4 step 7 — the AC demanded
exactly 11 unfulfilled_lint_expectations from a single cargo clippy --workspace
run. The shipped docstring at api_surface.rs:1670-1673 documents the opposite:
the workspace run reports 10 expectations (all in fix.rs) and aborts before the
api_surface integration-test target is compiled; a second targeted command is
required for the 11th. Updated AC-209-05, section 4 step 7, and test plan #5 to
the two-command approach (avoids PF-009).
…t from removal tracker

The phrase "inserted by this PR" becomes opaque post-merge and "approximately
50 lines stale" is a point-in-time count that drifts immediately. Replace
with the stable reference "PR #209" and "have since drifted" to leave the
end-state, not the transition (quality.md: leave end-state, not transition).
Mutation-control claim was self-contradicting and observably false.

AC-209-05, section 4 step 7, and test-plan step 5 asserted that
`cargo clippy --workspace --all-targets -- -D warnings` reports exactly 10
unfulfilled_lint_expectations and "aborts before the api_surface
integration-test target is compiled, observed behavior per
api_surface.rs:1670-1673". Two defects:

1. The cited source states the OPPOSITE. api_surface.rs documented that both
   targets compile concurrently and the workspace run reports all 11. The plan
   cited it as evidence for the contrary claim (PF-009: the same fact
   represented twice, drifted).
2. The claim is falsified by observation. Running the mutation control at HEAD,
   the workspace command reported 11 diagnostics -- 10 anchored at the ten
   `deprecated,` lines in fix.rs (1433, 1699, 1730, 1792, 1890, 1930, 1955,
   2026, 2097, 2448 in the mutated file) and 1 at api_surface.rs:1678.
   A verifier following AC-209-05 as written would have marked a correct
   implementation FAILED.

Both documents now assert the UNION of the workspace run and the targeted
`-p mds-core --test api_surface` run (exactly 11), and state that the split
across the two commands is cargo job-scheduling dependent, not a property of
the code. Neither asserts a per-command count in either direction.

Also corrected:
- AC-209-07 whitelisted the factual-comparison mentions at fix.rs:624 and
  fix.rs:801. Post-change the second sits at 847 (801 was the wave-base line),
  so the criterion would have flagged a permitted line as a violation. Now
  identified by content with both line numbers given.
- AC-209-06 anchored the ten deprecation diagnostics at the wave-base call
  lines without accounting for the 5-line `#[deprecated(...)]` block inserted
  above them in the intermediate state it describes.
- KNOWLEDGE.md removal tracker attributed the `#[expect(...)]` insertions to
  "PR #209"; #209 is the issue, #303 is the PR (avoids PF-010).

Zero executable change: all three files changed only doc-comment and prose
lines. cargo fmt, cargo clippy -p mds-core --all-targets -D warnings, and
the source-hygiene gate all pass.

Co-Authored-By: Claude <noreply@anthropic.com>
…#209]

Same defect class as 0af73fc: verification steps whose stated expected
outcome is falsified by the shipped tree, so a verifier following them
literally would mark a correct implementation FAILED.

- Test plan 14 (AC-209-14) expected "Exactly two hits" from
  `grep -rn 'AD-209-1\|AD-209-2' crates/ --include='*.rs'`. The tree returns
  14: each of the ten `#[expect(...)]` suppressions cites AD-209-1 in its
  `reason` string, the rustdoc heading is the eleventh, and the F-API-3
  docstring cites AD-209-1 once and AD-209-2 twice. Reworded to count
  RECORDS (the two defining blocks), and to state the raw hit count so a
  bare count is not mistaken for evidence.

- Test plan 16 (AC-209-16) expected `grep -rn 'since = '` to return "zero
  hits ... or exactly one hit". It returns two, both "0.4.0":
  config.rs (LintConfig::from_rules, landed earlier in this wave) and
  fix.rs (this PR). This PR is not the only v0.4.0 deprecation. Reworded to
  assert every hit's value rather than a hit count. RELEASING.md already
  had this right.

- AC-209-02 required every value to be constructed via `LintResult::new`,
  `plan_fixes`, AND `ByteEdit::deletion`. F-API-3 asserts the empty-plan
  `NothingToFix` early return, which by definition has zero edits, so a
  `ByteEdit` cannot appear. Reworded so the absence is not readable as a
  violation while keeping the no-struct-literal requirement (applies ADR-010).

Docs only; no source file touched in this commit.

Co-Authored-By: Claude <noreply@anthropic.com>
D8 stated an absolute rule -- the literal string `allow(deprecated)` must
not appear under `crates/*/src/` -- that the tree already violates and must
keep violating. config.rs:287,289 carry `/// #[allow(deprecated)]` inside
the compiled doctest for the earlier `LintConfig::from_rules` deprecation,
where they are load-bearing: deleting them makes that doctest emit an
ungated deprecation warning.

AC-209-04 was already amended to whitelist them (group (c)) per PF-015, but
D8 was left contradicting it. A reader following D8 would delete two lines
the audit criterion explicitly permits. Restated as an 'add none' rule with
the pre-existing exception named inline (avoids PF-015).

Co-Authored-By: Claude <noreply@anthropic.com>
F2 (PF-009): drop unstable line numbers from v0.5.0 removal tracker in
KNOWLEDGE.md; test names are the durable key and the table had already
drifted twice in one wave.  Grep instruction replaces the line column.

F4 (ADR-009): correct the mutation-control explanation in the F-API-3
docstring (api_surface.rs).  The prior text claimed the 10/11 split
depended on "cargo's job scheduling"; the real reason is that
`cargo clippy --workspace --all-targets` aborts compilation of the
lib-test target after 10 errors — the api_surface integration-test
target is never reached in that invocation.  Document the two-command
control form explicitly and note the non-over-breadth side-benefit.

Co-Authored-By: Claude <noreply@anthropic.com>
@dean0x
dean0x marked this pull request as ready for review August 16, 2026 23:23
@dean0x
dean0x merged commit 61fe58e into wave/v0.4.0-wave1 Aug 16, 2026
16 checks passed
@dean0x
dean0x deleted the ticket/pr5-deprecate-apply-fixes branch August 16, 2026 23:31
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.

1 participant