Skip to content

Post-#134: shipped templates still assume a repo-local .claude/scripts/ that nothing populates (worktree.sh never lands; CI needs gate.sh) #225

Description

@robercano-ghbot

Symptom

In reDeploy (onboarded before #134, plugin now 0.3.0), .claude/scripts/worktree.sh did not exist and never had:

$ git log --all --diff-filter=AD -- .claude/scripts/worktree.sh
(no output)

Nothing deleted it — no mechanism has ever existed to put it there.

Cause

#134 stopped vendoring agents/ commands/ hooks/ scripts/ skills/ into consumer repos, and sync.sh's managed-file table is only four rows (feature-fanout.js, the two .service templates, arm-loop.sh). It never copies scripts/.

But several shipped templates still assume a repo-local .claude/scripts/:

Template Line Assumes
templates/gates.yml 48 run: bash .claude/scripts/gate.sh ${{ matrix.gate }}
templates/action.yml 57 run: bash .claude/scripts/gate.sh install
templates/gates.json worktree._note "Run via .claude/scripts/worktree.sh setup|teardown"

So the templates promise a directory the plugin no longer populates.

Why it can't simply be "resolve from the plugin cache"

The CI ones genuinely need a repo-local copy: a GitHub Actions runner does a bare actions/checkout and has no plugin cache at all, and ${CLAUDE_PLUGIN_ROOT} is a Claude-Code-session-only variable that is never set there. gate.sh (plus resolve-roots.sh, which it sources at line 13) must therefore exist in the repo for CI to work.

resolve-roots.sh also documents that a repo-tracked .claude/scripts layout deliberately wins over the plugin cache, because worktree implementers need the worktree as root. So a repo-local copy is by design — there is just nothing that creates or refreshes one post-#134.

Consequences observed

  • worktree.sh absent, so the worktree.setup bootstrap the agent prompts call (bash ${CLAUDE_PLUGIN_ROOT:-.claude}/scripts/worktree.sh setup) silently skips via its "if present" guard whenever CLAUDE_PLUGIN_ROOT isn't set. In-worktree gates then fail for missing node_modules / Foundry libs rather than for real defects.
  • Consumers that hand-maintained the directory (reDeploy topped it up via occasional chore(harness): sync ... commits) drift arbitrarily far: reDeploy's copy was missing ~25 scripts that 0.3.0 ships.
  • sync.sh reports the directory as stale-vendor conflict forever, since it can't distinguish "stale relic" from "required for CI".

Possible directions (owner's call)

  1. Make gate.sh + resolve-roots.sh (+ worktree.sh?) a managed row in MANIFEST so setup/sync create and re-stamp them like arm-loop.sh. Smallest change; makes the required-repo-local set explicit and versioned.
  2. Have the CI templates install the plugin/marketplace in a step before calling gate.sh, so CI needs nothing repo-local.
  3. Teach sync.sh to recognise a known "required repo-local" subset and stop flagging it as stale-vendor.

Workaround applied in reDeploy

Trimmed .claude/scripts/ to the 8 files that are actually required, each refreshed byte-identical from plugin 0.3.0: gate.sh, resolve-roots.sh, worktree.sh, arm-loop.sh, prepare-pr.sh, bot-gh.sh, merge-ready.sh, notify-poll.sh.


Filed from reDeploy per #223. Labelled backlog — not self-assigning planned, per CONTRIBUTING.md.

Metadata

Metadata

Assignees

No one assigned

    Labels

    backlogFiled, not yet approved by the owner - the loop must NOT pick it upfrom:redeployOrigin: reDeploy rolloutmodule:harnessOrchestrator machinery under .claude

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions