| name | milestone-complete |
| description | Generate a milestone-completion report (summary.md, stats_code.md, stats_dev.md) under Docs/Milestones/<zero-padded-major>_<version-name>/, comparing code LoC and Docs/Specs/*/usage.csv dev stats against the previous milestone, then (with the user's sign-off) write Release Notes, draft a tech blog post and an English + Russian player-facing announcement, update this repo's README.md with a player-facing Milestones entry and a refreshed Game-features summary, cut a GitHub release + releases/<version> branch, roll the project version over to the next milestone, and (after a separate confirmation) delete branches already merged into main, local and remote. Tracks progress in the milestone dir's checklist.md so a run can be resumed. Load when the user asks to close out, wrap up, or report on a project milestone/version. |
Milestone Complete
Produces a point-in-time report of everything shipped in the current major-version
milestone: codebase size (LoC per tracked extension) and development cost/effort
(aggregated from every spec's usage.csv, see Docs/Specs/26_07_22_17_spec-dev-stats/),
each compared against the previous milestone if one exists. It then walks the user
through actually closing the milestone out: Release Notes, a tech blog post, an
English + Russian player-facing announcement, this repo's own README.md (a new
player-facing ## Milestones entry plus a refreshed ## The Game (briefly)
section), a GitHub release, a releases/<version> branch, the version bump that
starts the next milestone, and — as its own confirmed step — deleting branches
already merged into main (via PR or manually), both local and remote.
Per .claude/commands/commit.md, only a human decides when the milestone actually
turns over — this skill is that decision moment. It never bumps the major version or
renames _versionName without the user explicitly confirming the next milestone's
name first (step 15). Re-running the report before that confirmation simply
regenerates the current milestone's report with an updated end date.
This is a long, multi-session flow. Step 0 makes it resumable — always do that
first, and always check it first if the user asks to resume a milestone close-out
already in progress.
Step 0: Checklist (before anything else)
-
Resolve the milestone identity the same way the report script does: major version
(bundleVersion's X in X.YYY, from ProjectSettings/ProjectSettings.asset) and
version name (_versionName on MainMenuDocument in Assets/Scenes/MainMenu.unity),
slugified. This gives the output dir Docs/Milestones/<major>_<slug>/, where
<major> is zero-padded to 2 digits (01, 02, ... 99) so up to 99 milestones
sort correctly by filename — e.g. Docs/Milestones/01_world-domination/. The major
version itself stays unpadded everywhere else (summary header, checklist title,
commit messages, etc.) — only the directory name is padded.
-
If Docs/Milestones/<major>_<slug>/checklist.md already exists (padded dir name,
as above), this is a resume — read it, find the first unchecked step, tell the
user where the last run left off, and continue from there instead of restarting.
Don't re-run already-checked steps (e.g. don't regenerate a report that's already
been reviewed, don't re-cut a release that's already checked off).
-
Otherwise, create the directory and write checklist.md with every step below
(1 through 18) as an unchecked box, e.g.:
# Milestone Close-Out Checklist — <major>. <name>
- [ ] 1. Generate report (summary.md, stats_code.md, stats_dev.md)
- [ ] 2. Present report to user
- [ ] 3. Decide: continue to close-out now, or stop after the report
- [ ] 4. Review commit history in range
- [ ] 5. Propose release-note bullets; get user's list
- [ ] 6. Write ## Release Notes into summary.md
- [ ] 7. Propose tech_post.md themes; get user's choice
- [ ] 8. Propose players_post themes; get user's choice
- [ ] 9. Draft tech_post.md, players_post.en.txt / playerspost.md to the site
[ ] 12. Checkpoint: confirm release plan
[ ] 13. Cut the GitHub release + releases/ branch
[ ] 14. Ask for next milestone's name
[ ] 15. Checkpoint: confirm version transition
[ ] 16. Bump version, commit
[ ] 17. Checkpoint: confirm merged-branch cleanup list, then delete
[ ] 18. Report final summary
Step 1–3: Generate the report
Runs scripts/milestones/generate_milestone_report.py, which:
- Resolves the date range:
end_date = today; start_date = the day after the
previous milestone's end_date (read from its summary.md), or the repo's first
commit date if no previous milestone exists.
- Writes
stats_code.md — LoC + file count for .cs, .py, .sh, .ps1,
.prefab, .unity (Unity's actual scene extension), .asset, .json, .md
(via git ls-files, so untracked/ignored files never skew the count), diffed
against the previous milestone's numbers.
- Writes
stats_dev.md — every spec whose Docs/Specs/<YY_MM_DD_HH>_<name>/
timestamp falls in the date range, its usage.csv rows aggregated into one table,
plus meta stats (specs count, provider/model share, min/max/avg spec/plan size in
tokens, avg cost per stage, total cost/tokens), diffed against the previous
milestone's numbers.
- Writes
summary.md — # <major>. <name> header, the date range with duration,
and a ## Dev Notes section with short insight bullets pulled from both stats
files.
Each generated file also carries a hidden <!-- milestone-meta: {...} --> /
<!-- milestone-stats-code: {...} --> / <!-- milestone-stats-dev: {...} -->
HTML-comment JSON block — this is how the next milestone run finds this one's exact
prior numbers without re-parsing markdown tables, and how later steps find this
milestone's exact start_date/end_date. Don't strip these comments when editing a
generated file by hand.
-
Run, in a single Bash call (no cd, matching this repo's shell rule):
python3 scripts/milestones/generate_milestone_report.py
Useful overrides (rarely needed — defaults cover the normal case):
--major X / --name "..." — force the milestone identity instead of reading
it from ProjectSettings.asset / MainMenu.unity.
--start-date YYYY-MM-DD / --end-date YYYY-MM-DD — force the date range.
--out <path> — force the output directory.
-
Read the three generated files and present the summary.md content (and anything
notable from the two stats files) to the user. Do not commit them yet — that
happens, deliberately, as its own approved step (11) further down.
-
Ask the user whether to continue into closing the milestone out now, or stop here
with just the report. If they stop, the checklist is left mid-way on purpose —
this is a valid resume point.
Steps 4–11: Release Notes and the two write-ups
-
Review what shipped. Pull start_date/end_date from the <!-- milestone-meta: {...} --> comment at the end of summary.md (already read in step 2), then review
the commit history for that range on the current branch:
git log --pretty=format:"%h %s" --no-merges --since=<start_date> --until="<end_date> 23:59:59"
Read through the subjects (and skim bodies for anything non-obvious) to understand
what actually shipped — new systems, major fixes, cut features — not just the raw
list. This review feeds steps 5, 7, and 8 below, so do it once and reuse it.
-
Propose release-note bullets. Draft up to 10 candidate bullets for the
milestone's highlights, most important first, in plain user-facing language (not
commit-message shorthand). Present them as a numbered list and ask the user to
confirm, trim, reorder, or add to it — free-form reply, not a fixed menu (e.g.
"keep 1, 3, 5; drop the rest; add: X").
-
Write ## Release Notes. Once the user has settled the bullet list, Edit
the milestone's summary.md to insert a ## Release Notes section (the settled
bullets) — insert it before the trailing <!-- milestone-meta: {...} --> line,
after the existing ## Dev Notes section. Do not touch or remove the hidden
comment.
-
Propose tech_post.md themes. This is a technical blog post for the personal
site (../konh.github.io, published under src/content/blog/ — see its
EXAMPLE.md for the exact post format, and skim a couple of real posts already in
that directory for tone). Drawing on the commit review (step 4) and stats_dev.md,
propose 2–4 possible angles (e.g. "architecture deep-dive on system X",
"the AI-assisted dev-process story this milestone", "one flagship feature,
spotlighted end-to-end") and ask the user which theme/accent to run with — and
whether the milestone's timeline is better shown as a short table or a small inline
diagram (see step 9's formatting notes). This is a discussion, not a menu; take a
free-form reply.
-
Propose players_post themes. Same idea, for a short player-facing announcement
(Discord/Steam/itch.io-style, not this repo's own docs), written in both English
and Russian — this project ships real (not machine-translated) Russian for
player-facing text, per the localization skill's convention. Propose 2–4 angles
(e.g. "lead with the headline feature", "narrative/flavor framing", "plain
patch-notes list") and ask which to run with — one theme choice covers both
locales. Keep this pass light — it's a ≤1024-character post, not a spec.
Bias toward : an early milestone reads better calling itself an
"iteration" in exploratory/research-prototype mode than dressing it up as a
"working prototype" — honest framing over polish. Once 's URL
is known (step 10), close the player post with both the play-demo link and
the blog-post link inline in the text itself, not just in this repo's README.
Steps 12–18: Cut the release, roll the version, clean up branches
- Checkpoint — confirm before any GitHub-visible action. Show the user the
exact plan: the version number to release, the tag/release name, the
releases/<version> branch name, and the finalized Release Notes text. Wait for
explicit go-ahead before continuing — creating a release and pushing a branch are
public, hard-to-reverse actions per .claude/rules/workflow.md.
- Cut the release, once confirmed. Version number = the current full
bundleVersion (X.YYY) read from ProjectSettings/ProjectSettings.asset — this
pins the exact commit being released, unlike the milestone's bare major version.
- Confirm
git status is clean and the current commit already exists on origin
(e.g. git log origin/main..HEAD is empty) — gh release create needs the
commit to be reachable on GitHub already. If it isn't pushed, stop and tell the
user to push first rather than guessing at what to push.
git branch releases/<X.YYY> at the current commit, then git push origin releases/<X.YYY>.
gh release create v<X.YYY> --target releases/<X.YYY> --title "<major>. <name>" --notes "<Release Notes bullets from step 6>".
- Report the release URL (
gh release create prints it) back to the user.
- Ask for the next milestone's name. The major version is about to increment,
which per
Docs/Constitution.md/commit.md convention also gets a fresh
_versionName. Ask the user what to call it.
- Checkpoint — confirm the version transition before editing anything: old
<major>.<name> → new <major+1>.0, <new name>. Wait for explicit go-ahead.
- Bump the version, once confirmed:
Read ProjectSettings/ProjectSettings.asset, parse X and YYY from
bundleVersion: X.YYY, then Edit it to bundleVersion: {X+1}.0 (major
+1, minor reset to 0 — this is the one place X is allowed to change; see
.claude/commands/commit.md).
Edit 's top-level field to the
same (the main-menu label reads this, not —
see ).
Notes
- Report generation is pure stdlib Python (mirrors
scripts/stats/'s
no-third-party-deps convention) — no LLM calls, safe to re-run.
- If
Docs/Milestones/ has no prior entries yet (first-ever run), both stats files
clearly say so instead of fabricating a comparison — that's expected, not a bug.
- A spec with no
usage.csv (shouldn't happen post-spec-dev-stats, but possible for
a brand-new spec mid-session) is silently skipped in stats_dev.md's aggregation.
- For iterating on the upcoming milestone's WebGL build without touching the public
listing, use the separate Deploy Unity Play (DEV) GitHub Actions workflow
(
.github/workflows/deploy-unity-play-dev.yml, manual workflow_dispatch) — this
skill does not trigger it automatically.
checklist.md is scratch state for resuming a close-out, not a generated-report
artifact like the stats_*/summary files — it's fine (expected, even) for it to
carry all-checked boxes once the milestone is fully closed; no need to delete it.
- The README's
## Milestones section is additive only — each run prepends one
new entry and never edits, reorders, or removes an earlier one. It is the repo's
running player-facing changelog; the full write-ups stay under Docs/Milestones/.
## The Game (briefly) is a living summary, not a per-milestone log — it should
always read as an accurate snapshot of the game today, so update/replace its
bullets in place rather than appending to them.
- The site's
BlogPostView.vue already has a built-in image lightbox (a
hover-visible expand button on every post image opens a fullscreen, blurred-
backdrop view; closes via the × button, the backdrop, or the image itself) and
bordered/centered table styling. New posts get both automatically — no need to
reimplement either.
generateBlog.ts's excerpt generator strips markdown image/link syntax and raw
HTML tags (fixed after a post that opened with a bare <img> leaked its literal
tag text into the blog-list excerpt) — safe to open a post with an image again.
- This repo's own automation (or another concurrent session) can commit to the
same working tree while a close-out is in progress, in either repo. Before
committing anything in step 11 or 16, run
git status and check for unrelated
staged/unstaged changes that aren't yours; stage by explicit pathspec (git add <specific paths>, verified with before committing) rather
than /, so unrelated concurrent work doesn't get
swept into the milestone commit.