Every night I leave Claude Code sessions open. In the morning, they're closed. The transcripts get written to ~/.claude/projects/ as JSONL files — hundreds of turns, tool calls, partial thoughts, decisions made and unmade.
Most AI systems treat those transcripts as waste. orchestrator dream treats them as ore.
Run orchestrator dream status right now and you'll see: 250 transcripts processed, 344 chunks extracted, 2,274 learnings in the database. That number — 2,274 — came from conversations I had with agents, not from code I wrote. When the next session starts, the system reads back the best of those learnings before any prompt lands. The cycle closes. That's the part that sounds too clean to be real. Here's what it actually looks like.
What dream Does
orchestrator dream run walks ~/.claude/projects/ looking for JSONL transcript files. It skips anything that hasn't changed since the last run (file-level sha256) and anything it's already extracted (chunk-level sha256). For the rest, it cuts the conversation into token-bounded windows and sends each chunk to Haiku with a focused prompt: what decisions, insights, patterns, or gotchas are in here?
Haiku writes learnings to ~/.alluka/learnings.db — a single SQLite file that holds five tables: schema_version, learnings, learnings_fts, processed_transcripts, and processed_chunks. The dream tables and the learning tables share the same file. The DB is currently 58 MB on disk.
The last dedup layer runs at insert time. learning.DB.Insert computes a cosine similarity against existing learnings and discards anything above 0.85 similarity. The three layers together — file hash, chunk hash, semantic similarity — mean the same idea doesn't enter the database twice. They also mean that if Haiku extracts the same learning from two different conversations, only one survives.
One thing dream explicitly doesn't do: it excludes worker sessions. Anything where the working directory is inside ~/.alluka/worktrees/ gets skipped. Worker output is already captured live during phase execution via CaptureWithFocus. Dream is the offline path — for interactive sessions, one-off experiments, side conversations. The two pipelines don't overlap.

250 Transcripts, 2,274 Learnings
The current numbers, straight from dream/store.go:147-155 (SELECT COUNT(*)):
processed transcripts: 250
processed chunks: 344Those 344 chunks produced 2,274 learnings, 1,703 of which have embeddings. The gap — 571 learnings without embeddings — comes from the incremental embedding pipeline not backfilling everything immediately. Quality scores are assigned at extraction time based on specificity and actionability. The preflight hook at session start reads the top learnings by quality score, not recency.
The path from a learning in the database to my first Claude message of the day:
orchestrator hooks preflight
└─ preflight.BuildBrief(ctx, sections)
└─ learningsSection.Fetch()
└─ db.FindTopByQuality(domain, 10)The learningsSection has a priority of 30 (preflight/learnings.go:14). Scheduler and tracker are higher priority — so when the 6 KB session budget fills up, learnings get dropped first. This is intentional. An overdue scheduled job matters more to the next session than a three-month-old insight about Go compile times.
The quality ranking formula weighs recency:
quality_score * CASE
WHEN age < 30d THEN 1.0
WHEN age < 90d THEN 0.8
ELSE 0.5
ENDA high-quality old learning is worth less than a high-quality recent one. The system doesn't freeze the past as ground truth — it treats it as context that decays.
Five Learnings That Actually Landed
The database has 2,274 entries. Most of them are fine — useful notes about specific APIs, file paths, command flags. The ones worth looking at are the ones that changed something downstream.
learn_1770483276011286000 — "Use atomic.Int64 for counters shared across goroutines." This learning traced back to a debugging session on the event bus. The next time the bus was touched, the counter pattern was already in the session context. It's now at event/bus.go:21.
A note about phase objectives — "A phase agent without a file creation step can't prove it succeeded." This one came out of watching a research phase produce a narrative report and mark itself complete without any output file. It's now baked into the CLAUDE.md objective standard: "Success = file exists, every number traces to a command."
learn_1770483766201891000 — "A language that's 3× faster in execution produces roughly a 1.3% CLI speedup in a tool that's 98% I/O-bound." This came from a benchmarking session where I was questioning whether to rewrite parts of the orchestrator in Rust for the performance gains. The math said no. The decision to stay in Go happened partly because this learning was in context when we revisited it.
"executeWithSDK bypasses command building entirely" — This was a discovery from an agent session that switched between RUNTIME: cli and RUNTIME: sdk without understanding what changed under the hood. SDK phases call agent.Query() directly. CLI phases go through the full command builder. Different error surfaces, different timeouts, different retry behavior. The distinction now shows up in phase YAML choices.
"Sort Names() before registration" — A flaky test in persona selection was producing random ordering. The fix was at persona/personas.go:319-327. The learning captured the pattern: any system that maps over unordered data and caches the result will produce nondeterministic behavior across runs. Small finding. It's come up twice more in different contexts since.
Five examples out of 2,274. That's not a representative sample — it's the five that had the clearest downstream traces. The rest of the database is harder to evaluate precisely because good operational memory is invisible. If a learning prevented a decision that would have been wrong, there's no artifact showing that it worked.

