Objective
One human approval per Context Panel release, not one per job.
Why
On 2026-10-03, Ship run 37124932609 asked Chris for the release environment approval twice: once for Validate Release Intent (ship.yml), then again for the channel jobs (release.yml "Build macOS App" and app-store-connect-upload.yml "Upload Mac App"), because GitHub requires environment approval per job and the channel jobs reach the gate only after the intent job passes. Chris: "I thought we had one click release." No earlier decision makes release a single approval; Ship is one dispatch, but the approval count grows with the channels. Seven workflows attach environment: release today.
Owner decision
Chris, 2026-10-03, typed in the direction session codex-skills-d2, recorded by it: yes, make it a single approval.
Finish Line
- The Director's required review sits on exactly one job per Ship run (the release-intent gate).
- Channel jobs that need signing or upload secrets use a separate environment with no required reviewer, restricted to the protected
main branch, and run only after the approved intent job (job dependency), so the secrets stay reachable only through an approved Ship run.
- Standalone channel workflows that can be dispatched directly (TestFlight, App Store review submission, screenshots, companion upload) keep a required review, or are reachable only through Ship; say which on the PR.
- Executed tests or a dry-run proof show one approval prompt for a full Ship run.
- The release doc says how many approvals a release takes and why.
Hand step for Chris (posted by the implementing session when ready)
Creating the new environment, its branch rule and moving the channel secrets into it is an access change, so it is Chris's by hand, with exact clicks; the agent never copies or reads secret values.
Current Status
State: Complete. Source merged and Chris completed the environment-role hand setup; fresh read-only live checks and all-channel structural dry-run satisfy the finish line.
Merged: #751 at 5af6bb8, correcting merged #748 under Owner decision 5969947705.
Owner completion: #747 (comment). Existing release secrets stayed untouched; release-channels never existed. RELEASE_APPROVALS_CONFIGURED=true is owner-confirmed, not independently read by this bot.
Live evidence: Landed scripts/check-release-approval-environment.py full mode exited 0: required owner review verified. --probe exited 0: secret-store protection metadata verified. Additional GET-only metadata assertions verified release has no required reviewer and neither environment has a nonzero wait timer. release-approval requires exactly cbusillo (User), allows solo self-review, disables administrator bypass; both use protected-branches-only and the checker verified main is the sole protected branch. No secret endpoint or secret value was read.
Dry-run evidence: Landed scripts/check-release-approvals.py exited 0 at exact merge 5af6bb8. Ship has one reviewed approve job for all four channels, zero gate secret references, and release as the sole secret environment. Each of six standalone workflows has one reviewed approve gate. Docs explain that count. This is the finish line's permitted structural dry-run, not an observed release prompt.
Engineering evidence: 4/4 PR checks and exact landing CI/CodeQL green; commit gate passed with 1,203 Swift tests, focused release suite 118 passed, final approval fixtures/fast Python gate/actionlint passed. Exact 15-file PyCharm inspection GREEN, zero findings. Five independent Anthropic review dispositions recorded on #751; final approval implementation matches reviewed source. Four pre-existing Markdown MD013 findings reproduced on base.
Residuals: No live release dispatched or prompt exercised. The next separately authorized release will execute the activation-variable guard. Secret inventory is owner-confirmed. The documented optional ad-hoc signing mode remains. Historical-rerun exposure was accepted in switch-now Owner decision 5970898082; no 30-day wait remains. Computed future environment names remain separate #750; #749 and #736 were not started here. Sanitized secret scanning unavailable, not clean; no open CodeQL alerts observed during engineering closeout.
Next action: None required to complete #747. Future releases remain separately authorized; this worker must not dispatch or rerun one.
Blocked by: None.
Cleanup: Own implementation worktree/branches and task scratch removed; no transient job remains. One unowned SDK preserved. Clean primary main deliberately remains stale under no-primary-edit authority; fast-forward before future default-branch work/audits. Installed runtime, the 1.0.69 release session/run/worktree and other worktrees untouched.
Admission: direction#16 spare-capacity engineering rule recorded in claim 5970387065; claim released.
Last verified: 2026-10-03, fresh GET-only probe after Owner completion.
Objective
One human approval per Context Panel release, not one per job.
Why
On 2026-10-03, Ship run 37124932609 asked Chris for the
releaseenvironment approval twice: once forValidate Release Intent(ship.yml), then again for the channel jobs (release.yml"Build macOS App" andapp-store-connect-upload.yml"Upload Mac App"), because GitHub requires environment approval per job and the channel jobs reach the gate only after the intent job passes. Chris: "I thought we had one click release." No earlier decision makes release a single approval; Ship is one dispatch, but the approval count grows with the channels. Seven workflows attachenvironment: releasetoday.Owner decision
Chris, 2026-10-03, typed in the direction session codex-skills-d2, recorded by it: yes, make it a single approval.
Finish Line
mainbranch, and run only after the approved intent job (job dependency), so the secrets stay reachable only through an approved Ship run.Hand step for Chris (posted by the implementing session when ready)
Creating the new environment, its branch rule and moving the channel secrets into it is an access change, so it is Chris's by hand, with exact clicks; the agent never copies or reads secret values.
Current Status
State: Complete. Source merged and Chris completed the environment-role hand setup; fresh read-only live checks and all-channel structural dry-run satisfy the finish line.
Merged: #751 at 5af6bb8, correcting merged #748 under Owner decision 5969947705.
Owner completion: #747 (comment). Existing release secrets stayed untouched; release-channels never existed. RELEASE_APPROVALS_CONFIGURED=true is owner-confirmed, not independently read by this bot.
Live evidence: Landed scripts/check-release-approval-environment.py full mode exited 0: required owner review verified. --probe exited 0: secret-store protection metadata verified. Additional GET-only metadata assertions verified release has no required reviewer and neither environment has a nonzero wait timer. release-approval requires exactly cbusillo (User), allows solo self-review, disables administrator bypass; both use protected-branches-only and the checker verified main is the sole protected branch. No secret endpoint or secret value was read.
Dry-run evidence: Landed scripts/check-release-approvals.py exited 0 at exact merge 5af6bb8. Ship has one reviewed approve job for all four channels, zero gate secret references, and release as the sole secret environment. Each of six standalone workflows has one reviewed approve gate. Docs explain that count. This is the finish line's permitted structural dry-run, not an observed release prompt.
Engineering evidence: 4/4 PR checks and exact landing CI/CodeQL green; commit gate passed with 1,203 Swift tests, focused release suite 118 passed, final approval fixtures/fast Python gate/actionlint passed. Exact 15-file PyCharm inspection GREEN, zero findings. Five independent Anthropic review dispositions recorded on #751; final approval implementation matches reviewed source. Four pre-existing Markdown MD013 findings reproduced on base.
Residuals: No live release dispatched or prompt exercised. The next separately authorized release will execute the activation-variable guard. Secret inventory is owner-confirmed. The documented optional ad-hoc signing mode remains. Historical-rerun exposure was accepted in switch-now Owner decision 5970898082; no 30-day wait remains. Computed future environment names remain separate #750; #749 and #736 were not started here. Sanitized secret scanning unavailable, not clean; no open CodeQL alerts observed during engineering closeout.
Next action: None required to complete #747. Future releases remain separately authorized; this worker must not dispatch or rerun one.
Blocked by: None.
Cleanup: Own implementation worktree/branches and task scratch removed; no transient job remains. One unowned SDK preserved. Clean primary main deliberately remains stale under no-primary-edit authority; fast-forward before future default-branch work/audits. Installed runtime, the 1.0.69 release session/run/worktree and other worktrees untouched.
Admission: direction#16 spare-capacity engineering rule recorded in claim 5970387065; claim released.
Last verified: 2026-10-03, fresh GET-only probe after Owner completion.