Spoke

interview-scoring

Run a scored interview panel where nobody sees another rater's opinion until everyone's submitted — provably, not just by policy.

Character

You're a hiring manager or recruiting coordinator running a structured, multi-interviewer loop off a JobFrame-linked interview guide.

Problem

External. Panel interviews are supposed to be independent judgments reconciled after the fact — but shared spreadsheets, group chat threads, and "quick debrief before we all submit" quietly let the first mover's opinion anchor everyone else's.

Internal. Once that happens, the panel isn't measuring five independent reads anymore — it's one opinion plus four confirmations — and you can't prove otherwise after the fact when a hire is challenged.

Philosophical. A panel that can't prove independence isn't a panel — it's one person's opinion wearing five signatures.

Guide

interview-scoring runs the panel — provably, from the code, not asserted in a policy doc. A rater can never read another rater's scores pre-reconciliation. A session locks the moment it's first submitted; any later change is an append-only correction with a reason, never a silent edit. The reconciliation view unlocks only once every panelist has submitted, or the owner explicitly force-closes — and every unlock or force-close writes an audit-ledger row.

Abstract

Background. Structured interviews are the top-ranked selection procedure post-correction, and a properly-run panel shows meaningfully higher than a single interviewer (.74 vs .44) — but only if the panel actually judges independently, which everyday practice routinely defeats.

Methodology. A Roster pins a JobFrame profile key and the exact interview-guide edition scored against. Panelists score their Session on an anchored 1-5 scale plus evidence (or an explicit skip with a reason) via a private invite-token link — no login. canReadSessionScores() restricts every read to the caller's own session; canSubmitSession() / canCorrectSession() gate the submit-once-then- append-only-correction lifecycle; reconciliationReady() / canForceClose() gate the unlock. Both HTTP routes and MCP tools call the identical service functions, so the guarantee holds no matter which surface a caller used.

Scope. Runs and captures a scored interview panel. It does NOT author interview guides, isn't an ATS or scheduling system, isn't a hire/no-hire decision engine, and its v1 interrater snapshot is an honestly-labeled simple statistic — not Cohen's kappa or ICC.

Contribution. A code-enforced, audited uninfluenced-panel discipline — the trust story is provable, not promised — plus the first input to iterating the guide itself.

Evidence / Provenance. PAT-JFE-LOOP-1; the guarantee is unit-tested directly (31 pure tests, no DB required); reliability claims cite docs/research/SELECTION-ASSESSMENT-EVIDENCE.md §A5.

Plan

  1. 01

    Stand up a roster

    POST a JobFrame profile key + interview-guide edition to create a roster.

  2. 02

    Invite the panel, add candidates

    Panelists and candidates auto-wire into per-pair sessions; each panelist gets a private invite-token link.

  3. 03

    Score independently, submit once

    Each session locks on first submission; later changes are logged corrections, never silent edits.

  4. 04

    Reconcile

    Once every panelist has submitted (or the owner force-closes, always audited), read the side-by-side view with the per-question agreement snapshot.

Call to Action

Direct. curl the roster + reconciliation routes and see the 403 flip to 200 only once every panelist has submitted.

Transitional. Read the uninfluenced-panel discipline as tested code in core/uninfluenced.ts.

Spoke I/O (visual language v1)

Every toolbox spoke shares the same abstract choreography: typed inputs on the left, distilled verbs in the center, typed outputs on the right, and (when relevant) cross-spoke HTTP composition along the bottom rail. Source package: @people-analytics-toolbox/spoke-illustrations.

Interview ScoringINPUTSMAIN ACTIONSOUTPUTSRoster (profile + guide edition)ProfileKey + GuideEditionPanelists + candidatesInviteToken[]Per-question scoresScore | SkipWall off sessionsLock on submitUnlock reconciliationReconciliation + agreement snapshotReconciliationViewaudited unlock onlyCOMPOSES WITHjob-family-agentperformance-validity

Try it now

Copy this curl. Paste in any terminal. Public read — no auth needed.

interview-scoring.health

GET

Schema heartbeat verifying Postgres reachability for the interview-scoring spoke.

curl -sS "https://people-analytics-toolbox.vercel.app/api/spokes/interview-scoring/health"

Vendor the contract

The Zod contract is the source of truth. Vendor a copy into your consumer app — you keep it; we don't break it underneath you. Re-vendor when the version bumps.

// Vendor canonical types:
// src/spokes/interview-scoring/contracts/types.ts

Source path: src/spokes/interview-scoring/contracts/types.ts · GitHub

Failure

A panel debrief starts from one anchored opinion and four confirmations, and when the hire is later challenged, there's no way to prove the panel ever judged independently.

Success

Five interviewers submit five genuinely independent reads; reconciliation opens once, an audit trail proves nobody peeked, and the disagreement pattern becomes the next input to a better guide.