Skip to main content

milestone

Manage milestones: new, complete, audit, gaps.

Stars
17
Source
SienkLogic/plan-build-run
Updated
2026-04-03
Slug
SienkLogic--plan-build-run--milestone
View on GitHubRaw SKILL.md

// install — copy + paste into any project

mkdir -p .claude/skills && curl -fsSL https://raw.githubusercontent.com/SienkLogic/plan-build-run/HEAD/plugins/pbr/skills/milestone/SKILL.md -o .claude/skills/milestone.md

Drops the SKILL.md into .claude/skills/milestone.md. Works with Claude Code, Cursor, and any agent that loads SKILL.md files from .claude/skills/.

STOP — DO NOT READ THIS FILE. You are already reading it. This prompt was injected into your context by Claude Code's plugin system. Using the Read tool on this SKILL.md file wastes ~7,600 tokens. Begin executing Step 1 immediately.

Step 0 — Immediate Output

Before ANY tool calls, display this banner:

╔══════════════════════════════════════════════════════════════╗
║  PLAN-BUILD-RUN ► MILESTONE                                  ║
╚══════════════════════════════════════════════════════════════╝

Then proceed to Step 1.

/pbr:milestone — Milestone Management

You are running the milestone skill. Milestones represent significant project checkpoints — a set of phases that together deliver a cohesive chunk of functionality. This skill handles the full milestone lifecycle: creation, completion, auditing, and gap analysis.

This skill runs inline for most subcommands, but spawns agents for audit.

References

  • references/questioning.md — Questioning patterns for milestone review decisions
  • references/ui-brand.md — Status symbols, banners, milestone celebration format

Context Budget

Reference: skills/shared/context-budget.md for the universal orchestrator rules. Reference: skills/shared/agent-type-resolution.md for agent type fallback when spawning Task() subagents.

Additionally for this skill:

  • Never perform integration checks yourself — delegate to the integration-checker subagent
  • Minimize reading audit and verification outputs — read only frontmatter and status fields
  • Delegate all cross-phase integration analysis to the integration-checker subagent

Multi-Session Sync

Before any phase-modifying operations (archiving phases, updating ROADMAP.md/STATE.md/PROJECT.md), acquire a claim:

acquireClaim(planningDir, sessionId)

If the claim fails (another session owns this project), display: "Another session owns this project. Use /pbr:progress to see active claims."

On completion or error (including all exit paths), release the claim:

releaseClaim(planningDir, sessionId)

Core Principle

Milestones are the rhythm of the project. They force you to step back, verify everything works together, and create a clean snapshot before moving on. Never skip the audit — integration issues hide at milestone boundaries.


Argument Parsing

Parse $ARGUMENTS for the subcommand and optional version:

$ARGUMENTS format: {subcommand} [{version/name}]

Examples:
  "new"              → subcommand=new, arg=none
  "new User Auth"    → subcommand=new, arg="User Auth"
  "complete v1.0"    → subcommand=complete, arg="v1.0"
  "complete 1.0"     → subcommand=complete, arg="v1.0" (auto-prefix v)
  "preview v1.0"     → subcommand=preview, arg="v1.0"
  "audit v1.0"       → subcommand=audit, arg="v1.0"
  "audit"            → subcommand=audit, arg=current milestone
  "gaps"             → subcommand=gaps, arg=most recent audit

If no subcommand recognized: Show usage:

Usage: /pbr:milestone <subcommand> [version]

Subcommands:
  new [name]       — Start a new milestone cycle
  complete [ver]   — Archive completed milestone
  preview [ver]    — Dry-run of complete (show what would happen)
  audit [ver]      — Verify milestone completion
  gaps             — Create phases to close audit gaps

CRITICAL — After parsing the subcommand, run init command before any manual state reads:

node plugins/pbr/scripts/pbr-tools.js init milestone

Store the JSON result as blob. This single call replaces multiple file reads across all subcommands:

  • blob.state.current_phase, blob.state.status — current phase and status from STATE.md
  • blob.state.last_milestone_version, blob.state.last_milestone_completed — milestone history
  • blob.has_roadmap — whether ROADMAP.md exists
  • blob.has_project — whether PROJECT.md exists
  • blob.milestones — array of milestone sections parsed from ROADMAP.md (each with name and phases_range)
  • blob.existing_archives — array of existing archive directory names
  • blob.phase_count — total phase count
  • blob.config.mode, blob.config.planning, blob.config.git — config settings

