Process and CLI fixes: --stop identity check, Windows tree stop, --status mark, -- argv, SIGHUP shutdown, append-only deck.log, own-temp sweep - #1947
Merged
Conversation
…efore stopping it A deck between workers is named by the supervisor pid on the crashed worker's record. That pid is now accepted only when the process holding it started no later than the worker, and only for a record stamped since this boot; anything else is left alone.
Stopping the deck the app started killed only its supervisor on Windows, so a hung worker kept the port and the replacement deck landed on another one. The whole tree is now ended with taskkill /T /F there, with the plain kill kept for a taskkill that cannot run.
--status marked an older deck of the start's shape as the one `ccdeck` opens, while the start replaces any deck older than itself. The mark now asks serves(), shape and version both, and an older deck of that shape says a bare start replaces it.
…'s argv parseArgs drops everything after the first --, so the bound --port a respawn appends and the --no-open an npx update appends were never read, and the deck came back on another port. They now go in before the first --.
Closing the terminal of a --foreground deck, or its console window on Windows, ended the worker without its shutdown: acknowledged appends were dropped and the discovery record left behind. SIGHUP now takes the same way out as SIGINT and SIGTERM once the deck is up, and still exits with the hangup's code.
…ng it The first start opened deck.log without O_APPEND, so the running deck wrote over an attach's lines, and two starts in one boot window left holes in it. Every start now opens it for appending, and a fresh start moves the old log to deck.log.1 instead of truncating, skipped while a deck holds the boot lock.
With CCDECK_HOME pointed at a folder that holds other things, every boot deleted any *.tmp or *.migrating file there older than an hour, whoever made it. The sweep now matches only the names the deck's own writers use, past and present.
BarganConstantin
force-pushed
the
fix/cli-process
branch
from
October 5, 2026 00:24
5ec404b to
2fb1fae
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changes
--stopand--status: a deck between workers is named by the supervisor pid on its crashed worker's record. That pid is now accepted only when the process holding it started no later than the worker did (ps -o etime=on macOS/Linux,Get-Processon Windows), and only for a record stamped since this boot. A parent whose start cannot be read is left alone.taskkill /T /F. Before, only the supervisor went, so the hung worker kept the port and the replacement deck landed on another one.--statusmarks the deck a bareccdeckopens using the start's own rule (serves: same shape, and a version no older than ours). An older deck of that shape now says a bare start replaces it.--port <bound>a respawn adds, and the--port/--no-openan npx update adds, go in before a bare--in the user's argv. Before, the parser dropped them.--foregrounddeck, or its console window on Windows) now runs the same shutdown as SIGINT and SIGTERM once the deck is up: queued appends drained, record removed, children reaped. It still exits with the hangup's code (129). Before the boot finishes it still dies of the signal, as it did.deck.logis opened for appending by every start. A fresh start moves the old log todeck.log.1instead of truncating it, and skips that while a deck holds the boot lock. Before, the running deck wrote over an attach's lines, and two starts in one boot window left overwritten lines or NUL holes.*.agent-dag-<pid>[-<n>].tmp,prefs.json/state.json.<pid>[.<n>].tmp,<moved file>.<pid>.migrating). WithCCDECK_HOMEpointed at a shared folder, other programs'*.tmpfiles are no longer deleted.Verification
npm run typecheckclean.--maxWorkers=3 --minWorkers=1): 904 files, 11781 tests passed. After rebasing onto development, the 22 touched and neighbouring files pass (320 tests).stop-deck-identity.test.ts: a fresh record whoseparentnames a process started after the worker.--stopsignalled that process before (it is the test's own child); now it says no deck is running and leaves it alone. Also covers the before-this-boot record, an unreadable start, and reading a real child's start time.desktop-own-deck-tree-stop.test.ts: on win32,stopChildcalledchild.kill()only; now it runstaskkill /pid N /T /F, with the plain kill kept as the fallback.status-marks-older-deck.test.ts: the real CLI--statusagainst a sandboxed registry and a challenge-answering stand-in deck. A v0.0.1 deck of the start's shape was marked "opens this one"; now it says "replaces this one". The current-version control is still marked.supervisor-args-end-of-options.test.ts:parseArgs(workerArgs(..., ["--no-persist", "--"], { respawn: true, boundPort: 4350 }))had no port before; the npx relaunch had neither port nor--no-open.hangup-shuts-down.test.ts: a real sandboxedbin/deck.jssent SIGHUP. Before, it died with its discovery record still in place; now the record is gone and it exits 129. POSIX only (Windows cannot send SIGHUP); the case is registered inskip-gates.mjs, and the counts are updated inskip-gate-inventory.test.tsand thepublish.ymlcomment (28 sites, 57 cases).deck-log-append.test.ts:detachAndWatchdriven with child processes that share the log descriptor, the way a deck's supervisor and worker do. Before, an attach's line was overwritten by the running deck, and two fresh starts left the file corrupted. Now every line survives with no NULs, and nothing is rotated while the boot lock is held.deck-temp-sweep-own-files.test.ts: two-hour-oldreport.tmp,download.part.tmp,notes.migratingandphoto.jpg.1.tmpwere deleted before; now only the deck's own temp names are.ccdeck --stopduring a crash-restart wait says no deck is running, then the deck comes back by itself #1779 tests now give their fake supervisor a start before the worker'sstartedAt,deck-in-the-background.test.tspinsstartsFreshand the append-only open instead oflogMode, and the deck-home sweep failure fixture uses a deck-shaped temp name.