Development record
`/abcd:intent "<text>"` And `/abcd:capture "<text>"` Become Symmetric Create Paths
Press Release
abcd's two ledger commands gain a symmetric, sub-verb-free create path. Typing
/abcd:intent "I want users to feel the loyalty card respects their time"files the new intent directly — nonewsub-verb required. Typing/abcd:capture "the export button looks dead-on dark mode"works the same way for a quick observation. The bare command (zero arguments) keeps doing what the universal abcd convention says it must: shows status and help, never mutates state. The three invocation shapes are crisp: bare → status, quoted text → create, sub-verb [+ID] → act on existing. The product thinker reaches for the same shape no matter which ledger they want."I stopped having to remember
new," said Iris, product lead. "Quotes mean create. That's the whole rule for both commands. The cognitive overhead of/abcd:intent new "…"vs/abcd:capture "…"was tiny, but it was the difference between a flow that felt designed and a flow that felt grown — and now it feels designed."
Why This Matters
A 2026-05-22 design discussion, recorded in a dated working-log entry, landed on a clear conclusion: drop the new sub-verb from both /abcd:intent and /abcd:capture. Quoted-text-as-create-signal is symmetric across the two commands and aligned with abcd's universal "bare = status + help, never mutates" convention. The full rationale is recorded in that working-log entry; this intent captures the work to implement it.
Three reasons the change matters beyond aesthetics:
- It honours the universal convention.
docs/reference/commands.mdline 3 states: "Every command, when called with no arguments, shows help and a status summary… Bare invocation never mutates state; every state-changing operation requires an explicit sub-verb." The current/abcd:captureis already shaped correctly (/abcd:capture "<text>"is the documented create path)./abcd:intentis the asymmetric outlier with itsnewsub-verb. This intent removes the asymmetry. - It clarifies the bridge between the two commands.
/abcd:capture promote <iss-N>already hands an issue to/abcd:intent newas a seed. With the sub-verb removed, the promote path calls/abcd:intent "<text>"directly, and the conceptual model becomes "promote means: capture's content becomes intent's seed" rather than "promote means: invoke a specific sub-verb on intent". Cleaner mental model. - It is a small, well-scoped surface change with no behaviour change at
the output level. The artefact a
/abcd:intent "<text>"invocation produces is byte-identical to what/abcd:intent new "<text>"produced. Only the routing logic and the docs change.
This intent is project-agnostic in the same sense the rest of the command surface is — it shapes how the /abcd:intent and /abcd:capture commands behave in every project that installs abcd.
What's In Scope
- Update
abcd-cli/commands/abcd/intent.md— remove thenewrow from the sub-verb table; add a"<text>"row with the same description; update the routing logic so the first argument being a quoted string (not a known sub-verb) dispatches to the create path. - Update
abcd/docs/reference/commands.md/abcd:intenttable — remove thenew "<text>"row, replace with a"<text>"row carrying identical description. - Update
/abcd:capture promoteplumbing — the promote path currently hands content to/abcd:intent new; change it to call/abcd:intentdirectly with the issue text as the quoted-text argument. - Add a one-line decision rule to both commands' bare-form help output so
users know which ledger to reach for:
- Half-formed observation, question, or nitpick? →
/abcd:capture "…" - User-facing change you want to ship? →
/abcd:intent "…"
- Half-formed observation, question, or nitpick? →
- Confirm
/abcd:capturealready follows the shape — thedocs/reference/commands.md/abcd:capturerow for"<text>"already exists; verify the implementation matches the documented shape (per a 2026-05-22 working-log entry the implementation is already correct here — confirm and move on).
What's Out Of Scope
- Renaming
iss-N/itd-NtoC01/IN01or any new ID scheme. The 2026-05-22 ledger entry explicitly rejects this as a third partial terminology migration (sibling to itd-43's epic→spec sweep). - Changing the sub-verb-required rule for mutating sub-verbs.
refine,grill,plan,ship,review,reclassify,link,resolve,wontfix,promotecontinue to require their target's ID. Corpus-scope scan verbs (list,consistency,shape) continue not to require an ID. Already-correct shape; this intent does not modify it. - Merging
/abcd:intentand/abcd:captureinto one command. The ledger entry explicitly rejects a unified/abcd:capture <kind>design; this intent implements the conclusion of that discussion, not the rejected alternative.
Acceptance Criteria
- Given a contributor running
/abcd:intent "I want users to feel X", when the command executes, then a new intent file is created underintents/drafts/with content seeded from the quoted text — byte-identical to what/abcd:intent new "I want users to feel X"would have produced. - Given a contributor running
/abcd:intent new "I want users to feel X", when the command executes, then it either (a) routes to the create path as before (backwards-compatible alias), or (b) errors with a clear message naming the new shape. Decide at plan; lean (a) for a transition period, (b) eventually. - Given a contributor running
/abcd:intent(bare), when the command executes, then status + help is shown and no file is created — the universal bare-invocation convention is preserved. - Given a contributor running
/abcd:capture promote iss-N, when the command executes, then the issue text is handed to the intent create path and a new intent file appears underintents/drafts/— same outcome as before, different plumbing. - Given a contributor reading the bare-form help output of either command, when they scan the help text, then the one-line decision rule ("nitpick → capture; user-facing change → intent") is visible.
Open Questions
- Backwards-compatibility window for
/abcd:intent new. Keep it as an alias for one phase to ease the transition, then remove it? Or remove immediately on landing? Lean: alias-for-now with a deprecation warning, remove in a later sweep. - Documentation rewrite extent. Updating
commands.mdis trivial; the question is whether the supporting docs (thefacilitator.mdrole doc, theintent.mdskill files, any tutorial content) need parallel updates. Likely yes — record at plan. - Promote path testing.
/abcd:capture promote <iss-N>is a relatively rarely-exercised path; regression tests for it should land with this intent's spec, not as a side note.
Related
- a dated working-log entry (2026-05-22) — the design discussion that produced this intent.
docs/reference/commands.md— the doc that gets updated.commands/abcd/intent.md— the command-routing surface.- itd-4 (issue-capture intent) — the broader intent for
/abcd:capture's existence; this intent refines/abcd:intentto match/abcd:capture's already-correct shape. - itd-43 (epic→spec terminology) — precedent for not introducing a
partial terminology migration; this intent preserves
iss-N/itd-N.
Audit Notes
Fidelity review — receipt rcp-69589b8b5103 (verifier intent-fidelity-reviewer claude-opus-4-8).
Provenance: intent-fidelity-reviewer@claude-opus-4-8 · rubric_hash sha256:95792472ae74ca0469f69a51c618946e0d33cb1380032460099ed4b469d67e86 · prompt_hash sha256:9163e0a43a54575a50afb718052ae244a6d3763b0b2c8f20d64754457523da9f Input attestations: diff:7289aa520d72c867de68205d8a2b87c7c05d8321@-;
Acceptance rollup: MET 4 · MET_WITH_CONCERNS 1 · NOT_MET 0 · INCONCLUSIVE 0
Per-criterion verdicts:
- ac-1 — MET: CreateFromText derives a validated slug and atomically writes drafts/itd-N-<slug>.md seeded from the text; both the quoted-text route and the new alias call the identical createIntentFromText, so the artefact is byte-identical, and the adjudication that no prior Go
intent newverb existed is honest (verified absent in origin/main). Covered by TestCreateFromTextSeedsDraft and TestIntentQuotedTextCreates. evidence: internal/core/intent/create.go:59 — "rel := filepath.Join(IntentsRelDir, BucketDrafts, name)" evidence: internal/surface/cli/intent_cli_test.go:255 — "if got.ID != "itd-1" || got.Bucket != "drafts"" - ac-2 — MET: The
new <text>subcommand is registered as a backwards-compatible alias (lean (a)) that routes to the same createIntentFromText and prints a deprecation warning naming the quoted-text shape on stderr only, keeping stdout identical; proven by TestIntentNewAliasWarnsAndCreates. evidence: internal/surface/cli/cli.go:1108 — ""WARNING:abcd intent newis deprecated; useabcd intent \\\"<text>\\\"(quoted text is the create signal).")" evidence: internal/surface/cli/intent_cli_test.go:289 — "if !strings.Contains(stderr, "deprecat")" - ac-3 — MET: The create branch is guarded on len(args) > 0; a bare invocation falls through to intent.Status and mutates nothing. TestIntentBareCreatesNothing asserts the status render and zero files under drafts/. evidence: internal/surface/cli/cli.go:1070 — "if len(args) > 0 {" evidence: internal/surface/cli/intent_cli_test.go:311 — "t.Fatalf("bare intent created %d drafts files, want 0", len(entries))"
- ac-4 — MET_WITH_CONCERNS: The create path is engine-backed and tested end-to-end (ac-1 tests), and commands/abcd/capture.md now instructs promote to hand the issue body to
abcd intent "<text>"; but promote itself is skill-orchestrated markdown with no native verb and no automated regression test (grep for promote in internal/ finds no promote engine/test), despite the intent's Open Questions asking promote regression tests to land with this spec. The 'same outcome as before' and no-back-link caveats are honestly stated in the markdown. evidence: commands/abcd/capture.md:75 — "It hands the issue body to the intent create path —abcd intent \"<issue text>\"" evidence: commands/abcd/capture.md:78 — "It does not yet write the reciprocalrelated_intentsback-link onto theiss-Nrecord" - ac-5 — MET: The ledgerDecisionRule constant (nitpick -> capture; user-facing change -> intent) is printed in both the bare intent status render and the bare capture status render; TestBareHelpsCarryDecisionRule asserts both, and the capture skill markdown carries the same rule.
evidence: internal/surface/cli/cli.go:1162 — "const ledgerDecisionRule = " which ledger? half-formed observation, question, or nitpick ->
abcd capture \\\"…\\\"; a user-facing change you want to ship ->abcd intent \\\"…\\\"\n"" evidence: internal/surface/cli/intent_cli_test.go:327 — "if !strings.Contains(captureOut, "user-facing change") || !strings.Contains(captureOut, "nitpick")"
Gap audit:
- honoured:
- Sub-verb-free quoted-text create path files a lint-valid seeded draft under intents/drafts/, symmetric with capture evidence: internal/core/intent/create.go:38 — "func CreateFromText(repoRoot, text string) (Intent, error) {" evidence: internal/core/intent/create_test.go:88 — "// TestCreateFromTextPassesRecordLint runs the real intent_lifecycle record-lint"
intent newpreserved as a deprecation-warning alias (lean a) with byte-identical stdout evidence: internal/surface/cli/cli.go:1096 — "Use: "new <text>","- Decision rule visible in both bare helps evidence: internal/surface/cli/cli.go:1629 — "fmt.Fprint(w, ledgerDecisionRule)"
- diverged:
- Scope named updates to commands/abcd/intent.md and docs/reference/commands.md; neither file exists in this tree, so the intent verb family has no plugin markdown surface — the routing/table edits have no native counterpart (recorded honestly as iss-105). The AC-level outcomes are met at the CLI surface instead. evidence: .abcd/development/specs/closed/spc-7-abcd-intent-quoted-text-create-symmetric.md:54 — "Two scope bullets name files that do not exist in this tree"
- Promote is delivered as a markdown instruction pointing at the CLI create path rather than an engine-tested end-to-end flow; the reciprocal related_intents back-link is not written (no engine verb does it today). evidence: commands/abcd/capture.md:73 — "skill-orchestrated, not a binary sub-verb. It hands the issue body to the intent"
- Typo-guard asymmetry accepted: any non-sub-verb first token becomes create text, so a mistyped sub-verb files a draft (recorded as iss-104); not required by any AC. evidence: .abcd/development/specs/closed/spc-7-abcd-intent-quoted-text-create-symmetric.md:61 — "Typo-guard asymmetry accepted for now"
- missing:
- No promote-path regression test landed with the spec despite the intent's Open Questions flagging it should; promote's issue-text-to-create handoff is exercised only via the shared create-engine tests, not a promote-specific test. evidence: .abcd/development/intents/shipped/itd-46-abcd-intent-quoted-text-create-symmetric.md:102 — "regression tests for it should land with this intent's spec, not as a side note"
Frontmatter
| id | itd-46 |
|---|---|
| type | intent |
| lifecycle | shipped |
| kind | standalone |
| severity | minor |
.abcd/development/intents/shipped/itd-46-abcd-intent-quoted-text-create-symmetric.md
open on GitHub ↗ · commit history ↗
References1
- itd-4Nothing You Notice Gets Lostbuilds on
Referenced by15
- adr-12`.work/issues.md` stays the live operational ledger; the structured per-issue store is deferred until the native spec layer schedules the migration (historical)related
- iss-2610262032194841itd-46 treats `list` as a corpus-scope intent scan verb that already exists; the context page says there is no plain `list` sub-verbrelated
- iss-2610262035089991itd-46 calls bare-command-as-status a universal abcd convention; the intent chapter says it is a common convention, not a universal onerelated
- iss-2610262035091535itd-46 has promotion pass the issue text to the quoted-text create; the capture chapter has promotion mint a draft whose body is a by-id pointer, not a copyrelated
- iss-2610262040034442The README requires a flat commands/ directory where a plugin-named subdirectory breaks every verb; itd-46 edits the intent page at commands/abcd/intent.mdrelated
- iss-2610262042088869itd-46 lists `ship` and `grill` as existing intent sub-verbs that keep requiring an id; the build sequence says neither exists.related
- iss-2610262042091628itd-46 calls bare-invocation-renders-status a universal abcd convention; the skills chapter says it is a convention and not a universal.related
- iss-2610262043466977itd-25's dredge promote calls /abcd:intent new; itd-46 replaced the new sub-verb with quoted-text createrelated
- iss-2610262044430202itd-30 builds its fiction format on an `/abcd:intent new` sub-verb, but shipped itd-46 removed that sub-verb and made quoted text the create pathrelated
- iss-2610262044474439Shipped itd-46 states a universal rule that a bare command never changes state; in itd-2610031215002409, opening the bare `abcd` board writes the waiting-on statusrelated
- iss-2610262045199145itd-46 says quoted text alone creates a capture; itd-82 requires a remedy field on every new issuerelated
- iss-2610262045235833itd-46 says sub-verbs act on existing records and quoted text creates; itd-2609020625400194 adds a capture sub-verb that creates a new record from quoted textrelated
- iss-2610262045246595itd-46 lists `ship` and `review` among the intent sub-verbs; itd-121 says shipping an intent is a spec verbrelated
- iss-2610262045552105itd-46 lists ship as a live intent sub-verb; itd-2609111003026787 holds intent ship for a cyclerelated
- spc-7abcd-intent-quoted-text-create-symmetricimplemented by
mentions13
- adr-34Intent lifecycle and phase scheduling are orthogonal axes
- adr-40Review, audit, lint, and gate are four buckets, separated by what each compares
- dcn-26071700000000022026-07-17 — Burst 3 (M3, itd-4/spc-6), three record adjudications: (1) AC2's
- dcn-26071700000000032026-07-17 — Burst 4 (M4, itd-46/spc-7): quoted-text create shipped; the
- iss-3phase membership and lifecycle directories disagree: planned intents (itd-20, itd-24, itd-29, itd-46) appear in no phase Scope, while draft itd-43 is scoped into Phase 0/1 yet listed later-phase. ADR-bound.
- iss-104intent quoted-text create treats any non-subcommand first token as create text (no suspectedTypoedSubcommand guard like capture): 'abcd intent paln "x"' files a draft instead of erroring; consider porting capture's typo heuristic for symmetry
- 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-246`surface_coverage` is blind inside a row, so `shipped` means "the top-level verb exists" and every unbuilt sub-verb hides behind it.
- itd-1Every Intent Has Acceptance Criteria; Every Audit Verifies Them
- itd-43abcd Speaks One Word for a Specced Block of Work, and That Word Is "Spec"
- itd-80An Intent Ships Itself: `planned → shipped` Follows Its Spec Closing, With A Fidelity Audit Attached
- itd-116Validated GitHub Issues Become Ledger Entries Without Retyping
- spc-6issue-capture