Development record
abcd's text names the product thinker or the technical facilitator, never the maintainer
Press Release
Every place abcd writes names which of the two people it means, and the word maintainer leaves the vocabulary.
"Agents kept asking 'the maintainer' and I never knew if they meant me deciding what to build or me running the gates," said a product thinker. "They learned the word from abcd's own pages. Now the pages say which of us, the badge says which of us, and the word cannot come back."
Why This Matters
On 2026-09-21 the product thinker noted that agents blur the two roles under one word. The word is abcd's: twelve occurrences in the command pages agents read, twenty-two in the brief, five in the principles, one in the bundled rules and one in this repository's rule overrides ("a planned intent's adoption is a maintainer decision"), and a persona hint. Ruled: everywhere abcd writes, each use rewritten to the role it meant, and a lint from then on. The sweep is the run's, not this session's.
Mechanism
We expect agents to stop saying maintainer once no abcd text says it, because agents say what they read; shown wrong if transcripts after the sweep still use the word for either role.
Scope Conditions
None stated.
What's In Scope
- The sweep: every occurrence in the command pages, the bundled and repository rules, the brief, the principles, the docs, the personas registry and abcd's rendered text rewritten to the product thinker (what to build, adoption, rulings) or the technical facilitator (how, gates, mechanics); one change, each rewrite reviewed.
- The lint: the docs-lint banned-token list gains the word for every lint root including the command pages and the rules; the acknowledgements and a persona's outside job title are the only escapes, marked.
- The questions: every question or stop abcd's agents put to a human names which role it asks (the GRILL rule made mechanical where the page templates carry the question).
- The glossary: the two roles defined beside the record-families page, citing itd-97's stance that the facilitator is a mode.
- The test: walks the rendered help and the plugin pages for the word.
What's Out of Scope
- Defining a third role.
- Changing what either role decides (itd-174, itd-97).
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):
- Everywhere abcd writes, each use names the role it meant; a lint bans the word after (ruled 2026-09-21).
- Captured for the run to build; no sweep in the session that ruled it.
Open Questions
None open.
Acceptance Criteria
- Given the command pages, the rules, the brief, the principles, the docs and the personas, when the sweep lands, then no occurrence of the word remains outside the marked escapes, and each rewrite names the product thinker or the technical facilitator.
- Given a new page or rule carrying the word, when the docs lint runs, then it is refused as a banned token on every lint root.
- Given a question or stop an agent puts to a human through the page templates, when it renders, then it names which of the two roles it asks.
- Given the glossary, when the two roles are looked up, then each has an entry beside the record-families page citing itd-97.
- Given the rendered help and the plugin pages, when the test runs, then it fails on the word.
Audit Notes
Fidelity review — receipt rcp-12ccf7627aac (verifier intent-auditor claude-fable-5-1).
Provenance: intent-auditor@claude-fable-5-1 · rubric_hash sha256:effa65b3e9e88ff29433b443ec2be159522a8b0b71cf1434526514aa61edb13e · prompt_hash sha256:0d2779a6a8aa938ebbc363b05eb85aad759fc0c1ca7f93e139b6f26dcdb0ddf1 Input attestations: diff:commits 124b24510 b4df4f25d 993dc7b61 ee9e01dd6 88830a301 83596e7b1 (feat/roles-not-maintainer via integ/land-12), judged at main 7fb52a6b5@sha256:9abdab7a96537431406b403981c9e83be49a034304d905ea0323638f1fcb23ae;
Acceptance rollup: MET 3 · MET_WITH_CONCERNS 2 · NOT_MET 0 · INCONCLUSIVE 0
Per-criterion verdicts:
- ac-1 — MET: A case-insensitive grep at BASE over the command pages, .abcd/rules.json, the brief, the principles, docs/, README.md, AGENTS.md, ACKNOWLEDGEMENTS.md, the bundled rules source and the personas registry finds zero occurrences of the word, so no marked escape was even needed; the sweep landed as one 41-file change, the persona hint reads 'open-source project lead', and the rewrites name a role (the ready verb's remedies name the product thinker). The word survives only outside the listed surfaces: six .github workflow YAML comments, Go source comments, and the agents' injection-canary test fixtures.
evidence: .abcd/development/personas.json:16 — "{ "name": "Kira", "role_hints": ["open-source project lead", "DX engineer", "framework author"] }"
evidence: internal/core/intent/ready.go:163 — "confirm the Acceptance Criteria with the product thinker, then run
abcd intent plan %s" evidence: internal/core/rules/defaults/rules.json:1 — "(the bundled rules source: zero occurrences at BASE)" evidence: .abcd/development/brief/glossary/core/product-thinker.md:4 — "The person who decides what is built and why — who rules on intents, signs off acceptance criteria, adopts or declines a proposal" - ac-2 — MET_WITH_CONCERNS: The repository's docs-lint carries
roles/retired-role-wordas a blocker with the marked< !-- docs-lint: allow -- >escape, reaching the docs roots plus the extra rootscommands,.abcd/rules.jsonandinternal/core/rules/defaults, and the test runs the entry over a tree shaped like this one and asserts the refusal on each of the five roots and the escape's suppression. Concern: 'every lint root' is every root the lint defines, and the brief, the principles and the personas registry — three of the six surfaces ac-1 swept, the brief holding the largest share — are in no root the token reads, so the word can return there with nothing refusing it. evidence: .abcd/docs-lint.json:180-193 — ""id": "roles/retired-role-word", "pattern": "(?i)\bmaintainer", "severity": "blocker", ... "extra_roots": ["commands", ".abcd/rules.json", "internal/core/rules/defaults"]" evidence: .abcd/docs-lint.json:2-5 — ""roots": ["docs", "README.md"]" evidence: internal/core/lint/roleban_test.go:17 — "func TestRepoRoleWordIsRefusedOnEveryLintRoot" evidence: internal/core/lint/lint.go:3263-3272 — "lintTokenExtraRoots runs each banned token that declares extra_roots over" evidence: internal/core/lint/tokenroots_test.go:24 — "func TestTokenExtraRootsCarryThatTokenOnly" - ac-3 — MET_WITH_CONCERNS: The test walks every command page and agent prompt, finds each paragraph that puts a question to a human (an imperative ask of a person, a relayed question, a pre-answering
--yes, an act on someone's word), requires the paragraph to name one of the two roles the mode's Addressee() seam defines, and requires the section to setabcd mode <state>first; the follow-up commit made every stop on the ahoy, intent and site pages comply. Concern: the detector is a regex grammar over paragraph shapes, so a question phrased outside it is not held to the rule, and the floor is ten blocks found. evidence: internal/surface/cli/roles_vocabulary_test.go:105 — "func TestPluginQuestionBlocksNameTheAddressee" evidence: internal/surface/cli/roles_vocabulary_test.go:98 — "var questionBlock = regexp.MustCompile(" evidence: internal/surface/cli/roles_vocabulary_test.go:137-139 — "asks the %s but its section never setsabcd %sfirst" evidence: internal/core/mode/mode.go:136-141 — "func (s State) Addressee() string { ... return "technical facilitator" ... return "product thinker"" - ac-4 — MET:
product-thinker.mdandtechnical-facilitator.mdsit in the core glossary besiderecord-families.md, each introduced_in this intent, each naming the other and record-families under not_to_be_confused_with, and each citing itd-97's stance that the facilitator is a mode, not a person. evidence: .abcd/development/brief/glossary/core/product-thinker.md:25 — "The role does not change with who runs the machinery. itd-97 (a draft) holds that the" evidence: .abcd/development/brief/glossary/core/technical-facilitator.md:24 — "itd-97 (a draft) holds that the facilitator is a mode, not a person." evidence: .abcd/development/brief/glossary/core/record-families.md:1 — "(the record-families page, in the same directory)" - ac-5 — MET: The test renders every command's
--helpthrough the cobra tree (at least twenty pages) and reads every command page and agent prompt (at least twenty, the agents' CHANGELOG aside), failing on any line matching the retired word, spelled apart in the test so the file never trips its own ban; it passes at BASE. evidence: internal/surface/cli/roles_vocabulary_test.go:51 — "func TestRenderedHelpAndPluginPagesNameTheRoles" evidence: internal/surface/cli/roles_vocabulary_test.go:23 — "var retiredRoleWord = regexp.MustCompile((?i)\b+ "main" + "tainer")" evidence: internal/surface/cli/roles_vocabulary_test.go:28-47 — "for _, glob := range []string{"commands/.md", "agents/.md"}"
Gap audit:
- honoured:
- Lint before sweep, so the sweep was watched red then green (spec Approach) evidence: internal/core/lint/roleban_test.go:17 — "func TestRepoRoleWordIsRefusedOnEveryLintRoot" evidence: internal/core/lint/tokenroots_test.go:74 — "func TestTokenExtraRootsLoadFromConfig"
- The sweep is one reviewed change across the command pages, the rules, the brief, the principles, the docs and the personas, with the persona hint rewritten rather than escaped evidence: .abcd/development/personas.json:16 — ""open-source project lead"" evidence: internal/core/rules/defaults/rules.json:1 — "(bundled rules: zero occurrences at BASE)"
- The addressee comes from the mode, not from a restated list: the test reads mode.States() and their Addressee() evidence: internal/surface/cli/roles_vocabulary_test.go:108-115 — "for _, s := range mode.States() { if who := s.Addressee(); who != "" {"
- The two glossary entries cite itd-97 and sit beside the record-families page evidence: .abcd/development/brief/glossary/core/technical-facilitator.md:4 — "itd-97 holds that the role is a mode, not a person."
- The escape is the marked allow comment, the only way past the blocker evidence: .abcd/docs-lint.json:184-186 — ""allow_context": ["(?i)< !--\sdocs-lint:\sallow\b"]"
- diverged:
- The press release says the word cannot come back; the lint guards the docs, the command pages and the rules only, so the brief, the principles and the personas registry — swept by ac-1 — are guarded by nothing evidence: .abcd/docs-lint.json:187-191 — ""extra_roots": ["commands", ".abcd/rules.json", "internal/core/rules/defaults"]" evidence: internal/core/lint/roleban_test.go:48-50 — "for _, want := range []string{"commands", ".abcd/rules.json", "internal/core/rules/defaults"} {"
- The word survives outside abcd's rendered text: six .github workflow YAML comments, Go source comments (internal/core/lint among them) and the agents' injection-canary fixtures; none is a surface the intent lists, so none is captured evidence: .github/workflows/ci.yml:475 — "# github-actions ecosystem, so bumps are a deliberate maintainer act" evidence: internal/core/lint/collect.go:32 — "// manual queue can tell the maintainer where to look."
- The question-block rule is mechanical only as far as the test's regex grammar reaches evidence: internal/surface/cli/roles_vocabulary_test.go:89-97 — "questionBlock finds a paragraph in which a page tells the agent to put a question to a human: an imperative ask"
- missing: (none)
Grounds
- pursued: the badge intent and every interview today turn on which of two people is being asked, and the pages that brief agents blur them; we expect agents to stop saying maintainer once no abcd text says it; shown wrong if transcripts after the sweep still use the word
Frontmatter
| id | itd-2609212137129937 |
|---|---|
| type | intent |
| lifecycle | shipped |
| kind | standalone |
| severity | minor |
.abcd/development/intents/shipped/itd-2609212137129937-abcd-s-own-text-names-the-product.md
open on GitHub ↗ · commit history ↗
References6
- adr-2609212115255771Phases and milestones are retired: sequencing is dependencies rendered as status, the checkpoint is the derived releaserelated
- itd-97The Facilitator Is a Mode, Not a Personrelated
- itd-174Each repository configures how far its facilitator is consulted and when it escalatesrelated
- itd-201Every question abcd's agents put to a human is asked one at a time, in plain language, with options that widenbuilds on
- itd-2609211913453478One page maps the record families, and phase, milestone and roadmap are retiredrelated
- itd-2609212130146198The status-line badge is true at every stopbuilds on
Referenced by8
- iss-2610262039584858itd-2609212137129937 bans 'maintainer' in every lint root, the command pages and rules included; 06-lint limits docs-lint to `docs/` and the repo-root prose.related
- iss-2610262043197794itd-191 assigns selection to 'the maintainer', a word itd-2609212137129937 removed in favour of naming the product thinker or the facilitatorrelated
- iss-2610262043202769itd-109 lets 'the maintainer' record a disposition, where itd-2609212137129937 requires naming the product thinker or the facilitatorrelated
- iss-2610262043210108itd-2610111655362931, filed after the ruling, counts 'maintainers' for promotion agreement while itd-2609212137129937 bans the wordrelated
- iss-2610262044373028The memory-notes promotion rule is stated in terms of maintainers, a word the shipped vocabulary ruling retiredrelated
- iss-2610262045454143itd-60 attributes decisions and reviews to the maintainer; itd-2609212137129937 retires the word in favour of the two named rolesrelated
- itd-2609212130146198The status-line badge is true at every stoprelated
- spc-2609212141412864abcd-s-own-text-names-the-product-thinker-or-the-technicalimplemented 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).
- iss-2610020731591808The docs-lint ban on the retired role word (itd-2609212137129937, ac-2) reaches the docs roots, the command pages, .abcd/rules.json and the bundled rules source only: .abcd/docs-lint.json's 'roles/retired-role-word' entry lists extra_roots commands, .abcd/rules.json and internal/core/rules/defaults, and the top-level roots are docs and README.md. The brief (.abcd/development/brief, 22 occurrences before the sweep, the largest share), the principles (.abcd/development/principles, 5) and the personas registry (.abcd/development/personas.json) were swept by ac-1 but are in no root the token reads, and the ac-5 test walks only the rendered help, commands/*.md and agents/*.md, so the word can return to the brief or a principle with nothing refusing it, against the press release's 'the word cannot come back' and the mechanism claim that agents say what they read (the OPINIONS domain points agents at the principles).
- iss-2610021446271464The site's landing page composes its hero quote from the press release of the newest shipped intent whose fidelity audit is MET (internal/core/site/compose.go:1251 newestMetIntent, 1153), and the first ingested audit of itd-60 (shipped 2026-09-30, two days after the role-vocabulary sweep b4df4f25d, which rewrote no intent body) makes that intent the hero: its press release says 'flags it for the maintainer to read', so 'abcd lint site' refuses the render with roles/retired-role-word on index.html and the site-render gate of make preflight exits 2 on a branch that only recorded the audit (chore/audit-v012-gaps at 373d8b5f9, over main 7fb52a6b5). The sweep intent itd-2609212137129937 scoped intent bodies out, yet a press release is abcd's own text the moment the composer renders it publicly; the retired word stands nine times in itd-60 and ten in the sweep intent's own record, so any later MET audit of an intent carrying it reproduces the refusal, and the landing page's text is decided by which audit was ingested last rather than by a guarded source.
- iss-2610021502084298No check meets the retired role word in an intent's press release at the record: the docs-lint rule roles/retired-role-word roots at the docs, the command pages and the rules, so a shipped or planned intent's press release carrying it is refused only when the site composer renders it as the landing page's hero quote, which is how itd-60's first MET audit broke the site-render gate (iss-2610021446271464). After the R5 reword of itd-60, thirteen shipped press releases still carry the word (itd-65, itd-66, itd-67, itd-69, itd-73, itd-74, itd-93, itd-102, itd-111, itd-114, itd-125, itd-2609111003026787, itd-2609212137129937), so the next MET audit ingested for any of them refuses the render again on a branch that only recorded an audit; the product thinker's ruling R5 (2026-10-02) accepted that a future slip breaks the build and did not ask for this check. Related to iss-2610020731591808, which names the brief, the principles and the personas registry as swept but unguarded.
- iss-2610262045546558itd-2609150819445595 gives the persona Iris the technical facilitator's role; itd-2610090831227812 says the registry picks the name from the role, Iris being the product thinker