Skip to content

spec: 010 Phase 3 — content defects, and a D5 harness that found a wrong figure - #87

Merged
iancooper merged 1 commit into
masterfrom
docs/spec-010-phase-3
Aug 8, 2026
Merged

spec: 010 Phase 3 — content defects, and a D5 harness that found a wrong figure#87
iancooper merged 1 commit into
masterfrom
docs/spec-010-phase-3

Conversation

@iancooper

Copy link
Copy Markdown
Member

Phase 3 = PR 3 of Spec 010. The first phase that edits a page body. 17 of 52 tasks done.

Three pages touched, one tool added. No page created, no URL moved, SUMMARY.md untouched.

Task 3.4 — noloss.py, the D5 harness every split in Phases 4–9 depends on

Takes originals at a git ref and results in the working tree (or at --result-ref), and reports every substantive line surviving nowhere. Both sides take several paths, because a fold’s check is the union of the pages.

A heading is compared by the anchor it produces, via linkcheck.py’s own slug(), imported rather than copied. A section that becomes a page promotes its headings and may shed their bold; slug() ignores both, so the anchor survives and nothing is lost. Requalifying a heading does change the slug and is reported — the class of change standing obligation 3 exists to catch.

Calibrating it produced a finding

Spec 011 recorded 24 and 4 lines for its two demonstrator splits. This returns 46 and 11, and reproduces both recorded figures exactly as subsets. The recorded numbers were the prose lines. The extra 22 and 7 are 20 requalified headings, 2 lines merged into surviving sentences, 4 structural labels dropped in a fold, and 3 lines of the two Quick Migration Guide blocks — the last visible in 011’s own debt figure falling 804 → 802.

Nothing contradicts 011: every extra line is documented in its write-up, just not in the D5 count. A figure that was never wrong can still not be the whole answer — and the half it missed is the anchor breaks.

Proved red four ways, mutation asserted before each result was read

Probe Result
identity, page against itself 0 of 92 — no false positives
one substantive line deleted reported, exit 1; restored byte-identical
heading promoted a level and bolded not reported — matched on its anchor alone
heading requalified reported — the allowance is not a hole

Task 3.1 — NOT DUPLICATE, which is the passing outcome

The two sections pair one-to-one by subject and share 32 of 58 substantive lines verbatim — every one a code fragment or a fence, and not one prose line. A 55% line overlap that is 0% prose overlap is two pages using the same worked domain, not one copied from the other. The relationship is level of detail: query object shape against end-to-end recipe.

So Task 6.4 keeps the section and lands at ~579. Recorded but deliberately not acted on: the two pages disagree about the same code (SalesStatistics vs SalesStatisticsDto, and two more).

Task 3.3 — the fold, and the duplicate copy was also wrong

The removed block configured subscriptions with options.AddSubscription<MyCommand>(...), which does not exist. ConsumersOptions exposes Subscriptions; the only AddSubscription in the source is Dispatcher’s private one. A reader who followed the explanation page would not have compiled. Duplication rots asymmetrically, and the copy that rots is the one nobody consults for parameters.

Folded into the reference: the TimeOut trade-off pair and the ordering caveat on multiple Performers. Not folded: the block that does not compile. HowServiceActivatorWorks.md 486 → 416; the reference stays at 233, since both folds extend existing bullets. D5 over the union returned 40 lines, all accounted for.

Task 3.2 — the typo

## How It Work## How Sweeper Circuit Breaking Works, the corpus house form. Zero inbound #how-it-work links, re-derived across contents/, SUMMARY.md and .gitbook.yaml rather than trusted from design §8.

pagelint.py --changed is still vacuous, and the handover predicted otherwise

Three pages under contents/ are touched, but the rule is strict per block overlapping the diff, and this diff is five single prose lines. File granularity was the wrong unit for the prediction. Confirmed live by probe instead: a using-less block inserted into a changed page is an error under --changed and a warning repo-wide. It first bites for real in Phase 4, the first phase to create a page.

Gates

