Skip to content

Session relaunch: in-repo install and automated inverse, and background sessions by claude respawn - #1187

Open
seathatflowsinourveins wants to merge 2 commits into
mainfrom
claude/cc-native-practice-relaunch-install-20261015
Open

seathatflowsinourveins wants to merge 2 commits into
mainfrom
claude/cc-native-practice-relaunch-install-20261015

Conversation

@seathatflowsinourveins

@seathatflowsinourveins seathatflowsinourveins commented Oct 15, 2026 •

Copy link
Copy Markdown
Collaborator

Scope

  • What this PR changes, in one or two sentences: it ships Session relaunch after an unplanned WSL restart: a roster timer and a boot oneshot on the systemd user manager #1116's session-relaunch tool with an in-repo forward install (install.sh) and its automated inverse (uninstall.sh), both ported from the applied host install v6 with their gates unchanged. It also restarts profiled background sessions with the client's own claude respawn <id>, only when such a session has no process and its saved transcript exists. The new host's install stage (New WSL clean install plan (NativeHorizonNY) and the host Claude config reconciliation #1174) pins this commit and does not re-implement it.
  • Base commit: 8053f14e7e0817d2502dff2bb284bfb7e1b0152f
  • Lane: lane:foundation
  • Owned paths touched: tools/session-relaunch/ (install.sh, uninstall.sh, session_relaunch.py, README.md, config.example.json), tests/test_session_relaunch.py, tests/test_session_relaunch_install.py, docs/decisions/2026-10-15-session-relaunch-install-and-inverse.md, evidence/artifacts/session-relaunch-install-20261015/, the test count in evidence/artifacts/session-relaunch-20261014/README.md, manifests/evidence.json.

The command center's rulings of 2026-10-15 (coordination records, cited by name and date) asked for this as ONE PR:

  • the forward install for the new host, plus the automated inverse that closes v5's three P1s;
  • background rows through the vendor's own resume path, which closes the session_relaunch.py:420 follow-up;
  • an ns51 profile in the example config.

The reason-text follow-up at :249-250 is fixed in the same hunk. claude respawn <id> is the scripted form of the attach/reply path the command center named; it approved that design after the probe below. 2604 keeps its v6 install and manual inverse.

Commits

  • 93cdc6ea: the install, the inverse, background respawn, the reason text and the ns51 profile.
  • 6708e120: each respawn runs in its own transient scope. Before the first cue, a probe found that the boot oneshot's exit kills the on-demand supervisor a respawn starts inside it (receipts, case U).

SOTA sources

  • Claude Code 2.1.301, the installed client:
    • claude daemon --help line 12: service install is disabled, and the daemon runs on demand;
    • claude respawn --help;
    • claude agents --help (--json, --all).
  • Claude Code agent-view docs, https://code.claude.com/docs/en/agent-view.md, read 2026-10-15T20:05:17Z, sha256 c8e2b81092b94b4b3ded2c86b40b8329e73b8f39b36acb3288bd56385bc83266 (the same bytes as the 2026-10-14 read):
    • line 766: claude respawn <id> restarts a session, running or stopped, and a session with a saved conversation resumes it;
    • line 817: the supervisor starts on demand;
    • line 823: the supervisor restarts a session that exits unexpectedly only while it runs;
    • lines 884-886: a shutdown stops background sessions, which restart only when attached or replied to.
  • anthropics/claude-code@03b5892ee77de289bcd5dfa39f541525ade74aff CHANGELOG.md (sha256 0551b63e…): L794 (2.1.290) and L4147 (2.1.211), the respawn fixes.
  • systemd-run(1) --user --scope and systemd.kill(5) KillMode= (default control-group): each respawn runs in its own scope.
  • The systemd user manager, the scheduling-supervision layer's recorded winner (catalogs/landscape/foundation.json /layers/12, pinned at 255.4-1ubuntu8.17; this host runs 259.5-0ubuntu3.4):
    • systemctl(1): enable, disable --now, reset-failed, show -p LoadState/ActiveState;
    • systemd.unit(5): OnFailure=.
  • Session relaunch after an unplanned WSL restart: a roster timer and a boot oneshot on the systemd user manager #1116's applied host install v6 (apply.sh, MANUAL-INVERSE.md) and its simulation run_sim_v6.sh (v6 PASS 16 FAIL 0, v5 PASS 9 FAIL 7): coordination records of 2026-10-15, cited by name and date. Both scripts port them.

Evidence-class table

Claim Evidence class Command / receipt
Upstream has no relaunch after a boot at 2.1.301 source_review receipts/sources.json
claude respawn resumes a process-less row with a saved transcript on its own session id, from a non-interactive shell, and its process stays up native_proven (one run, scratch row) receipts/respawn-probe.json case S
A respawn of a failed row with no saved transcript re-sent its dispatch prompt, against CHANGELOG L794 native_proven (one run, unusual row); recorded as an untested boundary receipts/respawn-probe.json case F
A respawn from a oneshot unit with no supervisor running starts the supervisor in the unit's cgroup, and the unit's exit kills it and the session; through systemd-run --user --scope both outlive the unit and the session is listed with a process by claude agents --json with and without --all native_proven (one run each, scratch row) receipts/respawn-probe.json cases U, U-scope
install.sh and uninstall.sh keep v6's gates; each refusal stops for its own reason with zero mutating calls synthetic (systemctl stand-in) tests/test_session_relaunch_install.py
Each v5 P1 class is caught: a mutant of uninstall.sh for each fails exactly its fixture synthetic receipts/tests.json
Background rows are respawned only with no process and a saved transcript; a failed respawn leaves the run partial synthetic (client stand-in) tests/test_session_relaunch.py Background

Local commands run

