Skip to content

Say "already finished" when stop is given a finished run - #7

Open
webandseo wants to merge 2 commits into
rtravellin:mainfrom
webandseo:fix/stop-finished-run
Open

webandseo wants to merge 2 commits into
rtravellin:mainfrom
webandseo:fix/stop-finished-run

Conversation

@webandseo

Copy link
Copy Markdown
Contributor

stop <id> on a run that had already completed, failed or been cancelled failed with No run found for "<id>", as if the run did not exist. resolveCancelableJob only matched the id against active runs, so a run that finished a moment before the user typed /muse:stop looked like a typo.

  • lib/job-control.mjs: given an id with no active match, resolveCancelableJob matches it against every run and returns it with finished: true. An id that matches no run at all still throws "No run found". An id that matches an active run behaves as before.
  • muse-bridge.mjs: stop reports Run <id> is already <status>; nothing to stop., exits 0, sets alreadyTerminal: true in the JSON payload, and leaves the record as it was (no kill attempted, status not overwritten).
  • This sits after the checks merged in Mark dead runs as failed; atomic, Windows-safe write-run guard #1: a run whose processes have just died is still retired and reported as "had already ended", and a prefix shared by a just-ended and a live run is still ambiguous.
  • Runtime test: a finished run in text and JSON output with the record untouched, and an unknown id still erroring.
  • README (/muse:stop) and CHANGELOG (Unreleased).

Independent of #2 to #6 apart from the shared top line of the CHANGELOG's Unreleased section; I'll rebase whichever lands later.

Tests: 109/109 locally on Windows.

🤖 Generated with Claude Code

@rtravellin rtravellin left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice improvement. One edge case is worth closing, since this PR makes finished runs a normal target for stop.

scripts/lib/job-control.mjs:367: hasActiveMatch only looks at active runs. If exactly one active run matches the prefix, finished runs are never considered and nothing is reported as ambiguous.

Scenario: job-mabc12-x1 has completed and job-mabc9f-y2 is running. stop job-mabc, meant for the finished run, kills the live one and marks it cancelled, when it should say "already finished" or raise the "ambiguous" error. That's the same case the retired-run path in handleCancel already reports as ambiguous, so the two paths now disagree.

Suggested fix: run matchJobReference(jobs, reference) over all jobs first, then derive finished from the matched run's status, so a prefix shared by a finished and a live run throws the existing ambiguous error.

This will also need a rebase: #2 and #3 are merged and the CHANGELOG conflicts.

webandseo and others added 2 commits October 4, 2026 13:42
`stop <id>` on a completed, failed or cancelled run failed with
`No run found for "<id>"`, as if the run did not exist: resolveCancelableJob
only matched the id against active runs.

- lib/job-control.mjs: with an id and no active match, resolveCancelableJob
  matches it against every run and returns it with `finished: true`; an id
  that matches no run still throws "No run found".
- muse-bridge.mjs: stop reports `Run <id> is already <status>; nothing to
  stop.` (exit 0, `alreadyTerminal: true` in JSON) and leaves the record as
  it was.
- Runtime test: finished run (text and JSON, record untouched) and an
  unknown id.
- README (/muse:stop) and CHANGELOG (Unreleased).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
resolveCancelableJob only looked at finished runs when no live run
matched, so `stop job-mabc` meant for a finished run killed a live one
with the same prefix. Match all runs first, then decide from the matched
run's status, which agrees with the retired-run path in handleCancel.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@webandseo
webandseo force-pushed the fix/stop-finished-run branch from 9ba618d to 8f38cfa Compare October 4, 2026 07:27
@webandseo

Copy link
Copy Markdown
Contributor Author

Fixed in 8f38cfa: resolveCancelableJob now matches against all runs first and derives finished from the matched run, so a prefix shared by a finished and a live run raises the existing ambiguous error. The new test covers your scenario (before the fix it stopped the live run). Rebased on main.

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.

2 participants