feat(runtime): mount state kernel and notice ledger into generated request scopes (#233) - #251
Conversation
… in the packed consumer proof
🦋 Changeset detectedLatest commit: 74d2e58 The changes in this PR will be included in the next version bump. This PR includes changesets to release 2 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
commit: |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 74d2e58fef
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| || lifetime === 'process' | ||
| || lifetime === 'workspace-durable' | ||
| || lifetime === 'external'; | ||
| if (id === undefined || id.trim() === '' || !accepted) { |
There was a problem hiding this comment.
Reject the notice ledger's reserved state ID
When src/state.ts declares the otherwise-valid ID @agent-bundle/runtime/agent-notice-ledger/v1, the generated owner opens both the project definition and the internal notice definition through the same driver under that ID. For process state, the memory driver can return the project store as the notice store; for durable state, both definitions address the same SQLite file. Notice operations—or state operations, depending on which open wins—then fail with schema/event errors, so this reserved ID needs to be rejected during extraction.
Useful? React with 👍 / 👎.
| || context.state !== undefined | ||
| || context.noticeLedger !== undefined |
There was a problem hiding this comment.
Mount each missing route-unit binding independently
When a route-unit test supplies only context.state, this condition skips the entire manifest mount and leaves agent().notices unavailable; supplying only context.noticeLedger similarly removes the generated state binding. Production generated routes mount both, so tests that override one binding cannot accurately exercise routes using the other. Preserve each caller-provided value while auto-mounting the independently missing binding.
Useful? React with 👍 / 👎.
Summary
Closes the generated-runtime mounting gap tracked by #233 (items 1 and 2) and the #99 audit finding: every generated invocation path now mounts a correctly-scoped state driver and notice ledger, so a compiled bundle's routes get working
(await agent()).stateand.noticeshandles instead of permanentunavailable.Mounting architecture
@agent-bundle/runtime/mountsubpath:createGeneratedRuntimeState({ definition, driver })owns the project state store plus the notice ledger (agentNoticeStateDefinition(lifetime)) over one driver, with lazy opens and typed-failing handles when the driver cannot open (honest degradation, never fabricated success). Never importsnode:sqlite— callers inject the driver.src/state.tsdefault-exportingdefineState({...}); the build statically extracts literalid/lifetime(parse-only, AB4818–AB4820 diagnostics;state: falseopt-out;externallifetime rejected for generated mounting v1).request/processlifetimes,node:sqlitedriver forworkspace-durablerooted at$AGENT_BUNDLE_PLUGIN_ROOT/state(artifact-root fallback). The MCP host process forwards full invocation identity (requestInvocation,host,workspace) so notice admission runs exactly once, in the render scope, idempotent per invocation id.createWarmFlightHostgrows optionalruntimeStateownership..agent-bundle/statefallback for package bins). Stateless projects emit zero state/ledger code.Proofs (per harness level)
renderRouteauto-mounts fresh isolated bindings per render (sqlite temp root for durable definitions); caller-suppliedcontext.statewins.<pluginRoot>/state/), and a notice published in spawn 1 is observed attempted by a thin-client event invocation (IPC socket) in spawn 2, rendered by the compiled event route../mountentry.Deferred (recorded on #233): kernel-contract budgets (item 3) and inspect/Workbench lifetime visibility (item 4);
external-lifetime generated mounting; app-configurable notice authorization policy.Test plan
pnpm typecheck,pnpm lintpnpm --filter @agent-bundle/runtime test(mount, warm-runtime, packaging boundaries)pnpm test:route-unit,pnpm test:projectionnode scripts/run-packed-tests.mjs— 23 passed, 0 failedRefs #233, #98, #99.