linkcheck.py clean, 112 files
pagelint.py 0 errors, 797 warnings — debt falls 802 → 797, exactly the five C# blocks Task 3.3 removed
urlmap.py --check-shape 0 failures
urlmap.py --check-redirects 0 failures, 75 entries
pagetypes.tsv 110 rows, unchanged — no page created or retyped (standing obligation 7)

🤖 Generated with Claude Code

https://claude.ai/code/session_012tcdwxVb8NmKaX2S6fvyFg

…found a wrong figure

Phase 3 = PR 3, the first phase to edit a page body. Four tasks, 17 of 52 done.
Three pages touched, one tool added; no page created, no URL moved, SUMMARY.md
untouched.

Task 3.4, noloss.py, is the load-bearing one: every split in Phases 4-9 depends
on it. It takes originals at a git ref and results in the working tree (or at
--result-ref), and reports every substantive line surviving nowhere. Both sides
take several paths, because a fold's check is the union of the pages.

A heading is compared by the anchor it produces, via linkcheck.py's own slug(),
imported rather than copied. A section that becomes a page promotes its headings
and may shed their bold; slug() ignores both, so the anchor survives and nothing
is lost. Requalifying a heading does change the slug and is reported -- which is
the class of change standing obligation 3 exists to catch.

Calibrating it produced a finding. Spec 011 recorded 24 lines and 4 lines for its
two demonstrator splits; this returns 46 and 11, and reproduces both recorded
figures exactly as subsets. The recorded numbers were the prose lines. The extra
22 and 7 are 20 requalified headings, 2 lines merged into surviving sentences, 4
structural labels dropped in a fold, and 3 lines of the two Quick Migration Guide
blocks -- the last visible in 011's own debt figure falling 804 to 802. Nothing
contradicts 011: every extra line is documented in its write-up, just not in the
D5 count. A figure that was never wrong can still not be the whole answer, and
the half it missed is the anchor breaks.

Proved red four ways with the mutation asserted before each result was read:
identity returns 0 of 92; a deleted line is reported; a heading promoted and
bolded is not; a requalified heading is. The allowance is not a hole.

Task 3.1 returns NOT DUPLICATE, which is the passing outcome. The two sections
pair one-to-one by subject and share 32 of 58 substantive lines verbatim -- every
one of the 32 a code fragment or a fence, and not one prose line. A 55% line
overlap that is 0% prose overlap is two pages using the same worked domain, not
one copied from the other. The relationship is level of detail: query object
shape against end-to-end recipe. So Task 6.4 keeps the section and lands at ~579.
Recorded but not acted on: the two pages disagree about the same code.

Task 3.3 is the finding of the phase, because the duplicate copy was also wrong.
The removed block configured subscriptions with options.AddSubscription<T>(...),
which does not exist -- ConsumersOptions exposes Subscriptions, and the only
AddSubscription in the source is Dispatcher's private one. A reader who followed
the explanation page would not have compiled. Duplication rots asymmetrically,
and the copy that rots is the one nobody consults for parameters. Folded into the
reference: the TimeOut trade-off pair and the ordering caveat on multiple
Performers. Not folded: the block that does not compile.

Task 3.2 renames `## How It Work` to the corpus house form. Zero inbound
#how-it-work links, re-derived across contents/, SUMMARY.md and .gitbook.yaml
rather than trusted from design section 8.

pagelint --changed is still vacuous, and the handover predicted otherwise. Three
pages under contents/ are touched, but the rule is strict per block overlapping
the diff, and this diff is five single prose lines. File granularity was the
wrong unit for the prediction. Confirmed live by probe instead: a using-less
block inserted into a changed page is an error under --changed and a warning
repo-wide. It first bites for real in Phase 4, the first phase to create a page.

Gates: linkcheck 112 files, pagelint 0 errors, --check-shape 0, --check-redirects
0 at 75 entries. Debt falls 802 to 797, exactly the five C# blocks Task 3.3
removed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012tcdwxVb8NmKaX2S6fvyFg
@iancooper
iancooper merged commit 438166b into master Aug 8, 2026
6 checks passed
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