From 40c3081700248e1937f7178684ecb2addadac76d Mon Sep 17 00:00:00 2001 From: Codex Automation Date: Sun, 16 Aug 2026 16:38:45 -0500 Subject: [PATCH 1/3] fix: reconcile explicit admin deliveries --- .../__tests__/sync_pr_merge_contract.test.js | 41 ++++++++++++++++++ .github/scripts/maint71_merge_sync_prs.js | 43 ++++++++++++++++--- .github/workflows/maint-71-merge-sync-prs.yml | 3 ++ docs/ops/SYNC_DEPENDENCY_CAMPAIGN.md | 6 ++- .../workflows/test_sync_delivery_liveness.py | 2 + 5 files changed, 88 insertions(+), 7 deletions(-) diff --git a/.github/scripts/__tests__/sync_pr_merge_contract.test.js b/.github/scripts/__tests__/sync_pr_merge_contract.test.js index e4f006682..ab4f69ad6 100644 --- a/.github/scripts/__tests__/sync_pr_merge_contract.test.js +++ b/.github/scripts/__tests__/sync_pr_merge_contract.test.js @@ -60,9 +60,50 @@ const { parseNoChangeEvidenceDocument, parseReviewResolutionProofs, run, + selectReconciliationTargets, validateReviewResolutionProof, } = require('../maint71_merge_sync_prs'); +test('Maint 71 keeps Collab-Admin out of fleet runs but allows an explicit manual reconciliation', () => { + const excludedRepos = new Set(['stranske/Collab-Admin']); + const manuallyReconcilableRepos = new Set(['stranske/Collab-Admin']); + const registeredRepos = ['stranske/Trend_Model_Project']; + + assert.deepEqual( + selectReconciliationTargets({ + requestedSyncHash: 'delivery', + inputRepos: 'all', + registeredRepos, + expectedCanaryRepos: [], + excludedRepos, + manuallyReconcilableRepos, + }), + registeredRepos, + ); + assert.deepEqual( + selectReconciliationTargets({ + requestedSyncHash: 'delivery', + inputRepos: 'stranske/Collab-Admin', + registeredRepos, + expectedCanaryRepos: [], + excludedRepos, + manuallyReconcilableRepos, + }), + ['stranske/Collab-Admin'], + ); + assert.deepEqual( + selectReconciliationTargets({ + requestedSyncHash: 'candidate', + inputRepos: 'stranske/Collab-Admin', + registeredRepos, + expectedCanaryRepos: ['stranske/Travel-Plan-Permission'], + excludedRepos, + manuallyReconcilableRepos, + }), + ['stranske/Travel-Plan-Permission'], + ); +}); + const pr = (number, ref, created_at) => ({ number, title: `sync ${number}`, diff --git a/.github/scripts/maint71_merge_sync_prs.js b/.github/scripts/maint71_merge_sync_prs.js index 570dccedc..7f94bbad8 100644 --- a/.github/scripts/maint71_merge_sync_prs.js +++ b/.github/scripts/maint71_merge_sync_prs.js @@ -172,6 +172,29 @@ function validateReviewResolutionProof(proof = {}, { return { ok: errors.length === 0, errors }; } +function selectReconciliationTargets({ + requestedSyncHash, + inputRepos, + registeredRepos, + expectedCanaryRepos, + excludedRepos, + manuallyReconcilableRepos, +}) { + if (requestedSyncHash === 'candidate') { + return expectedCanaryRepos; + } + if (inputRepos === 'all') { + return registeredRepos; + } + return inputRepos + .split(',') + .map((repo) => repo.trim()) + .filter( + (repo) => + repo && (!excludedRepos.has(repo) || manuallyReconcilableRepos.has(repo)), + ); +} + async function collectReviewerEvidence({ owner, repo, @@ -725,6 +748,12 @@ async function run({ github, context, core }) { .map((repo) => repo.trim()) .filter(Boolean), ); + const manuallyReconcilableRepos = new Set( + String(process.env.MANUAL_RECONCILIATION_REPOS_INPUT || '') + .split(',') + .map((repo) => repo.trim()) + .filter(Boolean), + ); const registeredRepos = String(process.env.REGISTERED_REPOS_INPUT || '') .split(',') .map(r => r.trim()) @@ -838,11 +867,14 @@ async function run({ github, context, core }) { // complete consumer registry here lets unrelated non-canary delivery PRs // create target_missing failures and can make promotion evidence unusable. // Always derive this target set from the canonical canary registry. - const targetRepos = requestedSyncHash === 'candidate' - ? expectedCanaryRepos - : inputRepos === 'all' - ? registeredRepos - : inputRepos.split(',').map(r => r.trim()).filter((repo) => repo && !excludedRepos.has(repo)); + const targetRepos = selectReconciliationTargets({ + requestedSyncHash, + inputRepos, + registeredRepos, + expectedCanaryRepos, + excludedRepos, + manuallyReconcilableRepos, + }); console.log(`Registered consumer repos: ${registeredRepos.join(', ')}`); console.log(`Processing repos: ${targetRepos.join(', ')}`); @@ -2580,5 +2612,6 @@ module.exports = { parseNoChangeEvidenceDocument, parseReviewResolutionProofs, run, + selectReconciliationTargets, validateReviewResolutionProof, }; diff --git a/.github/workflows/maint-71-merge-sync-prs.yml b/.github/workflows/maint-71-merge-sync-prs.yml index 1bc57ca81..72b74f747 100644 --- a/.github/workflows/maint-71-merge-sync-prs.yml +++ b/.github/workflows/maint-71-merge-sync-prs.yml @@ -309,6 +309,7 @@ jobs: TRUSTED_REVIEW_RESOLUTION_ACTORS: stranske,stranske-automation-bot REVIEW_RESOLUTION_JSON: ${{ inputs.review_resolution_json }} EXCLUDED_REPOS_INPUT: stranske/Collab-Admin + MANUAL_RECONCILIATION_REPOS_INPUT: stranske/Collab-Admin SYNC_PR_MERGE_REPORT_JSON: artifacts/sync-review-resolution-report.json REGISTERED_REPOS_INPUT: ${{ steps.repos.outputs.list }} with: @@ -339,6 +340,7 @@ jobs: TRUSTED_REVIEW_RESOLUTION_ACTORS: stranske,stranske-automation-bot REVIEW_RESOLUTION_JSON: ${{ inputs.review_resolution_json || '' }} EXCLUDED_REPOS_INPUT: stranske/Collab-Admin + MANUAL_RECONCILIATION_REPOS_INPUT: stranske/Collab-Admin SYNC_PR_MERGE_REPORT_JSON: artifacts/sync-pr-premerge-report.json REGISTERED_REPOS_INPUT: ${{ steps.repos.outputs.list }} with: @@ -430,6 +432,7 @@ jobs: TRUSTED_REVIEW_RESOLUTION_ACTORS: stranske,stranske-automation-bot REVIEW_RESOLUTION_JSON: ${{ inputs.review_resolution_json || '' }} EXCLUDED_REPOS_INPUT: stranske/Collab-Admin + MANUAL_RECONCILIATION_REPOS_INPUT: stranske/Collab-Admin SYNC_PR_MERGE_REPORT_JSON: artifacts/sync-pr-merge-report.json REGISTERED_REPOS_INPUT: ${{ steps.repos.outputs.list }} with: diff --git a/docs/ops/SYNC_DEPENDENCY_CAMPAIGN.md b/docs/ops/SYNC_DEPENDENCY_CAMPAIGN.md index 28306e383..8a1cf569c 100644 --- a/docs/ops/SYNC_DEPENDENCY_CAMPAIGN.md +++ b/docs/ops/SYNC_DEPENDENCY_CAMPAIGN.md @@ -93,8 +93,10 @@ After a candidate-selector run has complete same-plan evidence and every configured candidate was merged or recovered, Maint 71 passes that exact JSON to Maint 68 `phase=promote`. Maint 68 in turn dispatches the delivery selector after writing non-canary PRs. Neither chain permits an explicit non-canary repo -through `phase=canary`, and `stranske/Collab-Admin` is excluded from reconciler -targets. +through `phase=canary`, and `stranske/Collab-Admin` is excluded from default +fleet reconciler targets. Its administration-surface delivery may be processed +only through an explicit one-repository Maint 71 request; it never contributes +to candidate or campaign evidence. An active review thread remains a hard merge block. The bounded exception is an explicit `workflows-sync-review-resolution/v1` proof supplied to Maint 71. It diff --git a/tests/workflows/test_sync_delivery_liveness.py b/tests/workflows/test_sync_delivery_liveness.py index da56b51c3..79339aa98 100644 --- a/tests/workflows/test_sync_delivery_liveness.py +++ b/tests/workflows/test_sync_delivery_liveness.py @@ -31,6 +31,8 @@ def test_maint71_has_proof_bound_review_resolution_and_exact_evidence_promotion( assert "canary_evidence_json: JSON.stringify(evidence)" in workflow assert "cancel-in-progress: false" in workflow assert "EXCLUDED_REPOS_INPUT: stranske/Collab-Admin" in workflow + assert "MANUAL_RECONCILIATION_REPOS_INPUT: stranske/Collab-Admin" in workflow + assert "selectReconciliationTargets" in executor assert "['candidate', 'campaign', 'delivery', 'dev-tool']" in workflow assert "/^[0-9a-f]{12,64}$/i.test(selector)" in workflow assert "active sync selector must be candidate, campaign, delivery, dev-tool, " in workflow From 0d949f14f9141dca53197948bb9b2614cf2efa02 Mon Sep 17 00:00:00 2001 From: Codex Automation Date: Sun, 16 Aug 2026 17:02:18 -0500 Subject: [PATCH 2/3] fix(maint-71): scope admin reconciliation to manual delivery --- .../__tests__/sync_pr_merge_contract.test.js | 36 +++++++++++++++++++ .github/scripts/maint71_merge_sync_prs.js | 19 +++++++--- 2 files changed, 50 insertions(+), 5 deletions(-) diff --git a/.github/scripts/__tests__/sync_pr_merge_contract.test.js b/.github/scripts/__tests__/sync_pr_merge_contract.test.js index ab4f69ad6..e9022fb2d 100644 --- a/.github/scripts/__tests__/sync_pr_merge_contract.test.js +++ b/.github/scripts/__tests__/sync_pr_merge_contract.test.js @@ -71,6 +71,7 @@ test('Maint 71 keeps Collab-Admin out of fleet runs but allows an explicit manua assert.deepEqual( selectReconciliationTargets({ + eventName: 'workflow_dispatch', requestedSyncHash: 'delivery', inputRepos: 'all', registeredRepos, @@ -82,6 +83,7 @@ test('Maint 71 keeps Collab-Admin out of fleet runs but allows an explicit manua ); assert.deepEqual( selectReconciliationTargets({ + eventName: 'workflow_dispatch', requestedSyncHash: 'delivery', inputRepos: 'stranske/Collab-Admin', registeredRepos, @@ -93,6 +95,7 @@ test('Maint 71 keeps Collab-Admin out of fleet runs but allows an explicit manua ); assert.deepEqual( selectReconciliationTargets({ + eventName: 'workflow_dispatch', requestedSyncHash: 'candidate', inputRepos: 'stranske/Collab-Admin', registeredRepos, @@ -102,6 +105,39 @@ test('Maint 71 keeps Collab-Admin out of fleet runs but allows an explicit manua }), ['stranske/Travel-Plan-Permission'], ); + + for (const [eventName, requestedSyncHash] of [ + ['repository_dispatch', 'delivery'], + ['workflow_dispatch', 'campaign'], + ['workflow_dispatch', 'dev-tool'], + ['workflow_dispatch', ''], + ]) { + assert.deepEqual( + selectReconciliationTargets({ + eventName, + requestedSyncHash, + inputRepos: 'stranske/Collab-Admin', + registeredRepos, + expectedCanaryRepos: [], + excludedRepos, + manuallyReconcilableRepos, + }), + [], + ); + } + + assert.deepEqual( + selectReconciliationTargets({ + eventName: 'workflow_dispatch', + requestedSyncHash: 'delivery', + inputRepos: 'stranske/Trend_Model_Project,stranske/Collab-Admin', + registeredRepos, + expectedCanaryRepos: [], + excludedRepos, + manuallyReconcilableRepos, + }), + ['stranske/Trend_Model_Project'], + ); }); const pr = (number, ref, created_at) => ({ diff --git a/.github/scripts/maint71_merge_sync_prs.js b/.github/scripts/maint71_merge_sync_prs.js index 7f94bbad8..be853b9f7 100644 --- a/.github/scripts/maint71_merge_sync_prs.js +++ b/.github/scripts/maint71_merge_sync_prs.js @@ -173,6 +173,7 @@ function validateReviewResolutionProof(proof = {}, { } function selectReconciliationTargets({ + eventName, requestedSyncHash, inputRepos, registeredRepos, @@ -186,13 +187,20 @@ function selectReconciliationTargets({ if (inputRepos === 'all') { return registeredRepos; } - return inputRepos + const requestedRepos = inputRepos .split(',') .map((repo) => repo.trim()) - .filter( - (repo) => - repo && (!excludedRepos.has(repo) || manuallyReconcilableRepos.has(repo)), - ); + .filter(Boolean); + const isExplicitManualDelivery = + eventName === 'workflow_dispatch' + && requestedSyncHash === 'delivery' + && requestedRepos.length === 1 + && manuallyReconcilableRepos.has(requestedRepos[0]); + return requestedRepos.filter( + (repo) => + !excludedRepos.has(repo) + || (isExplicitManualDelivery && manuallyReconcilableRepos.has(repo)), + ); } async function collectReviewerEvidence({ @@ -868,6 +876,7 @@ async function run({ github, context, core }) { // create target_missing failures and can make promotion evidence unusable. // Always derive this target set from the canonical canary registry. const targetRepos = selectReconciliationTargets({ + eventName: context.eventName, requestedSyncHash, inputRepos, registeredRepos, From 704e46b2c091dd80a234b33c1241efe93a46d330 Mon Sep 17 00:00:00 2001 From: Codex Automation Date: Sun, 16 Aug 2026 17:09:13 -0500 Subject: [PATCH 3/3] docs(maint-71): define manual admin recovery boundary --- docs/ops/CONSUMER_REPO_MAINTENANCE.md | 10 +++++++++- docs/ops/SYNC_DEPENDENCY_CAMPAIGN.md | 7 +++++-- tests/workflows/test_sync_delivery_liveness.py | 6 ++++++ 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/docs/ops/CONSUMER_REPO_MAINTENANCE.md b/docs/ops/CONSUMER_REPO_MAINTENANCE.md index 97873fb44..3c72a7dd5 100644 --- a/docs/ops/CONSUMER_REPO_MAINTENANCE.md +++ b/docs/ops/CONSUMER_REPO_MAINTENANCE.md @@ -496,7 +496,15 @@ delivery for the same plan; if a partial commit pass already merged it, resume the prepare pass so Maint 71 rebuilds authorization from trusted closed merged history. `stranske/Collab-Admin` is excluded from campaign authorization because it is the generated fleet dashboard/control repository, not a reviewed consumer -delivery target. +delivery target. A narrow operational recovery remains available for an +already-generated administration-surface delivery: manually dispatch +`maint-71-merge-sync-prs.yml` with exactly +`repos=stranske/Collab-Admin` and `active_sync_hash=delivery`. The exception is +accepted only for `workflow_dispatch` with that one normalized repository; it +does not add Collab-Admin to the registry, candidate or campaign evidence, or +scheduled, repository-dispatch, workflow-call, mixed-repository, unscoped, or +other selector runs. Maint 71 still applies the normal exact-head, review, +required-check, seal, and signature gates before any merge. Active non-outdated review threads remain merge blockers. When a shared source repair proves a finding obsolete on the current generated head, an authenticated diff --git a/docs/ops/SYNC_DEPENDENCY_CAMPAIGN.md b/docs/ops/SYNC_DEPENDENCY_CAMPAIGN.md index 8a1cf569c..e7427f462 100644 --- a/docs/ops/SYNC_DEPENDENCY_CAMPAIGN.md +++ b/docs/ops/SYNC_DEPENDENCY_CAMPAIGN.md @@ -95,8 +95,11 @@ to Maint 68 `phase=promote`. Maint 68 in turn dispatches the delivery selector after writing non-canary PRs. Neither chain permits an explicit non-canary repo through `phase=canary`, and `stranske/Collab-Admin` is excluded from default fleet reconciler targets. Its administration-surface delivery may be processed -only through an explicit one-repository Maint 71 request; it never contributes -to candidate or campaign evidence. +only by a `workflow_dispatch` Maint 71 request whose normalized inputs are +exactly `repos=stranske/Collab-Admin` and `active_sync_hash=delivery`; it never +contributes to candidate or campaign evidence. Scheduled, repository-dispatch, +workflow-call, mixed-repository, unscoped, candidate, campaign, and dev-tool +requests continue to exclude it. An active review thread remains a hard merge block. The bounded exception is an explicit `workflows-sync-review-resolution/v1` proof supplied to Maint 71. It diff --git a/tests/workflows/test_sync_delivery_liveness.py b/tests/workflows/test_sync_delivery_liveness.py index 79339aa98..8e913ced6 100644 --- a/tests/workflows/test_sync_delivery_liveness.py +++ b/tests/workflows/test_sync_delivery_liveness.py @@ -4,6 +4,8 @@ def test_maint71_has_proof_bound_review_resolution_and_exact_evidence_promotion(): workflow = Path(".github/workflows/maint-71-merge-sync-prs.yml").read_text() executor = Path(".github/scripts/maint71_merge_sync_prs.js").read_text() + maintenance_guide = Path("docs/ops/CONSUMER_REPO_MAINTENANCE.md").read_text() + campaign_contract = Path("docs/ops/SYNC_DEPENDENCY_CAMPAIGN.md").read_text() assert "review_resolution_json:" in workflow assert "github.event.client_payload.review_resolution_json" not in workflow @@ -33,6 +35,10 @@ def test_maint71_has_proof_bound_review_resolution_and_exact_evidence_promotion( assert "EXCLUDED_REPOS_INPUT: stranske/Collab-Admin" in workflow assert "MANUAL_RECONCILIATION_REPOS_INPUT: stranske/Collab-Admin" in workflow assert "selectReconciliationTargets" in executor + for document in (maintenance_guide, campaign_contract): + assert "repos=stranske/Collab-Admin" in document + assert "active_sync_hash=delivery" in document + assert "workflow_dispatch" in document assert "['candidate', 'campaign', 'delivery', 'dev-tool']" in workflow assert "/^[0-9a-f]{12,64}$/i.test(selector)" in workflow assert "active sync selector must be candidate, campaign, delivery, dev-tool, " in workflow