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 (mandatory triggers, 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

Capture starts in flight: four write-capable roles (engineer, adr-generator, product-discovery, release-orchestrator) append learnings the moment they occur via ds-learning-shard append --session-key <SESSION_KEY> - the key arrives in every spawn brief - into the external store ~/.agentic/learnings-shards/. Shards drain at /ds-implement-ticket Phase 11e and at the activation-preflight rollup; content/references/learnings-capture-instruction.md governs which roles append vs declare learnings_candidate[].

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
Background capture on the mandatory triggers. Spawned by the conductor the FIRST time a trigger fires in a session; see the mandatory trigger list in `content/references/conductor-operating-rules.md` §learnings-agent background capture.

Emits both LRN and KNW entries. Trigger: mandatory evaluation, conductor-initiated spawn.
Distinct triggers on purpose: learning-extractor guarantees coverage across every ticketed loop; learnings-agent captures the mandatory-trigger 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. learnings-agent may also append at most one pointer entry directly to MEMORY.md, in the same invocation, for conductor-behavioral events.

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

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

  • ~/.agentic/learnings-shards/ - in-flight capture buffer, external to the repo. Written by ds-learning-shard append from the four capture roles the moment a learning occurs. Never committed itself; drained at /ds-implement-ticket Phase 11e and by the activation-preflight rollup.
  • .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. Written by learnings-agent (at most one entry per invocation, when the event is conductor-behavioral - not a later promotion) and, as of DS-90, by /ds-wrap Part B (staging-drain promotion, capped 3/run).
  • .agentic/memory.md - deferred-wrap daemon staging only, written exclusively by /ds-wrap-deferred. Gitignored. NOT auto-injected. NOT the same as root MEMORY.md; drained into it by the next synchronous /ds-wrap.
ds-learning-shard (4 roles) ──> shard entry ──> ~/.agentic/learnings-shards/ (external; drained at Phase 11e + preflight rollup)
learning-extractor ──> LRN entry ──> .agentic/learnings.md (committed)
learnings-agent    ──> LRN entry ──> .agentic/learnings.md (committed)
learnings-agent    ──> KNW/LRN entry ──> .agentic/learnings.md (always)
learnings-agent    ──> conductor-behavioral? ──> MEMORY.md (same invocation, at most 1 entry)
Four stores, four writers, four audiences. The shard buffer is the only external one - it feeds the durable stores through a classified drain, never directly. Mixing the durable stores 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