If blob.error is set, display the error banner and stop (no project found).


Subcommand: new

Start a new milestone cycle with new phases.

Flow

  1. Read current state from init blob:

    • blob.milestones for existing milestone sections from ROADMAP.md
    • blob.state.current_phase and blob.state.status for current position
    • blob.has_project to check if PROJECT.md exists (read it for milestone history if needed)
    • blob.phase_count for total phase count
  2. Get milestone details via AskUserQuestion:

    • "What's the name/goal for this new milestone?"
    • "What are the major features or capabilities it should deliver?"
    • If the user provided a name in $ARGUMENTS, use it and skip the name question
  3. Determine phase numbering:

    • Find the highest phase number in the current ROADMAP.md
    • New phases start at highest + 1
    • Example: if phases 1-5 exist, new milestone starts at phase 6
  4. Mini roadmap session: Run a condensed version of the /pbr:new-project questioning flow:

    a. Ask about major components needed (via AskUserQuestion):

    • "What are the 2-5 major areas of work for this milestone?"

    b. For each area, ask:

    • "Any specific requirements or constraints for {area}?"

    c. Generate phases from the areas:

    • Each major area becomes a phase
    • Order by dependency (foundations first)
    • Include brief description and success criteria
  5. Update ROADMAP.md: Append new milestone section:

    ---
    
    ## Milestone: {name}
    
    **Goal:** {goal statement}
    **Phases:** {start_num} - {end_num}
    
    ### Phase {N}: {name}
    **Goal:** {goal}
    **Requirements:** {REQ-IDs mapped to this phase}
    **Success Criteria:** {verifiable conditions for phase completion}
    **Depends on:** {prior phases}
    
    ### Phase {N+1}: {name}
    ...
    
  6. Create phase directories: For each new phase:

    .planning/phases/{NN}-{slug}/
    
  7. Update PROJECT.md (create if needed): Add milestone to the active milestones list:

    ## Active Milestones
    
    ### {name}
    - **Phases:** {start} - {end}
    - **Created:** {date}
    - **Status:** In progress
    

CRITICAL (no hook) -- DO NOT SKIP: Update STATE.md frontmatter AND body with new milestone info.

  1. Update STATE.md:
    • Set current phase to the first new phase
    • Update milestone info

CRITICAL (no hook) -- DO NOT SKIP: Generate root MILESTONE.md file.

