SessionStart hook runs procman cleanup (ADR-0219 slice 3) #714
Labels
No labels
P0
P1
P2
P3
bug
category/code-change
category/cross-repo
category/eval-run
category/investigation
category/no-test-target
category/owner-ruling
category/prose-artifact
category/recurring-chore
category/structure
category/umbrella
crc-refactor
create
delete
enhancement
filed-by/agent
filed-by/user
frozen
lint-rule
needs-info
needs-triage
next
plugin/cc-architect
plugin/os
plugin/os-adr
plugin/os-aidd-lint
plugin/os-backlog
plugin/os-context
plugin/os-doc-hygiene
plugin/os-sdlc
plugin/os-vault
project/cc-os
ready-for-agent
ready-for-human
recurring
review
rule-proposal
update
waiting
wayfinder:grilling
wayfinder:map
wayfinder:map
wayfinder:research
wayfinder:task
wayfinder:task
wontfix
worklist/deviations
worklist/lint-rule
worklist/new-implement-build
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
jared/cc-os#714
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
procman servers self-exit, but a server killed hard leaves a registry entry. ADR-0219 assigns the sweep to session start.
Approach
The os plugin's SessionStart hook is a Python check registry:
plugins/os/hooks/session_start.pyiterateschecks.REGISTRYinplugins/os/hooks/checks.py, each entry aCheck(name, fn, project_scoped, remediation)whosefn(ctx)returnsOK,note(msg)(goes to additionalContext), orwarn(msg)(goes to the systemMessage banner). The runner wraps every check in a 2-second SIGALRM budget. The cleanup becomes one more check.procman cleanupprints oneremoved <row>line per server it stopped and nothing otherwise, exit 0.Required work:
procman_cleanup(ctx)toplugins/os/hooks/checks.py: resolve the executable withshutil.which("procman"); absent ->warn("procman not on PATH; helper-server cleanup skipped"); present ->subprocess.run([exe, "cleanup"], capture_output=True, text=True, timeout=1.5); stdout non-empty ->note("procman cleanup: " + the removed lines joined by "; "); stdout empty ->OK;subprocess.TimeoutExpired->warn("procman cleanup exceeded 1.5s").REGISTRYasCheck("procman-cleanup", procman_cleanup, project_scoped=False, remediation="put the os-sdlc plugin bin directory on PATH so procman resolves").plugins/os/tests/hook_test.py, run withpython3 plugins/os/tests/hook_test.py, patchingshutil.whichandsubprocess.run: absent -> warn; present with empty stdout -> OK; present withremoved xstdout -> note containingremoved x; TimeoutExpired -> warn. One real test behindPROCMAN_REAL=1that starts a procman-managed server in a tmpdir, deletes the tmpdir, runs the check, and asserts the note names it.procman-cleanupto the check list inplugins/os/CLAUDE.mdand add one History row to the os implementation-status leaf.Out of scope: wiring the Python hook tests into the os target's
test_command(Ruby-only today) is a separate ticket.Acceptance criteria
procmanon PATH and a registry entry whose root directory was deleted, a new session start removes the entry and additionalContext contains one line startingprocman cleanup:that names it.procmanabsent from PATH, the banner carries one warn line for this check and the other checks still run.python3 plugins/os/tests/hook_test.pypasses, andRemediationTest.test_every_registry_entry_has_a_remediationstill passes.Owner sketch
checks.procman_cleanupowns resolution, the subprocess call, and mapping stdout to a CheckResult; it takes no new Ctx fields.checks.REGISTRYowns registration;session_start.pyis unchanged.Blocked by: #712 (closed), #713 (closed).
VERDICT: CREATE — planned slice 3 of accepted ADR-0219 with recorded provenance and concrete acceptance criteria; blockers shipped.
Origin
Session: ecfe6e11-0810-4431-88e5-8e24d34a239e
Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os/ecfe6e11-0810-4431-88e5-8e24d34a239e.jsonl
Where: plugins/os/hooks
ADR: 0219
Blocked until procman 0.2.0 ships. See procman #4 (Release procman 0.2.0 as the stable line for cc-os): jared/procman#4.
Scope unchanged.
procman v0.2.0 is tagged on main (3c5f3b1); the blocker on this ticket is cleared. For the SessionStart hook: the CLI is exe/procman; procman cleanup sweeps servers whose root is gone or whose supervisor is dead and purges dead leases; procman list and procman stop --all are available. A missing procman binary is the only precondition to check.
Work started on branch ticket-714 (worktree). Hand-finished outside the os-sdlc pipeline: the os target's test_command runs Ruby only, so the pipeline gates cannot see the Python hook tests.
Resolution
Done: SessionStart check procman-cleanup in plugins/os/hooks/checks.py runs procman cleanup, relays removed servers to additionalContext, warns when procman is absent or exceeds 1.5s; registered with remediation; CLAUDE.md check list updated.
Evidence: Branch ticket-714 commit
8ebbffc9; python3 plugins/os/tests/hook_test.py: 85 tests OK (1 skipped); PROCMAN_REAL=1 run: 85 tests OK including the live removed-server test; ruby plugins/os/tests/all.rb 27 runs 0 failures; session_start.py prints no procman line when nothing was removed.Follow-ups: #738 filed: the os target's gate runs Ruby tests only, so the Python hook tests never run under os-sdlc gates; this ticket was hand-finished for that reason. procman ensure for lsp-probe and unix-socket kinds did not work standalone during the live test; only rubocop with a Gemfile did; noted on procman, no cc-os ticket.