Align source of truth with RC stabilization

This commit is contained in:
rcourtman
2026-03-19 15:35:49 +00:00
parent 3e603fd528
commit 8fd94e921e
2 changed files with 605 additions and 0 deletions
@@ -0,0 +1,522 @@
# Pulse v6 Source Of Truth
Last updated: 2026-03-17
Status: ACTIVE
This file is the stable human governance layer for the active v6 release
profile. It is not a live progress dashboard.
Evergreen control-plane governance now lives in
`docs/release-control/CONTROL_PLANE.md`, and the active profile plus active
target are machine-selected by `docs/release-control/control_plane.json`.
Current lane scores, evidence references, coverage-gap discovery records,
candidate-lane planning records, and typed operational decision records live
only in `docs/release-control/v6/status.json`.
Lane completion state, residual-gap summaries, normalized follow-up tracking,
and derived coverage scores also live only in
`docs/release-control/v6/status.json`.
Non-blocking same-lane residuals that are concrete enough to name directly
live in `status.json.lane_followups`.
Product-scope lane-discovery records that reveal where the current taxonomy is
still under-modeled live in `status.json.coverage_gaps`.
Planned future lane promotions for those gaps live in
`status.json.candidate_lanes`.
Active multi-agent lease records that reserve governed work in flight live in
`status.json.work_claims`.
Current repo/release readiness is derived by
`python3 scripts/release_control/status_audit.py --pretty` from
`status.json`, not hand-maintained in this file. The human runbook for
trust-critical manual release gates lives in
`docs/release-control/v6/HIGH_RISK_RELEASE_VERIFICATION_MATRIX.md`.
Use `python3 scripts/release_control/status_lookup.py` for candidate-lane,
coverage-gap, lane, readiness-assertion, release-gate, followup, and
work-claim lookups when only one governed surface is relevant.
Readiness assertion design rules live in this file.
The active assertion catalog, proof references, and executable proof commands
live in `status.json.readiness_assertions`.
## Purpose
1. Define the stable execution model for the active v6 release profile.
2. Lock profile-specific scope, release definition, and no-go rules.
3. Record only long-lived architectural and release decisions for this profile.
4. Point agents to the files that own live state and subsystem truth for this
profile.
5. Keep startup context light by preferring derived status commands and
targeted lookup helpers before opening large machine files in full.
This file must not contain:
1. hand-maintained lane score tables
2. hand-maintained evidence lists
3. ephemeral session recaps or task logs
## Canonical Control Files
1. `docs/release-control/AGENT_VALUES.md`
Evergreen values-only guidance for agent behavior.
2. `docs/release-control/CONTROL_PLANE.md`
Evergreen governance for the permanent Pulse release control plane.
3. `docs/release-control/control_plane.json`
Machine-readable control-plane state, including the active profile and
active target.
4. `docs/release-control/control_plane.schema.json`
Machine-readable contract for `control_plane.json`.
5. `docs/release-control/v6/status.json`
Live lane state, lane completion records, coverage-gap discovery records,
candidate-lane planning records, active work claims, structured evidence
references, and typed operational decision records.
6. `docs/release-control/v6/status.schema.json`
Machine-readable contract for the `status.json` shape.
7. `docs/release-control/v6/CANONICAL_DEVELOPMENT_PROTOCOL.md`
Repo-wide change rules for canonical work.
8. `docs/release-control/v6/internal/subsystems/registry.json`
Machine-readable subsystem ownership and proof requirements.
9. `docs/release-control/v6/internal/subsystems/registry.schema.json`
Machine-readable contract for the subsystem registry shape.
10. `docs/release-control/v6/internal/subsystems/*.md`
Per-subsystem contracts: truth, extension points, forbidden paths, and
completion obligations.
11. `docs/release-control/v6/RELEASE_PROMOTION_POLICY.md`
Canonical stable-versus-RC promotion rules, rollout criteria, and rollback
expectations for v6 and later release lines.
12. `docs/release-control/v6/V5_MAINTENANCE_SUPPORT_POLICY.md`
Canonical v5 maintenance-only support policy, release-line rules, and GA
notice requirements for the v6 cutover.
13. `docs/release-control/v6/RC_TO_GA_REHEARSAL_TEMPLATE.md`
Canonical human record shape for the non-publish RC-to-GA rehearsal run.
These machine files remain canonical, but agents should not ingest them in full
by default when a smaller derived command answers the question. Prefer
`status_audit.py --pretty`, `status_lookup.py`, and `subsystem_lookup.py`
first, then escalate into the raw files only when the current slice needs that
detail.
## Scope
`status.json.scope.control_plane_repo` is `pulse`.
`status.json.scope.repo_catalog` is the canonical machine-readable repo map for
the active Pulse workspace.
Active repositories for v6:
1. `pulse`
Core desktop/runtime repo and the canonical v6 release-control authority.
2. `pulse-pro`
Financial, operational, checkout, license-server, and relay-server
surfaces.
3. `pulse-enterprise`
Closed-source enterprise and paid runtime features.
4. `pulse-mobile`
Mobile client, relay pairing, approvals, and device-local auth/state.
Ignored for v6 control:
1. `pulse-5.1.x`
2. `pulse-refactor-streams`
## Release Definition
Pulse v6 is ready when these outcomes land together:
1. Unified resource model is stable and expansion-ready.
2. Product quality feels polished and trustable out of the box.
3. Commercial packaging materially improves conversion and revenue.
4. Stable or GA promotion happens only after RC validation, not as the first
customer exposure.
Pulse v6 has a bridge-release direction, but the current stabilization target
stays on the monitoring-and-alerting RC floor rather than the finished private
operational broker.
For this profile, "bridge release" means the product should stop reading as a
monitoring product growing sideways only where the surfaced case is already
proven; the broader resource-centric, policy-aware, action-ready control
platform remains a future lane.
Pulse owns infrastructure context, policy, and governed action boundaries so
any sandboxed agent can use them; Pulse does not own being the sandbox where
arbitrary agent execution lives.
The retained foundation is therefore the hidden backend layer: canonical
resources and relationships, standardized agent-emitted resource/signal/change
envelopes, policy metadata and routing hooks, governed action and approval
boundaries with auditability, and first-class fleet governance.
## Evergreen Readiness Assertions
Pulse v6 readiness is governed by a small evergreen assertion set.
These assertions are durable release truths, not one-off launch checklist
items.
`status.json.readiness_assertions` owns the active assertion catalog, proof
references, and executable proof commands for the active release line.
`docs/release-control/control_plane.json` owns the active engineering target
that this profile is currently pursuing.
`python3 scripts/release_control/control_plane_audit.py --check` enforces that
the active target cannot stay stale once its machine-derived completion rule is
already satisfied.
Assertion design rules:
1. Keep the set small and durable.
2. Write each assertion as a binary release truth, not as a task list.
3. Map each assertion to concrete lanes, governed subsystems, or release gates.
4. Prefer machine-derived proof and generated summaries over hand-maintained
docs.
5. If repeated manual proof becomes expensive, automate it or demote it to a
one-time migration item instead of keeping it in the evergreen set.
6. After GA, keep using the same control plane and promote a new active target
instead of cloning a new governance stack.
7. Not all evidence classes are equal.
High-risk release gates must declare the minimum evidence tier required for
closure, and rehearsal evidence below that tier must remain blocking even
when a dated record already exists.
8. When a user states a durable product truth, normalize it into a readiness
assertion, release gate, or open decision rather than leaving it as chat.
9. Treat casual user language about consistency, seamlessness, drift, bypass
resistance, or things that "should always be true" as candidate governance
input, not only explicit requests to add a formal assertion.
10. Active v6-facing guidance must stay current; legacy or historical docs may
exist only as clearly marked reference material, not as current instructions.
11. Comparable settings surfaces should be normalized into canonical
page-shell rules when the user raises consistency drift, rather than
treated as vague polish notes.
12. Lane taxonomy is allowed to evolve when it no longer reflects the current
product truth.
13. If a durable product surface is materially underrepresented by the current
lane map, record an active `status.json.coverage_gaps` entry instead of
hiding the gap inside a broad lane, a lane followup, or a generic
assertion.
14. Treat `status.json.coverage_gaps` as active fog-of-war records rather than
a loose backlog: each one should cite evidence, carry an explicit coverage
deduction, and name the intended promotion path such as a lane split, new
lane, lane expansion, or target update.
`coverage_gaps.status` is not cosmetic: once a lane-shaping gap
(`new-lane`, `lane-split`, or `lane-expansion`) has a typed
`candidate_lanes` record, move that gap to `planned`; do not mark such a
gap `planned` until a matching `candidate_lanes` record exists.
15. When the intended lane split/addition/expansion shape is already clear,
record it in `status.json.candidate_lanes` so lane-taxonomy evolution is
machine-readable rather than buried in prose.
Candidate lanes should also identify the owning control-plane target so
future lane-expansion work is routed to an explicit governed initiative.
`candidate_lanes` are only for lane-shaping promotion paths, so
`target-update` coverage gaps must stay out of that surface.
16. Once a coverage gap is resolved by a lane split/addition, lane expansion,
or target update, remove it from `coverage_gaps` instead of leaving it
behind as historical noise.
17. Before coding begins on a governed slice, record a `status.json.work_claims`
entry for the chosen slice.
The claim is an audit trail: it records what is being worked on and
prevents accidental overlap if the same surface is resumed or handed off.
Expired claims no longer mark active work; remove them when encountered so
the live claim set stays trustworthy.
18. Lane work must be evaluated against the canonical v6 model, not only the
local state it inherits.
For any lane or candidate lane, first identify the canonical v6 shape for
that surface: unified-resource-backed where applicable, canonical shared
types and APIs, explicit subsystem ownership, and legacy compatibility code
reduced to boundary-only exceptions instead of primary flow.
When a lane surface still routes through a pre-v6 or host-era shape, do
not merely improve that path locally and call the lane healthier.
Either modernize it toward the canonical v6 mechanism in the same slice or
record the remaining modernization gap explicitly in the owning lane's
completion state, follow-up tracking, or lane-shaping governance.
19. These modernization rules are retrospective.
Existing lanes do not keep their floor forever just because earlier work
landed before the control system made this explicit.
When an existing lane is touched, reviewed, or reopened, judge it against
the same canonical v6 modernization rules as new lane work and lower its
claimed completeness if legacy-primary paths are still carrying the surface.
Backward compatibility is not a blanket excuse to keep old internal
mechanisms alive. Preserve legacy behavior only at explicit boundaries such
as migrations, upgrades, imports, external contracts, or wire
interoperability that still genuinely exist; otherwise retire the
legacy-primary path instead of teaching the lane to depend on it.
20. Guardrail-only work is support work, not lane advancement.
Contract ratchets, proof-routing cleanup, registry tightening, and
guardrail-only tests may strengthen confidence, but they must not be
treated as substantive lane movement by themselves.
If `status.json` advances a lane's score, status, or completion state, the
same slice should normally include an owned runtime or product-surface
delta for that lane unless the remaining gap is explicitly governance-only.
21. Large machine control files are canonical databases, not startup prompt
payload.
Treat them as canonical databases, not startup prompt payload.
Agents should prefer executable summaries and targeted lookup commands over
rereading `status.json` or `registry.json` in full on ordinary turns.
Escalate into the raw files only when a lane, assertion, release gate,
work claim, or subsystem boundary actually requires full-detail inspection.
22. Legacy compatibility must be named as a boundary exception, not assumed as
a primary v6 design goal.
If a touched surface still needs old-path support, make the boundary
obligation explicit in the owning contract or lane residual. Otherwise,
treat continuing investment in that old internal path as drift, not
prudence.
23. Claimed lane work should prefer the largest coherent same-surface slice.
Within an active claimed lane, prefer the largest coherent same-surface slice.
When one behavior arc on one governed surface is already clearly in scope,
group the remaining same-surface work into the largest slice that still
has one coherent proof story.
Do not fragment a single modernization or canonicalization arc into many
tiny commits just because each residue item can be named separately. Split
only when there is a real risk boundary, concept boundary, or proof
boundary.
24. Lane scores, missing evidence items, and proof counts are signals, not the
work target.
Use them to find the remaining runtime, product, ownership, or governance
gap that still keeps the lane below floor.
Do not frame a slice as "get two more evidence items" or "raise the lane
score" unless the remaining gap is explicitly governance-only.
For ordinary lane work, identify the real same-lane gap first, then add
the proof that demonstrates the gap is actually closed.
25. Worktrees are available for isolated mutating slices when explicit isolation
is needed.
A shared mutable checkout is fine for normal single-session work.
Use `worktree_base.py`, `worktree_claim.py`, and `worktree_finish.py` when
a slice requires its own isolated hooks, staged scope, and dirty state —
for example when a subagent needs to mutate independently and land back
cleanly.
## Non-Negotiable Release Gates
1. Do not ship with open trust-critical P0s.
2. Do not ship when paywalls and runtime gates disagree.
3. Do not ship hosted Pulse flows that break signup, auth, provision, hosted
runtime access, billing/admin visibility, or revocation.
4. Do not ship multi-tenant support if tenant isolation, organization scope,
tenant-scoped runtime state, or cross-org sharing can leak outside the
intended tenant boundary.
5. Do not ship MSP support if one provider account cannot safely onboard,
manage, and separate multiple client tenants from one control surface.
6. Do not ship if API tokens can exceed assigned user, org, or scope
boundaries, survive revocation, or silently widen authority through legacy
alias handling.
7. Do not ship if a low-privilege user can view, mutate, or destroy beyond the
permissions granted by their effective org membership and role.
8. Do not ship if grandfathered recurring continuity, cancellation revocation,
and later re-entry pricing can drift across Stripe, Pulse runtime, and
customer-visible billing state.
9. Do not ship if Pulse Mobile can keep stale access, lose approval state, or
fail pairing, reconnect, or auth-transition recovery against a real
instance.
10. Do not ship if relay registration, reconnect, stale-session recovery, or
disconnect drain can strand clients in resume loops, dead sessions, or
lost inflight work.
11. Do not ship upgrades that reset paid state, licensing continuity, or
first-session flow.
12. Do not ship if comparable settings surfaces drift away from the canonical
page-shell contract and still present inconsistent top-level framing,
header chrome, or section treatment without explicit justification.
13. Do not keep polishing strong lanes while weak lanes remain behind.
14. Do not treat `status.json` lane scores reaching target as sufficient release approval by themselves; open operational decisions, machine-derived unresolved readiness assertions, and unresolved release gates still apply.
15. Do not promote v6 to stable or GA without an exercised RC, a real
release-pipeline proof run, a recorded rollback target plus exact
reinstall command, and a written v5 maintenance-only support policy.
16. Do not declare a lane or blocker complete just because the first passing
check landed. If obvious same-lane gaps still keep the outcome from being
coherent, trustworthy, or realistically shippable, that lane is not done
yet.
17. Lanes that are at target but intentionally not closed must record a
bounded residual in `status.json` with a short rationale and explicit
tracking references to the governing follow-up surface.
Pair lane `status` and `completion.state` coherently: `complete` goes with
`target-met`, `bounded-residual` goes with `partial`, and `open` must not
be paired with `target-met`.
`partial` means measurable progress, so it must not sit at zero score.
`not-started` means zero score and `open`. `blocked` remains an `open`
lane below target rather than a residual or complete state.
Blocked lanes must declare typed same-lane blocker references to unresolved
readiness assertions, release gates, or open decisions.
`completion.tracking` is only for bounded residuals; open or complete lanes
should keep that list empty until the lane reaches its current floor and
the remaining work becomes a governed residual.
Those references must belong to that same lane and must still be
unresolved rather than pointing at unrelated governance objects or
already-passed assertions, gates, or completed targets.
Bounded residual tracking must use a lane followup, readiness assertion,
release gate, or open decision rather than a broad target reference.
`lane_followups` are active residual records, not a loose backlog: each one
should stay referenced by the owning lane's `bounded-residual`
`completion.tracking`.
Once a lane followup is no longer active residual work, remove it from
`lane_followups` instead of leaving it behind with a completed status.
18. Do not treat a lane as healthy just because it has local fixes on a legacy path.
If the canonical v6 route for that surface now runs through unified
resources, canonical shared types, explicit subsystem ownership, or a
modernized proof path, the lane is still below floor until that migration
is made or the remaining gap is governed explicitly.
19. Do not treat missing evidence count or a score delta as the task itself.
If the real remaining gap is runtime, product, ownership, or behavior
coherence, fix that gap and let the score/evidence catch up as proof.
Only treat evidence-count closure itself as the task when the remaining
gap is explicitly governance-only.
20. Do not run parallel mutating agents out of one dirty checkout and call
that acceptable coordination.
Claims reduce overlap, but they do not isolate hooks, formatters, staged
reads, or unrelated dirt. Parallel mutation should use separate worktrees
so each agent sees one slice's git state at a time.
## Locked Decisions
1. Release-control execution is direct and repo-aware. The old orchestrator and
loop tooling are retired.
2. v6 GA is gated by `L1`, `L2`, `L3`, `L5`, `L6`, `L7`, `L8`, `L9`, `L10`,
`L11`, and `L12`. `L4` remains post-GA track work and is not a GA floor
gate.
3. Trial authority for v6 is SaaS-controlled.
`POST /api/license/trial/start` must initiate hosted signup only; the local
runtime may redeem signed trial activations but must not mint local trial
state directly.
4. v5 to v6 commercial migration must preserve unresolved paid-license state
and downgrade safety.
5. Cloud and MSP Stripe `price_*` IDs are operational fill-in items, not
architectural blockers.
6. Stable or GA promotion for v6 must come from an exercised RC and stay
blocked until the RC-to-GA promotion gate is cleared and the published v5
maintenance-policy notice is ready.
7. v6 and later releases use a promotion model, not a direct broad-rollout
model.
`stable` must receive only promoted, already-validated builds, `rc` is the
opt-in preview channel, and unattended auto-update exposure remains
`stable`-only unless a new channel policy is explicitly adopted.
8. Once v6 reaches stable or GA, v5 enters a 90-day maintenance-only window:
critical security issues, critical correctness/data-loss issues, and safe
migration blockers only. The exact end-of-support date must be published in
the GA release notice. After that window, v5 is unsupported.
9. Paid Pulse Pro v5 customers keep their existing recurring price through the
v6 pricing change until they cancel. Renewal and entitlement continuity
must preserve that grandfathered price state; any return after cancellation
must use current v6 pricing.
10. Pulse Mobile does not need desktop parity to stop blocking the v6 RC line.
The mobile usefulness floor for RC is narrower: preserve at least one
trusted paired instance across relaunches, expose relay/runtime state
clearly in the main shell, fail closed into a recoverable disconnected
state on stale or revoked access, and keep live approvals useful and
recoverable. Broader parity and expansion remain post-RC scope.
11. The minimum required update set for canonical work is a floor, not a lane
closure rule. Agents should push the current lane to a coherent,
defensible stop point and complete the next obvious same-lane work when it
is necessary for trustworthy results, then normalize any remaining valid
gap instead of calling the lane done by default.
## Cross-Repo Contracts
These contracts must not drift:
1. Licensing contract:
`pulse/pkg/licensing` semantics vs license-server plans and gates.
2. Relay grant contract:
license-server issued grants vs relay-server acceptance.
3. Relay protocol contract:
`pulse/internal/relay`, `pulse-pro/relay-server`, and
`pulse-mobile/src/relay` wire compatibility.
4. Pricing contract:
architecture pricing docs vs Stripe and checkout wiring in `pulse-pro`.
## Development Governance
For canonical subsystem work:
1. Read `docs/release-control/CONTROL_PLANE.md`,
`docs/release-control/AGENT_VALUES.md`,
`docs/release-control/control_plane.json`, this file, and
`docs/release-control/v6/status.json` first.
Use `python3 scripts/release_control/control_plane.py --agent-entrypoint --pretty`
when you need the canonical ordered entry bundle instead of reconstructing
it manually.
If the agent starts outside the `pulse` repo, resolve those files from
`pulse/docs/release-control/v6/` under the shared workspace root rather than
inventing a parallel control layer in the current repo.
2. Then read `docs/release-control/v6/CANONICAL_DEVELOPMENT_PROTOCOL.md`.
3. Then read `docs/release-control/v6/internal/subsystems/registry.json`.
4. Then read the relevant subsystem contract under
`docs/release-control/v6/internal/subsystems/`.
5. Update `status.json` when live lane state, readiness derivation rules,
lane completion records, coverage-gap records, candidate-lane planning
records, assertion proof routes, evidence references, or typed operational
decision records change.
6. Update this file only when stable governance, scope, locked decisions, or
the readiness-assertion design rules change.
7. When a canonical path replaces an old path, add or tighten a guardrail so
the old path cannot silently return.
8. When the active target's machine-derived completion rule is satisfied,
update `docs/release-control/control_plane.json` in the same task or stop
and promote the next target before continuing under stale scope.
9. When the user changes Pulse's priority or says what the product should focus
on next, classify that as an active-target update or another control-plane
change instead of leaving it as informal discussion.
10. Do not wait for a special governance prompt.
If the user casually says something should be consistent, seamless,
difficult to bypass, free of drift, or always true, decide whether it
belongs in a readiness assertion, release gate, open decision, or active
target before ending the task.
11. Do not stop at the first narrow success inside a lane.
When the next obvious same-lane work is still required for a coherent and
trustworthy result, complete it in the same slice when feasible.
12. Keep that standard bounded.
If the remaining work clearly belongs to another lane, another active
target, a larger redesign, or a separately governed open decision, record
that state explicitly instead of expanding the current slice without end.
13. If the current lane map no longer models a durable product surface cleanly,
record that discovery in `status.json.coverage_gaps` with evidence and an
intended promotion path instead of burying it in generic residual text.
14. Treat lane completion, lane coverage, and coverage planning as separate
derived signals.
`status_audit.py --pretty` may derive a lane-completion score from
`current_score/target_score`, a lane-coverage score from unresolved
`coverage_gaps`, a coverage-planning score from unresolved
`coverage_gaps` that still lack explicit `candidate_lanes`, and a
conservative governed-surface score as the lower of completion and
coverage.
Those scores are decision aids, not proof that unknown work does not
exist.
15. Treat active work claiming as its own live control surface.
`status.json.work_claims` should hold only live lease-style claims, not a
historical log, and `status_audit.py --pretty` should make active claims,
expired claims, claim conflicts, and the `available_candidate_lane_queue`
visible enough that agents can avoid overlapping picks.
Use `scripts/release_control/work_claim.py` as the default reservation
path rather than hand-editing claim objects when the system can reserve
the slice directly.
16. Keep prompt-like guidance values-led.
If a rule needs detailed repeated reminder, prefer strengthening the
control plane, active profile, subsystem contracts, audits, or guardrails
over expanding prompt prose into a second operating manual.
17. Keep governance routing quiet by default.
Resolving the canonical entry bundle, choosing the owning lane, and
deciding whether a claim or governance update is required should usually
happen in the background. Surface those mechanics only when they
materially change blockers, scope, cross-repo impact, or the user's next
decision.
For readiness assertion work:
1. Update this file only when the readiness-assertion design rules change.
2. Update `status.json.readiness_assertions` when the active assertion catalog
or proof references/proof commands change.
3. Route manual assertion proof through
`HIGH_RISK_RELEASE_VERIFICATION_MATRIX.md` whenever the assertion needs a
trust-critical release gate instead of a one-off checklist.
## Source Domains
If conflicts appear, resolve by domain:
1. `docs/release-control/v6/CANONICAL_DEVELOPMENT_PROTOCOL.md`,
`docs/release-control/v6/internal/subsystems/registry.json`, and the relevant
subsystem contract own implementation rules.
2. `docs/release-control/v6/status.json` owns live lane state, the active
readiness assertion catalog, readiness derivation rules, executable proof
commands, coverage-gap discovery records, candidate-lane planning records,
structured evidence references, and typed operational decision records.
3. `docs/release-control/v6/status.schema.json` owns the machine-readable shape
contract for `status.json`.
4. `docs/release-control/v6/internal/subsystems/registry.schema.json` owns the
machine-readable shape contract for the subsystem registry.
5. `docs/release-control/AGENT_VALUES.md` owns evergreen agent values, while
`docs/release-control/CONTROL_PLANE.md` and
`docs/release-control/control_plane.json` own evergreen governance, active
profile selection, and active target selection.
6. This file owns profile-specific governance, repo scope, release gates,
readiness assertion design rules, and locked decisions for v6.
7. Supporting architecture and release docs are evidence only. They do not
override the files above.
@@ -0,0 +1,83 @@
# RC-to-GA Promotion Readiness Blocked Record
- Date: `2026-03-13`
- Gate: `rc-to-ga-promotion-readiness`
- Result: `blocked`
## Blocking Facts
1. No Pulse v6 RC has shipped yet.
2. The repository contains accidental prerelease git tag history (`v6.0.0-rc.1`),
but those tags were never published and do not count as shipped RC lineage.
3. GitHub still validates `Release Dry Run` workflow dispatch inputs against the
default branch `main`, whose current workflow contract does not
accept the governed stable rehearsal metadata envelope (`promoted_from_tag`,
`rollback_version`, `ga_date`, and `v5_eos_date`).
4. The governed release profile in `docs/release-control/control_plane.json`
currently declares both `prerelease_branch` and `stable_branch` as
`pulse/v6-release`.
5. The active control-plane target is still `v6-rc-stabilization`, not
`v6-ga-promotion`.
6. The active local `pulse/v6-release` branch currently reports `VERSION=6.0.0-rc.1`, so the
working line is still prerelease and there is not yet a governed local stable
`6.0.0` candidate.
7. There is still no governed `RC-to-GA Rehearsal Record` proving a successful
non-publish `Release Dry Run` for the eventual stable `6.0.0` candidate.
8. `docs/releases/RELEASE_NOTES_v6.md` and
`docs/release-control/v6/V5_MAINTENANCE_SUPPORT_POLICY.md` now carry the
currently proposed exact dates for the eventual GA notice:
- `v6` GA date: `2026-03-24`
- `v5` end-of-support date: `2026-06-22`
9. There is still no governed `Release Dry Run` artifact or rehearsal record
exercising stable inputs for:
- `version=6.0.0`
- no governed `promoted_from_tag` exists yet because no RC has shipped
- the artifact-owned candidate stable tag for that rehearsal
- the artifact-owned promotion channel for that rehearsal
- the artifact-owned promoted RC tag for that rehearsal
- the artifact-owned rollback target for that stable candidate
- `ga_date=2026-03-24`
- an explicit `rollback_version`
- the exact derived rollback command that artifact will publish
- `v5_eos_date=2026-06-22`
## Why The Gate Cannot Be Cleared Yet
The blocker is no longer missing governance text. The remaining problem is that
the control plane still treats v6 as an RC-stabilization line, the working
version is still prerelease (`6.0.0-rc.1`), and there is still no exercised
`Release Dry Run` record proving the eventual stable `6.0.0`
candidate is ready for GA-style promotion. Until that rehearsal exists, stable
users would still be the first real cohort for the final promotion path.
## Required Unblock Steps
1. Promote the active target from `v6-rc-stabilization` to
`v6-ga-promotion` only when that change is actually intended.
2. Push the governed `pulse/v6-release` branch state that is intended to become the
stable `6.0.0` candidate, including the eventual `VERSION=6.0.0`
change and release-control records, to `origin/pulse/v6-release`.
3. Land the canonical `.github/workflows/release-dry-run.yml` workflow-dispatch input
contract on the default branch `main` so GitHub accepts the
governed stable rehearsal metadata envelope when dispatching from `pulse/v6-release`.
4. Ship the first real RC through the governed prerelease release path and record
its exact published prerelease tag plus rollback target and exact derived
rollback command.
5. Run `Release Dry Run` from `pulse/v6-release` using that published RC as
`promoted_from_tag` with:
- `version=6.0.0`
- an artifact-owned candidate stable tag matching that rehearsal
- an artifact-owned promotion channel matching that rehearsal
- an artifact-owned promoted RC tag matching that rehearsal
- an artifact-owned rollback target for the stable candidate
- the exact planned GA and v5 end-of-support dates for the publish notice
- `ga_date=2026-03-24`
- an explicit stable `rollback_version`
- the exact derived rollback command that artifact will publish
- `v5_eos_date=2026-06-22`
6. Capture the `rc-to-ga-rehearsal-summary` artifact and run URL.
7. Materialize the final rehearsal record from that artifact without
hand-repairing any missing candidate tag, promoted RC tag, rollback
target, rollback command, or GA/EOS metadata.
8. Change the gate from `blocked` only if the rehearsal passes and the rollout
inputs remain explicit.