Skip to content

Fix: record slice delivery in the roadmap manifest, with a deliver helper - #114

Merged
StarshipSuperjam merged 2 commits into
mainfrom
claude/roadmap-delivery-fix
Sep 3, 2026
Merged

Fix: record slice delivery in the roadmap manifest, with a deliver helper#114
StarshipSuperjam merged 2 commits into
mainfrom
claude/roadmap-delivery-fix

Conversation

@StarshipSuperjam

@StarshipSuperjam StarshipSuperjam commented Sep 3, 2026

Copy link
Copy Markdown
Owner

A green mechanical check below shows this change conforms to the engine's rules — not that it is correct. What covers correctness is the behavioural steps in Review and your own read of the change; a green check is never a substitute for that. Your merge is the binding gate.

About those checks: only the one that runs when the change is proposed for merge can stop a risky merge — a check that ran while the change was still being written is early advice. Each check is itself proven against a deliberately broken example it must catch, so a passing check can't be one that quietly did nothing — but that proves the check works, not that this change is right. And a check that could not run leaves its area unverified.

Purpose

Record slices 7 & 8 as delivered in the roadmap manifest, and add a helper so this bookkeeping never drifts again.

  • The roadmap board/issues are a forward projection of docs/roadmap/manifest.json: a leaf's status drives its issue open/closed state and board Status (history → Done/closed, else Backlog/open). Recording a delivery is a manual manifest edit (plannedhistory + delivered_by) that was never documented or automated, so it was never performed — slices 7 (PR Feature: difficulty director and normal flying formations, live #34) and 8 (PR Feature: Toroid vertical slice — first live flying enemy (slice 8) #110) merged with their leaves still planned.
  • That is the entire reconcile drift, and it is a latent hazard: a future roadmap.py apply would force those merged issues back open and reset the board to Backlog.

Impact: reconcile becomes clean, apply can no longer reopen merged work, and delivery-recording stops being a step that gets forgotten.

Scope

A deliver --pr N helper + doc, and the manifest edit recording the ten merged leaves delivered.

  • tools/roadmap.py — new deliver --pr N subcommand.
  • docs/roadmap/manifest.json — ten leaves flipped plannedhistory + delivered_by.
  • docs/roadmap/README.md — the post-merge step, with the ordering rule.
  • tests/test_roadmap.pyDeliverTests.

Change profile — the shape of this pull request at a glance:

  • Size: 4 files changed, +228 / −11 lines.
  • Kinds of thing touched: 4 project files (roadmap tool, its test, roadmap data, roadmap doc).
  • Where: docs, tests, tools.
  • Shape: 2 commits; a standalone change (closes no roadmap leaf — it fixes the roadmap tooling itself).

Impact: the roadmap's delivered state matches reality, and the recording is now a single reliable command.

Behaviors

What this delivers, each with the check that exercises it.

  • deliver --pr N flips only the PR's planned leaves to history + delivered_bytests/test_roadmap.py::DeliverTests.test_flips_only_the_prs_planned_leaves.
  • It skips parents and already-recorded leaves — test_skips_parents_and_already_delivered.
  • It refuses a pull request that is not merged — test_refuses_a_pr_that_is_not_merged.
  • It re-validates and writes nothing on an invalid result — test_an_invalid_result_aborts_the_write.
  • The committed manifest stays valid after the ten edits — test_committed_manifest_is_complete_and_acyclic / roadmap.py validate.

Out of scope

