Skip to content

update_milestone

Add a new milestone or transition an existing one in the target repo’s MILESTONES.md. State transitions are restricted: planned → active → complete | deferred | retired. Marking complete requires evidence_path resolving to docs/verification/.

Upholds: MR-2 · MR-7 Side effects: Modifies MILESTONES.md on a new branch, opens a PR.

  • REPO_IN_REGISTRY — target_repo must appear in registry.yaml.
  • MILESTONE_ID_VALID — milestone_id matches ^M\d+(.\d+){0,2}$.
  • ID_NOT_REUSED — On action=add, milestone_id must not already exist (even for cancelled/retired milestones; phase-discipline rule 5).
  • EXISTING_FOR_TRANSITION — On action=mark_complete|defer|retire, milestone_id must exist.
  • EVIDENCE_FOR_COMPLETE — action=mark_complete requires evidence_path matching ^docs/verification/.
  • DEFER_TARGETS_LATER_PHASE — On action=defer, deferred_to must be a milestone ID in a later phase than the current one (MR-2).
  • TRANSITION_LEGAL — State machine: planned→active|deferred|retired; active→complete|deferred|retired; complete is terminal except via supersession decision doc.
  • milestone_idMilestoneId (required)
  • action string (required) enum: add, mark_active, mark_complete, defer, retire
  • title string — Required when action=add.
  • acceptance_criteria array
  • evidence_path string — Required when action=mark_complete. Path to docs/verification/.md.
  • deferred_toMilestoneId — Required when action=defer. Must be in a later phase.
  • rationale string — Free-text rationale; included in the PR body.
  • milestone_idMilestoneId
  • previous_state string
  • new_state string
  • prPRRef
  • diff_previewDiffPreview

Input:

{
"envelope": {
"verb": "update_milestone",
"target_repo": "kahn-hq",
"idempotency_key": "b4e1aa4c2f9e87135c6b9d8e2f3e4b5c6d7e8f90a1b2c3d4e5f6a7b8c9d0e1f2",
"dry_run": true,
"actor": "fleet:kahn-planner",
"triggered_by": {
"kind": "phase_close",
"ref": "docs/decisions/2026-04-29-phase-7-close.md"
}
},
"params": {
"milestone_id": "M8.1.1",
"action": "add",
"title": "Operator re-probe of post-Phase-7 SPA",
"acceptance_criteria": [
"Visitor-grade probe transcript captured",
"Verdict recorded in docs/decisions/"
],
"rationale": "M7.8.2 friction deferred from Phase 7 close (MR-2)."
}
}

Output (output_dry_run):

{
"envelope": {
"verb": "update_milestone",
"status": "dry_run",
"idempotency_key": "b4e1aa4c2f9e87135c6b9d8e2f3e4b5c6d7e8f90a1b2c3d4e5f6a7b8c9d0e1f2",
"mr_citations": [
"MR-2",
"MR-7"
]
},
"result": {
"milestone_id": "M8.1.1",
"previous_state": "absent",
"new_state": "planned",
"diff_preview": {
"files": [
{
"path": "MILESTONES.md",
"operation": "modify"
}
],
"branch": "petrova/update-milestone/m8-1-1",
"commit_message": "milestone: add M8.1.1 (idempotency: b4e1aa4c2f9e8713)"
}
}
}

Schema: spec/verbs/update_milestone.schema.json Upholds: MR-2 (friction → next phase), MR-7 (append-only). Emits: PR modifying MILESTONES.md.

  • Adding a new milestone (action: add).
  • Transitioning state (mark_active, mark_complete, defer, retire).
{
"milestone_id": "M<phase>.<n>[.<m>]",
"action": "add | mark_active | mark_complete | defer | retire"
}

Per-action requirements:

  • add → also requires title. Optional: acceptance_criteria[].
  • mark_complete → requires evidence_path matching docs/verification/....
  • defer → requires deferred_to (a milestone ID in a later phase per MR-2).

Optional anywhere: rationale (free text, lands in PR body).

  • milestone_id matches ^M\d+(\.\d+){0,2}$.
  • add: ID must not already exist (state machine: planned/active/etc.).
  • mark_complete: evidence path required; complete is terminal.
  • defer: deferred_to must be in a later phase (MR-2 enforcement).
Terminal window
cat > /tmp/petrova-input.json <<'JSON'
{
"milestone_id": "M8.1.1",
"action": "add",
"title": "Operator re-probe of post-Phase-7 SPA",
"acceptance_criteria": [
"Visitor-grade probe transcript captured",
"Verdict recorded in docs/decisions/"
],
"rationale": "M7.8.2 friction deferred from Phase 7 close (MR-2)."
}
JSON
petrova update_milestone kahn-hq --input /tmp/petrova-input.json

The verb does the simplest viable edit:

  • add appends a new milestone block at the end of MILESTONES.md.
  • transitions update an inline [state] marker if present, else append a transition note.

For complex restructuring (renumbering, splitting), edit the file by hand and use request_review instead.