[#974] Setup hardening#984
Conversation
Fixes 5 confirmed setup/start defects + 2 folded lows. Changes confined
to setup/start paths (bin/quadwork.js, server setup route, server listen);
no steady-state runtime or agent-spawn behavior changes.
1. Stale-branch brick — if a `worktree-<agent>` branch survives after its
dir was deleted, setup aborted with no rollback ("branch already exists").
Both the CLI wizard and the server create-worktrees route now reuse an
existing branch (prune stale registration + `worktree add` re-attach),
making setup re-runnable. Server logic extracted to createAgentWorktree.
2. CLI silently shipped an agent with no AGENTS.md when its seed template was
missing; now hard-fails (matches the server seed-files route).
3. CLI collected a reviewer-token *path* but never the token itself, so
RE1/RE2 launched pointed at an empty file. Now prompts via askSecret and
writes it 0600 (matching the server save-token endpoint), or prints a
clear "set it in Settings" step when skipped.
4. No server.listen error handler — a second `quadwork start` threw a raw
EADDRINUSE stack. Adds server.on('error') → friendly message + exit 1.
5. No origin-mismatch check — pointing setup at a clone of a different repo
than the entered slug silently seeded the wrong project. ensureGitHeadForSetup
(CLI + server) now compares `git remote get-url origin` to the slug and
fails clearly. New repoSlugFromRemote normalizes https/ssh/.git forms.
Folds: don't force `sudo npm i -g` when the global prefix is user-writable
(nvm/fnm/volta/brew); use stdio:inherit for installs so `sudo apt` password
prompts actually reach the TTY.
Tests: server/routes.setupHardening.test.js (6 cases — slug normalization,
origin-match/mismatch guard, worktree fresh/stale-reuse/detached). Full
suite 60 passed / 0 failed. EADDRINUSE + stale-branch reuse also verified
end-to-end against a live server and a real git repo.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
project7-interns
left a comment
There was a problem hiding this comment.
Verdict: APPROVE
Epic Alignment: PASS
EPIC #967 Phase 3 calls for isolated setup/start hardening without steady-state runtime regression; PR #984 is confined to bin/quadwork.js, setup routes, server.listen, and setup tests.
Checked (evidence)
- Structural gate:
gh pr view 984 --json body,headRefOid-> head3f7b3cc7feffd91d030a27204e72c67872e3dae4; required## EPIC Alignmentand## Self-Verificationare filled. - Context: issue #974 and epic #967 read live; scope is stale worktree branch reuse, missing-seed hard fail, reviewer-token setup, friendly EADDRINUSE, and origin mismatch guard.
- Scope:
gh pr diff 984 --name-only->bin/quadwork.js,server/index.js,server/routes.js,server/routes.setupHardening.test.js; no agent spawn or steady-state runtime path changed. - Acceptance coverage: CLI origin guard at
bin/quadwork.js:121, reviewer token write 0600 atbin/quadwork.js:650, stale branch reuse atbin/quadwork.js:690, seed hard-fail atbin/quadwork.js:711, server worktree helper atserver/routes.js:3766, setup route use atserver/routes.js:3905, EADDRINUSE handler atserver/index.js:2123. - Tests:
server/routes.setupHardening.test.js:51covers slug normalization;:64origin-match;:75mismatch;:92/:105/:118fresh/reuse/detached worktree paths.server/run-tests.jsdiscovers every*.test.js, so this is included innpm test. - Riskiest part of this diff: reusing existing
worktree-*branches; acceptable because both CLI/server prune stale registrations, attempt branch reattach first, and retain detached fallback for checked-out branches. - Kill-list: scanned all items — clean; raw scan found no added TODO/FIXME/HACK, debugger, sensitive values, or runtime mocks.
- CI:
gh pr checks 984->testpass, 54s.
Findings
None.
Decision
APPROVE. The implementation matches #974 and #967 constraints, covers both CLI and server setup paths where required, and has focused regression coverage for the highest-risk setup cases.
|
APPROVE at Full independent review — issue #974 Setup hardening (EPIC #967 Phase 3). Changes confined to setup/start paths (
Folds: Contracts checked: Verification: |
|
APPROVE at Re-issuing my verdict in the compliant format (comment-based approval — the shared reviewer GH identity blocks a formal Approve). Full independent review of issue #974 Setup hardening (EPIC #967 Phase 3); changes confined to setup/start paths, no steady-state runtime / agent-spawn change. Checked (evidence)
Verification
|
Closes #974
Setup hardening — 5 confirmed setup/start defects + 2 folded lows. Changes are confined to the setup / start paths (
bin/quadwork.js, the servercreate-worktrees/ensureGitHeadForSetupsetup route, andserver.listen). No steady-state runtime, agent-spawn, or orchestrator behavior changes.Changes
Stale-branch brick (
bin/quadwork.js,server/routes.jscreate-worktrees) — if aworktree-<agent>branch survived after its directory was deleted, setup rangit branch <name> HEAD, which failsalready exists, and aborted the whole re-run with no rollback. Both paths now reuse an existing branch: prune any stale worktree registration still holding it, thengit worktree addre-attaches. Setup is re-runnable. Server logic extracted tocreateAgentWorktree(injectableexecFnfor tests).CLI shipped an agent with no AGENTS.md —
if (fs.existsSync(seedSrc))silently skipped a missing seed, launching the agent with no role definition. Now hard-fails (mirrors the serverseed-filesroute, which already did).Reviewer token never collected — the wizard asked for the token file path but never the token, so RE1/RE2 launched pointed at an empty/nonexistent file and PR reviews failed. Now prompts via the existing
askSecretand writes the token0600(same as the serversave-tokenendpoint); if skipped, prints a clear "add it later in Settings" step naming the exact path.No
server.listenerror handler — a secondquadwork start(or any process already on the port) threw a rawEADDRINUSEstack trace. Addsserver.on("error")→ friendly, actionable message +exit 1.No origin-mismatch check — pointing setup at a clone of a different repo than the entered slug silently seeded worktrees/branches into the wrong project.
ensureGitHeadForSetup(CLI and server) now comparesgit remote get-url originto the entered slug and fails clearly. NewrepoSlugFromRemotenormalizeshttps,ssh(scp + url),.git, and trailing-slash forms.Folds:
sudo npm i -gwhen the global npm prefix is user-writable (nvm/fnm/volta/Homebrew installs); fall back to sudo only when the prefix genuinely needs root (npmGlobalNeedsSudo).stdio: "inherit"for auto-installs sosudo apt install …password/confirmation prompts actually reach the TTY (the old pipedrun()swallowed them and hung/failed silently).EPIC Alignment (#967)
EPIC #967 Phase 3 — isolated setup/start hardening. No steady-state runtime change, per the ticket's safety invariant: the agent spawn path and running orchestrator are untouched; every change lives in first-run setup, the reviewer-credential prompt, or the one-time
server.listen. ThecreateAgentWorktree/repoSlugFromRemoteextractions keep the CLI wizard and server setup wizard behaviourally symmetric (defect 1 & 5 fixed in both).Self-Verification
npm test(server suite, what CI runs) → 60 passed, 0 failed, 2 skipped (includes the newserver/routes.setupHardening.test.js, 6 cases: slug normalization; origin match vs mismatch guard; worktree fresh-branch / stale-reuse / detached-fallback).pack-smokegreen — no new runtimerequires added.node --checkon all three edited files → clean.server/index.js(tempHOME, config port pre-occupied) → exits1withQuadWork: port N is already in use…on stderr, no raw stack. ✅git worktree add -b worktree-dev …→rm -rfthe dir →git branch worktree-dev HEADfailsalready exists), then confirmed the fix (rev-parse --verify→worktree prune→worktree add) re-creates the worktree. ✅🤖 Generated with Claude Code