Projecting the manifest to the live GitHub board — deliberately staged as a separate, gated step.

  • Running roadmap.py apply / reconcile (which set the board Status → Done, rebuild the board's lost cards, and correct the stale board slice tag on issue 60) is a broad live GitHub mutation. It runs after this merges, previewed and on the operator's go-ahead — not inside this PR.
  • Changing the engine's sync semantics (e.g. auto-recording delivery from a merge event) is out — that would be engine machinery; this fix stays in project-owned files.
  • #60 (difficulty.live-pressure) is left planned — it is Part of #60, deferred to slice 10, not delivered.

Impact: the safety fix (manifest recording) lands now; the broad board resync stays a deliberate, reviewable action.

Risk

Low. Project data + one self-contained helper; no gameplay, specs, or engine machinery touched.

  • The manifest edit is a minimal per-line change (10 lines) guarded by roadmap.py validate and the test suite; fully reversible.
  • The helper only edits the manifest — it never mutates GitHub or the journal, and refuses an unmerged PR so it cannot mark work delivered early.
  • No engine guardrail is weakened; no .engine/** file is touched.

Impact: a wrong edit would be caught by validation/tests before merge, and the change is trivially revertible.

Validation

Full test suite green; manifest validates; minimal diff confirmed.

  • python3 -m unittest discover tests — 234 tests pass (5 new DeliverTests).
  • python3 tools/roadmap.py validate — manifest valid (13 parents, 66 leaves).
  • The manifest diff is exactly 10 changed lines, preserving the file's one-line-per-leaf style.

Impact: an approver can rely on the helper's behavior and the manifest's validity being exercised.

Review

I made this contained, reversible change at a quick check — I looked it over myself and ran the automatic checks plus the roadmap tests; no extra review passes.

  • Diagnosed the drift with read-only exploration before changing anything; the fix is project-data only (confirmed tools/roadmap.py and docs/roadmap/* are project-owned, not engine surfaces).
  • All findings handled in-scope; the broad board resync is deferred to a gated post-merge step (see Out of scope).
  • No settled product description drives this tooling/data fix, so there are no spec-derived acceptance steps.

Impact: this records the chosen review depth; your review at merge is the binding gate.

Demonstration

Run the helper and the validator against this branch.

  • python3 tools/roadmap.py validate → prints "roadmap manifest valid: 13 parents, 66 leaves"; a malformed manifest prints the failures and exits non-zero.
  • python3 tools/roadmap.py deliver --pr 34 on an already-recorded manifest → prints "skip … already recorded delivered" and refuses to write (nothing to record), showing the idempotence guard; on an unmerged PR it refuses with a clear message.
  • python3 -m unittest tests.test_roadmap → the DeliverTests pass, and fail if the flip/skip/refuse logic breaks.

Impact: the operator can watch the recording and its guards work, and see validation reject a bad manifest.

Files of interest

The helper and the manifest edit.

  • tools/roadmap.py — the deliver subcommand (reuses the existing dispatch, gh wrapper, and validate_manifest).
  • docs/roadmap/manifest.json — the ten plannedhistory + delivered_by edits.
  • docs/roadmap/README.md — the post-merge "record delivery" step and ordering rule.
  • tests/test_roadmap.pyDeliverTests.

Impact: the helper and the manifest edit most determine whether this is sound.

AI involvement

Claude Code (Opus) diagnosed the drift, designed and wrote the helper + tests + doc, and produced the manifest edit by running the helper.

  • AI-driven: the root-cause diagnosis (three read-only explorations), the helper design (minimal per-line edit to preserve manifest style), and the tests.
  • Operator-driven: the plan approval, the review depth (quick check), the choice of a helper + doc over lighter options, and the merge itself.

Impact: AI judgment is load-bearing on the helper design and the diagnosis; the operator's review and merge are the binding checks.

🤖 Generated with Claude Code

StarshipSuperjam and others added 2 commits September 3, 2026 09:11
The roadmap board and issues are a forward projection of the manifest:
a leaf's `status` drives its issue open/closed state and board Status
(`history` -> Done/closed, else Backlog/open). Recording a delivery was
an undocumented manual manifest edit, so it was never done — the first
live-delivered slices drifted (closed issues still `status:"planned"`),
and a future `apply` would reopen them.

Add a `deliver --pr N` subcommand: read the PR's computed closing issues,
map each to a leaf via the journal, and set that leaf `status:"history"`
+ `delivered_by:N`. It refuses an unmerged PR, skips parents and
already-recorded leaves, and re-validates before writing. The edit is a
targeted per-line text substitution so it preserves the manifest's
hand-authored one-line-per-leaf style (a JSON round-trip would reflow the
whole file).

Document the post-merge step (deliver -> apply -> reconcile, in that
order) in docs/roadmap/README.md, with the ordering rule that recording
delivery must precede apply. Add DeliverTests covering the flip, the
parent/already-history skips, the unmerged refusal, and the
validate-abort-before-write guard.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Flip the ten already-merged leaves from status:"planned" to
status:"history" with their delivering PR: difficulty.models-live-state
(#56, PR #34) and the nine slice-8 leaves #57-66 except #60 (PR #110).
#60 (difficulty.live-pressure) stays planned — it is Part of, deferred
to slice 10. Produced with `roadmap.py deliver --pr 34` / `--pr 110`.

This clears the reconcile drift for those leaves and removes the hazard
that a future `apply` would reopen the merged issues. proof and titles
are left unchanged (truthful — these were playtested; validation only
requires delivered_by on a history leaf).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@StarshipSuperjam
StarshipSuperjam force-pushed the claude/roadmap-delivery-fix branch from 9d369f8 to d88900b Compare September 3, 2026 16:11
@StarshipSuperjam
StarshipSuperjam marked this pull request as ready for review September 3, 2026 16:12
@StarshipSuperjam
StarshipSuperjam merged commit 1281392 into main Sep 3, 2026
17 of 20 checks passed
@StarshipSuperjam
StarshipSuperjam deleted the claude/roadmap-delivery-fix branch September 3, 2026 16:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant