(tasks) add tasks for harness

This commit is contained in:
Story Crater Bot
2026-08-17 23:05:20 -07:00
parent e2d678b118
commit 5a30d0ffc6
74 changed files with 8204 additions and 1 deletions
+105
View File
@@ -0,0 +1,105 @@
# T6.6 — Held-out split
| Field | Value |
|---|---|
| Phase | P6 — Learning loop |
| Size | M — 1 to 3 days |
| Status | Not started |
| Flags | — |
| Spec | inlined below |
| Blocks | — |
## Goal
Partition tasks into selection and held-out sets. Promote on selection, report
held-out without optimizing against it.
## Facts (inlined — no spec read needed)
- Selecting on a fixed set of recorded tasks overfits to those tasks, **silently**:
shadow scores improve while live performance does not.
- **No promotion gate takes held-out as an entry criterion.** A gate that reads
held-out has converted it into a second selection set and left nothing
measuring generalization.
- **The proposer reads the selection set only.** If the slow loop consumes
held-out failures to generate candidates, the held-out set is contaminated
through the generator instead of the selector. **This leak is easy to introduce
and invisible once present** — which is why the audit test is the control, not
a nicety.
- A widening selection-versus-held-out gap is the overfitting alarm.
- Under one-state convergence there is no competing variant whose divergence
would reveal a stalled loop, so **the held-out report is also the only stall
detector there is**. It must be produced and surfaced even when no promotion is
pending.
- Held-out catches overfitting to *episodes*. It does not catch drift in the
*task mix* — that is T6.7.
## Steps
1. Assign each `TaskId` to selection or held-out by a deterministic hash of the
id, so the partition is stable and needs no stored membership list.
2. Expose two separate query surfaces — `selection_tasks()` and
`heldout_tasks()` — rather than one with a flag. A flag defaults wrong.
3. Give the proposer access to the selection surface only, at the type level if
possible.
4. Compute the held-out report on a **schedule**, independent of promotion
activity, and surface the selection-versus-held-out gap as a metric.
5. Write the audit test: enumerate every proposer input and every gate
evaluation, assert no held-out `TaskId` appears in either.
6. Keep the audit test running in CI permanently. It is the only thing that will
notice the leak.
## Acceptance
- An audit test asserting **no held-out `TaskId` appears in proposer input**, and
none in any promotion-gate evaluation. This leak is invisible once present, so
the test is the control.
- The held-out report is **emitted on a schedule, not only at a gate** — asserted,
since under one-state convergence it is the only stall detector there is.
## Verify
**Harness:** an interception layer recording **every** `TaskId` that reaches the
proposer and every `TaskId` read during a gate evaluation. The audit is the
deliverable — it is the only thing that will ever notice this leak.
**Integration test**`tests/it_heldout_audit.rs`:
1. Partition a corpus of 1000 `TaskId`s. Assert the split is deterministic:
recompute it in a second process and assert identical membership.
2. Run a full generate-and-promote cycle with interception on.
3. Assert **no held-out `TaskId`** appears in the recorded proposer input set —
intersection with the held-out set is empty.
4. Assert **no held-out `TaskId`** appears in any gate evaluation.
5. Assert the two query surfaces are distinct types or distinct functions —
`trybuild` a call that tries to pass held-out tasks into the proposer.
6. **Schedule:** advance simulated time with **no promotion pending**; assert the
held-out report is still emitted. Under one-state convergence it is the only
stall detector there is.
7. Assert the selection-versus-held-out gap is emitted as a metric.
8. Negative control: deliberately wire a held-out task into the proposer in a
test-only build; assert the audit **fails**. An audit that never fails is not
a control.
**Command:** `cargo test -p loop heldout_audit`
**False pass:**
- Steps 34 passing because the interception layer only sees one of several code
paths into the proposer. Assert the interception is at the single chokepoint,
or the audit measures nothing.
- Step 8 omitted. This is the most important one: an audit test that has never
been observed failing may simply be looking in the wrong place, and the leak it
guards is invisible once present.
- Step 6 omitted, so the report is computed only at gates — exactly when a
stalled loop produces none, which is when it is needed.
## Traps
- A single task query with an `include_heldout: bool`. Someone passes `true`.
- Computing the report only when a promotion is pending, which is exactly when a
stalled loop produces none.
---
Background (not required to do this task):
[rust-agentic-sys.md](../../../rust-agentic-sys.md) §12.1, §12.3, §12.5, §15 ·
[rust-agentic-task.md](../../../rust-agentic-task.md)