feat: wire sessionId alongside instanceId on the trace wire (accept-only) - #347
Closed
EdwardIrby wants to merge 1 commit into
Closed
EdwardIrby wants to merge 1 commit into
EdwardIrby wants to merge 1 commit into
Conversation
The engine self-mints `instanceId = ueid('bp_')` and stamps it on every
trace. With an ACP ingress landing later, the host owns session identity
policy (mints on `session/new`, passes a client's old id on `session/load`),
so the engine must ACCEPT a host-supplied session id — it never mints one
and never returns ids. No rename: the two ids are separate axes and both
live on the wire.
- `TraceBase` gains `sessionId: string` alongside `instanceId`; a new
exported `TraceBaseSchema` is the one home for the trace wire's common
shape, so per-kind validators derive from it instead of hand-mirroring.
- `behavioral()` gains `{ sessionId?: string }`; the frozen return object
is unchanged. Session id is computed once at factory time
(`options?.sessionId ?? instanceId`) and stamped on every trace next to
`instanceId`; `resumePendingThreadsForSelectedEvent` stamps it on
interrupt traces too.
- The frontier faculty speaks the same wire with no drift: replay/explore/
verify inputs accept `sessionId` (AJV `nullable`, defaulting to the
`instanceId`), and every synthetic trace it builds (frontier, selection,
deadlock) carries both ids.
- `serve.ts`/`trace-consumer.ts` are pass-through only — no construction
sites existed in production code; only spec fixtures gained the field.
- `skills/behavioral/references/behavioral.md` factory signature updated.
Validation: `bun --bun tsc --noEmit` plus the behavioral, frontier
faculty, and cli serve/trace-consumer suites (211 specs).
| export const behavioral = (options?: { sessionId?: string }) => { | ||
| const instanceId = ueid('bp_') | ||
| /** @internal Host session identity — accepted at factory time, never minted. */ | ||
| const sessionId = options?.sessionId ?? instanceId |
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.
Context
The engine self-mints
instanceId = ueid('bp_')and stamps it on every trace viaTraceBase. An ACP ingress is landing later; the ACP host owns session identity policy (mints onsession/new, passes a client's old id onsession/load), so the engine must ACCEPT a host-supplied session id — it never mints one and never returns ids. Decision: no rename ofinstanceId; the two ids are separate axes and both live on the wire.Summary
TraceBase(src/behavioral/behavioral.types.ts) gainssessionId: stringalongsideinstanceId, with doc comments describing the two-axis trace wire. A new exportedTraceBaseSchemais the one home for the trace wire's common shape; per-kind trace validators derive from it (src/behavioral/tests/schemas.spec.ts) instead of hand-mirroring.behavioral()(src/behavioral/behavioral.ts) gains an optional{ sessionId?: string }options param;sessionId = options?.sessionId ?? instanceIdis computed once at factory time and stamped on everysendTracecall (step, pending_bids, frontier, deadlock, idle, thread_added, add_thread_error, trigger_error, transform, transform_error, selection, interrupt). The frozen return object is unchanged — no ids are returned.resumePendingThreadsForSelectedEvent(src/behavioral/behavioral.utils.ts) takes and stampssessionIdon interrupt traces.src/faculties/frontier/faculty.ts) — same treatment, no schema drift withTraceBase: replay/explore/verify inputs accept optionalsessionId(declared in all three AJV input schemas,nullable), defaulting to theinstanceId;replayToFrontierRaw/exploreFrontiersRawthread it through, and every synthetic trace they build (frontier, selection, deadlock) carries both ids.resumePendingThreadsForSelectedEventreceives it for interrupt traces.src/cli/serve.ts/src/cli/trace-consumer.tsare pass-through only — no production code constructsTraceobjects by hand (verified;redactTraceclones). Only spec fixtures gained the field (trace-consumer.spec.ts,serve.spec.ts).skills/behavioral/references/behavioral.mdfactory signature corrected tobehavioral({ sessionId?: string }).Changed Files
src/behavioral/behavioral.types.ts—TraceBase.sessionId+TraceBaseSchemasrc/behavioral/behavioral.ts— options param, factory-time default, stampingsrc/behavioral/behavioral.utils.ts— interrupt trace stampingsrc/faculties/frontier/faculty.ts— input types/schemas + synthetic trace stampingsrc/behavioral/tests/session-id.spec.ts— new (both branches: host-supplied + default)src/behavioral/tests/schemas.spec.ts— validator derived fromTraceBaseSchema, rejects missingsessionIdsrc/cli/tests/trace-consumer.spec.ts,src/cli/tests/serve.spec.ts— construction-site fixturessrc/faculties/frontier/tests/faculty.spec.ts— boundary test for sessionId stamping + defaultingskills/behavioral/references/behavioral.md— doc syncKnown Failures / Drift
None.
bun --bun tsc --noEmitclean; behavioral (152), frontier faculty (40), and cli serve/trace-consumer suites pass (211 specs total).Review Notes / Residual Risks
behavioral({ sessionId })) or onsession/loadby constructing a fresh program with the client's id.TraceBaseSchemais a plain-const schema (notJSONSchemaType<T>-cast) because it describes the shared trace prefix, not a complete wire event; per-kind validators extend it with the discriminatingkind/stepconstraints, asschemas.spec.tsdemonstrates.b-program.ts/serve.tsyet — deliberately pass-through only per the task scope.