Guard the ADR index README's own hand-written prose against loss #140

Merged
rob merged 1 commit from task-198-guard-the-adr-index-prose into main 2026-08-12 10:01:08 +00:00
Owner

Task 198. AdrIndexTests only ever reads the generated table between the marker lines — everything outside them (numbering rule, Status conventions, "Open questions", "Provenance") had nothing checking it still existed. Lost the ADR-0105 row on 2026-08-11 (inside the table, already caught) and 118 lines of prose on 2026-08-12 (outside it, caught only by a reviewer reading the diff).

Two checks, argued in ADR-0120 rather than defaulted: every known section heading must still be its own line (catches a whole section vanishing), and the prose's own non-blank line count must clear a floor (100, against a measured 124) — catches a section trimmed to a stub while its heading survives. Deliberately not an exact-text match; says plainly what it does not cover.

Mutation-tested against both real incidents: deleting "Open questions" reddens the new test and leaves the table test green; dropping a table row reddens the table test and leaves the new test green.

Marker matching is now exact-whole-line everywhere (AdrIndex.FindMarkerLines), not a substring search, proved against the exact incident (a prose line mentioning both markers in backticks) and the mid-line case.

The splice tool now lives in-repo (scripts/regenerate-adr-readme.cs) rather than as an unreviewed external tool — that's how the second incident happened. Its marker-matching is a small, self-contained duplicate of AdrIndex.FindMarkerLines rather than a #:project reference to the tested method, because any #: directive at all trips this repo's formatting analyser as a build error under the pinned SDK (confirmed directly, not assumed) — a tooling limitation recorded in the ADR, not a design choice. Verified by direct invocation against both adversarial cases, the same way check-coverage-ratchet.cs already is (no test project references a file-based script).

docs/adr/README.md's own index table is regenerated (via the new script) to add this record's own row — the only change to that file besides the ADR-0088 status line already there.

1792 total / 1781 passing / 11 skipped (7 e2e, no browser locally; 4 WebUI repro tests). dotnet format --verify-no-changes clean. coverage-baseline.json untouched — no tracked assembly touched.

Task 198. `AdrIndexTests` only ever reads the generated table between the marker lines — everything outside them (numbering rule, Status conventions, "Open questions", "Provenance") had nothing checking it still existed. Lost the ADR-0105 row on 2026-08-11 (inside the table, already caught) and 118 lines of prose on 2026-08-12 (outside it, caught only by a reviewer reading the diff). Two checks, argued in ADR-0120 rather than defaulted: every known section heading must still be its own line (catches a whole section vanishing), and the prose's own non-blank line count must clear a floor (100, against a measured 124) — catches a section trimmed to a stub while its heading survives. Deliberately not an exact-text match; says plainly what it does not cover. Mutation-tested against both real incidents: deleting "Open questions" reddens the new test and leaves the table test green; dropping a table row reddens the table test and leaves the new test green. Marker matching is now exact-whole-line everywhere (`AdrIndex.FindMarkerLines`), not a substring search, proved against the exact incident (a prose line mentioning both markers in backticks) and the mid-line case. The splice tool now lives in-repo (`scripts/regenerate-adr-readme.cs`) rather than as an unreviewed external tool — that's how the second incident happened. Its marker-matching is a small, self-contained duplicate of `AdrIndex.FindMarkerLines` rather than a `#:project` reference to the tested method, because any `#:` directive at all trips this repo's formatting analyser as a build error under the pinned SDK (confirmed directly, not assumed) — a tooling limitation recorded in the ADR, not a design choice. Verified by direct invocation against both adversarial cases, the same way `check-coverage-ratchet.cs` already is (no test project references a file-based script). `docs/adr/README.md`'s own index table is regenerated (via the new script) to add this record's own row — the only change to that file besides the ADR-0088 status line already there. 1792 total / 1781 passing / 11 skipped (7 e2e, no browser locally; 4 WebUI repro tests). `dotnet format --verify-no-changes` clean. `coverage-baseline.json` untouched — no tracked assembly touched.
Guard the ADR index README's own prose against loss
All checks were successful
CI / build (pull_request) Successful in 3m20s
CI / container-images (pull_request) Has been skipped
CI / e2e (pull_request) Successful in 2m0s
195ebec262
rob left a comment

