Skip to content

Proctored evals on the task runtime (supersedes #523) #943

Description

@legreffier

Supersedes #523. Closing #523 because the new task runtime (libs/task-service + libs/tasks) plus the rubrics resource planned in #881 collapse the original design down to a thin task-types + query feature. No new entities, no bespoke session lifecycle, no API-side telemetry pipeline.

Why #523 collapses

#523 was designing from scratch what the task runtime now provides:

#523 concept Task runtime equivalent
eval_sessions (with/without pair) correlation_id grouping the 4 tasks
eval_scores claim/submit + nonce Existing task claim / complete lifecycle
Bespoke proof receipt (Ed25519) crypto-service claim + complete attestations
Trust tiers (vitro / vivo / Gondolin) executorTrustLevel enum (self_declaredsandbox_attested)
Criteria withheld until claim Existing claim releases full input only to claimer
eval_tasks (immutable {task_md, criteria} CID) input_cid (task body) + rubric_cid from #881
OTel forwarding pipeline (Phase 4) traceparent already returned by claim; trajectory lives in OTel/Axiom

Proposed shape

Wait for #881 (first-class rubrics with CID lookup), then:

  1. Register two task types in libs/tasks/src/task-types/:
    • run-eval — input { scenarioCid, variant: 'with' | 'without', packCid?, model, mode: 'vitro' | 'vivo' }. Output: transcript hash + token totals.
    • judge-eval-variant — input { runTaskId, rubric_cid }. Output: scored criteria + verdict.
  2. Add traceparent to the shared task complete-output base schema. The runtime already returns it on claim; tasks echo it on completion. Trajectory queryable from Axiom by trace id; nothing eval-specific shipped through the API.
  3. One correlation_id per session, grouping all 4 tasks (with-run, without-run, with-judge, without-judge).
  4. Atomicity ("both variants graded or neither counts") enforced at query time, not via a new workflow:
    GROUP BY rubric_id, pack_cid, model
    HAVING count(distinct variant where status='completed') = 2
       AND every run-task has executorTrustLevel >= sandbox_attested
    
  5. CLI:

What's gone

  • evals table (anchor) — rubric_id already serves this role.
  • eval_tasks table — input_cid + rubric_cid already content-address both halves.
  • eval_sessions table — correlation_id already groups tasks.
  • eval_scores table — task attempts + complete output already store this.
  • ❌ Bespoke proof signature flow — claim/complete attestations already cover it.
  • ❌ Phase 4 server-side OTel forwarding — traceparent carries the link; no need to re-ingest spans through the API.

Proctored guarantee

"Score counts toward published aggregates iff both run tasks have executorTrustLevel >= sandbox_attested." Enforced at query time. No new endpoint, no new entity. Sandbox-attested trust ties directly into Gondolin (#826).

Open question

Should judge-eval-variant ship before #881 with inline rubric bodies (mirrors #881 Phase 1 pattern in judge_pack), then migrate to rubric_cid? Or block this entirely on #881?

Default: block on #881 — avoids the migration churn.

Related

Metadata

Metadata

Assignees

Labels

context-flywheelContext flywheel, evals, tiles, packs, and observation loop workcontext-packsevalsAgent context evaluation

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions