3.8 KiB
Merman v1 spec: constraints with time
Merman v0 has time (paths played as keyframes) but untyped edges. The "harness / loop / graph" ladder has typed constraints but narrates time in prose. v1 is the union.
1. Edge types
v0: every edge means "possible transition". v1 adds a kind:
| kind | meaning | early-start test |
|---|---|---|
dep |
B's input is A's output; B cannot start before A passes its gate | "something breaks" |
seq |
drawn in this order but no data flows; a habit | "nothing breaks" |
return |
feedback edge: 🧪 → 🛠️ with EXPECTED/SAW/FENCE/DEAD-ENDS attached |
n/a |
rewrite |
an edge that only exists in G₁; the 🌱 shortcut |
n/a |
seq edges render dashed and do not block. Fork/join falls out: nodes with no dep between them run in parallel, and the animation shows it (two tokens leave 🔎 on the same tick). A seq edge is a bug report waiting to be filed.
2. Gates carry undo cost, not confidence
🛣️ and 🧪 nodes get a gate block:
gate:
undo: one-click | cleanup | none
needs: [green] | [green, trace, second-opinion] | [human]
one-clickships on green.cleanupneeds green + trace + an independent reviewer in its own context.nonehas no score. The only edge out is🚩👤. This is a constraint gadget: any path through it must assign the human variable.
The model may label a change ("touches auth"); code decides what the label unlocks, before the run starts. Confidence never appears in a gate.
3. Evidence ladder on 🧪
A verify node declares the weakest proof it accepts: deterministic > observable > independent > self-report. A loop that accepts self-report anywhere is a self-report loop. The playground should colour 🧪 by its floor.
4. Freeze
Once a node's output passes its gate it is read-only. In trace mode, a rerun re-enters only the failed node; frozen nodes stay lit and do not replay. v0 replays the whole path; v1 replays the diff.
5. Exits
A loop without exits is a cost leak. return edges get a budget and a cycle detector:
- green →
✅ - same SAW and same diff twice →
🚩👤(the agent changed nothing, not merely the world) - budget spent →
🚩👤
v0's DFS already caps revisits at 2 for 🛠️/🧪/🛣️/💬. That is a path-enumeration limit; v1 makes it a runtime exit with the same shape.
6. Lessons land on a layer
A 🌱 rewrite is typed by what it changes:
| failure | lesson becomes | layer |
|---|---|---|
| couldn't see X | new tool / read-only node | harness |
| retried a dead end | entry in DEAD ENDS |
harness (memory) |
| "fixed" with no reproducing test | new needs: on a gate |
loop |
| two audits overlapped | split rule in 🔎 |
graph |
A lesson that stays in a prompt is visibly not learned: it has no edge.
7. File format
One YAML (or JSON) per flow. Mermaid remains the editable projection, generated from it, never hand-edited.
nodes:
inspect: {e: "🔎"}
gate: {e: "🛣️", gate: {undo: cleanup, needs: [green, trace, second-opinion]}}
work: {e: "🛠️"}
verify: {e: "🧪", floor: deterministic}
andon: {e: "🚩👤"}
edges:
- [inspect, gate, dep]
- [gate, work, dep]
- [work, verify, dep]
- [verify, work, return, {budget: 3}]
- [verify, andon, dep]
Ladder, in Merman terms
| level | Merman |
|---|---|
| 1–2 harness | nodes (what can act at each vertex); DEAD ENDS as node memory |
| 3 check | 🧪 floor |
| 4 feedback | return edge payload |
| 5 shape | dep vs seq; fork/join |
| 6 gates | gate.undo; freeze |
| 7 learning | rewrite edges, G₀ → G₁ |
Harness = the nodes. Constraint graph = the edges. Flow = the tokens over time. Loop and gate are local properties of how a token moves through a vertex.