Operant Studio
OPER-125

[OPER-QA-5] Re-run loop: failed TestRun opens Ledger Task; Task=DONE triggers re-run

Band
MEDIUM
Suggested
Justin Cooke

Body

feature_id: FEAT-studio-qa

## Context

Ship `packages/qa/src/rerun.ts` — the closing loop from the [REDACTED-DOB] QA-primitive PDT. When a `TestRun.status = FAILED`, this module:
1. Opens a Ledger Task in the same team with `feature_id`, `caused_by_run_id`, `harm_class` prefilled, and a `TestBugLink` row joining them
2. Registers a Ledger status watcher on the Task
3. When the Task lands `DONE`, dispatches a new `TestRun` of the same TestCase (marked `triggeredBy='rerun-loop'`)

## Acceptance Criteria

- `packages/qa/src/rerun.ts` exports `openBugForFailedRun(run: TestRun): Promise<{ task: Task; bugLink: TestBugLink }>` and `enqueueRerunOnResolve(bugLink: TestBugLink): Promise<void>`
- Ledger Task created via existing `POST /api/studio/[team]/tasks` — body carries `feature_id`, `caused_by_run_id`, `harm_class`, prose 'Depends on caused_by_run_id' pattern
- TestBugLink row upserted on `(runId, taskId)` unique pair; idempotent
- Status-watcher path uses existing dispatcher watcher mechanism; on Task=DONE fires `enqueueRerunOnResolve` which creates a new TestRun via TestRun state machine (OPER-QA-6)
- Vitest coverage: (a) FAILED run opens a Task with correct fields; (b) duplicate FAILED for same TestCase does not open second Task while first is non-terminal; (c) Task=DONE fires rerun; (d) Task=CANCELED does NOT fire rerun

Attachments

Loading attachments…

Comments

Loading comments…