The Learnings Pipeline

How DinoStack gets smarter every session

Why a learnings pipeline

  • Every Skeptic finding, error-fix cycle, and tool-failure workaround is a signal
  • Without capture, the next agent starting cold re-derives the same lessons from scratch
  • The learnings pipeline converts ephemeral session knowledge into durable entries in .agentic/learnings.md
  • That file is committed - teammates and future sessions inherit the knowledge automatically
  • Two distinct feeders exist: learning-extractor (mechanical, per-ticket) and learnings-agent (discretionary, per-session)
The pipeline is not a logging system. It is a self-improving loop: each closed ticket leaves the project measurably smarter than it found it.

The two feeders

learning-extractor
Mechanically wired to /ds-implement-ticket Phase 6 clean exit. Fires automatically on every ticketed Skeptic loop completion. The conductor does NOT spawn this manually - it is part of the Phase 6 sequence.

Emits LRN entries only (bug-fix residuals). Trigger: phase gate, not conductor judgment.
learnings-agent
Conductor-discretionary background capture. Spawned ad-hoc the FIRST time a learning-worthy event occurs in a session: Skeptic finding resolved, error-fix cycle, tool failure workaround, architectural decision, cross-component gotcha, user-called-out reusable pattern.

Emits both LRN and KNW entries. Trigger: conductor judgment.
Distinct triggers on purpose: learning-extractor guarantees coverage across every ticketed loop; learnings-agent captures ad-hoc session events no phase gate would catch.

Entry types: LRN vs KNW

LRN-YYYYMMDD-XXX
Bug-fix learning. Fields:
  • Discovered, Severity, Domain
  • Pattern (what went wrong)
  • Fix (how it was resolved)
  • Source (phase/agent/ticket)
Used for bug-shaped findings from Skeptic loops and error-fix cycles. Emitted by both feeders.
KNW-YYYYMMDD-XXX
Knowledge learning. Fields:
  • Discovered, Domain, Fact
  • Why-it-matters
  • Source
No Severity field. Used for env facts, dead-ends, architectural rationale, tool-failure workarounds, and cross-component gotchas. Emitted by learnings-agent only.

LRN and KNW maintain independent per-day counters. KNW entries are promoted to MEMORY.md at /ds-wrap.

Capture classification: guardrail first

Before writing any entry, the guardrail-first precedence chain runs:

  1. Can this be a guardrail? If the knowledge encodes as a regression test, lint rule, type annotation, schema constraint, or CI check - write the guardrail instead. The guardrail IS the capture.
  2. Already covered? If an existing guardrail, AGENTS.md, MEMORY.md entry, or the diff encodes it - SKIP. No duplicates.
  3. Apply the table only when (a) and (b) both fail.
Tier Signal Action
MUST Expensive to re-derive AND no better home as a guardrail Write LRN or KNW entry
SHOULD One gate strong, the other marginal Capture if cheap; prefer promoting to MEMORY.md
SKIP Guardrail enforces it, visible in diff/code, already documented, one-off Do not write
A learning entry is the lowest tier of capture. The question is not "should I capture this?" - it is "what is the cheapest durable form this knowledge can take?"

The MUST two-gate bar

MUST tier requires both conditions to hold simultaneously:

Gate 1: Expensive to re-derive
A future agent starting cold would need non-trivial tool calls, failed attempts, external lookups, or multi-step diagnosis to rediscover it. If the next agent can find it in one Read or one search, SKIP.
Gate 2: No better home
A guardrail (test, type, lint, assertion, CI check) cannot encode it, AND it is not already in AGENTS.md, MEMORY.md, or the diff. If a better home exists, use it.

"If I had to figure it out, the next agent shouldn't have to - but if a guardrail can stop them needing to figure it out at all, write the guardrail."

If either gate fails, drop to SHOULD or SKIP. MUST is genuinely rare.

Where learnings land

Three distinct knowledge stores - each with a different writer and lifecycle:

  • .agentic/learnings.md - primary destination. Committed to git. Written by learning-extractor (LRN) and learnings-agent (LRN + KNW). Teammates inherit it on pull after merge.
  • MEMORY.md (root <cwd>/MEMORY.md) - canonical durable facts. Committed. Loaded at session start via the @MEMORY.md import in the project root CLAUDE.md. KNW entries are promoted here at /ds-wrap when they stabilize.
  • .agentic/memory.md - /ds-wrap-internal rolling scratch only. Gitignored. NOT auto-injected. NOT the same as root MEMORY.md.
learning-extractor ──> LRN entry ──> .agentic/learnings.md (committed)
learnings-agent    ──> LRN entry ──> .agentic/learnings.md (committed)
learnings-agent    ──> KNW entry ──> .agentic/learnings.md ──> MEMORY.md (at /ds-wrap)
Three stores, three writers, three audiences. Mixing them corrupts the `@MEMORY.md` import contract that keeps MEMORY.md clean for every session start.

Skill-candidate detection

When friction recurs across sessions faster than learnings can absorb it, the pipeline escalates to skill-candidate detection:

  • Repeated tool-failure workarounds with the same domain_tag in events.jsonl cluster into a signal
  • /ds-wrap Part D and wrap-ticket session reflection scan for recurring patterns via skill-candidate-deep-cluster.js
  • When a domain crosses the threshold, an entry appears in .agentic/skill-candidates.md with status open
  • The conductor surfaces it at the next session start: SKILL-CANDIDATE: domain '<domain>' has accumulated <count> occurrences - consider creating a skill

A skill encodes what a sequence of LRN/KNW entries cannot: a reusable, activatable procedure the agent applies on demand rather than re-learning each time.

Learnings reduce re-derivation cost. Skills eliminate it. The pipeline routes from ad-hoc friction to structured knowledge to activatable skill - each tier cheaper than the one before.

Capture once. Inherit forever.

Two feeders. One file. Every session smarter.

github.com/Space-Dinosaurs/DinoStack