Verdict: mergeable

Verified independently, not just read:

  • The #: directive constraint is real. Tried #:project and a bare #:sdk line myself, in-repo: both fail with IDE0055 at (1,2)/(1,3). Copied the same #:sdk file outside the repo tree (no ancestor Directory.Build.props) and it ran clean, and a directive-free script in-repo also runs clean — isolates the failure to the directive specifically, under this repo's TreatWarningsAsErrors/EnforceCodeStyleInBuild combination, exactly as ADR-0120 attributes it (not a bare "SDK bug" overclaim).
  • Nothing catches the two copies drifting, confirmed by grep — no test project references scripts/regenerate-adr-readme.cs at all, only doc comments mention it. Worth having said explicitly, which ADR-0120's Consequences does.
  • Mutation-tested both incidents myself against the real docs/adr/README.md: deleting "Open questions these records raise" reddens only the new prose test (table test stays green); separately dropping the ADR-0105 row reddens only the table test (prose test stays green). Matches the PR's own claim exactly, restored after each.
  • MinimumProseLineCount: computed the file's actual non-blank prose line count directly — 124, matching the ADR's own stated measurement exactly. 100 leaves real headroom (24 lines) without coming close to waving through anything like the 118-line loss it exists to catch.
  • Ran the in-tree script myself against both adversarial cases (backtick mention before the real markers; a mid-line marker) — both behave exactly as claimed: correct splice in the first, a clear thrown error in the second.
  • Count (1792/1781/11, including the 7 E2E, all skip locally) and coverage-baseline.json untouched both confirmed directly. dotnet format --verify-no-changes clean in a fresh build.

No findings. The ADR is honest about what the guard doesn't cover (ADR-0066's own register) and about the remaining duplication being a tooling limitation to revisit, not a design choice.

Verdict: mergeable Verified independently, not just read: - **The `#:` directive constraint is real.** Tried `#:project` and a bare `#:sdk` line myself, in-repo: both fail with `IDE0055` at (1,2)/(1,3). Copied the same `#:sdk` file outside the repo tree (no ancestor `Directory.Build.props`) and it ran clean, and a directive-free script in-repo also runs clean — isolates the failure to the directive specifically, under this repo's `TreatWarningsAsErrors`/`EnforceCodeStyleInBuild` combination, exactly as ADR-0120 attributes it (not a bare "SDK bug" overclaim). - **Nothing catches the two copies drifting**, confirmed by grep — no test project references `scripts/regenerate-adr-readme.cs` at all, only doc comments mention it. Worth having said explicitly, which ADR-0120's Consequences does. - **Mutation-tested both incidents myself** against the real `docs/adr/README.md`: deleting "Open questions these records raise" reddens only the new prose test (table test stays green); separately dropping the ADR-0105 row reddens only the table test (prose test stays green). Matches the PR's own claim exactly, restored after each. - **`MinimumProseLineCount`**: computed the file's actual non-blank prose line count directly — 124, matching the ADR's own stated measurement exactly. 100 leaves real headroom (24 lines) without coming close to waving through anything like the 118-line loss it exists to catch. - **Ran the in-tree script myself** against both adversarial cases (backtick mention before the real markers; a mid-line marker) — both behave exactly as claimed: correct splice in the first, a clear thrown error in the second. - Count (1792/1781/11, including the 7 E2E, all skip locally) and `coverage-baseline.json` untouched both confirmed directly. `dotnet format --verify-no-changes` clean in a fresh build. No findings. The ADR is honest about what the guard doesn't cover (ADR-0066's own register) and about the remaining duplication being a tooling limitation to revisit, not a design choice.
rob merged commit 31611c6ff8 into main 2026-08-12 10:01:08 +00:00
rob deleted branch task-198-guard-the-adr-index-prose 2026-08-12 10:01:08 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
rob/PlaceMark!140
No description provided.