Skip to content

W2.B.4 — fanout reducer race test + deterministic merge#55

Draft
TimothyVang wants to merge 2 commits into
feat/W2.B.3-comprehension-mismatch-ledgerfrom
feat/W2.B.4-fanout-reducer-race
Draft

W2.B.4 — fanout reducer race test + deterministic merge#55
TimothyVang wants to merge 2 commits into
feat/W2.B.3-comprehension-mismatch-ledgerfrom
feat/W2.B.4-fanout-reducer-race

Conversation

@TimothyVang

Copy link
Copy Markdown
Owner

Summary

  • Lands tests/graph/test_fanout_race.py exercising the LangGraph fanout through the canonical Send-based parallel-edge idiom against a real compiled graph (no mocks).
  • 4 branches (vol_exec/hay_exec/pls_exec/mft_exec) each sleep 0-500ms and must merge in deterministic order; two runs with different RNG seeds must produce identical executor_results orderings (HMAC ledger chain reproducibility, ARCHITECTURE.md §2).
  • Restores the deterministic sort in verdict/graph/reducers.py after the W2.B.4 RED commit regressed it to a naive concat — the test catches the regression by failing on both wall-clock-race and pure-reducer paths.
  • Pure-reducer unit tests pin the contract independently: None handling, (branch_name, sequence_id) sort key, keyless items sort to tail in stable insertion order.
  • TDD: RED test(graph): RED — fanout reducer race test [W2.B.4] (3 fails) → GREEN feat(graph): reducer pattern for parallel-executor merge [W2.B.4] (31 pass).

Test plan

  • pytest tests/graph/test_fanout_race.py -v — 6 passed.
  • pytest tests/graph/ -v — 31 passed.
  • ruff check — clean.

Base

This PR targets feat/W2.B.3-comprehension-mismatch-ledger.

TimothyVang added 2 commits May 2, 2026 08:44
Adds tests/graph/test_fanout_race.py exercising the LangGraph fanout
through the canonical Send-based parallel-edge idiom:

- 4 branches (vol/hay/pls/mft_exec), each sleeping 0-500ms,
  must merge in DETERMINISTIC order (sorted by branch_name then
  sequence_id) so the HMAC ledger chain hashes to identical bytes
  across runs;
- two runs with different random seeds must produce identical
  executor_results orderings;
- no branch is silently dropped (ARCHITECTURE.md §1 empty-set rule);
- reducer is idempotent across .ainvoke() calls (no cross-run
  accumulator state).

Plus pure-reducer unit tests:
- None left/right -> []
- (branch_name, sequence_id) sort key
- keyless items sort to tail in stable insertion order.

This commit also REGRESSES verdict/graph/reducers.py to a naive
concat (no sort) so the test suite goes RED first per CLAUDE.md §3.7
TDD discipline. The W2.B.1 reducer was speculative-design; this
commit pins the contract via failing test, GREEN restores the
deterministic sort.
Restore the deterministic merge in verdict/graph/reducers.py:

- Sort key is (branch_name, sequence_id); items missing those keys
  use chr(0x10FFFF) so they sort to the tail in stable insertion order;
- Python's stable sort guarantees identical merged bytes regardless of
  branch completion timing;
- None-left/None-right are tolerated (first write, empty update);
- HMAC ledger chain reproducibility is preserved across runs even when
  wall-clock branch order differs (the failing case in the W2.B.4
  RED commit).

Tests: 31 passed (W2.B.1 + W2.B.2 + W2.B.3 + W2.B.4).
Ruff: clean.
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