Skip to content

v0.7.0

Choose a tag to compare

@jitokim jitokim released this 13 Aug 14:51
· 30 commits to main since this release
0f1546b

Three changes, one story: a user reported that the longest wait in the tool
shows nothing, and chasing it surfaced two defects underneath.

A run has ONE status, and it has six values (#163, ADR 0023)

auto prints Planning a graph for goal "…" and then, for the entire planner
call, runs list says nothing and the dashboard is empty — indistinguishable
from a command that silently failed. The cause was ordering: the run id was
minted after the planner returned, so during planning there was nothing for
any reader to find.

A run id now identifies an oh-my-graph execution, so planning is inside it,
and one enumeration replaces a liveness value plus a verdict string that six
surfaces each combined for themselves:

PLANNING → RUNNING → { PASS | FAIL | PAUSED | ABANDONED }

Two of those six are fixes, not additions. ABANDONED because ADR 0015
refuses to call it FAIL — "a FAIL is a verdict about the work, and the work
never got one"
. And PAUSED because a run stopped at a human gate was
already being rendered FAIL: exit code 2, resumable, working exactly as
designed, and listed as a failure. If you have been ignoring FAIL rows on
gated runs, that is why.

ADR 0015's liveness rule is unchanged and un-duplicated — a planning phase
opens a leg and holds the run lock, so a killed planner reads ABANDONED rather
than hanging in flight forever.

A node timeout is its own retry cause

It used to be classified as run_error, the same token a failed spawn gets, so
retry.on could not ask for one without the other. It now has its own:

retry: { max: 1, on: [timeout] }

Nothing retries automatically because of this — the cause makes a timeout
askable, and the graph author decides. Auto-retry was considered and
rejected: a timeout is the one failure that always burns its full budget before
dying, so a retry costs another whole timeout, and it cannot tell a slow
machine from an instruction that cannot finish at any timeout.

Existing meanings are unchanged — the closed set grew, no token changed. But
a graph that retried on run_error expecting timeouts to be covered now needs
on: [run_error, timeout].

The boundary is whose clock it was: a deadline this engine minted is timeout;
one inherited from the caller's context stays run_error, because retrying
inside an already-expired context burns every remaining attempt on a deadline
that has passed.

adr-driven-dev's localrun asked for stress it could not finish

Found by running ADR 0023's own work through that shipped template. Its prompt
asked for go test … -race -count=300 under a 20-minute node timeout; measured
on this repository, cmd/oh-my-graph alone would need about 72 minutes, so the
pipeline halted with the implementation already committed.

Underneath it, a second trap: the prompt never mentioned -timeout, and
go test's default is 10 minutes per package — so a stress run that did fit
the node's budget would still have reported an artificial FAIL, and
localrun's FAIL halts the pipeline. The instruction now derives a budget from
the node's own timeout, reports what it actually exercised, and passes
-timeout.


Install: go install github.com/jitokim/oh-my-graph/cmd/oh-my-graph@v0.7.0

Full changelog: https://github.com/jitokim/oh-my-graph/blob/v0.7.0/CHANGELOG.md