Skip to content

Refuse a legacy exit before the restart prompt while its daemon lives - #211

Merged
myobie merged 1 commit into
mainfrom
agent/legacy-attach-refuses-a-finishing-exit
Nov 4, 2026
Merged

myobie merged 1 commit into
mainfrom
agent/legacy-attach-refuses-a-finishing-exit

Conversation

@myobie

@myobie myobie commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

A follow-up to #209, from its post-merge read. It is separate from #210.

What happened. #209 lets attach admit a legacy record (no daemonBootId) whose recorded start token verifies against the live daemon. That admission wasn't limited to a running session. When the exit record was already written but the daemon was still finishing, attach went on to the dead-session path:

  • It printed the exit and asked Restart? [Y/n].
  • It read a closed stdin as yes.
  • It then refused at the owner-loss wait with Refusing to remove session "z": daemon identity is unknown. and exited 1.

Nothing reran. A restart needs proof that the daemon is gone, and a live legacy daemon can't give that proof. So the prompt offered a restart that couldn't happen, and the refusal talked about removing.

Change. Legacy-verified records are admitted only while the session's status is running. In that window attach now refuses up front with pty attach: refusing session "z": daemon identity is unknown., as it did before #209. Once the daemon is gone, its identity reads Gone, and attach offers the restart as before. The README's #209 paragraph gets one sentence about this.

Test. cli_attach_guard::legacy_exit_with_a_live_daemon_is_refused_before_the_restart_prompt sets up a legacy record with exitedAt and exitCode, a verified live daemon and a PID sidecar. It runs four commands:

  • plain attach with a closed stdin
  • attach with y on stdin
  • attach -r
  • attach --force

Each must exit 1 with the up-front refusal, and must not show Restart? or the exit details. The stored command must not run, and the record bytes must be unchanged.

  • Control: I reverted attach.rs and kept the test. It fails on the first command, whose stdout is Session "finishing" exited with code 0. … Restart? [Y/n] and whose stderr is Refusing to remove session "finishing" ….
  • Linux, sandboxed root, at this head: -p pty with cli_attach_guard (6/6), client_library, cli_rm, cli_e2e, cli_binary_upgrade, cli_up_down and daemon_lifecycle gives 72 passed, 1 ignored.

Not changed. No tier-1 files, no JSON shape, and no change for records with boot evidence or for running legacy sessions.

Since #209, attach admits a legacy record (no daemonBootId) whose
recorded start token verifies against the live daemon. That admission
was not limited to a running session. A record whose exit is written
while its daemon is still finishing went on to the dead-session path:
it printed the exit, asked "Restart? [Y/n]", read a closed stdin as yes,
and then refused at the owner-loss wait with "Refusing to remove session
... daemon identity is unknown". Nothing reran, because a restart needs
proof that the daemon is gone and a live legacy daemon can't give it,
but the prompt offered a restart that could not happen.

Admit legacy-verified records only while the session is running. In
that window attach now refuses up front with "daemon identity is
unknown", as it did before #209. Once the daemon is gone, its identity
reads Gone and attach offers the restart as before.
@myobie

myobie commented Nov 4, 2026

Copy link
Copy Markdown
Contributor Author

Independent read GO at exact head 75f21f3a8b96b0085257bbb197c78fde15503c56. All 9 checks are SUCCESS on this head and the PR is CLEAN.

Read:

  • attach admits a pre-boot-ID (legacy) record through the explicit-control identity check. With this change it does so only while the session is running. A legacy record whose exit is already written while its live daemon is still finishing is now refused up front ("refusing session ... daemon identity is unknown"), instead of printing Restart? [Y/n] and being refused afterwards. A restart waits for proof that the daemon is gone, and a live legacy daemon cannot give it, so the prompt could never be honoured.
  • Once the daemon is gone its identity reads Gone and restart behaves exactly as before. A running legacy daemon attaches as before.
  • The new test builds a legacy record with an exit and a live verified daemon, then runs attach with a closed stdin, with y on stdin, with -r and with --force. Each must refuse with the same message, show no prompt and no exit details, not rerun the command, and leave the record bytes unchanged. The author reports it fails on the reverted attach.rs.
  • Four lines of code, three README lines, one test. No wire-format change and no tier-1 file (events.jsonl, <id>.json, docs/disk-layout.md).

Risks (low): attach gives one more refusal in that short window; the test uses the test process itself as the stand-in daemon.

@myobie
myobie merged commit 85b6ce5 into main Nov 4, 2026
9 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