Skip to content

ROT-3: Opposite-provider review and SHA-bound merge provenance #8

Description

@williacj

Migrated from williacj/cowrite#937 (opened 2026-07-31).
Moved 2026-08-03 as harness-product work under epic williacj/cowrite#173 (Rigger extraction).
Recreated rather than transferred: GitHub forbids issue transfer from a private repo to a public one.
Labels not carried (consumer-taste vocabulary per setup-labels.mjs HX-7 / spec §7.2.1, not engine contract): type:feature, area:harness, conflict:harness-engine-tests, conflict:harness-run-loop, conflict:review-marker-contract, conflict:harness-provider-rotation.
Parent epic in cowrite was #650 — relink to its Rigger counterpart.


Goal

Complete #650 by driving every Reviewer and re-review through the latched opposite provider, binding both providers into the exact-SHA review proof, enforcing that proof in the engine and server-side merge gate, and cutting Cowrite over only after the full path is fail-closed.

Decision trace

  • Parent epic: #650
  • Ratified mechanism: DH-35 amendment, docs/proposals/cross-provider-card-rotation.md
  • Builds on #935 (ROT-1)'s board/config contract and #936 (ROT-2)'s lease-bound provider-pair latch.
  • Strengthens DH-8's coder≠reviewer and exact-SHA gates; it does not replace or loosen either.
  • Extends DH-28's server-side merge enforcement.
  • Requires the coordination-journal reliability fix in #881 / PR #904.

Scope

  • harness/engine.mjs
  • Reviewer/spike-reviewer dispatch and publication prompts
  • .claude/hooks/review-marker.cjs
  • .claude/hooks/review-gate.cjs
  • Focused engine and hook tests
  • harness/board-config.json for the final atomic cutover
  • docs/test-matrix.md

Acceptance

  • Every ordinary Reviewer, spike Reviewer, and re-review dispatch for a rotated card uses the journal's latched reviewerProvider, mechanically opposite engineerProvider.
  • The exact PR head recorded in the journal is bound to that provider pair.
  • A rotated card's SHA-bound marker carries engineerProvider and reviewerProvider.
  • Both the engine and the server-side gh pr merge gate reject a rotated marker that:
    • omits either provider;
    • names equal providers;
    • disagrees with the journal's pair; or
    • is not bound to the exact current PR head.
  • Legacy/non-rotated markers retain their existing schema behavior.
  • Opposite providers never substitute for distinct dispatch identity; the existing coder≠reviewer gate remains independently enforced.
  • Reviewer/provider failure waits or escalates through DH-18 against the assigned provider; no same-provider fallback can produce merge authority.
  • Missing adapters, unreadable journal state, board/latch mismatch, and provenance mismatch all fail closed before merge.
  • After the board field exists and the complete test suite is green, Cowrite's committed configuration enables coordination.enabled: true and provider.rotation: ["claude", "codex"] together. Startup validation succeeds on the resulting live configuration.
  • Rollback remains one configuration change: disabling rotation affects only unclaimed cards, while claimed cards finish under their latch.
  • TDD: focused Node and hook tests land first, then implementation.
  • npm run test:harness passes.

Test-matrix row

Add NI-provider-rotation-review-gate covering at least:

  • ordinary/spike Reviewer and re-review dispatches use the latched opposite provider;
  • rotated marker publication records both distinct providers for the exact SHA;
  • engine classification rejects missing, equal, stale-SHA, or pair-mismatched provenance;
  • the server-side merge gate independently rejects every malformed rotated proof;
  • legacy marker fixtures retain current behavior;
  • assigned-provider outage never falls back; and
  • the committed Cowrite configuration validates with coordination and the claude/codex rotation enabled.

Dependencies

  • Native blocked_by: #881 and #936 (ROT-2).

Non-goals

  • Do not weaken Critical or recorded-decision escalation.
  • Do not infer control state from telemetry.
  • Do not add rotation to single-role senior/intake dispatches.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions