Development record
2026-08-20 — Bug-hunt round 3 (hunt B), branch bughunt-b/round-3. Baseline
2026-08-20 — Bug-hunt round 3 (hunt B), branch bughunt-b/round-3. Baseline (make preflight + gofmt -l .) green before any change. Captured iss-382..iss-392 (11 records), each adversarially refuted before capture. Fixed and resolved this round: iss-382 disembark plan's RenderManifest printed source-repo file paths raw while the same view sanitised its neighbours (terminal-escape injection over an untrusted source repo); iss-383 the history transcript store's read path used raw os.ReadFile while its write path was fully hardened, so a planted FIFO wedged history capture under the store flock and a symlink was followed (both reads now fsutil.ReadGuarded); iss-384 Baseline.validate sanitised final_url alone while echoing the entry key and quoted fields raw to the terminal through the CLI error surface (incomplete-fix residue of iss-359); iss-386 launch scaffold stripped the go.mod patch and refused one back, shipping every adopter a floating go-version (the adopter-side residue of iss-289); iss-385 commands/version.md still named only two network verbs after two rewrites (docs cite refresh and memory ingest also fetch); iss-387 the release-gate manifest pinned 17 briefDocs while four shipped surface chapters (guard/ideate/identity/banlist) sat outside it, so every full-tier crosscheck attested coverage it never ran; iss-388 the phases README called the shipped itd-88 planned; iss-389 the examples-use-reserved-identifiers principle described its shipped iss-154 lint as not-yet-built; iss-391 research/notes/README routed to the adr-30-rejected research/phase and research/adr layouts; iss-392 the confirmed nitpick batch (canonical id-uniqueness key closing the zero-padded-filename hole, .yaml coverage in the go-version lockstep sweep, scripts/.sh eol=lf, the lifeboat-reviewer 0.1.1 reconciliation, and the commands/abcd/ path repoint across five live records). Recorded, not fixed: iss-390 — the pre-decided promotion of the reserved-identifiers principle to a discipline-kind intent is a maintainer ceremony, so it stays open as the tracker. Refuted this round (kept out of the ledger): the scanner genericHomeRe case-fold (iss-308 already adjudicated against folding the POSIX /users/ arm — real API-route false positives, and home_path_other is warn-tier anyway); the ahoy refounding-candidate case compare (documented mutable labels; the miss lands on the designed decline path; iss-221 owns the real repair); govulncheck non-gating (documented deliberate advisory, DECISIONS 2026-08-19 and commit 61a15b4); the CODEOWNERS publish-surface omissions (the .abcd/ paths reach no installed user and the Go-tree reading proves too much; sole-maintainer bypass makes the scenario moot — a golden-file test for the bare scaffold render is the real follow-up if a write rung is ever granted); isHexSHA 40-hex (display-only, sha256 repos unreachable, iss-206 owns the sibling); the coverage_index.json raw read (already named by open #365); commands/docs.md's scoped "on behalf of documentation" heading; the agents/ host-agnosticism claim (docs-lint bans harness names, not the model id, which is the sanctioned disclosure token); the make smoke vacuous-gate and runbook-parity claims. Model routing: orchestration on Claude Fable 5; five parallel hunters, seven per-finding adversarial refuters on Claude Opus 5; the dual pre-merge review runs one reviewer as Claude Fable 5 and one as Claude Opus 5.
Frontmatter
| id | dcn-2608200000000008 |
|---|---|
| type | decision |
| date | 2026-08-20 |
.abcd/work/decisions/dcn-2608200000000008-bug-hunt-round-3-hunt-b-branch-bughunt-b.md
open on GitHub ↗ · commit history ↗
mentions19
- adr-30Design-record information architecture — flat artefact-type folders
- iss-154privacy-hygiene detects only absolute home paths — no network-identifier patterns (IPv4 incl. CGNAT/tailnet 100.64/10, hostnames, device names, ports-in-context). Field incident: an agent committed a Tailscale investigation (tailnet IP, two device hostnames, firewall posture, service port, presence/away patterns) into a public repo's committed tier and audit passed it silently. The v1 deferral note names only emails and private-repo names; network identifiers are not even recorded as deferred.
- iss-206The version-skew notice promised by itd-105 ('Given an installed surface newer than the newest published binary, when a session starts, then the skew is surfaced') can never fire, and fails silently. itd-105's warrant says the harness names each plugin cache directory for the commit it was cloned from; that holds only as a 12-character SHORT sha. Observed .binary-meta from the first manual install (2026-08-10): plugin_root_basename=872f0a1e6aab, which is exactly 'git rev-parse --short=12 HEAD', and plugin_sha=unknown. hooks/bootstrap.sh gates plugin_sha on exactly 40 hex chars, and internal/surface/cli/skew.go resolvedSHA() requires 40 again, so plugin_sha is permanently 'unknown' and binarySkewNotice() returns "" forever on every machine. This is precisely the failure the comment at hooks/bootstrap.sh anticipated and armed a diagnostic for — recording the raw ungated plugin_root_basename beside the gated field so that 'why has the skew notice never fired' has an answer in the file rather than only in a comment. The diagnostic worked exactly as designed; the gate is what is wrong. Fix direction: accept 7-40 hex in both places and compare on the shorter value's prefix length, since one side is a short sha and the other a full one.
- iss-221ahoy install's re-founding lineage prompt is a one-shot: under --yes/non-TTY it prints and silently takes the [y/N] default No, registers the root as new, and a second run reports already_up_to_date without re-asking — no verb links lineage after the fact, leaving two active index entries for the same project (old epoch 85573f…, new 488a0aa… after the attribution rewrite). Non-TTY identity prompts should refuse rather than default, and lineage should be linkable post-registration
- iss-289The release workflow builds on an unpinned Go minor: scaffold substitutions set GoVersion 1.25, which resolved to 1.25.12 on runners today — the toolchain with four stdlib vulnerabilities fixed in 1.25.13 that govulncheck flagged in ci. ci.yml was pinned to 1.25.13 the same day but release.yml renders from the template, so shipped binaries build on whatever 1.25.x the runner resolves. The v0.6.0 tag predates any fix and cannot be retro-patched (anti-tag-move); the pin lands for the next cut
- iss-308repolint absPathRe Windows arm is case-sensitive so a lowercase c-users path escapes the privacy rule
- iss-359cite fetch records a redirect-controlled FinalURL verbatim, so C1, bidi and zero-width runes in a hostile Location query reach abcd docs lint --json and the committed citations baseline raw; the termsafe doc claim that encoding/json escapes control characters is false for those classes
- iss-382disembark plan's RenderManifest prints planned file paths unsanitised, so a hostile source-repo filename injects raw C1/bidi terminal escapes into the plan render and its --json twin
- iss-383the history transcript store's read path is unguarded — listRecords and Read use raw os.ReadFile, so a planted FIFO wedges history list and history capture while the store flock is held, and a symlinked record is followed
- iss-384Baseline.validate sanitises final_url alone while echoing the entry key, url and quoted fields raw, so a committed citations-baseline entry writes ESC/bidi/zero-width to the terminal through the blocking docs-lint gate
- iss-385commands/version.md's network enumeration is still false after two rewrites — it names version --check and update as the only fetch verbs while docs cite refresh and memory ingest <url> also reach the network
- iss-386launch scaffold derives a floating Go minor for adopter repos — goModVersionRe strips the go.mod patch, goVersionRe rejects supplying one, the toolchain directive is ignored, and a hand-pinned release.yml is refused then overwritten — the adopter-side residue of iss-289
- iss-387the release-gate manifest pins 17 briefDocs while four shipped surface chapters (guard, ideate, identity, banlist) are outside the pin, so every full-tier crosscheck attests coverage it never ran
- iss-388roadmap phases README states itd-88 is in planned/ and unscheduled, but the intent has shipped — a false bucket claim in present-tense current-state prose
- iss-389the examples-use-reserved-identifiers principle still says a fixture-identifier lint would make it a discipline — the allowlist-inversion lint shipped (iss-154) and cites the principle by name, so the Promotion paragraph misdirects an agent to build an existing rule
- iss-390the pre-decided promotion of examples-use-reserved-identifiers to a discipline-kind intent never happened — the iss-154 lint shipped, the principles README contract says a mechanical gate promotes the principle, and no discipline intent exists
- iss-391research notes README routes phase-scoped research to research/phase/N/ and names research/adr/ as a sibling — both layouts adr-30 rejected and the gated research-children index denies — and its Related display texts sit one level short of their hrefs
- iss-392bughunt round-3 confirmed nitpick batch — zero-padded record-id filenames evade the id-uniqueness lint in all three families; the go-version lockstep test skips .yaml workflows; scripts/*.sh lack the eol=lf pin the repo's own policy states; agents/CHANGELOG announces lifeboat-reviewer 0.1.1 while the prompt carries 0.1.0; five live records still route to the pre-flattening commands/abcd/ and retired docs/reference pages
- itd-88Know What a Repo Can and Cannot Tell You — Before You Trust the Lifeboat