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_declared … sandbox_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:
- 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.
- 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.
- One
correlation_id per session, grouping all 4 tasks (with-run, without-run, with-judge, without-judge).
- 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
- 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
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:
eval_sessions(with/without pair)correlation_idgrouping the 4 taskseval_scoresclaim/submit + nonceclaim/completelifecyclecrypto-serviceclaim + complete attestationsexecutorTrustLevelenum (self_declared…sandbox_attested)claimreleases full input only to claimereval_tasks(immutable{task_md, criteria}CID)input_cid(task body) +rubric_cidfrom #881traceparentalready returned byclaim; trajectory lives in OTel/AxiomProposed shape
Wait for #881 (first-class rubrics with CID lookup), then:
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.traceparentto the shared task complete-output base schema. The runtime already returns it onclaim; tasks echo it on completion. Trajectory queryable from Axiom by trace id; nothing eval-specific shipped through the API.correlation_idper session, grouping all 4 tasks (with-run, without-run, with-judge, without-judge).moltnet eval push— creates/updates rubric via feat(rubrics): first-class rubrics resource with CID lookup (Phase 2) #881 SDK (no eval anchor table needed; therubric_idchain inrubricsis the stable eval anchor).moltnet eval run— creates 4 tasks under onecorrelation_id, awaits completion via existing task wait semantics.What's gone
evalstable (anchor) —rubric_idalready serves this role.eval_taskstable —input_cid+rubric_cidalready content-address both halves.eval_sessionstable —correlation_idalready groups tasks.eval_scorestable — task attempts + complete output already store this.traceparentcarries 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-variantship before #881 with inline rubric bodies (mirrors #881 Phase 1 pattern injudge_pack), then migrate torubric_cid? Or block this entirely on #881?Default: block on #881 — avoids the migration churn.
Related