Skip to content

Process and CLI fixes: --stop identity check, Windows tree stop, --status mark, -- argv, SIGHUP shutdown, append-only deck.log, own-temp sweep - #1947

Merged
BarganConstantin merged 7 commits into
developmentfrom
fix/cli-process
Oct 5, 2026
Merged

BarganConstantin merged 7 commits into
developmentfrom
fix/cli-process

Conversation

@BarganConstantin

Copy link
Copy Markdown
Owner

What changes

  • --stop and --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-Process on Windows), and only for a record stamped since this boot. A parent whose start cannot be read is left alone.
  • Desktop app: stopping the app's own deck (Restart ccdeck on a hung deck, or Quit) now ends the supervisor and its worker together on Windows with taskkill /T /F. Before, only the supervisor went, so the hung worker kept the port and the replacement deck landed on another one.
  • --status marks the deck a bare ccdeck opens 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.
  • Supervisor: the --port <bound> a respawn adds, and the --port/--no-open an npx update adds, go in before a bare -- in the user's argv. Before, the parser dropped them.
  • SIGHUP (closing the terminal of a --foreground deck, 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.log is opened for appending by every start. A fresh start moves the old log to deck.log.1 instead 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.
  • The boot's temp-file sweep only removes names the deck's own writers use, past and present (*.agent-dag-<pid>[-<n>].tmp, prefs.json/state.json .<pid>[.<n>].tmp, <moved file>.<pid>.migrating). With CCDECK_HOME pointed at a shared folder, other programs' *.tmp files are no longer deleted.

Verification

  • npm run typecheck clean.
  • Full suite before the rebase (--maxWorkers=3 --minWorkers=1): 904 files, 11781 tests passed. After rebasing onto development, the 22 touched and neighbouring files pass (320 tests).
  • Each new regression test failed before its fix, for the reason described:
    • stop-deck-identity.test.ts: a fresh record whose parent names a process started after the worker. --stop signalled 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, stopChild called child.kill() only; now it runs taskkill /pid N /T /F, with the plain kill kept as the fallback.
    • status-marks-older-deck.test.ts: the real CLI --status against 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 sandboxed bin/deck.js sent 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 in skip-gates.mjs, and the counts are updated in skip-gate-inventory.test.ts and the publish.yml comment (28 sites, 57 cases).
    • deck-log-append.test.ts: detachAndWatch driven 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-old report.tmp, download.part.tmp, notes.migrating and photo.jpg.1.tmp were deleted before; now only the deck's own temp names are.
  • Repointed, not removed: the ccdeck --stop during 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's startedAt, deck-in-the-background.test.ts pins startsFresh and the append-only open instead of logMode, and the deck-home sweep failure fixture uses a deck-shaped temp name.
  • No UI changes, so no browser check.

…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
BarganConstantin merged commit 46b867d into development Oct 5, 2026
10 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