8b. Generate root MILESTONE.md: Read the current milestone section from ROADMAP.md (the ## Milestone: section just created in Step 5) and STATE.md for current phase and status. Write MILESTONE.md at the project root with:

# Current Milestone: {name}
**Version:** {version} | **Status:** In Progress | **Created:** {date}

**Goal:** {goal}

## Phases
| Phase | Goal | Status |
|-------|------|--------|
| {N}. {name} | {goal} | Pending |
...

---
*Auto-generated by `/pbr:milestone new`. Updated by `/pbr:autonomous`.*
  • Read the phase list from the ROADMAP.md section just written in Step 5
  • Status column: "Pending" for all new phases

Milestone branch creation (when git.branching is 'milestone'): When starting a new milestone and git.branching is milestone:

  • Create branch: git switch -c pbr/milestone-v{version}
  • All phase work happens on this branch
  • Branch is merged when /pbr:milestone complete is run
  1. Commit if planning.commit_docs: true:

    docs(planning): start milestone "{name}" (phases {start}-{end})
    
  2. Confirm with branded output — read ${CLAUDE_SKILL_DIR}/templates/new-output.md.tmpl and fill in {name} (milestone name), {count} (phase count), {N} (first phase number).


Subcommand: preview

Dry-run of milestone completion — shows what would happen without making any changes.

Flow

  1. Determine version:

    • Same logic as complete: use $ARGUMENTS or ask via AskUserQuestion
  2. Identify milestone phases:

    • Read ROADMAP.md to find phases belonging to this milestone
    • List each phase with its current status (from STATE.md or VERIFICATION.md)
  3. Verification status check:

    • For each milestone phase, check if VERIFICATION.md exists and its result frontmatter
    • Flag phases that are unverified or have stale verification (SUMMARY.md newer than VERIFICATION.md)
  4. Preview archive structure:

    • Show what the archive directory would look like:
      .planning/milestones/v{version}/
      ├── ROADMAP.md (snapshot)
      ├── STATS.md (would be generated)
      ├── REQUIREMENTS.md (snapshot)
      └── phases/
          ├── {NN}-{slug}/ (moved from .planning/phases/)
          │   ├── PLAN-01.md
          │   ├── SUMMARY.md
          │   └── VERIFICATION.md
          └── ...
      
  5. Show what would change:

    • Which phase directories would be moved
    • What ROADMAP.md section would be collapsed
    • What STATE.md updates would occur
    • What git tag would be created
  6. Display summary:

    ╔══════════════════════════════════════════════════════════════╗
    ║  PLAN-BUILD-RUN ► MILESTONE PREVIEW — v{version}             ║
    ╚══════════════════════════════════════════════════════════════╝
    
    Phases to archive: {count}
    ✓ Verified: {verified_count}
    ⚠ Unverified: {unverified_count}
    ⚠ Stale verification: {stale_count}
    
    Archive location: .planning/milestones/v{version}/
    Git tag: v{version}
    
    Ready to complete? Run: /pbr:complete-milestone v{version}
    

CRITICAL (no hook): This subcommand is READ-ONLY. Do not create directories, move files, modify STATE.md, modify ROADMAP.md, or create git tags. Only read and display.


Subcommand: complete

Archive a completed milestone and prepare for the next one.

Flow

  1. Determine version:

    • If provided in $ARGUMENTS: use it (auto-prefix v if missing)
    • If not provided: ask via AskUserQuestion: "What version number for this milestone? (e.g., v1.0)"
  2. Check verification debt across ALL phases:

    • Use blob.milestones to find the target milestone's phase range
    • For each phase in the range, check VERIFICATION.md status:
      • gaps_found or human_needed or partial → verification debt exists
    • If verification debt found, display warning:
      Verification Debt:
        - Phase {N}: {status} ({count} outstanding items)
      
    • This is non-blocking but prominently displayed before the completion decision
  3. Verify all phases are complete:

    • For each phase in the range, check for VERIFICATION.md

    • If any phase lacks VERIFICATION.md:

      Present the warning context: Unverified phases:

      • Phase {N}: {name}
      • Phase {M}: {name}

      CRITICAL -- DO NOT SKIP: Present the following choice to the user via AskUserQuestion before proceeding: Use AskUserQuestion (pattern: yes-no from skills/shared/gate-prompts.md): question: "{count} phases haven't been verified. Continue with milestone completion?" header: "Unverified" options: - label: "Continue anyway" description: "Proceed despite unverified phases (not recommended)" - label: "Stop and review" description: "Run /pbr:verify-work for unverified phases first"

      • If "Stop and review" or "Other": stop and suggest the review commands for each unverified phase
      • If "Continue anyway": proceed with warning noted

    Timestamp freshness check: For each phase that has a VERIFICATION.md, compare its checked_at frontmatter timestamp against the most recent SUMMARY.md file modification date in that phase directory (use ls -t or file stats). If any SUMMARY.md is newer than its VERIFICATION.md checked_at:

    • Warn: "Phase {N} ({name}) was modified after verification. The VERIFICATION.md may not reflect the current code state."
    • List affected phases with their freshness details

    CRITICAL -- DO NOT SKIP: Present the following choice to the user via AskUserQuestion before proceeding: Use AskUserQuestion (pattern: stale-continue from skills/shared/gate-prompts.md): question: "{count} phases were modified after verification. Re-verify or continue?" header: "Stale" options: - label: "Re-verify" description: "Run /pbr:verify-work for affected phases (recommended)" - label: "Continue anyway" description: "Proceed with potentially outdated verification"

    • If "Re-verify" or "Other": suggest the review commands for affected phases and stop
    • If "Continue anyway": proceed with warning noted
  4. Gather milestone stats:

    # Get commit range for this milestone's phases
    git log --oneline --since="{milestone start date}" --until="now"
    
    # Count files changed
    git diff --stat {first_milestone_commit}..HEAD
    

    Collect:

    • Total commits in milestone
    • Total files changed
    • Lines added / removed
    • Duration (start date to now)
    • Number of phases completed
    • Number of plans executed
    • Number of quick tasks
  5. Extract accomplishments: Read all SUMMARY.md files for milestone phases:

    • Collect provides fields (what was built)
    • Collect key_decisions fields
    • Collect patterns fields
    • Collect tech_stack union

Milestone branching (config-gated): Read blob.config.git.branching (or fall back to reading config if blob unavailable).

  • If milestone: a. Check if milestone branch exists: git branch --list pbr/milestone-v{version} b. If branch exists:
    • Use AskUserQuestion: question: "Milestone v{version} complete. Merge branch pbr/milestone-v{version} to main?" header: "Merge milestone branch?" options:
      • label: "Yes, merge" description: "Merge milestone branch to main and delete it"
      • label: "No, keep" description: "Keep the branch for manual review"
    • If "Yes, merge":
      1. git switch main
      2. git merge --no-ff pbr/milestone-v{version} (no-ff to preserve milestone history)
      3. git branch -d pbr/milestone-v{version}
      4. Log: "Milestone branch merged and deleted"
    • If "No, keep": leave branch as-is c. If branch does not exist: no action (phases were on main or individual phase branches)
  • If none, phase, or disabled: no milestone branch operations
  1. Archive milestone documents:

    CRITICAL (no hook): Pre-flight safety checks BEFORE archiving. Do NOT skip this step.

    Before creating or moving anything, verify the destination is safe:

    • Check blob.existing_archives to see if the version directory already exists
    • If it exists AND contains files (phases/, STATS.md, etc.), STOP and display:
      ╔══════════════════════════════════════════════════════════════╗
      ║  ERROR                                                       ║
      ╚══════════════════════════════════════════════════════════════╝
      
      Archive destination `.planning/milestones/{version}/` already contains files.
      Completing this milestone would overwrite the existing archive.
      
      **To fix:** Run `/pbr:health` or manually inspect `.planning/milestones/{version}/`.
      Use a different version number (e.g., {version}.1) or remove the existing archive first.
      
      Ask the user via AskUserQuestion whether to use a different version or abort.
    • Verify each source phase directory exists before attempting to move it
    • If any source phase directory is missing, warn but continue with the phases that do exist

    CRITICAL (no hook): Back up ROADMAP.md BEFORE any destructive operations. Do NOT skip this step.

    Use the compound init-milestone command to atomically create the archive directory, copy ROADMAP.md, copy REQUIREMENTS.md (if present), and update STATE.md:

    pbr-tools compound init-milestone {version} --name "{milestone_name}" --phases "{start}-{end}"
    

    This MUST happen before any of the following: moving phase directories, collapsing ROADMAP.md sections, or further STATE.md updates.

    The compound command creates the archive directory and copies ROADMAP.md + REQUIREMENTS.md. Now move phase directories and create STATS.md:

    • .planning/milestones/{version}/STATS.md — milestone statistics
    • .planning/milestones/{version}/phases/{NN}-{slug}/ — move each milestone phase directory from .planning/phases/ into the archive

    CRITICAL (no hook): Move phase directories from .planning/phases/ to archive NOW. Do NOT skip this step.

    Move phases: For each phase belonging to this milestone, move (not copy) its directory from .planning/phases/{NN}-{slug}/ to .planning/milestones/{version}/phases/{NN}-{slug}/. This keeps the active phases directory clean for the next milestone.

    CRITICAL (no hook): Write STATS.md to .planning/milestones/{version}/STATS.md NOW. Do NOT skip this step.

    Stats file content:

    Read ${CLAUDE_SKILL_DIR}/templates/stats-file.md.tmpl for the stats file format. Fill in all {variable} placeholders with actual data gathered in Steps 3-4.

5b. Archive stale research data:

After archiving phase directories, prune stale research/intel/codebase data that predates the milestone:

pbr-tools data prune --before {milestone_start_date}

Where {milestone_start_date} is the earliest phase start date from the milestone (derived from the first SUMMARY.md start_time or the milestone creation date).

  • Log the count of archived files (e.g., "Archived 12 stale research files")
  • If no files to archive, log "No stale research files to archive"
  • Note: SUMMARY.md, STACK.md, and FEATURES.md are preserved (never pruned) since they are canonical references for active work
  1. Update PROJECT.md:

    • Move milestone from "Active" to "Completed"
    • Add completion date and version tag
    ## Completed Milestones
    
    ### {name} ({version})
    - **Completed:** {date}
    - **Phases:** {start} - {end}
    - **Key deliverables:** {summary}
    
    • Move validated requirements from active to completed section

CRITICAL (no hook): Run PROJECT.md evolution review NOW. Do NOT skip this step.

6b. PROJECT.md Evolution Review: After moving the milestone to completed status, review and evolve the project definition:

  1. Move completed Active Requirements to Validated — Any requirement from the completed milestone that was satisfied (per VERIFICATION.md) should move from Active to Validated section
  2. Review Out of Scope — Check if any previously out-of-scope items are now unblocked by the completed milestone's deliverables. If so, note them for the user's consideration (do not move them automatically)
  3. Annotate Key Decisions with outcomes — For each Key Decision in PROJECT.md that relates to the completed milestone, add an Outcome column value: Good (decision worked well), Revisit (decision caused issues), or Pending (outcome not yet clear)
  4. Update Constraints — Remove or update any constraints that changed during the milestone (e.g., a technology constraint that was relaxed)
  5. Refresh Core Value — If the project direction shifted meaningfully during the milestone, suggest an updated Core Value statement to the user via AskUserQuestion

CRITICAL (no hook): Update ROADMAP.md with collapsed milestone section NOW. Do NOT skip this step.

  1. Collapse completed phases in ROADMAP.md: Replace detailed phase entries with a <details> collapsed summary (backward compat: also recognized by -- COMPLETED text):

    <details>
    <summary>## Milestone: {name} ({version}) — SHIPPED {date}</summary>
    
    | Phase | Status |
    |-------|--------|
    | {N}. {name} | Completed |
    | {N+1}. {name} | Completed |
    
    Completed: {date} | Archive: `.planning/milestones/{version}/`
    
    </details>
    

7a. Update milestone index: After collapsing the milestone, update or create a ## Milestones index section near the top of ROADMAP.md (after the title, before the first active milestone). Each entry is one line:

## Milestones

| Version | Name | Status | Date |
|---------|------|--------|------|
| {version} | {name} | SHIPPED | {date} |

If the section already exists, append a row. If it does not exist, create it.

CRITICAL (no hook): Update STATE.md to mark milestone as complete NOW. Do NOT skip this step.

7b. Update STATE.md:

  • Update .planning/STATE.md frontmatter to reset to idle state:
    • current_phase: null
    • phase_slug: null
    • phase_name: null
    • phases_total: 0
    • status: "idle"
    • progress_percent: 0
    • plans_total: 0
    • plans_complete: 0
    • last_activity: "{date} Milestone {version} complete"
  • Update the body section to reflect idle state (no active phase)

7c. Record milestone completion in STATE.md frontmatter:

  • Update STATE.md frontmatter with milestone completion data:
    • Set last_milestone_version: "{version}"
    • Set last_milestone_completed: "{ISO datetime}"
  • Do NOT write to a ## History section in STATE.md — History has been removed from STATE.md to keep it lean. Milestone completion records are preserved in the archive's STATS.md and ROADMAP.md snapshot.
  • If a ## History section exists in STATE.md (from a prior version), remove it during milestone completion to enforce the new format.

Run state reconcile after archival to reset phases_total and current_phase to reflect the next milestone's phases:

pbr-tools state reconcile

This command re-derives phase counts from ROADMAP.md and reports any phantom phase rows (progress table rows with no corresponding directory on disk). Review and remove phantom rows manually if no longer needed.

CRITICAL (no hook): Reconcile ROADMAP phase statuses NOW. Do NOT skip this step.

7c2. ROADMAP Reconciliation: After state reconcile, run a full reconciliation pass to fix any stale phase statuses across the entire ROADMAP:

pbr-tools roadmap reconcile
  • Log the output (number of entries fixed)
  • This catches phase status mismatches that accumulated during the milestone lifecycle
  • Covers both the just-completed milestone and any prior stale entries

7d. Aggregate learnings into KNOWLEDGE.md from milestone phases:

CRITICAL (no hook): Run learnings aggregation NOW. Do NOT skip this step.

node ${CLAUDE_PLUGIN_ROOT}/scripts/milestone-learnings.js .planning/milestones/{version} --project {project-name-from-STATE.md}

This script aggregates SUMMARY.md patterns, decisions, and deferred items into the project-scoped .planning/KNOWLEDGE.md (table format with K/P/L-prefixed IDs). It also writes to the global ~/.claude/learnings.jsonl for cross-project use.

  • If the script outputs an error, log it but do NOT abort milestone completion — learnings aggregation is advisory.
  • Display the aggregation summary line to the user (e.g., "KNOWLEDGE.md: 5 new entries, 2 duplicates skipped").
  • After aggregation, check for triggered deferral thresholds:
pbr-tools learnings check-thresholds

If any thresholds are triggered, display each as a notification:

Note: Learnings threshold met — {key}: {trigger}. Consider implementing the deferred feature.

7e. Run calibration for all evaluative agents on expanded corpus:

pbr-tools calibrate all

This re-analyzes corpus data for all evaluative agents (verifier, audit, integration-checker, plan-checker) and updates .planning/intel/{agent}-calibration.md with gap patterns and recommendations. The calibration data informs each agent's few-shot examples.

  • If the command fails, log it but do NOT abort — calibration is advisory.
  • Display per-agent corpus size and pass rate summary to the user.
  • If any agent has recommendations, note: "Calibration updated for {agents}. Review few-shot examples to apply findings."
  1. Git tag:

    git tag -a {version} -m "Milestone: {name}"
    
  2. Generate RETROSPECTIVE.md:

    The CLI (pbr-tools.js milestone complete) auto-generates a RETROSPECTIVE.md entry. Verify it exists at .planning/RETROSPECTIVE.md. If the CLI was not used (manual completion), create the entry using ${CLAUDE_PLUGIN_ROOT}/templates/RETROSPECTIVE.md.tmpl as the format reference. Fill in {version}, {name}, {date}, and the "What Was Built" section from MILESTONES.md accomplishments. Leave other sections as placeholders for the user to fill.

9aa. Insights integration:

Check for a recent /insights HTML report:

find ~/.claude/insights/ -name "*.html" -mtime -7 2>/dev/null | head -1

If a recent report exists (modified within 7 days):

  1. Read the HTML file and extract key workflow findings (friction patterns, efficiency suggestions, recurring issues)
  2. Append a "## Workflow Insights" section to .planning/RETROSPECTIVE.md with 3-5 bullet points summarizing the most relevant insights for this milestone's work
  3. Add the RETROSPECTIVE.md to the git staging area

If no recent report exists: Display this suggestion after the RETROSPECTIVE.md is generated:

Tip: Run /insights to capture workflow patterns from this milestone's sessions.
     Insights feed into future audits and help the planner avoid repeated friction.

9a. Commit:

git add .planning/milestones/ .planning/phases/ .planning/ROADMAP.md .planning/PROJECT.md .planning/STATE.md .planning/RETROSPECTIVE.md
git commit -m "docs(planning): complete milestone {version}"

CRITICAL (no hook): Generate changelog entry NOW. Do NOT skip this step.

9b. Generate changelog entry:

Generate a user-facing changelog entry for this milestone. Read all SUMMARY.md files from the milestone phases (now in .planning/milestones/{version}/phases/) and categorize deliverables into Keep a Changelog sections:

  • Added — New features, commands, capabilities (from SUMMARY.md provides fields)
  • Changed — Modifications to existing behavior, UI updates, performance improvements
  • Fixed — Bug fixes, error corrections (from commits with fix: type)

Format each entry with a bolded feature name followed by an em-dash and description:

### Added
- **Feature name** — What it does and why it matters
- **Another feature** — Description focusing on user impact

Rules for good entries:

  • Lead with the user-visible impact, not the implementation detail
  • Group related commits into a single entry (e.g., 5 commits for "auth" become one "Authentication system" entry)
  • Use bold feature names, not commit scopes
  • No commit hashes — this is prose, not a git log
  • No internal scopes (phase-plan numbers, TDD markers)
  • End with install line: Install/upgrade: \npx @sienklogic/plan-build-run@latest``

Draft the full entry and present it to the user for review:

Use AskUserQuestion:

question: "Here's the draft changelog for {version}. Want to edit it before writing?"
header: "Changelog"
options:
  - label: "Looks good"        description: "Write this to CHANGELOG.md as-is"
  - label: "Edit"              description: "I'll provide corrections"
  - label: "Skip changelog"    description: "Don't update the changelog for this release"
  • If "Looks good": write the entry to CHANGELOG.md (insert after the header, before any existing version entries)
  • If "Edit" or "Other": apply the user's corrections, then present again for final confirmation
  • If "Skip changelog": proceed without changelog update

If writing to CHANGELOG.md:

git add CHANGELOG.md
git commit -m "docs: update changelog for {version}"

9c. Push milestone to remote:

Use AskUserQuestion to ask the user how they want to publish the milestone:

question: "How should this milestone be published to GitHub?"
header: "Publish"
options:
  - label: "Push tag + commits"    description: "Push the v{version} tag and any unpushed commits to origin"
  - label: "Skip for now"          description: "Keep everything local — push later manually"
  • If "Push tag + commits": run git push origin main --follow-tags to push both commits and the annotated tag in one command. Display success or error.
  • If "Skip for now": display reminder: "Tag v{version} is local only. Push when ready: git push origin main --follow-tags"
  • If "Other": follow user instructions (e.g., create a PR, push to a different branch, etc.)

9d. Automatic npm release:

After pushing, automatically run the npm release to publish this milestone:

npm run release -- --minor

Display the output to the user. The --minor flag is used because milestone completions always represent new features.

  • If the release succeeds: display the new version number and GitHub Release URL
  • If the release fails: show the error as an advisory warning — the milestone is already archived. Suggest the user run npm run release manually after fixing the issue.

Post-Completion Smoke Test

If config.deployment.smoke_test_command is set and non-empty:

  1. Run the command via Bash

  2. If exit code 0: display "Smoke test passed" with command output

  3. If exit code non-zero: display advisory warning:

    ⚠ Smoke test failed (exit code {N})
    Command: {smoke_test_command}
    Output: {first 20 lines of output}
    

    This is advisory only — the milestone is already archived. Surface it as a potential issue for the user to investigate.

  4. Confirm with branded output — read ${CLAUDE_SKILL_DIR}/templates/complete-output.md.tmpl and fill in {version}, {count} (phases, plans, commits), {lines}, {duration}.

NEXT UP block after milestone complete:

After displaying the branded complete-output banner, always display a NEXT UP routing block:

╔══════════════════════════════════════════════════════════════╗
║  ▶ NEXT UP                                                   ║
╚══════════════════════════════════════════════════════════════╝

**Start the next milestone** — continue development with new phases

`/pbr:milestone new`

**Also available:**
- `/pbr:release` — tag and publish this milestone as a GitHub Release
- `/pbr:status` — review project state before continuing

<sub>`/clear` first → fresh context window</sub>

This ensures the milestone complete subcommand never ends in a routing dead end.


Subcommand: audit

Verify milestone completion with cross-phase integration checks.

Flow

  1. Determine target:

    • If version provided: audit that specific milestone
    • If no version: audit the current milestone (use blob.milestones to identify the most recent active milestone)
  2. Read all VERIFICATION.md files for milestone phases (use blob.milestones to identify the phase range):

    • Collect verification results
    • Note any gaps_found statuses
    • Note any phases without verification
  3. Spawn integration checker:

    Display to the user: ◆ Spawning integration checker...

    Spawn Task(subagent_type: "pbr:integration-checker"). Read ${CLAUDE_SKILL_DIR}/templates/integration-checker-prompt.md.tmpl, fill in {version or "current"}, {list of phase directories}, and {phase SUMMARY.md paths}, then use the filled template as the Task() prompt.

  4. Check integration-checker completion:

    After the integration-checker completes, check for ## INTEGRATION CHECK COMPLETE in the Task() output. If the marker is absent, warn: ⚠ Integration checker did not return completion marker — results may be incomplete. Proceed with whatever findings were returned but note the incomplete status in the audit report.

  5. Check requirements coverage:

    • Read REQUIREMENTS.md
    • For each requirement tagged for this milestone:
      • Search VERIFICATION.md files for coverage
      • Search SUMMARY.md provides fields
      • Flag uncovered requirements
  6. Write audit report:

    Create .planning/{version}-MILESTONE-AUDIT.md using the structured template:

    Read ${CLAUDE_PLUGIN_ROOT}/templates/MILESTONE-AUDIT.md.tmpl for the audit report format with YAML frontmatter scores. Fill in all {variable} placeholders with actual data from the audit. The YAML frontmatter MUST include scores (requirements, phases, integration, flows), gaps array, and tech_debt array.

    Spot-check: After writing, verify .planning/{version}-MILESTONE-AUDIT.md exists on disk using Glob. If missing, re-attempt the write. If still missing, display an error and include findings inline.

  7. Report to user using branded banners — read ${CLAUDE_SKILL_DIR}/templates/audit-output.md.tmpl. The template contains all 3 variants (PASSED, GAPS FOUND, TECH DEBT). Select the appropriate section based on audit result. Fill in {version}, {count}, {gap 1}, {gap 2} as applicable.


Subcommand: gaps

Create phases to close gaps found during an audit.

Flow

  1. Find most recent audit:

    • Search for *-MILESTONE-AUDIT.md in .planning/
    • If multiple, use the most recent
    • If none: "No audit found. Run /pbr:audit-milestone first."
  2. Read audit report:

    • Extract all gaps and tech debt items
    • Parse severity levels
  3. Prioritize gaps:

    Group by priority:

    • Must fix (critical/high): Blocking issues, broken integration, uncovered requirements
    • Should fix (medium): Non-critical integration issues, important tech debt
    • Nice to fix (low): Minor tech debt, optimization opportunities
  4. Present to user:

    Gaps from milestone audit:
    
    Must fix ({count}):
    - {gap}: {description}
    
    Should fix ({count}):
    - {gap}: {description}
    
    Nice to fix ({count}):
    - {gap}: {description}
    
    **CRITICAL -- DO NOT SKIP**: Present the following choice to the user via AskUserQuestion before proceeding:
    Use AskUserQuestion (pattern: multi-option-priority from `skills/shared/gate-prompts.md`):
      question: "Which gaps should we address? ({must_count} must-fix, {should_count} should-fix, {nice_count} nice-to-fix)"
      header: "Priority"
      options:
        - label: "Must-fix only"    description: "Address {must_count} critical/high gaps"
        - label: "Must + should"    description: "Address {must_count + should_count} critical through medium gaps"
        - label: "Everything"       description: "Address all {total_count} gaps including low priority"
        - label: "Let me pick"      description: "Choose specific gaps to address"
    - If "Must-fix only": filter to must-fix gaps for phase creation
    - If "Must + should": filter to must-fix + should-fix gaps
    - If "Everything": include all gaps
    - If "Let me pick" or "Other": present individual gaps for selection
    
  5. Group into logical phases:

    • Group related gaps together (same subsystem, same files)
    • Each group becomes a phase
    • Name phases descriptively: "{N+1}. Fix {area} integration" or "{N+1}. Address {component} gaps"
  6. Update ROADMAP.md: Add gap-closure phases after the current milestone phases:

    ### Phase {N}: Fix {area} (gap closure)
    **Goal:** Address gaps found in milestone audit
    **Gaps addressed:**
    - {gap 1}
    - {gap 2}
    **Success criteria:** All addressed gaps pass verification
    
  7. Create phase directories:

    .planning/phases/{NN}-fix-{slug}/
    
  8. Commit:

    docs(planning): add gap-closure phases from milestone audit
    
  9. Confirm with branded output — read ${CLAUDE_SKILL_DIR}/templates/gaps-output.md.tmpl and fill in {count} (gap-closure phases created), {N} (first gap phase number), {name} (phase name).


State Integration

All subcommands use blob.state and blob.config from the init call for reading state. All subcommands update STATE.md on write:

  • new: Sets current milestone, resets phase
  • complete: Clears current milestone, updates history
  • audit: Notes audit status and date
  • gaps: Updates phase count and roadmap info

Git Integration

Reference: skills/shared/commit-planning-docs.md for the standard commit pattern.

All subcommands commit if blob.config.planning.commit_docs is true:

  • new: docs(planning): start milestone "{name}" (phases {start}-{end})
  • complete: docs(planning): complete milestone {version}
  • audit: docs(planning): audit milestone {version} - {status}
  • gaps: docs(planning): add gap-closure phases from milestone audit

Tags (complete only):

  • git tag -a {version} -m "Milestone: {name}"

Reference: skills/shared/error-reporting.md for branded error output patterns.

Edge Cases

For all edge case handling, see ${CLAUDE_SKILL_DIR}/templates/edge-cases.md. Key scenarios: no ROADMAP.md, no phases, no gaps found, version collision, partially verified, large milestone (8+ phases).


Anti-Patterns

  1. DO NOT skip the audit before completing — integration issues hide at boundaries
  2. DO NOT auto-complete milestones without user confirmation
  3. DO NOT create gap phases without user approval of priorities
  4. DO NOT delete audit reports — they're historical records
  5. DO NOT reuse version numbers — each milestone gets a unique version
  6. DO NOT modify code during milestone operations — this is project management only
  7. DO NOT collapse phases in ROADMAP.md before archiving — archive first, collapse second
  8. DO NOT skip the git tag — tags make milestone boundaries findable