Lessons - failure classes carried into the next run
A lesson that stays in the retrospective that wrote it is read by nobody after that sprint. The tooling’s own comment on the function that moves them is the clearest statement of the problem:
Without this, the retro is a diary.
Failure classes: what went wrong, counted
Section titled “Failure classes: what went wrong, counted”A run’s failures are recorded as failure classes in sdlc-studio/lessons.jsonl, committed with the project, one row per class: a code (LC-003), a name, a rule, the behaviour to change, the phases it is injected at, its hits and its state.
They come from the retro’s Try items. A Try item tagged [LC-003] adds a hit to that class; one tagged [new: class name] records a new class. A review can count one too: a REJECT whose finding cites a class adds a hit on that unit when the run closes.
lessons.py classes # every code, name, state and hit countlessons classes is how the author of a Try item finds the class to cite, so a repeat is counted on the class rather than written down again under a new name.
Carried into the next run, unasked
Section titled “Carried into the next run, unasked”The next run reads the classes without anyone opening a file. sprint plan prints the classes injected at plan in the plan itself; each build brief and each review brief (critic.py brief) carries the classes injected at its phase. Each gets at most five, rule plus behaviour, most-repeated first, and nothing else from the lessons stores.
That is the rung that makes the difference. The batch you approve already contains the failures the last runs paid for, and the reviewer is told what to look for first.
The 8 seeded classes
Section titled “The 8 seeded classes”A new project with no classes of its own reads the skill’s bundled seed until it records some: 8 seeded classes, each drawn from this project’s own history.
| Code | Class |
|---|---|
LC-001 |
mutant never applied |
LC-002 |
criterion words outrun the fixture |
LC-003 |
mechanism reaches no caller |
LC-004 |
premise not executed |
LC-005 |
repair breaks its neighbour |
LC-006 |
absence read as an answer |
LC-007 |
shared machine resources exhausted |
LC-008 |
constraint added without retirement |
A project’s own store grows past the seed as it records classes of its own. This repository’s held 12 at the close of the 6.0.0 release run: the 8 seeded and 4 it recorded (RPT0011).
A class that keeps recurring becomes work
Section titled “A class that keeps recurring becomes work”A lesson that is read and still repeated is not working, so the close acts on the store with no operator step:
| When | The close |
|---|---|
| a class has recurred twice after the run that recorded it | files one change request, Prevent or retire lesson LC-NNN, naming each hit; the class reads graduating |
a graduating class’s change request has shipped, or was rejected |
marks the class graduated, or retired so a later repeat revives it |
| an active class has gone unhit through the last five runs | retires it, so the brief carries what is biting now |
| a retired class is hit again | puts it back in force |
The change request asks for the code path each hit names to be fixed, and any check it proposes must name the lane, refusal or baseline it retires. A lesson turns into a fix, not into another gate.
graduated ships in 6.1 (US0977). In 6.0 a class stopped at graduating, and marking it graduated was a hand edit. Now the close marks it graduated once its change request is Complete or Superseded, retired if the request was Rejected, and leaves it graduating while the request is open. At the 6.0.0 release run’s close, five of this repository’s classes read graduating and none read graduated (RPT0011).
Recording a class does not by itself stop the mistake. At that same close, LC-002 had been hit 51 times in all, 14 of them in that run, while it was carried into the plan and every review brief.
The prose tiers
Section titled “The prose tiers”Beside the classes, two prose tiers still ship. An untagged Try item goes to the first.
Per-project. A lesson learned here stays here, in sdlc-studio/.local/lessons.md. It is the default, because a lesson learned on your project is not automatically true on any other.
Cross-project. The skill ships its own registry of generalisable engineering and process lessons - the ones that improve decisions on any project at all. A brand-new project inherits it on day one, before it has made a single mistake of its own.
/sdlc-studio lessons add # a lesson for this project/sdlc-studio lessons add --global # promote it - the deliberate act, not the reflex/sdlc-studio lessons recall # anything we should know before deciding this?/sdlc-studio lessons list/sdlc-studio lessons revalidate # which of these still hold?/sdlc-studio lessons summary/sdlc-studio lessons prune --older EP0003lessons carry puts one prose lesson into the fixed-size set carried into the next batch; once the set is full, carrying another means naming the one it displaces and why:
lessons.py carry --id L-0004 --displaces L-0002 --reason "enforced in CI since EP0006"Promotion needs a version-controlled destination. Without one it is refused rather than written into a copy the next update deletes.
The close keeps the log honest
Section titled “The close keeps the log honest”gate --require-retro reads the lessons as well as the retro. It fails on a committed summary that is not the digest of the current log - a lesson closed since the last regeneration fails it exactly as an added one does - and on an open lesson past its validity horizon. lessons revalidate closes or extends the stale ones, and lessons summary regenerates the digest. The log cannot silently grow into unread noise.
Recall is also how an audit starts
Section titled “Recall is also how an audit starts”Before an audit fans out, the ranked lessons are read first - because a lesson this project already paid for is a lens. What went wrong last time is where to look first.
And the estimate learns too
Section titled “And the estimate learns too”The same principle runs through the forecast. Every project starts on a shipped default rate. Once it has five units of its own measured evidence, its own numbers replace the default - and the plan always says which of the two it is quoting.
A rate re-fitted to one or two units is fitting noise. This project has twice had to delete a rate that hardened into an article of faith, which is why the threshold exists and why nothing is allowed to hard-code it.
Where to next
Section titled “Where to next”- The retrospective - where Try items come from.
- Sprint planning - where the classes are printed back.
- One independent review - the brief that carries them to the reviewer.
- Audit - where lessons become lenses.