$ python3 -m unittest tests.test_session_relaunch tests.test_session_relaunch_install   # main's tree 8053f14e7 + these tests
Ran 73 tests; FAILED (failures=15, errors=10)
$ bash /var/tmp/ccnp-floor/relaunch-mut/run.sh   # three uninstall.sh mutants, one per v5 P1 class
no-realpath-parents: 1 failure (test_F_B3); no-consumed-twin: 1 failure (test_F_B1b); inventory-in-substitution: 1 failure (test_F_B4)
$ python3 -m unittest tests.test_session_relaunch tests.test_session_relaunch_install   # this head
Ran 73 tests; OK
$ systemd-run --user --scope -p CPUWeight=idle --quiet -- python3 scripts/validate.py
rc 0; status passed (12147 hashed files)
$ systemd-run --user --scope -p CPUWeight=idle --quiet -- python3 -m unittest tests.test_pre_push_gate   # on the committed tree
Ran 29 tests; OK (at 93cdc6ea and again at 6708e120)

Decision record

docs/decisions/2026-10-15-session-relaunch-install-and-inverse.md. It covers:

  • the upstream check;
  • the five decisions;
  • the probe and its untested boundary;
  • the tests;
  • what is not covered.

Overturn: a release that relaunches sessions after a boot, which this tool would then defer to; or a clean reproduction of the respawn re-send, which would make the transcript gate a recorded upstream defect.

Host evidence

Not applicable: no evidence/hosts/ change.

Follow-ups

  • Not covered:
    • real systemd behaviour, a boot, the E: path and alert delivery (the stand-in proves control flow, gating, binding and filesystem effects only);
    • the tab opener on a second distro;
    • a failed background row with a saved transcript after a real shutdown;
    • the boot unit's own environment and the supervisor's credential source when the scope-wrapped respawn runs at a real boot.
  • New-host precondition: the install stage installs the stack-alert@ template first, because install.sh refuses until it loads.
  • The third Session relaunch after an unplanned WSL restart: a roster timer and a boot oneshot on the systemd user manager #1116 follow-up (a planned restart without plan-restart is labelled unplanned) belongs to the command center's restart checklist. The README states the command.
  • A clean reproduction of the no-transcript re-send, before anyone calls it an upstream regression.

Checklist

  • New/changed GitHub Actions are pinned to a full commit SHA with a version comment (no floating tags). (None changed.)
  • New/changed workflows declare top-level permissions: {} and grant each job only what it needs. (None changed.)
  • No secrets are printed, logged or committed; no new required secret was added without a documented owner.
  • No new paid hosting, subscription or billing surface was introduced.
  • Peer-owned untracked files and worktrees were preserved (not deleted, moved or overwritten).

🤖 Generated with Claude Code

…e, and background sessions by claude respawn

The command center's rulings of 2026-10-15 route #1116's automated inverse to the new host's install stage: upstream at
2.1.301 still has no relaunch after a boot (claude daemon --help line 12; agent-view docs lines 817, 823, 884-886 at
sha256 c8e2b810), so the in-repo tool stays and ships with its install and inverse.

- tools/session-relaunch/install.sh ports the applied host install v6 (apply.sh, install_id ba61c343) with its gates
  unchanged; sources are the tool's committed bytes at HEAD, the host config comes in with --config, and the install
  state has its own root.
- tools/session-relaunch/uninstall.sh ports v6's manual inverse with its gates unchanged; the expected file records are
  the recorded source commit's bytes in the checkout.
- Background rows with a profile are respawned with claude respawn <id> (agent-view docs line 766) only when they are
  listed with no process and their saved transcript exists; otherwise the handoff gives claude attach <id>. A probe at
  2.1.301 saw a respawn without a saved transcript re-send the dispatch prompt, against CHANGELOG 2.1.290 L794
  (anthropics/claude-code@03b5892e): recorded as an untested boundary.
- The handoff names the real reason a row is left (the :249-250 follow-up); background rows are no longer skipped (the
  :420 follow-up); config.example.json gains the ns51 profile.

Tests: tests/test_session_relaunch_install.py runs both scripts against the v6 simulation's systemctl stand-in with its
fixtures (A, F-B4, F-B3, F-B1a, F-B1b, F-B1c, F-D, E, C, R) plus G, W and K, each refusal asserted by its reason;
tests/test_session_relaunch.py gains six background, reason and profile cases. On main's tree they fail (72 run:
15 failures, 9 errors); a mutant of uninstall.sh for each v5 P1 class fails exactly its fixture. After: 72 OK;
validate rc 0.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@seathatflowsinourveins seathatflowsinourveins added the lane:foundation Foundation lane: Claude/Codex setup, hosts, memory, RAG, research, workers label Oct 15, 2026
…ope so the supervisor outlives the boot unit

A probe at 2.1.301 (2026-10-15) ran `claude respawn <id>` from a transient Type=oneshot user unit with no supervisor
running, as the boot unit does: the unit returned 0, but the on-demand supervisor it started lived in the unit's cgroup,
and the unit's exit killed the supervisor and the session (systemd's default KillMode=control-group, systemd.kill(5)).
Through `systemd-run --user --scope --quiet --` (systemd-run(1)) both outlived the unit, and the session was listed with
a process by `claude agents --json`, with and without --all. respawn_one now runs the call that way (config key
systemd_run, default /usr/bin/systemd-run).

tests/test_session_relaunch.py: the respawn goes through the scope wrapper (an error before the fix, OK after). The
probe receipt gains cases U and U-scope; the README and the decision record state the finding, and the boot's own
environment stays an untested boundary. Publication files name 2604's applied install by date, not by its id.
After: 73 tests OK; the three uninstall.sh mutants still fail exactly their fixtures; validate rc 0.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lane:foundation Foundation lane: Claude/Codex setup, hosts, memory, RAG, research, workers

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant