Run rubocop --server through procman in lint gates (ADR-0219 slice 2) #713
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#713
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
gate_commands.rb starts rubocop --server through a shell string and never stops it. rubocop keys its server by a digest of Gemfile.lock and .rubocop.yml, not by directory, and has no idle exit. On 2026-09-25 the machine held 509 orphaned rubocop servers rooted at deleted test tmpdirs.
Approach
The procman gem 0.2.0 already ships
Procman::Kinds::Rubocop, which runsrubocop --start-server --no-detachunder the procman supervisor with chdir root, and aprocman with KIND --root DIR -- CMDCLI that runs CMD and releases the lease on exit. The lint gate command string changes to run rubocop through that CLI.procmanis not on PATH today, so os-sdlc gets abin/procmanexecutable, which lives on PATH because~/.claude/plugins/os-sdlc/bindoes.Required work:
plugins/os-sdlc/bin/procman:require_relative "../lib/os_sdlc"(pins BUNDLE_GEMFILE and runs bundler/setup), thenrequire "procman/cli"andProcman::CLI.start(ARGV), rescuingProcman::Errorto warn its message and exit 1, following the shape ofbin/lsp-probe.OsSdlc::Pipeline::GateCommands#rubocop_command_forreturnsprocman with rubocop --root <project.path> -- rubocop --server --format json <files>.project.pathis the same directoryGateEvaluatorchdirs into (both come fromGateHandoff#project_root).skip unless ENV["PROCMAN_REAL"] == "1"runs the lint gate command string throughModel::ProjectShell.capture3for real against a fixture project with one Ruby file, asserts stdout parses as rubocop JSON with afileskey, and assertsprocman status rubocop --root <root>exits 0 afterwards.Out of scope:
lint.rb,rubocop_report_fetcher.rb,autocorrect_prepass.rb, andhook/lint_changed/autocorrect.rbrun one-shot rubocop without--server; they start no server and stay as they are. Stopping servers whose root is gone is #714.Acceptance criteria
GateCommands#to_hfor the lint and test-lint gates yields a command that starts withprocman with rubocop --rootfollowed by the project path and-- rubocop --server --format json, and yields nil when no Ruby files changed.plugins/os-sdlc/bin/procman listexits 0 from a shell whose cwd is a user project with its own Gemfile.Owner sketch
OsSdlc::Pipeline::GateCommandsowns the lint command string; it readsproject.paththrough its existingattr_reader :project.plugins/os-sdlc/bin/procmanowns PATH exposure of the gem CLI; no library code loads it.Procman::CLI(gem) owns the lease, readiness, and release; cc-os adds no wrapper class.plugins/os-sdlc/tests/pipeline/gate_commands_rubocop_procman_test.rbfor criterion 1;plugins/os-sdlc/tests/pipeline/lint_gate_procman_integration_test.rbfor criterion 3.Blocked by: #712 (closed).
VERDICT: CREATE — slice 2 of ADR-0219 with concrete provenance (509 orphaned servers), remaining required work items not yet shipped, criteria distinct from #712.
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-sdlc/lib/os_sdlc/pipeline/gate_commands.rb
ADR: 0219
Split decided 2026-09-25: the rubocop kind and CLI kind resolution move to procman. See procman #2 (Kinds::RubocopServer with cache dir under the root hash) jared/procman#2 and procman #3 (CLI resolves KIND by catalog name) jared/procman#3.
This ticket narrows to replacing the shell
rubocop --servercall inplugins/os-sdlc/lib/os_sdlc/pipeline/gate_commands.rbwithProcman.with.Blocked until procman #4 (Release procman 0.2.0 as the stable line for cc-os) ships: jared/procman#4.
procman v0.2.0 is tagged on main (3c5f3b1) and is the stable line for this ticket. Public API: Procman.with(kind, root:) { |lease| ... } yields a Lease with #endpoint and releases on exit; Procman.ensure(kind, root:) returns the Lease. Catalog names: unix-socket, rubocop. Consumer kinds register with Procman::Kinds.register(name, klass); the contract is name, command(root:, dir:), endpoint(dir:), ready?(dir:) and register raises naming a missing method. Rubocop kind: Procman::Kinds.build("rubocop") runs rubocop --start-server --no-detach; rubocop keeps its default cache location so a client rubocop --server in the same root finds it with no env. CLI form for gate_commands: procman with rubocop --root DIR -- rubocop --server --format json FILES. The blocker on this ticket is cleared.
Work started via os-sdlc pipeline on branch ticket-713 (worktree).
Resolution
Done: Lint and test-lint gates run rubocop --server through procman (Procman::Kinds::Rubocop) via plugins/os-sdlc/bin/procman, resolved by absolute path from GateCommands; three tests added, integration test behind PROCMAN_REAL=1.
Evidence: Branch ticket-713 commit
fdfbb991; implementation 48, 16 dispatches, suite 1427 runs 0 failures; PROCMAN_REAL=1 integration test passed once by hand (5 assertions); procman list shows the rubocop server rooted at the test tmpdir.Follow-ups: Pipeline defect: suite-check looped twice because bare procman was not on PATH inside a worktree (plugin symlink points at main); fixed by absolute path, recorded in the #713 close comment; no new ticket. Orphan cleanup for roots that no longer exist is #714.