Skip to content

fix(reactor): merge causal wake references across fan-in and in-flight coalescing - #9

Open
Adityakk9031 wants to merge 1 commit into
openprose:mainfrom
Adityakk9031:fix/reconciler-wake-clobbering
Open

fix(reactor): merge causal wake references across fan-in and in-flight coalescing#9
Adityakk9031 wants to merge 1 commit into
openprose:mainfrom
Adityakk9031:fix/reconciler-wake-clobbering

Conversation

@Adityakk9031

Copy link
Copy Markdown

Overview

Fixes a critical flaw in the reconciler where multiple wake events targeting the same downstream node clobbered each other, resulting in the permanent erasure of causal provenance references (wake.refs) from the immutable ledger and rendering prompt context ("waking receipt refs") blind to preceding producers.

Problem & Architectural Invariant

According to SHAPES.md §1 and spec/02-ReactorHarness.md:

A Wake is { source, refs } where refs are the content addresses of the upstream receipt(s) (input), or of the synthetic self/external receipt (self / external).

In fan-in/diamond topology merges (e.g. $P_1 \to S$ and $P_2 \to S$) or concurrent in-flight renders, when multiple wakes are delivered to the same node:

  1. In startFrontier.commit: wakeFor.set(target, p.wake) unconditionally overwrote any previous producer's wake for target.
  2. In startFrontier: iterating initial seeds unconditionally overwrote duplicate seed wakes for the same node.
  3. In reconcile and reconcileAsync: state.pendingWake = wake unconditionally overwrote any prior coalesced wakes that arrived while a render was in flight.

As a result, downstream receipts were committed with only the last producer's receipt reference in wake.refs. The causal trail of preceding producers was severed from the ledger, and composeWakeHeader injected incomplete pointers into LLM agent prompts.

Proposed Changes

  1. packages/reactor/src/sdk/wake.ts:
    • Implemented and exported mergeWakes(existing: Wake, incoming: Wake): Wake.
    • Combines causal refs via an order-preserving, deduplicated union (Set).
    • Resolves source precedence (external > input > self).
  2. packages/reactor/src/reactor/index.ts:
    • Updated startFrontier to merge duplicate initial seed wakes.
    • Updated startFrontier.commit to merge propagated wakes into wakeFor.
    • Updated sync reconcile and async reconcileAsync single-flight coalescing to merge in-flight wakes into state.pendingWake.
  3. packages/reactor/src/index.ts & packages/reactor/src/sdk/index.ts:
    • Exported mergeWakes as part of the public @openprose/reactor API.
  4. packages/reactor/src/reactor/__tests__/wake-merge.test.ts:
    • Added unit tests for mergeWakes (order, deduplication, source precedence, freezing).
    • Added integration test proving multi-producer fan-in preserves all upstream receipt refs in the downstream receipt.
    • Added integration test proving multiple mid-render wakes merge all causal refs into the follow-up render's receipt.

Verification

  • Unit tests in wake-merge.test.ts (5/5 passed).
  • Reconciler and async reconciler suites (46/46 passed).
  • Offline eval harness suite (10/10 passed).

@Adityakk9031

Copy link
Copy Markdown
Author

@josemontesdeoca have a look

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant