Repository navigation
Split app release readiness from continuous release readiness - #372
Conversation
Rename the computed releaseEligible to continuousReleaseEligible (keep a deprecated alias for one release), add appReleaseEligible gated on the configuration and machineInterface phases plus the user's appReleaseAttested, and bump the report schemaVersion to 2 (E20 option A). Test-First: scripts/lib/continuous-readiness.test.mjs::app release is blocked without the user attestation Test-First: scripts/lib/continuous-readiness.test.mjs::app release attestation does not make continuous mode release-eligible Test-First: scripts/lib/continuous-readiness.test.mjs::app release still needs configuration and machine interface Test-First: scripts/lib/continuous-readiness.test.mjs::readiness report is schema version 2 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: bce2eda833
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| // App release (E20): needs only the `configuration` and `machineInterface` | ||
| // phases plus the user's own attestation; it never depends on the continuous | ||
| // phases (runtime, delivery, rollout) and never enables continuous mode. | ||
| const appReleaseState = explicitState(evidence, 'appReleaseAttested', 'app release'); | ||
| const appReleaseEligible = phases.configuration.state === 'ready' | ||
| && phases.machineInterface.state === 'ready' | ||
| && appReleaseState.state === 'ready'; |
There was a problem hiding this comment.
Wait for approval before adopting the new release path
At this commit's base, docs/PLAN.md:489 records E20 option A as offen, Nutzer, but these lines implement that option by making the app release eligible with only setup, the machine interface, and a supplied boolean, omitting the existing continuous/review/delivery gates. This is a release-policy change rather than neutral plumbing, so it should retain the prior semantics until the user selects an option and that approval is recorded.
AGENTS.md reference: AGENTS.md:L125-L128
Useful? React with 👍 / 👎.
| appReleaseEligible, | ||
| continuousMode: continuousEligible ? 'eligible-but-disabled-until-explicit-enable' : 'blocked', | ||
| stableRelease: releaseEligible ? 'eligible-after-explicit-release' : 'blocked', | ||
| stableRelease: continuousReleaseEligible ? 'eligible-after-explicit-release' : 'blocked', |
There was a problem hiding this comment.
Label the legacy stable release as continuous-only
When all continuous gates pass but appReleaseAttested is false, this field becomes eligible-after-explicit-release while the new appRelease field remains blocked. The existing consumer in docs/dev-hq/hq.js:731 renders stableRelease under the generic label release, so the human cockpit can say the release is eligible before the user's app-release attestation; rename/deprecate this field as continuous-only or update that consumer to display both domains explicitly.
AGENTS.md reference: AGENTS.md:L44-L48
Useful? React with 👍 / 👎.
| continuousReleaseEligible, | ||
| // Deprecated alias of `continuousReleaseEligible` (not the app release); | ||
| // kept for one release, then removed. Do not present it as "release ok". | ||
| releaseEligible: continuousReleaseEligible, |
There was a problem hiding this comment.
Point the acceptance matrix at app release readiness
The canonical acceptance contract in .pa/continuous_acceptance_matrix.md:37 still requires the audit to produce releaseEligible: true, but this line deliberately keeps that field aliased to continuous-release eligibility. With continuous mode intentionally disabled, a user can therefore attest the app release and obtain appReleaseEligible: true while matrix row 27 remains impossible to satisfy, so this change does not actually remove the E20 release blocker; after approval, update the contract to require the new app-specific field.
Useful? React with 👍 / 👎.
|
Queued — the merge queue status continues in this comment ↓. |
|
Coordinator: B1 (E20 user decision missing) resolved. The user decided option A on 2026-10-04; record in #390. See review disposition. |
|
@Mergifyio queue |
Merge Queue Status
This pull request spent 22 minutes 1 second in the queue, including 12 minutes 5 seconds running CI. Required conditions to merge
|
Der Bericht trennt jetzt den App-Release (v1.5.0) vom Dauerbetrieb-Release:
appReleaseEligiblewird nur durch deine eigene Bestätigung (appReleaseAttested) wahr und setzt nur Einrichtung und Maschinenschnittstelle voraus. Der Dauerbetrieb bleibt exakt so streng gesperrt wie bisher (continuousReleaseEligible). Das alte FeldreleaseEligiblebleibt für ein Release als veralteter Alias, der nicht „Release ok“ bedeutet.Report
What changed (E20 option A, M4-R27-01; base origin/main 9e58578)
scripts/lib/continuous-readiness.mjs:releaseEligiblecomputed ascontinuousReleaseEligible;releaseEligiblekept as deprecated alias (commented); newappReleaseEligible = configuration ready && machineInterface ready && explicitState(evidence,'appReleaseAttested'),appRelease: 'eligible-after-explicit-release' | 'blocked', blockerattestation:appRelease;schemaVersion2.scripts/continuous-audit.mjs: exit code now usescontinuousReleaseEligible(unchanged semantics), hardcodedappReleaseAttested: false, dropped the shadowed outerschemaVersion: 1(the spread already overrode it).scripts/hq-live.mjs:appReleaseAttested: false. No agent writes the attestation.src/andscripts/found no UI/HQ label usingreleaseEligible; onlyhq-routes.test.mjs(now asserts the new fields) anddocs/development/CONTINUOUS.md(updated).continuous-readiness.test.mjs(app false without attestation, true with it while continuous stays false, needs setup/runtime, schema 2); alias equality asserted in existing tests.Evidence
bash scripts/ci/red-first.shexit 0 (4 new tests red/missing at merge base, green at head).node --test scripts/lib/continuous-readiness.test.mjs scripts/lib/hq-routes.test.mjsexit 0 (17 tests).node scripts/ci/architecture-drift.mjs checkexit 0 (no new occurrences).bash scripts/ci/gates.sh lane prepushexit 0 at bce2eda (independent reviewer run: 1769 Rust tests, 520 HQ tests and 480 frontend tests passed).gh pr checks 372exit 0; required PR checks reported pass on candidate bce2eda.Architecture drift: none; the drift gate reported no new occurrences and the review found no competing frontend state, command-result/error, store/lock, IPC-name, or Rust-to-frontend event pattern.
NICHT ABGEDECKT:
#[cfg(windows)]tests and Windows clippy arms (Windows lane runs in the merge queue); no GUI/HQ screenshot (no UI change);.pa/release_attestation_v1.5.0.jsonreader not part of this package. The localprepushlane also does not cover Browser Smoke, the frontend production build, workflow gates, or external updater/OmniRoute/mirror services.Review disposition
bce2eda833b8adc74fb0a7a76adc384869577f1a; tier B; reviewed 2026-10-04.scripts/lib/continuous-readiness.mjs:82: E20 option A is implemented as the app-release eligibility contract although the currentorigin/mainstill records E20 indocs/PLAN.md:489asopen, user. The review checked the current remote plan, the complete diff, PR body, PR comments, and actual callers. The hardcodedappReleaseAttested: falseprevents an immediate release through the current audit, but it does not authorize or cure the new public readiness contract. Resolved (coordinator, 2026-10-04 23:50): the finding was correct about the missing record, but the decision itself exists: the user chose E20 option A on 2026-10-04 in the orchestrator session (his literal answer: "Option A"). The plan record is PR docs(plan): record user decision E20 (option A) #390 (docs/PLAN.md E20 -> "✓ entschieden (Nutzer 04.10.): Option A"), labelled priority so it merges first. No code change needed here.