mcp: project-plan — Synthesis Layer
This commit is contained in:
parent
36a4c95efb
commit
093f66563c
71
Sources/Dev/synthesis-layer.md
Normal file
71
Sources/Dev/synthesis-layer.md
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
---
|
||||||
|
created: '2026-05-30'
|
||||||
|
path: Sources/Dev
|
||||||
|
project: synthesis-layer
|
||||||
|
tags:
|
||||||
|
- mcp
|
||||||
|
- dispatch
|
||||||
|
- lovebug
|
||||||
|
- claude-code
|
||||||
|
- automation
|
||||||
|
type: project-plan
|
||||||
|
---
|
||||||
|
|
||||||
|
# Synthesis Layer
|
||||||
|
|
||||||
|
Short-term memory for agent orchestration. The execution journal is the durable long-term record (immutable, complete, append-only). The synthesis layer is the small, bounded, fast working view that the harness actually reads when deciding the next move. Workers write journal entries; the synthesis layer is how those entries become consumable context for Lovebug without bloating Lovebug's own window.
|
||||||
|
|
||||||
|
This plan is **not fully baked** — captured here so the design discussion doesn't get lost. Iteration expected. Companion to `execution-journal`.
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
|
||||||
|
Give the harness (Lovebug) a bounded, current, queryable view of project state that:
|
||||||
|
|
||||||
|
- Stays small regardless of how long a project runs — the harness's per-cycle context cost is roughly constant whether step 3 or step 50.
|
||||||
|
- Carries forward the things that matter (active constraints, rule-outs, current state) so a new actor doesn't re-propose what's already been tried and rejected.
|
||||||
|
- Is recoverable from the journal — the synthesis layer can be lossy *safely* because the journal is the system of record.
|
||||||
|
- Doesn't require Lovebug to read raw worker output. Ever. Lovebug consumes conclusions; the synthesis layer produces them.
|
||||||
|
|
||||||
|
## Locked Decisions
|
||||||
|
|
||||||
|
- **Long-term / short-term split.** Journal = long-term (durable, complete, immutable). Synthesis layer = short-term (small, current, volatile). The harness reads short-term; nobody holds long-term in context. The journal is queryable on disk but not normally read in the hot path.
|
||||||
|
- **Per-step summaries, not cumulative.** Each summary describes its own step and is immutable once written. No fold-forward, no rewriting, no carry-forward discipline. The "history" is the ordered list itself. Trades read-time cost (read several summaries) for write-time safety (no drift surface inside any summary).
|
||||||
|
- **Why not cumulative.** A cumulative rolling summary introduces per-step drift at the synthesis pass and the recovery story is circular — "regenerate from the journal" is itself the hard synthesis problem we don't fully trust. Per-step summaries sidestep this: no artifact gets rewritten, so no artifact can drift.
|
||||||
|
- **Synthesis is deferred until the list is long enough to need compression.** At current scope (small projects, ~10–30 steps), reading the full list of per-step summaries is fine — token budget is not the constraint. A compression layer is added *later*, when project length forces it, with real data about what's worth keeping. Premature compression is a synthesis-prompt-design problem we don't have yet.
|
||||||
|
- **Synthesizer (when it eventually exists) is a stateless function over durable state.** Same pattern as every other layer in the stack. Spawn → read inputs → emit output → terminate. Never accumulates context across invocations.
|
||||||
|
- **Drift is bounded, not eliminated.** 100% accurate history is not the goal; it's never been a thing. Good checks and balances anchored to the journal (immutable reference) are. Bounded sawtooth via mechanical comparison against ground truth, not unbounded ramp.
|
||||||
|
|
||||||
|
## Open Items
|
||||||
|
|
||||||
|
- **What exactly is a per-step summary?** Probably very close to the worker's own structured `handoff` field from the journal — goal, current state, next step, ruled-out + why. The synthesis layer may collapse to "lightly normalize the worker's handoff and append to a list" for v1. If so, no separate synthesizer agent is needed yet — the worker's handoff *is* the summary.
|
||||||
|
- **When does a real synthesizer get built?** Trigger: the per-step list grows past the point where reading it all on every harness cycle is comfortable. At that point, add a compression pass that produces a bounded rolling brief from the list. Defer until it's a real problem with real numbers.
|
||||||
|
- **Read shape for the harness.** `get_project_summaries(slug)` returning the ordered list, newest-first, with optional limit. Probably the same MCP surface as the journal — synthesis layer may just be a view over journal handoff fields rather than a separate table. To be decided.
|
||||||
|
- **Drift detection for v2 (cumulative).** If/when compression is added, drift checks are mechanical and anchor to the journal: structural invariants (active rule-outs must persist unless explicitly reversed), periodic reconciliation (rebuild from journal, diff against rolling brief), harness sanity checks (claimed task done → testable plan condition holds). None of these are "another agent's second opinion" — they're measurements against immutable references. Not building this for v1; documenting it so we don't have to re-derive when we do.
|
||||||
|
- **Speed/volume asymmetry.** The reason this *feels* harder than human institutional drift is correction-loop tempo, not novelty. Agents can compound 50 generations of lossy retelling in an afternoon while the correction loop (Travis reading on Tuesday) is slow. Implication: checks need to run automatically and frequently *if* we ever go cumulative. Another reason per-step summaries are the right v1.
|
||||||
|
|
||||||
|
## Phases
|
||||||
|
|
||||||
|
### Phase 1 — Trivial synthesis (v1)
|
||||||
|
- [ ] Confirm that the worker's structured `handoff` from the journal can serve directly as the per-step summary. If yes, no new layer is built — the synthesis layer is a *read pattern* over the journal, not a separate write path.
|
||||||
|
- [ ] Define the MCP read: `get_project_summaries(slug, limit?, order=desc)` — ordered list of handoffs across the project. Newest-first by default.
|
||||||
|
- [ ] Harness reads the summary list + immutable plan to decide the next step. No synthesizer agent in this phase.
|
||||||
|
|
||||||
|
### Phase 2 — Compression (only when triggered)
|
||||||
|
- [ ] Trigger condition: summary list is long enough that reading it all on every harness cycle is uncomfortable. Define "uncomfortable" with real numbers when we get there, not now.
|
||||||
|
- [ ] Design the synthesizer agent: stateless, spawns per harness cycle (or per N worker completions), reads recent summaries, emits a bounded rolling brief, terminates.
|
||||||
|
- [ ] Open question deferred to this phase: cumulative rolling brief vs. windowed (last-N summaries compressed). Cumulative is smaller-steady-state but reintroduces drift; windowed is simpler but doesn't bound size as tightly. Decide with data.
|
||||||
|
|
||||||
|
### Phase 3 — Drift detection (only if Phase 2 is cumulative)
|
||||||
|
- [ ] Structural invariant check: active rule-outs from prior brief persist in current brief unless a journal entry explicitly reverses them. Mechanical, deterministic.
|
||||||
|
- [ ] Periodic reconciliation: regenerate brief from journal, diff against rolling brief, flag divergence.
|
||||||
|
- [ ] Anchor every check to the journal (immutable) or the plan (immutable). Never anchor a drift check to another synthesis pass — that's the regress.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
**Why this is a separate plan from `execution-journal`.** The journal is the ground-truth store. The synthesis layer is the consumption pattern on top. Journal is build-now; synthesis layer is build-as-needed. Keeping them separate prevents the journal scope from creeping into "and also a synthesizer" when the journal stands on its own.
|
||||||
|
|
||||||
|
**On the "history" framing.** The instinct that motivated this whole thread — "doomed to repeat history if you don't know it" — resolves cleanly under per-step summaries: history *is* the list, no information is dropped, the harness can read as far back as it needs. Under cumulative summaries the same instinct produces a real problem (silently dropped rule-outs cause re-proposal) which is why cumulative needs the carry-forward discipline + drift checks. Per-step is the simpler answer that doesn't trade away the safety property.
|
||||||
|
|
||||||
|
**On scope.** This whole discussion was over-scoped relative to current project size. At ~10–30 steps per project, the simple read-the-whole-list approach is correct and finishes the problem. The deeper analysis (cumulative summaries, drift detection, synthesizer regress) is captured here so when scale forces a revisit, the reasoning isn't redone from scratch — and so the simple v1 is "simple because we reasoned to it," not "simple because we didn't look."
|
||||||
|
|
||||||
|
**Companion plan.** See `execution-journal` for the durable-store side of this architecture. The two were discussed together and split intentionally — journal is concrete and near-term; synthesis is a pattern that may or may not need its own agent depending on how the journal-handoff field shapes up.
|
||||||
Loading…
Reference in New Issue
Block a user