Development record
Every verb's help opens with one sentence an agent can act on
Press Release
Every verb's help opens with one sentence, does / writes / refuses, identical on the list, the verb's
--helpand its page."I read one line per verb before I decide whether to call it," said a technical facilitator watching an agent choose. "When that line says what the verb does, what it writes and when it refuses, the agent calls the right one. When it says 'manage things', it grep's the binary."
Why This Matters
Fifty-three verbs and sub-verbs carry a short line today, of uneven shape, and nothing holds them to a form or keeps the three places they appear in agreement. The field's guidance for both people and agents is the same: one concise, actionable line per command, in one voice. Ruled 2026-09-21: does, writes, refuses, in that order, under the repository's writing-style guide, generated from one source.
Mechanism
We expect an agent choosing a verb from its sentence to call the right one more often and to stop reading the binary for verbs, because the sentence answers the three questions an agent asks before a call; shown wrong if agent transcripts after it ships still show a verb called for what it does not do.
Scope Conditions
None stated.
What's In Scope
- The form: one sentence per verb and sub-verb naming what it does, what it writes (or "writes nothing"), and when it refuses, in that order, under
docs/reference/writing-style.md. - One source: the sentence lives in the surface manifest and is rendered onto the command list, the verb's own
--helpand its plugin page, byte-identical. - The test: walks every visible verb; fails on a missing clause, a length over the declared cap, or a difference between the three places.
- The agent block (itd-146) shows the same sentences.
- The lint: the docs-lint writing-style checks run over the sentences.
What's Out of Scope
- The long help body per verb.
- Examples per verb (the page's).
Decisions
Ruled by the product thinker on 2026-09-21, in the interview that filed and planned this intent (adr-2609212115255771 records the vocabulary rulings it rests on):
- Does / writes / refuses, in that order, identical in three places, under the writing-style guide.
Open Questions
None open.
Acceptance Criteria
- Given any visible verb or sub-verb, when its sentence is read, then it names what the verb does, what it writes or that it writes nothing, and when it refuses, in that order, and obeys the writing-style guide.
- Given the command list, the verb's
--helpand its plugin page, when the sentence is compared across them, then it is byte-identical, rendered from the surface manifest. - Given a verb whose sentence lacks a clause, exceeds the cap or differs between places, when the test runs, then it fails naming the verb and the defect.
- Given
--help --agent, when the agent block renders, then each line is the verb's sentence. - Given the docs lint, when it runs, then the sentences are checked as any page is.
Audit Notes
Fidelity review — receipt rcp-47bbe53f5074 (verifier intent-auditor claude-fable-5-1).
Provenance: intent-auditor@claude-fable-5-1 · rubric_hash sha256:effa65b3e9e88ff29433b443ec2be159522a8b0b71cf1434526514aa61edb13e · prompt_hash sha256:7f6d17b45108836a6ea8570db0f0b0bd800cce168c60870c481353ee1b7a4b9b Input attestations: diff:tree at 7c476185 (main lineage, itd-2609212113220149 shipped)@-;
Acceptance rollup: MET 5 · MET_WITH_CONCERNS 0 · NOT_MET 0 · INCONCLUSIVE 0
Per-criterion verdicts:
- ac-1 — MET: every sentence is declared once in the manifest and ParseSentence splits it on the declared separators into a doing clause, a Writes clause and a refuses/never refuses clause in that order, refusing a missing, doubled or out-of-order clause or a run over the 160-character cap; TestEverySentenceInTheManifestParses walks the manifest and TestEveryVisibleVerbCarriesItsSentenceEverywhere walks over a hundred visible commands, both green at BASE; writing-style adherence is the docs lint's (ac-5) evidence: internal/core/surface/sentences.go:23 — "var sentences = map[string]string{" evidence: internal/core/surface/sentence.go:54 — "func ParseSentence(s string) (Sentence, error) {" evidence: internal/core/surface/sentence.go:31 — "const SentenceCap = 160" evidence: internal/core/surface/sentence_test.go:99 — "func TestEverySentenceInTheManifestParses(t *testing.T) {" evidence: internal/surface/cli/sentences_test.go:160 — "func TestEveryVisibleVerbCarriesItsSentenceEverywhere(t *testing.T) {"
- ac-2 — MET: SentenceFor is the one source: the surface snapshot records it per command, the CLI's --help opens with it, and each commands/< verb>.md description is diffed against it by sentenceDefects; TestEveryVisibleVerbCarriesItsSentenceEverywhere fails on any byte difference between the list, the verb's help and the page, and TestVerbHelpOpensWithTheSentenceThenTheLongHelp pins the help's opening line evidence: internal/core/surface/sentences.go:269 — "func SentenceFor(path string) (string, bool) {" evidence: internal/surface/cli/surface.go:112 — "s, _ := surface.SentenceFor(cmd.CommandPath())" evidence: internal/surface/cli/sentences.go:86 — "sentence, ok := surface.SentenceFor(cmd.CommandPath())" evidence: internal/surface/cli/sentences_test.go:151 — "commands/%s.md's description differs from the manifest's sentence" evidence: internal/surface/cli/sentences_test.go:258 — "func TestVerbHelpOpensWithTheSentenceThenTheLongHelp(t *testing.T) {" evidence: commands/peers.md:3 — "description: "List the records sibling worktrees and local branches hold that this checkout does not: Writes nothing; refuses outside a git checkout.""
- ac-3 — MET: TestSentenceDefectsNamesTheVerbAndTheDefect is the negative control on a synthetic tree: a verb with no sentence, one over the cap, one missing a clause, one whose list text differs and one whose page differs are each named with the defect and the well-formed verb is not; TestParseSentenceNamesEachDefect covers the parser's messages; TestTheFrameworkCommandsAreTheOnlyExemption pins that only cobra's help and completion escape evidence: internal/surface/cli/sentences_test.go:203 — "func TestSentenceDefectsNamesTheVerbAndTheDefect(t *testing.T) {" evidence: internal/core/surface/sentence_test.go:45 — "func TestParseSentenceNamesEachDefect(t *testing.T) {" evidence: internal/surface/cli/sentences_test.go:174 — "func TestTheFrameworkCommandsAreTheOnlyExemption(t *testing.T) {"
- ac-4 — MET: with --help --agent each line of the agents-and-hosts block is the entry's name, its manifest sentence and its page, and nothing else; TestAgentBlockLinesAreTheSentences matches every line against SentenceFor and refuses a vacuous block evidence: internal/surface/cli/sentences_test.go:274 — "func TestAgentBlockLinesAreTheSentences(t *testing.T) {" evidence: internal/surface/cli/helpgroups.go:61 — "helpAgentsTitle = "For agents and hosts (each line names the page to read next):""
- ac-5 — MET: the generated CLI reference docs/reference/cli/commands.md renders every sentence as its own line under the docs root the committed docs-lint configuration declares, so the lint reads the sentences as any page; TestSentencesAreCheckedByTheDocsLint asserts the root covers the page, that every sentence is on it, that the banned-token rules find nothing, and that a sentence carrying a banned token is caught evidence: internal/surface/cli/sentences_test.go:309 — "func TestSentencesAreCheckedByTheDocsLint(t *testing.T) {" evidence: .abcd/docs-lint.json:3 — ""docs"," evidence: internal/surface/cli/sentences_test.go:317 — "const reference = "docs/reference/cli/commands.md""
Gap audit:
- honoured:
- one source: the sentence lives in the surface manifest and is rendered onto the list, the verb's --help and its plugin page byte-identically evidence: internal/core/surface/sentences.go:269 — "func SentenceFor(path string) (string, bool) {" evidence: internal/surface/cli/sentences_test.go:160 — "func TestEveryVisibleVerbCarriesItsSentenceEverywhere(t *testing.T) {"
- the test walks every visible verb and fails on a missing clause, a length over the declared cap, or a difference between the three places evidence: internal/surface/cli/sentences_test.go:203 — "func TestSentenceDefectsNamesTheVerbAndTheDefect(t *testing.T) {"
- the agent block (itd-146) shows the same sentences evidence: internal/surface/cli/sentences_test.go:274 — "func TestAgentBlockLinesAreTheSentences(t *testing.T) {"
- a reworded sentence is visible in the committed surface snapshot and gated by its drift test evidence: internal/surface/cli/surface.go:112 — "s, _ := surface.SentenceFor(cmd.CommandPath())" evidence: internal/core/surface/sentence_test.go:261 — "func TestSentenceChangesNamesEachRewordedVerb(t *testing.T) {"
- diverged:
- spec scope 5 says docs lint includes the manifest's sentences as a lint root; the delivery reaches the sentences through the generated CLI reference page under the existing docs root rather than a manifest root, which satisfies the criterion (checked as any page is) by another route evidence: internal/surface/cli/sentences_test.go:317 — "const reference = "docs/reference/cli/commands.md"" evidence: .abcd/docs-lint.json:3 — ""docs","
- missing: (none)
Grounds
- pursued: the run adds five verbs and the per-verb lines today are fifty-three sentences of uneven shape; we expect an agent to choose from the sentence and stop grepping the binary; shown wrong if transcripts still show a verb called for what it does not do
Frontmatter
| id | itd-2609212113220149 |
|---|---|
| type | intent |
| lifecycle | shipped |
| kind | standalone |
| severity | minor |
.abcd/development/intents/shipped/itd-2609212113220149-every-verb-s-help-opens-with-one.md
open on GitHub ↗ · commit history ↗
References3
- adr-2609212115255771Phases and milestones are retired: sequencing is dependencies rendered as status, the checkpoint is the derived releaserelated
- itd-146abcd's help renders in labelled command groups, and the grouping is gated like every other surface claimbuilds on
- itd-172Every record has a short title and a one-line summary a non-engineer can readrelated
Referenced by4
- iss-2610262039556194itd-2609212113220149 requires the verb's sentence to be byte-identical on the list, the help and the plugin page; the README adds a 'use when' clause to two pages' descriptions.related
- itd-146abcd's help renders in labelled command groups, and the grouping is gated like every other surface claimrelated
- itd-2610090831227812A person who types `/abcd:` sees the commands people userelated
- spc-2609212139583822every-verb-s-help-opens-with-one-sentence-an-agent-can-actimplemented by
mentions5
- dcn-26092100000000012026-09-21 — Phases and milestones are retired, and the word roadmap with them (product thinker, at an interactive interview after an independent research pass; adr-2609212115255771 supersedes adr-9). Sequencing is dependencies plus the lifecycle shelves, rendered as a Now / Next / Later status block on the `abcd` board and the site (itd-2609212103568351), never stored; the checkpoint is the derived release plus each intent's acceptance criteria, with an optional `target_release` the cut reports and moves forward (itd-2609212103572513); the unit below a spec is the step, a section not a family (itd-2609212103565953); an issue carries no spec by design; the batch is the run's internal order; one page maps the families (itd-2609211913453478). itd-24 becomes release retrospectives; itd-34 drops its phase rule. Same interview: `build` is the verb a person types and `implement` the loop (itd-2609201916151817 decision 8), the loop takes an issue key (decision 10), only the loop writes a verdict (decision 9); the person's command list is grouped with an agents block behind `--agent` (itd-146), every verb opens with a does/writes/refuses sentence (itd-2609212113220149), modes become flags and five checks one lint (itd-2609212130136102, breaking); the status-line badge is guarded and reset (itd-2609212130146198); a new capture or draft is matched and linked at filing, never refused (itd-2609212137116617); abcd's text names the product thinker or the technical facilitator and never the maintainer (itd-2609212137129937, captured for the run, no sweep today); the lab conventions become `abcd lab` (itd-2609212137128014); a managed repository's site goes live by one verb behind a provider seam (itd-2609061543533170).
- dcn-26092500000000222026-09-25 — How each verb's sentence is sourced and rendered (itd-2609212113220149): the implementing lane's technical rulings in autonomous run A, subject to the product thinker's review on return (recorded, not asked); decision 1 of the intent (does, writes, refuses, in that order, identical in three places, under the writing-style guide) is not reopened. The surface manifest's sentence field is a table in `internal/core/surface/sentences.go`, keyed by full command path, because the binary ships without `.abcd/` and so cannot read the committed snapshot at run time; the front door sets every visible command's Short from it and no constructor declares one, so there is no second copy, and the snapshot records the sentence at schema version 3 with versions 2 and 1 still readable (the release guardrail reads its baseline from the last tag), and the surface diff never reads it, because a reworded sentence changes no invocation. The form is mechanical: the doing clause, a colon, a writing clause opening "Writes" (a capital after the colon, per the style guide), a semicolon, a refusing clause opening "refuses" or "never refuses", one sentence, at most 160 characters counted as characters. The three places are the command list (a parent's list, the root's groups, the agents block), the verb's own `--help`, which now opens with the sentence and then the long help for every verb and the root, and the plugin page's `description:`, the line a host lists the page by, double-quoted because every sentence carries a colon and a space; the generator writes it. A sub-verb has no page of its own, nor do `changelog`, `rules`, `spec` and `statusline`, so their places are the list and the help; a page with no verb (consult, ingest, prepare-this-repo) is not the manifest's to rewrite. Hidden commands and the framework's `help` and `completion` carry no sentence. Criterion 5 is met through the generated CLI reference, which renders every sentence as its own line under the `docs` lint root: the docs lint walks markdown only, so a Go table cannot be a root of its own, and a test holds each sentence to a line of that page and to the configured banned-token set. The sentences are British English although they are code strings, because they are prose rendered onto pages the docs lint reads. The count is 106 (every visible verb and sub-verb, and the root), not the fifty-three the intent names. Long help bodies are unchanged, as the intent scopes them out, including the few whose first paragraph restates the short line they replaced (implementer of lane sentences).
- dcn-26092500000000242026-09-25 — The sentences of itd-2609212113220149 after its review's fix round (the implementing lane's technical rulings in autonomous run A, subject to the product thinker's review on return; recorded, not asked). A parent verb's sentence names the family's work and its write discipline, never the list of its sub-verbs, because for a top-level verb it is the description a host lists the family's plugin page by; `disembark`, `docs`, `embark`, `guard`, `history`, `ideate` and `implement` are reworded on that rule, and `docs cite`, the same shape one level down, with them. The rule is held mechanically on the doing clause alone: a parent's doing clause names no verb, while its refusing clause may still say "refuses an unknown sub-verb". cobra's `help` and `completion` stay listed under Set-up with cobra's own text, as the earlier ruling placed them, rather than hidden; the sentence gate walks the tree as it executes and exempts their six commands by name, and a test holds the name list to exactly the visible commands with no sentence. The stale-surface refusal and the snapshot drift test name each reworded sentence the way they name a moved verb. CORRECTION to this lane's report, which said the release guardrail reads a version-2 baseline from the last tag: v0.10.0 carries a version-1 `surface.json`, no tag carries version 2, and versions 1 to 3 are all readable; the guardrail decodes the tagged version-1 baseline end to end (implementer of lane sentences, fix round 1).
- itd-2610301346085246An agent learns how to call abcd from the abcd it runs
- spc-2609212139586554abcd-s-help-renders-in-labelled-command-groups-and-the-group