Skip to content

Upgrading to v6

Nothing rewrites an existing project without asking. But v6 is not a drop-in: it refuses the verbs, flags and config keys it retired, each by name with its replacement, and migrate --apply carries the project across.

6.1 retires the handoff writers and one config key, so a 6.0 project takes three steps: reinstall, then run migrate and migrate --apply in each project.

Terminal window
curl -fsSL https://raw.githubusercontent.com/DarrenBenson/sdlc-studio/main/install.sh \
| SDLC_STUDIO_REQUIRE_CHECKSUM=1 bash -s -- --version v6.1.0
/sdlc-studio migrate # a dry run: lists what it would change, writes nothing
/sdlc-studio migrate --apply # removes review.policy, restamps the project version
  • Reinstall. A plain install.sh or install.ps1 now fetches the latest verified release; the command above pins 6.1.0 and makes the checksum mandatory. Pass --version main for the moving branch.
  • migrate is needed. migrate --apply removes review.policy from sdlc-studio/.config.yaml, the one key 6.1 retires, keeping every other byte. Every project now carries a unit whose REJECT stands at the review cap (review.max_rounds), filing its findings as a bug.
  • What it names, and what it cannot see. Both runs name each line of your markdown docs that uses a retired handoff command, with what replaced it; in the root AGENTS.md and CLAUDE.md they name only handoff.py generate. Neither reads your CI files or scripts, so search those yourself: a CI job that runs gate.py --require-handoff is refused by the gate, not named by migrate.
Retired or changed in 6.1 Use instead
handoff.py generate, artifact.py new --type handoff the signed sprint report hands over the remaining work: sprint.py sign seals it, and sprint.py plan --worklist RPTxxxx plans its open items as the next run
gate.py --require-handoff nothing: the signed report is the run’s hand-over, and the close’s gate runs without it
review.policy (key) nothing to choose; migrate --apply removes it
a plain install tracking main a plain install takes the latest published release; --version main (-Version main for install.ps1) keeps the moving branch
--target copilot writing the current directory’s .github/skills it writes ~/.agents/skills, the folder Copilot CLI reads; --local still writes the repository’s .github/skills
the release gate’s revert-check lane a tag runs release-rehearsal and module-alone beside the full suite; verify_ac.py revert-check --unit <id> stays for one unit
validate.py check outside a workspace, at exit 0 it exits 1 where there is no sdlc-studio/ workspace, and says so

The HO files already in sdlc-studio/handoffs/ stay readable: they resolve by id, reconcile cleanly and are never rewritten, and handoff.py show still prints the remaining work without writing anything. Release 6.1.0 says what else changed.

/sdlc-studio migrate # a dry run: what it would change
/sdlc-studio migrate --apply # carry the project across

That is the upgrade, once the v6 skill is installed: re-run the installer, or /sdlc-studio skill-update, which offers the latest published release. Then run migrate in each project.

migrate --apply removes every retired .config.yaml key with its children, keeping every other byte, strips the two retired [check:] tags from the Definition of Ready and Done while keeping each criterion as a human-judged line, and restamps the project version. Three things it leaves to you, and names:

  • Instruction files. Each AGENTS.md, CLAUDE.md, DoR or DoD line naming a retired key or verb is reported by file and line, never rewritten. Edit those by judgement.
  • Your own scripts and CI. migrate cannot see them. Search them for each verb and flag in the CHANGELOG’s 6.0.0 Breaking inventory; the retired plan_review.py, repair_plan.py and validate.py warning-ratchet are not reported by migrate at all.
  • The frozen review records under sdlc-studio/reviews/ are listed as history and left as written. Nothing needs deleting.

v5 had grown ceremony around every unit: a plan review before code, a test plan, registered mutants for each repair, a written repair design after a REJECT, an evidence row, a batch review, and a sign-off per unit. v6 removes that stack and keeps what catches defects - acceptance criteria that run, and a review by someone other than the author.

The loop, as it runs now:

  • A Sprint Goal of 20 words or fewer, traced to an outcome or a persona with sprint plan --serves. The seats’ read of the goal is advice printed with the plan; it no longer stops it.
  • One independent reviewer per unit, briefed with critic.py brief and recorded with critic.py record, in at most two rounds. A unit still rejected at the cap is carried as a known issue, not reviewed a third time.
  • One verdict ledger. critic.py record decides whether a unit was reviewed, and every reader - conformance, the close, the signature, the report - decides from it.
  • Close once, sign once. sprint close runs in one pass and files a one-page report that states every known issue. sprint.py sign --report RPTxxxx --principal "<name>" seals it, once per run.
  • A unit closes on its criteria. No test plan, plan review or registered mutant is asked for. mutation.py run still measures a suite on demand, and line coverage runs only when a project opts in.

Each retired verb and flag is refused by name - exit 2, the reason and the replacement printed, nothing written - or meets argparse’s usage error. The ones most likely to be in your fingers or your scripts:

Before (v5) In v6
critic.py signoff, and signing through the close sprint close once, then sprint.py sign --report RPTxxxx --principal "<name>" once
critic.py evidence, critic.py sprint-review, the batch-review verb critic.py record, one delivery verdict per unit
critic.py repair a round-two critic.py record from the same reviewer, or carry the unit at the cap
mutation.py register, retract, retractions, audit nothing to record; mutation.py run --story <id> measures on demand
plan_review.py, verify_ac.py testplan nothing; a unit’s criteria and Verify: selectors are its plan
the separate close pre-flight verb sprint.py close --retro RETROxxxx --dry-run
sprint plan --override-goal-review drop it; the goal read is advice

Config keys that changed:

Key In v6
review.test_plan_after, review.signoff, review.mutation_evidence, review.line_coverage_after, the plan_review block and the other retired review cutoffs read by nothing; migrate --apply removes them
review.line_coverage default now off. Set report or block to keep measuring
triage.low_consolidation default now false: a Low finding mints its own bug. Set true to keep consolidating

The full inventory - every retired verb, flag, config key, check id and gate lane, each with its migration - is the 6.0.0 Breaking section of the CHANGELOG.

If you have used SDLC Studio since the early, mostly human-driven days, the tool has grown a lot of discipline. The same migrate does the mechanical part: it reviews every artefact, applies the deterministic set - conventions, version, sizing - and reports the judgement calls with the command that fixes each.

What is new to learn:

  • The two-backlog model. The single biggest shift: a request (CR/RFC) is not work until refine sizes it into delivery units.
  • Sizing is compulsory. Delivery units carry points (stories and bugs) or a T-shirt size (CRs, RFCs, epics). sprint plan refuses a unit with no Affects or Points: - and that gate is on by default, so it fires on the first plan over an old backlog. Groom the units you are about to plan, or record sprint.breakdown: judgement as a deliberate decision.
  • The sprint. A deliberate batch driven to a goal, each unit reviewed independently, closed once and signed once.

The two-backlog gates are the deliberate exception: off until you set two_backlog.enforce: true in .config.yaml, after refine-ing the accepted requests into sized delivery work. The sizing migration only adds a Size: line and the workflow is one config line, so that part of the upgrade is reversible.

New projects mint collision-free ULIDs (US-01JQK3F8) so parallel agents never fight over sequential ids. An existing project is asked the numbering question explicitly on upgrade, with three supported answers - migrate everything, adopt forward-only, or stay sequential - and it is never auto-flipped.