Skip to content

A worktree runs the main checkout's kit; a move names missing pinned tools - #92

Merged
hhff merged 3 commits into
mainfrom
worktree-kit-and-pins
Nov 4, 2026
Merged

hhff merged 3 commits into
mainfrom
worktree-kit-and-pins

Conversation

@hhff

@hhff hhff commented Nov 4, 2026

Copy link
Copy Markdown
Member

Two problems from moving the Stacks fleet to a new machine (parity 4d61afac671e9c09 matched; the restarts didn't go cleanly).

What

  • scripts/devteam.mjs, top: in a project (the main checkout has docs/devteam/project), a worktree's copy of the script re-execs the main checkout's copy when the two differ. DEVTEAM_OWN_KIT=1 opts out. The kit's own repo is untouched: it has no project/, and its worktrees are where the kit is changed.
  • scripts/devteam.mjs, §2: new kitDir (the running kit). The schema, the constitution's ladder and the dashboard are read from it. devteamDir stays the checkout's, for project/ (the branch's tickets and plans) and kitRel.
  • scripts/devteam.mjs, missingPins/pinsHint: the .tool-versions pins this machine's asdf, or else mise, hasn't installed. A manager that isn't installed (ENOENT) passes to the next; a probe that times out counts as installed. The hint is named in three places: the new-machine supervisor prompt (step 0), fleet unpark (before the restart commands), and a failed worktree_setup.
  • test/kit.test.mjs: a stale worktree copy (without handoff) fails as it should under DEVTEAM_OWN_KIT=1 and runs main's kit by default. A fake asdf reports a missing pin in the prompt and in unpark. Dashboard tests take a free port from the OS: macOS's AirPlay receiver holds 5000 and answers 403, which flaked the review test on a Mac.

Why

  • A ticket branch that forked before a kit upgrade carried the old devteam.mjs. After the move, a worker resumed on such a branch got unknown command "handoff" for a command worker.md names. It also folded the shared live log under the old schema and trust ladder. Every session writes one live log, so every session should run main's rules.
  • On the new machine, worktree_setup failed under the system Ruby 2.6, because the pinned 3.4.12 wasn't installed yet. It read like a project bug. The move checklist says to asdf install, but nothing checked it.

Authority

The re-exec only ever moves toward the main checkout's kit. A worker can't pick its branch's rules except through DEVTEAM_OWN_KIT=1, and the rules it gets that way are what the branch's script ran before this change. Reading the constitution from the running kit rather than the checkout means a branch that edits its own constitution.md no longer changes the ladder the main checkout's script applies.

Migration

None. A session that deliberately runs a branch's newer kit from a worktree (a kit-sync chore trying its new commands before merge) sets DEVTEAM_OWN_KIT=1.

Tests

Run sequentially on this machine: Node 20.19.6 42/42. Node 18.20.4 40/42 before the port fix, and both failures were the AirPlay port collision. Node 24.14.1 running.

🤖 Generated with Claude Code

hhff and others added 3 commits November 4, 2026 13:11
…tools

A branch that forked before a kit upgrade carried the old devteam.mjs, so a worker resumed on it
after a move got "unknown command" for `handoff`, which worker.md names, and folded the shared live
log by the old schema and trust ladder. In a project, a worktree's copy now re-execs the main
checkout's when they differ (DEVTEAM_OWN_KIT=1 opts out), and the rules and dashboard always come
from the kit that runs. The kit's own repo is untouched: it has no project/, and its worktrees are
where the kit is changed.

On a fresh machine worktree_setup failed under the system Ruby because the pinned one wasn't
installed yet, which read like a project bug. The new-machine prompt, fleet unpark, and a failed
worktree_setup now name the .tool-versions pins that asdf or mise hasn't installed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nothing

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A random port in 4400-5399 could land on a listener the machine already has: macOS's AirPlay
receiver holds 5000 and answers 403, which passed the startup probe and failed the dashboard
review test on a Mac.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@hhff

hhff commented Nov 4, 2026 •

Copy link
Copy Markdown
Member Author

Review (upstream loop), as author, so it was adversarial on purpose:

  • Authority: the re-exec only moves toward the main checkout's kit. It resolves from the script's own location, not the cwd, so a worktree can't steer it elsewhere. DEVTEAM_OWN_KIT=1 gives a session only what it already ran before this PR. The ladder and schema now come from the running kit, so a branch that edits its own constitution.md no longer changes the rules applied from the main checkout. That closes a small existing path; it doesn't open one.
  • Kit's own repo: no docs/devteam/project, so no re-exec. Kit development in .claude/worktrees is unaffected.
  • Pins probe: ENOENT passes to the next manager, a timeout proves nothing, and no .tool-versions means no hint.
  • Tests, sequential on macOS: Node 20.19.6 42/42, 24.14.1 42/42. Node 18.20.4 failed only on the AirPlay port-5000 collision, fixed in 8bc795e (free port from the OS). CI 18/20/22/24 green.

@hhff
hhff merged commit 98b986b into main Nov 4, 2026
4 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