Context
Operator direction (2026-07-05): close the planning gap on NL transactions. The gap, verified live today: the undo/redo transaction machinery is fully shipped (the #9848 wave — src/ai/TransactionService.mjs, the begin/commit/abort_transaction + undo / redo / list_transactions tools, e2e proofs #13286 / #13306), and its own module doc records the converged design as "in-memory now by the converged design, persistence a later slice — the active-vs-archive split" — but that later slice was never ticketed. Nothing in open planning turns a committed transaction into a durable artifact.
This is the carrier for the operator's product direction recorded in the #13349 supersession (comment 4884691993): agents create via NL, and the harness keeps what they build — "blueprints or state permutations for the harness itself," saved outputs without any schema funnel.
The Problem
An agent builds live UI through the Neural Link (call_method(parent, 'add', [config]) is the agent creation primitive per #13376), inside transactions, with undo/redo — and at session end it all evaporates: the per-writer stack is in-heap and the disconnect sweep (#13282) tears down active state by design. There is no way to save a build, survive a reload, re-materialize it, or hand it to the fleet manager as an artifact. The superseded constrained-blueprint funnel (#14644, closed) tried to solve this by inventing a blueprint format + schema registry — wrong by construction. The right format already exists and is enforced by the platform itself.
The Architectural Reality
src/ai/TransactionService.mjs — per-writer (agentId, sessionId)-keyed in-heap stacks; lifecycle open → committed → undone with redo re-entry; every op is a {forward, reverse} pair of data-only JSON tool-descriptors, and cloneOp THROWS on a smuggled function/class reference — the Neural Link wire boundary is the format guarantee. Ops carry originWriter provenance + label; named transactions exist.
- Undo's established semantics: reverse ops are re-dispatched and re-enforced as the current requester (
Neo.ai.admitWrite path) — the enforcement model for replay already exists; nothing new is trusted.
- The forward-only audit side already crosses to the Brain:
nl_action_log / NL_ACTION_SEQUENCE nodes land in the graph, consumed by ai/daemons/orchestrator/services/DreamService.mjs — precedent for durable, Brain-side records of NL activity.
#13376 (parent epic, the NL write-surface home) records the ceiling honestly: logic cannot cross the wire — which means an archived transaction is a data-only permutation of REGISTERED classes by construction. That is the safety story, complete, with zero added gates.
#14783 (capability matrix, PR #14817 in flight) carries "transaction participation" per op and requires v13.2+ gaps to be filed as leaves — this ticket is that filing for the archive/replay gap.
Structure evidence: live reads of src/ai/TransactionService.mjs, src/ai/Client.mjs, ai/services/neural-link/ConnectionService.mjs, and the #9848-wave ticket set, 2026-07-05 (owning-folder precedent: src/ai/ service siblings).
The Fix — one vertical slice (walking skeleton, no wave)
- Archive (
save_transaction {txId, name}): an explicit NL verb persists a COMMITTED transaction as a durable record — {archiveId, name, ops[{forward, reverse, label, sequenceId}], originWriter, committedAt, archivedAt}. Durable home: recommended Brain-side via the Bridge, adjacent to the nl_action_log precedent (criteria: survives browser storage wipes, queryable by the fleet manager, visible to the Dream pipeline); the implementer settles the exact store WITH recorded rationale in the PR if the recommendation doesn't survive contact. Explicit save only — auto-archival policy/retention is out of scope.
- Replay (
replay_transaction {archiveId}): forward ops re-dispatch through the STANDARD dispatch path on the current session, re-enforced as the current requester (undo's existing trust semantics) — and the replay lands as a NEW live transaction, so a replayed build is itself undoable.
- Matrix wiring: both verbs enter the
#14783 capability matrix with contracts + firewall posture (composition-class verbs; generated-payload-drivable per the firewall column).
Contract Ledger
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback |
Docs |
Evidence |
save_transaction (NEW NL verb) |
#13349 supersession + TransactionService's recorded active-vs-archive design |
Committed tx → durable archive record |
Refuses on non-committed / unknown txId; data-only guard re-runs on serialize |
#14783 matrix row + tool description |
AC e2e below |
replay_transaction (NEW NL verb) |
Same + undo's re-dispatch-re-enforce semantics |
Archive → live build as a NEW transaction |
Full admitWrite enforcement per op; partial-failure aborts the replay tx |
Same |
AC e2e below |
TransactionService in-heap stack |
Existing (#13230) |
UNCHANGED — active authority stays in-heap; archive is a separate store (the active-vs-archive split) |
n/a |
Module JSDoc already records the split |
Module doc line quoted above |
Decision Record impact
aligned-with ADR 0021 (extended-NL multi-writer write enforcement — replay ops are live writes under full enforcement) · aligned-with the #13349 supersession record (capability-first; the wire is the format; no schema registry).
Acceptance Criteria
Out of Scope
- Any browse/gallery UI for saved builds (fleet-manager surface — design-led,
#14805/#14807 direction, later).
- Sharing/export, diffing archives, auto-archival, retention policy.
- The conversational chat surface (the post-
#14828 re-planning owns it).
- Extending in-heap stack lifetime — active and archive stay distinct authorities per the recorded split.
Avoided Traps
- No blueprint format invention, no schema registry — the superseded funnel's mistake (
#13349 ruling). The wire boundary (configs are data, functions throw at cloneOp) IS the format contract.
- No enforcement bypass on replay — replayed ops are live writes; the moment replay skips
admitWrite it becomes a privileged side-channel.
- No gate additions — per the recorded rule: a constraint must name the NEW risk it closes beyond the platform boundary; this slice adds capability (persistence + replay) and reuses existing enforcement, adding zero gates.
Related
Parent: #13376 (NL write-surface epic — native link set after creation). #14783 / PR #14817 (matrix; this files the archive/replay gap the matrix names). #13349 comment 4884691993 (the save-outputs direction). #9848 wave: #13230 / #13257 / #13304 / #13326 / #13282 / #13286 / #13306 (the shipped active half). Closed #14766 (the goal's previous wrong-shaped carrier).
Live latest-open sweep: latest 20 open issues checked 2026-07-05T04:33Z, no equivalent found; A2A in-flight scan clean (newest message 04:08Z, unrelated scope).
Origin Session ID: b9b95ac6-42f5-47a3-b58f-6071f79657e8
Retrieval Hint: "NL transaction archive replay save-outputs slice" · query_raw_memories("transaction persistence active-vs-archive split")
Authored by Mnemosyne (Claude Fable 5, Claude Code).
Context
Operator direction (2026-07-05): close the planning gap on NL transactions. The gap, verified live today: the undo/redo transaction machinery is fully shipped (the
#9848wave —src/ai/TransactionService.mjs, thebegin/commit/abort_transaction+undo/redo/list_transactionstools, e2e proofs#13286/#13306), and its own module doc records the converged design as "in-memory now by the converged design, persistence a later slice — the active-vs-archive split" — but that later slice was never ticketed. Nothing in open planning turns a committed transaction into a durable artifact.This is the carrier for the operator's product direction recorded in the
#13349supersession (comment 4884691993): agents create via NL, and the harness keeps what they build — "blueprints or state permutations for the harness itself," saved outputs without any schema funnel.The Problem
An agent builds live UI through the Neural Link (
call_method(parent, 'add', [config])is the agent creation primitive per#13376), inside transactions, with undo/redo — and at session end it all evaporates: the per-writer stack is in-heap and the disconnect sweep (#13282) tears down active state by design. There is no way to save a build, survive a reload, re-materialize it, or hand it to the fleet manager as an artifact. The superseded constrained-blueprint funnel (#14644, closed) tried to solve this by inventing a blueprint format + schema registry — wrong by construction. The right format already exists and is enforced by the platform itself.The Architectural Reality
src/ai/TransactionService.mjs— per-writer(agentId, sessionId)-keyed in-heap stacks; lifecycleopen → committed → undonewith redo re-entry; every op is a{forward, reverse}pair of data-only JSON tool-descriptors, andcloneOpTHROWS on a smuggled function/class reference — the Neural Link wire boundary is the format guarantee. Ops carryoriginWriterprovenance +label; named transactions exist.Neo.ai.admitWritepath) — the enforcement model for replay already exists; nothing new is trusted.nl_action_log/NL_ACTION_SEQUENCEnodes land in the graph, consumed byai/daemons/orchestrator/services/DreamService.mjs— precedent for durable, Brain-side records of NL activity.#13376(parent epic, the NL write-surface home) records the ceiling honestly: logic cannot cross the wire — which means an archived transaction is a data-only permutation of REGISTERED classes by construction. That is the safety story, complete, with zero added gates.#14783(capability matrix, PR#14817in flight) carries "transaction participation" per op and requires v13.2+ gaps to be filed as leaves — this ticket is that filing for the archive/replay gap.Structure evidence: live reads of
src/ai/TransactionService.mjs,src/ai/Client.mjs,ai/services/neural-link/ConnectionService.mjs, and the#9848-wave ticket set, 2026-07-05 (owning-folder precedent:src/ai/service siblings).The Fix — one vertical slice (walking skeleton, no wave)
save_transaction {txId, name}): an explicit NL verb persists a COMMITTED transaction as a durable record —{archiveId, name, ops[{forward, reverse, label, sequenceId}], originWriter, committedAt, archivedAt}. Durable home: recommended Brain-side via the Bridge, adjacent to thenl_action_logprecedent (criteria: survives browser storage wipes, queryable by the fleet manager, visible to the Dream pipeline); the implementer settles the exact store WITH recorded rationale in the PR if the recommendation doesn't survive contact. Explicit save only — auto-archival policy/retention is out of scope.replay_transaction {archiveId}): forward ops re-dispatch through the STANDARD dispatch path on the current session, re-enforced as the current requester (undo's existing trust semantics) — and the replay lands as a NEW live transaction, so a replayed build is itself undoable.#14783capability matrix with contracts + firewall posture (composition-class verbs; generated-payload-drivable per the firewall column).Contract Ledger
save_transaction(NEW NL verb)#13349supersession + TransactionService's recorded active-vs-archive design#14783matrix row + tool descriptionreplay_transaction(NEW NL verb)admitWriteenforcement per op; partial-failure aborts the replay txTransactionServicein-heap stack#13230)Decision Record impact
aligned-with ADR 0021 (extended-NL multi-writer write enforcement — replay ops are live writes under full enforcement) · aligned-with the
#13349supersession record (capability-first; the wire is the format; no schema registry).Acceptance Criteria
save_transactionpersists a committed transaction; the record survives session end AND the disconnect sweep (the sweep purges ACTIVE state only — falsifier test).replay_transactionre-materializes the build on a FRESH session through standard dispatch; every op passesadmitWrite; the result is a new committed transaction thatundocleanly reverts.cloneOpguard class to the archive boundary).originWriter,committedAt) +archivedAtstamped; replay records both the archive source and the new writer.save_transaction→ page reload (fresh session) →replay_transaction→ the same component-tree shape is live — the reload-survival goal the closed#14766carried, now NL-native.#14783matrix with transaction-participation + firewall columns.Out of Scope
#14805/#14807direction, later).#14828re-planning owns it).Avoided Traps
#13349ruling). The wire boundary (configs are data, functions throw atcloneOp) IS the format contract.admitWriteit becomes a privileged side-channel.Related
Parent:
#13376(NL write-surface epic — native link set after creation).#14783/ PR#14817(matrix; this files the archive/replay gap the matrix names).#13349comment 4884691993 (the save-outputs direction).#9848wave:#13230/#13257/#13304/#13326/#13282/#13286/#13306(the shipped active half). Closed#14766(the goal's previous wrong-shaped carrier).Live latest-open sweep: latest 20 open issues checked 2026-07-05T04:33Z, no equivalent found; A2A in-flight scan clean (newest message 04:08Z, unrelated scope).
Origin Session ID: b9b95ac6-42f5-47a3-b58f-6071f79657e8 Retrieval Hint: "NL transaction archive replay save-outputs slice" ·
query_raw_memories("transaction persistence active-vs-archive split")Authored by Mnemosyne (Claude Fable 5, Claude Code).