Skip to content

T-1RLU-move-sdlc-tool-to-apps-sdlc

Status: closed/done · Impact: high · Complexity: large

Today the repo root doubles as the @sksizer/sdlc package AND the monorepo workspace-root. That conflation makes the SDLC release run a whole-repo bun test (which sweeps unrelated vitest app suites) and tangles SDLC’s build and deps with the monorepo. Move the SDLC tool (plugin/) into apps/sdlc/ and slim the root into a pure workspace-root, so SDLC is one app among peers with its own scoped build/test/deps. This is Phase -1 of the distribution revamp (D-2APS-sdlc-standalone-binary-app); it lands before the binary work so that targets the final layout.

LocationRole today
package.json (root)IS the @sksizer/sdlc manifest (name, bin plugin/cli/sdlc.js, files [plugin,vendor], deps) AND the workspace-root.
plugin/ (642 files)The SDLC source tree: cli/, lib/, skills/, conventions/, .claude-plugin/, site-template/.
tsconfig*.json, sdlc.yaml, lefthook.yml, release.yml, moon.yml, .rumdl.toml, justfileEncode plugin/… paths and plugin/cli/sdlc.ts invocations.
.claude/settings.jsonRegisters the dev-repo plugin marketplace at ./plugin.
docs/planning/**The SDLC data corpus — resolved as <projectRoot>/docs/planning/…, decoupled from where code lives.

plugin/ becomes apps/sdlc/ (flat rename); the @sksizer/sdlc identity moves into apps/sdlc/package.json; root becomes a private workspace-root. The SDLC release scopes to apps/sdlc/. The published artifact keeps its inner plugin/ prefixbuild-artifact already relocates the emitted tree, so bin, NODE_MODULES_MARKETPLACE_PATH, and the release smoke stay byte-identical and zero consumer churn results. docs/planning and the rest of the monorepo stay put.

Land as ONE squash-merge (the git mv + repoints are atomic — the repo does not build in between). Ordered for reviewability:

  1. git mv plugin apps/sdlc and git mv README.md apps/sdlc/README.md as a pure move commit (git log --follow intact).
  2. tsconfig: @lib/@cli alias bases + include/exclude → apps/sdlc/….
  3. In-code source-tree literals (~15) → introduce ONE pluginSourceDir() resolver (mirroring the configurable docs_site pattern) rather than editing each.
  4. Module-relative hops: keep counts; fix the two anchors that target the app root’s parent (info-report.ts ×4, _install.ts re-descent — add an apps/sdlc candidate, keep the plugin candidate for the installed artifact).
  5. Launcher + dev use/status/link literal contract (plugin/cli/sdlc.tsapps/sdlc/cli/sdlc.ts, byte-identical across the three sites).
  6. .claude/ dev-harness repoints — CRITICAL first: .claude/settings.json marketplace ./plugin./apps/sdlc; then project-check imports/joins.
  7. build-artifact.ts: source reads → apps/sdlc; dest writes stay plugin/ (keeps the published prefix).
  8. package.json split: new apps/sdlc/package.json (identity; markdown-contract file: repointed ../../vendor/…; declare esbuild); slim root to @sksizer/dev-monorepo, add explicit apps/sdlc to workspaces; bun install.
  9. Root config invocations (sdlc.yaml, lefthook.yml, moon.yml, release.yml, .rumdl.toml, justfile, sibling moon.yml command strings).
  10. Final relink + full verification.
LocationKindChange
plugin/modifygit mvapps/sdlc/ (whole tree; internals unchanged).
README.mdmodifygit mvapps/sdlc/README.md.
package.jsonmodifySplit: identity out to apps/sdlc/package.json; root → pure workspace-root.
tsconfig.json, tsconfig.build.jsonmodifyAlias bases + include/exclude → apps/sdlc.
plugin/lib/services/plugin/ops/build-artifact.tsmodifySource reads → apps/sdlc; dest writes stay plugin/.
plugin/lib/util/*, plugin/cli/sdlc (launcher), harness/ops/_install.tsmodifyRoot/hop resolvers + launcher redirect; pluginSourceDir() resolver.
.claude/settings.json, .claude/hooks/**, .claude/scripts/**, .claude/skills/project-check/**modifyMarketplace path + skills/entities/CLI joins → apps/sdlc.
sdlc.yaml, lefthook.yml, moon.yml, .github/workflows/release.yml, .rumdl.toml, justfilemodifyInvocations plugin/cli/sdlc.tsapps/sdlc/cli/sdlc.ts; rumdl pluginapps/sdlc.
apps/sdlc/moon.ymlnewSDLC build/site moon tasks (relocated from root).
  • AC-1: git grep "plugin/cli/sdlc" ':!apps/sdlc' ':!dist-pkg' and git grep "\"plugin\"" -- apps/sdlc/lib return only intended (published-prefix) hits.
  • AC-2: bunx tsc --noEmit clean; bun run apps/sdlc/cli/sdlc.ts --help works.
  • AC-3: Bare-CLI resolver (the untested seam) — env -u CLAUDE_PLUGIN_ROOT bun run apps/sdlc/cli/sdlc.ts project doctor --output json resolves a real manifest root and version (not “unknown”).
  • AC-4: The dev repo loads the plugin (.claude/settings.json repointed) — sdlc//sdlc:info reports the loaded root = apps/sdlc.
  • AC-5: build-artifact --out dist-pkg then node dist-pkg/plugin/cli/sdlc.js project doctor work (published prefix unchanged); the bundled plugin/lib/_vendor/markdown-contract.js is present.
  • AC-6: All pre-commit gates pass; bun test and bun test ./.claude green; the release dry-run is green with the version tag reading apps/sdlc/package.json.
  • Compiling SDLC to a bun binary (the spike is proven on branch spike/bun-binary-compile; productionization is the next phase of D-2APS-sdlc-standalone-binary-app).
  • Changing the published artifact’s inner plugin/ prefix (deliberately kept).
  • A freeze window: drain/close in-flight plugin/** PRs first (a tree-rename conflicts irrecoverably with concurrent edits inside the moved tree), quiesce the orchestrator, then land in one squash-merge rebased against latest origin/main.

Surfaced across the v0.3.1 release effort: repeated plain-Node artifact regressions (a vendored markdown-contract, a .ts-source @sksizer/agent-plugin) and the whole-repo bun test sweeping vitest app suites all trace to SDLC being the repo root. A parallel workflow produced the full step-by-step plan with per-file line anchors (the biggest risk: the untested bare-CLI plugin-root resolver, AC-3).


← Back to Tasks