Development record
2026-10-27 — Majors ruling for the next cut, product thinker, 27 October 2026, on abcd-78's recommendations for the 17 hand-captured majors since v0.15.1. Fix before the cut: the eight recommended fixes (iss-2610251555094324, iss-2610241537197997, iss-2610241414124940, iss-2610241911052191, iss-2610241240133009, iss-2610241133284600, iss-2610241239492159, iss-2610241519088123) and five recommended for deferral that the product thinker chose to fix instead: the short install command in the docs (iss-2610240827243654), a worktree per session (iss-2610240859590333), clearing lapsed holds everywhere (iss-2610241107191205), the reflect criteria (iss-2610241431221889) and the measured home-folder receipt (iss-2610241551259104). Deferred one cycle: iss-2610241228359748, iss-2610240932215918, iss-2610241613191748. Amended and closed: iss-2610241427397332 (itd-3's obsolete criteria). The 69 consistency-pass majors are ruled on branch decisions/interview-2026-10-27.
2026-10-27 — Majors ruling for the next cut, product thinker, 27 October 2026, on abcd-78's recommendations for the 17 hand-captured majors since v0.15.1. Fix before the cut: the eight recommended fixes (iss-2610251555094324, iss-2610241537197997, iss-2610241414124940, iss-2610241911052191, iss-2610241240133009, iss-2610241133284600, iss-2610241239492159, iss-2610241519088123) and five recommended for deferral that the product thinker chose to fix instead: the short install command in the docs (iss-2610240827243654), a worktree per session (iss-2610240859590333), clearing lapsed holds everywhere (iss-2610241107191205), the reflect criteria (iss-2610241431221889) and the measured home-folder receipt (iss-2610241551259104). Deferred one cycle: iss-2610241228359748, iss-2610240932215918, iss-2610241613191748. Amended and closed: iss-2610241427397332 (itd-3's obsolete criteria). The 69 consistency-pass majors are ruled on branch decisions/interview-2026-10-27.
Frontmatter
| id | dcn-2610271922502480 |
|---|---|
| type | decision |
| date | 2026-10-27 |
.abcd/work/decisions/dcn-2610271922502480-majors-ruling-for-the-next-cut-product.md
open on GitHub ↗ · commit history ↗
mentions18
- iss-2610240827243654The documented CLI install one-liner (README and docs/how-to/install.md) is far too complicated to be a one-liner: a single sh -c string of roughly 3,000 characters that unsets proxy variables, refuses a symlinked ~/.abcd.noindex, maps uname output to a release asset, downloads it and checksums.txt, verifies the checksum, probes gh attestation verify for four flags, resolves the latest tag and its commit through the GitHub API, verifies build provenance, prints a long fallback warning, installs to ~/.local/bin and writes ~/.abcd.noindex/path-entry. Nobody can read, audit or safely retype it, and a reader cannot tell what they are agreeing to run.
- iss-2610240859590333A session wrote records into the main checkout's working tree on main while another live session (abcd-0d) was working in the same checkout, because nothing enforces the rule that a concurrent session works in its own worktree. On 2026-10-24 this session ran capture, intent, decide --adr and go generate from the main checkout: an issue record, an intent draft, an ADR and two regenerated index regions landed in the shared tree, the regenerated indexes folding in a peer's untracked draft. Nothing refused or warned. capture, intent and decide write into whichever checkout they run in; the guard judges shell commands and questions, not where records are written; and the CONCURRENCY rules domain, which carries the rule, recalls only on prompts about worktrees, peers or sessions, so a prompt saying 'file the decision record' never injected it. The agent also skipped the required scan (session listing and abcd peers) before mutating. The rule held only as prose.
- iss-2610240932215918The claude runner cannot run on a Claude subscription, so a person without an API key has no route to any role abcd runs from a plain terminal: the planning interview, a build's implementer and validators, the drain's judge.
- iss-2610241107191205A lapsed hold or reservation must be lifted without a person, or autonomous work waits on a holder that no longer exists. On 2026-10-24 a computer that had reserved a release cut (rel-v0.15.2) and dozens of issues and intents crashed. Its leases lapsed, yet sessions on another machine kept waiting on it: one session relayed the release hold to six others as live, from a read made before it lapsed, two finished pull requests waited for the dead cut's ruling, and a build was held behind the crashed copy's work. The product thinker ruled the same day that lifting a lapsed hold is autonomous: no person is needed to declare a lapsed holder gone. The reading side already counts a reservation five minutes past its expiry as released. What is missing is that every reader, verb and agent instruction acts on that, and that spent branches leave origin without a person. This record carries the ruling that the whole path runs unattended.
- iss-2610241133284600On 2026-10-24 the main checkout of abcd had no git hooks installed: core.hooksPath was unset in every config scope and the common .git/hooks held only samples, so the committed .githooks (commit-msg, pre-commit, pre-push) ran for no commit and no push made from it or from its linked worktrees. Several sessions were committing and pushing that day. Nothing said so: commits went through silently, a commit message naming an issue without a Refs: line (RS004) was accepted at commit time, and a push to origin was made with no preflight receipt, which the pre-push hook exists to refuse. The gap surfaced only because make preflight's lint-issues gate failed afterwards. How the setting was lost is not known; the setup redesign under way the same day touches the hooks. abcd ahoy reports install state but did not flag it, and no commit verb checks it before writing.
- iss-2610241228359748Which abcd runs is confusing because several installs coexist and nothing says which one wins: the plugin can be installed at user scope and at project scope at once, each with its own plugin-root binary, and there is also a PATH binary (ahoy install) and, in abcd's own checkout, a source build (go run). Observed 2026-10-24: the person updated the plugin to v0.15.1, but the update landed as a new project-scope install for this repository while the user-scope install stayed at 0.13.3, and the session went on loading the user-scope copy (command pages still named .../abcd/0.13.3/abcd, its hooks bootstrapped there at 14:23); the 0.15.1 directory had never bootstrapped and held no binary; and the binary inside the 0.13.3 directory reported v0.14.1, so even the directory name did not say which version ran. Nothing in the board, ahoy or the command pages surfaced any of this. The person wants it unified (for example: does a repository-scope plugin win over a user-scope one, and how does the CLI on PATH relate to either?). Earlier rulings each settled one rung on its own (dcn-2609080000000001 the owned-only PATH rung for the hook shims, adr-2609151706587280 the cache-to-PATH attestation, iss-2610070547057816 dogfooding a source build in abcd's own checkout) without addressing the underlying problem: no single, stated precedence across plugin scopes, the plugin-root binary, the PATH binary and a source build.
- iss-2610241239492159abcd guard has no hazard for deleting a branch or a worktree: git push origin --delete, git branch -D and git worktree remove are all allowed whatever the target holds, so the safety of a cleanup rests on the agent remembering its own checks. On 2026-10-24 a hand-run sweep's check-then-act loop invoked abcd guard check with the wrong syntax, read the nonzero exit as an objection, printed it and deleted seven remote branches anyway; the deletes were safe only because the survey before them was right, and the hook would have allowed them regardless. A guard has to be enforced at the hook, not hoped for in a script.
- iss-2610241240133009In a source checkout every abcd invocation is go run ./cmd/abcd, and go run turns every nonzero exit into 1: the binary's exit 2 (guard unevaluable, a usage error) and exit 3 (reserve: back off) both arrive as 1, the same code as a guard block. Measured 2026-10-24: guard check on an unterminated quote exits 2 as a built binary and 1 under go run. The dogfooding rule therefore makes the documented exit-code contract unreadable to the agents it governs, and a script that branches on exit 3 never sees it.
- iss-2610241414124940The preflight load gate can starve every waiter on a busy machine and holds its only slot for a hung command. It opens only while the one-minute load is below twice the online cores (20 on 10 cores), but the preflight stages it does not gate (lint, record gates, evals, build, vet) run before it, so seven sessions' preflights on 2026-10-24 kept the load near 25 and the gate never opened: one drain lane's preflight ended 'load gate still shut after 2h0m0s: load 20.9 is not below 20 (2 x 10 online cores); 3 make preflights are running'. Later the same day, at 14:04 UTC, the load was 8 on 10 cores and about nine preflights were still queued, their logs unchanged for 45 minutes, because the one open slot (~/.abcd.noindex/load-wait.json, form command, opened 13:19 UTC, held to 14:19) belonged to a package test run that had used about 11% CPU for 45 minutes; load.preflights was 2, yet only one slot was open, possibly because waiters started before the setting was written read one slot when they began. Nothing reclaims a slot whose holder is idle, and nothing lets the gate open when the load it waits on comes from the ungated stages of its own queued runs. Adjacent records on an unmerged branch cover the ungated stages running unbounded and the unmeasured wait, which this issue does not restate.
- iss-2610241427397332The after-merge fidelity audit of itd-3 judged a criterion unmet, so its check is still owed: ac-5 NOT_MET, ac-6 NOT_MET
- iss-2610241431221889The after-merge fidelity audit of itd-24 judged a criterion unmet, so its check is still owed: ac-2 NOT_MET, ac-7 NOT_MET
- iss-2610241519088123The host still cancels abcd's SessionEnd hook on a loaded machine, so the session's transcript is neither staged nor stored, and nothing says so. On 2026-10-24, at a load average of about 21 on 10 cores, session ad158fbf ended with 'SessionEnd hook [sh .../hooks/session-end.sh] failed: Hook cancelled' under the 0.15.1 plugin, whose hook is identical to the current source; its 559 KB transcript reached neither the staging area nor the store, though the host's own copy is still on disk. The host gives a SessionEnd hook 1.5 seconds in all, and a timeout set in a plugin's hooks.json does not raise it (the host's hooks reference, read 2026-10-24). Before it stages anything, hook session-end detects the repository through ahoy.Detect and git, with up to two retries inside a 1.2-second budget; under this load starting the binary alone takes about 0.36 s and each git call about 0.15 s. The August fix (iss-2608230817034768) took redaction off the exit path but left this lookup on it, and the comment at internal/surface/cli/hook_subagent.go:95-110 says the hook could ask the host for more time, which the reference says a plugin hook cannot.
- iss-2610241537197997Concurrent preflights on one machine all fail: on 2026-10-24 a records-only branch's preflight reached its test stage while six other preflights and several direct test runs shared a 10-core machine at a load near 20, and six packages (cloudscripts, ahoy, autonomy, claim, embargo, implement/loop) hit their 20-minute per-binary timeouts, so the run failed on nothing its own change touched. The load gate admits each preflight's test stage once the load dips under its limit, and the stages before it run ungated, so every admitted run then competes with the rest and none can finish inside its timeouts. Wrapping the whole run in the gate's command form, which one session found by hand, serialises them.
- iss-2610241551259104The after-merge fidelity audit of itd-2610030720038073 judged a criterion unmet, so its check is still owed: ac-6 NOT_MET
- iss-2610241613191748The after-merge fidelity audit of itd-2610111707085098 judged a criterion unmet, so its check is still owed: ac-13 NOT_MET
- iss-2610241911052191The load gate opened a whole make preflight at load 17.8 on ten cores, under the 20 threshold, yet three packages (internal/core/claim, internal/core/implement/loop, internal/surface/cli) then hit the twenty-minute test timeout, because the other sessions' ungated stages kept the load near the threshold for the whole run
- iss-2610251555094324make preflight cannot land a one-record change on a busy machine: on 2026-10-24 a branch whose whole diff is one new issue record (iss-2610241228359748) ran preflight twice, every gate before the test stages passed both times, and both runs then waited the load gate's full two hours (abcd implement load --wait --timeout 2h) behind two to four running preflights and six to eight queued waiters, and failed with 'load gate still shut after 2h0m0s'. With no receipt the pre-push hook refuses the push, so a change that touches no Go code waits behind the full test and race stages of every other session and in practice cannot be pushed.
- itd-3abcd Loads Its Own Rules On Demand