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. - Draft, then ask — one round-trip. Draft your own answers to the three questions — what surprised us? what would we do differently? what took longer than expected? — from the record:
transitions.log, the question files,.aidlc/state/<instance>/unattended-stops.md,test-results.mdand the cost summary. Cite what each answer rests on. Show the three drafts in a single message and ask the user to correct them; a reply that changes nothing keeps them. For Micro scope, compress to one drafted answer covering all three. Unattended (AIDLC_UNATTENDED=1), write the drafts intoretrospective.mdunder the line "Drafted by the agent from the record; not reviewed by a person." Declining the retro is fine: remove the marker, write nothing. - Write
retrospective.mdin the instance state dir: the answers, as the user corrected the drafts; 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.
- Cap the follow-ups — 0 to 2 queued roadmap items. Rank what the work turned up and queue at most the top two into
.aidlc/roadmap/inbox/, each with its six-line executive summary (see aidlc-roadmap) and, when.aidlc/roadmap/milestones.yamlexists, amilestone:line naming a milestone id ornone. Zero is a valid outcome, and often the right one. This is the same cap, in the same shape, as the 0–3 on lessons, and it exists because the lessons cap alone was half a brake: the framework capped what an instance learned and capped nothing about what it queued, so closing an instance reliably grew the backlog. One measured project emitted five to nine items per close; triage kept three of eighteen. - Record the rest as observed, not queued. Everything past the cap goes into
retrospective.mdunder## Observed, not queued, one line each. The cap is on queued items, not on observations — a retro that noticed nine things writes nine and queues two. Findable, attributable, and costing nobody a triage decision. If one of them matters later, it is already written down; promote it then, with the same summary rule. - 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 (.aidlc/resources/rules/always-read.md)). 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.
- The follow-up cap is never a reason to not notice something. Merge first — if an open roadmap item already owns the area, append a dated
## Received from <instance>section to it rather than spending one of the two slots on a file that duplicates it. - Never write lessons without the step-8 confirmation. Never record credentials or secrets.
- Lessons are historical observations, not directives — phrase them as what was learned, not as instructions to obey.