Say which failure is the cause and which are its echoes - #490
Merged
Conversation
One dead hook runtime produced four independent-looking findings, and a reader had no way to tell the cause from the consequences. A dependent whose failure only restates its dependency's now carries `blockedBy` naming the root, so a fix plan can name causes once instead of repeating a symptom per row. The rule the whole milestone rests on is that annotation is not suppression. A blocked row keeps its status, its detail and its own evidence, and still appears in the report. A suppressed row is how a diagnostic lies by not looking, which is the defect #458 was, and a collapse that hid rows would have reintroduced it while claiming to reduce noise. The constructor refuses to name an `ok` blocker rather than trusting callers to avoid it. A collapse that points at a healthy check is worse than no collapse: it tells a reader to fix something that is not broken, and nothing downstream can detect the mistake. Independence is preserved deliberately. A stale stub whose runtime is also dead keeps its own finding unannotated, because that failure survives fixing the runtime and a fix plan that dropped it would leave the user with a repaired dependency and an unrepaired stub. Limit: only two edges are declared -- inject-version on inject-runtime, and the §2.2 checks on the capture chain -- so a dependency nobody wrote down still surfaces as an independent finding Ruled-out: declaring commit-msg-hook on hook-runtime to complete the graph | that edge runs backwards against registry order, and a declared edge the emission order cannot satisfy is a lie in the structure the fix plan walks Ruled-out: omitting a blocked row from the report and keeping it only in the JSON | the text report is what a user reads, and a row missing from it is indistinguishable from a check that was never run Warn: `blockedBy` resolves chains to the root, so a two-link chain reports the far cause and the intermediate failure is visible only as its own row -- correct for a fix plan, and surprising if read as a parent pointer Blast: local Undo: easy Certainty: firm Verified: thirteen rows in and thirteen out with collapse active, no row omitted and no `blockedBy: null` in the serialized report; a blocked dependent keeps its detail and evidence, a chain resolves to its root, an independent failure stays unannotated, and naming an ok blocker throws Provenance: authored Record-Id: r-collapse466
CommitLore — record lintTrailers: clean — 1 commit in Active constraints for the paths this PR touchesLimits (110)
Ruled out (253)
Truncated: 124 lines omitted — the comment hit GitHub's 65000 character limit. Trailer violations fail this check. Active constraints are informational — they are what the repository already decided, not a verdict on this PR. |
7 tasks
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.
Closes #466. Sixth ticket of Doctor · Diagnostic Rigor. Text report byte-identical.
One dead runtime, four independent-looking findings
A reader had no way to tell the cause from the consequences. A dependent whose failure only restates its dependency's now carries
blockedBynaming the root, so a fix plan can name causes once instead of repeating a symptom per row.Annotation is not suppression — the rule the milestone rests on
A blocked row keeps its status, its detail and its own evidence, and still appears in the report. A suppressed row is how a diagnostic lies by not looking, which is what #458 was. A collapse that hid rows would have reintroduced that defect while claiming to reduce noise.
Verified on a live run: 13 rows in, 13 rows out with collapse active, and no
"blockedBy":nullanywhere in the serialized report.The constructor refuses an ok blocker
Beyond what the ticket asked. A collapse pointing at a healthy check is worse than no collapse — it tells a reader to fix something that is not broken, and nothing downstream can detect the mistake.
Independence preserved deliberately
A stale stub whose runtime is also dead keeps its own finding unannotated, because that failure survives fixing the runtime. A fix plan that dropped it would leave the user with a repaired dependency and an unrepaired stub.
Tests
Chain resolves to root · blocked row keeps detail and evidence · independent failure stays unannotated ·
blockedByomitted rather than null · naming an ok blocker throws.Stated limits
Only two edges are declared. A dependency nobody wrote down still surfaces as an independent finding.
commit-msg-hook → hook-runtimeis deliberately not declared: that edge runs backwards against registry order, and a declared edge the emission order cannot satisfy is a lie in the structure the fix plan walks.blockedByresolves chains to the root, so a two-link chain reports the far cause — correct for a fix plan, surprising if read as a parent pointer.CI note
The full local run showed
test/secret-guard.test.ts > regex costfailing under three concurrent suites; it passes 79/79 in isolation and touches nothing here.