Skip to content

/sdlc:milestone-new

Generated from solutions/ontological/skills/milestone-new/SKILL.md.

Interactively define a new milestone. Walk the user through title, status, version, target date, and known member tasks; create the file via sdlc milestone create (which auto-assigns an immutable id); validate the frontmatter; report the path. Optionally also capture prose for Goal / Success criteria / Out of scope and Edit them into the file.

  • Bash
  • Read
  • Edit
  • AskUserQuestion

Usage:

  • /sdlc:milestone-new — start the interview. End state: a validated milestone file at docs/planning/milestones/M<NNNN>.md under the project root.

References:

  • ${CLAUDE_PLUGIN_ROOT}entities/milestone/definition.md — storage path, id-as-filename convention, sdlc milestone create as canonical writer, validator usage, frontmatter ↔ body Deliverables sync rule. Read this once per project — it governs every skill that writes milestone files.

Project context (skill-specific):

  • This skill captures the intake. Body sections beyond the title (Goal, Success criteria, Out of scope, Risks, Discovery context) are filled in by Edit only if the user opts in at step 5; the default is to leave the template’s <...> placeholders for the author to flesh out later.
  • Mid-milestone task additions (extending tasks: and the body ## Deliverables section together) should also be done via this skill where possible, so both halves stay in sync.

Ask the user in plain text: “What’s the title for this milestone?” Skip this step if the user already gave a title in their invocation message.

2. Triage (one AskUserQuestion call, up to 4 questions)

Section titled “2. Triage (one AskUserQuestion call, up to 4 questions)”

Send a single AskUserQuestion with these questions:

  1. Status — header “Status”. Options: open/draft (capturing only), open/planned (committed; nothing started), open/active (work in progress on at least one task). Default open/draft.
  2. Version — header “Version”. Options: Not yet / unknown and Other (Other lets the user type a semver like 0.2.0). Skip-by-choosing-Not-yet leaves the field unset; can be added later. Recommend setting if this milestone targets a known release.
  3. Target date — header “Target date”. Options: None and Other (Other accepts YYYY-MM-DD). Optional.
  4. Tags — header “Tags”. Options: None and Other (Other accepts comma-separated free text). Optional.

Validate user-typed values against the schema patterns before continuing:

  • Version: ^v?\d+\.\d+\.\d+(-[\w.]+)?(\+[\w.]+)?$
  • Target date: ^\d{4}-\d{2}-\d{2}$

If a value fails, ask again with a one-line explanation of the rule.

Ask plain text: “Any member tasks or epics to seed the milestone with? (Comma-separated task basenames like 2026-05-17-add-astro-docs-site or epic ids like E0042, or ‘skip’).”

If the user provides values, validate each against ^(E\d{4}|\d{4}-\d{2}-\d{2}-[a-z0-9]+(?:-[a-z0-9]+)*)$. Pass valid ones to sdlc milestone create via repeated --tasks flags; the op wraps them in [[...]]. Milestone tasks: is a mixed-member field — task basenames and epic ids both live here, no separate --epic flag.

Don’t try to enumerate the whole backlog or invent members the user didn’t name — this step is only for items the user already knows belong.

Run:

${CLAUDE_PLUGIN_ROOT}cli/sdlc milestone create \
--title "<title>" \
--status <status> \
[--version <semver>] \
[--target-date YYYY-MM-DD] \
[--tasks <basename>]... \
[--tags <tag>]...

The op prints the absolute path of the new file on stdout (and the assigned id is visible in the filename); pass --output json for {path,id}. Capture it.

If it exits non-zero, report the error verbatim, fix the flag, and re-run.

Ask once via AskUserQuestion: “Fill in Goal / Success criteria / Out of scope / Risks now, or leave the placeholders for later?”

If “now”: for each section, ask in plain text for the content, then use Edit to replace the matching <...> placeholder block in the file with the user’s text. Leave a section’s placeholders intact if the user explicitly skips it. Headers (## Goal, etc.) stay; only the placeholder body changes.

If “later”: don’t touch the body.

${CLAUDE_PLUGIN_ROOT}cli/sdlc entities validate <path-from-step-4>

If validation fails, report the error verbatim and walk the user through fixing it.

Tell the user:

  • The absolute path of the new file (the assigned id is in the filename).
  • One line: <id> · <status> · <version-or-no-version> — <title>.
  • Next-step pointer:
    • If tasks: is non-empty, suggest one of the member tasks via /sdlc:task-work <task-basename>.
    • Otherwise, suggest creating tasks via /sdlc:task-new and adding them to this milestone (add to frontmatter tasks: AND the body ## Deliverables section).
  • File exists at docs/planning/milestones/M<NNNN>.md under the project root with an auto-assigned id.
  • Frontmatter passes sdlc entities validate with zero errors.
  • The title is set both in frontmatter title: and in the body # ... line (no <Title> placeholder remains).
  • If --tasks args were passed, both frontmatter tasks: and the body ## Deliverables section reflect them.
  • The op’s output path was reported back to the user.
  • This skill never writes frontmatter by hand. sdlc milestone create is the writer. To change a frontmatter value after creation, edit the file directly or re-run the op in a new id slot.
  • Keep the conversation short. If the user packed everything into the first invocation message (“new milestone: docs surface, version 0.2, target end of June”), skip the AskUserQuestion calls and go straight to step 4.
  • When adding a task to an existing milestone mid-stream, both frontmatter tasks: and the body ## Deliverables bullets must be updated together. This skill doesn’t currently handle add-task — for now do it as a hand-edit and run sdlc entities validate after.