Skip to content

fix(api): a submitted run is readable before it ends - #39

Merged
linhdmn merged 1 commit into
mainfrom
fix/run-visibility
Sep 21, 2026
Merged

linhdmn merged 1 commit into
mainfrom
fix/run-visibility

Conversation

@linhdmn

@linhdmn linhdmn commented Sep 21, 2026

Copy link
Copy Markdown
Member

POST /v1/runs registered nothing until the loop returned, so the run id it handed back resolved to 404 for the whole run. The documented submit-then-poll flow could not poll, and POST /v1/runs/{id}/kill (P75, NFR-1) had no run to signal — killing a live run answered run not found.

What changed

  • submitRun registers the run before any exit path, so every exit writes its outcome through storeRunIfPresent instead of depending on a row that was never created.
  • LoopRunner.WithProgress publishes a partial result at every step boundary (and once before the first step, and once after the loop), so a poll sees the steps that have run rather than nothing.
  • All writes go through storeRunIfPresent, which refuses to create a row. DELETE removed the key and the loop's own final write re-inserted it, so a run an operator removed came back.

The bug found while fixing the bug

A blocked goal's 201 pointed at a run that was never stored at all — the goal-screen verdict was unreadable too, so the P1 guardrail path was invisible from the API. TestGuardrailScreenFiresInProduction caught it once storeRunIfPresent stopped creating rows.

Verification

go test ./... -count=1 green, gofmt clean, golangci-lint 0 issues, docs/check-prd.py OK. Both directions checked by deleting the registration line and watching TestRunVisibleWhileInFlight and TestGuardrailScreenFiresInProduction fail.

docs/PRD.md footer stamp updated in the same commit.

`POST /v1/runs` registered nothing until the loop returned, so the run id
it handed back resolved to 404 for the whole run. The documented
submit-then-poll flow could not poll, and `POST /v1/runs/{id}/kill` (P75)
had no run to signal — a kill on a live run answered "run not found".

Three writes now make a run visible: the endpoint registers it before any
exit path, the runner publishes a partial at every step boundary
(`LoopRunner.WithProgress`), and the terminal result lands last. All three
go through `storeRunIfPresent`, which refuses to create a row — `DELETE`
removes the key and the loop's own final write used to re-insert it, so a
run an operator removed came back.

Found while fixing the first: a blocked goal's 201 pointed at a run that
was never stored, so the goal-screen verdict was unreadable too.

Both directions are checked by removing the registration line and watching
`TestRunVisibleWhileInFlight` and `TestGuardrailScreenFiresInProduction`
fail.
@linhdmn
linhdmn merged commit ae3c6ae into main Sep 21, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant