npx eslint . reported 0 errors, 53 warnings. The floor eroded the signal: a
genuinely new warning had to be spotted against noise, so 'lint is clean' was not
usable as a check. This takes it to zero.
Fifty of the 53 were one category in gsd-core/bin/gsd-tools.cjs — all unused
ARGUMENTS (error x30, cwd x10, raw x7, args x3), never unused variables. They are
the Command Routing Hub's uniform handler signature, function routeX({ args, cwd,
raw, error }), declared identically whether or not a handler uses all four
members. argsIgnorePattern: '^_' is structurally in conflict with that convention:
satisfying it would mean _-prefixing ~50 parameters and making the signature
non-uniform across the table. Option 1 of #2453: disable args checking for that
file only, keeping varsIgnorePattern intact so genuinely dead variables (the #2379
class) still surface — verified by injecting an unused variable, which still warns.
This is the config decision #732 explicitly deferred ('Severities stay warn (no
config change in this pass)').
The remaining three predate the issue's count of 51 and are real defects, not
suppressions:
- tests/workflow-compat.test.cjs — the step-9 lookahead used (?=\*\*10\.|\z).
\z is a Perl/Ruby end-of-input anchor with NO meaning in JavaScript; it matched
a literal 'z', so the lazy span silently stopped at the first z whenever **10.
was absent, truncating the captured step and letting the assertion pass against
a partial block. Corrected to $.
- tests/debugger-prevention.test.cjs — an unused RegExp built one line above the
one actually used. Removed.
- tests/installer-migrations.test.cjs — try/finally inside a test body, which
CONTRIBUTING prohibits ('verbose, masks test failures, not an approved
pattern'); the unused t was the symptom. Converted to t.after().
Closes#2453
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
* test(#1963): add failing-first prevention/postmortem contract tests
Epic #1957 Phase 3B. Source-text-is-the-product contract tests: blameless
5-Whys that BRANCHES per Phase 2A RCA (not a single-cause chain; treats agent
error as 'why was that possible?'), the 'why wasn't this caught?' question,
the recurrence-guard taxonomy (regression test / assertion / lint rule / KB
pattern), the KB-entry why_not_caught + recurrence_guard fields with backward
compat, the session-manager prevention summary line, and the Zawinski
scope-boundary (a block, not a subsystem).
Failing-first: reference, archive_session edit, KB schema extension, and
session-manager summary do not yet exist.
* feat(#1963): emit blameless-postmortem Prevention block at resolution
Epic #1957 Phase 3B. At archive_session the debugger now produces a
Prevention block with three blame-free components: a branching 5-Whys causal
chain (branches per Phase 2A RCA, not a single chain; 'agent error' prompts
'why was that possible?', never blame), a 'why wasn't this caught?' answer
naming the missed gate (test/typecheck/lint/review/verify), and a concrete
recurrence guard (regression test / assertion / lint rule / KB pattern).
The knowledge-base entry gains two structured fields (why_not_caught +
recurrence_guard) so future Phase-0 recall surfaces the prior prevention, not
just the prior fix. Additive: old entries without the fields still load. The
session-manager compact summary surfaces a one-line prevention summary.
Full rules extracted to gsd-core/references/debugger-prevention.md (slim
archive_session step + 2 KB fields kept in the agent). INVENTORY + manifest +
agent-size baseline + install-parity goldens + AGENTS.md updated.
* fix(#1963): address orthogonal review (CRITICAL append-template drift + Phase-0 consumption + parity test)
- CRITICAL: the archive_session KB append template omitted Why not caught +
Recurrence guard (only the Entry Format had them) — the feature's core
deliverable silently did not happen. Added both fields to the append template
the agent actually follows (nearest-instruction wins).
- HIGH: Phase 0 (KB read) only surfaced root_cause + fix; the new fields were
dead data. Extended the Phase 0 Evidence line to consume why_not_caught +
recurrence_guard when present (absent on old entries — backward compat holds).
- MEDIUM: added a cross-section parity test (every Entry-Format field must also
appear in the append template — the guard that would have caught the
Critical) + a Phase-0-consumption assertion.
- MEDIUM: the 'branches per Phase 2A' claim is now wired — reuses
reasoning_checkpoint.candidate_causes across the four categories.
- MEDIUM: recurrence-guard taxonomy gains type refinement + config-default
change; LOW: added 'build' gate to both surfaces for parity.
- NIT: compact-summary fallback shape ('no gate existed'); verify the guard
artifact exists before recording it.
* test(#1963): anchor Phase-0 consumption test on the specific heading
The regex /Phase 0[\s\S]{0,1200}/ matched the first 'Phase 0' in the file
(in knowledge_base_protocol prose), not the Phase 0 block in investigation_loop.
Anchor on '**Phase 0: Check knowledge base**' and widen to 1500 chars.
* chore(#1963): backfill changeset pr number (PR #2410)