Roadmap persistence decision prerequisite¶
Status: owner selected option A (original GitHub milestones) on 2026-10-09. Issue #3694 remains a prerequisite to live persistence in #3616; the manual closure of parent #3400 does not satisfy its children's technical acceptance. This document does not approve a replacement design, enable writes, or demonstrate the original milestone-assignment concurrency guarantee.
Dependency-ordered delivery plan¶
| Wave | Issue | Required outcome |
|---|---|---|
| 1 | #3694 | Decide a persistence contract with demonstrable concurrency protection. |
| 2 | #3616 | Deliver approved persistence, authenticated plan authority, resumable checkpoints and artifact publication. |
| 3 | #3617 | Deliver default-off runtime integration, bounded reconciliation and earliest-release ordering. |
| 4 | #3618 | Deliver exact release-set validation, verified release and advance. |
The grouping and preview foundation already exists. Do not recreate it or interpret an umbrella parent as an execution prerequisite. Each subsequent wave requires the preceding acceptance, not just a merged design document.
Verified capability evidence¶
Read-only inspection on 2026-10-09 established:
- GitHub's REST best practices explicitly exclude conditional unsafe methods unless a specific endpoint documents support. GET ETags are not mutation preconditions.
- Milestone update documents title, state, description and due date, with no expected version or conditional-write guarantee.
- Authenticated GraphQL introspection found no
UpdateMilestoneInputtype;UpdateIssueInputhasmilestoneIdbut no expected resource version.clientMutationIdis correlation metadata, not compare-and-set. - Authenticated schema introspection describes
CreateCommitOnBranchInput'sexpectedHeadOidas the expected Git commit OID at the branch head before committing. This is a candidate Git-backed primitive, not proof that milestone or issue writes are conditional.
No mutation probe, test milestone, assignment change, or permission change was performed. The existing unconditional live-write rejection remains required.
Alternatives and decision¶
| Option | Human-pin protection | Change to approved acceptance | Disposition |
|---|---|---|---|
| A: direct GitHub milestone/assignment writes | Unproven against external writers | None | Owner-selected scope; keep disabled until a supported conditional contract is demonstrated. |
| B: Git-backed canonical roadmap; no milestone/assignment writes | Cannot overwrite GitHub state because it never writes it | Replace live GitHub assignment with canonical ledger membership | Unselected alternative; not authorized. |
| C: exclusive-writer convention plus pre/post-write reads | Does not constrain repository admins or human UI edits | Weakens the pin invariant unless every writer is technically constrained | Reject as an equivalent solution without enforceable exclusion proof. |
Option B is not a drop-in fulfillment of #3400. It preserves the stronger no-overwrite property by eliminating the problematic writes, at the cost of losing automatic GitHub milestone assignment. No derived mirror is permitted: an asynchronous assignment mirror would reintroduce the same race.
Selected option and Projects APIs¶
Retain GitHub milestone persistence; do not substitute a canonical Git ledger, weaken human-pin protection or treat the selection as proof of atomic writes. GitHub Projects v2 exposes GraphQL APIs for membership and custom fields, but the inspected update/delete and field-value inputs did not expose an expected version or old-value precondition. Projects may present read-only planning evidence; it is not a demonstrated compare-and-set workaround. No Project mutation or permission expansion is authorized by this decision.
The mocked persistence/race suite in #3700 tests the required contract under a strong atomic compare-and-commit assumption. It does not prove that separate GitHub APIs implement that assumption. Live #3616 acceptance remains blocked; Issues #3617 and #3618 must not consume a simulation as production authority.
Candidate Git-backed contract¶
If explicitly approved, a repository-owned ledger defines release membership,
canonical pins, plan digest, bounded run identity and immutable receipts.
docs/reference/roadmap.md is rendered from that ledger in the same commit.
Publication uses a stable bot branch and a PR through existing admission gates,
never a direct-main write or force update.
Every proposed update binds the exact observed branch head. Reject a changed
head; re-read and revalidate rather than replaying a stale overwrite.
Normal Git expected-old ref updates or expectedHeadOid require contract and
failure-injection coverage before implementation chooses its transport.
A branch update is not an atomic main merge or an atomic GitHub inventory read.
GitHub milestones, assignments and pin labels remain observation-only exclusion signals. Observe them before planning and again before execution; unknown, changed or inaccessible state pauses the affected release. This detects observed divergence but cannot promise atomicity against a concurrent GitHub edit. Canonical pin edits must therefore occur through ledger commits for transactional protection. If the owner requires instantaneous GitHub UI pin semantics, option B is insufficient and option A remains blocked.
A recorded proposal or merged artifact is not plan approval. Authenticated authority must bind repository, scope, digest, bounds and current policy. One-time consumption and claimed execution ownership belong to a single conditional state transition; a local SQLite receipt alone is not remote authority. Missing proof keeps execution disabled. Existing release controls remain authoritative; a ledger receipt cannot authorize arbitrary dispatch.
Required revised acceptance and failure tests¶
Before option B implementation, amend the parent PRD/spec and #3616-#3618:
- Replace GitHub milestone upsert/assignment with canonical ledger membership, and replace milestone-number execution scope with exact canonical release ID.
- State the canonical-pin workflow and observed-only GitHub pin semantics. Do not imply preservation of instantaneous external-edit behavior.
- Define ownership, schema/version migration, bounded retention and redaction. Inventory content and actor evidence inherit repository access controls; no secrets or full private issue bodies belong in the ledger or logs.
- Demonstrate stale branch-head rejection, concurrent canonical pin edits, duplicate logical keys and deterministic artifact/ledger consistency.
- Simulate lost responses, replay and superseded approval; verify no duplicate approval consumption or execution, and bounded explicit recovery.
- Prove post-merge state revalidation, unauthorized actor rejection, default-off behavior, missing inventory failure and earliest blocked release pausing.
- Preserve #3618's exact merged-PR set, previous tag, planned version, verified release URL and no advance on partial release failure.
Rollout and decision boundary¶
The owner selected option A. Merging this document records that choice but does not prove conditional milestone mutation or enable runtime writes. Continue safe read-only work until a supported contract is demonstrated; do not start dependent live delivery. Any revised option B acceptance needs a new explicit decision. After technical acceptance, split persistence, runtime ordering and release along the existing dependency chain rather than a single large PR.
Shadow first, then opt in only after the revised contract's race/replay and end-to-end requirements pass. Rollback disables new execution and retains receipts; never delete human milestones or clear assignments. Previously published releases keep their existing recovery procedure.
Implementation status¶
Issue #3616 implements the approved spec; the milestone adapter gate stays closed until the owner provisions it and records positive probe evidence.