Brownfield Retrospective
Run ECC's engineering process retroactively against a project that was built without it. Pick any slice of an existing codebase, audit what exists, reconstruct how it got there, extract a four-axis gap register, then execute the fixes forward through the standard ECC pipeline.
The workflow is slice-first: no whole-repo onboarding is required before it is useful, and every phase is re-enterable from a durable artifact on disk. Start in the middle, work backwards, then move forward.
When to Activate
- Adopting ECC in a repository that already exists and is already shaped
- User asks to "audit my existing project", "retro this codebase", or "what did we miss?"
- Taking over, inheriting, or returning to a codebase after a long gap
- User asks "why is it like this?" followed by "should it stay like this?"
- A module, feature, or service needs a rethink before the next feature lands on top of it
- Deciding whether a legacy area should be fixed forward, rewritten, or left documented as-is
When Not to Use
- Greenfield work with no existing code — use
planner and tdd-workflow directly
- Onboarding to spec-driven development without the redesign loop — the
spec-miner agent does that on its own
- A launch go/no-go production-readiness pass — use
production-audit
- Security-only sweeps — use
security-review
- Team process retrospectives (sprint ceremonies) — this audits a codebase, not people
The Working Set
All artifacts are written inside the audited project, under docs/retro/<slice>/:
| File | Phase | Purpose |
|---|
gap-register.md | 0-6 | The state machine — perimeter, Current phase: marker, and rows. The only file required to resume mid-stream. |
baseline-audit.md | 1 | Reviewer findings, test/CI snapshot, TODO inventory. |
reconstructed-spec.md | 2 | What the code actually does today (Requirements + Invariants). |
target-design.md | 4 | Target shape for the slice and the fix sequence. |
Backfilled decisions go to docs/adr/ per the architecture-decision-records skill. If the project uses OpenSpec, reconstructed-spec.md may instead be openspec/specs/<capability>/spec.md produced by spec-miner.
How It Works
Phase 0 — Pick the Entry Point
Start from what the user cares about today. Do not map the whole repo first.
Any of these is a valid slice:
| User signal | Slice |
|---|
| Names a directory, module, or service | That path plus its direct callers |
| Names a feature or user flow | The files that implement it, traced from the entry point |
| Names a bug, incident, or pain point | The code that produced it plus one level of call chain |
| Names a dependency or tech choice | Everything that touches it |
| Names nothing | The 2-3 hottest paths by churn — propose them and let the user pick |
Record the perimeter at the top of gap-register.md before anything else: paths in scope, entry points, callers, blast radius. Budget the slice at roughly 15 files or 2,000 lines; if the user's pick is bigger, cut it into named sub-slices and register each as its own row of work. A slice too big to audit in one session is a slice that never finishes. Keep a Current phase: marker beside the perimeter and advance it each time a phase completes.
Phase 1 — Present-State Audit
Establish what exists now, with evidence. Do not fix anything yet.
- Recon the slice: manifest and framework fingerprint, entry points, test layout, CI checks (borrow the recon steps from
codebase-onboarding, scoped to the perimeter).
- Run the reviewers that match the stack, in parallel where possible. Every finding must carry a
file:line pointer:
- The language reviewer for the stack (
typescript-reviewer, python-reviewer, go-reviewer, ...)
security-reviewer
silent-failure-hunter for swallowed errors
type-design-analyzer where invariants are encoded in types
performance-optimizer only if the slice is on a hot path
- Snapshot the current state: test count and coverage, lint/CI status,
TODO/FIXME/HACK inventory inside the perimeter.
Write everything to baseline-audit.md. Findings that get fixed during this phase corrupt the baseline — hold them for the register.
Phase 2 — Backward Reconstruction
Work backwards from the present state to the decisions that produced it.
- Mine the behavioral spec: run
spec-miner against the slice. Its Requirements (WHEN → THEN) and Invariants become reconstructed-spec.md — the baseline truth for Phase 5 tests.
- Git archaeology on the perimeter:
git log --oneline -- <slice> for directory history; use --follow only with a single file path — age, authors, cadence
- Largest and most reverted commits — where the design changed under pressure
- Churn hotspots — files changed far more often than neighbors
- Dead ends — branches or scaffolding that never shipped
- Decision inventory: list the significant decisions frozen into the code (stack and framework choices, data model, boundaries, error strategy, state management). Check each against
docs/adr/, README, and comments. Every decision with no written record is itself a pre-existing thinking gap — record it in Phase 3, do not silently backfill it here.
- Where behavior is opaque, use
code-explorer to trace execution paths before guessing at intent.
Phase 3 — Gap Analysis (Four Axes)
Convert the audit and reconstruction into register rows. One axis per class of gap:
| Axis | Question | Sources |
|---|
| Thinking | What was decided but never recorded? Which invariants live only in code? | Decision inventory, reconstructed spec |
| Coding practice | Where does the code diverge from how ECC would have written it? | Phase 1 findings, the rules/ pack for the language, spec items with no test anchor |
| Missing features | What would a day-one build have included that this slice never got? | Boundary input validation, observability, rate limiting, idempotency, migrations plus rollback, a11y, i18n, user docs, CI gates |
| Technology selection | Is the chosen tech fighting the codebase? Outdated, duplicated, risky, or missing? | Dependency inventory, git archaeology, recon |
Register format (the table is the skill's durable output):
| ID | Axis | Gap | Evidence | Forward fix | Severity | Effort | Status |
|----|------|-----|----------|-------------|----------|--------|--------|
| G-001 | practice | Errors swallowed in retry loop | src/api/retry.ts:42 | Propagate + map at boundary | P1 | S | open |
- Severity:
P0 security exposure or data loss, P1 correctness, P2 practice and observability, P3 selection and cleanup.
- Effort:
S under a session, M a few sessions, L needs its own plan.
- Status:
open, in-progress, done, wont-fix.
- Every row needs an evidence pointer. A gap you cannot point at is an opinion.
Phase 4 — Redesign / Rethink
Turn the register into a sequenced plan. Follow the project's existing task and approval authority. Keep the register as audit evidence linked to that system; do not create competing canonical task state. Confirm scope and obtain project-required approval before a rewrite, technology replacement, migration, or other material change.
- Run
architect or code-architect over the P0 and P1 rows to produce target-design.md: target shape for the slice, the fix sequence, and an explicit "what does not change" list to protect working behavior.
- Backfill retro-ADRs for every undocumented decision from Phase 2. Mark them as reconstructed (
status: proposed (reconstructed), date of the retro, note the original decision predates the record). Separate observed history from inferred intent, and have the project owner confirm a decision before marking it accepted. Never present a backfilled ADR as if it were written at decision time.
- Triage every register row into one of:
fix-forward (repair in place), rewrite (replace the slice), leave-documented (wont-fix). A wont-fix must record its reason in the register — a wont-fix with a reason closes the thinking gap; a silent one reopens it.
- Sequence the backlog:
P0 first, then interleave quick wins with larger repairs to keep momentum.
Phase 5 — Forward Execution
Work the register through the standard ECC pipeline, one row per session as a baseline pace:
planner (scope the row)
→ tdd-guide (failing test first — for a legacy gap the first test
usually encodes the missing invariant from reconstructed-spec.md)
→ implement
→ code-reviewer
→ security-reviewer (if the row touches input, auth, or data)
→ doc-updater + ADR (if the decision changed)
→ conventional commit
→ mark the register row done
- Update
gap-register.md statuses as rows close; the register is the durable state, not the conversation.
- On session boundaries, hand off through the project's memory mechanism (
unified-memory, context carriers) so the next session resumes from the register alone.
Phase 6 — Closure and Re-Audit
When every row is done or wont-fix:
- Re-run the Phase 1 audit over the same perimeter.
- Diff against
baseline-audit.md and verify with verification-loop — the gaps claimed closed must stay closed.
- Record the delta (findings then, findings now, rows closed, rows deferred) at the bottom of
gap-register.md.
- Anything that resurfaced becomes a new row, not a failure — the register is a loop, not a one-shot.
Resuming Mid-Stream
Any session can start in the middle. Read docs/retro/<slice>/gap-register.md first:
- Register exists with a row
in-progress → Phase 5, finish that row.
- Register exists with at least one row, all rows closed → Phase 6.
- Register exists, rows open, none in progress → resume at the
Current phase: marker (Phase 3 register awaiting triage, or Phase 4 backlog awaiting its first row).
- No register, but
baseline-audit.md exists → Phase 2.
- No artifacts at all → Phase 0 with the user.
Anti-Patterns
- Auditing the whole repo before any slice — the workflow is slice-first by design.
- Fixing code during Phases 1-3 — audit phases produce the register; edits mid-audit corrupt the baseline.
- Register rows without evidence pointers.
wont-fix without a recorded reason.
- Presenting backfilled ADRs as contemporaneous records.
- Skipping the Phase 6 re-audit — closure is verified, not declared.
Related Skills
codebase-onboarding — recon baseline for Phase 1
architecture-decision-records — retro-ADR backfill in Phase 4
tdd-workflow — Phase 5 execution discipline
verification-loop — Phase 6 closure
production-audit — launch-readiness lens (complementary, later)
security-review — security-only requests