From session-orchestrator
Runs session-process evaluations against rubric-v1 dimensions using deterministic metrics from orchestrator sessions. Supports scoring, reporting, and reproducibility verification.
How this skill is triggered — by the user, by Claude, or both
Slash command
/session-orchestrator:evalsonnetThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
> **Platform Note:** State files use the platform's native directory: `.claude/` (Claude Code), `.codex/` (Codex CLI), or `.cursor/` (Cursor IDE). Shared metrics + the eval journal live in `.orchestrator/metrics/`. See `skills/_shared/platform-tools.md`.
Platform Note: State files use the platform's native directory:
.claude/(Claude Code),.codex/(Codex CLI), or.cursor/(Cursor IDE). Shared metrics + the eval journal live in.orchestrator/metrics/. Seeskills/_shared/platform-tools.md.
On-demand, honest measurement of ONE completed orchestrator session against the
pre-registered rubric-v1 check set. The deterministic engine
(scripts/eval-session.mjs → scripts/lib/eval/engine.mjs) reads only local
metrics files (sessions.jsonl + events.jsonl), scores the five deterministic
dimensions, appends a session-eval record to the journal, and optionally
renders an HTML report. An opt-in LLM judge overlays two advisory dimensions.
The standard this skill implements is docs/eval/aiat-llm-eval-v1.md;
the frozen, content-hashed check set is skills/eval/rubric-v1.md.
cannot-determine (a first-class,
non-error verdict) with an honest reason — never a fabricated pass/fail.
Do NOT "fill in" a missing KPI or infer a gate result the events do not show.uncalibrated in
v1 — never blend a judge verdict into the deterministic tally..orchestrator/metrics/eval.jsonl is authoritative. The HTML report is
rebuildable from any stored record and is never authoritative over the journal.--verify is the reproducibility proof. Re-scoring stored source data
reproduces the stored dimensions byte-for-byte (exit 0) or reports drift
(exit 1). This proves the SCORING replays — NOT that the model is deterministic.Read skills/_shared/bootstrap-gate.md and execute the gate check. If the gate is
CLOSED, invoke skills/bootstrap/SKILL.md and wait for completion before
proceeding. If the gate is OPEN, continue to Phase 1.
Read and parse Session Config per skills/_shared/config-reading.md. Extract the
eval block (scripts/lib/config.mjs returns it as config.eval, parsed by
scripts/lib/config/eval.mjs):
enabled: boolean (default false)
mode: 'warn' | 'off' (default 'warn')
judge: 'off' | 'haiku' | 'sonnet' (default 'off')
report: 'html' | 'none' (default 'html')
handle: string | null (default null)
On-demand /eval runs regardless of eval.enabled. The enabled flag gates
the AUTOMATIC session-end eval phase only — it does NOT gate this command (same
posture as /reconcile vs reconcile.enabled). mode: off is honoured as a
kill-switch only for the automatic phase; on-demand invocation still runs. If
eval.judge is off, skip Phase 3 entirely.
Parser gotcha: the
eval:key-line itself MUST NOT carry an inline comment (strict/^eval:\s*$/); a trailing# commenton that exact line makes the parser skip the whole block and silently apply ALL defaults. Sub-key lines tolerate inline comments.
Inspect $ARGUMENTS:
--session <id> → pass through to --session.--no-write → evaluate without appending to the journal (dry-run).--verify <run-id> → verification mode: skip Phases 2–4, run the CLI
--verify path (see Phase 6), report MATCH/DRIFT, done.The record's model.source records HOW the model id was captured, precisely
because self-report is unreliable:
$ANTHROPIC_MODEL is set in the environment, the engine reads it
automatically with source: env — env wins over the flag (precedence
env > flag). Do not pass --model-id in that case; let the engine resolve it.--model-id <self-reported-model-id> --model-source self-report.Run the deterministic engine via its CLI. Default target is the last completed
session (resolution cascade); --session overrides.
node scripts/eval-session.mjs [--session <id>] --json \
[--model-id <self-reported-id> --model-source self-report] \
[--no-write]
--metrics-dir for a real run — the engine defaults to the
live .orchestrator/metrics, the session being evaluated.timestamp (the one sanctioned clock read) and hands
it to the engine as a parameter, so the scoring path stays clock-free and
--verify-reproducible.0 success · 1 user error (session not found) · 2 system error.
On exit 1 (e.g. "no completed session found"), surface the message and stop —
do not retry with fabricated inputs.Parse the emitted JSON record. It carries dimensions[] (5 deterministic
entries), kpis{}, provenance.rubric_sha256 (non-null once rubric-v1.md
exists), model, harness, and run_id. Unless --no-write was passed, the
record is already appended to .orchestrator/metrics/eval.jsonl by the CLI.
Contamination check: if the human-render/summary reports a peer-overlapped
window, note it — verification-evidence and gate-health will read
cannot-determine for that reason (attribution is unsafe), which is correct, not
a defect.
eval.judge != off)The judge runs coordinator-side — AskUserQuestion and the Agent tool are
not available inside a dispatched subagent, so the judge is dispatched from the
coordinator thread using the read-only agent session-orchestrator:eval-judge
(model = eval.judge). Reference the API; do not reimplement scoring here:
import { runEvalJudge, mergeJudgeDimensions } from '$PLUGIN_ROOT/scripts/lib/eval/judge.mjs';
import { appendEvalRecord } from '$PLUGIN_ROOT/scripts/lib/eval/sink.mjs';
// dispatchAgent = the coordinator's Agent-tool dispatch closure targeting
// subagent_type 'session-orchestrator:eval-judge'.
const { status, dimensions } = await runEvalJudge({
dispatchAgent,
record, // the deterministic record from Phase 2
model: EVAL_JUDGE_MODEL, // eval.judge ('haiku' | 'sonnet')
budget: JUDGE_BUDGET_TOKENS, // optional
});
// mergeJudgeDimensions appends the advisory judge dimensions to the record.
const merged = mergeJudgeDimensions(record, dimensions);
// The COORDINATOR appends the enriched record (subagents never write the journal).
appendEvalRecord(merged, { path: '.orchestrator/metrics/eval.jsonl' });
advisory: true + calibration_status: "uncalibrated" (the schema firewall rejects any other shape). Keep them
visibly separated from the deterministic five in the summary.runEvalJudge returns a non-ok status (e.g. dispatch failed), keep the
deterministic record as-is and note the judge was unavailable — the
deterministic evaluation is complete without it.--no-write was passed in Phase 2, do NOT append the merged record either.The judge merge re-writes the record with the SAME
run_id/timestamp, so a later--verify <run-id>re-scores the deterministic dimensions from source and diffs them; judge dimensions are advisory and excluded from the drift diff.
eval.report == html)Render the derived HTML view from the record:
import { writeEvalReport } from '$PLUGIN_ROOT/scripts/lib/eval/report.mjs';
const res = writeEvalReport(record, { generatedAt: new Date().toISOString() });
// res.ok === true → res.path === .orchestrator/eval/reports/<run_id>.html
.orchestrator/eval/reports/<run_id>.html (gitignored — a derived
view, rebuildable from the journal).writeEvalReport NEVER throws; on res.ok === false surface the WARN reason
and continue (the journal record is unaffected — the report is derived).eval.report == none, skip this phase.Emit a compact, honest per-dimension summary. Status lines only — no global score.
## /eval — <session_id> (self-evaluation, aiat-llm-eval/1.0 · rubric-v1 · n=1, no CI)
Deterministic:
verification-evidence PASS <one-line evidence>
plan-fidelity PASS completion_rate=1.0 (score)
gate-health PASS <one-line evidence>
process-safety PASS <one-line evidence + guard-emission disclosure>
efficiency-kpis N/A (reported: duration=…s waves=… agents=… tok_in=… tok_out=… carryover=…)
Judge (advisory, uncalibrated) [only when eval.judge != off]:
instruction-adherence <verdict> advisory
report-quality <verdict> advisory
cannot-determine: <k> of 5 deterministic dimensions (<reasons>)
Report: .orchestrator/eval/reports/<run_id>.html
Journal: .orchestrator/metrics/eval.jsonl (appended: <yes|--no-write>)
Re-verify: node scripts/eval-session.mjs --verify <run_id>
Always report the cannot-determine share explicitly — a high abstention count
is an honest signal about missing telemetry, not a failure to hide. Always print
the --verify command as the reproducibility handle.
--verify <run-id>)When Phase 1.2 detected --verify, run ONLY:
node scripts/eval-session.mjs --verify <run-id> --json
0 + { match: true } → the stored record re-scores identically across
all deterministic dimensions. Report MATCH with the dimension count.1 + { match: false, diffs } → scoring drift. Report the per-dimension
diff (id.field: stored=… fresh=…). Drift means the source data or the engine
changed since the record was written — investigate, do not overwrite.--verify reproduces the stored model + timestamp verbatim (no env override),
so a MATCH is a real reproducibility proof of the scoring, not of model output.The deterministic core is pure Node CLIs (scripts/eval-session.mjs) plus Node
library modules (report.mjs, sink.mjs) — they run identically on every
platform. Only the judge phase needs harness-specific tooling.
Agent tool (and AskUserQuestion) are
unavailable, so Phase 3 (judge) is SKIPPED with a one-line note
("judge phase skipped: requires the Agent tool, unavailable on <platform>").
Phases 2, 4, 5, 6 run unchanged — they are Node-only. See
skills/_shared/platform-tools.md § Agent Dispatch Pattern.harness.platform on the record is resolved from $SO_PLATFORM
(falls back to claude-code) inside the engine — no skill action needed.--verify are fully
available on all platforms; the judge overlay is a Claude-Code-only enrichment
in v1.cannot-determine/null, never a fabricated pass or 0.uncalibrated in v1 and must stay visibly separated from the deterministic
tally.--verify when reproducibility is in question — it is the
executable proof, and its MATCH/DRIFT exit code is the source of truth.--metrics-dir for a real run — that points the engine at
fixture data instead of the live session metrics.runReconcile-style writes from a subagent — the coordinator
owns every eval.jsonl append (PSA-007).npx claudepluginhub kanevry/session-orchestrator --plugin session-orchestratorRuns a three-stage evaluation pipeline (mechanical, semantic, multi-model consensus) on execution sessions. Useful for code review and quality assurance workflows.
Executes evaluations against test cases for skills, scores outputs with judges, and reports results. Useful for benchmarking, detecting regressions, and verifying skill quality.
Scores produced changes against an eval set rubric using a cheaper LM judge (haiku) with per-dimension scoring, grounded justifications, and deterministic fallback on failure.