The Four Things It Can't Capture
The pipeline is real. The blind spots are also real. There are four structural gaps that don't show up in the numbers.
Worker sessions are excluded by design. The 344 chunks came entirely from interactive sessions — my Claude Code conversations. Worker phases run inside ~/.alluka/worktrees/ and get skipped. This is correct: worker output goes through CaptureWithFocus in real time, which is more targeted than retrospective extraction. But it means that if a worker agent makes a decision that's interesting and doesn't surface it in its output markers, that decision is gone. Two learning pipelines, two coverage gaps.
Tacit correct decisions leave no signal. When something goes right without friction — the right tool picked, the right approach chosen, no retry needed — there's often nothing in the transcript to extract. Dream reads text. A session where I got the right answer immediately looks identical to a session where I got lucky. The database accumulates evidence of things that were hard, not things that were smooth. That's a bias in the corpus.
External context never enters the JSONL. I'll read a blog post, make a decision, come back to Claude Code. The reasoning that shaped the decision exists entirely outside the transcript. The transcript sees the output — the tool call, the file edit, the message — not the thinking that produced it. Dream extracts from what's there. Everything I thought before typing is invisible to it.
Cross-chunk causal reasoning is lost. Conversations get cut into token-bounded windows. A decision made in chunk 3 that directly responds to a problem introduced in chunk 1 looks unconnected when the chunks are processed independently. Dream processes each window as a standalone unit. Long-arc reasoning — the kind where you try something, it fails, you adjust over several turns, and the final approach is shaped entirely by the failures — gets fragmented. The learning extracted from chunk 3 won't know why it happened.
What the Cycle Actually Is
The dream cycle isn't a memory system in the way that phrase usually sounds. It's not a record of what happened. It's a distillation process — run across 250 sessions, producing 2,274 signals, filtered by quality score, delivered in 6 KB per session start.
The thing worth understanding is what that process is optimizing for. It's not completeness. A complete record of 250 sessions would be noise. It's extractability — what can a language model read from a conversation window and articulate as a durable, actionable insight? That selection pressure is real, and it has a shape: concrete over abstract, specific over general, recoverable over tacit.
The four blind spots aren't bugs. They're the edges of what text-based retrospective extraction can see. Worker phases are excluded because a different pipeline covers them. Tacit decisions are invisible because transcripts capture text, not intent. External context is missing because it was never written down. Cross-chunk reasoning is fragmented because windows have limits.
The question I don't have a clean answer to: how much of the most important stuff falls into those four categories? The 2,274 learnings are real and some of them are useful. But the things that aren't in the database — the smooth sessions, the outside reasoning, the long-arc decisions — might matter more. I don't know how to measure what's absent.
orchestrator dream run --since 24h runs nightly. The number keeps going up. I'm not sure yet whether going up is the same thing as getting better.