Development record
launch phase ownership contradicts across the record: phase-1-ahoy.md and build-sequence.md make install plus launch the first milestone, but 04-surfaces/04-launch.md says full launch builds in Phase 5. ADR-bound.
issueresolvedcriticaliss-1
launch phase ownership contradicts across the record: phase-1-ahoy.md and build-sequence.md make install plus launch the first milestone, but 04-surfaces/04-launch.md says full launch builds in Phase 5. ADR-bound.
Frontmatter
| id | iss-1 |
|---|---|
| type | issue |
| lifecycle | resolved |
| severity | critical |
.abcd/work/issues/resolved/iss-1-launch-phase-ownership.md
open on GitHub ↗ · commit history ↗
Referenced by2
- iss-4phase count mismatch: 04-scope.md, 03-out-of-scope.md and 06-delivery README say six phases (Phase 0-5), but roadmap phases README has Phase 0-6 with Phase 6 as lifeboat round-trip.blocks
- iss-5disembark and embark status banners point to the wrong phase: 02-disembark.md says Phase 4, 03-embark.md says Phase 5, but phase-6-lifeboat.md owns both.blocks
mentions11
- adr-33Launch phase ownership is tiered; the phase index is the sole ownership source
- dcn-26071700000000022026-07-17 — Burst 3 (M3, itd-4/spc-6), three record adjudications: (1) AC2's
- dcn-26080500000000032026-08-05 — iss-80 (v0.5.0): resolved as already-fixed, with the residual verification gap closed rather than the defect re-fixed. The branch-local id-collision class this item tracked — `itd-N`/`spc-N`/`iss-N` allocators scanning only the working tree, so two agents on branches cut from one base each mint the same id and collide at merge — was already closed by iss-115 and iss-120, which introduced `recordid.MaxAcrossRefs` (scan every git ref for the family's highest committed id) and folded it into all three minting paths: `internal/core/spec/store.go`, `internal/core/intent/create.go`, and `internal/core/capture/workflow.go`. What survived was uneven evidence, not an uneven fix: only the `spc-N` family had an end-to-end regression test standing up a real two-branch history (`internal/core/spec/refunion_test.go`), while none of capture's or intent's existing tests stood up a real two-branch history through `Capture`/`CreateFromText` and so never drove the ref scan through their public entry points at all — `MaxAcrossRefs` was exercised only as a primitive in its own package test, never as wiring. That is the shape in which a fix silently un-wires: a refactor that dropped the `MaxAcrossRefs` call from `Capture` or `CreateFromText` would have left every existing test in both packages green. So this round adds `internal/core/capture/refunion_test.go` (`TestCaptureMintsPastACommittedBranch`) and `internal/core/intent/refunion_test.go` (`TestCreateFromTextMintsPastACommittedBranch`), each mirroring the spec test's exact fixture via `internal/gittest.NewRepo` — branch A mints and commits record 1, branch B is cut from before that commit so its working tree carries no record, and B must mint record 2. Both were mutation-checked before being trusted: with `MaxAcrossRefs` stubbed to return an empty `RefScan`, each fails with precisely the collision it names (`iss-1`/`itd-1` re-minted on branch B), and all three families fail together — so the tests are pinned to the ref-union behaviour rather than passing incidentally. No production code was touched, which is the point: the minting paths were verified correct by reading before the coverage was written, and the change is test-and-record only. Impact recorded as `internal` and no CHANGELOG entry, matching the iss-34 precedent for a test-only closure with no user-facing behaviour change.
- iss-210A lone token that a user plausibly expects to be a subverb, but which is not one, is swallowed as free text and WRITES A RECORD on both mutating verb families — 'abcd intent status' files drafts/itd-N-status.md and 'abcd capture status' files issues/open/iss-N-status.md, each exit 0. Verified 2026-08-11 by building HEAD into a scratch repo and running both. This is a residual hole in the unrecognized-input-never-writes rule (iss-29) that iss-104's fix does not cover: suspectedTypoedSubcommand (internal/surface/cli/cli.go:2000) fires only on a NEAR-MISS of a real subverb, bestDist initialised to 3 so only edit distances 1 and 2 refuse. It is deliberately high-precision so a genuine multi-word prose title whose first word resembles a verb still files — the controls confirm that half works: 'capture resovle iss-1 note' and 'intent paln itd-1' both exit 2 with a did-you-mean and write nothing. But 'status' is edit distance >=4 from every real subverb in either family (intent: new/plan/ready/link/review/ingest; capture: list/resolve/wontfix), so the guard never engages and the word becomes the record title. The class is any plausible-but-nonexistent subverb far from every real one; 'abcd intent list' happens to be caught only by the accident that levenshtein(list,link)=2. NOT an intent-vs-capture asymmetry: the two behave identically, so a fix must land on the shared guard, not on the intent path alone. Fix direction: edit distance is the wrong discriminator for this class. A LONE single token with no other args is never a useful issue or intent title, so treat it as an unrecognized subcommand regardless of distance — refuse, exit 2, write nothing, name the real subverbs, and say how to force prose (quote it, or add words) so the terse-free-text escape hatch stays open. Detector: extend intent_surface_test.go and the capture surface test with a lone-token case per mutating verb family asserting exit 2 and zero records written, watched fail before the change; the existing near-miss cases must keep passing, and a multi-word prose title must still file. Impact on resolve is 'fix' at best and arguably 'breaking' — an unattended script or loop that shells 'abcd capture <one-word>' expecting a file would start failing — so it is NOT additive-class. Standing risk this closes: any autonomous loop that shells a bare word into either verb silently grows the ledger with junk records that a human must later triage.
- iss-2609301128211767The loop admits a zero-padded issue key: issueIDRe in internal/core/implement/loop/receipt.go is ^iss-[0-9]{1,20}$, so abcd build iss-02609292352131344 opens a run keyed by the padded spelling, which the brief, the DECISIONS lookup, the branch, the PR title and capture resolve all carry, and which drain's == dedupe of runs misses (review-drainLoop finding 1).
- iss-2610040732240935Record pages scroll sideways at 360 px whenever a record's title or source path holds a long unbroken token, and the overflow audit cannot see it. Every ADR minted with a timestamp id shows its source path, .abcd/development/decisions/adrs/<16 digits>-<slug>.md, as one mono span in the side panel's reclinks paragraph, and the run up to the first hyphen is about fifty characters with no break opportunity: /record/adr/adr-2609091248200336/ measures scrollWidth 374 at 360 px. adr-2610031751065746 and adr-2610031751066232 also carry a home-relative path in their titles, which overflows the record page's h1 (scrollWidth 455). The stylesheet sets no overflow-wrap on body, the title or reclinks, so a block whose text has nowhere to break widens the page. The site-screenshots audit samples only the lowest-numbered record of each type (adr-1, itd-1, iss-1), whose paths and titles are short, so these pages have overflowed since timestamp ADRs began without the job noticing.
- iss-2610170814081317With stacked branches, abcd land announces items that are already merged: after the parent branch lands by a squash or rebase merge, its original commits are not on origin's default branch, so land reads their Refs:, Resolves: and Delivers: trailers again when the child branch lands and posts merging for them, for example merging iss-1 for an issue already merged and resolved.
- itd-4Nothing You Notice Gets Lost
- itd-82`abcd drain` fixes the issues that need no decision, and hands the rest back by kind
- itd-2609091034175565Before an agent starts on an item, it reserves it on the shared remote, and everyone who works on the project sees the reservation
- spc-6issue-capture