Skip to content

v2.16.0 ·

Milestones show up on GitHub

Roadmap milestones landed in the last release, but only on my side of the screen. The local page and aidlc roadmap status grouped every item under the goal it serves. The GitHub issues that aidlc roadmap sync writes for the same items had no idea milestones existed. Anyone reading the roadmap on GitHub saw a flat list of issues again.

What changed

With a milestones.yaml in the roadmap folder, aidlc roadmap sync now creates one GitHub milestone per entry, in file order. The title is the milestone's title. The description is its exit test, followed by one line, aidlc-milestone: <id>.

Each issue it manages is put under its item's milestone. An item marked none has its milestone cleared. A milestone whose items are all done or declined is closed on GitHub, and reopened if something under it opens again. An issue created in the same run gets its milestone in that run, so a dry run after a real one should say there is nothing to write.

The plan names every one of these writes before anything happens, the same way issue writes always have:

milestone-create      milestone m1 ("Stage 1", closed)
update-milestone      backlog/20260101-a.md → #7 (milestone m1)

Why this way

The link is that marker line, not the title. Matching on the title would turn a rename into a brand new milestone.

Issue milestones are set by number through gh api. The friendlier gh issue edit --milestone only looks up open milestones by name, so an issue could never be put under a milestone that is already done. That would have made GitHub's counts wrong for exactly the milestones you care about having finished.

It is still push only. If someone retitles a milestone on GitHub, or drags an issue to a different one, the next sync puts it back. Nothing is read back into the files.

What it does not do

GitHub only counts the issues sync manages. Items in a status that is not projected, inbox and hold by default, have no issue, so a milestone's GitHub total can be lower than the one aidlc roadmap status prints.

It will not adopt a milestone you made by hand. If one already uses the same title, sync refuses and names it, rather than guessing which one is yours. A milestone dropped from the file is reported and left alone, because deleting it is a decision for a person.

The tests drive a fake gh. The writes to the real milestones API have not run yet, so the first real check is a dry run, a real run, and a second dry run that should come back empty. A repo without milestones.yaml syncs exactly as before. I checked that against this repo's own roadmap, and the plan came out byte for byte the same.