feat(#97): extend event vocabulary with ratify + supersede emit/replay (re-merge as rebase, supersedes #129)#132
Conversation
Wires the missing decision-status events into the existing JSONL + materializer pipeline so the shipped event vocabulary matches the v0 architecture description (decision_ratified, decision_superseded alongside the existing ingest/bind/link_commit events). Changes: - ledger/adapter.py: add `apply_ratify(decision_id, signoff)` and `apply_supersede(new_id, old_id, ...)` to SurrealDBLedgerAdapter. Both methods are idempotent so the materializer can replay them safely. They wrap the existing inline UPDATE + project + supersedes helpers — no behavioral change for solo mode. - events/team_adapter.py: add wrappers that emit `decision_ratified.completed` and `decision_superseded.completed` events before delegating to the inner adapter. Event payloads carry `canonical_id` (UUIDv5 from description + source_type + source_ref) so cross-author replay can resolve to the peer's local row even though SurrealDB-generated decision ids are per-DB. - events/materializer.py: replay cases for the two new event types. Each looks up the local decision row by canonical_id; warns and skips if not found (out-of-order replay across authors). - handlers/ratify.py: route through `ledger.apply_ratify` instead of inline UPDATE + project_decision_status + update_decision_status. Pre-write idempotency check (early return when state already matches) is unchanged. - handlers/resolve_collision.py: route through `ledger.apply_supersede` for the supersede branch. Edge creation + frozen-signoff merge moves into the adapter so it's reachable from replay. - ledger/queries.py: new `get_canonical_id(client, decision_id)` and `find_decision_by_canonical_id(client, canonical_id)` helpers. Tests: - tests/test_team_event_replay.py (new) — three round-trip tests: ratify, supersede (with edge replay), and ingest regression. Each ingests through team adapter A, then connects a fresh team adapter B pointing at the same JSONL log + a fresh memory:// inner DB and a fresh watermark. Asserts state in B matches what A wrote. - tests/test_preflight_id_plumbing.py — updated the ratify mock to match the new `ledger.apply_ratify` shape. Out of scope (deferred to future PRs): compliance_checked event (Phase 4 uses CHANGEFEED), CHANGEFEED extension to code_subject / subject_identity / binds_to / code_region (schema migration), SHA256 chain (strictly v1). Closes part of #97. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…_adapter The materializer imports the helper inline at the call site. The top-level import in team_adapter.py was leftover from an earlier draft and never used. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Run ruff format on the three files modified in this PR. No semantic change — purely whitespace/argument-split normalization to satisfy `ruff format --check .` in CI. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Per DEV_CYCLE §7, every user-visible change gets a CHANGELOG entry. This is an additive feature (new event types in the team-mode JSONL log), so it bumps to MINOR per §6.2. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Bicameral drift report — skippedNo To enable: add a |
Summary
Re-opens the v0.18.0 event vocabulary extension work for rebase-and-merge so the 4 original atomic commits land on `dev` as individually-cherry-pickable SHAs (instead of one opaque squash blob).
This is the same code as the previous PR #129 — no diff changes. Only the merge mechanics are different.
Commits (in order)
Why this re-merge
Original #129 squash-merged into `c233eb1`. Reverted in #131 (`b3d93d0`) so this replacement can land via rebase-and-merge. Net diff vs dev pre-revert is zero — same files, same content. Only the history shape changes from one opaque commit to four atomic ones.
Sequencing context
Linked issues
Refs #97 (already labeled `merged-to-dev`; staying open per RFC convention)
Test plan
Notes
🤖 Generated with Claude Code