Repository navigation
Story (F): major-version boundary in the channel/ring model [#604] #657
Description
Part of the shim-identity epic #604 — Story F (major-version boundary). Filed from the 2026-07-10 plan review.
Gap
The version+ring model gates blast radius, not compatibility. Consumer-facing channels (<agent>/next, /ring0, /ring1, /stable) encode a repo's ring tier, not a semver major. Since #870, @vN pins are treated as drift, and immutable <agent>/vMAJOR.MINOR.PATCH tags exist only as rollback anchors that nothing pins to.
Consequence: a breaking (major) change to an agent, once promoted through the rings to stable, reaches every stable consumer with no opt-in gate. There is no @dev-lead/v1-stable vs @dev-lead/v2-stable separation, and nothing halts a major bump as it advances next → ring0 → ring1 → stable. The strategy accepts this implicitly rather than by decision.
Decision needed (pick one)
- Major-scoped channels — introduce per-agent major-scoped channel tags (e.g.
dev-lead/v2-stable) so a breaking release requires a deliberate consumer re-pin to opt in. Preserves "callers pin once" within a major; a major bump is the one sanctioned re-pin event. Cost: doubles channel count per agent; re-sync + drift tooling (ring-pins.sh,compliance-audit.sh,fleet_stub_drift.sh) must learn thevN-prefix. - Promotion gate at the major bump — keep single channels, but the canary-rollout engine halts a release flagged as a major (breaking) at the
next → ring0edge pending explicit human sign-off, instead of auto-advancing. Cheaper; needs a way to mark a release "major" (release note / label / tag metadata) and a gate in the promotion engine. - Accept and document — keep the channel-only model; add an explicit note to
agentic-release-strategy.mdthat majors are not gated and consumers accept auto-flow tostable. No engineering.
Acceptance
- A decision is recorded in the release-strategy doc's decision log.
- If (1) or (2): the ring/drift tooling and the canary-rollout engine honor the chosen mechanism, with tests; a breaking change cannot silently reach
stableconsumers. - If (3): the accepted trade-off is documented where the channel model is defined.
Notes
- Depends on nothing else in Epic: Enforce identical reusable-workflow shims across the fleet (full-file drift, not just pin) #604; can be decided independently. Sequence after Story (B): channel-ify feature-ideation + pr-auto-review [#604] #606/Story (D): full-file on:/permissions drift guard in compliance-audit [#604] #607 if it competes for attention — the identity gap (Story (D): full-file on:/permissions drift guard in compliance-audit [#604] #607) is the higher-value fix.
- Relevant surfaces:
scripts/lib/ring-pins.sh,scripts/compliance-audit.sh, the canary-rollout engine (relocated to.githubper Epic: relocate the canary-rollout engine + bootstrap into .github (org tooling consolidation) #613),.github-private/scripts/cut-release.sh,.github-private/docs/initiatives/agentic-release-strategy.md.
Activity
don-petry commentedon Jul 13, 2026
Decision (2026-07-13): Option 1 — major-scoped channels.
A breaking (major) agent change must require a deliberate consumer re-pin to opt in. Recorded here + to be logged in
.github-private/docs/initiatives/agentic-release-strategy.md.Design — channel = major × tier
Channel tag naming:
<agent>/v<MAJOR>-<tier>— e.g.dev-lead/v1-next,dev-lead/v1-ring0,dev-lead/v1-ring1,dev-lead/v1-stable, and independentlydev-lead/v2-next… as a v2 soaks. Immutable release tags<agent>/vX.Y.Zunchanged (rollback anchors).The key semantic shift: today
ring_canonical_ref(agent, repo) = <agent>/<tier>— expected ref is a pure function of (agent, repo-tier). With major-scoping, the expected ref is<agent>/v<M>-<tier>where M is the major the consumer currently pins (its opt-in). Drift = "consumer is NOT on a validv<M>-<tier>channel for its repo tier," NOT "consumer is on the wrong major." A consumer onv1-stablestays valid until IT re-pins tov2-stable; a v2 reaching its ownv2-stablenever touches av1-stableconsumer.Per-agent current major: migration maps each agent's live
<agent>/<tier>→<agent>/v<currentMajor>-<tier>(currentMajor from the agent's latest release: dev-lead=v1, pr-auto-review=v1, agent-shield=v2, etc. — read from<agent>/vX.Y.Z). The bare<agent>/<tier>channels are retired after consumers move.Phased plan (each phase = its own PR, dev-lead + pr-review, serial where files overlap)
.github-private/docs/initiatives/agentic-release-strategy.md): record the decision-log entry + the major×tier model + migration. (no engine change)cut-release.sh(.github-private): teach--channelto accept/emitv<major>-<tier>; derive<major>from the<version>arg;channel_refgains the prefix. Add cut/promote for a fresh major line.ring-pins.sh(.github):ring_canonical_refemits<agent>/v<M>-<tier>; new helper to read a consumer stub's currently-pinned major; drift becomes tier-match within the consumer's major.RING_REUSABLESunchanged (membership), the ref builder changes. Bats.canary-rollout.sh+canary-rings.json): channel resolution +promote/autocut/promote-alloperate onv<M>-<tier>tags; a candidate soaks within its major line;evaluatereports the major. Bats (gated byCanary-rollout Testsci: add canary-rollout-tests.yml — enforce the engine's bats suite (CI gap from #613/#624) #685).compliance-audit.shRING branch +fleet_stub_drift.sh/template_stub_drift.shhonor the prefix; migrate live channel tags (<agent>/<tier>→<agent>/v<M>-<tier>) via the App token; re-pin all consumer templates/stubs to@<agent>/v<M>-<tier>; retire bare-tier channels. Bats + fleet re-sync.Acceptance (from #657)
v<major>-<tier>, with tests; a breaking change cannot silently reachstableconsumers — it lands onv<newMajor>-stable, which nothing pins to until a consumer opts in.Sequencing
F1 → F2 → F3 → F4 → F5, serial (each builds on the prior; F5's live migration is last). F1 (
.github-privatedoc) is independent of the in-flight #607 (.githubcompliance-audit). Start F1 now.feat: implement issue #694 — F3: ring-pins.sh major-aware canonical-r…
feat: implement issue #696 — F4: canary-rollout engine operates on v<…
feat: implement issue #698 — F5: migration tooling — emit v<major>-ti…
chore: major-scope repin dev-lead.yml [#657 F5]
chore: major-scope repin feature-ideation.yml [#657 F5]
chore: major-scope repin initiative-planner.yml [#657 F5]
chore: major-scope repin self-consumer stubs [#657 F5] (#703)
feat: implement issue #704 — F5 gap: deploy-standard-workflows exempt…
fix: re-pin agent_ref to v-form for dev-lead.yml [#657]
fix: re-pin agent_ref inputs to v-form (missed by #657 uses:-only re-…
fix(migrate): retire-guard + emit-repins must also scan agent_ref: in…
fix(migrate): retire-guard must scan agent_ref: inputs (regression th…
fix(migrate): fail-closed on undecodable/oversized stub content
feat: implement issue #707 — #657 F5: complete bare-tier tag retireme…
Add the persona @-mention router (#754)
feat: implement issue #694 — F3: ring-pins.sh major-aware canonical-r…
feat: implement issue #694 — F3: ring-pins.sh major-aware canonical-r…
feat: implement issue #694 — F3: ring-pins.sh major-aware canonical-r…
don-petry commentedon Oct 21, 2026
Closing after the 2026-10-21 backlog triage.
Why: Decided (major-scoped channels) and implemented; every agent has v-tier tags.
Evidence: PRs #695-#754 merged; tag audit 2026-10-21 all 17 agents complete
Reopen if this still reproduces on main.