Skip to content

fix(core): commit state before finalize publishes - #38983

Merged
kitlangton merged 1 commit into
v2from
state-event-ordering
Jul 27, 2026
Merged

fix(core): commit state before finalize publishes#38983
kitlangton merged 1 commit into
v2from
state-event-ordering

Conversation

@kitlangton

Copy link
Copy Markdown
Contributor

What

State update events now act as read barriers: a subscriber that observes a domain update event (command.updated, agent.updated, catalog.updated, ...) and immediately refetches is guaranteed to see the rebuilt state.

Fixes #37422.

Before / After

Before: State.commit ran finalize (where every domain publishes its update event) before assigning the rebuilt state:

  1. A command file changes and command state rebuilds.
  2. finalize publishes command.updated.
  3. A subscriber receives the event and calls command.list().
  4. The swap state = next has not happened yet, so the subscriber reads the old commands and never refetches again.

After: the rebuilt state is assigned first, then finalize runs. Any consumer reading on the event observes committed state.

How

  • packages/core/src/state.tsState.commit swaps state = next before invoking finalize, and the finalize doc comment now states the read-barrier contract.
  • packages/core/test/state.test.ts — new test commits rebuilt state before finalize runs, written and confirmed red against the old ordering.

All seven finalize consumers were audited (agent, command, catalog, skill, websearch, integration, reference): six only publish their update event; reference rebuilds its derived materialized map and then publishes, so its event also still fires after both the swap and the rebuild. None rely on pre-commit ordering.

Scope

First slice of the config source reload plan (docs/design/config-source-reload.md on the config-source-reload branch). Deliberately excluded, coming as separate PRs:

Testing

bun test test/state.test.ts                      # 6 pass (new test red before fix)
bun test test/{agent,command,catalog,skill,websearch,reference,integration}.test.ts \
         test/config/{agent,command}.test.ts     # 58 pass

bun typecheck in packages/core reports only pre-existing sdk-drift diagnostics also present at the base commit; none reference state.ts.

@kitlangton
kitlangton force-pushed the state-event-ordering branch from 715ea9b to 196a03f Compare July 27, 2026 15:03
@kitlangton

Copy link
Copy Markdown
Contributor Author

Unit checks fail with Unbound layer node: @opencode/Location in session-runner/codemode/plugin-hooks — inherited from 8db7487 (tool architecture consolidation), which introduced Tool.node -> Image.node -> Config.node -> Location.node and has been red on v2 since it landed. Verified locally at the base tip with this PR's change reverted: identical 25 failures. The state tests and all 58 State-consumer tests pass with this change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant