Skip to content

Tell the CLI why a restart was refused - #961

Merged
scgopi merged 1 commit into
mainfrom
fix/restart-refusal-reaches-cli
Nov 5, 2026
Merged

scgopi merged 1 commit into
mainfrom
fix/restart-refusal-reaches-cli

Conversation

@scgopi

@scgopi scgopi commented Nov 5, 2026

Copy link
Copy Markdown
Owner

Problem

graphcode node restart on a finished loop did nothing, and said nothing about why. Seen on 0.1.84-beta2 with a Copilot child that had reported its goal met:

  • restartNode refuses a resolved loop by design, but sent the refusal as an error to every connection.
  • runAndPrintGraph, which node restart, stop, delete, create and edge verbs use, waited only for .graphChanged. A refusal changes nothing, so the CLI either printed the graph from an unrelated broadcast (exit 0, looks like success) or timed out with exit 75, "may still have been applied".
  • graphcode status printed the session's presence (awaitingInput) over the loop's succeeded state, so the finished loop looked restartable.

Fix

  • GraphStore.refuse(_:to:) sends a refusal to the CLI connection that asked, as mailroomInbox already does, and falls back to the broadcast when there is no CLI requester. restartNode uses it for "no loop" and "has finished".
  • runAndPrintGraph also waits for .errorOccurred and fails with its message, as the other verbs in main.swift and the remote Python CLI already do.
  • status prints a resolved loop's state rather than its presence. The remote Python CLI already prints the stored state.

Evidence

Isolated daemon and CLI built from this branch, with a loop edited to succeeded on disk:

Command Output Exit
this branch's node restart graphcode: Finished has finished — there is no session to restart 1
this branch's node restart on an unknown id graphcode: no loop 00000000-… in this graph 1
0.1.84-beta2 CLI, same daemon prints the graph 0
this branch's status succeeded turnBased Finished 0

RED: xcodebuild test -only-testing SessionRestartTests and GraphcodeCommandTests on main's sources -> exit 65, 47 tests, 2 issues: the bystander received the refusal, and status printed the presence
GREEN: xcodebuild -scheme graphcode test -> exit 0, both new tests passed
REGRESSION: xcodebuild -scheme graphcode test -> exit 0, 2353 tests, 2352 passed, 0 failed, 1 skipped; make check -> exit 0, 0 serious; graphcoded and graphcode-cli builds -> exit 0; cli-smoke on a fresh SwiftPM build -> exit 0

Not covered

  • Other verbs that change nothing still broadcast their refusals, for example "could not restart: its session did not die" and the refusals of stop and delete. The CLI now reports those too, so any error broadcast while a CLI waits ends that CLI, as it already does for node send and mail post.
  • There is still no CLI verb to reopen a finished loop; the app does it with resumeSession.

Restarting a finished loop was refused, but the refusal went to every
connection and the CLI waited only for a graph change, so it printed an
unrelated graph or timed out with exit 75. The refusal now answers the
asking connection, the CLI reports any error it is sent, and status
shows a finished loop's ending instead of its open session's presence.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: scgopi <scgopireddy@gmail.com>
@scgopi
scgopi merged commit d3d1cd9 into main Nov 5, 2026
26 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