Development record
an-intent-that-is-not-planned-cannot-be-implemented-abcd-gai
Summary
spc-9 delivers itd-94: a machine-checkable implement-readiness gate,
abcd intent ready <itd-N>, plus the plugin surface that routes an unready
intent to a human planning interview instead of an improvised implementation.
Scope
- Core (
internal/core/intent/ready.go):Ready(repoRoot, intentID)returns a structuredReadyResult— always exactly four checks in fixed order (bucket,acceptance_criteria,spec_link,spec_body), each with a detail and, on failure, the exact remedy. "Not ready" is a result;erroris reserved for structural faults (malformed id, unknown intent, unreadable record). Read-only: the verb never mutates the store. - Supporting (
internal/core/spec): the minted placeholder is extracted into a sharedstubMarkerconstant with an exportedBodyIsStubdetector, lockstep-tested so template and detector cannot drift. - CLI (
internal/surface/cli):abcd intent ready <itd-N>renders the report (with--jsonemitting the fullReadyResult) under the exit-code contract 0 ready / 1 not ready (report is the output, empty message) / 2 fault — the embark-conflicts precedent. - Plugin surface (
commands/abcd/intent.md, resolving iss-105): the full verb family plus THE RULE (gate before implementing any itd-N) and the host-run planning interview, whose closing act — the human-confirmedabcd intent plan— is the maintainer's acceptance-criteria sign-off. - Protocol (
.abcd/development/plans/2026-07-12-abcd-run-protocol.md): step 0 for intent-backed items; nonzero exit is a journaled SKIP, and unattended planning is forbidden (the intent-level form of iss-83's fail-closed rule).
Approach
The gate composes existing single-purpose guards into one reporter rather than
adding state: bucket is directory-as-truth, acceptance criteria reuse
countAcceptanceCriteria (the same parser Plan and the fidelity review
use), the link check mirrors Reconcile's bidirectional-agreement guard as a
report, and the body check keys on the shared stub marker. AC sign-off is
implicit in a human-run abcd intent plan (dcn-2607180000000002): no new
frontmatter, no forgeable schema; agents are barred from unattended planning
at the protocol layer.
Acceptance-criteria satisfaction
- Draft → NOT READY + remedy, exit 1 —
bucketCheckfails every non-planned bucket; the drafts remedy names the confirm-then-plan route (or the interview when no AC bullets exist). Tests:TestReadyDraftWithRealAC(the itd-93 shape),TestReadyDraftSeededPlaceholder, CLITestIntentReadyNotReadyExit1. - Stub spec body fails —
specBodyCheck+spec.BodyIsStub;TestReadyPlannedStubSpecBody,TestBodyIsStubLockstep. - Planned + linked + written passes, exit 0 —
TestReadyGreen, CLITestIntentReadyGreenExit0. - Faults exit 2 —
TestReadyFaults, CLITestIntentReadyUnknownExit2. - Surface refuses and offers the interview, never plans unattended —
commands/abcd/intent.md(THE RULE + interview steps 1–8 + Autonomous runs). - Run-protocol step-0 gate — the skip/stop filter amendment in
2026-07-12-abcd-run-protocol.md.
Frontmatter
| id | spc-9 |
|---|---|
| type | spec |
| lifecycle | closed |
.abcd/development/specs/closed/spc-9-an-intent-that-is-not-planned-cannot-be.md
open on GitHub ↗ · commit history ↗
References1
- itd-94An intent that is not planned cannot be implemented: abcd gains a machine-checkable implement-readiness gate that refuses with a remedy and offers the planning interviewimplements
mentions8
- adr-40Review, audit, lint, and gate are four buckets, separated by what each compares
- dcn-26071800000000022026-07-18 — Acceptance-criteria sign-off is implicit in a human running
- iss-83The /abcd:run protocol has no precondition that the PLAN file itself exists: its fail-closed check covers a missing or malformed mandatory PLAN *field* (ROLE / RECOVER STATE) but not a wholly-absent PLAN *file*. In the drain #2 run the /loop fired against a PLAN_PATH that did not resolve on HEAD because the plan was being authored concurrently in another worktree and only merged mid-session (HEAD moved 54fef5f -> 137f8de under the running session). The runner correctly fail-closed but the gap invited synthesizing a substitute plan. Fix (protocol robustness): add an explicit step 0 — resolve PLAN_PATH on current HEAD; if the file does not exist, STOP and report without synthesizing a replacement plan (synthesis re-introduces the guess-the-gate risk fail-closed exists to prevent). Add an operational note: a plan-driven loop must only be launched after its PLAN is merged to the branch it reads. Secondary: at burst start git fetch + re-derive HEAD rather than trusting the session-start snapshot — here both the snapshot and NEXT.md were stale (NEXT.md described already-committed itd-81 work as uncommitted). Acceptance: the protocol names a missing-plan-file STOP distinct from missing-field, and forbids substitute-plan synthesis.
- iss-105the intent verb family (plan/link/review/ingest and now quoted-text create) has no plugin markdown surface (no commands/abcd/intent.md) — pre-existing gap against the wired-from-both-surfaces boundary; itd-46's old-system scope bullets assumed one existed
- iss-2609290448510918The predecessor-store qualifier sweep reaches past the six intents iss-2609261536147903 named: outside drafts/ and those six, 192 citation sites across about forty intents name a spc-N at or below spc-70 that is not the citing intent's own spec, with no '(predecessor store)' on the line. Some are live cross-references (the cold-reading family's intents cite each other's live specs), and some are the predecessor store's (itd-4, itd-6, itd-29, itd-47 and itd-49 describe pre-rebuild work in its terms), so each site needs the same reading against the live spec it collides with; the specs charter's Two spc-N Namespaces section is the rule. Found while sweeping the pattern of iss-2609261536147903 in lane drainDrift3; a census script over intents/{planned,shipped,disciplines} reproduces the count.
- iss-2611040554357485The land chapter says the composed pull-request body carries the commits' Refs:, Resolves: and Delivers: lines once each (.abcd/development/brief/04-surfaces/38-land.md:143). The composer keeps only Resolves: or Refs: lines naming iss-N ids alone and Delivers: lines naming itd-N ids alone (internal/core/landing/prbody.go:46-47,82), and leaves merge commits out (prbody.go:62). `Refs: spc-9 step 3`, the chapter's own example at line 69, is dropped, as are `Refs: itd-N` and `Refs: #12`.
- itd-29Domain Experts Run A Spec Autonomously And Recover From Anything Without Touching Git
- itd-93abcd Scaffolds a Release Gate That Works on the First Try