Commit 4ec3551
committed
fix(scripts): teach check:durability-log-level a declared failure-propagation vocabulary (#5241)
The gate had two legal answers for a catch guarding a durability-critical
callee — rethrow, or log at `error` — and no way to express the third:
the failure was handed to the CALLER. AGENTS.md's own judgment question
("does the system still look normal from the outside?") answers NO for
that shape, so it is not a degradation at all.
#4754 hit this the moment `saveMetaItem` entered the vocabulary: three of
its four hits were propagation, not degradation, and had to be parked in
`durability-degradation.baseline.json` — entries for CORRECT code, in a
shrink-only ledger whose header calls every line debt. Worse, the cheapest
way out at `meta.ts` was to bolt on a `logger.error` on a path whose common
case is a rejected request: one durability `error` per bad keystroke, the
mirror-image failure AGENTS.md names.
The vocabulary is DECLARED, never guessed, and the declaration only supplies
the NAME — the checker still proves the STRUCTURE (every path out of the
catch delivers the failure), so a declaration cannot become a baseline entry
wearing a friendlier name:
- FAILURE_PROPAGATION_CALLEES — repo-wide names (`errorFromThrown`), split
by how they deliver: `via: 'return'` (the value IS the answer, so it only
counts inside a `return`) vs `via: 'effect'` (the call IS the delivery).
- FAILURE_PROPAGATION_SITES — function-scoped names for the second shape:
a batch whose contract is a per-item outcome report, delivering through
`record(...)` / `failed.push(...)`. Keyed by file plus enclosing FUNCTION,
not by file: `protocol.ts` is nine thousand lines and a file-wide licence
for `saveMetaItem` would hide the next #4669. Entries are staleness-checked.
`catchDeliversFailure()` is conservative by construction: it can carry a
delivery forward but never invent one, and any exit it cannot prove delivered
counts as an escape — "cannot prove" reads as "does not deliver", which judges
the seam instead of excusing it.
Both #5241 baseline entries went stale and are deleted; the ledger is now
empty, which is its intended steady state. No production code changed — the
three sites were correct all along.
Self-test grows 19 -> 35 cases, pinning both halves of the rule: partial
propagation, an envelope built but never returned, a delivery in a later
callback, a report written on one branch only, an undeclared report shape,
and a site declaration keyed to a different function all still flag.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V7WetGmnfoXNn8cLieKKmx1 parent e0b2ea7 commit 4ec3551
3 files changed
Lines changed: 669 additions & 55 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
608 | 608 | | |
609 | 609 | | |
610 | 610 | | |
| 611 | + | |
| 612 | + | |
| 613 | + | |
| 614 | + | |
| 615 | + | |
| 616 | + | |
| 617 | + | |
| 618 | + | |
| 619 | + | |
| 620 | + | |
| 621 | + | |
| 622 | + | |
| 623 | + | |
| 624 | + | |
| 625 | + | |
| 626 | + | |
611 | 627 | | |
612 | 628 | | |
613 | 629 | | |
| |||
617 | 633 | | |
618 | 634 | | |
619 | 635 | | |
620 | | - | |
| 636 | + | |
| 637 | + | |
| 638 | + | |
| 639 | + | |
| 640 | + | |
621 | 641 | | |
622 | 642 | | |
623 | 643 | | |
| |||
0 commit comments