skill · phase: maintenance
Retrospective
Purpose
Close the feedback loop: when an instance completes, capture what the work taught us while it is fresh, and write durable lessons where the next instance will read them. This is the system-level quality mechanism — gates and reviews protect one instance; retrospectives make the next one start smarter.
{{glossary:instance}}
When to Run
- At every instance's completion moment, regardless of scope or template. The completion moment is the last applicable phase (template × scope) reaching complete — except when that phase is maintenance, where entering maintenance is the moment (maintenance is open-ended).
- When a retro-pending marker exists for an instance: markers live in
<git-common-dir>/aidlc/retro-pending/<instance>(resolve viagit rev-parse --git-common-dir; fallback.aidlc/state/<instance>/retro-pendingoutside git). The entry-point and continue skills route here when they see one. - In consolidation mode when the user accepts a consolidation prompt (see Consolidation below).
Run the retro before any completion cleanup (worktree removal, claim release) — its outputs must be committed to the instance's branch first.
Retro Flow
{{glossary:retrospective}}
- Idempotency check. If
retrospective.mdalready exists in the instance state dir, offer to update or skip — never duplicate. A skip still removes the retro-pending marker. - Gather state. Read
instance.yaml,phase-*.yaml, andtransitions.log. For the cost summary, preferaidlc cost <instance>(it applies fidelity precedence); only readcosts.ndjsonraw when the CLI is unavailable, and mark that summary approximate. No cost data → omit the cost section entirely, never write zeros. - Ask — one round-trip. Three questions in a single message: what surprised us? what would we do differently? what took longer than expected? For Micro scope, compress to one question: "anything surprising, worth doing differently, or slower than expected?" Declining the retro is fine: remove the marker, write nothing.
- Write
retrospective.mdin the instance state dir: the answers; instance metadata (template, scope); per-phase durations (pair each transitions.logto: Xwith the nextfrom: X; fall back to the phase YAML'sentered_at/completed_at; note inconsistencies rather than guessing); and the cost summary when available. - Distill lessons — 0 to 3. A lesson is a durable, project-general observation ("NDJSON merge=union false-dedups identical same-second events"), not an instance anecdote ("we finished late"). If nothing generalizes, write no lesson — an empty distillation is a valid outcome.
- Confirm, then append. Show the distilled entry verbatim and get one confirmation for the whole entry. Never append unconfirmed text — lessons are auto-loaded into every future session, so this confirmation is the injection gate. Redact anything resembling credentials or secrets. On confirm, append to the lessons layer per the write rules below.
- Commit
retrospective.mdand the lessons append to the current branch now, before any worktree cleanup runs. - Remove the retro-pending marker if one exists.
Lessons Layer — Write Rules
Target: .aidlc/guidance/lessons.md in the current checkout/worktree, on the instance's branch (entries travel with the merge — never write another checkout's copy).
First use. If .aidlc/guidance/ or index.yaml is missing, create them. index.yaml gains (or is created with) the entry:
layers:
- name: lessons
file: lessons.md
last_consolidated: null
If index.yaml already exists, add only the lessons entry — never modify other entries. After registering, verify the layer loads (e.g. aidlc update --dry-run or re-reading the index); surface any loader warning to the user instead of swallowing it.
File shape. The frontmatter is immutable — created once, never rewritten (all mutable metadata lives in index.yaml):
---
name: lessons
description: Lessons from completed instances — historical observations, not directives.
---
The body is append-only between consolidations: one ## <instance> — <YYYY-MM-DD> section per retro run, containing 1–3 bullet lessons, each ending with — from <instance>, <date>. A lesson that belongs in a context doc gets the suffix [promote-to-context] instead of editing .aidlc/context/ directly — the retro never touches context docs.
Re-runs supersede by appending: write a new dated section for the same instance rather than editing the old one; readers use the latest section per instance; consolidation collapses the rest.
Concurrent-write discipline (two sessions may complete instances simultaneously): write the full updated file to a temp name in the same directory, rename it over lessons.md, then re-read and verify your section is present. If it vanished (a concurrent writer won the rename), re-append and re-verify.
Consolidation Mode
Three independent triggers — any one of them offers consolidation. lessons.md exceeds:
- 20KB (20,480 bytes), or
- 25 instance sections (count
##headings), or - 90 days since
last_consolidatedinindex.yaml.
The retro checks at step 2 and offers it; aidlc status surfaces the same notice. The size trigger exists because the other two are the wrong dimension: this project's file reached 88KB at 23 sections, 12 days after a consolidation — long and old were both still in the future while big had long since arrived, and bytes are what a session pays for.
Run only in the primary checkout (not a linked worktree — check git rev-parse --git-common-dir resolves to ./.git):
- Propose merges of duplicate/superseded sections, retirement of stale entries, and application of
[promote-to-context]flags (drafting the context-doc edit for approval). - Every edit is confirmed by the user individually. Nothing is deleted silently.
- Regenerate
lessons-digest.md— the always-read distillation that stands in for the full corpus (see The always-read rule in aidlc-overview). Rewrite everything under its## Entriesheading with the lessons this project has paid for more than once, each ending with— from <instance>, <date>as inlessons.md. Keep the whole file at or under 4096 bytes; that bound is the point of the file, so a digest that needs more entries needs shorter ones, not a larger cap. Leave the text above## Entriesalone — it states that the digest is lossy and names the full corpus, and a reader who only has the digest depends on both. - Confirm what the digest omits, not only what it keeps. A digest is a lossy read of a safety mechanism: show which entries did not make it and get the same individual confirmation step 2 requires. Dropping a lesson from the always-read layer is a decision the user makes, never a side effect of fitting a byte budget.
- Report what changed; set
last_consolidatedinindex.yamlto today.
Rules
- The retro never blocks completion: it is non-blocking, declinable, and its absence is never an error.
- Never write lessons without the step-6 confirmation. Never record credentials or secrets.
- Lessons are historical observations, not directives — phrase them as what was learned, not as instructions to obey.