Learnings

Lessons that earn their place in your next session.

Canon turns what a fresh reviewer finds in a sprint into rules your agent starts with next time. A different agent judges which ones are worth keeping, and you make the final call.

How a finding becomes a rule

Capture automatically. Promote deliberately.

The first three steps run every time a sprint closes. Nothing becomes a standing rule until a fresh reader recommends it and you agree.

at sprint closeAutomatic, no extra command
  1. Capture
  2. reviewer

    A fresh agent with no build history reads the diff and writes review-notes.md. Advisory, not blocking.

  3. tkt learn

    Step 8 of sprint complete writes .tickets/<id>/learnings.md from deviations, evaluator findings and reviewer findings. Status UNPROMOTED. A clean sprint writes nothing.

  4. learnings-sweep

    The agent compresses one row into the root LEARNINGS.md index. A protocol step, never a close gate. The file is an unreviewed queue and is not imported.

later, fresh sessionJudged by someone who was not there
  1. Judge
  2. promote-learningsreport only

    Reads every UNPROMOTED row and its source file in full. Asks whether a different future sprint would hit the same mistake.

  3. one destination

    Each durable lesson gets exactly one proposed home. Each one-off gets a recommendation to dismiss, with a reason.

  4. no self-promotion

    The sprint that produced a lesson never promotes it. Everything looks load-bearing to the agent that lived through it.

your callA human decides
  1. Decide
  2. apply

    In canon, you write the rule by hand and flip the row to promoted or dismissed. In a project, /promote-learnings asks which proposals to write.

  3. Use
  4. next sessionloaded

    Promoted rules arrive through files a session already loads, so nobody has to recall the incident.

A real ticket, end to end

One missed quote mark became a rule.

Ticket t-6328 added a board label for branches that diverge. Everything below is quoted from its ticket files.

1 · The reviewer finds a real bug
app.html:2807 puts esc(info.long) in a double-quoted title="...", but esc() escapes only & < >, not ". A git branch name can contain ", so this is an attribute-breakout XSS. The ticket's own hostile-name test injects <img onerror=...> and never tries attribute breakout, so it passed straight through the bug.

Verdict: NO, advisory. The author fixes it and shows the new test fails without the fix.

2 · It lands in the queue
No evaluator findings, but the advisory reviewer caught an attribute-breakout XSS the ticket's own hostile-input test passed straight through: the board's esc() does not escape "…

One row in LEARNINGS.md, status UNPROMOTED, linked to its source file.

3 · A fresh reader splits it in two
The XSS half becomes a testing rule. The real-git half becomes an extra example on an existing critique entry. Five tickets, this one included, converged on one rule: a new guard needs a test that fails when the guard is reverted.

Read-only report. It wrote no files.

4 · The rule your next session starts with
A hostile-input test must match the sink's context: escaped text in title="…" needs a quote-breakout payload (a"onmouseover="x), not just <img onerror>.

Row status becomes promoted → standards/efficiency.md, so where a lesson went can be read from the row.

That queue of 10 rows became 7 standards bullets, 2 critique entries, 1 gate-protocol note and 2 dismissals. Dismissed rows change nothing and are never loaded.

Where a lesson goes

The narrowest home that is read at the right moment.

A rule that is always loaded costs tokens on every turn. Ask when a future session would make the mistake, then pick the smallest place read at that point.

If the lesson…Goes toExample
applies to every session, whatever it is doing
CLAUDE.md or AGENTS.md. Rare.
"Fail loudly, surface ambiguity"
applies while writing code, tests, commits or reviews
standards/efficiency.md, auto-loaded
t-6328: a hostile-input test must match the sink's context
only bites at one workflow step or in one skill
That step's reference doc or SKILL.md
t-4c24: no-tracked-diff sprints need an explicit base ref
needs its incident to be understood
critique/canon-learnings.md
t-15ee: "Read the Gate Before Writing the Cause"
Claude already has memory

Memory remembers you. Learnings remember what the codebase taught.

They are complementary. Use memory for how a person works, and this flow for engineering mistakes worth not repeating.

 Claude memory and CLAUDE.mdCanon learnings flow
Who writes it
The working agent, from what it recalls or was told
A reviewer and evaluator with no build history find it. tkt learn copies the text
Who judges it durable
The agent that just lived through it
A separate fresh session, then a human
Evidence
A one-line note. The proof is not attached
Each row links to review-notes.md or summary.md with quoted file:line text
Where it lives
One user's machine
Files in the repo, reviewed and versioned like code
Who benefits
That user, in that Claude Code install
Every contributor, and other harnesses that read the same files
Cost
Instant, no ceremony
Fires at sprint close and needs a human step. Slower on purpose
In your own project

Your project gets its own PROMOTED.md.

Canon's standards/ and skill references belong to canon, so a project never writes into them. It keeps its own destination instead.

One file, one import.

skills.sh add sprint creates PROMOTED.md at the project root and adds @PROMOTED.md to AGENTS.md. Claude Code loads it every session. skills.sh refresh covers projects that added the skill earlier.

Unreviewed stays unloaded.

LEARNINGS.md is never imported. Loading it every session would skip the fresh-reader judgment this flow exists for.

You confirm every line.

Run /promote-learnings in an interactive session. After the report it asks which proposals to apply, writes only those to PROMOTED.md with the ticket ID, and flips each row to promoted → PROMOTED.md.

The Upkeep card reports, never writes.

It runs the same skill headlessly and stays report-only. Its ? panel points to the interactive step. Keep PROMOTED.md short: the skill warns when entries pass 60 lines.

Get started

Stop re-learning the same mistake.

Register the sprint skill and every close feeds the queue.

$curl -fsSL https://raw.githubusercontent.com/sunitghub/canon-skills/main/install.sh | bash
Windows: irm https://raw.githubusercontent.com/sunitghub/canon-skills/main/install.ps1 | iex