Development record
2026-08-20 — bughunt round 2 (branch bughunt-a/round-2): captured iss-331..iss-343 and fixed (ids 339-343 re-minted from an initial 326-330 after main concurrently took those numbers in the v0.6.1 cut)
2026-08-20 — bughunt round 2 (branch bughunt-a/round-2): captured iss-331..iss-343 and fixed (ids 339-343 re-minted from an initial 326-330 after main concurrently took those numbers in the v0.6.1 cut)
ten (six fix-impact, four internal). Code/security: iss-339 the scanner's githubRemoteRe matched
the github.com host case-sensitively, so a mixed-case remote (git@GitHub.com:…) left
GitRemoteUsername empty and the github_username redaction kind never armed — the caller's handle
survived history-capture redaction and the PII scan (added (?i)); iss-340 abcd history show/list
printed the untrusted transcript body and metadata fields with no termsafe, replaying ESC/CSI/C1/bidi
sequences raw (now SanitizeBlock on the body, Sanitize on the fields); iss-341 readLifeboatFile kept
an Lstat→root.Open window over an untrusted lifeboat (FIFO hang / symlink-follow) — routed through
fsutil.ReadGuardedInRoot, dropping the unused abs param; iss-342 SourceContext.ListDir opened
directory entries with a blocking open, so a statically-planted FIFO named docs hung
disembark probe/plan/pack over an untrusted target repo with no race (now O_RDONLY|nonBlock, matching
ReadFile). Docs (fix): iss-343 prepare-this-repo.md named the pre-flattening commands/abcd/ path and
"three levels up" (now flat commands/ and "two levels up", tied to CLAUDE_PLUGIN_ROOT); iss-331
lint.md presented the abcd-lint:allow waiver as global when only privacy-hygiene honours it. Record
(internal): iss-332 development/README.md denied the issue ledger adr-32 created; iss-333 the brief's
05-internals/03-configuration.md development tree drew the pre-adr-30 layout (roadmap/intents, research/adr,
research/phase, .abcd/specs) — redrawn flat by artefact type; iss-334 intents/README.md taught the
v0.6.0-retired intent review verb and intent-fidelity-reviewer agent (swept to intent audit /
intent-auditor); iss-335 the issues/ store contract omitted the mandatory impact field and the
agent-observation source. Recorded not fixed (stay open): iss-336 gate_lockstep blank-path silent
disarm (nitpick, no external arming path — defence-in-depth only); iss-337 probe.go inner-descent
OpenRoot FIFO race (needs a raw openat restructure, os.Root.OpenRoot takes no flags); iss-338 seven
registry personas given gendered pronouns against the itd-79 they/them discipline (nitpick cosmetics
batch). Refuted this round: govulncheck non-gating (documented deliberate advisory — commit 61a15b4
and ci.yml:362-363), and the CHANGELOG bijection gap (the bijection reads the composer's JSON payload,
never CHANGELOG.md; the residual is the already-open iss-256). Model routing: orchestration on
Claude Fable 5; hunters, per-finding refuters, and one of the two pre-merge reviewers on Claude
Opus 5; the second pre-merge reviewer on Claude Fable 5 (dual-model merge gate).
Frontmatter
| id | dcn-2608200000000001 |
|---|---|
| type | decision |
| date | 2026-08-20 |
.abcd/work/decisions/dcn-2608200000000001-bughunt-round-2-branch-bughunt-a-round-2.md
open on GitHub ↗ · commit history ↗
mentions18
- adr-30Design-record information architecture — flat artefact-type folders
- adr-32The issue ledger is working-tier data, not authored record
- iss-256Post-cutover, a hand-written CHANGELOG Unreleased entry blocks every derived cut: ingest refuses a non-empty Unreleased section by design, but nothing stops the entry landing in the first place — the contributor habit predates the derived flow, and the first collision happened the day after the cutover (a merged PR added an Unreleased entry for work that had no resolved record, wedging the next cut until the entry was converted into a record by hand). Detector: a record-lint or CI rule that blocks a PR adding lines under '## [Unreleased]'; acceptance: such a PR fails its record gate with a message naming the record-first flow.
- iss-331commands/lint.md presents the abcd-lint:allow line waiver as applying to any finding, but only the privacy-hygiene rule consumes it; a user waiving a docs-currency/three-tier-layout/etc finding gets a silent no-op and a stray committed token, colliding with docs-currency's own differently-spelled escape
- iss-332.abcd/development/README.md conventions line says issues graduate into intents/ or principles/ rather than a ledger, but the repo runs on a committed issue ledger at .abcd/work/issues/ (adr-32); the map of the durable record denies the store it governs, in the file iss-42 ruled must be current
- iss-333brief/05-internals/03-configuration.md's Plugin-internal development namespace tree draws the pre-adr-30 layout: roadmap/intents/{drafts,planned,shipped}, research/adr/, research/phase/, and specs/ under .abcd/ — the record's only map of its own namespace routes a reader to four paths that do not exist; the blocker moved-intents-path rule is defeated only by the ASCII art splitting the string
- iss-334intents/README.md teaches the v0.6.0-retired intent review verb and the intent-fidelity-reviewer agent (retired to intent audit / intent-auditor by adr-40); the intents store front door documents an invocation that exits non-zero and an agent absent from the tree, and its template block is copied into new intents while contradicting create.go
- iss-335.abcd/work/issues/README.md self-declares the store contract with strict validation but omits the impact field (mandatory in resolved/, gated by the issue_impact_valid blocker) and the agent-observation source value (accepted by capture and used by live records) — a reader hand-authoring a resolved record per the contract fails preflight
- iss-336checkGateLockstep returns clean when its runbook or workflow config path is blank while enabled:true, before the rule's own fail-closed guards — a defence-in-depth asymmetry against the rule's stated posture; functionally equivalent to enabled:false (no external arming path), so recorded not fixed
- iss-337probe.go's inner directory descent (dirRoot.OpenRoot(name)) is guarded only by the parent ReadDir's IsDir, so a directory swapped for a FIFO in that window blocks — same TOCTOU shape as readLifeboatFile but race-only and unfixable via the nonBlock const (os.Root.OpenRoot takes no flags); needs a raw openat restructure, recorded not fixed
- iss-338Seven registry personas are given he/she/his/her pronouns across intents/drafts (itd-92,97,98,108,126,128) and intents/shipped (itd-100), violating the they/them persona discipline (itd-79); review-enforced convention with no mechanical gate, concentrated in one 2026-08 authoring batch — a cosmetics-batch cleanup
- iss-339githubRemoteRe matches the remote host case-sensitively, so a mixed-case github.com remote (git@GitHub.com:...) leaves GitRemoteUsername empty and the github_username redaction kind is never compiled — the caller's handle survives history capture redaction and the PII scan
- iss-340abcd history show writes the stored transcript body to the terminal with no termsafe sanitisation (cli.go human render branch) — a transcript that ingested hostile content (fetched pages, target-repo files) replays ESC/CSI/C1/bidi sequences raw; the termsafe sweep missed the history surface
- iss-341readLifeboatFile keeps an Lstat then root.Open window over an untrusted lifeboat (embark), bypassing fsutil.ReadGuardedInRoot — a vetted regular file swapped for a FIFO blocks the open forever, or an in-root symlink is read/hashed in place of the vetted file
- iss-342SourceContext.ListDir opens directory entries with root.Open (no O_NONBLOCK), so a statically-planted FIFO named at a path a probe adapter lists (e.g. docs) hangs abcd disembark probe/plan/pack forever over an untrusted target repo — no race required, breaking the package's stated no-hang-on-FIFO invariant
- iss-343commands/prepare-this-repo.md locates the record at commands/abcd/prepare-this-repo.md and says the repo root is three levels up, but the file lives flat at commands/prepare-this-repo.md (two levels up) since the iss-161 flattening — an agent following it resolves $ABCD one dir above the repo and every Phase 0/1 read misses, under a no-search-fallback directive
- itd-79Personas Come From the Registry; the Role Picks the Name
- itd-114Two Agents Can Mint At The Same Instant And Never Collide