Skip to content

/sdlc:migrate-runtime-state

Generated from solutions/ontological/skills/migrate-runtime-state/SKILL.md.

Move SDLC-plugin runtime state from the legacy .claude/ location to .sdlc/ in a consuming project (worktrees, pr-cursors, orchestrator-log). Idempotent — re-running on an already-migrated project is a no-op. Operates directly on the main repo, since the things being moved are worktrees.

  • Bash

Usage:

  • /sdlc:migrate-runtime-state — move every piece of legacy SDLC-plugin runtime state from .claude/ to .sdlc/ in the current project. PR cursors are discarded by default (they regenerate on the next /sdlc:pr-check tick).
  • /sdlc:migrate-runtime-state --preserve-cursors — move PR cursors to .sdlc/pr-cursors/ instead of discarding them.
  • /sdlc:migrate-runtime-state --dry-run — report what would change without moving or deleting anything.

Project context (don’t re-derive every run):

  • Three buckets move:
    1. Worktrees: every subdir under .claude/worktrees/<basename>/ becomes .sdlc/worktrees/<basename>/ via git worktree move. Idempotent — a worktree already at the destination is skipped silently.
    2. PR cursors: .claude/pr-cursors/<pr>.json. Discarded by default; cursors regenerate on the next /sdlc:pr-check tick. Pass --preserve-cursors to move them to .sdlc/pr-cursors/ instead.
    3. Orchestrator log: .claude/orchestrator-log.md moves to .sdlc/orchestrator-log.md. If a log already exists at the destination (rare — both coexisted somehow), the source is appended with a separator line.
  • Operate on the main repo; do NOT add a worktree. Run the script in the main repo. Do not wrap it in git worktree add — a new worktree would land under .claude/worktrees/ and itself need migrating.
  • Do not commit. The migrated state lives in gitignored directories (.claude/* and .sdlc/*). Just run the script and report the marker line.
  • Idempotent. Re-running after a successful migration emits NOTHING-TO-MIGRATE and exits 0.

From the project root:

bun run ${CLAUDE_PLUGIN_ROOT}skills/migrate-runtime-state/migrate_runtime_state.ts

Forward any flags the user passed (--dry-run, --preserve-cursors).

The script emits exactly one summary line on stdout:

  • MIGRATED worktrees=N pr-cursors=M orchestrator-log=<moved|absent|merged> — success; at least one bucket changed.
  • NOTHING-TO-MIGRATE — all three buckets were absent or already migrated. The project is already on the new layout.
  • DRY-RUN worktrees=N pr-cursors=M orchestrator-log=<would-move|absent|would-merge>--dry-run summary.
  • ERROR reason="<diagnostic>" — failure. Details on stderr.

Surface the marker plus a one-line interpretation:

  • On MIGRATED: list what moved. If pr-cursors=N and --preserve-cursors was NOT passed, note that N cursor file(s) were discarded (they regenerate on the next /sdlc:pr-check tick).
  • On NOTHING-TO-MIGRATE: tell the user plainly — the project is already on the new layout.
  • On DRY-RUN: surface the marker as-is plus a one-line “to apply, re-run without —dry-run.”
  • On ERROR: surface the stderr details too so the user can act on the failure.
  • git worktree move fails — most often because the worktree at the source has uncommitted changes git refuses to move, or because the destination basename is already taken. The script captures git’s stderr; surface it to the user. Fix the underlying state (commit/stash, or move/remove the conflicting destination) and re-run.
  • PR cursor with name collision--preserve-cursors won’t clobber an existing cursor at the destination. The cursor stays at the source and the run errors. Delete the conflicting destination file (or accept the default discard behavior) and re-run.
  • Orchestrator log merge fails — both source and destination present and the append-with-separator path errored on write. Inspect both files; concatenate manually if needed.
  • Discarded cursors. Pass --preserve-cursors only when an active PR mid-cycle has a review-comment offset that must survive; otherwise let the default discard them and /sdlc:pr-check regenerates them on its next tick.
  • Run right after a plugin upgrade, before any other worktree-creating SDLC verb, so runtime state doesn’t split across .claude/ and .sdlc/. The umbrella /sdlc:migrate is the canonical entry point.
  • Eval suite. ${CLAUDE_PLUGIN_ROOT}skills/migrate-runtime-state/tests/migrate_runtime_state.test.ts validates the round-trip against a fixture project. Run it before changing migrate_runtime_state.ts.