feat(simulator): capture agent-to-agent message bodies in the run ledger - #981
Merged
Conversation
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Workflows to automatically generate PRs for you. |
chughtapan
force-pushed
the
feat/ledger-message-bodies
branch
from
August 6, 2026 18:58
55504ef to
1eaf4b6
Compare
chughtapan
force-pushed
the
feat/ledger-message-bodies
branch
from
August 6, 2026 19:07
af40346 to
1eaf4b6
Compare
The post-stop reader now selects the plaintext parts column and the commit time the router already stores, and router-message-committed/v1 carries them: the run ledger is the run's transcript. The event's content-blind variant is deleted along with its guard test — the simulator exists to record what agents said, and a router that cannot see plaintext has no business producing this event. Ledgers written before this change do not decode under the new schema; accepted. Evals needed only fixture updates: its commit corroboration counts records per message key and never read the payload. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
chughtapan
force-pushed
the
feat/ledger-message-bodies
branch
from
August 6, 2026 21:08
1eaf4b6 to
b03f975
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Every simulator run now records what the agents actually said to each other — unconditionally, with no flag to forget to set.
CommittedRouterMessage, the router stop-report projection, widens from commit identity to identity plus the plaintextparts(composed from@moltzap/protocol/message, so bodies cannot drift from the wire contract) andcreatedAtMillis. The PGlite reader selects the two new columns from the message store the server already writes.Each durable commit then contributes two adjacent ledger records:
moltzap.router-message-committed/v1— unchanged, its exact four identity fieldsmoltzap.router-message-body/v1— new sibling carrying the contentWhy two events instead of one wider event
The commitment event is the evidence that also works against a content-blind router, and
@moltzap/evalscorroborates endpoint testimony against it by identity. Widening it in place would have made old and new ledgers incomparable and made the commitment unproducible by a router that cannot see plaintext. Keeping identity and content in separate tags leaves the commitment byte-identical, and its existing content-blind guard test is untouched.RouterMessageCommittedtherefore spells its four fields out rather than spreadingCommittedRouterMessage.fields, which now carries plaintext.partsis required onCommittedRouterMessagerather than optional: that is a deliberate type-level commitment that only a plaintext-visible router can produce this projection. A content-blind or E2EE router needs a stop-report v2, not a sometimes-absent field.Ledger reader: equality → coverage
Adding a tag to the core catalog would have made every previously written ledger unreadable under exact tag-set equality.
verifyCatalognow requires the manifest to be a subset of the reader catalog: a reader may declare tags a historical manifest never wrote, but a reader missing a tag the manifest claims still fails withLedgerCatalogMismatch.Because a wider reader can now decode records the ledger never declared it would contain, a post-decode guard keeps the manifest authoritative over its own records, failing with the new
event-outside-manifestreason.Scope
packages/simulatorsources and tests only.packages/protocol,server,client, andevalssources are untouched — evals composescoreEvents, so it picks up the new tag automatically, and itsinstanceof RouterMessageCommittedprojection is unaffected by the sibling event.packages/simulator/src/MODULE.mdand itsdocs/modules/**twin are mechanical typedoc output frompnpm nx run-many -t docs:generate.Tests
events/core.test.ts— round-trips the new tag with parts; rejects a body event without parts. Content-blind guard untouched.network/server/messages.test.ts— rewritten: its fixture header pinned "no payload columns" as the invariant, and that deliberately flips. Adds body/timestamp reads in sequence order and a malformed-parts rejection.run/router.test.ts— asserts the interleaved[committed, body, committed, body]record order, that encoded commitments carry nopartskey, and that a failed body append still lands as router-stop evidence.ledger/append.test.ts— manifest ⊂ reader opens; reader missing a manifest tag fails; a record outside the manifest fails.Gates:
pnpm check,pnpm test, andpnpm nx run-many -t docs:generate(clean tree after) all green.🤖 Generated with Claude Code