Development record
The decide verb hands its working directory straight to the record writer without resolving the checkout root, so it mints an architecture decision record relative to wherever the shell happens to be. Run outside any repository it exits zero, reports a repo-relative path, and creates a full decisions store in a plain directory; run from a subdirectory of a real checkout it mints into a second store beneath that subdirectory rather than into the repository's own. This is the same defect the capture verbs carried until this release, and the same remedy applies: every front door resolves the checkout root before it builds a request, and refuses rather than guessing when there is no repository to address. The evidence is not hypothetical. A checker of this release's own semantic gate, running in a scratch directory, left behind an ADR store containing one record whose slug says it was written outside any repository; nothing in the verb, its help, its surface chapter or its plugin page warned that this could happen. The cost is a decision record that no gate reads, no release cut sees and no reader finds, written with every appearance of success, and the durable record family is the one where a lost entry is least recoverable because the decision it holds was never anywhere else. Fix: resolve the root the way the capture verbs now do, refuse outside a repository with nothing written, and report a store found below the checkout root rather than adding to it. Detector: decide run outside a repository refuses with exit 2 and creates nothing, decide run from a subdirectory mints into the checkout's own store, and decide run at the root is unchanged.
The decide verb hands its working directory straight to the record writer without resolving the checkout root, so it mints an architecture decision record relative to wherever the shell happens to be. Run outside any repository it exits zero, reports a repo-relative path, and creates a full decisions store in a plain directory; run from a subdirectory of a real checkout it mints into a second store beneath that subdirectory rather than into the repository's own. This is the same defect the capture verbs carried until this release, and the same remedy applies: every front door resolves the checkout root before it builds a request, and refuses rather than guessing when there is no repository to address. The evidence is not hypothetical. A checker of this release's own semantic gate, running in a scratch directory, left behind an ADR store containing one record whose slug says it was written outside any repository; nothing in the verb, its help, its surface chapter or its plugin page warned that this could happen. The cost is a decision record that no gate reads, no release cut sees and no reader finds, written with every appearance of success, and the durable record family is the one where a lost entry is least recoverable because the decision it holds was never anywhere else. Fix: resolve the root the way the capture verbs now do, refuse outside a repository with nothing written, and report a store found below the checkout root rather than adding to it. Detector: decide run outside a repository refuses with exit 2 and creates nothing, decide run from a subdirectory mints into the checkout's own store, and decide run at the root is unchanged.
Grounds
- pursued: a decision filed outside the checkout is a decision no gate, no cut and no reader ever reaches, and the front door is the only place that knows which checkout the caller is in
Frontmatter
| id | iss-2609091707224329 |
|---|---|
| type | issue |
| lifecycle | resolved |
| severity | major |
.abcd/work/issues/resolved/iss-2609091707224329-decide-writes-an-adr-store-wherever-it.md
open on GitHub ↗ · commit history ↗
mentions1
- iss-2609091729516940The checkout-root defect that decide carried is a pattern the surface shares, not two instances of it. iss-2609090951291524 fixed it for the seven capture verbs and iss-2609091707224329 for decide; the same raw shape — os.Getwd() handed to a core that joins a repo-relative store path onto whatever it is given — remains at the intent, spec, ideate and memory front doors, which between them own the intent store, the spec store, the ideate verdict record and the memory substrate. Reproduced against a scratch git checkout holding one intent draft: abcd intent run from internal/core reports drafts 0, planned 0, shipped 0 while the identical binary at the root reports the draft, and abcd intent "<text>" run from the same directory mints a second store at internal/core/.abcd/development/intents/drafts and reports a repo-relative path that reads exactly like the checkout store's. Run in a plain directory that is not a repository at all it exits 0 and lays the full intent skeleton there. spec and memory show the read half of the same thing from a subdirectory. The cost is the one the two closed records already argue: a record filed where no gate, no release cut and no reader looks, written with every appearance of success, and for the intent store an intent whose spec can never be closed against it. Fix direction: the resolution is already shared and already generalised — gitutil.CheckoutRoot takes git's toplevel, refuses a repo-shaped tree git will not answer for, and refuses when nothing repo-shaped sits above, with the store's noun as its only parameter — so each remaining front door needs a resolving step of the captureLedgerRoot and decideStoreRoot shape and the strayStoreNotes call that reports what an unresolved door already deposited, not a new resolver. Detector, per family: the verb run from a subdirectory addresses the checkout's store, the verb run outside a repository refuses with exit 2 and writes nothing, the verb run at the root is unchanged, and a static pass over the surface package refuses a request built from an unresolved working directory.