Skip to content

T-7PXF-declare-worktree-init-bun-install

Status: closed/done · Impact: medium · Complexity: small

AUTO-DEFINED: this spec was best-effort machine-authored by /sdlc:task-auto-define on 2026-06-03. Review the Goal, Approach, Today, Files-to-touch, and Acceptance-criteria carefully before trusting it.

This repo’s root sdlc.yaml declares no worktree_init: key, so /sdlc:task-work Step 4 no-ops and fresh worktrees start with no node_modules. Declaring worktree_init: ["bun install"] would arm each worktree deterministically before Step 7’s quality checks run.

Fresh /sdlc:task-work worktrees start with no node_modules, so every bun-test quality verb fails with Cannot find module 'eta' until a manual bun install. This project’s sdlc.yaml declares no worktree_init: key, so task-work Step 4 no-ops. Add worktree_init: ["bun install"] to the repo-root sdlc.yaml so worktrees are armed deterministically before Step 7’s quality checks run.

— originating task T-XD7M-retire-task-sort-stub

LocationRole today
sdlc.yamlDeclares lease_authority, quality_checks (four bun-dependent verbs: bunx tsc --noEmit, bun test, bun test ./.claude, two audit runs), orchestrator, and pr_check — but no worktree_init: key, so task-work Step 4 no-ops and fresh worktrees lack node_modules.
plugin/scripts/run_quality_checks.tsThe shared executor; worktree_init is already a schema-owned key (SCHEMA_OWNED_KEYS), and --allow-empty turns a missing/empty key into exit 0 with a stderr warning. No code change needed.
plugin/skills/task-work/SKILL.mdStep 4 (“Initialize the worktree”) already invokes the executor with --key worktree_init --allow-empty against the project’s sdlc.yaml. No skill change needed.
plugin/conventions/sdlc-yaml.mdDocuments the worktree_init: key shape (a list of shell verbs) with worked examples. No doc change needed.

Add a worktree_init: key to the repo-root sdlc.yaml declaring - bun install, with a one-paragraph comment mirroring the file’s house style (why: every quality verb is bun-run and needs the project’s node_modules; fresh task-work worktrees start without them). The plugin machinery already consumes the key — this is pure project configuration, exactly the declared-not-inferred shape S-0003-deterministic-general-extension-points prescribes.

  1. Edit sdlc.yaml: add the worktree_init: key (a list with the single verb bun install) next to quality_checks:, with a brief comment in the file’s existing comment style.
  2. Verify the executor accepts it: from the repo root run bun run plugin/scripts/run_quality_checks.ts --config sdlc.yaml --key worktree_init --log --allow-empty — it must run bun install and exit 0 (instead of the current “no worktree_init configured” warning path).
  3. Smoke the real flow: create a throwaway worktree (git worktree add /tmp/t7pxf-smoke -b chore/t7pxf-smoke main), run the same executor invocation with --project-root /tmp/t7pxf-smoke, confirm node_modules/ appears there and a previously-failing verb (bun test plugin/cli/task_cli/) now resolves modules; tear the worktree down.
