Skip to content

fix(#689): only remove control-runner units the acting checkout owns - #692

Merged
VijitSingh97 merged 3 commits into
developfrom
claude/save-preview-hanging-4d3970
Jul 21, 2026
Merged

fix(#689): only remove control-runner units the acting checkout owns#692
VijitSingh97 merged 3 commits into
developfrom
claude/save-preview-hanging-4d3970

Conversation

@VijitSingh97

Copy link
Copy Markdown
Collaborator

Closes #689.

What

The pithead-control.{path,service} unit names are box-global, but a release bench holds several checkouts at once (live stack + e2e harness + bundle-smoke tmp dirs). Two removal paths deleted the units without checking which checkout installed them:

Hit live on the bench 2026-07-19, twice in one afternoon (15:46 tmp-smoke, 16:07 targeted e2e): the live stack's runner was deleted, every dashboard Save & Preview spooled a request nothing processed, and the config editor sat at "Previewing…".

How

Both removals now key on the service unit's ExecStart matching the acting checkout ($PWD), with grep -F throughout — versioned install dirs carry dots (pithead-v1.9.3), and a regex dot could claim a sibling's unit as our own (adversarial-review catch; the pre-existing "already installed" greps got -F too). Foreign-owned units are left in place, and the e2e reap counts that as success. A dangling path unit with no service file is still reaped. PITHEAD_UNIT_DIR env seam added so the removal branch is testable at tier 1.

Known ceiling, out of scope (noted in #689): the full e2e hardening phase installs its own units over the live stack's and its teardown then removes them — the live stack is unitless until its next apply/upgrade re-converges.

Testing

  • 4 new tier-1 cases in tests/stack/run.sh (foreign owner left alone, own units removed, dangling path unit reaped, regex-dot foreign owner left alone — the last two fail on the pre-fix code): 1504 pass, 0 fail.
  • make lint clean; docs updated (docs/operations.md documents the ownership check).
  • Live remediation on the bench: units reinstalled by hand, the three stranded preview requests processed within seconds, editor round-trip working again.

🤖 Generated with Claude Code

VijitSingh97 and others added 2 commits July 19, 2026 17:26
The pithead-control.{path,service} names are box-global, but a release
bench holds several checkouts (live stack + e2e harness + bundle-smoke
tmp dirs). Both removal paths — provision_control_runner's disabled
branch and the e2e teardown reap — deleted whatever units were
installed, stranding the live stack's dashboard control requests (the
config editor sat at "Previewing…" until the next apply reinstalled the
units; hit live on the bench 2026-07-19, twice in one afternoon).

Key both removals on the service unit's ExecStart matching $PWD, with
grep -F throughout — versioned dirs carry dots (pithead-v1.9.3), and a
regex dot could claim a sibling's unit as our own. Foreign-owned units
are left in place (the e2e reap counts that as success); a dangling
path unit with no service file is still reaped. PITHEAD_UNIT_DIR env
seam added for the tier-1 tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… entry

Review fixes for the ownership check. The literal ExecStart=$PWD match
missed that one checkout has two path spellings: production units carry
the versioned dir, while an operator's disable apply runs through the
`current` symlink — the apply saw its own unit as foreign and never
removed it (fails safe, never converges). Both removal paths now extract
the ExecStart path from the service unit and compare physical
resolutions (deepest existing ancestor via cd/pwd -P, remainder kept
verbatim; unparseable ExecStart stays foreign). The e2e teardown mirror
in tests/integration/run.sh gets the same treatment, and the tier-1
block gains the versioned-spelling-via-symlink case — it fails on the
pre-fix literal comparison, and the foreign-owner cases still hold.

Also the missing Keep-a-Changelog entry under [Unreleased].

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ctions

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@VijitSingh97
VijitSingh97 merged commit b354588 into develop Jul 21, 2026
16 checks passed
@VijitSingh97
VijitSingh97 deleted the claude/save-preview-hanging-4d3970 branch July 21, 2026 23:18
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.

Sibling checkout removes the live stack's control-runner units — dashboard preview hangs

1 participant