Skip to content

T-ITMN-skills-normalize-sdlc-launcher

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

D-0014 requires that a consumer without Bun can drive every skill. Today the skill corpus hardcodes bun run …cli/sdlc.ts in six variant shapes (~132 launcher lines), and the cli/sdlc bash shim itself hardcodes exec bun run "$here/sdlc.ts". This task makes the launcher the single invocation seam — it picks the runtime and entry per context — and rewrites every corpus invocation onto it, so the published artifact’s Node path needs zero skill edits.

LocationRole today
plugin/cli/sdlc16-line bash shim: resolves own dir, exec bun run "$here/sdlc.ts" — Bun and .ts hardcoded
plugin/skills/*/SKILL.md115 canonical bun run ${CLAUDE_PLUGIN_ROOT}cli/sdlc.ts lines across 29 skills
plugin/skills/task-review/SKILL.md3 of the 5 stray-slash …}/cli/sdlc.ts variants (others: task-define/SKILL.md, plugin/lib/model/entities/task/file-resolution.md)
plugin/conventions/commit-messages.mdteaches the hybrid bun run ${CLAUDE_PLUGIN_ROOT}cli/sdlc … shape (3 lines; also in skill-reports.md, principle-review, task-review, task-work SKILL.md)
plugin/skills/backlog-capture/SKILL.mdone of only 5 lines already in the target shape ${CLAUDE_PLUGIN_ROOT}cli/sdlc <verb> (also task-work ×2, orchestrate ×2)
plugin/cli/README.md4 repo-relative bun run plugin/cli/sdlc.ts examples
plugin/skills/orchestrate/watch_loop.shhardcodes default CLI cli="${SDLC_CLI:-bun run ${CLAUDE_PLUGIN_ROOT}cli/sdlc.ts}"
plugin/skills/CLAUDE.mdcorpus-wide skill-authoring instructions; teaches the bun run …sdlc.ts shape as the example
.claude/settings.local.jsonpermission allowlist entries keyed on the bun plugin/cli/sdlc.ts <verb> shape (need re-allowlisting when the shape changes)

Bare sdlc <verb> prose (op tables, READMEs, ~40+ sites) already matches the end state and stays.

One invocation shape corpus-wide: ${CLAUDE_PLUGIN_ROOT}cli/sdlc <verb>. The launcher resolves what runs: if a built sibling sdlc.js exists (the published artifact — T-XTGT’s layout invariant puts .js in place of .ts in the same tree), exec node "$here/sdlc.js"; otherwise exec bun run "$here/sdlc.ts" (the dev repo). Teaching docs teach the launcher shape. A gate keeps sdlc.ts invocations from re-entering the corpus.

  1. Rewrite plugin/cli/sdlc: keep the dir-resolution preamble; branch on [ -f "$here/sdlc.js" ]exec node "$here/sdlc.js" "$@", else exec bun run "$here/sdlc.ts" "$@". Fail with a clear message naming both runtimes if the required one is absent.
  2. Mechanical corpus rewrite to ${CLAUDE_PLUGIN_ROOT}cli/sdlc <verb>: the 115 canonical lines, 5 stray-slash lines, 1 bare-.ts prose ref, and 7 hybrid bun run …cli/sdlc lines (drop the bun run); the 4 repo-relative examples in plugin/cli/README.md become plugin/cli/sdlc <verb>.
  3. plugin/skills/orchestrate/watch_loop.sh: default becomes cli="${SDLC_CLI:-${CLAUDE_PLUGIN_ROOT}cli/sdlc}"; update its doc-comment.
  4. Update the teaching docs to the launcher shape: plugin/skills/CLAUDE.md, plugin/conventions/commit-messages.md, plugin/conventions/skill-reports.md, plugin/lib/model/entities/task/spawn-from-post-mortem.md, plugin/lib/model/entities/task/file-resolution.md.
  5. Extend the corpus gate: a check (new sdlc gate op or a case in the existing skill-prose gate) failing on cli/sdlc.ts or bun run ${CLAUDE_PLUGIN_ROOT} in plugin/**/*.md or plugin/skills/**/*.sh; wire into sdlc.yaml quality_checks.
  6. Re-run sdlc plugin install-permissions and refresh the .claude/settings.local.json allowlist entries pinned to the old invocation shape.
  7. Verify: bun run .claude/scripts/audit_skill_runtime.ts passes; drive the launcher live (${CLAUDE_PLUGIN_ROOT}cli/sdlc --help and one task create --dry-run); full quality suite green.
LocationKindChange
plugin/cli/sdlcmodifyruntime/entry resolution branch (node+sdlc.js when built sibling exists, else bun+sdlc.ts)
plugin/skills/*/SKILL.mdmodifyall bun run …cli/sdlc.ts variants → ${CLAUDE_PLUGIN_ROOT}cli/sdlc <verb>
plugin/skills/CLAUDE.mdmodifyteach the launcher shape in the authoring instructions
plugin/skills/orchestrate/watch_loop.shmodifySDLC_CLI default → launcher path
plugin/conventions/commit-messages.mdmodifylauncher-shape invocation examples
plugin/conventions/skill-reports.mdmodifylauncher-shape invocation example
plugin/cli/README.mdmodifyrepo-relative examples → plugin/cli/sdlc <verb>
plugin/lib/model/entities/task/spawn-from-post-mortem.mdmodifycanonical-shape lines → launcher shape
plugin/lib/model/entities/task/file-resolution.mdmodifystray-slash line → launcher shape
plugin/lib/services/gate/ops/modifycorpus-invocation gate (new op file or extension of the skill-prose gate)
sdlc.yamlmodifywire the corpus-invocation gate into quality_checks
.claude/settings.local.jsonmodifyrefresh allowlist entries pinned to the old invocation shape
  • AC-1: grep -rE 'cli/sdlc\.ts|bun run \$\{CLAUDE_PLUGIN_ROOT\}' plugin --include='*.md' --include='*.sh' returns zero matches.
  • AC-2: the launcher execs Bun+sdlc.ts in the repo (no sdlc.js sibling) and Node+sdlc.js when a built sibling is present — both branches covered by a test that stubs the sibling file.
  • AC-3: the corpus-invocation gate exits non-zero when a cli/sdlc.ts invocation is seeded into a SKILL.md, and is listed in sdlc.yaml quality_checks.
  • AC-4: bun run .claude/scripts/audit_skill_runtime.ts passes against the rewritten corpus.
  • AC-5: ${CLAUDE_PLUGIN_ROOT}cli/sdlc --help and one side-effecting verb (… task create --dry-run <slug>) run successfully through the launcher in a live session.
  • Skill-local .ts scripts run via bun run ${CLAUDE_PLUGIN_ROOT}skills/… (13 reference sites, e.g. ensure_ready_mutate.ts, dedup_search.ts): they remain Bun-dependent head-side code. D-0014 names them migration debt to be folded into registry ops; that folding is separate work.
  • Dev-repo tooling that hardcodes Bun (lefthook.yml, sdlc.yaml quality-check command strings, root package.json scripts) — dev-side per D-0014, unchanged.
  • Producing sdlc.js (T-XTGT); this task’s Node branch is dormant in the dev repo.
  • none hard. The Node branch is exercised end to end only once T-WGV4 and T-XTGT land; the branch itself is testable with a stub sibling now.
  • D-0014 Migration step 2 (launcher-normalization clause).
  • Invocation survey 2026-07-02: 115 canonical, 5 stray-slash, 1 bare-.ts, 7 hybrid, 5 already-target, 4 repo-relative lines, plus watch_loop.sh’s SDLC_CLI default.

← Back to Tasks