Bug-hunt round 9: verbs agree with the gates they mint for, and two dead detector legs come alive - #519
Merged
Conversation
Eighteen records: twelve confirmed substantive findings, five confirmed nitpicks, and one adjacent defect noticed during refutation (recorded, not fixed here). Assisted-by: Claude:claude-fable-5
…tates it The round-8 gate correction changed RS001 from leaves-open/ to enters-resolved/-or-wontfix/, and the docs kept the superseded rule: the README's flagship refusal example quoted a message the gate no longer emits, and AGENTS.md and the record-lands-with-the-act principle both taught the predicate under which a bare delete of the open record satisfies the trailer — the exact hole that correction closed. Resolves: iss-2608261437041111 Assisted-by: Claude:claude-fable-5
The README counted /abcd:prepare-this-repo as the only plugin-side command the CLI lacks; /abcd:consult and /abcd:ingest are likewise host-delegated markdown with no Go verb (the brief's surface chapters and the 2026-07-11 sign-off both record the three together), so a reader looking for 'abcd consult' or 'abcd ingest' in the terminal found only 'unknown command'. Resolves: iss-2608261437042550 Assisted-by: Claude:claude-fable-5
…a Breaking section The CHANGELOG header promised each pre-1.0 break a **Breaking** section, but the derived ingest renders a closed set of six Keep a Changelog sections and refuses any other, so the promise is unfulfillable for every cut since v0.6.0's final manual roll. The header now states the derived truth; adr-37 carries a dated amendment recording that its interim called-out-under-Breaking clause lapsed when itd-73 landed, and the version-arithmetic comment quotes the amendment instead of the lapsed clause. Resolves: iss-2608261437046261 Assisted-by: Claude:claude-fable-5
The record explorer shipped without the theme control; the stylesheet's own header was corrected in that change and the build README's claim that the explorer ships the control was left behind, contradicting the sibling file one directory over. Resolves: iss-2608261437047965 Assisted-by: Claude:claude-fable-5
The glossary_terms_used machine field listed both core/epic — a term file that does not exist, whose name is the armed forbidden synonym — and its successor core/spec. The dangling entry sat in the blind spot between forbidden_synonyms (frontmatter out of scope) and record_schema (field not cross-referenced). core/spec already covers the concept, so the retired entry is dropped losslessly. Resolves: iss-2608261437046944 Assisted-by: Claude:claude-fable-5
The five shell pins in .gitattributes missed site-src/install.sh.tmpl — the one shell artefact the repository distributes: the site build copies its bytes into the /install.sh users pipe into sh, where a trailing carriage return on every line is a syntax error. Today every publishing path runs on a Linux runner, so the exposure is latent; the pin gives the template the control its siblings already have. Resolves: iss-2608261437040448 Assisted-by: Claude:claude-fable-5
The spc-28 rename (intent-fidelity-reviewer to intent-auditor, abcd intent review to abcd intent audit) listed disciplines/ in neither its swept inventory nor its not-swept exemptions, and the bucket is live state with no reachable reconciliation event — intent audit refuses a non-shipped intent, so the audited-when-first-audited promise in these files could never fire. Twenty-one substitutions across itd-1, itd-37, itd-81 and itd-84, including the two /abcd:intent review invocations in itd-1's spc-12 clause; stored artefact spellings (abcd-review markers, review-<ts> receipt directories, the logbook paths) stay frozen per spc-28, and drafts/ and planned/ stay unswept under the iss-94 convention. spc-28's not-swept paragraph records the late sweep. Resolves: iss-2608261437043634 Assisted-by: Claude:claude-fable-5
…udit The discipline named a machine-readable task_classes enum in internal/core/lint that has never existed and carried the retired intent_review token; the naming registry declared itself the source of truth today (iss-265) and the token flipped to intent_audit with spc-28. The three remaining intent-auditor name renames in this file ride the disciplines sweep landing beside this change. Resolves: iss-2608261437043962 Assisted-by: Claude:claude-fable-5
The planned intent still specified work against the retired terminology/ tree: it asserted an epic.md term file that does not exist, pointed its canonical-term scope bullet and acceptance criterion at a path that cannot come into existence, kept two open questions its own spec records as answered, and named two schema files the Go rebuild never carried. Each stale site now states the delivered truth spc-8 already verified — the term file lives at brief/glossary/core/spec.md with epic forbidden — while the live remainder (the reviews-subsystem rename, correctly blocked on itd-28) stands untouched. Resolves: iss-2608261437044340 Assisted-by: Claude:claude-fable-5
…ches A slug-suffixed (spc-9-widget) or zero-padded (spc-09) spec_id is lint-green — record-lint's spec rules match on the spec number, and the spec store's reservation check tolerates both spellings by recorded design — yet Reconcile compared the raw string, spec.Store.Lookup compared exactly, and the audit path re-applied the strict argument grammar to the stored field, so a record every gate passes bricked intent ready, spec close, intent link and the audit emit. Lookup now resolves by spec number after an exact-match pass, Reconcile compares via the shared SameNum helper, and the stored spec_id is validated with HasNum; the strict grammar still guards CLI arguments. An unparseable value matches nothing, so two malformed ids never compare equal. Resolves: iss-2608261437047643 Assisted-by: Claude:claude-fable-5
The intent half of the shared traversal swallowed every walk and per-file read error while the spec half ten lines later fails closed, and the fail-open half feeds the release cut's stale-intent refusal — an unreadable intent file contributed zero links, so the guard against a silent under-bump was disarmed exactly when the tree was damaged. The walk error is now captured and propagated, keeping the one documented tolerance: a missing intents root is an unpopulated repository, not a fault. Resolves: iss-2608261437049307 Assisted-by: Claude:claude-fable-5
cleanLessonProse kept the pre-migration body its sibling cleanSynthProse was moved off: it neutralised only the HTML-comment pair, not the full opener class, and did so before Sanitize — the exact ordering the canonical primitive documents as unsafe, since a masked control byte after < forges a processing instruction. The consolidation's own doc claimed lifeboat routed through CleanProse; this was the boundary the sweep missed. The body now delegates with the unchanged 4096-byte cap. Resolves: iss-2608261437040578 Assisted-by: Claude:claude-fable-5
firstRootSHA was the one git read on the untrusted-repo probe path still using the uncapped runner, against the file's own every-read-is- bounded contract; a repo with many parentless roots buffers one line per root. The read now goes through RunLimited with rev-list -n 1, which returns the same first root, and a source-guard test keeps the package off the uncapped runner. Resolves: iss-2608261437048689 Assisted-by: Claude:claude-fable-5
The per-file probe ran git log --diff-filter=MR under a pathspec limited to the new path, where diffcore can never form a rename pair — so renaming a review file in the same commit as a rewrite passed the append-only gate, and the stderr swallow made any git failure read as a clean corpus. One history pass over the reviews root now flags every modify, rename, delete or type change of a dated review file, closing the deferred deletion case with the same line; git failures refuse with exit 2, an unborn HEAD reports loudly that nothing is covered, and a cases harness pins all eight polarities in the Makefile gate and CI. The brief's RD002 row states the delivered rule. Resolves: iss-2608261437044382 Assisted-by: Claude:claude-fable-5
CONTRIBUTING, AGENTS.md and ci.yml's own header comment all described the check job's Linux leg as three additions when the blocking site-render gate is a fourth, and billed the record-lint job as the reviews-charter check alone when it also runs the issue-resolution gates. A contributor sizing up CI from these sentences would not expect a site-render or RS-family refusal from a required check. Resolves: iss-2608261437047992 Assisted-by: Claude:claude-fable-5
The flag validated its ids for shape only and wrote the record with exit 0, and record_schema — armed at blocker over the issue store — then refused the record the tool itself minted, wedging preflight until a hand edit; the sibling provenance flags already existence-check through the shared probe before anything is written. Capture now probes each target across all three buckets before reserving a path, refusing with nothing written on a miss; blocking on a resolved or wontfixed target stays legal, and the CLI shape check and strict validator keep their layers. Resolves: iss-2608261437046287 Assisted-by: Claude:claude-fable-5
…cker A committed issue record missing schema_version was invisible to every capture surface — the list skipped it, the bare status board silently undercounted, and the dispatch said not found — while record-lint stayed green, because record_schema asserted structure but never the reader's required properties. The issue store now declares its required frontmatter from a shared leaf package both the reader and the lint consume, so the two cannot drift; the bare status board renders the skipped roster the way capture list already does; and the one live record in that state — hand-edited three days ago — gets its schema_version restored and its unknown status key removed, keeping its id, filename and provenance intact. Resolves: iss-2608261437041050 Assisted-by: Claude:claude-fable-5
The round-9 fix gates a missing required property; a record carrying an unknown property is the second way the reader skips a lint-green file, which the live record this round repaired had demonstrated. Assisted-by: Claude:claude-fable-5
Seventeen records move open -> resolved, each stamped with its fixing commit; the round summary lands in the decision log. Assisted-by: Claude:claude-fable-5
Assisted-by: Claude:claude-fable-5
REPPL
enabled auto-merge
August 26, 2026 15:02
Collaborator
Author
Merge gate — round 9CI: all 13 checks green on head Two independent adversarial reviews of the full diff — both SHIP:
Both reviewers flag one thing for the merger: land this with a merge commit, not squash or rebase — the 17 Auto-merge is not authorised for this loop; the PR stays open for a human to merge. Assisted-by: Claude:claude-fable-5 Generated by Claude Code |
github-merge-queue
Bot
removed this pull request from the merge queue due to failed status checks
Aug 26, 2026
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.
What
Bug-hunt round 9 (
bughunt-b). Baseline green before any change (make preflightexit 0 with the full suite executed — 77 package results including the race lane — andgofmt -l .empty) after unshallowing this environment's clone. Five parallel hunters swept the four dimensions; every candidate went through an independent adversarial refuter. 21 candidates in; 12 substantive and 5 nitpicks confirmed and fixed, 4 refuted or prior art, 2 recorded open.Confirmed and fixed — substantive
capture --blocked-byminted records its own blocker refuses (internal/core/capture/workflow.go, iss-2608261437046287). Shape-only validation wrote a dangling cross-reference with exit 0;record_schema(blocker) then wedged preflight on the tool's own output — the invariantworkflow.gostates verbatim ("the tool's own resolve path can never mint a record its own blocker rejects"), swept for--intent/--specand missed here. Capture now probes each target through the shared existence probe before reserving a path; a resolved/wontfix target stays legal (watched-fail test both directions).spec_idspellings (internal/core/intent/lifecycle.go:306,ready.go:166,audit.go:182,internal/core/spec/spec.go:82; iss-2608261437047643). Lint matches spec references by number and the store's reservation check toleratesspc-N-slug/spc-0Nby recorded design (iss-68 P5), but Reconcile compared raw strings andLookupcompared exactly — a record every gate passes brickedintent ready,spec close,intent linkand the audit emit. The verbs now resolve by number via sharedSameNum/HasNumhelpers; the strict grammar still guards CLI arguments; unparseable values match nothing.scripts/check-reviews.sh:53, iss-2608261437044382).git log --diff-filter=MRunder a pathspec limited to the new path can never form a rename pair, so renaming a review file in the same commit as a full rewrite passed the append-only gate — reproduced; and the stderr swallow turned any git failure into a clean pass. One--name-status --diff-filter=DMRThistory pass over the reviews root now refuses every modify/rename/delete of a dated review file (closing the previously deferred deletion case with the same line), git failures exit 2, unborn HEAD reports loudly, and a newscripts/check-reviews-cases.shpins eight polarities in the Makefile gate and CI — 5 of 8 fail against the old script.schema_versionvanished while every gate stayed green (internal/core/lint/schema.go,internal/surface/cli/cli.go, iss-2608261437041050). The reader skips such a record (list omits it, the bare status board silently undercounted, dispatch says not found) andrecord_schemanever asserted required properties — a live record hand-edited three days ago sat invisible through two bug-hunt rounds. The issue store now declares its required frontmatter from a new sharedinternal/core/issueschemaleaf both the reader and the lint consume (an import cycle bars exporting from capture — proved empirically), the status board renders the skipped roster, and the live record is repaired in place with id, filename and provenance intact.cleanLessonProsekept the body the CleanProse consolidation claims it routed (internal/core/lifeboat/graveyard_lessons.go:313, iss-2608261437040578). Byte-identical to the pre-migrationcleanSynthProseN: only<!--neutralised, and before Sanitize — the orderingtermsafe/prose.godocuments as forging<?from a masked control byte (reproduced). Now delegates totermsafe.CleanProsewith the unchanged cap; two watched-fail tests pin the opener class and the ordering.ScanSpecLinksfailed open on the intent tree (internal/core/lint/speclinks.go:106-112, iss-2608261437049307). The intent half swallowed every walk/read error while the spec half ten lines later fails closed — and the fail-open half feedsrelease.staleIntents, the guard whose own doc says it exists to stop a silent under-bump. Errors now propagate; a missing intents root stays soft (the documented unpopulated-repository state).README.md:44,AGENTS.md:171,principles/the-record-lands-with-the-act.md:50; iss-2608261437041111). All three taught the leaves-open/predicate — under which a baregit rmsatisfies aResolves:trailer, the exact hole round 8 closed — and the README's flagship refusal example quoted a message the gate no longer emits.README.md:110, iss-2608261437042550). "Adds one command" — the brief's surface chapters and the 2026-07-11 sign-off record three host-delegated markdown commands with no Go verb (prepare-this-repo,consult,ingest); the CLI refuses the latter two by name.CHANGELOG.md:8, iss-2608261437046261). The section set is closed at six and the refusal is structural, so the promise became unfulfillable at v0.6.0's final manual roll. Header now states the derived truth (the minor bump is the signal); adr-37 carries a dated amendment in the repo's established form; the version-arithmetic comment quotes the amendment.site-src/README.md:11, iss-2608261437047965). The explorer shipped without it and the stylesheet's header was corrected in that same commit; the README clause was left behind, contradicting the file one directory over. Nothing in the tree setsdata-theme..abcd/development/intents/disciplines/, iss-2608261437043634 + iss-2608261437043962). itd-1 instructed running/abcd:intent review— a verb the binary refuses — and five active cross-cutting rules named the removedintent-fidelity-reviewer; the bucket appears in neither spc-28's swept inventory nor its not-swept list, andintent auditrefuses non-shipped intents, so no reconciliation event could ever fire. 21 substitutions plus itd-5'stask_classesline repointed at the naming registry (iss-265) withintent_audit; stored artefact spellings stay frozen; spc-28's not-swept paragraph records the late sweep;drafts//planned/stay deliberately unswept under iss-94.terminology/tree (.abcd/development/intents/planned/itd-43-...md, iss-2608261437044340). Its problem statement asserted a term file that does not exist, its canonical-term scope bullet and AC2 pointed at a path that cannot come into existence, two open questions were answered by its own spec, and two schema files never existed in the Go rebuild. Reconciled in place (the iss-392 precedent on this same file); the live remainder — the reviews-subsystem rename, correctly blocked on itd-28 — stands untouched.Confirmed and fixed — nitpicks
CONTRIBUTING.md:22,AGENTS.md:77,ci.yml:5-10; iss-2608261437047992): the Linux leg's blocking site-render gate and the record-lint job's RS001–RS003 steps were absent from all three closed enumerations (iss-318 established these sentences as intended-exhaustive).firstRootSHAunbounded (internal/core/lifeboat/probe.go:557, iss-2608261437048689): the one uncapped git read in the file that documents every-read-is-bounded; nowRunLimited+rev-list -n 1, with a source-guard test..gitattributeseol gap (iss-2608261437040448):site-src/install.sh.tmpl— the one distributed shell artefact — lacked thetext eol=lfpin its five siblings carry; a CRLF render would publish an installercurl | shcannot run.glossary_terms_used(iss-2608261437046944): listed the nonexistentcore/epic(the armed forbidden synonym) beside its successorcore/spec; dropped losslessly.task_classesenum claim.Considered and rejected (refuted or prior art)
renderReviewMDwrites provenance fields via Sanitize only — real, but verbatim the subject of open issuedisembark reviewwrites untrusted_provenance.jsonfields (source_name,manifest_sha256) into the durable review.mdviatermsafe.Sanitize, which does not neutralize CommonMark HTML-block openers — so a hostile lifeboat can make the review record hide its own findings #325; an elaboration (the evidence-path vector), not a new discovery. Not fixed here to keep the round honest about provenance.{40}vs--release-gate{7,64}) — two different jobs, not one contract: the arming input is a path-safety filter on a release-time external value, the directory sha is machine-derived 40-hex on every real path, and the width is documented where RD001 is defined; widening would fail open..gitattributesmerge=unionwith its rationale); one claimed instance was not even a merge, and iss-2608220150157511 already rules append logs tolerate union merges.Recorded open (not fixed here)
Verification
make preflightexit 0 on the final merged tree (lint-reviews with the new cases harness, lint-issues, record-lint, docs-lint, site-render, build, vet, test, race — 77 package results, suite executed) andgofmt -l .empty;scripts/check-attribution.sh commitsclean over the range.origin/mainwas merged after #516/#517 landed mid-round; the merge was clean and the full gate re-ran green on the merged tree. Every behaviour change carries a test watched fail before the change and pass after: the dangling--blocked-byrefusal, the spec_id spelling tolerance at all four verb sites, the RD002 rename/rewrite/deletion refusals (5 of 8 harness cases fail against the old gate), the required-frontmatter blocker, the status-board skip roster, the CleanProse opener and ordering cases, thegitutil.Runsource guard, and the ScanSpecLinks dangling-symlink propagation. Each confirmed finding is captured in the ledger and resolved with fixing-commit provenance in this PR (RS001 checks all 17 trailers).Assisted-by: Claude:claude-fable-5