Skip to content

fix(jury): adjudication consent gate + reviewer no-show pause#98

Merged
theailab-org merged 3 commits into
mainfrom
feat/adjudication-eligibility-gates
Jun 10, 2026
Merged

fix(jury): adjudication consent gate + reviewer no-show pause#98
theailab-org merged 3 commits into
mainfrom
feat/adjudication-eligibility-gates

Conversation

@t-bhendarkar

Copy link
Copy Markdown
Collaborator

Summary

Implements the two documented-but-unenforced eligibility gates found during the user-journey doc fact-checks (issues registry #71/#72). Stacked on #97 (includes its commit until it merges).

Commit 1 — adjudication consent gate (selectJury / selectExperts)

Both journey docs (JUROR.md, EXPERT.md) describe the "I want to help adjudicate" toggle as gating panel seats — "same toggle as Juror." In code, reviewer_consent was enforced only for reviewer selection; jurors and experts were drafted from every personal identity above the score floor, then charged the −1 no-commit penalty for ignoring summonses they never agreed to receive.

  • Same consent contract as reviewer-selection (true or legacy 1)
  • Hard filter — never relaxed by the score/geo cascade; an all-non-consenting pool returns insufficient: true rather than drafting anyone
  • Tests: non-consenting identities never seated (jury + experts), numeric consent accepted, insufficient-pool behavior

Commit 2 — reviewer no-show pause

REVIEWER.md claims "your no-show count goes up and can pause your assignments" — no counter or consequence existed; a reviewer could ignore every assignment forever, burning a 48h SLA per flagged content.

  • getReviewerNoShowCount: pure read over DAG history — RECUSED reviews with decision_note = sla_expired (node-signed auto-recusals) within the last NOSHOW_SAMPLE_SIZE resolved assignments. Manual recusals and still-open assignments never count. No new state.
  • Gate: more than MAX_NOSHOW_RECUSALS (3) within the window (10) ⇒ paused. Hard filter — relaxing would re-assign the case to someone already ignoring assignments.
  • The "sla_expired" literal (written by the trigger, now matched by selection) is promoted to RECUSAL_REASONS.SLA_EXPIRED in shared/constants so the two sites can't drift.
  • New genesis constants max_noshow_recusals / noshow_sample_size (selection must agree across nodes) ⇒ genesis payload changednpm run seed re-run regenerated GENESIS_TX_SIGNATURE / GENESIS_VP_TX_SIGNATURE and genesis-data artifacts per the documented procedure.
  • Tests: only sla-expired counts, threshold boundary, rolling-window recovery by serving, open assignments don't consume the window, paused reviewer excluded at every cascade pass.

⚠️ Consensus-affecting — coordinated upgrade

Selection is deterministically replayed by every node; nodes on different versions would seat different panels for the same dispute. Additionally the genesis-constants change means a new genesis hash — fine for dev clusters (reset by convention), but this and #97 should deploy in one coordinated window.

Operational note: from this version, adjudication requires opt-in — pilot/seed users must have reviewer_consent set or jury selection will (correctly) return insufficient.

Test plan

  • New: tests/jury-consent.test.js (4) + no-show describe in tests/reviewer-selection.test.js (5)
  • Full suite: 1954 passed / 1996, 0 failures on final run (one intermediate run hit the known pre-existing roaming flake — rotation-coordinator this time — which reproduces on pristine main and is tracked in the issues registry)
  • Genesis verification tests green after re-seed

@theailab-org theailab-org merged commit e4d4cd8 into main Jun 10, 2026
@theailab-org theailab-org deleted the feat/adjudication-eligibility-gates branch June 10, 2026 18:40
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.

2 participants