From eac9edea1c45738fc4d4b4ddb15d5d32f6221aa4 Mon Sep 17 00:00:00 2001 From: REPPL <77722411+REPPL@users.noreply.github.com> Date: Mon, 21 Sep 2026 18:53:06 +0100 Subject: [PATCH 01/19] =?UTF-8?q?docs(intent):=20plan=20itd-24=20=E2=80=94?= =?UTF-8?q?=20phase=20retrospectives=20get=20their=20spec=20on=20the=20pro?= =?UTF-8?q?duct=20thinker's=20rulings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nudge once at the last close, a ranked few on embark, the durable-tier layout; the seed is the per-intent audit that exists. Planned through a hand move to drafts, since no verb gives a planned intent a spec (iss-2609211738504433). Refs: iss-2609211738504433 Assisted-by: Claude:claude-opus-5 --- .../intents/planned/itd-24-reflect-command.md | 29 +++++-- .../spc-2609211751376504-reflect-command.md | 83 +++++++++++++++++++ 2 files changed, 106 insertions(+), 6 deletions(-) create mode 100644 .abcd/development/specs/open/spc-2609211751376504-reflect-command.md diff --git a/.abcd/development/intents/planned/itd-24-reflect-command.md b/.abcd/development/intents/planned/itd-24-reflect-command.md index 0e5dcbc5f..56b410500 100644 --- a/.abcd/development/intents/planned/itd-24-reflect-command.md +++ b/.abcd/development/intents/planned/itd-24-reflect-command.md @@ -1,7 +1,7 @@ --- id: itd-24 slug: reflect-command -spec_id: null +spec_id: spc-2609211751376504 kind: bundle-member bundle: spc-83-operator-surfaces suggested_kind: null @@ -14,6 +14,7 @@ prd_path: null prd_grandfathered: true severity: minor builds_on: [itd-27] +impact: additive --- # Completed Phases Get A Retrospective @@ -34,6 +35,10 @@ The legacy `~/.claude/templates/retrospective.md.template` had the right prompt A phase audit and a phase retrospective are **distinct activities**, the same split `intent-fidelity-reviewer` Role 1 draws at the intent grain — one grain up. The audit asks *did the phase's `## Phase Acceptance` pass* (a per-bullet verdict). The retrospective asks *what did we learn* (transferable insight, interview-driven). `/abcd:reflect` does not replace the audit — it **consumes** it: the audit's verdicts are the seed material the retrospective interview opens from. +## Mechanism + +We expect the value of a retrospective to be in the lifeboat: a new project that starts from an old one's lessons avoids a repeat, because the lessons arrive with the work rather than being re-derived; shown wrong if projects embarked from a lifeboat carrying retrospectives never open a surfaced lesson. + ## What's In Scope - **`/abcd:reflect `** — retrospective for a completed phase, and the command's *only* argument form. Examples: `/abcd:reflect phase-1-substrate`, `/abcd:reflect phase-2-ahoy`. Per-intent reflection is out of scope (see below) — `/abcd:reflect` operates at the phase grain only. @@ -46,7 +51,7 @@ A phase audit and a phase retrospective are **distinct activities**, the same sp - Lessons learned (transferable insights, framed for future-you) - Decisions made (architectural / design choices crystallised during the phase) - Metrics (intents shipped, audit-note severity distribution, time-to-ship if measurable) -- **Output**: `.abcd/retrospectives//README.md` — a peer of `.abcd/intents/` and `.abcd/logbook/`, committed as part of the phase's permanent record. +- **Output**: `.abcd/development/retrospectives//README.md` — a peer of `.abcd/development/intents/`, committed as part of the phase's permanent record. - **Lifeboat integration**: `/abcd:disembark to ` packs *all* of the voyage's phase retrospectives into the lifeboat — the full reflection arc travels. `/abcd:embark from ` surfaces predecessor retrospectives during the press-release interview ("here's what the previous voyage learned about X — does that apply here?"). - **Reference back to intents and the audit**: the retrospective links to the phase doc, to the intents the phase bundled, and to the phase audit; per-intent reviewer notes are referenced (not duplicated). - **`reflection-composer` agent** — runs the interview, drafts the structured output, asks clarifying questions when answers feel thin. @@ -69,14 +74,22 @@ None stated. - **Given** a completed phase with no phase audit yet recorded, **when** the persona runs `/abcd:reflect `, **then** the command reports the missing audit and offers to run the phase-fidelity-reviewer inline before continuing into the retrospective. - **Given** a phase doc that exists but has no spec carrying its `phase:` anchor, **when** the persona runs `/abcd:reflect `, **then** the command refuses with "no specs anchored to `` — nothing shipped to reflect on" and writes no output. - **Given** a draft retrospective with thin answers (e.g. "what went well: it worked"), **when** the agent drafts the output, **then** the agent surfaces the thinness as a clarifying question rather than committing the thin answer. -- **Given** the same repo's lifeboat is then packed via `/abcd:disembark to `, **when** the lifeboat is inspected, **then** every `.abcd/retrospectives//README.md` the voyage produced is included in the lifeboat artefact. -- **Given** a target repo embarked from a lifeboat that includes retrospectives, **when** `/abcd:embark from ` runs the press-release interview, **then** the persona is shown predecessor retrospective lessons and asked which apply to the new voyage. +- **Given** the same repo's lifeboat is then packed via `/abcd:disembark to `, **when** the lifeboat is inspected, **then** every `.abcd/development/retrospectives//README.md` the voyage produced is included in the lifeboat artefact. +- **Given** a target repo embarked from a lifeboat that includes retrospectives, **when** `/abcd:embark from ` runs the press-release interview, **then** the persona is shown the few predecessor lessons ranked most like the new voyage's brief, with the rest as a list, and asked which apply. - **Given** an attempt to reflect on a phase whose specs are not all closed, **when** `/abcd:reflect ` runs, **then** the command warns the persona, lists the open specs anchored to that phase, and asks for confirmation to proceed anyway. +- **Given** the last piece of work anchored to a phase closes, **when** that close completes, **then** abcd says once that a retrospective for the phase is owed and names the command, and says nothing further about it. + +## Decisions + +Ruled by the product thinker on 2026-09-21, in the interview that gave this intent its spec: + +1. **Nudge once.** When a phase's last piece of work closes, abcd says once that a retrospective is owed; it is not repeated and it is not a gate. +2. **A ranked few on embark.** Predecessor lessons most like the new voyage's brief are shown; the rest are a list opened on request. +3. **Layout.** The retrospective lives under the durable record tier, `.abcd/development/retrospectives//README.md`; the paths this record was written against predate the three-tier layout and are read as that. ## Open Questions -- **Reflection cadence** — is there a soft prompt to encourage running it (e.g. when the last spec of a phase closes), or fully on-demand? -- **Lifeboat surfacing on embark** — how intrusive? The lifeboat carries all phase retrospectives; how should embark present them — show every one, or rank by relevance to the new voyage? Risk of "previous-voyage lessons" feeling like noise on a brand-new voyage. +_None open; decisions 1 and 2 settle the two this record carried (the reflection cadence and the lifeboat surfacing on embark)._ ## Blocking Dependency @@ -125,3 +138,7 @@ spec" as a bundle (`kind: bundle-member` + shared `bundle: spc-83-operator-surfa require. Bundle member by delivery relationship, not a scope change. This intent keeps its real grill linkage (`grill_session_id`); GR002 is handled via `prd_grandfathered`. Full record in the spec's process-exception note. + +## Grounds + +- pursued: nine phases have closed with their lessons living only in session handovers; we expect the first retrospectives to hold what the handovers do not, and a new voyage to open a carried lesson; shown wrong if the first retrospectives say nothing the handovers did not, or if no embarked project opens one diff --git a/.abcd/development/specs/open/spc-2609211751376504-reflect-command.md b/.abcd/development/specs/open/spc-2609211751376504-reflect-command.md new file mode 100644 index 000000000..9239a9f2d --- /dev/null +++ b/.abcd/development/specs/open/spc-2609211751376504-reflect-command.md @@ -0,0 +1,83 @@ +--- +id: spc-2609211751376504 +slug: reflect-command +intent: itd-24 +origin: researcher-authored +production_mode: hand-written +--- +# reflect-command + +## Summary + +The design record for itd-24, from the product thinker's interview of +2026-09-21 (decisions 1 to 3 on the intent). One host-run interview, +`/abcd:reflect `, seeded from what the phase actually shipped, +written to the durable record tier, packed by the lifeboat and surfaced on +embark. + +## Scope + +1. **The seed**: the phase document under `.abcd/development/roadmap/phases/` + names the intents it bundled; for each in `shipped/`, the `## Audit Notes` + the intent auditor wrote (per-criterion verdicts, honoured / diverged / + missing) and the `impact` and `shipped_in` stamps are the seed. The + phase-fidelity report this record first named does not exist; the + per-intent audit is the audit there is, and the seed says so when a + shipped intent carries no audit notes (criteria 1, 2). +2. **The interview**: five sections in order (went well, could improve, + lessons, decisions, metrics), one question at a time through the host's + question tool under the GRILL rules; the metrics section is computed + (intents shipped, audit-note severity distribution, first and last + `shipped_in`), not asked (criterion 1). +3. **The thin-answer rule**: an answer under a declared floor (one clause, or + a restatement of the section heading) is met with one follow-up question + before anything is written (criterion 4). +4. **Refusals and warnings**: a phase document naming no shipped intent + refuses and writes nothing; a phase with a named intent still in + `planned/` warns, lists them, and asks before proceeding; a shipped intent + with no audit notes is offered `abcd intent audit ` first, and the + interview continues either way (criteria 2, 3, 7). +5. **The output**: `.abcd/development/retrospectives//README.md`, + frontmatter naming the phase, the intents, the date and the seed's + provenance (which audits fed it), five sections, links to the phase + document and each intent; never a copy of the audit notes (criterion 1). +6. **The nudge**: `spec close` that ships the last planned intent a phase + document names prints one line that a retrospective is owed and the + command to run; it is printed once (the retrospective's absence is not + re-announced) and gates nothing (criterion 8, decision 1). +7. **The lifeboat**: `disembark` packs `.abcd/development/retrospectives/` + whole; `embark` ranks the packed retrospectives' lessons against the new + voyage's brief by term overlap with the brief's framing chapter and shows + the top three with the rest as a list, asking which apply (criteria 5, 6, + decision 2). + +## Out of scope + +- A phase-level fidelity audit: the seed is the per-intent audit. +- Per-intent or per-spec retrospectives. +- Editing a retrospective after it is written; a second run on the same phase + refuses naming the existing file. + +## Approach + +`internal/core/reflect` holds the seed builder (reads the phase document and +the shipped intents), the metrics, the thin-answer floor and the writer; the +interview itself is host-run from `commands/reflect.md`, which renders the +seed and the five sections and calls `abcd reflect write +--answers ` with the answers. The nudge is one line in `spec close`'s +ship path. Lifeboat packing extends the record-family list `disembark` +already carries; the embark ranking is a small term-overlap score in +`internal/core/lifeboat`, declared a heuristic. + +## How the criteria are satisfied + +| Criterion | Where | +| --- | --- | +| 1 seeded interview and the file | scope 1, 2, 5 | +| 2 missing audit offered first | scope 4 | +| 3 empty phase refuses | scope 4 | +| 4 thin answer gets a follow-up | scope 3 | +| 5 lifeboat packs them | scope 7 | +| 6 embark shows a ranked few | scope 7 | +| 7 open work warns and asks | scope 4 | +| 8 nudge once at the last close | scope 6 | From 4992e2a440ba27c135c3c6d461eed8d87231755c Mon Sep 17 00:00:00 2001 From: REPPL <77722411+REPPL@users.noreply.github.com> Date: Mon, 21 Sep 2026 18:54:26 +0100 Subject: [PATCH 02/19] =?UTF-8?q?docs(intent):=20supersede=20itd-27=20?= =?UTF-8?q?=E2=80=94=20the=20planning=20interview=20is=20the=20grilling=20?= =?UTF-8?q?it=20asked=20for?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Assisted-by: Claude:claude-opus-5 --- .../itd-27-grill-skill-and-glossary.md | 4 ++++ 1 file changed, 4 insertions(+) rename .abcd/development/intents/{planned => superseded}/itd-27-grill-skill-and-glossary.md (97%) diff --git a/.abcd/development/intents/planned/itd-27-grill-skill-and-glossary.md b/.abcd/development/intents/superseded/itd-27-grill-skill-and-glossary.md similarity index 97% rename from .abcd/development/intents/planned/itd-27-grill-skill-and-glossary.md rename to .abcd/development/intents/superseded/itd-27-grill-skill-and-glossary.md index 73d9e9bb7..a5e8dae2f 100644 --- a/.abcd/development/intents/planned/itd-27-grill-skill-and-glossary.md +++ b/.abcd/development/intents/superseded/itd-27-grill-skill-and-glossary.md @@ -1,5 +1,6 @@ --- id: itd-27 +superseded_by: itd-94 slug: grill-skill-and-glossary spec_id: null kind: standalone @@ -29,6 +30,9 @@ severity: major # Domain Experts Get Their Intents Grilled Before Anyone Codes Them +> **Superseded by itd-94** on 2026-09-21, on the product thinker's ruling: the planning interview that itd-94's readiness gate requires is the grilling this record asked for, run one question at a time under the GRILL rules; the PRD it synthesised is the native spec `abcd intent plan` mints; the glossary lives in the brief; the external planner it handed the PRD to no longer exists. The named Socratic moves and the per-session question cap are not carried forward. + + ## Press Release > **abcd ships `/abcd:intent grill`, a two-phase Socratic-challenger sub-verb: it interrogates an intent for vagueness and hidden assumptions, then silently synthesises a Pocock-shaped PRD that becomes primary context for `/flow-next:plan`.** Phase 1 (interactive) caps at three questions per round, twelve per session, each tagged with a named Socratic move (Definition / Elenchus / Dialectic / Maieutics / Counterfactual / Generalization). Phase 2 (silent, post-grill) writes the seven Pocock sections — Problem, Solution, `User Stories`, Implementation Decisions, Testing Decisions, Out of Scope, Further Notes — to `.abcd/intents//prd.md`. Template adapted from [mattpocock/skills `to-prd`][pocock-to-prd] (MIT, attributed). With a `terminology/` glossary present, Phase 1 also flags forbidden synonyms and offers inline term additions as they're sharpened. The `press-release` intent and the frozen PRD are both **immutable input artefacts** — frozen at `/abcd:intent plan` time, never edited after promotion. The `press release` is the elevator pitch; the PRD is the `oracle`-consumption contract. `intent-fidelity-reviewer` (paper-only initially) compares delivered reality to both. `internal/core/lint` blocks promotion when no PRD is on disk, when forbidden synonyms appear, or when a frozen PRD is mutated. Sibling of `/abcd:intent refine` — refine is gentle and persona-driven; grill is adversarial, oracle-driven, and uniquely produces the handoff artefact. From 2a91ebe04e034f442392d606e1f7522458c23aea Mon Sep 17 00:00:00 2001 From: REPPL <77722411+REPPL@users.noreply.github.com> Date: Mon, 21 Sep 2026 18:54:46 +0100 Subject: [PATCH 03/19] docs(intent): close the itd-27 supersession both ways and repoint its links Assisted-by: Claude:claude-opus-5 --- .../decisions/adrs/0007-grill-skill-and-glossary.md | 2 +- .../intents/planned/itd-42-coherence-aware-grill.md | 4 ++-- ...tent-that-is-not-planned-cannot-be-implemented-abcd-gai.md | 1 + .../notes/socratic-and-first-principles-skills-evaluation.md | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.abcd/development/decisions/adrs/0007-grill-skill-and-glossary.md b/.abcd/development/decisions/adrs/0007-grill-skill-and-glossary.md index f4a738e02..6ed6cc0cc 100644 --- a/.abcd/development/decisions/adrs/0007-grill-skill-and-glossary.md +++ b/.abcd/development/decisions/adrs/0007-grill-skill-and-glossary.md @@ -153,6 +153,6 @@ are written to PRD frontmatter. After freeze: ## Related -- [itd-27](../../intents/planned/itd-27-grill-skill-and-glossary.md) — source intent +- [itd-27](../../intents/superseded/itd-27-grill-skill-and-glossary.md) — source intent - [05-internals/01-agents.md](../../brief/05-internals/01-agents.md) — `intent-fidelity-reviewer` auditor contract - tests/fixtures/grill/ — fixture corpus diff --git a/.abcd/development/intents/planned/itd-42-coherence-aware-grill.md b/.abcd/development/intents/planned/itd-42-coherence-aware-grill.md index 94bd6d154..45a7798f5 100644 --- a/.abcd/development/intents/planned/itd-42-coherence-aware-grill.md +++ b/.abcd/development/intents/planned/itd-42-coherence-aware-grill.md @@ -33,7 +33,7 @@ severity: major ## Why This Matters -The intent layer is abcd's highest-leverage moment for product clarity ([itd-27](itd-27-grill-skill-and-glossary.md) built `/abcd:intent grill` on exactly that premise). But the grill itd-27 shipped has a blind spot its `--with-docs` flag name actively hides: "glossary-aware" mode loads **only** the terminology database. It checks that an intent *speaks* the brief's words. It never reads the brief, never reads another intent, never reads a shipped spec. It enforces vocabulary; it does not enforce coherence. This intent also corrects the misnomer: `--with-docs` becomes `--glossary` (the terminology tier it always was), the new coherence tier is `--coherence`, and `--full` runs both. +The intent layer is abcd's highest-leverage moment for product clarity ([itd-27](../superseded/itd-27-grill-skill-and-glossary.md) built `/abcd:intent grill` on exactly that premise). But the grill itd-27 shipped has a blind spot its `--with-docs` flag name actively hides: "glossary-aware" mode loads **only** the terminology database. It checks that an intent *speaks* the brief's words. It never reads the brief, never reads another intent, never reads a shipped spec. It enforces vocabulary; it does not enforce coherence. This intent also corrects the misnomer: `--with-docs` becomes `--glossary` (the terminology tier it always was), the new coherence tier is `--coherence`, and `--full` runs both. So an intent can pass a full grill — crisp terms, EARS-clean acceptance, warrants surfaced — and still: @@ -97,7 +97,7 @@ _Empty. Populated by intent-fidelity-reviewer when intent moves to shipped/._ ## References -- Extends: [itd-27](itd-27-grill-skill-and-glossary.md) (grill skill & glossary) — adds a coherence tier to the grill itd-27 built; the glossary tier's behaviour is unchanged. **Also renames itd-27's `--with-docs` flag to `--glossary` and adds `--coherence` / `--full`** — itd-27's surface table and the grill `SKILL.md` flag list must be updated when this intent is planned. +- Extends: [itd-27](../superseded/itd-27-grill-skill-and-glossary.md) (grill skill & glossary) — adds a coherence tier to the grill itd-27 built; the glossary tier's behaviour is unchanged. **Also renames itd-27's `--with-docs` flag to `--glossary` and adds `--coherence` / `--full`** — itd-27's surface table and the grill `SKILL.md` flag list must be updated when this intent is planned. - Shares the grounded-adversary pattern with: [itd-41](../drafts/itd-41-phase-negotiator.md) (phase negotiator) — Socratic where it questions, grounded where it asserts. - Defers to: [itd-39](../drafts/itd-39-scope-aware-memory-retrieval.md) (scope-aware memory retrieval) — full-body cross-intent comparison at scale is itd-39's problem, not this intent's. - Coordinates with: [itd-48](itd-48-intent-fidelity-reviewer-roles-2-3.md) (cross-document fidelity reviewer — supersedes [itd-31](../superseded/itd-31-cross-document-fidelity-reviewer.md)) — different register: itd-48's Role 2 reviews delivered documents for drift; this grills an intent for coherence before it is planned. diff --git a/.abcd/development/intents/shipped/itd-94-an-intent-that-is-not-planned-cannot-be-implemented-abcd-gai.md b/.abcd/development/intents/shipped/itd-94-an-intent-that-is-not-planned-cannot-be-implemented-abcd-gai.md index c63a2c8cb..1ee07904a 100644 --- a/.abcd/development/intents/shipped/itd-94-an-intent-that-is-not-planned-cannot-be-implemented-abcd-gai.md +++ b/.abcd/development/intents/shipped/itd-94-an-intent-that-is-not-planned-cannot-be-implemented-abcd-gai.md @@ -1,5 +1,6 @@ --- id: itd-94 +supersedes: [itd-27] slug: an-intent-that-is-not-planned-cannot-be-implemented-abcd-gai spec_id: spc-9 kind: standalone diff --git a/.abcd/development/research/notes/socratic-and-first-principles-skills-evaluation.md b/.abcd/development/research/notes/socratic-and-first-principles-skills-evaluation.md index 3493564f3..e41ea8533 100644 --- a/.abcd/development/research/notes/socratic-and-first-principles-skills-evaluation.md +++ b/.abcd/development/research/notes/socratic-and-first-principles-skills-evaluation.md @@ -31,7 +31,7 @@ abstraction-layer boundary). > **Pointer corrected 2026-07-13.** This note originally cited a > `skills/abcd-intent-grill/` directory and its ACKNOWLEDGEMENTS as existing. > They do not exist in the tree: the Go rebuild left the grill as *planned, -> unbuilt* work — [itd-27](../../intents/planned/itd-27-grill-skill-and-glossary.md), +> unbuilt* work — [itd-27](../../intents/superseded/itd-27-grill-skill-and-glossary.md), > [adr-7](../../decisions/adrs/0007-grill-skill-and-glossary.md), extended by > [itd-42](../../intents/planned/itd-42-coherence-aware-grill.md). The harvest > disposition below stands; its target is itd-27/itd-42, and the mattpocock From b6fbcfd6330cfb374bb38d6f513dc929f393c367 Mon Sep 17 00:00:00 2001 From: REPPL <77722411+REPPL@users.noreply.github.com> Date: Mon, 21 Sep 2026 19:54:24 +0100 Subject: [PATCH 04/19] =?UTF-8?q?docs(intent):=20plan=20itd-28=20=E2=80=94?= =?UTF-8?q?=20reviews=20carry=20the=20commit=20they=20read=20and=20the=20b?= =?UTF-8?q?oard=20says=20how=20stale=20each=20is?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Re-scoped to the pin and the staleness view; the store, the redaction and the verifier are dropped in favour of what the record already holds. Assisted-by: Claude:claude-opus-5 --- .../planned/itd-28-rp-reviews-into-flow.md | 42 ++++++++----- ...c-2609211854150455-rp-reviews-into-flow.md | 60 +++++++++++++++++++ 2 files changed, 86 insertions(+), 16 deletions(-) create mode 100644 .abcd/development/specs/open/spc-2609211854150455-rp-reviews-into-flow.md diff --git a/.abcd/development/intents/planned/itd-28-rp-reviews-into-flow.md b/.abcd/development/intents/planned/itd-28-rp-reviews-into-flow.md index e809bbb48..2dd9e9469 100644 --- a/.abcd/development/intents/planned/itd-28-rp-reviews-into-flow.md +++ b/.abcd/development/intents/planned/itd-28-rp-reviews-into-flow.md @@ -1,7 +1,7 @@ --- id: itd-28 slug: rp-reviews-into-flow -spec_id: null +spec_id: spc-2609211854150455 kind: standalone suggested_kind: null reclassification_history: [] @@ -20,10 +20,14 @@ glossary_terms_used: - core/transport builds_on: [itd-1] severity: major +impact: additive --- # Spec-Tied Reviews Live Next To The Spec They Reviewed +> **Re-scoped on 2026-09-21** by the product thinker: the record keeps the pin and the staleness view and drops its own review store, its two-stage redaction and its pre-commit verifier. The record already holds dated review folders under `.abcd/work/reviews/` and gate receipts keyed by the commit they gate; what is missing is that every review names the commit it read and the status board says how stale each has become. The scrub rides the scanner that already exists. The press release and scope below are read through this paragraph and the Decisions section. + + ## Press Release > **abcd lands every spec-tied review next to the spec it reviewed, in the native review store, pinned to the commit it reviewed, with a sanitisation pass before commit.** When a plan-review or impl-review finishes — whichever oracle adapter produced it — an abcd-side post-processor captures the review receipt via the native receipt contract and lands a canonical JSON sidecar (`review.json`) and rendered Markdown view (`review.md`) in a per-review directory at `.abcd/reviews//--/`. The sidecar carries the full sanitised review body, structured findings, and a `review_of_commit` SHA pin so future agents can detect when a review's findings have gone stale. Raw transcripts land in a per-review `raw/` subdirectory (gitignored). A two-stage redaction scheme applies: Stage 1 is a write-time sanitiser (AWS, GCP, Azure, Cloudflare, GitHub, Anthropic, OpenAI, Stripe, Slack, JWT, PEM) before any file is written; Stage 2 is a detect-and-block commit gate run through the scanner seam — native patterns by default, `gitleaks protect --staged --redact=100` as the stronger opt-in adapter when the binary is present, the engine always reported — that rejects commits if secrets survive Stage 1. An on-demand `reviews-index --spec ` regenerates `INDEX.md` + `INDEX.json`; CI runs `--check` mode to catch drift without ever writing to the working tree. @@ -85,30 +89,32 @@ The unscoped-transport sweep is adapter-scoped and runs only when an oracle adap - **Unscoped oracle transport storage** — covered by the adapter-scoped sweep into `.abcd/work/reviews/`. - **`Reviewed-by:` git trailer auto-injection on implementation commits** — out of scope (nice-to-have bidirectional linkage). +## Mechanism + +We expect a visible staleness count to make a stale review get re-run before a release rather than trusted, because the count turns "is this still valid" from a question nobody asks into a row on the board everyone sees; shown wrong if a release cut still cites reviews past the threshold with nobody re-running them. + ## Scope Conditions None stated. ## Acceptance Criteria -- **Given** a persona runs a plan-review for `spc-X` end-to-end via any oracle adapter, **when** the review completes, **then** a per-review directory lands at `.abcd/reviews/spc-X/--/` containing `review.json` (all required fields populated, `verdict` ∈ `{SHIP, NEEDS_WORK, MAJOR_RETHINK}`, non-empty `body_markdown` and `reviewed_files`) and `review.md` (mechanically rendered from `review.json`). -- **Given** the post-processor runs twice on the same receipt, **when** both invocations complete, **then** there is exactly one per-review directory in `.abcd/reviews/spc-X/` (idempotent; the second invocation is a no-op). -- **Given** the post-processor is killed mid-write (`kill -9`), **when** the persona inspects the working tree, **then** no `.tmp` or partial files are visible to git. -- **Given** 5 concurrent post-processor invocations on the same spec, **when** they complete, **then** 5 distinct sequence numbers exist (no collisions). -- **Given** the persona sets `ABCD_REVIEW_POSTPROCESS=0` and runs a plan-review, **when** the review completes, **then** the post-processor exits 0 with no side effects and the review remains only in the producing oracle adapter's raw output. -- **Given** a staged `.abcd/reviews/**` file containing a multi-cloud secret (AWS access key, fine-grained GitHub PAT, Anthropic key, JWT, or PEM private key) that was NOT caught by Stage 1, **when** the pre-commit hook runs the Stage-2 scan (native engine, or gitleaks when present), **then** the commit is blocked with the finding path/line/rule reported (never the raw secret value). -- **Given** the gitleaks binary is absent, **when** the pre-commit hook runs the Stage-2 scan, **then** the native engine runs and the hook output names the engine that ran — a downgrade is never silent. -- **Given** a committed `.abcd/reviews/**/*.md` file containing `AKIAIOSFODNN7EXAMPLE`, **when** the pre-commit hook runs, **then** the EXAMPLE-allowlisted value is NOT redacted. -- **Given** a review file with a `review_of_commit` SHA that fails `git rev-parse --verify`, **when** the pre-commit hook runs, **then** the commit is rejected with a clear error message. -- **Given** a `review.json` with `body_markdown` exceeding `body_max_bytes`, **when** the pre-commit verifier runs, **then** the commit is rejected with guidance (the post-processor truncates automatically; this acceptance captures the case where someone manually edits the sidecar to violate the cap). -- **Given** a CI run on a PR touching `.abcd/reviews/**`, **when** `reviews-index --check --all` runs, **then** the workflow fails on drift with the exact remediation command and never writes back to the branch. -- **Given** the brief is updated, **when** a contributor reads `05-internals/02-adapters.md` and `05-internals/03-configuration.md`, **then** they find explicit text describing the two-store carve-out (spec-tied via the native review pipeline; unscoped via a configured oracle adapter). -- **Given** the README is updated, **when** a contributor reads the Acknowledgements section, **then** they find explicit citations of `gitleaks` (Apache-2.0) and `REPPL/abcdZero` F-075 / F-037 prior art. +- **Given** a review folder under `.abcd/work/reviews/` is filed by any of abcd's own review paths, **when** it is written, **then** its summary carries `review_of_commit: ` written by the tool, and the record lint refuses a review folder without one (a folder that predates the rule is named as legacy, not refused). +- **Given** the bare `abcd` status board renders, **when** review folders exist, **then** each is listed with the spec or scope it reviewed and the number of commits the default branch has moved since its `review_of_commit`, and one past twenty is flagged for a re-run. +- **Given** a review of a spec, **when** it is filed, **then** its folder name carries the spec's id, so a reader finds it from the spec. +- **Given** a review body carries a secret, **when** it is committed, **then** the scanner the repository already runs refuses it; this record builds no second scrubber. +- **Given** `--json`, **when** the board renders, **then** the staleness rows and the threshold are in the payload. + +## Decisions + +Ruled by the product thinker on 2026-09-21, in the interview that gave this intent its spec: + +1. **Pin and staleness only.** The review store, the two-stage redaction and the pre-commit verifier this record first described are dropped: the dated review folders and the gate receipts are the store, and the scanner is the scrub. +2. **The staleness view is on the status board**, flagged past twenty commits. ## Open Questions -- **Hook coverage for hosts without a Stop-hook equivalent**: standalone invocation of the post-processor with `--from-receipt --spec ` is the documented fallback. Should a per-host wrapper also ship? -- **Stale review threshold for `staleness` column**: currently `_commits` since `review_of_commit`. Should we add a "danger" threshold (e.g., `>20_commits` shown red)? Deferred polish. +_None open; the hook-coverage and the danger-threshold questions this record carried fall away with the store, and the threshold is decision 2._ ## Audit Notes @@ -124,3 +130,7 @@ _Empty. Populated by intent-fidelity-reviewer when intent moves to shipped/._ [bias]: https://arxiv.org/html/2603.18740v1 "Confirmation Bias in `LLM`-Assisted Security Code Review" [liip]: https://www.liip.ch/en/blog/preventing-context-pollution-for-%61i-agents "Liip — Preventing Context Pollution for `AI` Agents" + +## Grounds + +- pursued: the release gate now demands review receipts, and a receipt with no commit named cannot be judged fresh; we expect the next cut to read the staleness rows before it trusts a receipt; shown wrong if the next cut never asks how old a receipt is diff --git a/.abcd/development/specs/open/spc-2609211854150455-rp-reviews-into-flow.md b/.abcd/development/specs/open/spc-2609211854150455-rp-reviews-into-flow.md new file mode 100644 index 000000000..dfd2a6396 --- /dev/null +++ b/.abcd/development/specs/open/spc-2609211854150455-rp-reviews-into-flow.md @@ -0,0 +1,60 @@ +--- +id: spc-2609211854150455 +slug: rp-reviews-into-flow +intent: itd-28 +origin: researcher-authored +production_mode: hand-written +--- +# rp-reviews-into-flow + +## Summary + +The design record for itd-28 as re-scoped on 2026-09-21: every review names +the commit it read, and the status board says how stale it has become. No +new store, no new scrubber. + +## Scope + +1. **The pin**: every path in abcd that files a review folder under + `.abcd/work/reviews/-/` writes `review_of_commit: ` + into `00-summary.md`'s frontmatter, taken from the tree it reviewed; the + gate receipts keyed by sha already carry the pin in their directory name + (criterion 1). +2. **The lint**: the reviews-charter rule (RD001's sibling) refuses a review + folder written after this ships without the key, and names a folder from + before it as legacy rather than refusing (criterion 1). +3. **The board**: the bare `abcd` status board gains a reviews block: scope + or spec id, `review_of_commit` short sha, commits since (`git rev-list + --count ..`), and a flag past twenty; ordered stalest first + (criteria 2, 5). +4. **The name**: a review of a spec is filed as `--/`, so + the spec id is in the folder name; the board reads it from there + (criterion 3). +5. **The scrub**: unchanged; the scanner's store-before-commit redactor and + the pre-commit name-guard already run on the reviews tree (criterion 4). + +## Out of scope + +- A review store of abcd's own, a JSON sidecar, a two-stage redaction, a + pre-commit verifier: dropped by decision 1. +- Re-running a stale review: the board flags, a person or a run re-runs. + +## Approach + +`internal/core/record` already reads the reviews tree for the charter check; +the pin is one more frontmatter key it reads and the lint one more rule +beside RD001. The board's block is computed in `internal/core/positioning` +(where the status board's other blocks live) from the same read plus one +`rev-list --count` per folder through `gitutil`. The writers are the few +places abcd itself files a review (the semantic-gate receipts already pin; +the intent-audit ingest and the reviews-charter template gain the key). + +## How the criteria are satisfied + +| Criterion | Where | +| --- | --- | +| 1 pin written, lint refuses its absence | scope 1, 2 | +| 2 board lists staleness, flags past twenty | scope 3 | +| 3 spec id in the folder name | scope 4 | +| 4 scrub is the existing scanner | scope 5 | +| 5 json carries the rows | scope 3 | From 2e66864e11f111b28ed393e29e1aae99e77a2b43 Mon Sep 17 00:00:00 2001 From: REPPL <77722411+REPPL@users.noreply.github.com> Date: Mon, 21 Sep 2026 20:00:05 +0100 Subject: [PATCH 05/19] =?UTF-8?q?docs(intent):=20plan=20itd-34=20=E2=80=94?= =?UTF-8?q?=20the=20bundle=20command=20and=20the=20reclassify=20verb,=20th?= =?UTF-8?q?e=20kinds=20being=20shipped?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Assisted-by: Claude:claude-opus-5 --- .../planned/itd-34-three-intent-kinds.md | 50 +++++++------ ...spc-2609211859391533-three-intent-kinds.md | 72 +++++++++++++++++++ 2 files changed, 100 insertions(+), 22 deletions(-) create mode 100644 .abcd/development/specs/open/spc-2609211859391533-three-intent-kinds.md diff --git a/.abcd/development/intents/planned/itd-34-three-intent-kinds.md b/.abcd/development/intents/planned/itd-34-three-intent-kinds.md index dd77bafe6..70ed32464 100644 --- a/.abcd/development/intents/planned/itd-34-three-intent-kinds.md +++ b/.abcd/development/intents/planned/itd-34-three-intent-kinds.md @@ -4,14 +4,18 @@ slug: three-intent-kinds kind: standalone suggested_kind: standalone bundle: null -spec_id: null +spec_id: spc-2609211859391533 reclassification_history: [] builds_on: [itd-1] severity: major +impact: additive --- # Intents Promote In Three Flavours — Standalone, Bundle-Member, Discipline +> **Re-scoped on 2026-09-21** by the product thinker: the three kinds, the `disciplines/` shelf and the two-way supersession link this record described have shipped through other records; what remains, and what this record now plans, is the bundle command and the `reclassify` verb. The press release and scope below are read through this paragraph and the Decisions section. + + ## Press Release > **abcd ships three intent kinds, each with its own lifecycle path through `/abcd:intent plan`.** A standalone intent maps 1:1 to a flow-next `spec` — the default for ~60% of intents, and the only path the prior brief recognised. A bundle-member intent shares a `spec` with its bundle-mates: the persona runs `/abcd:intent plan itd-A itd-B`, abcd creates one shared `spec` with both intents listed, and both files move from `drafts/` to `planned/` together. A discipline intent has no persona moment of its own — it's a cross-cutting rule (every `spec` must carry acceptance criteria, every agent `prompt` must declare a `version`) that lives in `disciplines/` instead of `drafts/`, never gets its own `spec`, but applies to every other `spec` as an inherited acceptance gate. Capture stays format-neutral; the binding `kind` field is set at plan time, with an `oracle` classifier writing an advisory hint at capture time. The discipline shape is `voyage`-agnostic — an application `voyage` (e.g., a macOS app under abcd) produces its own disciplines around privacy-impact review or accessibility passes with the same lifecycle as abcd's own discipline intents. @@ -62,7 +66,6 @@ For late kind changes (a standalone intent realised to be a bundle-member; a dra All intent files gain four new fields: ```yaml -kind: null # set by /abcd:intent plan: standalone | bundle-member | discipline suggested_kind: null # advisory, written by capture-time LLM classifier; can be ignored bundle: null # for kind: bundle-member, the bundle ID reclassification_history: [] # appended to by /abcd:intent reclassify @@ -129,27 +132,21 @@ This mirrors the lint-code namespace pattern in [`05-internals/06-lint.md`](../. - **A fourth kind** for some hypothetical case the three kinds don't cover. If a fourth kind is needed, it lands as a future intent, not this one. **Lineage update (itd-44, spc-56):** the standing-infrastructure-choice case the three kinds don't fit landed as [itd-44](../drafts/itd-44-fourth-intent-kind-decision.md) — but *not* as a fourth persisted `kind`. itd-44 adds a fourth capture-time *verdict*, `decision`, that routes a confirmed standing choice into the existing ADR store (`adr-N`); the persisted `kind` enum here stays **three-valued**, and there is deliberately no `intents/decisions/` lifecycle. - **Migrating disciplines into the brief itself.** Disciplines live in `intents/disciplines/` so they have the same lifecycle, lint, and frontmatter discipline as other intents. Folding them into the brief would lose the lifecycle handling. The brief *describes* the discipline kind in its mental-model and intent-surface sections; the discipline files themselves stay under `intents/`. +## Mechanism + +We expect a `reclassify` verb to end the hand moves that leave one-way supersession links and mismatched kinds, because the two-way write and the shelf move become one command whose refusals name what is missing; shown wrong if superseded records still arrive with a missing back-link after it ships. + ## Scope Conditions None stated. ## Acceptance Criteria -> _BDD format, per the [itd-1 discipline](../disciplines/itd-1-acceptance-gates.md). These gates are checked by `intent-fidelity-reviewer`'s single-document role when this intent moves to `shipped/`._ - -- **Given** a draft intent at `drafts/itd-N-foo.md` with `kind: null`, **when** the user runs `/abcd:intent plan itd-N`, **then** abcd proposes a kind based on the intent body and cross-references, the user confirms or overrides via interactive prompt, and the chosen kind is written to the intent's frontmatter as binding. -- **Given** two draft intents at `drafts/itd-A-foo.md` and `drafts/itd-B-bar.md` whose press releases reference each other in their References sections, **when** the user runs `/abcd:intent plan itd-A itd-B`, **then** `/flow-next:plan` is called once with both intents as joint input; the resulting spec (`spc-N`) in the native spec store has `intent: [itd-A, itd-B]`; each intent's frontmatter has `kind: bundle-member`, `bundle: `, and `epic_id: spc-N`; both files move from `drafts/` to `planned/`. -- **Given** two draft intents `itd-A` and `itd-B` scoped to different phases, **when** the user runs `/abcd:intent plan itd-A itd-B` (multi-arg, kind=bundle-member), **then** abcd hard-blocks promotion with lint code `IL011`, cites the bundle invariant in [`brief/04-surfaces/05-intent.md § 1`](../../brief/04-surfaces/05-intent.md#1-intent-ids-kinds-and-lifecycle), and offers the user two resolutions: (a) re-scope all proposed members into the same phase, or (b) downgrade one or more members to `kind: standalone` and re-run plan. Worked example in the wild: the `intent-capture-discipline` bundle (itd-27 + itd-30) was retired on 2026-05-07 for exactly this reason — both intents now ship as `kind: standalone`. -- **Given** a bundle's shared spec closes in the native spec store, **when** the lifecycle hook fires, **then** all bundle-member intents (those with the matching `bundle:` field) move from `planned/` to `shipped/` together AND `intent-fidelity-reviewer`'s single-document role runs once per member against the same delivered reality, producing per-member Audit Notes. -- **Given** a draft intent that the user wants to promote as a discipline, **when** the user runs `/abcd:intent plan itd-N` and selects `kind: discipline` at the prompt, **then** NO `/flow-next:plan` call is made; the intent's acceptance gates are registered in `.abcd/disciplines/.json`; the file moves from `drafts/` to `disciplines/`. The intent's frontmatter has NO `status` field — the directory IS the state. -- **Given** a discipline-kind intent in `disciplines/`, **when** any subsequent flow-next spec is plan-reviewed, **then** the plan-review verifies the spec's acceptance criteria are compatible with all active disciplines' rules — drift between spec acceptance and discipline gate is flagged. -- **Given** a shipped intent that the user later realises is fully superseded by a newer intent, **when** the user runs `/abcd:intent reclassify --kind superseded --by --reason "fully covered by itd-M"`, **then** the file moves from `shipped/` to `superseded/`; frontmatter gains both `superseded_by: itd-M` AND `kind_at_supersession: standalone` (preserving what the intent was when retired); a `reclassification_history` entry records the date + reason. -- **Given** an active discipline that is being replaced by a stricter successor, **when** the user runs `/abcd:intent reclassify --kind superseded --by `, **then** the file moves from `disciplines/` to `superseded/`; frontmatter gains both `superseded_by: itd-M` AND `kind_at_supersession: discipline` so future readers can tell the retired intent was a rule (not a capability). -- **Given** an intent in `superseded/` lacks either `superseded_by` or `kind_at_supersession`, **when** `internal/core/lint` runs, **then** the lint hard-blocks with a clear error — both fields are required for every superseded intent regardless of original kind. -- **Given** the corpus contains two intents whose press releases reference each other and target the same release, **when** `intent-fidelity-reviewer`'s shape-classification role runs (pre-commit or on `/abcd:intent` invocation), **then** a "bundle candidate" suggestion appears in `/abcd:intent` status output AND in `.abcd/logbook/audit/shape-/report.{json,md}`. -- **Given** the user declines a shape-classification suggestion, **when** the reviewer runs again on the same corpus state, **then** the declined suggestion is NOT re-surfaced (logged in the reviewer's "declined-suggestions" cache) — the reviewer doesn't nag. -- **Given** a project shipping a non-abcd application (e.g., idelphiDev) under the abcd intent framework, **when** the user captures a project-specific discipline (e.g., "every recording feature includes a privacy-impact review"), **then** the same lifecycle applies — the discipline lands in `disciplines/`, never gets its own spec, and is enforced against every other spec via plan-review. The framework treats it identically to abcd's own disciplines. -- **Given** the brief and intent corpus are updated, **when** `internal/core/lint` runs, **then** it verifies (a) every intent in `planned/` has `kind` set and matching the directory; (b) `kind: bundle-member` intents have `bundle:` set bidirectionally with their bundle-mates; (c) `kind: discipline` intents live only in `disciplines/` or `superseded/`; (d) `kind: discipline` intents have `epic_id: null`; (e) discipline-kind intents have NO `status` field (the directory is the state); (f) every intent in `superseded/` has both `superseded_by` and `kind_at_supersession`. Violations are hard-block lint failures. +- **Given** two draft intents, **when** `abcd intent plan itd-A itd-B` runs, **then** it asks for a bundle name, mints one shared spec naming both, writes `kind: bundle-member` and `bundle: ` on each, and moves both to `planned/` together; two drafts scoped to different phases are refused naming both phases, and nothing moves. +- **Given** a bundle's shared spec is closed, **when** the close-hook runs, **then** every member with that `bundle:` ships together. +- **Given** `abcd intent reclassify --kind ` or `--kind superseded --by --reason "…"`, **when** it runs, **then** the record's kind, shelf and links change in one write, with `superseded_by` on the record and `supersedes` on the successor written together; a shipped intent asked to become a discipline is refused and told to file a discipline that supersedes it. +- **Given** one member of a bundle is superseded, **when** the reclassify completes, **then** the surviving member stays `bundle-member` and its record states that the bundle now has one member. +- **Given** the record lint runs, **when** a planned intent's `kind` does not match its shelf, or a `bundle-member` names a bundle whose other members do not exist, **then** the lint refuses naming the record. ## Dependencies @@ -158,13 +155,18 @@ None stated. - **Coordinated with:** [itd-48](itd-48-intent-fidelity-reviewer-roles-2-3.md) — itd-48 owns the cross-document role (Role 2) and the shape-classification role (Role 3) on `intent-fidelity-reviewer`, superseding [itd-31](../superseded/itd-31-cross-document-fidelity-reviewer.md) which originally introduced the cross-document concept. The agent's three-role architecture is documented uniformly across the brief and intent surfaces. - **Coordinated with:** [itd-48](itd-48-intent-fidelity-reviewer-roles-2-3.md) (cross-document role) and [itd-34's own shape-classification role] — these are the second and third roles on `intent-fidelity-reviewer` (the first being single-document fidelity per itd-1). Each role has its own user-facing verb under `/abcd:intent` (consistency, shape, review respectively). The earlier `tier-0-audit-substrate` bundle ([itd-31](../superseded/itd-31-cross-document-fidelity-reviewer.md) + itd-32) was dissolved on 2026-05-07 when the unified-`/abcd:audit`-surface premise no longer held; itd-31 promoted to standalone (later superseded by itd-48 on 2026-05-27), itd-32 superseded. An even earlier attempted bundle (`intent-capture-discipline`, itd-27 + itd-30) was retired on the same day because itd-27 and itd-30 are scoped to different phases — bundles cannot span phases (one shared spec shipped together is the invariant). Both intent-capture intents reclassified to standalone. +## Decisions + +Ruled by the product thinker on 2026-09-21, in the interview that gave this intent its spec: + +1. **Both remainders are built**: the bundle command and the `reclassify` verb. +2. **You name the bundle**; the command asks for a short name. +3. **A survivor stays.** When one member is superseded the other stays a bundle-member of a bundle of one, and says so. +4. **A shipped intent never changes kind.** A rule discovered after the fact is filed as a discipline that supersedes it. + ## Open Questions -- **Bundle ID assignment.** Multi-arg `/abcd:intent plan itd-A itd-B` needs to generate or accept a bundle ID. Options: (a) auto-generate a slug from the joint title (terse), (b) prompt for an explicit ID at plan time (deliberate), (c) require pre-declaration in one of the member intents' frontmatter before plan runs (strict). Recommend (b) with default suggestion derived from joint title. -- ~~**What happens if a bundle's intents are scoped to different phases?**~~ **Resolved 2026-05-07** — bundle invariant codified: all members belong to the same phase; multi-arg plan hard-blocks via `IL011` if they disagree. See [`brief/04-surfaces/05-intent.md § 1`](../../brief/04-surfaces/05-intent.md#1-intent-ids-kinds-and-lifecycle) "Bundle invariant" and AC bullet above. Worked example: `intent-capture-discipline` retirement (itd-27 + itd-30 scoped to different phases). -- **Discipline reclassification of a *shipped* intent.** Hypothetical: a standalone intent ships, then later we realise it was actually a discipline all along (rule applied to every subsequent spec anyway). Can `/abcd:intent reclassify --kind discipline` work post-ship? Probably yes, with the historical fidelity audit preserved as a `pre-reclassification-audit` field. Edge case; defer until first occurrence. -- **Bundle dissolution.** If two bundle-members ship as a bundle, then later one of them is superseded, what happens to the bundle? Recommend: the surviving member stays at `kind: bundle-member` with `bundle: ` but a new `bundle_dissolved: true` field; the superseded member moves to `superseded/` as usual. -- **Multi-bundle membership.** Can an intent belong to two bundles? Recommend no — bundle membership is exclusive. If two bundles overlap on an intent, that's a sign one of the bundles is mis-scoped. +_None open; decisions 2 to 4 settle the three this record carried._ ## Audit Notes @@ -178,3 +180,7 @@ _Empty. Populated by intent-fidelity-reviewer's single-document role when this i - [`README.md`](../../../../README.md) — top-level "What is intent-driven development?" section gains a paragraph on the three kinds; `/abcd:intent` planned-commands table gains `reclassify` and multi-arg `plan` rows. - 2026-05-07 audit conversation that surfaced the structural finding: ~40% of intents have non-1:1 relationships with at least one other intent. - The discipline-kind framing is consistent across project types (framework projects produce more disciplines than application projects, but both produce some). Cross-project taxonomy revisit: see "Discipline subtypes are deferred" above. + +## Grounds + +- pursued: the autonomous run supersedes and re-plans records unattended and has no verb to do it with; we expect the reclassify verb and the bundle command to be what it calls, and the hand moves with their one-way links to stop; shown wrong if a record superseded after this ships still carries a one-way link, or if the run never calls either diff --git a/.abcd/development/specs/open/spc-2609211859391533-three-intent-kinds.md b/.abcd/development/specs/open/spc-2609211859391533-three-intent-kinds.md new file mode 100644 index 000000000..02acbc98f --- /dev/null +++ b/.abcd/development/specs/open/spc-2609211859391533-three-intent-kinds.md @@ -0,0 +1,72 @@ +--- +id: spc-2609211859391533 +slug: three-intent-kinds +intent: itd-34 +origin: researcher-authored +production_mode: hand-written +--- +# three-intent-kinds + +## Summary + +The design record for itd-34's remainder, from the product thinker's +interview of 2026-09-21 (decisions 1 to 4): the bundle command and the +`reclassify` verb. The kinds, the shelves and the two-way supersession link +already exist and are read, not built. + +## Scope + +1. **The bundle command**: `abcd intent plan itd-A itd-B [itd-C…]` takes + `--bundle ` (asked for by the plugin page, refused absent on the + CLI), refuses members scoped to different phases naming both, mints ONE + spec whose frontmatter lists every intent (`intents: [itd-A, itd-B]` + beside the existing `intent:` key naming the first), stamps + `kind: bundle-member` and `bundle: ` on each, links each `spec_id`, + stamps scope conditions on each, and moves all together under the intent + store's mint lock; any refusal leaves nothing moved (criterion 1). +2. **The close-hook**: `spec close` on a spec naming several intents ships + every member whose `bundle:` matches, with the same impact rule per + member (criterion 2). +3. **`abcd intent reclassify --kind ]|superseded --by --reason "…">`**: one write under + the lock that sets `kind`, moves the shelf where the kind implies one + (superseded → `superseded/`), writes `superseded_by` on the record and + appends to `supersedes` on the successor (an intent or an ADR), appends a + `reclassification_history` entry (from, to, date, reason), and prints + the paths moved; `--kind discipline` on a shipped intent is refused with + the remedy "file a discipline that supersedes it" (criterion 3). +4. **The survivor rule**: superseding a bundle member leaves the other as + `bundle-member` and appends a line to its `reclassification_history` + stating the bundle now has one member (criterion 4). +5. **The lint**: `record_schema` gains two checks: a planned or shipped + intent's `kind` matches its shelf (`discipline` on `disciplines/`, the + other two on `planned/` or `shipped/`), and every `bundle-member`'s + `bundle:` names a bundle at least one other record names or a history + line saying it is one (criterion 5). + +## Out of scope + +- Reclassifying a shipped intent to `discipline` (decision 4). +- Dissolving a bundle (decision 3). +- Any change to the disciplines' template or the supersession note's prose. + +## Approach + +The bundle command extends `intent.Plan` to take a list, minting once and +stamping per member inside the existing `withIntentMintLock`; the close-hook +extends the spec store's `Reconcile` to iterate the spec's `intents` list. +`reclassify` is a new `internal/core/intent` entry point over the same lock +and the record store's frontmatter writer, reusing the supersession-note +shape the superseded records already carry. The lint rows go beside the +one-way-supersession check that already exists. CLI and `commands/intent.md` +gain the two forms; the brief's intent chapter says what they do. + +## How the criteria are satisfied + +| Criterion | Where | +| --- | --- | +| 1 bundle plan, named, refused across phases | scope 1 | +| 2 members ship together | scope 2 | +| 3 reclassify in one write, shipped-to-discipline refused | scope 3 | +| 4 survivor stays and says so | scope 4 | +| 5 lint on kind and bundle | scope 5 | From 29dc740d47a51eab79cddf666a11436bb455a882 Mon Sep 17 00:00:00 2001 From: REPPL <77722411+REPPL@users.noreply.github.com> Date: Mon, 21 Sep 2026 20:06:07 +0100 Subject: [PATCH 06/19] =?UTF-8?q?docs(intent):=20close=20itd-36=20as=20del?= =?UTF-8?q?ivered=20=E2=80=94=20the=20memory=20verbs=20shipped=20in=20v0.1?= =?UTF-8?q?.0=20with=20no=20spec=20to=20close?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The three criteria that wait on other records become issues so they are not forgotten; the record carries shipped_in so the next cut does not report v0.1.0 work as new. Refs: iss-2609211905340006, iss-2609211905346507, iss-2609211905347458 Assisted-by: Claude:claude-opus-5 --- .../brief/04-surfaces/07-memory.md | 2 +- .../itd-37-modification-grammar.md | 4 +- .../itd-36-memory-unification.md | 27 ++++++++--- ...spc-2609211905174684-memory-unification.md | 45 +++++++++++++++++++ ...he-memory-store-as-its-own-source-class.md | 14 ++++++ ...d-as-documentation-and-vendored-as-code.md | 14 ++++++ ...te-does-not-read-a-kept-memory-original.md | 14 ++++++ .../iss-12-memory-shipped-vs-planned.md | 2 +- .../iss-23-itd-36-adr-28-reconcile.md | 2 +- 9 files changed, 113 insertions(+), 11 deletions(-) rename .abcd/development/intents/{planned => shipped}/itd-36-memory-unification.md (92%) create mode 100644 .abcd/development/specs/closed/spc-2609211905174684-memory-unification.md create mode 100644 .abcd/work/issues/open/iss-2609211905340006-dredge-synthesis-output-lands-in-the-memory-store-as-its-own-source-class.md create mode 100644 .abcd/work/issues/open/iss-2609211905346507-one-registry-entry-for-a-source-ingested-as-documentation-and-vendored-as-code.md create mode 100644 .abcd/work/issues/open/iss-2609211905347458-the-lifeboat-s-restrictive-licence-gate-does-not-read-a-kept-memory-original.md diff --git a/.abcd/development/brief/04-surfaces/07-memory.md b/.abcd/development/brief/04-surfaces/07-memory.md index 3de141df5..73e36585d 100644 --- a/.abcd/development/brief/04-surfaces/07-memory.md +++ b/.abcd/development/brief/04-surfaces/07-memory.md @@ -148,5 +148,5 @@ meaningful. - [`05-internals/07-memory.md`](../05-internals/07-memory.md): substrate spec - [`05-internals/09-provenance-substrate.md`](../05-internals/09-provenance-substrate.md): provenance and licence subsystem -- [`../../intents/planned/itd-36-memory-unification.md`](../../intents/planned/itd-36-memory-unification.md): the full intent spec with acceptance criteria +- [`../../intents/shipped/itd-36-memory-unification.md`](../../intents/shipped/itd-36-memory-unification.md): the full intent spec with acceptance criteria - [`research/related-work.md § Karpathy LLM Wiki`](../../research/related-work.md#karpathy-llm-wiki--pattern-source-for-abcdmemory): pattern source diff --git a/.abcd/development/intents/disciplines/itd-37-modification-grammar.md b/.abcd/development/intents/disciplines/itd-37-modification-grammar.md index d5c359827..944625725 100644 --- a/.abcd/development/intents/disciplines/itd-37-modification-grammar.md +++ b/.abcd/development/intents/disciplines/itd-37-modification-grammar.md @@ -22,7 +22,7 @@ Every spec carries a `## Modification Grammar` section with three sub-headings, A fourth axis — **`### Ripple`** — captures the per-spec-external concerns absorbed from idea-3 (systems thinking) at adversarial review (chat `idea-3-itd-38-adversaria-31A06A`, MAJOR_RETHINK outcome): vocabulary delta (HARD-enforced via the [vocabulary-registration requirement in `02-constraints/04-naming.md`](../../brief/02-constraints/04-naming.md)), surface delta (new commands / sub-verbs / agents / disciplines), coupling delta (what this spec newly depends on; what newly depends on it). The `Ripple` axis stays under itd-37 (same retrieval key as modification grammar — domain) rather than spawning a separate discipline. -At spec completion, `principle-distiller` (the role-extended curator from [itd-36](../planned/itd-36-memory-unification.md)) extracts the `## Modification Grammar` section into two memory pages per [`05-internals/07-memory.md`](../../brief/05-internals/07-memory.md): +At spec completion, `principle-distiller` (the role-extended curator from [itd-36](../shipped/itd-36-memory-unification.md)) extracts the `## Modification Grammar` section into two memory pages per [`05-internals/07-memory.md`](../../brief/05-internals/07-memory.md): - **`spec_modification_grammar_.md`** — append-only, per-spec. Source class `spec_modification_grammar`. Lifecycle: append-only per [`05-internals/04-universal-patterns.md § 8`](../../brief/05-internals/04-universal-patterns.md#8-artefact-lifecycle-taxonomy). - **`modification_grammar_.md`** — compounding-curated, per-domain. `principle-distiller` runs a curator-pass that synthesises across the per-spec pages. Lifecycle: compounding-curated per the same taxonomy. @@ -111,7 +111,7 @@ _Empty. Populated by `intent-auditor` Role 1 (single-document fidelity per itd-1 - [`research/related-work.md § Naur 1985`](../../research/related-work.md#naur-1985--programming-as-theory-building) — full prior-art comparison. - [`itd-1-acceptance-gates.md`](itd-1-acceptance-gates.md) — companion discipline; this discipline's acceptance criteria conform to its Given-When-Then shape. - [`itd-5-prompt-quality-additions.md`](itd-5-prompt-quality-additions.md) — companion discipline; disciplines stack at three (itd-1 + itd-5 + itd-37). -- [`../planned/itd-36-memory-unification.md`](../planned/itd-36-memory-unification.md) — companion intent (standalone); ships alongside itd-37; provides the substrate for `spec_modification_grammar` and `modification_grammar` page classes. +- [`../shipped/itd-36-memory-unification.md`](../shipped/itd-36-memory-unification.md) — companion intent (standalone); ships alongside itd-37; provides the substrate for `spec_modification_grammar` and `modification_grammar` page classes. - [`05-internals/07-memory.md`](../../brief/05-internals/07-memory.md) — substrate spec for the curator agent's two-page-class extraction. - [`02-constraints/04-naming.md`](../../brief/02-constraints/04-naming.md) — vocabulary-registration requirement (HARD) and bare-command-as-render discipline; both companion rules to this discipline's `Ripple` axis. - [`01-product/03-mental-model.md § The Naurian gap`](../../brief/01-product/03-mental-model.md) — the framing this discipline closes. diff --git a/.abcd/development/intents/planned/itd-36-memory-unification.md b/.abcd/development/intents/shipped/itd-36-memory-unification.md similarity index 92% rename from .abcd/development/intents/planned/itd-36-memory-unification.md rename to .abcd/development/intents/shipped/itd-36-memory-unification.md index 1de78394b..a12df2f2b 100644 --- a/.abcd/development/intents/planned/itd-36-memory-unification.md +++ b/.abcd/development/intents/shipped/itd-36-memory-unification.md @@ -1,16 +1,21 @@ --- id: itd-36 +shipped_in: v0.1.0 slug: memory-unification -spec_id: null +spec_id: spc-2609211905174684 kind: standalone suggested_kind: null reclassification_history: [] related_adrs: [adr-28] severity: major +impact: additive --- # Knowledge That Compounds, Not Knowledge That Re-Derives +> **Closed as delivered on 2026-09-21** on the product thinker's ruling: `/abcd:memory ingest`, `ask` and `lint`, the quotation budgets (MQ001, MQ002), the source-class rules (MS001, MS002), the licence rule (ML001) and `--keep-original` shipped in v0.1.0 while this record sat planned with no spec. The three criteria that wait on other records (the dredge synthesiser's output, the shared registry with the code-vendoring path, the lifeboat's restrictive-licence gate on a kept original) are captured as their own issues rather than carried here: iss-2609211905340006, iss-2609211905346507 and iss-2609211905347458. + + > **Packaging framing per [adr-28](../../decisions/adrs/0028-single-repo-curated-release.md) (supersedes adr-18).** The restrictive-licence gate's consumer is the **lifeboat** (`/abcd:disembark`), future/inert at launch: the curated release excludes `.abcd/**` wholesale, so `/abcd:launch` never evaluates what the gate guards. The canonical framing lives in the brief (`05-internals/09-provenance-substrate.md § 4`, `07-memory.md § 4`, `04-surfaces/04-launch.md § 2`). ## Press Release @@ -54,6 +59,10 @@ There's a real gap: **per-project durable knowledge has multiple legitimate upst - **Auto-classify the upstream.** This intent requires the user to invoke `/abcd:memory ingest ` explicitly. Auto-detection (e.g., scanning `~/Downloads/*.pdf` for ingest candidates) is deferred — a separate intent if friction proves real. - **MCP server for runtime memory editing.** Other knowledge frameworks ship MCP servers for `add_page`, `merge_pages`, etc. This intent ships JSON-on-disk + CLI surface only; the curator agent (`principle-distiller`) edits via standard file-edit tools. MCP integration is deferred if friction is real. +## Mechanism + +None stated. + ## Scope Conditions None stated. @@ -96,16 +105,18 @@ Per the idea-1 R5 review: the push replaces "≥3 projects in anger" (unachievab If all three produce coherent `.abcd/memory/` outputs, this intent ships. If one produces sprawl or fails the licence gates, scope is reduced and the failed example becomes the primary debug target. +## Decisions + +Ruled by the product thinker on 2026-09-21: close as delivered; the remainders become issues so they are not forgotten. + ## Open Questions -- **Persona for the press release** — Carol is product-lead per `personas.json`. The current draft assigns Carol "technical lead" instead — verify that the persona registry's role assignment doesn't conflict, OR pick a persona whose role-hint is "researcher" / "engineer" / "lead investigator" instead. (Closing fix expected at promotion time.) -- **Lint code numbering** (`MQ001`/`MQ002`/`MS001`/`MS002`/`ML001`) — illustrative; verify against [`05-internals/06-lint.md`](../../brief/05-internals/06-lint.md) reservation table at promotion time. Adjacent reserved codes (`SD001` per the bare-command-as-render discipline; `VR001` per the vocabulary-registration requirement; `MG001`-`MG004` per itd-37) should not collide. -- **Recursive ingest** — does `/abcd:memory ingest` accept a directory (recursive ingest of all files) or only one source per call? Operational decision, not architectural. Lean: one source per call (avoids accidental "ingest the whole filesystem" mistake); directory-walk via `--recursive` flag is a candidate if friction is real. -- **Cumulative coverage state location** — `.abcd/memory/.coverage_index.json` (per-source cumulative coverage) is its own JSON registry rebuilt by full crawl on demand. Drift between the index and source-of-truth pages IS the lint signal. Verify location matches existing dotfile conventions in `.abcd/memory/`. +_None open; the four this record carried were operational and are answered by what shipped (the persona quote's role stands as written; the lint codes are the ones the package carries; ingest takes one source per call; the coverage index is rebuilt on demand)._ ## Audit Notes -_Empty. Populated by `intent-fidelity-reviewer` Role 1 (single-document fidelity per the itd-1 discipline) when this intent moves to `shipped/`._ + +Fidelity review OWED (receipt rcp-f3f5495f519e). ## References @@ -120,3 +131,7 @@ _Empty. Populated by `intent-fidelity-reviewer` Role 1 (single-document fidelity - [`itd-26-loot-oss-vendor.md`](../drafts/itd-26-loot-oss-vendor.md) — sibling intent; consumes the same provenance/licence substrate this intent ships. [karpathy-llm-wiki]: https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f "Karpathy LLM Wiki gist (April 2026)" + +## Grounds + +- pursued: the record is being closed for work v0.1.0 carried, so that the store's state matches what ships and the release cut stops carrying a planned intent whose code is on main; shown wrong if the delivered verbs are found not to meet the criteria this record keeps diff --git a/.abcd/development/specs/closed/spc-2609211905174684-memory-unification.md b/.abcd/development/specs/closed/spc-2609211905174684-memory-unification.md new file mode 100644 index 000000000..cbd0dbd00 --- /dev/null +++ b/.abcd/development/specs/closed/spc-2609211905174684-memory-unification.md @@ -0,0 +1,45 @@ +--- +id: spc-2609211905174684 +slug: memory-unification +intent: itd-36 +origin: researcher-authored +production_mode: hand-written +--- +# memory-unification + +## Summary + +The design record for itd-36 as delivered: `/abcd:memory` with `ingest`, +`ask` and `lint` over the per-project store at `.abcd/memory/`, shipped in +v0.1.0 (`internal/core/memory`, `commands/memory.md`). Written on +2026-09-21 to close a record that shipped without one. + +## Scope, as delivered + +1. **`memory ingest [--keep-original]`**: reads a source, + distils it into typed pages with `source.class`, citation and licence, + discards the original by default and stores it under `sources/` by hash + with the flag; the URL fetch masks its origin in every failure message. +2. **`memory ask `**: answers from the store with citations by + class, citation and source hash; term-safe over an empty question. +3. **`memory lint`**: MQ001 (per-page quotation span), MQ002 (cumulative + coverage per source, refusing further quotation), MQ003, MS001 (advisory: + single-class synthesis), MS002 (cross-class synthesis without a weighting + note blocks), ML001 (undeclared licence blocks; `unknown` is explicit). +4. **The bare render**: store presence, last ingest, contradictions and + per-source headroom. +5. **Legacy pages**: pre-existing flat-named pages are not renamed; the + index is generated over them and they read as `session_memory`. + +## Out of scope, captured as issues on 2026-09-21 + +- The dredge synthesiser's output landing as `dredge_synthesis` pages + (itd-25 is a draft). +- One registry entry shared with the code-vendoring path (itd-26 is a draft). +- The lifeboat's restrictive-licence gate refusing to surface a kept + original. + +## How the criteria are satisfied + +Criteria 1, 2, 4 to 9 and 13 by scope 1 to 5 above as shipped; criteria 3, +10, 11 and 12 are the out-of-scope items, each an issue in the ledger (iss-2609211905340006, iss-2609211905346507, iss-2609211905347458). diff --git a/.abcd/work/issues/open/iss-2609211905340006-dredge-synthesis-output-lands-in-the-memory-store-as-its-own-source-class.md b/.abcd/work/issues/open/iss-2609211905340006-dredge-synthesis-output-lands-in-the-memory-store-as-its-own-source-class.md new file mode 100644 index 000000000..43c15ea04 --- /dev/null +++ b/.abcd/work/issues/open/iss-2609211905340006-dredge-synthesis-output-lands-in-the-memory-store-as-its-own-source-class.md @@ -0,0 +1,14 @@ +--- +schema_version: 1 +id: "iss-2609211905340006" +slug: "dredge-synthesis-output-lands-in-the-memory-store-as-its-own-source-class" +severity: "minor" +category: "future-work-seed" +source: "agent-finding" +found_during: "product thinker interview closing itd-36 as delivered, 2026-09-21" +origin: researcher-authored +production_mode: hand-written +found_at: "internal/core/memory; itd-25 (dredge, draft)" +--- + +Dredge synthesis output lands in the memory store as its own source class. itd-36 (closed as delivered on 2026-09-21) asked that the dredge synthesiser (itd-25, still a draft) write its synthesised entries to .abcd/memory/__.md with source.class dredge_synthesis and the per-run provenance the lint reads; dredge does not exist yet, so the memory store has no such class and the lint has no rule for it. Wanted, when itd-25 is planned: the class in the closed enum, the writer in the dredge path, and MS001/MS002 reading it as a cross-class input. diff --git a/.abcd/work/issues/open/iss-2609211905346507-one-registry-entry-for-a-source-ingested-as-documentation-and-vendored-as-code.md b/.abcd/work/issues/open/iss-2609211905346507-one-registry-entry-for-a-source-ingested-as-documentation-and-vendored-as-code.md new file mode 100644 index 000000000..dd652c251 --- /dev/null +++ b/.abcd/work/issues/open/iss-2609211905346507-one-registry-entry-for-a-source-ingested-as-documentation-and-vendored-as-code.md @@ -0,0 +1,14 @@ +--- +schema_version: 1 +id: "iss-2609211905346507" +slug: "one-registry-entry-for-a-source-ingested-as-documentation-and-vendored-as-code" +severity: "minor" +category: "future-work-seed" +source: "agent-finding" +found_during: "product thinker interview closing itd-36 as delivered, 2026-09-21" +origin: researcher-authored +production_mode: hand-written +found_at: "internal/core/memory/provenance.go; itd-26 (loot, draft)" +--- + +One registry entry for a source ingested as documentation and vendored as code. itd-36 (closed as delivered on 2026-09-21) asked that the same source content ingested by memory ingest and by the code-vendoring path (itd-26, loot, still a draft) share one provenance registry entry with an ingest count of two; the vendoring path does not exist, so the registry has one writer and no count. Wanted, when itd-26 is planned: the registry keyed by source hash across both paths, the count, and one licence declaration read by both. diff --git a/.abcd/work/issues/open/iss-2609211905347458-the-lifeboat-s-restrictive-licence-gate-does-not-read-a-kept-memory-original.md b/.abcd/work/issues/open/iss-2609211905347458-the-lifeboat-s-restrictive-licence-gate-does-not-read-a-kept-memory-original.md new file mode 100644 index 000000000..dcfcc15b4 --- /dev/null +++ b/.abcd/work/issues/open/iss-2609211905347458-the-lifeboat-s-restrictive-licence-gate-does-not-read-a-kept-memory-original.md @@ -0,0 +1,14 @@ +--- +schema_version: 1 +id: "iss-2609211905347458" +slug: "the-lifeboat-s-restrictive-licence-gate-does-not-read-a-kept-memory-original" +severity: "minor" +category: "future-work-seed" +source: "agent-finding" +found_during: "product thinker interview closing itd-36 as delivered, 2026-09-21" +origin: researcher-authored +production_mode: hand-written +found_at: "internal/core/lifeboat (disembark gates); .abcd/memory/sources/" +--- + +The lifeboat restrictive-licence gate does not read a kept memory original. itd-36 (closed as delivered on 2026-09-21) asked that disembark refuse to surface .abcd/memory/sources/. (an original kept with --keep-original) unless the launch allowlist names it, and refuse a gated payload carrying a GPL-3.0 citation when the project publishes as MIT; the memory pages carry source.licence today, and disembark packs the record families by path without reading that field. Wanted: the disembark gate reads source.licence on memory pages and the kept originals, refuses a restrictive licence against the project licence, and names the allowlist that admits one. diff --git a/.abcd/work/issues/resolved/iss-12-memory-shipped-vs-planned.md b/.abcd/work/issues/resolved/iss-12-memory-shipped-vs-planned.md index 893657aff..1ae1076ce 100644 --- a/.abcd/work/issues/resolved/iss-12-memory-shipped-vs-planned.md +++ b/.abcd/work/issues/resolved/iss-12-memory-shipped-vs-planned.md @@ -7,7 +7,7 @@ impact: internal category: "inconsistency" source: "review-followup" found_during: "roadmap-consistency-review" -found_at: ".abcd/development/intents/planned/itd-36-memory-unification.md" +found_at: ".abcd/development/intents/shipped/itd-36-memory-unification.md" resolution: "Memory docs no longer assert shipped state: spc-38/spc-39 references demoted from delivery claims to spec attribution, 07-memory header states itd-36 is planned/ and defers delivery state to the intent lifecycle, backed by the new brief-README provenance note." --- diff --git a/.abcd/work/issues/resolved/iss-23-itd-36-adr-28-reconcile.md b/.abcd/work/issues/resolved/iss-23-itd-36-adr-28-reconcile.md index 9dfa288f0..d904ee384 100644 --- a/.abcd/work/issues/resolved/iss-23-itd-36-adr-28-reconcile.md +++ b/.abcd/work/issues/resolved/iss-23-itd-36-adr-28-reconcile.md @@ -7,7 +7,7 @@ impact: internal category: "inconsistency" source: "agent-finding" found_during: "intent-dependency-sweep" -found_at: ".abcd/development/intents/planned/itd-36-memory-unification.md" +found_at: ".abcd/development/intents/shipped/itd-36-memory-unification.md" resolution: "Body reconciled with adr-28 ahead of spec planning: every launch-gate / '/abcd:launch refuses' reference (Why This Matters, both scope bullets, two GWT criteria, the mixed-licence test scenario) now names the gate's real consumer — the lifeboat restrictive-licence gate run by /abcd:disembark, with .abcd/launch-allowlist.json re-including files into the gate's own evaluation input only. The read-every-X-as-Y banner shrank to a pure framing pointer since the body no longer needs translation." --- From 3e0bf9122927e409843a210d7bc560c8f5fa5bcb Mon Sep 17 00:00:00 2001 From: REPPL <77722411+REPPL@users.noreply.github.com> Date: Mon, 21 Sep 2026 20:14:16 +0100 Subject: [PATCH 07/19] docs(intent): draft the record-families map, with the phase question it must answer Assisted-by: Claude:claude-opus-5 --- .../brief/06-delivery/03-out-of-scope.md | 1 + ...ary-maps-abcd-s-record-families-and-how.md | 57 +++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 .abcd/development/intents/drafts/itd-2609211913453478-one-page-in-the-glossary-maps-abcd-s-record-families-and-how.md diff --git a/.abcd/development/brief/06-delivery/03-out-of-scope.md b/.abcd/development/brief/06-delivery/03-out-of-scope.md index 185fa1c6a..01663b81a 100644 --- a/.abcd/development/brief/06-delivery/03-out-of-scope.md +++ b/.abcd/development/brief/06-delivery/03-out-of-scope.md @@ -126,6 +126,7 @@ gate. That is what keeps "not hand-counted" true after the day it was written. - `itd-2609180517121254` — every payload a host hands back from a delegated step names the model that produced it and the number of agents that ran, and the ingesting verb refuses one that does not - `itd-2609201916056194` — a delegated agent runs through a command-line model runner the operator chose (claude CLI, opencode/openrouter); the opt-in cli oracle rung - `itd-2609211116005482` — `abcd build next` picks the readiest planned intent itself, writes on the record why and what would show the pick wrong, and hands it to the implement machinery; one by default, all by flag +- `itd-2609211913453478` — one glossary page maps the record families (intent, spec, bundle, phase, batch, issue, roadmap, release) and how they relate, and answers whether a phase is still the sequencing layer **Later-phase items with no intent id.** These four were written into the brief diff --git a/.abcd/development/intents/drafts/itd-2609211913453478-one-page-in-the-glossary-maps-abcd-s-record-families-and-how.md b/.abcd/development/intents/drafts/itd-2609211913453478-one-page-in-the-glossary-maps-abcd-s-record-families-and-how.md new file mode 100644 index 000000000..a1c7849fd --- /dev/null +++ b/.abcd/development/intents/drafts/itd-2609211913453478-one-page-in-the-glossary-maps-abcd-s-record-families-and-how.md @@ -0,0 +1,57 @@ +--- +id: itd-2609211913453478 +slug: one-page-in-the-glossary-maps-abcd-s-record-families-and-how +spec_id: null +kind: standalone +suggested_kind: null +reclassification_history: [] +builds_on: [itd-34, itd-78] +related_intents: [itd-24, itd-42, itd-172] +severity: minor +impact: additive +origin: researcher-authored +production_mode: hand-written +--- + +# One page maps the record families and how they relate, and says whether a phase still is one + +## Press Release + +> One page in the glossary maps abcd's record families and how they relate: intent, spec, bundle, phase, batch, issue, roadmap and release each get one definition and one line saying what they group, what groups them, and which verb moves them. A product thinker reads it in five minutes and knows which word to use; bundle and batch gain entries; and the page answers whether a phase is still the sequencing layer now that bundles group intents that ship together and a run works in batches. + +## Why This Matters + +On 2026-09-21 the product thinker asked, mid-interview, whether abcd has an intent that sorts out its own vocabulary (intents, issues, phases, bundles, roadmap, specs) and how they relate, and whether phases are still wanted now that bundles exist. The answer was: a glossary exists (`.abcd/development/brief/glossary/`, with phase, intent, spec, roadmap, record and ledger defined in prose and adr-9 making the phase the product layer between the brief and the intent), but nothing draws the map, `bundle` has no entry, and the autonomous run adds a third grouping, the batch. Three ways of grouping intents is one too many for a vocabulary a product thinker is meant to hold; the evidence that phases have thinned is that no spec carries a phase anchor and phase membership is recorded editorially in the phase document. + +## Mechanism + +> _Prompted (the claim-recording gradient): why the authors expect this to work, as a falsifiable "we expect X because Y" — not the outcome restated. Replace this line with the claim, or with the exact token `None stated.` alone on its line to record the claim as considered and declined._ + +## Scope Conditions + +> _Required (the claim-recording gradient): the population, platform, scale, or assumptions this claim holds under, one per top-level bullet — `abcd intent plan` stamps each with a persistent identity. Replace this line with those bullets, or with the exact token `None stated.` alone on its line._ + +## What's In Scope + +- **One page**, `glossary/core/record-families.md` or its equivalent, with one row per family: the noun, one definition, what it groups, what groups it, its lifecycle folders, and the verb that moves it; the page is the single source the other entries point at. +- **Two new entries**: `bundle` (intents sharing one spec because they ship as one change; itd-34) and `batch` (the order an autonomous run takes lanes in; the run file). +- **The phase question, answered on the page**: whether a phase remains the sequencing layer, is folded into bundles, or is replaced by the run's batches; the answer is a decision recorded before the page ships, and the retrospective intent (itd-24) and the bundle rule in itd-34 follow it. +- **The lint**: every glossary entry's `not_to_be_confused_with` names a family on the page; a family named in a record's frontmatter that the page does not define is a finding. + +## What's Out of Scope + +- Renaming any family or any folder. +- The dependency graph between intents (itd-78). + +## Acceptance Criteria + +> _Required (the itd-1 discipline): add at least one Given-When-Then bullet describing the verifiable bar for "shipped" before this draft can be planned._ + +## Open Questions + +- **Do phases stay?** Kept as the sequencing layer ending in a milestone; folded into bundles (a bundle is the only grouping, and the roadmap orders bundles); or replaced by the run's batches (the run file's routing is the roadmap). Each answer changes itd-24 and itd-34. +- **Where the page lives**: one glossary page, or the brief's mental-model chapter with the glossary pointing at it. + +## Audit Notes + +_Empty. Populated by intent-auditor when intent moves to shipped/._ From 71e64548a797f9abb7381285b1bb6983a4771d50 Mon Sep 17 00:00:00 2001 From: REPPL <77722411+REPPL@users.noreply.github.com> Date: Mon, 21 Sep 2026 20:18:55 +0100 Subject: [PATCH 08/19] =?UTF-8?q?docs(intent):=20plan=20itd-42=20=E2=80=94?= =?UTF-8?q?=20the=20coherence=20pre-pass=20before=20the=20planning=20inter?= =?UTF-8?q?view?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Assisted-by: Claude:claude-opus-5 --- .../planned/itd-42-coherence-aware-grill.md | 41 +++++++----- ...-2609211918551301-coherence-aware-grill.md | 62 +++++++++++++++++++ 2 files changed, 88 insertions(+), 15 deletions(-) create mode 100644 .abcd/development/specs/open/spc-2609211918551301-coherence-aware-grill.md diff --git a/.abcd/development/intents/planned/itd-42-coherence-aware-grill.md b/.abcd/development/intents/planned/itd-42-coherence-aware-grill.md index 45a7798f5..0c58b94bb 100644 --- a/.abcd/development/intents/planned/itd-42-coherence-aware-grill.md +++ b/.abcd/development/intents/planned/itd-42-coherence-aware-grill.md @@ -1,7 +1,7 @@ --- id: itd-42 slug: coherence-aware-grill -spec_id: null +spec_id: spc-2609211918551301 kind: standalone suggested_kind: standalone reclassification_history: [] @@ -21,10 +21,14 @@ warrants_assumed: blocked_by: [itd-27] builds_on: [itd-41] severity: major +impact: additive --- # Grill Reads an Intent Against the Brief and Its Siblings, Not Just the Glossary +> **Re-scoped on 2026-09-21** by the product thinker: this record is the automated pre-pass the decomposition discipline (itd-84) names as its next rung. Before the planning interview, abcd reads the brief's invariants, the principles and a one-line index of every intent, and writes the coherence questions into the planning brief the interview starts from. The grill it first named is superseded (itd-27); the press release and scope below are read through this paragraph and the Decisions section. + + ## Press Release > **abcd's grill stops checking an intent in isolation: a full grill now reads it against the brief's invariants, its scope boundary, and every other intent — and asks the coherence questions a solo interrogation cannot.** Capturing an idea stays one line and zero friction. But when a product thinker promotes a draft, the grill loads more than the terminology glossary: it loads the brief's invariants and scope sections, and a one-line index of every other intent — drafted, planned, and shipped. Now it can ask the question that actually catches wrong code: "Invariant 3 says config is never written outside `~/.abcd/` — your intent implies it is; which gives?" and "itd-19 already covers stage-aware behaviour — how is this different?" It still grills vague terms and hidden assumptions; it now also grills *incoherence* — the intent that is locally clear and globally wrong. Grilling against the corpus is grounded the way the phase negotiator is grounded: a coherence concern that cannot be tied to a named invariant, scope clause, or sibling intent is asked as a Socratic question, never asserted as a conflict. @@ -66,30 +70,33 @@ The brief is already structured for selective loading — numbered sections, inv - **Grilling against shipped *code*** — Tier 3 reads shipped *intents*, not the implementation. Delivered-reality comparison remains `intent-fidelity-reviewer`'s job at the shipped transition. - **A new sub-verb or command** — this is a capability of the existing `/abcd:intent grill`, not a sibling verb. +## Mechanism + +We expect a pre-pass that reads the invariants and the sibling index to catch the contradiction or the duplicate before a spec exists, because both are visible from the record alone and the interview today finds them only when the person happens to remember; shown wrong if planned intents still turn out to duplicate or contradict one another after it ships. + ## Scope Conditions None stated. ## Acceptance Criteria -> _BDD format, per the itd-1 discipline._ +- **Given** a draft intent, **when** the pre-pass runs, **then** the planning brief it writes names every brief invariant the draft's text implies a conflict with, quoting the invariant's line and the draft's. +- **Given** a draft that overlaps an existing intent on any shelf, **when** the pre-pass runs, **then** the brief names the sibling from a one-line index of every intent, writes the question with the four answers (keep both, bundle, supersede, refine), and, where it has one, its recommendation with the reason in the prose beside the question and never as a marked option. +- **Given** the pre-pass has run, **when** the tree is inspected, **then** the draft, the brief and the sibling intents are unchanged; the pre-pass read the invariants, the principles, the index and the draft, and wrote only the planning brief under the local tier. +- **Given** a planning brief with questions, **when** the interview runs, **then** each question is asked, and the answer lands on the record as a decision or a typed link. +- **Given** a concern the pre-pass cannot anchor to a named invariant or record, **when** it writes the brief, **then** the concern is a question marked unanchored, not a finding. -- **Given** an intent in `drafts/`, **when** the product thinker runs a light grill on it, **then** the grill loads at most the glossary tier and does not load brief or sibling context — capture-stage grilling stays cheap. -- **Given** an intent being promoted out of `drafts/`, **when** the full grill runs, **then** it loads the glossary tier, the named brief invariant/scope/surface slices, the `principles/` set, and the one-line sibling-intent index. -- **Given** an intent whose body implies behaviour that a `02-constraints/03-invariants.md` invariant forbids, **when** the full grill runs, **then** it surfaces the conflict and cites the specific invariant; a conflict surfaced without such a citation is a defect. -- **Given** an intent that overlaps a sibling intent, **when** the full grill runs, **then** it names the sibling intent ID and asks the product thinker to state the difference as a Socratic question — sibling overlap is never asserted as fact, because a draft sibling is a mutable anchor. -- **Given** the product thinker answers a surfaced overlap question, **when** the session ends, **then** the answer — the stated difference, or a kill/merge decision — is captured in the `grill-report` against that question, so the claimed distinction is on record. -- **Given** a coherence concern the grill cannot anchor to a named invariant or scope clause, **when** it surfaces that concern, **then** it is phrased as a Socratic question tagged with a named move — never as an asserted conflict. -- **Given** a full grill has run, **when** the `grill-report.json` is written, **then** coherence questions and any grounded conflicts appear in it alongside the existing question stream, each grounded conflict carrying its invariant or scope-clause anchor reference. -- **Given** the grill has surfaced a coherence conflict, **when** the session ends, **then** the intent, the brief, and the sibling intents are unchanged on disk — the grill's coherence output is advisory. +## Decisions -## Open Questions +Ruled by the product thinker on 2026-09-21, in the interview that gave this intent its spec: -> _Tier-selection surface and the Tier 3 index mechanism were resolved during the grill (2026-05-16): tier set is lifecycle-derived with `--light`/`--full` override; the sibling index is built fresh each grill, not a maintained file. Brief-slice degradation is resolved in scope (skip-and-warn). The questions below remain genuine plan-time decisions._ +1. **The record is the pre-pass**, run before the interview and writing into the planning brief; the interview stays the human's. +2. **Overlaps are asked with the four standard answers**, and the pre-pass may recommend one with its reason in the prose beside the question, never as a marked option (the GRILL rule). +3. **The loader is the interview's own** (the planning-brief writer the intent page describes), not a module shared with the phase negotiator or the fidelity reviewer; the context is the invariants, the principles, the index and the draft, and nothing else, which is the budget. -- Does coherence grilling share a context-loading module with itd-41's phase negotiator and itd-31's cross-document fidelity reviewer, or keep its own loader until the three demonstrably converge? -- Should a surfaced sibling-overlap question, once the thinker answers it, be allowed to *recommend* reclassification (bundle-member) or supersession, or strictly surface-and-record? itd-27's grill already touches reclassification-adjacent territory. -- Token budget — at 40+ intents the one-line index is small, but the brief slices plus glossary plus intent body must still fit. Is there a point where Tier 2/3 must itself become selective (the itd-39 boundary)? +## Open Questions + +_None open; decisions 2 and 3 settle the three this record carried._ ## Audit Notes @@ -101,3 +108,7 @@ _Empty. Populated by intent-fidelity-reviewer when intent moves to shipped/._ - Shares the grounded-adversary pattern with: [itd-41](../drafts/itd-41-phase-negotiator.md) (phase negotiator) — Socratic where it questions, grounded where it asserts. - Defers to: [itd-39](../drafts/itd-39-scope-aware-memory-retrieval.md) (scope-aware memory retrieval) — full-body cross-intent comparison at scale is itd-39's problem, not this intent's. - Coordinates with: [itd-48](itd-48-intent-fidelity-reviewer-roles-2-3.md) (cross-document fidelity reviewer — supersedes [itd-31](../superseded/itd-31-cross-document-fidelity-reviewer.md)) — different register: itd-48's Role 2 reviews delivered documents for drift; this grills an intent for coherence before it is planned. + +## Grounds + +- pursued: the autonomous run may prepare interviews but not perform them, and the planning brief it writes is only worth reading if this pass fed it; we expect the first briefs to carry a conflict or an overlap the person had not seen; shown wrong if the briefs raise nothing the person did not already know diff --git a/.abcd/development/specs/open/spc-2609211918551301-coherence-aware-grill.md b/.abcd/development/specs/open/spc-2609211918551301-coherence-aware-grill.md new file mode 100644 index 000000000..079541c72 --- /dev/null +++ b/.abcd/development/specs/open/spc-2609211918551301-coherence-aware-grill.md @@ -0,0 +1,62 @@ +--- +id: spc-2609211918551301 +slug: coherence-aware-grill +intent: itd-42 +origin: researcher-authored +production_mode: hand-written +--- +# coherence-aware-grill + +## Summary + +The design record for itd-42 as re-scoped on 2026-09-21: the automated +pre-pass before the planning interview (itd-84's next rung). It reads the +brief's invariants, the principles and a one-line index of every intent, and +writes the coherence questions into the planning brief. + +## Scope + +1. **`abcd intent prepass `** (CLI) and the same step at the top of + the plugin page's interview: reads `.abcd/development/brief/02-constraints/ + 03-invariants.md`, the principles directory, the draft, and an index the + verb builds from every intent's id, title and shelf (criteria 1 to 3). +2. **Invariant conflicts**: a host-delegated judgement (adr-25) over the + draft against each invariant, each finding quoting both lines; the binary + assembles the input and validates the output shape, the host judges + (criterion 1). +3. **Overlaps**: the same judgement over the draft against the index, + naming siblings; each becomes a question with the four answers and an + optional recommendation-with-reason in prose (criterion 2, decision 2). +4. **The planning brief**: written to + `.abcd/.work.local/scratch/planning-briefs/.md` in the shape the + intent page describes (summary-back, decomposition table, questions, + blocks-planning flags); nothing else is written (criterion 3). +5. **The interview reads it**: the plugin page's interview opens from the + brief, asks each question, and records the answer as a decision or a + typed link on the record (criterion 4). +6. **Unanchored concerns** are written as questions marked unanchored + (criterion 5). + +## Out of scope + +- Grading into the calibration note (the human's, on confirming the routing). +- The capture-time validator (itd-84's later rung). +- Any write to the draft, the brief or a sibling. + +## Approach + +`internal/core/intent/prepass.go`: the index builder, the input assembler +(invariants, principles, draft), the brief writer; the judgement is a host +pass with a validated JSON return, the pattern the intent audit and the +cold reading already use. The plugin page calls the verb, hands the host the +input, and writes the brief from the validated return. + +## How the criteria are satisfied + +| Criterion | Where | +| --- | --- | +| 1 invariant conflicts quoted | scope 1, 2 | +| 2 overlaps as four-answer questions, recommendation in prose | scope 3 | +| 3 reads the four inputs, writes the brief only | scope 1, 4 | +| 4 the interview asks and records | scope 5 | +| 5 unanchored concerns marked | scope 6 | From 808327e68a976962e192f6453d12f8c09d217ec4 Mon Sep 17 00:00:00 2001 From: REPPL <77722411+REPPL@users.noreply.github.com> Date: Mon, 21 Sep 2026 20:21:27 +0100 Subject: [PATCH 09/19] =?UTF-8?q?docs(intent):=20plan=20itd-48=20=E2=80=94?= =?UTF-8?q?=20the=20corpus=20consistency=20pass,=20the=20shape=20role=20go?= =?UTF-8?q?ing=20to=20the=20kinds=20lint?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Assisted-by: Claude:claude-opus-5 --- ...d-48-intent-fidelity-reviewer-roles-2-3.md | 47 +++++++++-------- ...2106-intent-fidelity-reviewer-roles-2-3.md | 52 +++++++++++++++++++ 2 files changed, 77 insertions(+), 22 deletions(-) create mode 100644 .abcd/development/specs/open/spc-2609211921272106-intent-fidelity-reviewer-roles-2-3.md diff --git a/.abcd/development/intents/planned/itd-48-intent-fidelity-reviewer-roles-2-3.md b/.abcd/development/intents/planned/itd-48-intent-fidelity-reviewer-roles-2-3.md index 5660b7630..ee0f38b18 100644 --- a/.abcd/development/intents/planned/itd-48-intent-fidelity-reviewer-roles-2-3.md +++ b/.abcd/development/intents/planned/itd-48-intent-fidelity-reviewer-roles-2-3.md @@ -1,7 +1,7 @@ --- id: itd-48 slug: intent-fidelity-reviewer-roles-2-3 -spec_id: null +spec_id: spc-2609211921272106 kind: standalone suggested_kind: bundle-member reclassification_history: @@ -11,10 +11,14 @@ related_adrs: [] routed_from: ["spc-33:A1", "spc-33:A2", "spc-33:A3", "spc-33:A4", "spc-33:G1"] builds_on: [itd-34, itd-5] severity: major +impact: additive --- # `intent-fidelity-reviewer` Gains Its Cross-Doc And Kind-Classification Roles +> **Re-scoped on 2026-09-21** by the product thinker: the consistency pass only. The shape role goes to the kinds lint (itd-34) and the overlap question to the pre-pass (itd-42); the headless oracle leg this record named no longer exists. The press release and scope below are read through this paragraph and the Decisions section. + + ## Press Release > **abcd's `intent-fidelity-reviewer` agent grows from one `role` to three.** `Role 1` (per-intent fidelity) grades a shipped intent's acceptance criteria against delivered reality and writes `MET`/`MET_WITH_CONCERNS`/`NOT_MET`/`INCONCLUSIVE` verdicts back into the intent's `## Audit Notes`. This intent ships `Role 2` (cross-document consistency — surfaces terminology drift, premise contradictions, scope leakage, sequencing impossibilities, naming conflicts across the brief + intents corpus) and `Role 3` (kind classification — examines whether intents' declared `kind` still fits the corpus and surfaces suggested reclassifications). With all three roles live, `/abcd:intent consistency` and `/abcd:intent shape` move from documented command surface to working command surface. The reviewer becomes the corpus's continuous fidelity auditor. @@ -125,32 +129,27 @@ The intent is project-agnostic: every abcd project that uses the intent corpus b None stated. +## Mechanism + +We expect a whole-corpus read to find contradictions no single-record review can, because terminology drift, a premise that two records state differently and a scope that leaked are visible only with both ends in view; shown wrong if a pass over the current corpus finds nothing the ledger did not already hold. + ## Acceptance Criteria -- *Given* the agent file with Roles 2 and 3 sections added, *when* `lint_prompts.py` runs, *then* `prompt_version` is bumped, the CHANGELOG carries the bump entry, and at least one injection canary per role exists in `agents/intent-fidelity-reviewer/fixtures/`. -- *Given* a facilitator runs `/abcd:intent consistency` (bare), *when* the corpus contains a known seeded drift (terminology, premise, scope, sequencing, or naming), *then* the command writes a structured report to `.abcd/logbook/audit/consistency-/report.{json,md}` whose findings name the judgement category, the conflicting documents, and the drift kind. -- *Given* a facilitator runs `/abcd:intent consistency itd-N`, *when* the named intent contradicts another corpus document, *then* the persisted report identifies both ends of the contradiction. -- *Given* a facilitator runs `/abcd:intent shape` (bare), *when* an intent in the corpus has drifted from its declared `kind` (e.g., a `standalone` that has become bundle-shaped), *then* the command writes `.abcd/logbook/audit/shape-/report.{json,md}` with a suggestion naming the reclassification target. -- *Given* a facilitator runs `/abcd:intent shape itd-N`, *when* the named intent's kind still fits, *then* a `KIND_OK` scoped verdict is emitted in the persisted report. -- *Given* a Ralph session runs the consistency or shape verb in headless mode, *when* the call reaches `_build_cli_oracle()`, *then* the Codex leg is used (per itd-47) and the command completes with a real verdict. -- *Given* itd-48 is the standalone intent owning Roles 2 and 3, *when* it is planned, *then* the planned spec ships only the on-demand verbs (no pre-commit hook installation) and records pre-commit scheduling for both roles as deferred follow-ups. +- **Given** `abcd intent consistency` runs bare, **when** it completes, **then** a dated report exists under the reviews shelf listing each contradiction found across the brief and every intent (terminology, premise, scope, sequencing, naming), with both ends quoted and located, and the commit it read named. +- **Given** the report's findings, **when** the pass files them, **then** each is an issue naming both ends with the report as its evidence, and a finding the ledger already holds is linked to the existing record rather than filed twice. +- **Given** `abcd intent consistency `, **when** it runs, **then** the pass is scoped to that intent against the corpus and the report says so. +- **Given** the pass has run, **when** the tree is inspected, **then** the brief and the intents are unchanged; the binary assembled the input and validated the return, and the judgement rode the host. + +## Decisions + +Ruled by the product thinker on 2026-09-21, in the interview that gave this intent its spec: + +1. **The consistency pass only.** The shape role is the kinds lint in itd-34; the overlap question is the pre-pass in itd-42. +2. **A report, and a capture per finding**, deduplicated against the ledger. ## Open Questions -- **Standalone vs. two standalones.** Plan time resolved this in favour of - one standalone intent whose scope covers both roles: the shared agent - file, shared `prompt_version` family, shared injection-canary discipline, - and shared oracle infrastructure all argue against splitting. A future - spec could split the prompt sections without splitting the intent if the - roles diverge. -- **Pre-commit follow-up shape.** A follow-up intent will define when and - how `/abcd:intent consistency` and `/abcd:intent shape` run in - pre-commit (every intent-touching commit, every kind-frontmatter-touching - commit, or only at state transitions). Out of scope for this intent. -- **Mechanical Role 2 categories.** Schema/state contradictions, reference - rot, and acknowledgement gaps are deferred to a separate intent that - owns the mechanical (lint-driven) half of cross-doc fidelity. spc-29 - ships only the judgement half. +_None open; the standalone-versus-two question this record carried is moot with one role left._ ## Routed Deferrals (spc-33) @@ -199,3 +198,7 @@ scope captured here — NOT active spc-33 work: rows this intent makes real. - **a dated working-log entry (2026-05-16)** — the gap entry that motivated this intent. + +## Grounds + +- pursued: the autonomous run builds forty-eight intents against this corpus, and a contradiction between two of them is a stop condition it cannot resolve; we expect the first whole-corpus pass to find contradictions the ledger does not hold; shown wrong if it finds none diff --git a/.abcd/development/specs/open/spc-2609211921272106-intent-fidelity-reviewer-roles-2-3.md b/.abcd/development/specs/open/spc-2609211921272106-intent-fidelity-reviewer-roles-2-3.md new file mode 100644 index 000000000..f6a2e128e --- /dev/null +++ b/.abcd/development/specs/open/spc-2609211921272106-intent-fidelity-reviewer-roles-2-3.md @@ -0,0 +1,52 @@ +--- +id: spc-2609211921272106 +slug: intent-fidelity-reviewer-roles-2-3 +intent: itd-48 +origin: researcher-authored +production_mode: hand-written +--- +# intent-fidelity-reviewer-roles-2-3 + +## Summary + +The design record for itd-48 as re-scoped on 2026-09-21: one on-demand +consistency pass over the brief and every intent, producing a dated report +and a capture per finding. + +## Scope + +1. **`abcd intent consistency []`**: assembles the input (the brief's + chapters, every intent's press release, scope and decisions, the glossary + entries), hands it to the host with the five drift classes named, and + validates the returned findings (class, both ends quoted with paths, + severity) before anything is written (criteria 1, 3, 4). +2. **The report**: `.abcd/work/reviews/-consistency[-]/ + 00-summary.md` with `review_of_commit` (itd-28's pin) and one row per + finding (criterion 1). +3. **The captures**: one `capture` per finding (category inconsistency, + source agent-finding, found-during naming the report), after a ledger + search for an open record naming either end; a hit links the report to it + instead (criterion 2). +4. **Read-only over the record**: no write outside the report and the ledger + (criterion 4). + +## Out of scope + +- The shape role (itd-34's lint) and the overlap question (itd-42). +- A pre-commit hook or a scheduled run; it is on demand. + +## Approach + +`internal/core/intent/consistency.go` assembles and validates; the host pass +follows the intent-audit request/ingest shape (a request file, a validated +JSON return); the report writer reuses the reviews-charter template; the +captures go through `capture`'s core with the dedup search over open records. + +## How the criteria are satisfied + +| Criterion | Where | +| --- | --- | +| 1 dated report, both ends quoted | scope 1, 2 | +| 2 capture per finding, deduplicated | scope 3 | +| 3 scoped run | scope 1 | +| 4 read-only, host-judged | scope 1, 4 | From 7c851c85e5ed98f5266249620ecc30e25655eaef Mon Sep 17 00:00:00 2001 From: REPPL <77722411+REPPL@users.noreply.github.com> Date: Mon, 21 Sep 2026 20:24:34 +0100 Subject: [PATCH 10/19] =?UTF-8?q?docs(intent):=20plan=20itd-50=20=E2=80=94?= =?UTF-8?q?=20the=20audit-driven=20fix=20round=20as=20the=20last=20stage?= =?UTF-8?q?=20of=20build?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Assisted-by: Claude:claude-opus-5 --- .../planned/itd-50-loop-toward-acceptance.md | 42 ++++++++----- ...2609211924346308-loop-toward-acceptance.md | 59 +++++++++++++++++++ 2 files changed, 87 insertions(+), 14 deletions(-) create mode 100644 .abcd/development/specs/open/spc-2609211924346308-loop-toward-acceptance.md diff --git a/.abcd/development/intents/planned/itd-50-loop-toward-acceptance.md b/.abcd/development/intents/planned/itd-50-loop-toward-acceptance.md index 2eb69732a..485bc2476 100644 --- a/.abcd/development/intents/planned/itd-50-loop-toward-acceptance.md +++ b/.abcd/development/intents/planned/itd-50-loop-toward-acceptance.md @@ -1,7 +1,7 @@ --- id: itd-50 slug: loop-toward-acceptance -spec_id: null +spec_id: spc-2609211924346308 kind: standalone suggested_kind: standalone reclassification_history: [] @@ -12,10 +12,14 @@ grilled_at: 2026-06-02 blocked_by: [itd-53] builds_on: [itd-44, itd-43] severity: major +impact: additive --- # The Audit Loop Drives An Intent To Acceptance — Or Calls For A Replan +> **Re-scoped on 2026-09-21** by the product thinker: the loop is the last stage of `abcd build` (itd-2609201916151817), not a per-intent mode. After the fidelity audit, a not-met verdict starts a fix round with a fresh implementer, bounded by the pace rule's fix-round count; exhaustion hands the intent back as unachievable, reopened to drafts with the reason. The press release and scope below are read through this paragraph and the Decisions section. + + ## Press Release > **abcd's fidelity audit stops being a report card and becomes a loop the facilitator can drive toward acceptance.** Today, when a shipped intent's delivered reality fails a criterion, the `intent-fidelity-reviewer` records a `NOT_MET` verdict and the voyage moves on — the divergence is logged, but nothing closes it. With this change, the facilitator elects, per intent, whether that intent should *loop toward acceptance*: a `NOT_MET` verdict re-opens the work and iterates against the same acceptance criteria until they read `MET`, bounded by a budget so the loop can never grind forever. When an intent genuinely *cannot* be met as written, the loop doesn't thrash — it terminates with an explicit `UNACHIEVABLE` verdict that summons the product thinker and facilitator to sit together and replan the intent. And only once the machine-checkable criteria all read `MET` is the product thinker invited to manually verify the intention — so a human is never asked to hand-test something the audit already knows is broken. @@ -65,17 +69,17 @@ This intent is **project-agnostic**: every abcd project ships intents whose deli None stated. +## Mechanism + +We expect a bounded fix round after the audit to turn most not-met verdicts into met without a person, because a not-met criterion names exactly what to change and a fresh implementer with that criterion is the shape the pilot's fix rounds already proved; shown wrong if the loop's fix rounds mostly end unachievable. + ## Acceptance Criteria -- *Given* an intent carries `audit_mode: loop-to-acceptance` in its frontmatter (set at plan time; portable with the intent), *when* a fidelity review returns `NOT_MET` for a criterion, *then* the linked work is re-opened and re-reviewed against the same criteria, and the cycle repeats until all criteria read `MET` or the iteration budget is exhausted. -- *Given* an intent in `loop-to-acceptance` whose iteration budget is exhausted (or whose criteria are judged unmeetable as written), *when* the loop terminates, *then* the intent-level Family-2 rollup becomes `UNACHIEVABLE`, the loop **stops** (never auto-continues), the intent is **marked with a written explanation of why it is unachievable**, and a replan invitation is recorded naming both the product thinker and facilitator — with no automatic rollback of delivered reality and no machine-authored replan. -- *Given* an intent whose machine-checkable criteria all read `MET`, *when* the product thinker is invited to verify, *then* a manual-verification step is offered and its sign-off is recorded as a verification receipt distinct from the machine verdict of record. -- *Given* an intent whose machine-checkable criteria all read `MET` **but** the product thinker judges the criteria themselves were wrong (the why is not delivered despite every criterion passing), *when* manual verification is rejected, *then* the intent routes to the **replan** path (revise the intent's criteria), **not** a synthetic `NOT_MET` that would re-loop the implementation against criteria that already pass. -- *Given* an intent whose machine-checkable criteria do **not** all read `MET`, *when* the workflow reaches the manual-verification point, *then* the product thinker is **not** asked to verify — the loop (or the replan invitation) runs first. -- *Given* a fidelity review returns `INCONCLUSIVE` (the fail-closed result of a malformed or unreachable reviewer), *when* the loop processes it, *then* it is recorded as today — `INCONCLUSIVE` does **not** summon the product thinker and does **not** itself trigger replan (it is a "could not run the audit" signal, not a "the intent is impossible" signal). -- *Given* an intent left at the default `audit_mode: record-only`, *when* a fidelity review returns `NOT_MET`, *then* behaviour is unchanged from today — the verdict is recorded to `## Audit Notes` and no re-work is triggered. -- *Given* an intent reaches `UNACHIEVABLE` (loop exit) or its manual verification is rejected (wrong-criteria replan), *when* the product thinker takes it up, *then* they use the `/abcd:intent grill` skill to think the replan through, and the recorded `why-unachievable` / rejection justification seeds that grill session. -- *Given* the on-close lifecycle hook (`intent_lifecycle`), *when* any of these modes is active, *then* the hook remains a pure data function (no subprocess, no oracle dispatch) — the mode logic lives in the drainer/policy layer. +- **Given** a `build` lane whose fidelity audit returns not-met on any criterion, **when** the verdict is ingested, **then** a fix round starts with a fresh implementer briefed on those criteria, and the audit re-runs after it. +- **Given** the pace rule's fix-round count is exhausted with a criterion still not met, or the auditor judges a criterion unmeetable as written, **when** the loop reaches that point, **then** the lane stops with the verdict unachievable and starts nothing further. +- **Given** an unachievable verdict, **when** the loop hands back, **then** the intent is moved to `drafts/` carrying `replan_reason` and its audit notes, the spec stays open, and the run's summary lists it for a replan. +- **Given** every machine-checkable criterion reads met, **when** the lane reaches its landing, **then** the product thinker is offered a hand verification and the answer is recorded as a grounds entry on the intent in their words; a rejection of the criteria themselves reopens the intent as above. +- **Given** an inconclusive audit (a malformed or unreachable reviewer), **when** the loop processes it, **then** no fix round starts, nothing counts against the budget, and the run names the inconclusive audit in its summary. ## Resolved (grill 2026-06-02) @@ -87,12 +91,18 @@ The 2026-06-02 grill (5 questions across Dialectic / Definition / Counterfactual - **`UNACHIEVABLE` always stops and summons the product thinker**, with a written `why-unachievable` explanation; no machine auto-replan (the product thinker owns the why). The product thinker uses `/abcd:intent grill` to think the replan through, seeded by that explanation. - **`INCONCLUSIVE` stays fail-closed only — no summons, no replan.** It is the result of a malformed/unreachable reviewer (a backend signal), not a "the evidence is contradictory" signal, so it cannot be trusted as a human-summons trigger. +## Decisions + +Ruled by the product thinker on 2026-09-21, in the interview that gave this intent its spec: + +1. **The loop is `build`'s last stage**, not a per-intent mode; every intent the run ships goes through it. +2. **An iteration is a fix round** (fresh implementer plus re-audit), bounded by the pace rule's count; exhaustion, or a criterion judged unmeetable, is unachievable. +3. **Unachievable reopens the intent to drafts** with the reason and its audit notes. +4. **Hand verification is a grounds entry** in the product thinker's words, not a separate receipt. + ## Open Questions -- **The loop budget for `loop-to-acceptance`.** What consumes an iteration (a full re-review? a re-open + re-implement + re-review cycle?), and what the default budget is. Mirror `MAX_REVIEW_ITERATIONS` or set an intent-grain equivalent. -- **How the replan invitation surfaces.** Re-open the intent to `drafts/` with a `replan_reason`? A dedicated replan queue/surface the facilitator drains? What state the original delivered reality is left in. (Both replan entry points — `UNACHIEVABLE` and wrong-criteria rejection — share this surface.) -- **How manual-verification sign-off is recorded.** A verification receipt schema, distinct from the machine verdict of record, with an explicit `rejected` state that carries the wrong-criteria justification into the seeded grill. -- **Iteration autonomy bound.** `loop-to-acceptance` iterates unattended up to budget; the precise rule for when a budget-exhausted loop flips to `UNACHIEVABLE` vs. is judged unmeetable earlier. +_None open; decisions 2 to 4 settle the four this record carried._ ## Related @@ -124,3 +134,7 @@ In the predecessor implementation each acceptance criterion above is satisfied a | on-close hook stays a pure data function (no subprocess / oracle) | Satisfied | The mode logic rides the spc-43 drainer / policy layer; `intent_lifecycle` is untouched by the loop | **Open questions (predecessor answers, to re-adjudicate at spec time):** loop budget = one re-open+re-review cycle per iteration, default `3` (spc-52.1 § Decision context); replan surface = no `drafts/` move, a `why-unachievable` + replan block in `## Audit Notes` with the intent kept in `shipped/` (spc-52.2 R4); manual-verification sign-off = the receipt schema `{intent_id, machine_rollup, state, justification?, recorded_by_role, ts}` with the `rejected_wrong_criteria` state carrying the justification to the shared replan surface (spc-52.3 R5). + +## Grounds + +- pursued: the run audits every intent it ships and today a not-met verdict is a note nobody acts on; we expect the bounded fix round to close most of them without a person; shown wrong if most fix rounds end unachievable diff --git a/.abcd/development/specs/open/spc-2609211924346308-loop-toward-acceptance.md b/.abcd/development/specs/open/spc-2609211924346308-loop-toward-acceptance.md new file mode 100644 index 000000000..d10ffa9e4 --- /dev/null +++ b/.abcd/development/specs/open/spc-2609211924346308-loop-toward-acceptance.md @@ -0,0 +1,59 @@ +--- +id: spc-2609211924346308 +slug: loop-toward-acceptance +intent: itd-50 +origin: researcher-authored +production_mode: hand-written +--- +# loop-toward-acceptance + +## Summary + +The design record for itd-50 as re-scoped on 2026-09-21: the audit-driven +fix round as the last stage of `abcd build`, bounded by the pace rule, +handing an unachievable intent back to drafts. + +## Scope + +1. **The stage** in the implement loop's state file: after `intent audit + ingest`, a not-met criterion sets the lane to `fix-round` with the + criteria named; the loop renders the fix brief from them and starts a + fresh implementer through the same runner path as any lane agent + (criterion 1). +2. **The bound**: the pace configuration's fix-round count (itd-2609201925079472) + read per lane; the state file counts rounds; exhaustion, or an auditor + verdict of unmeetable-as-written, sets `unachievable` (criterion 2). +3. **The hand-back**: the intent is moved `planned/ → drafts/` under the + intent store's lock with `replan_reason: ` written and the audit + notes kept; the spec stays open; the run record and the summary list it + (criterion 3). +4. **The hand verification**: when every checkable criterion reads met, the + loop's step interface returns a `verify` step naming the intent; the + host asks the product thinker one question; the answer is written with + `intent ready --grounds ": "`; declined + reopens as in 3 (criterion 4). +5. **Inconclusive**: no fix round, no count, one line in the summary + (criterion 5). + +## Out of scope + +- A per-intent `audit_mode`; the loop applies to every lane. +- A verification receipt schema; the grounds entry is the record. + +## Approach + +Three additions to the implement spec's state machine (`fix-round`, +`unachievable`, `verify`), the fix brief renderer beside the lane brief +renderer, and the hand-back write in `internal/core/intent` (a bucket move +the reclassify verb of itd-34 can also make). The auditor's request gains an +"unmeetable as written" verdict value the ingest validates. + +## How the criteria are satisfied + +| Criterion | Where | +| --- | --- | +| 1 fix round after not-met, re-audit | scope 1 | +| 2 bounded; unachievable | scope 2 | +| 3 reopened to drafts with the reason | scope 3 | +| 4 hand verification as a grounds entry | scope 4 | +| 5 inconclusive counts for nothing | scope 5 | From 9ea56b9dde03b2993d39cd05c20889b606cee5eb Mon Sep 17 00:00:00 2001 From: REPPL <77722411+REPPL@users.noreply.github.com> Date: Mon, 21 Sep 2026 20:30:05 +0100 Subject: [PATCH 11/19] =?UTF-8?q?docs(intent):=20plan=20itd-53=20=E2=80=94?= =?UTF-8?q?=20one=20bounded=20command=20pays=20the=20owed=20audits?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Assisted-by: Claude:claude-opus-5 --- ...3-review-queue-auto-drain-fidelity-gate.md | 36 +++++++++---- ...6-review-queue-auto-drain-fidelity-gate.md | 50 +++++++++++++++++++ 2 files changed, 75 insertions(+), 11 deletions(-) create mode 100644 .abcd/development/specs/open/spc-2609211930059886-review-queue-auto-drain-fidelity-gate.md diff --git a/.abcd/development/intents/planned/itd-53-review-queue-auto-drain-fidelity-gate.md b/.abcd/development/intents/planned/itd-53-review-queue-auto-drain-fidelity-gate.md index b43133355..97307b1dd 100644 --- a/.abcd/development/intents/planned/itd-53-review-queue-auto-drain-fidelity-gate.md +++ b/.abcd/development/intents/planned/itd-53-review-queue-auto-drain-fidelity-gate.md @@ -1,7 +1,7 @@ --- id: itd-53 slug: review-queue-auto-drain-fidelity-gate -spec_id: null +spec_id: spc-2609211930059886 kind: standalone suggested_kind: standalone reclassification_history: [] @@ -9,10 +9,14 @@ related_adrs: [adr-16] routed_from: ["spc-33:I-D2"] prd_path: null severity: major +impact: additive --- # A Shipped Intent No Longer Drifts Out Of Audit Just Because Nobody Ran The Review +> **Re-scoped on 2026-09-21** by the product thinker: one bounded command that pays the backlog, `abcd intent audit --owed`, run once by the autonomous run's first batch. The standing list is itd-2609150819445595 and the inline audit of every new lane is `abcd build`'s (itd-2609201916151817, itd-50); the boundary-hooked autodrain and the blocking gate this record first described are dropped. The press release and scope below are read through this paragraph and the Decisions section. + + ## Press Release > **abcd closes the audit back-edge: when a specced block of work ships, its owed fidelity review actually gets run at a safe moment, and a standing gate surfaces any shipped intent whose review is missing or unmet — without ever blocking the autonomous loop.** Today abcd does the honest half: closing a spec moves its intent to shipped and enqueues a fidelity-review entry. But the review itself only runs when someone manually invokes it, so the queue can quietly accumulate owed reviews that nobody drains, and a shipped intent can sit with its acceptance never machine-checked. This intent adds an opt-in drainer that runs queued reviews at a safe boundary (after a loop, at a session edge, in a pre-commit or CI step — never inside the pure close hook), leaving entries deferred rather than failed when no review backend is reachable, plus a consistency gate that lists shipped intents whose latest review is absent or not-met. Enforcement, not just bookkeeping — and loop purity preserved. @@ -43,22 +47,28 @@ The fix is not to make the close hook run the review — that would break loop p None stated. +## Mechanism + +We expect the backlog of owed audits to clear once paying it is one bounded command, because the debt accrued only while each audit was a hand-run request and ingest; shown wrong if the owed count is unchanged a month after it ships. + ## Acceptance Criteria -> _Given-When-Then per the itd-1 discipline._ +- **Given** `abcd intent audit --owed [--max ]`, **when** it runs, **then** it lists the owed audits oldest first and runs each as the host pass a single-intent audit uses, ingesting each verdict; the cap stops it and the summary names how many remain. +- **Given** no reviewer is reachable, **when** it runs, **then** every entry is left owed, not failed, and the summary says why nothing ran. +- **Given** a verdict, **when** it is ingested, **then** it lands exactly as a single audit's does (audit notes, receipt, scope-condition dispositions), and a not-met verdict on a long-shipped intent is captured, not fixed. +- **Given** a spec closes, **when** the close hook runs, **then** it still only enqueues; nothing starts a reviewer from it. -- **Given** `review.autodrain` is enabled, **when** a safe boundary is reached and a review backend is reachable, **then** pending fidelity-review queue entries are run and their verdicts recorded. -- **Given** no review backend is reachable, **when** the drainer runs, **then** entries are left `deferred` (not failed) and nothing blocks. -- **Given** the close hook, **when** a spec closes, **then** it still only enqueues — no subprocess or oracle dispatch is added to it (loop purity preserved). -- **Given** the consistency gate, **when** it runs, **then** it lists every shipped intent whose latest fidelity review is absent or not-met. -- **Given** `review.autodrain` is off (default), **when** specs close, **then** behavior is unchanged from today (enqueue-only, manual review). +## Decisions + +Ruled by the product thinker on 2026-09-21, in the interview that gave this intent its spec: + +1. **One bounded command for the backlog**, run once by the autonomous run's batch 0; no boundary-hooked autodrain. +2. **The gate reports and never blocks**; the report is itd-2609150819445595's listing. +3. **Cost is bounded by `--max`** and by the host pass running one audit at a time. ## Open Questions -- Which safe boundary is the primary drain point — a post-turn hook, a session-edge step, a pre-commit/CI step, or several, configurably? -- Does the gate merely report, or can it be wired to block a commit / a phase transition when a shipped intent is unaudited or not-met? (Report first; blocking is a policy decision.) -- How does the drainer bound its own cost (number of reviews per drain, token budget) so a large backlog does not stall the boundary it runs at? -- Interaction with itd-50 (loop-toward-acceptance): does the drainer just run reviews, with itd-50's policy deciding what a not-met verdict triggers, or does the drainer need hooks for that policy from the outset? +_None open; decisions 1 to 3 settle the three this record carried._ ## Audit Notes @@ -75,3 +85,7 @@ _Empty. Populated by intent-fidelity-reviewer when intent moves to shipped/._ NO; add a drainer instead). - Touches: the pure on-close lifecycle hook (spc-28) and the review-queue drain/claim machinery; the fidelity reviewer (spc-12) is the run target. + +## Grounds + +- pursued: the run's first batch audits every shipped-but-open intent and has no verb to run the audits with; we expect the owed count to fall to zero in that batch and stay near it once build audits inline; shown wrong if the owed count is unchanged a month after it ships diff --git a/.abcd/development/specs/open/spc-2609211930059886-review-queue-auto-drain-fidelity-gate.md b/.abcd/development/specs/open/spc-2609211930059886-review-queue-auto-drain-fidelity-gate.md new file mode 100644 index 000000000..b10db0cb9 --- /dev/null +++ b/.abcd/development/specs/open/spc-2609211930059886-review-queue-auto-drain-fidelity-gate.md @@ -0,0 +1,50 @@ +--- +id: spc-2609211930059886 +slug: review-queue-auto-drain-fidelity-gate +intent: itd-53 +origin: researcher-authored +production_mode: hand-written +--- +# review-queue-auto-drain-fidelity-gate + +## Summary + +The design record for itd-53 as re-scoped on 2026-09-21: `abcd intent audit +--owed`, one bounded command that runs the owed fidelity audits oldest +first through the host pass a single audit uses. + +## Scope + +1. **The listing** comes from itd-2609150819445595's owed-intents read + (receipt ids per shipped intent); `--owed` orders it oldest first and + applies `--max ` (criterion 1). +2. **Each audit**: `intent audit ` writes the request; the plugin + page hands it to the auditor agent one at a time; `intent audit ingest` + applies the verdict; the loop continues with the next (criteria 1, 3). +3. **No reviewer**: the page detects no auditor available (the host's agent + listing, or a refused launch) and the command leaves every entry owed + with the reason in its summary (criterion 2). +4. **Not-met on a long-shipped intent** is captured through `capture` with + the receipt named, never fixed by this command (criterion 3). +5. **The close hook** is untouched (criterion 4). + +## Out of scope + +- A boundary-hooked autodrain, a blocking gate, a scheduled run. +- Fixing anything: the audit-driven fix round is itd-50's, inside `build`. + +## Approach + +A thin loop in the plugin page over the existing request/ingest pair, with +the ordering and the cap computed by `internal/core/intent` from the owed +list; the CLI form prints the ordered list and the next request path, so a +host without the page can drive it by hand. + +## How the criteria are satisfied + +| Criterion | Where | +| --- | --- | +| 1 oldest first, capped, ingested | scope 1, 2 | +| 2 left owed when no reviewer | scope 3 | +| 3 lands as a single audit; not-met captured | scope 2, 4 | +| 4 close hook enqueue-only | scope 5 | From 5ac9a7a94b5029ac0fe99110300f4154cf16fb94 Mon Sep 17 00:00:00 2001 From: REPPL <77722411+REPPL@users.noreply.github.com> Date: Mon, 21 Sep 2026 20:37:44 +0100 Subject: [PATCH 12/19] =?UTF-8?q?docs(intent):=20fold=20itd-58=20into=20th?= =?UTF-8?q?e=20build=20machinery=20=E2=80=94=20only=20the=20loop=20writes?= =?UTF-8?q?=20a=20verdict?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Assisted-by: Claude:claude-opus-5 --- ...akes-a-single-intent-from-ready-to-delivered-witho.md | 4 +++- .../itd-58-session-reviewer-verdict-ingestion.md | 4 ++++ ...akes-a-single-intent-from-ready-to-delivered-witho.md | 9 +++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) rename .abcd/development/intents/{planned => superseded}/itd-58-session-reviewer-verdict-ingestion.md (93%) diff --git a/.abcd/development/intents/planned/itd-2609201916151817-one-verb-takes-a-single-intent-from-ready-to-delivered-witho.md b/.abcd/development/intents/planned/itd-2609201916151817-one-verb-takes-a-single-intent-from-ready-to-delivered-witho.md index 42835475e..87e863d4e 100644 --- a/.abcd/development/intents/planned/itd-2609201916151817-one-verb-takes-a-single-intent-from-ready-to-delivered-witho.md +++ b/.abcd/development/intents/planned/itd-2609201916151817-one-verb-takes-a-single-intent-from-ready-to-delivered-witho.md @@ -6,7 +6,7 @@ kind: standalone suggested_kind: null reclassification_history: [] builds_on: [itd-2609201916056194, itd-2609091014076309, itd-2609091416295622] -supersedes: [itd-29] +supersedes: [itd-29, itd-58] related_intents: [itd-29, itd-50, itd-2, itd-2609170822093401] severity: major impact: additive @@ -71,6 +71,7 @@ Asked and answered on 2026-09-20: Ruled by the product thinker on 2026-09-21, in the interview that filed `itd-2609211116005482` (`abcd build next`) and revived `itd-82` (`abcd drain`): 8. **`build` for people, `implement` for the machinery.** `abcd build ` is what a person types and is the verb this record's press release names; `abcd build next` and `abcd drain` are the two customised runs that hand over to the same loop. `abcd implement` is that loop, with the step-level words a driving host calls renamed from `next` to `step` (`implement step` returns the brief, `implement receipt ` advances) so that `next` is free to mean the pick. Which verbs the command list shows a person and which it shows an agent is its own record (`iss-2609211119023345`). +9. **Only the loop writes a verdict** (itd-58 folded in). A validator's verdict is recorded by the loop from the validator's own return, into the state file, before the advance is decided; a lane has no write to it, and a receipt carrying a verdict the loop did not record is refused at the advance, naming the receipt. ## Open Questions @@ -88,6 +89,7 @@ _None open; decisions 5 to 7 settle the interview's questions._ - **Given** a host with no configured runner, **when** `abcd implement step` returns a brief, **then** the host is told which agent to start and where the receipt goes, and the loop advances only on `abcd implement receipt`. - **Given** a configured runner and the process driver opted in, **when** the loop reaches a lane, **then** it starts the lane through the runner itself, and the run record names the runner. - **Given** a completed run, **when** the run record is read, **then** it names every lane, receipt, reviewer verdict, the model each runner reported, and the transcripts captured into the history store. +- **Given** a validator has returned, **when** the loop records its verdict, **then** the verdict in the state file is the one the loop parsed from the validator's return, and a lane report carrying a verdict the loop did not record is refused at the advance, naming the report; a real SHIP recorded by the loop lets the advance proceed. - **Given** any refusal, **when** it is rendered, **then** it names the step, the reason and the remedy, in text and in `--json`. ## Typed Links diff --git a/.abcd/development/intents/planned/itd-58-session-reviewer-verdict-ingestion.md b/.abcd/development/intents/superseded/itd-58-session-reviewer-verdict-ingestion.md similarity index 93% rename from .abcd/development/intents/planned/itd-58-session-reviewer-verdict-ingestion.md rename to .abcd/development/intents/superseded/itd-58-session-reviewer-verdict-ingestion.md index 36fc60f57..7966b92d2 100644 --- a/.abcd/development/intents/planned/itd-58-session-reviewer-verdict-ingestion.md +++ b/.abcd/development/intents/superseded/itd-58-session-reviewer-verdict-ingestion.md @@ -1,5 +1,6 @@ --- id: itd-58 +superseded_by: itd-2609201916151817 slug: session-reviewer-verdict-ingestion spec_id: null kind: standalone @@ -12,6 +13,9 @@ severity: major # A Real Reviewer's SHIP Verdict Reaches The Session Gate Through A Channel The Worker Cannot Forge +> **Superseded by itd-2609201916151817** on 2026-09-21, on the product thinker's ruling: the unforgeable verdict is an invariant of the build machinery, not a record of its own. That intent's decision 9 and its last criterion carry it: only the loop writes a verdict, from the validator's own return, and a lane report carrying one is refused at the advance. + + ## Press Release > **abcd's autonomous-run enforcement learns to ingest a live reviewer's verdict through a trusted production path — so a genuine SHIP advances the work, while a worker's self-written SHIP still cannot.** The pluggable autonomous seam closes the A4 *exploit*: a worker that writes its own `"verdict":"SHIP"` receipt is denied at the advance gate, because no trusted verdict was ever recorded. But that is only the negative half. The positive half — a real reviewer (any oracle adapter) returning SHIP, parsed into a `TrustedVerdict`, and recorded so the legitimate advance proceeds — needs a production path: recording a trusted verdict is a seam-owned operation, and something in the live run must parse reviewer output and invoke it. This intent builds that ingestion path and proves it end-to-end, so the trusted-verdict channel is a full round-trip, not a one-sided denial. diff --git a/.abcd/development/specs/open/spc-2609202134338445-one-verb-takes-a-single-intent-from-ready-to-delivered-witho.md b/.abcd/development/specs/open/spc-2609202134338445-one-verb-takes-a-single-intent-from-ready-to-delivered-witho.md index 5de089c47..f0bb49d6f 100644 --- a/.abcd/development/specs/open/spc-2609202134338445-one-verb-takes-a-single-intent-from-ready-to-delivered-witho.md +++ b/.abcd/development/specs/open/spc-2609202134338445-one-verb-takes-a-single-intent-from-ready-to-delivered-witho.md @@ -84,3 +84,12 @@ and calls `receipt`, so the loop is proven without any model. piece 9; 7 by pieces 1 and 2; 8 by piece 2; 9 by piece 3; 10 by piece 10; 11 by the refusal shape every piece shares. +## Invariant folded in on 2026-09-21 (itd-58) + +Only the loop writes a verdict. The validator stage records each validator's +verdict into the state file from the validator's own return, before the +advance is decided; the lane's receipt and report carry no verdict field the +loop reads, and a report that carries one is refused at the advance naming +it. The end-to-end test enters through the loop's step interface, has a +fake validator return SHIP, and asserts the advance; a second run has the +lane write a SHIP into its report and asserts the refusal. From f11e8ce7dea15c5b9b27c9b59ac3ff9601d54f88 Mon Sep 17 00:00:00 2001 From: REPPL <77722411+REPPL@users.noreply.github.com> Date: Mon, 21 Sep 2026 20:50:43 +0100 Subject: [PATCH 13/19] =?UTF-8?q?docs(intent):=20plan=20itd-6=20=E2=80=94?= =?UTF-8?q?=20RepoPrompt=20over=20MCP=20as=20one=20opt-in=20reviewer=20rou?= =?UTF-8?q?te?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Assisted-by: Claude:claude-opus-5 --- .../planned/itd-6-rp-mcp-only-integration.md | 40 ++++++++----- ...609211950427074-rp-mcp-only-integration.md | 58 +++++++++++++++++++ 2 files changed, 85 insertions(+), 13 deletions(-) create mode 100644 .abcd/development/specs/open/spc-2609211950427074-rp-mcp-only-integration.md diff --git a/.abcd/development/intents/planned/itd-6-rp-mcp-only-integration.md b/.abcd/development/intents/planned/itd-6-rp-mcp-only-integration.md index 186043d92..b4b112a90 100644 --- a/.abcd/development/intents/planned/itd-6-rp-mcp-only-integration.md +++ b/.abcd/development/intents/planned/itd-6-rp-mcp-only-integration.md @@ -1,17 +1,21 @@ --- id: itd-6 slug: rp-mcp-only-integration -spec_id: null +spec_id: spc-2609211950427074 kind: standalone suggested_kind: null reclassification_history: [] builds_on: [itd-2] severity: minor +impact: additive --- > **⚠️ Framing superseded by [ADR-25](../../decisions/adrs/0025-host-delegated-llm-default.md)** (host-delegated LLM is the default; RepoPrompt is one optional oracle adapter among many, not abcd's single integration — see also [ADR-22](../../decisions/adrs/0022-bundled-deps-as-pluggable-adapters.md)). The intent itself stays live and is scheduled in Phase 0's `## Scope` as the oracle adapter seam: read "abcd's only RP integration is MCP" below as the contract of the *RP adapter*, not of abcd — the RP-specific mechanics (MCP bridge, cascade position, `chat_id` semantics) are adapted to the adapter seam at spec time. -# RP-Only Integration: abcd Talks to RepoPrompt via MCP, Period +# RepoPrompt over MCP is one opt-in reviewer route, beside the host's own agents + +> **Re-filed on 2026-09-21** by the product thinker: not abcd's one integration but one opt-in reviewer adapter. abcd is host-delegated by default; with `oracle.review = rp` configured, a lane's reviews go to RepoPrompt over MCP, and when it is unreachable the host's own agent runs the review and the receipt says so. The three-step cascade, the setup discovery and the non-Mac flow this record first described are dropped; the press release and scope below are read through this paragraph and the Decisions section. itd-7 waits on this record. + ## Press Release @@ -54,23 +58,29 @@ This intent re-frames the brief's RP integration: drop "select RP backend with p None stated. +## Mechanism + +We expect a reviewer route a person has already configured and paid for to be used over one abcd would have to own, because the review is the run's scarcest step and the person's own tool is where their model choices already live; shown wrong if nobody opts in within a release of it shipping. + ## Acceptance Criteria -> _BDD format, per `itd-1-acceptance-gates`. These gates are checked by `intent-fidelity-reviewer` when this intent moves to `shipped/`._ +- **Given** `oracle.review = rp` in the repository's or the machine's abcd configuration, **when** a `build` lane reaches its reviews, **then** the ruthless and security review requests are sent to RepoPrompt over MCP and each returned verdict is recorded by the loop as any validator's is. +- **Given** the adapter is configured and RepoPrompt is unreachable, **when** a review is due, **then** the host's own agent runs it and the receipt states that the review fell back and why; no review is silently skipped. +- **Given** the adapter is not configured, **when** a review runs, **then** nothing differs from today, and abcd never spawns, installs or configures RepoPrompt. +- **Given** the adapter ships, **when** the brief's adapters chapter and the command page are read, **then** the adapter is one entry beside the command-line runner, with the opt-in named. -- **Given** a macOS user with RepoPrompt installed and `oracle.backend = "rp"` (or `"auto"` with RP available), **when** any abcd command invokes the oracle (lifeboat-oracle, press-release-composer, intent-fidelity-reviewer, plan-review, impl-review, prompt SOTA audit), **then** the call goes through `mcp__RepoPrompt__*` tools exclusively — no `claude -p` subprocess spawn, no direct OpenAI / Anthropic / Google API call, and no preset-selection prompt to the user. -- **Given** abcd issues an RP MCP audit call, **when** the call returns, **then** `McpResult.chat_id` is populated AND the audit-fix loop in `oracle.py` threads that `chat_id` back as the `chat_id` argument on the next call — never `--new-chat`, never a fresh `rp builder`. This holds within a single `abcd-cli` invocation across plan-review→fix→re-review, impl-review→fix→re-review, and lifeboat-oracle→fix→re-audit cycles. (Per ADR-02 § 3: "same chat" is scoped to within one `abcd-cli` command invocation; cross-invocation chat continuation requires fresh GUI approval and is not supported for autonomous operation.) -- **Given** an audit-fix iteration produces a verdict change in either direction (NEEDS_WORK→SHIP after fixes; SHIP→NEEDS_WORK after a regression), **when** abcd's `re_audit` runs, **then** both directions are accepted as valid signal — no rejection of downgrades, no special-casing of upgrades. -- **Given** RP MCP is unreachable (RP not running, MCP server config missing, network failure), **when** abcd attempts an oracle call with `oracle.backend = "auto"`, **then** the resolution chain falls through to Codex CLI (if `codex` is on PATH) and then to in-session subagent (per itd-2) — three-step cascade, surfaced in the run log so the user can see which backend served the call. -- **Given** the user runs `/abcd:ahoy` for the first time on a macOS machine with RP installed, **when** ahoy's setup discovery runs, **then** the RP MCP config path is detected (in `~/Library/Application Support/RepoPrompt/MCP/` or the project's `.mcp.json`), recorded in `.abcd/config.json` → `oracle.rp.mcp_config_path`, reachability is tested, and `oracle.backend` is locked to `"rp"` on success or to the next available backend on failure (with a one-time hint about how to enable RP later). -- **Given** the user has configured Claude, Codex, and Gemini as separate model presets inside RP, **when** abcd issues different oracle call types (review, audit, question), **then** abcd makes no preset-selection decision — RP routes to whatever the user has configured for that call type. abcd's logs record only the MCP call shape, never the resolved model. -- **Given** a non-Mac user with Codex CLI but no RP, **when** abcd's resolution chain runs, **then** Codex CLI is selected and the user is never prompted about RP setup; RP-related friction is invisible to non-Mac users. +## Decisions + +Ruled by the product thinker on 2026-09-21, in the interview that gave this intent its spec: + +1. **One opt-in reviewer route**, not the integration; the host stays the default. +2. **Reviews only**, not audits. +3. **Unreachable falls back to the host**, with the receipt saying so. +4. **itd-7 waits** on this record and is not in the run. ## Open Questions -- What does the RP MCP API actually expose for "review this prompt" vs "ask this question" vs "audit this content"? Need to verify which `mcp__RepoPrompt__*` tools cover the abcd oracle use cases (lifeboat-oracle, press-release-composer, intent-fidelity-reviewer, prompt SOTA audit, plan-review, impl-review). _(Open: this is an RP-API-shape sub-question; spc-5 delivered the `MCPBridge` transport but not the per-oracle-call tool mapping.)_ -- How does this interact with itd-22 (OpenCode portability)? OpenCode probably has its own equivalent integration pattern (its own MCP setup, or a different surface entirely). The harness's `mcp_call(server, tool, args)` shim should treat "RP" as one server name; OpenCode's equivalent picks up via its own server config. -- **Standardised review-chat naming — naming affordance sub-question (still Open).** When abcd opens an RP chat for an oracle/review call, the chat should carry a deterministic, identifiable label — e.g. `spc-6: Phase 1 reconciliation` (or `: ` for intent-stage work) — not RP's auto-generated `untitled-chat-`. Field evidence (2026-05-16, spc-6 plan-review): the RepoPrompt MCP `oracle_send` tool exposes **no chat-name parameter** — it always auto-names — and the MCP toolset has no rename op. Naming only worked via `flowctl rp chat-send --chat-name`, a path broken against rp-cli 2.x. itd-6 must still settle: does abcd's RP integration name chats at creation (needs an MCP affordance RP may not currently provide — verify against the RP MCP API), name the *tab* instead (the `builder` path does title tabs from its summary), or rename post-creation? A consistent `: