Skip to content

Draw an ended run's worker as building again, and a CI head the run will replace as superseded - #86

Merged
kirangathani merged 2 commits into
mainfrom
fm/fm-pipeline-view-stale-run-r4
Sep 15, 2026
Merged

kirangathani merged 2 commits into
mainfrom
fm/fm-pipeline-view-stale-run-r4

Conversation

@kirangathani

Copy link
Copy Markdown
Owner

Two frames the captain read wrong on 2026-09-15, diagnosed in the scout report data/fm-pipeline-view-stale-run-r4/report.md (private, not in this repo) and fixed here under the captain's rulings.

What was wrong

A run that ended under a live worker. eln-live-body-coedit-b2's run ended failed (daemon shutting down) and the worker had been building again for 27 minutes, but the row drew building 1h29m finished beside review FAIL, with no band and no reason. The collector marked building completed the moment any run existed for the branch, whatever its status, and never put the run's error on the wire; the renderer never read run.status at all.

A CI head the run will replace. eln-location-no-project-l3 was 31 minutes into Run #5's review on an unpushed head while the CI cell drew amber 4/4 your word for PR 50's checks on 4a22cbba, pushed by a cancelled earlier run, and the header counted 1 ready to merge. The wire carried no head of any kind, and amber meant both "parked on the captain" and "not green".

What changes

Collector, bin/fm-flow-snapshot.sh:

  • The building box measures the current phase only: Run chore(treehouse): add worktree pool config; commit the reset-accounts skill #1 from dispatch, Run #N from Run #N-1's last write, and after a failed or cancelled run it runs again from that run's last write while the worker's endpoint still resolves. A gone worker keeps the finished interval.
  • run.error and run.head reach the wire from the daemon's record; ci.head is read in the same gh pr view call as the rollup.
  • ci.superseded states, when a live run past its rebase has a different head from the checked one, whether main moved (git merge-base against the default branch) and whether the branch's content changed (git patch-id), read in the run's own worktree. The daemon's base_sha is the previous run's head, not a main base, so it is not consulted.

Renderer, bin/fm-flow-tui.mjs:

  • The run's end reason is stated on the head line: run failed: daemon shutting down.
  • The CI cell's colour is its verdict alone: green N/N passed on the head that will land, red failed, white running, yellow for a superseded head with the captain's sentences main moved, must retest and new branch commit, must retest wrapped whole over the detail rows. The checked commit rides the facts line. your word moves to the pre-merge box.
  • Every finished box is the runner band's centre green, from one named token shared with the band. Run #N is dim.
  • The pipeline block gains a fifth detail row: the two sentences wrap to five fifteen-column rows, and widening the cell by one column (the ruled alternative) was measured and still leaves them at five.

Doc, docs/flow-tui.md: the amended building contract, the new wire fields, and a section on the CI verdict colours with the measurements behind them.

Tests

tests/fm-flow-tui.test.sh reproduces both frames from the collector output captured that day, pinned, and asserts each cell's word and paint through the renderer's own layout arithmetic: the rebuild with its band and reason, the gone-worker twin, the cancelled note, the three superseded captions plus the unreadable-reason fallback, the green cell with the word on pre-merge, green finished boxes, and the dim counter.

tests/fm-flow-snapshot.test.sh builds the superseded fixture with real git so merge-base and patch-id are the tool's own answers, and asserts the rebuild's elapsed, the per-run phase of a second run, the two heads, all three comparison outcomes, the missing-worktree fallback, and that the question is not asked for the run's own head, before rebase, or under --no-ci.

bin/fm-lint.sh clean; tests/fm-flow-tui.test.sh, tests/fm-flow-snapshot.test.sh, and tests/fm-flow.test.sh pass.

…ill replace as superseded

The fleet pipeline view drew two frames the captain read wrong on 2026-09-15.

A worker whose run had ended `failed` (daemon shutting down) and who had been
building again for 27 minutes drew `building 1h29m` finished beside `review
FAIL`, with no band and no reason. The collector marked building completed the
moment any run existed, whatever its status, and never put the run's error on
the wire; the renderer never read run status at all. Now the building box
measures the current phase only: Run #1 from dispatch, Run #N from Run #N-1's
end, and after a failed or cancelled run it runs again from that run's last
write while the worker's endpoint still resolves, with the running band. The
run's end reason is stated on the head line in the daemon's own words.

A row on Run #5 with review 31 minutes in drew the CI cell amber `4/4 your
word` for PR 50's checks on head 4a22cbba, pushed by a cancelled earlier run,
and the header counted it ready to merge. Now the collector reads GitHub's head
beside the rollup and the run's own head from the daemon, and when a live run
past its rebase has a different head it compares the two in the run's own
worktree: merge-base against the default branch for "main moved", patch-ids
for "new branch commit". The cell draws yellow with those sentences wrapped
whole, the checked commit rides the facts line, and the header does not count
it. The daemon's base_sha is the previous run's head, not a main base, so it is
not consulted.

Colour now encodes the verdict alone: every finished box and a CI cell whose
checks passed on the head that will land are the runner band's centre green
from one named token; "your word" moves to the pre-merge box; Run #N is dim
rather than red. The pipeline block gains a fifth detail row because the two
sentences wrap to five fifteen-column rows and widening the cell by one column
leaves them at five.

Tests reproduce both frames from the collector output captured that day and
build the superseded fixture with real git so merge-base and patch-id are the
tool's own answers.
The merge gate re-runs main's own copy of each test file against the branch.
Main's collector test builds its fixture database from a schema trimmed to the
columns the collector read at the time, which has no worktree_dir; the run
index now names that column, so against that fixture SQLite refused the whole
statement, no run resolved for any task, and every run-dependent assertion in
the file failed or was never reached. With only the column added to the
fixture, all 61 of main's assertions pass, so the collector now reads the
table's columns once and selects worktree_dir only where it exists. The daemon
trails its current release by several minor versions, so a column one version
records is not one every database carries.

The run counter goes back to red, main's behaviour. Painting it dim came from
the scout report's own recommendation, not from a captain ruling, and the
captain asked for it back. Main's counter test is restored byte for byte.

The three main assertions that expect "your word" inside the GITHUB CI cell
remain superseded under the captain's ruling that the cell's colour is its
verdict alone; their replacements on this branch assert the ruled behaviour.
@kirangathani
kirangathani merged commit 94cc228 into main Sep 15, 2026
10 of 12 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