Development record
Completed Releases Get A Retrospective
Press Release
abcd ships
/abcd:reflectfor release retrospectives. Run/abcd:reflect v0.11.0and abcd walks an interview-driven retrospective: what went well, what could improve, lessons learned, decisions made, metrics. The interview is seeded by what the release shipped — the intents the tag shipped, read the way the release cut reads them, each with the audit notes the intent auditor wrote on it, and the changelog section the cut composed — so the conversation opens from what actually passed and failed. Output is a structured.abcd/development/retrospectives/v0.11.0/README.md, committed as part of the permanent record. Future lifeboats carry the retrospective forward; future intents reference past lessons. Reflection becomes a first-class abcd primitive, not an afterthought."abcd's brief and intents captured what I'd done," said Henry, a junior-developer persona. "Reflect captures what I learned — and because it starts from what the release shipped and how each audit went, it doesn't ask me to re-remember the work, it asks me what the verdicts mean. When I started a new voyage six months later, embark surfaced past retrospectives in the lifeboat unpack — the lessons came with the work. I didn't re-make the mistakes."
Why This Matters
abcd ships strong post-implementation transparency: shipped intents have audit notes (per itd-1 acceptance criteria); the native spec store's completion records capture what was built; and each release cut composes a changelog from the records that shipped in it. What's missing is post-release reflection — the structured "what did we learn" doc that's bigger than per-intent audit notes, bigger than a pass/fail audit verdict, and smaller than a brief rewrite.
The legacy ~/.claude/templates/retrospective.md.template had the right prompt structure (what went well, what could improve, lessons learned, decisions made, metrics) but lived as a manual template that rarely got used. It was deferred (see research/legacy-harvest.md Pass 4 retrospective decision); /abcd:reflect promotes it to a first-class command with structured interview + structured output.
/abcd:reflect is the release-level reflection surface — broader than per-intent audit notes (which the intent auditor already produces on ship per the itd-1 discipline) and narrower than a brief rewrite. It spans the intents a release shipped and captures what's transferable to future voyages. It was first written at the grain of a roadmap phase (adr-9); phases are retired (adr-2609212115255771), and the release is the unit that replaced them (decisions 4 and 5).
An audit and a retrospective are distinct activities. The audit asks did each intent deliver its criteria (a per-criterion verdict). The retrospective asks what did we learn (transferable insight, interview-driven). /abcd:reflect does not replace the audit — it consumes it: the release's audit 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 <release-tag>— retrospective for a cut release, and the command's only argument form. Examples:/abcd:reflect v0.10.0,/abcd:reflect v0.11.1. Per-intent reflection is out of scope (see below) —/abcd:reflectoperates at the release grain only.- Seeded from the release (decision 5). The seed is the intents a tag shipped, read the way the release cut reads them (ruling AD): those that reached
shipped/between the previous release tag and this one, less any whoseshipped_innames another release, plus any whoseshipped_innames this one. For each, its## Audit Notes(per-criterion verdicts, honoured / diverged / missing) and itsimpact; and the changelog section the cut composed. The interview opens from them rather than from a blank prompt. - Audit-missing handling. A shipped intent in the release with no audit notes is named, and the command offers
abcd intent audit <itd-N>for it first; the interview continues either way. - Empty-release refusal. A tag whose release shipped no intent refuses — there is no delivered work to reflect on.
- Interview-driven structure:
- What went well (successes and strengths, with specific examples)
- What could improve (issues and gaps, ranked)
- Lessons learned (transferable insights, framed for future-you)
- Decisions made (architectural / design choices crystallised during the release)
- Metrics (intents shipped, audit-note severity distribution, time-to-ship if measurable)
- Output:
.abcd/development/retrospectives/<release-tag>/README.md— a peer of.abcd/development/intents/, committed as part of the permanent record. - Lifeboat integration:
/abcd:disembark pack <repo> <path>packs all of the voyage's retrospectives into the lifeboat — the full reflection arc travels./abcd:embark from <path>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 release's changelog section, to the intents it shipped, and to their audit notes; the audit notes are referenced, not duplicated.
reflection-composeragent — runs the interview, drafts the structured output, asks clarifying questions when answers feel thin.
What's Out of Scope
- The audit itself — judging delivered reality against each intent's criteria is the intent auditor's job.
/abcd:reflectconsumes those verdicts; it does not produce them. - Per-intent reflection — the intent auditor already produces per-criterion verdicts and a three-bucket prose audit on every shipped intent (per the itd-1 discipline). That is per-intent reflection;
/abcd:reflectdoes not duplicate it. There is no/abcd:reflect <itd-N>form — the command takes a release tag only. - A date or tag range as the seed, and phase documents as the seed: the alternatives decision 5 did not take.
- Quantitative retrospective metrics (DORA, velocity, etc.) — abcd doesn't gather the underlying telemetry. Metrics section is qualitative + simple counts only.
- Team retrospectives — abcd is single-developer-shaped (or pair-shaped); team retrospective patterns belong elsewhere.
- Automatic triggering — reflection requires the persona's deliberate engagement; beyond the one-line nudge of decision 1, nothing prompts for it.
Scope Conditions
None stated.
Acceptance Criteria
- Given an abcd repo with a cut release (
v0.11.0is tagged and at least one intent reachedshipped/in it, as the release cut reads membership under ruling AD), when the persona runs/abcd:reflect v0.11.0, then the reflection-composer agent runs an interview seeded by that release's shipped intents and their audit notes and writes.abcd/development/retrospectives/v0.11.0/README.mdwith all five required sections populated. - Given a release one of whose shipped intents carries no audit notes, when the persona runs
/abcd:reflect <release-tag>, then the command names that intent and offersabcd intent audit <itd-N>before continuing into the retrospective. - Given a release tag that shipped no intent, when the persona runs
/abcd:reflect <release-tag>, then the command refuses with "no intent shipped in<release-tag>— 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 pack <repo> <path>, when the lifeboat is inspected, then every.abcd/development/retrospectives/<release-tag>/README.mdthe voyage produced is included in the lifeboat artefact. - Given a target repo embarked from a lifeboat that includes retrospectives, when
/abcd:embark from <path>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 a release with intents still unshipped whose
target_releasenames it, when/abcd:reflect <release-tag>runs, then the command warns the persona, lists those intents, and asks for confirmation to proceed anyway. - Given a release cut is written, when that cut completes, then abcd says once that a retrospective for the release 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:
- 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.
- A ranked few on embark. Predecessor lessons most like the new voyage's brief are shown; the rest are a list opened on request.
- Layout. The retrospective lives under the durable record tier,
.abcd/development/retrospectives/<phase-id>/README.md; the paths this record was written against predate the three-tier layout and are read as that. - The unit is the release (ruled 2026-09-21, adr-2609212115255771): phases are retired, so
<phase-id>reads as the release tag (v0.10.0), the seed is the release's shipped intents and their audit notes with the derived changelog, the empty case is a release that shipped no intent, the nudge fires once when the cut is written, and criterion 7's warning names intents targeted at the release (target_release) still unshipped. Every criterion below is read with "phase" meaning "release". - Seed from a release (ruled by the product thinker on 2026-09-29, ruling AD of autonomous run A's owed list): a retrospective starts from the intents a tag shipped. Seeding from a date or tag range the person names, and keeping phase documents as the anchor, were the alternatives not taken. The press release, scope and criteria were rewritten to the release on 2026-09-29, so decision 4's reading rule is now the text itself; the Blocking Dependency and v1 notes below record the phase-grain design this replaces.
Open Questions
None open; decisions 1 and 2 settle the two this record carried (the reflection cadence and the lifeboat surfacing on embark).
Blocking Dependency
Superseded by decisions 4 and 5: the seed is the per-intent audit notes, which exist, so no phase-fidelity output is awaited. The text below is the phase-grain history.
/abcd:reflect cannot be planned until the phase-fidelity-reviewer ships and its output artefact is stable and machine-readable. The reviewer is deferred in adr-9. Because /abcd:reflect's core design is to consume the audit's per-bullet verdicts as interview seed material, and the audit-missing AC depends on running the reviewer inline, the command has no buildable contract until the reviewer's output format exists. /abcd:intent plan itd-24 must not proceed while the phase-fidelity-reviewer remains unbuilt.
Satisfied: the stable machine-readable phase-fidelity output is provided by spc-66 (predecessor store) (phase_review_report.schema.json + .abcd/logbook/audit/phase-<ts>/report.{json,md}), so this dependency is met and /abcd:reflect is planned under spc-83. V1 keys empty-phase detection off the spc-66 (predecessor store) receipts (not a phase: anchor) and refuses on a missing/empty-audited receipt rather than offering the inline reviewer — see the ### Implementation notes (spc-83.3 — v1 scope) block below.
Audit Notes
Fidelity review — receipt rcp-2215987d5eb7 (verifier abcd:intent-auditor claude-opus-5-5).
Provenance: abcd:intent-auditor@claude-opus-5-5 · rubric_hash sha256:effa65b3e9e88ff29433b443ec2be159522a8b0b71cf1434526514aa61edb13e · prompt_hash sha256:c908ff4a28ec3e93638b483a19765fd18fca15012986840f45674a7aa7f6e489 Input attestations: repository:4f05055572ada95ccedb28a2c49418f4d5d3b6f5@-; diff:c8ddafcaa508868a0685adf0f0e4fa26bfd82dd5^..63c9969e39aee422aed67be8f6e3d7f9f9356857@-; intent:.abcd/development/intents/shipped/itd-24-reflect-command.md@sha256:43c33152de401e4f8b470678484097aeab694c55c4c789bf208594d8cb6011e8; spec:.abcd/development/specs/closed/spc-2609211751376504-reflect-command.md@sha256:a8834c5bae6bf8e0b54509a2757556e66ba827c144889dc4db1cd918ed575699; request:.abcd/.work.local/reviews/rcp-2215987d5eb7.request.md@sha256:7b36a525f63a5ae7820d4566aba12ba8776448dfb96948a603fc21aa32de0ac0;
Acceptance rollup: MET 4 · MET_WITH_CONCERNS 4 · NOT_MET 0 · INCONCLUSIVE 0
Per-criterion verdicts:
- ac-1 — MET_WITH_CONCERNS: BuildSeed reads the intents the tag shipped the way the cut reads membership, with each one's impact, audit counts and the changelog section. The host page dispatches the reflection-composer with that seed, and the writer renders the four asked sections plus computed metrics; the test asserts all five. Concerns: since the placement of 2026-10-09 the /abcd:reflect page is hidden from the person's menu, so the persona reaches it through an agent. The only real retrospective (v0.12.0) was written by the old audit reader, still carries its miscount, and cannot be regenerated because a second run on a tag refuses.
evidence: internal/core/reflect/seed.go:131 — "func BuildSeed(root, tag string) (Seed, error) {"
evidence: commands/reflect.md:55 — "Dispatch the
reflection-composeragent with the seed." evidence: internal/core/reflect/sections.go:17 — "var AskedSections = []Section{WentWell, CouldImprove, Lessons, Decisions}" evidence: internal/core/reflect/write.go:233 — "sec.Heading(), strings.TrimSpace(ans.Text))" evidence: internal/core/reflect/write.go:241 — "- Intents shipped: %d (%d with audit notes, %d without)" evidence: internal/core/reflect/write_test.go:29 — "func TestWriteProducesTheRetrospectiveWithFiveSections(t *testing.T) {" evidence: commands/reflect.md:6 — "user-invocable: false" evidence: .abcd/development/brief/04-surfaces/09-reflect.md:41 — "hidden from a person's/abcd:menu (the product thinker's placement of" evidence: .abcd/development/retrospectives/v0.12.0/README.md:56 — "- Intents shipped: 11 (11 with audit notes, 0 without)" - ac-2 — MET_WITH_CONCERNS: The prior failure is fixed. The review marker is read first: an OWED review is never audit notes, and a section with no marker counts only if it names criteria with verdicts (HandAudited, the owed listing's own rule). Each unaudited intent is offered 'abcd intent audit < itd-N>', and the host page names each one before the interview. Tests cover an owed review beside an amendment note and a stray note. Concerns: (a) a DEAD_LETTER review's quarantine line is not skipped, so it counts as audit notes, although owed.go calls a dead-lettered review unreviewed; (b) the plain-Terminal 'abcd reflect interview' still names no unaudited intent and offers no audit before the first question; (c) the v0.12.0 record still says 'unaudited: []'.
evidence: internal/core/reflect/audit.go:44 — "case intent.ReviewOwed:"
evidence: internal/core/reflect/audit.go:47 — "it.Audited = intent.HandAudited(text)"
evidence: internal/core/reflect/seed.go:172 — "s.Unaudited = append(s.Unaudited, AuditOffer{IntentID: it.ID, Command: "abcd intent audit " + it.ID})"
evidence: commands/reflect.md:44 — "- Intents without audit notes (
unaudited[]): name each one to the product thinker" evidence: internal/surface/cli/reflect.go:351 — "no audit notes on %d intent(s); offer the audit first, then continue either way:" evidence: internal/core/reflect/seed_owed_test.go:37 — "func TestSeedOffersTheAuditToAnOwedReviewBesideAnAmendmentNote(t *testing.T) {" evidence: internal/core/reflect/seed_owed_test.go:65 — "func TestSeedJudgesAnUnmarkedSectionByTheOwedListingsRule(t *testing.T) {" evidence: internal/core/reflect/audit.go:71 — "strings.HasPrefix(t, "Fidelity review OWED")" evidence: internal/core/reflect/audit.go:99 — "if prose {" evidence: internal/core/intent/audit.go:1877 — ""Fidelity review DEAD_LETTER (receipt %s): %s. Raw payload retained at %s. "+" evidence: internal/core/intent/owed.go:61 — "dead-lettered review is unreviewed but not owed" evidence: internal/surface/cli/reflect.go:205 — "w := &interview.Written{" evidence: internal/core/interview/tasks.go:12 — "(an intent with a NOT_MET verdict, an intent shipped with no audit, an intent that missed the release)" evidence: .abcd/development/retrospectives/v0.12.0/README.md:7 — "unaudited: []" - ac-3 — MET: NothingShippedError's message is the criterion's exact wording. BuildSeed returns it before anything is created, Write rebuilds the seed and so refuses the same way, and the CLI and core tests assert the exact text and that nothing is written.
evidence: internal/core/reflect/reflect.go:67 — "return fmt.Sprintf("no intent shipped in
%s— nothing shipped to reflect on", e.Tag)" evidence: internal/core/reflect/seed.go:158 — "return Seed{}, &NothingShippedError{Tag: tag}" evidence: internal/surface/cli/reflect_cli_test.go:148 — "func TestReflectRefusesAReleaseThatShippedNothing(t *testing.T) {" evidence: internal/surface/cli/reflect_cli_test.go:158 — "no intent shipped inv0.3.0— nothing shipped to reflect on" evidence: internal/core/reflect/write_test.go:140 — "func TestWriteRefusesAReleaseThatShippedNoIntentAndWritesNothing(t *testing.T) {" - ac-4 — MET_WITH_CONCERNS: underFloor marks 'it worked' as thin. Write refuses, writing nothing, until every thin section has a follow-up, and returns that section's question for the reflection-composer to ask. Concerns: the thin original is still written verbatim above the follow-up reply (v0.12.0 'What went well' opens 'How we worked.'), and the reply is not held to the floor. So a thin answer can still be committed after one question, while the agent page says a thin answer is not committed. evidence: internal/core/reflect/thin.go:33 — "func underFloor(s Section, text string) (bool, string) {" evidence: internal/core/reflect/write.go:105 — "if !isThin || strings.TrimSpace(a.FollowUp) != "" {" evidence: internal/surface/cli/reflect_cli_test.go:276 — "func TestReflectWriteMeetsAThinAnswerWithAQuestion(t *testing.T) {" evidence: internal/core/reflect/write.go:234 — "if f := strings.TrimSpace(ans.FollowUp); f != "" {" evidence: internal/core/reflect/write_test.go:109 — "func TestWriteTakesAThinAnswerOnceItsFollowUpIsAnswered(t *testing.T) {" evidence: agents/reflection-composer.md:82 — "A thin answer is not committed." evidence: agents/reflection-composer.md:92 — "if the reply is still thin, say so to the person and let them decide" evidence: .abcd/development/retrospectives/v0.12.0/README.md:31 — "How we worked."
- ac-5 — MET: The lifeboat plan copies every < release-tag>/README.md under the retrospectives store into the lifeboat as a record family sealed by the manifest. The core and CLI tests pack two retrospectives verbatim and write them back on embark. evidence: internal/core/lifeboat/plan.go:288 — "if ctx.IsDir(corereflect.RetrospectivesRelDir) {" evidence: internal/core/lifeboat/plan.go:299 — "pb.copyRecord(ctx, src, path.Join(retrospectivesLifeboatDir, tag, retrospectiveLeaf))" evidence: internal/core/lifeboat/retrospectives_test.go:50 — "func TestPlanPacksEveryRetrospective(t *testing.T) {" evidence: internal/surface/cli/reflect_lifeboat_cli_test.go:45 — "func TestDisembarkPackCarriesEveryRetrospectiveAndEmbarkWritesThemBack(t *testing.T) {" evidence: internal/core/lifeboat/retrospectives_test.go:102 — "func TestEmbarkFromWritesRetrospectivesBack(t *testing.T) {"
- ac-6 — MET_WITH_CONCERNS: Main today: 'embark lessons' verifies the manifest and ranks every lesson by deterministic lexical term overlap (record/match) against the target's framing chapter or a --brief file. It shows the top three, then the rest as a list, with 'which of these apply?', and the embark page has the host ask that one question. This is the term-overlap method the spec names. Concerns: (a) the ranking is a lexical heuristic; the judgement-based ranking through the decision adapter is planned in itd-2609221009495079 and not on main; (b) 'embark from' runs no press-release interview (the matrix marks it staged), so the lessons are a separate step; (c) with no framing chapter and no --brief the lessons come back unranked but are still headed 'most like this voyage'.
evidence: internal/surface/cli/cli.go:1479 — "lessonsCmd := &cobra.Command{"
evidence: internal/surface/cli/cli.go:1515 — "const embarkFramingRel = ".abcd/development/brief/01-product/06-framing.md""
evidence: internal/core/reflect/lessons.go:15 — "const TopLessons = 3"
evidence: internal/core/reflect/lessons.go:100 — "fwd, _, shared := match.Overlap(terms[i], framingTerms, w)"
evidence: internal/core/lifeboat/retrospectives.go:54 — "func PredecessorLessons(lifeboatDir, framing string) (LessonsView, error) {"
evidence: internal/surface/cli/reflect_lifeboat_cli_test.go:77 — "func TestEmbarkLessonsShowsTheFewMostLikeTheBrief(t *testing.T) {"
evidence: commands/embark.md:83 — "Show the product thinker the
topfew (three), each with the release it came from, and" evidence: .abcd/development/specs/closed/spc-2609211751376504-reflect-command.md:60 — "whole;embarkranks the packed retrospectives' lessons against the new" evidence: .abcd/development/intents/planned/itd-2609221009495079-abcd-s-typed-judgements-can-run-through.md:43 — "embark's lesson ranking" evidence: .abcd/development/brief/06-delivery/02-verification-matrix.md:62 — "| Embark press-release interview | (staged)" evidence: commands/embark.md:59 — "fromruns the same planner asprobe, then writes eachcreatefile into the" evidence: internal/core/lifeboat/retrospectives.go:122 — "strings.TrimSpace(framing) == """ evidence: internal/core/lifeboat/retrospectives.go:151 — "most like this voyage — which of these apply?" - ac-7 — MET: The prior failure is fixed. unshippedTargets now lists the planned intents whose target_release names the tag, plus the still-planned intents that the release's own changelog section names in the cut's target-move note. The note's lead is spelled once for its writer and this reader, so targets launch ship rewrote to 'next' before tagging are found again. The CLI prints a WARNING listing them, the host page asks, Write and the plain-Terminal interview refuse without --proceed, and a test cuts a release with moved targets and checks only the still-unshipped one is listed.
evidence: internal/core/reflect/seed.go:200 — "func unshippedTargets(corpus intent.Corpus, tag string, cl ChangelogSection) []TargetedIntent {"
evidence: internal/core/reflect/seed.go:216 — "if it.Bucket == intent.BucketPlanned && it.TargetRelease == tag {"
evidence: internal/core/reflect/seed.go:221 — "if !changelog.IsTargetMoveNote(ln) {"
evidence: internal/core/changelog/targetmove.go:22 — "const targetMoveLead = "Targeted and not shipped in this release, so each targets the next release (
next): "" evidence: internal/surface/cli/reflect.go:357 — "WARNING: %d intent(s) targeted at %s have not shipped; ask before proceeding (reflect write --proceed):" evidence: commands/reflect.md:49 — "(unshipped_targets[]): warn the product thinker, list them, and ask whether to" evidence: internal/core/reflect/write.go:98 — "if len(seed.Unshipped) > 0 && !req.ProceedDespiteUnshipped {" evidence: internal/surface/cli/reflect.go:192 — "if len(seed.Unshipped) > 0 && !proceed {" evidence: internal/core/reflect/seed_owed_test.go:109 — "func TestSeedListsTheTargetsTheCutMovedPastTheRelease(t *testing.T) {" evidence: internal/core/reflect/write_test.go:153 — "func TestWriteAsksBeforeProceedingPastUnshippedTargets(t *testing.T) {" - ac-8 — MET: launch ship sets retrospective_owed to reflect.Nudge(tag) only when the cut is written and prints it as the run's last line. The CLI is the only non-test caller of release.Ingest, and no other non-test surface mentions an owed retrospective. The test asserts one mention, at the end, and none on an emit that writes nothing. evidence: internal/core/reflect/nudge.go:10 — "return fmt.Sprintf("A retrospective for %s is owed: run /abcd:reflect %s when you are ready.", tag, tag)" evidence: internal/surface/cli/ship.go:677 — "res.RetrospectiveOwed = reflect.Nudge(ingested.Cut.NextTag)" evidence: internal/surface/cli/ship.go:48 — "return release.Ingest(repoRoot, current, raw, at)" evidence: internal/surface/cli/reflect_cli_test.go:363 — "func TestLaunchShipSaysOnceThatARetrospectiveIsOwed(t *testing.T) {" evidence: internal/surface/cli/reflect_cli_test.go:371 — "if n := strings.Count(string(out), "retrospective"); n != 1 {"
Gap audit:
- honoured:
- The interview opens from what the release shipped: the intents the tag shipped, read the way the cut reads membership, each with impact and audit counts, plus the changelog section the cut composed. evidence: internal/core/reflect/seed.go:319 — "func shippedBy(root, tag, prev string, corpus intent.Corpus) ([]member, error) {" evidence: internal/core/reflect/seed_test.go:22 — "func TestSeedIsTheIntentsTheTagShipped(t *testing.T) {"
- A shipped intent whose review is owed is named and offered the audit, by the same rule the list of reviews owed uses. evidence: internal/core/reflect/audit.go:44 — "case intent.ReviewOwed:" evidence: internal/core/reflect/seed_owed_test.go:65 — "func TestSeedJudgesAnUnmarkedSectionByTheOwedListingsRule(t *testing.T) {"
- Intents targeted at the release that did not ship are warned about and confirmed past, including those a cut moved to next. evidence: internal/core/reflect/seed.go:221 — "if !changelog.IsTargetMoveNote(ln) {" evidence: internal/core/reflect/seed_owed_test.go:109 — "func TestSeedListsTheTargetsTheCutMovedPastTheRelease(t *testing.T) {"
- The output is a five-section README in the durable record tier that links to the changelog section and each intent's audit notes rather than copying them; metrics are computed, never asked. evidence: internal/core/reflect/write.go:216 — "b.WriteString(" Each intent's audit notes stay on the intent and are linked here, not repeated.\n\n")" evidence: internal/core/reflect/sections.go:17 — "var AskedSections = []Section{WentWell, CouldImprove, Lessons, Decisions}"
- An empty release is refused in the criterion's words, and the release is the only grain (an intent id is refused).
evidence: internal/core/reflect/reflect.go:67 — "return fmt.Sprintf("no intent shipped in
%s— nothing shipped to reflect on", e.Tag)" evidence: internal/surface/cli/reflect.go:271 — ""abcd reflect: %s is an intent; reflect takes a release tag (such as v0.11.0). Per-intent reflection is the intent audit: abcd intent audit %s"," - Future lifeboats carry every retrospective forward, and embark writes them back. evidence: internal/core/lifeboat/plan.go:299 — "pb.copyRecord(ctx, src, path.Join(retrospectivesLifeboatDir, tag, retrospectiveLeaf))" evidence: internal/core/lifeboat/retrospectives_test.go:102 — "func TestEmbarkFromWritesRetrospectivesBack(t *testing.T) {"
- Reflection has a single nudge at the written cut, and nothing repeats it or gates on it. evidence: internal/surface/cli/ship.go:677 — "res.RetrospectiveOwed = reflect.Nudge(ingested.Cut.NextTag)" evidence: internal/surface/cli/reflect_cli_test.go:363 — "func TestLaunchShipSaysOnceThatARetrospectiveIsOwed(t *testing.T) {"
- diverged:
- Clarifying questions for thin answers add to the thin answer instead of replacing it: the thin original is committed beside the follow-up, and the reply is not held to the floor. evidence: internal/core/reflect/write.go:234 — "if f := strings.TrimSpace(ans.FollowUp); f != "" {" evidence: .abcd/development/retrospectives/v0.12.0/README.md:31 — "How we worked."
- Embark surfaces predecessor lessons during the press-release interview: delivered as a separate 'embark lessons' step ranked by lexical term overlap. The interview embark would run is staged, the judgement-based ranking awaits the decision adapter, and unranked lessons are still headed 'most like this voyage'. evidence: .abcd/development/brief/06-delivery/02-verification-matrix.md:62 — "| Embark press-release interview | (staged)" evidence: .abcd/development/intents/planned/itd-2609221009495079-abcd-s-typed-judgements-can-run-through.md:43 — "embark's lesson ranking" evidence: internal/core/lifeboat/retrospectives.go:151 — "most like this voyage — which of these apply?"
- Reflection is a first-class command the persona runs as /abcd:reflect: the page is hidden from the person's menu, while the cut's nudge still tells the person to run /abcd:reflect < tag>. evidence: commands/reflect.md:6 — "user-invocable: false" evidence: internal/core/reflect/nudge.go:10 — "return fmt.Sprintf("A retrospective for %s is owed: run /abcd:reflect %s when you are ready.", tag, tag)"
- Every shipped intent without audit notes is named and offered the audit: a DEAD_LETTER quarantine line is counted as audit notes, and the plain-Terminal interview makes no offer before its first question. evidence: internal/core/reflect/audit.go:71 — "strings.HasPrefix(t, "Fidelity review OWED")" evidence: internal/core/intent/owed.go:61 — "dead-lettered review is unreviewed but not owed" evidence: internal/core/interview/tasks.go:12 — "(an intent with a NOT_MET verdict, an intent shipped with no audit, an intent that missed the release)"
- The one retrospective in the record (v0.12.0) was written under the old audit reader and still overstates its audits; a second run on a tag refuses, so it is not regenerated. evidence: .abcd/development/retrospectives/v0.12.0/README.md:7 — "unaudited: []" evidence: .abcd/development/retrospectives/v0.12.0/README.md:56 — "- Intents shipped: 11 (11 with audit notes, 0 without)"
- missing:
- Future intents reference past lessons: nothing on the intent side reads the retrospective store; lessons are read only by embark's lifeboat view. evidence: internal/core/reflect/lessons.go:28 — "func ReadLessons(readme []byte) []Lesson {" evidence: internal/core/lifeboat/retrospectives.go:107 — "for _, l := range corereflect.ReadLessons(data) {"
Audit owed flag cleared 2026-10-29 (receipt rcp-2215987d5eb7): a re-run of the audit judged no criterion NOT_MET or INCONCLUSIVE, and iss-2610241431221889 is resolved.
- 2026-09-30: the press release, scope item 1 and criterion 1 read release membership the way the release cut reads it, under ruling AD, as spec scope 1 does since its amendment of the same date;
shipped_inmoves a record between releases and does not define membership.
Implementation notes (v1 scope)
Phase-grain history of a thin V1 that is not in the tree; superseded by decision 5, which seeds from a release.
/abcd:reflect (thin V1) refines two acceptance behaviours from
their originally-drafted form; both are recorded here so the fidelity review
reads them as deliberate v1 scope, not gaps:
- Missing-audit inline-reviewer offer → refusal (deferred). The draft AC
had the command "offer to run the phase-fidelity-reviewer inline" when no
audit exists. V1 instead refuses when no spc-66 (predecessor store) phase-audit receipt exists
for the named phase (and when the latest matching receipt is empty-audited).
Empty-phase detection keys off the spc-66 (predecessor store) receipts, not a
phase:spec anchor (that anchor is deferred; phase membership is editorial). Running the reviewer inline from reflect is a recorded future extension. - Open-spec warn/confirm (deferred). The draft AC had reflect warn and ask for confirmation when a phase's specs are not all closed. V1 does not parse editorial Scope membership, so this warn/confirm path is deferred; the refusal semantics above are the v1 gate.
- Phase-only grain, source links, lifeboat.
/abcd:reflect <itd-N>is refused (phase-only grain). V1 links to the phase doc + audit report + member specs only (no intent links — the spc-66 (predecessor store) receipt carries no intent ids; recorded future extension). The lifeboat-packs-all-retrospectives requirement is a DOCUMENTED forward requirement on the future disembark spec (spc-17 (predecessor store) stubs), not a behaviour this surface implements — recorded in the surface doc.
The interview is a single seeded pass (per-bullet verdicts → five questions);
multi-turn depth is a recorded future extension. Full surface record:
../../brief/04-surfaces/09-reflect.md.
Linkage note (2026-09-30)
builds_on named itd-27 (the grill sub-verb), which is superseded by itd-94.
The edge is dropped rather than relinked: itd-94 carries the grill forward only
as the planning interview behind the implement-readiness gate, and a
retrospective seeded from a release's shipped intents needs neither that
interview nor that gate. The retrospective interview is its own, so nothing
itd-94 delivers is an input to this record.
Linkage note (spc-83.5)
Ships as one of FOUR intents sharing spec
spc-83-operator-surfaces-manifest-lockstep. abcd represents "N intents, one
spec" as a bundle (kind: bundle-member + shared bundle: spc-83-operator-surfaces)
— the representation the doc_fidelity intent-resolution + spec-close preflight
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
Frontmatter
| id | itd-24 |
|---|---|
| type | intent |
| lifecycle | shipped |
| kind | bundle-member |
| severity | minor |
.abcd/development/intents/shipped/itd-24-reflect-command.md
open on GitHub ↗ · commit history ↗
Referenced by23
- adr-2609212115255771Phases and milestones are retired: sequencing is dependencies rendered as status, the checkpoint is the derived releaserelated
- iss-2610241431221889The after-merge fidelity audit of itd-24 judged a criterion unmet, so its check is still owed: ac-2 NOT_MET, ac-7 NOT_METrelated
- iss-2610262031592610itd-24 uses voyage for a project's working life; 04-naming reserves voyage for the operator-level operations namespace.related
- iss-2610262033081135itd-24 has the embark unpack show earlier retrospectives in the press-release interview; the embark chapter gives that job to the separate lessons sub-verbrelated
- iss-2610262033086503itd-24 says reflect reads a release's intents the way the cut does, but its shipped_in rule is not the one the launch chapter's cut appliesrelated
- iss-2610262033096678The launch chapter says the repo organises work by phase; itd-24 records that phases are retired and the release is the unitrelated
- iss-2610262034479574The intent chapter names the phase plan as the canonical build order; itd-24 records that phases are retired.related
- iss-2610262041301883Shipped itd-24 has embark surface past retrospectives during its press-release interview; the verification matrix says embark's press-release interview is staged and what ships is probe-then-writerelated
- iss-2610262041318943itd-24 uses "voyage" for a project's lifetime of work; the glossary defines voyage as the operations namespace of disembark and embark runs and forbids it for a projectrelated
- iss-2610262043005827itd-192's verdict rule turns on 'this phase'; itd-24 records that phases are retired and the release is the unit.related
- iss-2610262043017551itd-196's cumulative and closing rehearsal rungs are defined over a phase; itd-24 records that phases are retired.related
- iss-2610262044017905The phase negotiator (itd-41) proposes and argues over roadmap phases; itd-24 records that phases are retiredrelated
- iss-2610262044029050The dependency graph (itd-78) lints phase ordering; itd-24 records that phases are retiredrelated
- iss-2610262044093076The agent that judges delivery against an intent is `intent-fidelity-reviewer` in itd-30 and the intent auditor in itd-24related
- iss-2610262044102287itd-24 says abcd is single-developer or pair shaped; itd-99 says the product thinker can be a teamrelated
- iss-2610262044591588itd-24 has the person run /abcd:reflect < tag>; itd-2610090831227812 makes reflect an agent-only page the host refuses when a person types itrelated
- iss-2610262045054264The agent that writes per-criterion audit verdicts is the intent-fidelity-reviewer in itd-50 and the intent auditor in itd-24related
- iss-2610262045168363The agent that grades shipped intents is `intent-fidelity-reviewer` in itd-48 and 'the intent auditor' in itd-24related
- iss-2610262045198472itd-67 picks the release bump by phase-completion detection; itd-24 records that phases are retired and the release is the unitrelated
- iss-2610262045214826The lifeboat packer is `disembark pack <repo> <path>` in itd-24 and `disembark <repo> to <dest>` in itd-88related
- itd-2609211913453478One page maps the record families, and phase, milestone and roadmap are retiredrelated
- itd-2609231013154443Every release arrives with a press release composed from what shippedrelated
- spc-2609211751376504reflect-commandimplemented by
mentions29
- adr-9Phase as a product-reflection layer between brief and intent
- adr-34Intent lifecycle and phase scheduling are orthogonal axes
- dcn-26082600000000072026-08-26 — Bug-hunt round 9 (bughunt-b): baseline green on the unshallowed
- dcn-26092100000000012026-09-21 — Phases and milestones are retired, and the word roadmap with them (product thinker, at an interactive interview after an independent research pass; adr-2609212115255771 supersedes adr-9). Sequencing is dependencies plus the lifecycle shelves, rendered as a Now / Next / Later status block on the `abcd` board and the site (itd-2609212103568351), never stored; the checkpoint is the derived release plus each intent's acceptance criteria, with an optional `target_release` the cut reports and moves forward (itd-2609212103572513); the unit below a spec is the step, a section not a family (itd-2609212103565953); an issue carries no spec by design; the batch is the run's internal order; one page maps the families (itd-2609211913453478). itd-24 becomes release retrospectives; itd-34 drops its phase rule. Same interview: `build` is the verb a person types and `implement` the loop (itd-2609201916151817 decision 8), the loop takes an issue key (decision 10), only the loop writes a verdict (decision 9); the person's command list is grouped with an agents block behind `--agent` (itd-146), every verb opens with a does/writes/refuses sentence (itd-2609212113220149), modes become flags and five checks one lint (itd-2609212130136102, breaking); the status-line badge is guarded and reset (itd-2609212130146198); a new capture or draft is matched and linked at filing, never refused (itd-2609212137116617); abcd's text names the product thinker or the technical facilitator and never the maintainer (itd-2609212137129937, captured for the run, no sweep today); the lab conventions become `abcd lab` (itd-2609212137128014); a managed repository's site goes live by one verb behind a provider seam (itd-2609061543533170).
- dcn-26092900000000072026-09-29 — The product thinker answered twenty-six owed rulings and the published-history question in one interview, asked one at a time by orchestrator abcd-23 of autonomous run A (recorded by lane recRulings for orchestrator abcd-cb). The answers are kept verbatim in the local-tier file `.abcd/.work.local/scratch/reports/rulings-answered-2609-29.md`, dated 2026-09-29, and are restated here because that file is not committed. Published history is left as it is, with no rewrite. The build loop's fidelity audit runs once, on the lane that closes the spec, over the whole delivery (AI). On the vendor denylist the product thinker answered, verbatim: "I think we need an allow list rather than trying to catch a deny list." The interviewer's reading of that answer, recorded as a reading and not as the product thinker's words, is that the per-provider allowlist is the control and the vendor denylist is not extended to chase spellings, with whether the bundled `anthropic/*` entry stays as a backstop left to the technical facilitator (AA(a)). Only a route the person set up on their own machine may use their paid key, and a repository's own route to it is refused, which replaces the route half of itd-2609081951381895 decision 8 (AA(b)). The live site setup, the API adapter and the decision adapter may each close on tests against a simulated service, with the live paid check recorded as owed to a person (iss-2609291925387011, iss-2609291925393913, iss-2609291925398978). itd-111's last criterion is met by an agent's timing check on macOS plus the Linux CI run, so the intent may be finished. Automated dependency updates are switched on, pushed with a personal or app token the person creates and stores as a repository secret (itd-2609221842494980; creating the token is the person's act, and the lane builds everything else and names the secret it expects). itd-6 adds a Go MCP module, proposed for the person's explicit sign-off before it is fetched; closing itd-6 on a fake server was not ruled in this interview. (A later answer the same day, H1b in the local-tier file `.abcd/.work.local/scratch/reports/rulings-answered-2609-29-b.md`, dated 2026-09-29, rules that it is not: itd-6 is finished only after running once against the real RepoPrompt app, a check owed to a person.) For itd-148: the store under the home folder wins (adr-2609091248200336); the store draft itd-2609091014076309 owns add, list and clean-up and itd-148 uses them; a session that declares itself the coordinator is exempt from the write block in the primary checkout and every other session is blocked; and the store draft is planned first, with nothing from the store draft, the merged-worktree clean-up included, built before its planning interview (Q4). itd-148's own wait is not part of that ruling: it follows from Q2, because itd-148 uses the store's verbs, and is carried by the `blocked_by` below. itd-148 and spc-42 are rewritten to match in this change, and itd-148 is now `blocked_by` the store draft. A release retrospective is seeded from a release, the intents a tag shipped (AD); itd-24 and its spec are rewritten to the release in this change. An unpointed route is refused naming the one setting to add, as built in 35100512e, so AC11 of itd-2609170822093401 is complete (BR1). A missed target becomes `next`, whatever the following release is numbered (BS1). Spec pieces keep "step" and the lane stages are renamed, a breaking change to the JSON fields `step`, `performed` and `refusal.step` that resolves iss-2609291313276243 and corrects the glossary entry `core/step.md` (BU1), and the old command spellings are removed in that same breaking release (BT1). The text board shows Later as a count only while the site and `--json` keep the full list (BV1), and an intent in progress appears only under Now (BV2). A pause of zero is allowed (BW1); drain stays in the agents' help list until it runs end to end (BX1); a managed repository must hold the drain eligibility decision in its own record, and drain refuses there until it does (BX2); a capture without a remedy is refused (BX3), which tightens the one-line capture friction `commands/capture.md` promises, so the lane that builds it reconciles that page, the principle wording and every caller that files a capture; a run's pick reason keeps the shared `pursued:` kind with its marker (BZ1); and an intent whose blocker was superseded waits on the successor, transitively (BZ2). The five itd-48 follow-ups are planned as one intent, drafted as itd-2609291923559186 (BT2), and all warn rules share one shrink-only baseline file in which a new warning fails, drafted as itd-2609291924469783 (BT3); both drafts wait on their planning interviews. Each ruling that contradicts a shipped behaviour or another record is amended in the change that builds it, not here. itd-7's planning interview stays owed.
- dcn-26102907481904762026-10-29 — The product thinker ruled on 29 October 2026 that an intent's Audit Notes section carrying no reviewer's marker counts as audited only when it reads as a real audit, one that names the acceptance criteria and gives a verdict on them; a ruling's amendment line or any other note that does not is not an audit, and the intent still owes its review. The retrospective seed and the list of reviews owed judge this by one shared rule (intent.HandAudited), so they cannot disagree about a record. Carried by iss-2610241431221889 for itd-24 criterion 2.
- iss-3phase membership and lifecycle directories disagree: planned intents (itd-20, itd-24, itd-29, itd-46) appear in no phase Scope, while draft itd-43 is scoped into Phase 0/1 yet listed later-phase. ADR-bound.
- iss-94The intent corpus still specifies the pre-adr-35 lifeboat model: itd-2, itd-8, itd-9, itd-10, itd-13, itd-15, itd-19, itd-22 and itd-24 variously use the retired 'disembark to home' signature, the in-tree .abcd/lifeboat/ home, or the in-tree .abcd/development/voyage/ path (itd-9's acceptance writes voyage provenance in-tree — the exact path that would fail abcd's own privacy-hygiene audit rule). The brief, glossary and roadmap were reconciled to adr-35; the intents were deliberately NOT rewritten, because an intent is a proposal with its own lifecycle and silently rewriting nine of them inside an unrelated change is worse than tracking the drift. Each reconciles when it is next planned.
- iss-123Round-4 residue of the brief reconciliation: nine precision-grade discrepancies remain after three fix rounds (102 -> 52 -> 25 -> 9), all empirically verified by the checkers and none of the judgement-flip-flop class. Examples: bare ahoy prints a next-step line only for unmanaged kinds but the criterion says any folder kind; embark's manifest verification excludes the post-pack synthesis layer while the chapter claims blanket tamper-evidence; a live bundle (spc-83-operator-surfaces, itd-20+itd-24) contradicts the no-live-bundles claim; the persona_registry lint checks personas.json, not the markdown page named as SSOT; history capture idempotency keys on (sha256, session, kind), not content hash alone. Full findings in the local scratch tier (2026-07-22-iss35-crosscheck-round4 file). The geometric tail also suggests the detector at 22-checker depth has a nonzero noise floor per fresh run — the pass threshold question belongs to iss-122.
- iss-2608261437046944itd-24 glossary_terms_used still lists the retired core/epic term
- iss-2609251618079479After adr-2609212115255771 retired the phase, the milestone and the word roadmap, the brief outside the mental-model chapter still describes the phase as the live sequencing unit: 59 files under .abcd/development/brief mention it, among them 01-product/04-scope.md (bounded by the planned phases), and the glossary entries release, version, loop, plan and spec, whose prose says a phase sequences the work and a release falls out of completing one. itd-2609211913453478 rewrote only the mental-model chapter and repointed each entry's not_to_be_confused_with; no record carries the rest of the sweep.
- iss-2609261536147903Planned intents and disciplines still cite specs of the retired predecessor store unqualified, and such an id at or below spc-70 resolves to a live spec on another subject (spc-12, for one, is live as the disembark grounding spec): itd-48, itd-50 and itd-53 name spc-12, spc-28, spc-29, spc-31, spc-33, spc-43 and spc-52 for the fidelity reviewer, lifecycle hook and cleanup work (which of these are predecessor ids is itself the reading this record owes); itd-24 names spc-66 as the phase-audit receipt; itd-1 and itd-37 name spc-12 as the manual reviewer. The specs charter (Two spc-N Namespaces) rules that every predecessor citation carries the '(predecessor store)' qualifier; iss-239 applied it to the draft corpus only. Each site needs a reading to tell a predecessor citation from a live one, which is why the sweep was not folded into iss-239.
- iss-2609290448510918The predecessor-store qualifier sweep reaches past the six intents iss-2609261536147903 named: outside drafts/ and those six, 192 citation sites across about forty intents name a spc-N at or below spc-70 that is not the citing intent's own spec, with no '(predecessor store)' on the line. Some are live cross-references (the cold-reading family's intents cite each other's live specs), and some are the predecessor store's (itd-4, itd-6, itd-29, itd-47 and itd-49 describe pre-rebuild work in its terms), so each site needs the same reading against the live spec it collides with; the specs charter's Two spc-N Namespaces section is the rule. Found while sweeping the pattern of iss-2609261536147903 in lane drainDrift3; a census script over intents/{planned,shipped,disciplines} reproduces the count.
- iss-2610252214242532intents/README.md lags the code and the record. :38 and :277 list the spc-83-operator-surfaces members as planned (itd-24, 63 and 69 shipped; itd-20 superseded). :100 and :132 mark bundle and reclassify as design targets, though bundle.go and reclassify.go ship. :159 says an intent is 'implemented by exactly one spec', against invariant 17 (02-constraints/03-invariants.md:171). Its own :33 names the brief canonical.
- iss-2610252224248804For a release cut by launch ship, reflect's warning about intents targeted at the release that did not ship can never fire. The cut moves those targets to next before a tag exists (internal/core/release/ingest.go:455, PlanTargetMoves), and the reflect seed (internal/core/reflect/seed.go:173) reads only the intents' current target_release, not the cut's record of the moves (fidelity review of itd-24).
- iss-2610252224253701itd-24 promises that future intents reference past lessons, but nothing on the intent side reads the retrospective store: lessons are read only by embark's lifeboat view (ReadLessons at internal/core/reflect/lessons.go:28, used from internal/core/lifeboat/retrospectives.go:54).
- iss-2610262032262544Embark's lessons view reads only retrospective lessons; disembark's graveyard also writes lessons into the same lifeboat
- iss-2610262032516143embark's lessons speak of 'the previous voyage' and 'the new voyage's brief'; the voyage glossary restricts the word to the operations namespace and forbids it for a project
- iss-2610262033444397The out-of-scope page frames the brief as the work of eight planned phases; the reflect chapter says adr-2609212115255771 retired the phase.
- iss-2610262033596296itd-196 keys its cumulative and closing rehearsals on the phase; the reflect surface says the phase was retired and the release is the grain
- itd-1Every Intent Has Acceptance Criteria; Every Audit Verifies Them
- itd-4Nothing You Notice Gets Lost
- itd-27Domain Experts Get Their Intents Grilled Before Anyone Codes Them
- itd-94An intent that is not planned cannot be implemented: abcd gains a machine-checkable implement-readiness gate that refuses with a remedy and offers the planning interview
- itd-2609221009495079abcd's typed judgements can run through a decision adapter, measured in a lab before it decides anything
- spc-17every-citation-abcd-publishes-is-provably-alive-and-honestly
- spc-66The scribe: ledger-only context, authors nothing
- spc-2609231435545473The release cut writes RELEASE.md from the press releases of the intents it shipped
- spc-2610100613109045a-person-who-types-abcd-sees-only-the-commands-people-use