LocationKindChange
sdlc.yamlmodifyAdd worktree_init: declaring - bun install, with a house-style comment.
  • AC-1: command grep -A2 'worktree_init:' sdlc.yaml shows a list containing bun install.
  • AC-2: bun run plugin/scripts/run_quality_checks.ts --config sdlc.yaml --key worktree_init --log exits 0 having executed bun install (no “no worktree_init configured” warning).
  • AC-3: In a fresh worktree, the Step-4 invocation (--key worktree_init --allow-empty --project-root <worktree>) leaves <worktree>/node_modules/ present, and bun test plugin/cli/task_cli/ there no longer fails with Cannot find module 'eta'.
  • Implicit detection for downstream consumers — having /sdlc:setup / /sdlc:find-quality-checks probe for package.json + a bun lockfile and offer the recipe (the PR #255 design question; see Discovery context). Spawn separately if wanted; this task is the one-line declaration for this repo only.
  • Any change to run_quality_checks.ts, task-work Step 4, or the sdlc-yaml.md convention — the machinery already supports the key.
  • none

Spawned by /sdlc:spawn-task-pr on 2026-06-03 UTC from T-XD7M-retire-task-sort-stub in git@github.com:sksizer/dev.git.

Design question (PR #255 review, 2026-06-03): should the SDLC system run bun install implicitly, since bun is its runtime? Two layers to separate. The plugin’s own runtime is not what broke — plugin scripts execute from the plugin install with the plugin’s own dependencies. What failed was the project’s quality verbs (bun test over this repo’s suites) needing the project’s node_modules in a fresh worktree; this repo is the degenerate case where project == plugin. An implicit bun install in every consumer worktree would misfire on non-JS consumers (no package.json), and S-0003-deterministic-general-extension-points keeps init recipes declared, not inferred — worktree_init: is the same shape as quality_checks:. The implicit-friendly middle: /sdlc:setup / /sdlc:find-quality-checks detect package.json + a bun lockfile and offer worktree_init: ["bun install"] at setup time. Receiver should weigh folding that detection into this task or spawning it separately.

Bullet: Fresh worktree had no node_modules; the implementing sub-agent had to run bun install manually before anything worked — already tracked by T-7PXF-declare-worktree-init-bun-install; link, don’t respawn Keywords searched: t-7pxf-declare-worktree-init-bun-install, node_modules, sub-agent, worktree, manually, anything, install, tracked Excluded: T-VWH3-ts-index-generator-script Top candidates (score / status / headline):

  • 36 / closed/done / T-SIHV-task-state-frontmatter-commits-on-main-not-worktree-branch — All task-state frontmatter commits land on main; worktree branch is implementation diff only
  • 35 / closed/done / T-6HFR-orchestrator-categorized-in-flight-limits — Replace orchestrator parallelism cap with categorized in-flight limits configurable in sdlc.yaml
  • 35 / planning/backlog / T-ZFE9-task-work-uses-worktree-skill-md — task-work loads SKILL.md from the worktree, not ${CLAUDE_PLUGIN_ROOT}
  • 34 / closed/done / T-G834-move-plugin-runtime-state-to-sdlc-dir — Migrate sdlc plugin runtime state from .claude/ to .sdlc/
  • 33 / closed/superseded / T-407I-subagent-invariant-preflight-lint — Run skill-prose invariant linter inline during sub-agent edits to catch forbidden-phrase violations pre-flight Decision: SPAWNED → overridden to LINKED-EXISTING Rationale: The originating post-mortem bullet (T-VWH3-ts-index-generator-script) explicitly names this task as its tracker (“already tracked by T-7PXF…; link, don’t respawn”) and per-task inputs flagged it LINKED-EXISTING. The script scored T-7PXF below threshold (it didn’t surface in the top-5 — the task is freshly minted and shares few keywords with the bullet) but the bullet’s symptom (fresh worktree missing node_modules until a manual bun install) is exactly this task’s scope: declaring worktree_init: [“bun install”] in sdlc.yaml. Linked from: T-VWH3-ts-index-generator-script

Captured by /sdlc:task-work on 2026-06-04. PR: pending.

  • AC-1: agent-manual — grep -A2 'worktree_init:' sdlc.yaml shows a list containing bun install.
  • AC-2: agent-manual — ran run_quality_checks.ts --config sdlc.yaml --key worktree_init --log; it executed bun install and exited 0 with no “no worktree_init configured” warning.
  • AC-3: agent-manual — created a throwaway worktree from the task branch (no node_modules), ran the Step-4 invocation (--key worktree_init --allow-empty --project-root <worktree>); it installed 78 packages, node_modules/eta appeared, and bun test plugin/cli/task_cli/ there passed 15/15 (previously failed with Cannot find module 'eta').
  • The machinery was already in place — worktree_init is a schema-owned key, the executor honours --key worktree_init --allow-empty, and task-work Step 4 already invokes it. This task was pure one-line project configuration, exactly the declared-not-inferred shape the spec called for.
  • The resume path recovered cleanly: the implementation commit had already landed on the task branch, the working tree was clean, and the orphaned heartbeat from the killed run had kept the lease alive (same-host re-acquire succeeded).
  • Baseline-diff quality gate reported 12 spurious new-drift lines — all benign - OK audit-corpus rows (and the ## tasks (schema vN) — N file(s) header) that differ only because the task branch was cut from an older main carrying other in-flight tasks’ start-commits. The line-based differ over audit_entities.ts corpus listings flags task-count churn as drift even when no genuine finding changed. A gap worth closing: --diff-against-baseline should diff on genuine finding lines (DRIFT/FAIL rows) rather than the whole corpus listing, or the gate should be re-run after Step 9’s rebase so the corpus matches origin/main. (Plugin-meta: routes upstream.) → T-TWZD-normalize-baseline-diff-nondeterministic-output

← Back to Tasks