fix(harness): vendor runtime harness into consumers so the plugin drops off session-start critical path (#128) - #151
Conversation
) An enabled plugin loads (and pays its ~18s load cost) on every session start regardless of how its hooks are wired, which blows claude remote-control's ~20-30s spawn-ack window for headless driver sessions in consumer repos. Make the vendored local .claude/ files the runtime path instead: scaffold.sh now copies the plugin's own agents/, commands/, hooks/, scripts/, and skills/ subtrees wholesale into the consumer repo, gated as one unit by a single .claude/.orchestrator-vendor marker reusing the existing managed-file marker ladder, and creates a settings.json (user-owned, create-if-absent) that wires the runtime hooks to $CLAUDE_PROJECT_DIR/.claude/scripts/... instead of the plugin's hooks/hooks.json. sync.sh mirrors the re-vendor on plugin upgrades with the same behind/conflict/never-downgrade semantics as every other managed row. .claude/scripts/arm-loop.sh is excluded from the whole-tree copy since it already has its own dedicated managed-file row with a different canonical template, avoiding two divergent sources of truth for the same destination. Once vendored, the plugin only needs to stay enabled to run /orchestrator:setup or /orchestrator:sync, not for everyday sessions. Updates MANIFEST.md, both skill docs, and the GETTING_STARTED/USAGE passages that described the old plugin-stays-loaded-at-runtime model. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…(issue #128) copy_vendor_dirs in scaffold.sh and sync.sh used `cp -a "$entry" "$dst/$base"` per top-level entry, which nests into an already-existing destination on any restamp — skills/ is the only vendored dir with subdirectories, so a real version bump produced duplicate nests (.claude/skills/setup/setup, .claude/skills/sync/sync) and left the real files stale, permanently diverging the tree and making every later /orchestrator:sync report a false conflict. Switch to prune-then-copy of directory CONTENTS (rm -rf dest, then cp -a src/. dest/) so restamps are idempotent and prune files removed upstream, while explicitly backing up and restoring .claude/scripts/arm-loop.sh around the scripts/ prune so its own MANAGED_FILES row/template stays the sole source of truth for that file. Strengthen vendor-runtime.test.sh: assert no nesting and genuine content refresh on restamp (fails against the old cp -a form, passes after the fix), add never-downgrade coverage for both scripts, prove conflict paths leave the tree untouched by grepping the injected local marker back out of the file (not just the log line), and trim plugin-root fixtures to only the entries the vendor step reads instead of copying the whole .claude/ tree. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
fix(harness): vendor runtime harness into consumers so the plugin drops off session-start critical path (#128) (not yet reviewed) |
6 similar comments
|
fix(harness): vendor runtime harness into consumers so the plugin drops off session-start critical path (#128) (not yet reviewed) |
|
fix(harness): vendor runtime harness into consumers so the plugin drops off session-start critical path (#128) (not yet reviewed) |
|
fix(harness): vendor runtime harness into consumers so the plugin drops off session-start critical path (#128) (not yet reviewed) |
|
fix(harness): vendor runtime harness into consumers so the plugin drops off session-start critical path (#128) (not yet reviewed) |
|
fix(harness): vendor runtime harness into consumers so the plugin drops off session-start critical path (#128) (not yet reviewed) |
|
fix(harness): vendor runtime harness into consumers so the plugin drops off session-start critical path (#128) (not yet reviewed) |
What
Makes
/orchestrator:setupand/orchestrator:syncvendor the runtime harness (agents/,commands/,hooks/,scripts/,skills/) into a consumer repo's local.claude/, and adds a consumersettings.jsontemplate whose hooks resolve to$CLAUDE_PROJECT_DIR/.claude/scripts/…instead of${CLAUDE_PLUGIN_ROOT}/…. Theorchestratorplugin then becomes the install/update channel only and no longer has to stay enabled on the session-start critical path — exactly how reCode itself already runs.Why (#128)
In a plugin-consumer repo (reDeploy, reDeFi) the enabled
orchestratorplugin is loaded from the marketplace at every session start (~18s), which breachesclaude remote-control's ~20-30s spawn-ack window and kills headless / Routine / loop-fired sessions (the parent declares the still-alive child dead; abandoned children die of SIGPIPE). Running the consumer off vendored local files removes the per-session plugin load from the critical path.How
scaffold.sh/sync.sh: vendor the runtime subtrees into.claude/, gated by a single top-level marker.claude/.orchestrator-vendor(@orchestrator-managed runtime-vendor vN) reusing the existingmanaged_version_ofbehind/never-downgrade/conflict ladder. Copy is prune-then-copy of directory contents (rm -rf dest && cp -a src/. dest/) so restamps are idempotent and prune upstream-removed files (no nestedskills/setup/setup). Thearm-loop.shcarve-out (its own dedicatedMANAGED_FILESrow) is preserved via backup-before-prune / restore-after-copy, so it stays singly-managed.settings.jsontemplate (create-if-absent, never clobbered): hooks reference local$CLAUDE_PROJECT_DIR/.claude/scripts/…, noenabledPlugins/extraKnownMarketplaces.GETTING_STARTED.md,USAGE.md),MANIFEST.md, and both SKILL.md files updated to the vendored-runtime / plugin-as-updater model..claude/scripts/vendor-runtime.test.sh(10 scenarios / 38 checks), auto-discovered by.claude/self/checks.sh: fresh-vendor, idempotent re-run, restamp (asserts no nesting + subdir content actually refreshed), never-downgrade (byte-identical tree), conflict paths (asserts installed bytes untouched), arm-loop carve-out.Gates
build / lint / test / test_affected all green (self-adapter
GATES_FILE=.claude/self/gates.json), includingsmoke-fanout.shand the new 38-check test.Review
Correctness (opus) + tests (sonnet) both APPROVE, consensus=all. Reviewers reconstructed the pre-fix buggy copy and confirmed the new tests catch the directory-nesting regression.
Closes #128