From 13ba70ddfd195956ec29d5332d21ed78724951e6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 20 Aug 2026 16:18:33 +0900 Subject: [PATCH 1/5] fix: make hourly coordinator credential absence auditable --- ...organization-commercial-readiness-loop.yml | 39 ++++++++++++++++++- CHANGELOG.md | 1 + .../organization-commercial-readiness-loop.md | 2 +- ..._commercial_readiness_loop_secret_scope.py | 10 +++++ 4 files changed, 49 insertions(+), 3 deletions(-) diff --git a/.github/workflows/organization-commercial-readiness-loop.yml b/.github/workflows/organization-commercial-readiness-loop.yml index 521495617a..52b3beb229 100644 --- a/.github/workflows/organization-commercial-readiness-loop.yml +++ b/.github/workflows/organization-commercial-readiness-loop.yml @@ -56,8 +56,43 @@ jobs: shell: bash --noprofile --norc -e -o pipefail {0} run: | if [ -z "${GH_TOKEN:-}" ]; then - echo "::error::PR_REVIEW_MERGE_TOKEN is required; neither the reviewer credential nor repository-scoped GITHUB_TOKEN is accepted." - exit 1 + echo "::warning::PR_REVIEW_MERGE_TOKEN is not provisioned; recording a bounded no-op until the maintainer credential is configured." + python - "$RUNNER_TEMP/organization-commercial-readiness-loop.json" <<'PY' + from __future__ import annotations + + import json + import os + import sys + from pathlib import Path + + output_path = Path(sys.argv[1]) + output_path.parent.resolve(strict=True) + if output_path.is_symlink(): + raise RuntimeError("credential-unavailable receipt must not be a symlink") + rendered = ( + json.dumps( + { + "status": "skipped_credential_unavailable", + "reason": "PR_REVIEW_MERGE_TOKEN is not provisioned", + "next_action": "Provision PR_REVIEW_MERGE_TOKEN for the next hourly pass.", + }, + indent=2, + ) + + "\n" + ) + descriptor = os.open( + output_path, + os.O_WRONLY | os.O_CREAT | os.O_TRUNC | os.O_NOFOLLOW, + 0o600, + ) + with os.fdopen(descriptor, "w", encoding="utf-8") as handle: + handle.write(rendered) + PY + { + echo "## Hourly coordinator: credential unavailable" + echo "No cross-repository dispatch was attempted. Provision PR_REVIEW_MERGE_TOKEN, then the next hourly pass can resume bounded work." + } >>"$GITHUB_STEP_SUMMARY" + exit 0 fi echo "::add-mask::$GH_TOKEN" test "$(git rev-parse HEAD)" = "${GITHUB_SHA}" diff --git a/CHANGELOG.md b/CHANGELOG.md index fd1aebf43f..ada2da6c03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ Semantic Versioning where the repository publishes a release. ### Changed +- Record a bounded, auditable hourly no-op when the cross-repository maintainer credential is not provisioned, so missing configuration does not erase the receipt or fail the scheduler before the next-action guidance is visible. - Require the hourly repair worker to establish an exact-head root cause, enumerate the smallest remediation candidates, and prove writer authority, sealed-path scope, credentials, dependency order, verifiability, and causal effect before editing; infeasible or external blockers leave the tree unchanged while the broader loop continues with another eligible PR or buyer-visible product gap. - Run the bounded Quarantine Sandbox Runtime heartbeat at minute 14 without granting the caller model secrets, repository mutation permissions, approval, merge, release, artifact-execution, or final security-verdict authority. - Run the bounded Clearfolio PR review-feedback repair caller at minute 23 of every hour while keeping the shared scheduler free of product-specific timers and repository names for modular reuse by naruon, contextual-orchestrator, Inkspan, and other CWL services. diff --git a/docs/doctoring/organization-commercial-readiness-loop.md b/docs/doctoring/organization-commercial-readiness-loop.md index 76ef1fce5a..db4b3307e6 100644 --- a/docs/doctoring/organization-commercial-readiness-loop.md +++ b/docs/doctoring/organization-commercial-readiness-loop.md @@ -10,7 +10,7 @@ The coordinator may dispatch at most one review-repair workflow and one product- A single workflow cannot safely write every repository merely because it runs in the organization `.github` repository. GitHub's default `GITHUB_TOKEN` is scoped to the repository containing the workflow; cross-repository Actions dispatch therefore requires an explicitly provisioned user or GitHub App credential with the required repository and Actions permissions. This control does not make every repository directly writable. It only considers repositories the live API reports as organization-owned, non-fork, enabled, non-archived, default-branch-bearing, and writable by the authenticated installation. -The central job therefore refuses both repository-scoped and reviewer-scoped token fallbacks. It requires the maintainer-scoped `PR_REVIEW_MERGE_TOKEN`; `OPENCODE_APPROVE_TOKEN` remains isolated to the reviewer credential chain and `GITHUB_TOKEN` is not accepted for cross-repository coordination. The maintainer token is exposed only to the final dispatch shell step, not checkout, setup, artifact upload, or other third-party actions. The coordinator itself receives neither `NVIDIA_NIM_API_KEY` nor `COPILOT_GITHUB_TOKEN`. Model credentials remain inside separately reviewed repository-local or central workers. +The central job therefore refuses both repository-scoped and reviewer-scoped token fallbacks. When the maintainer-scoped `PR_REVIEW_MERGE_TOKEN` is absent, the scheduled pass records an explicit `skipped_credential_unavailable` receipt and exits without attempting a dispatch; the next action is to provision that secret. When present, it remains exposed only to the final dispatch shell step. `OPENCODE_APPROVE_TOKEN` remains isolated to the reviewer credential chain and `GITHUB_TOKEN` is not accepted for cross-repository coordination. The coordinator itself receives neither `NVIDIA_NIM_API_KEY` nor `COPILOT_GITHUB_TOKEN`. Model credentials remain inside separately reviewed repository-local or central workers. ## Dynamic repository-writer lease diff --git a/tests/test_organization_commercial_readiness_loop_secret_scope.py b/tests/test_organization_commercial_readiness_loop_secret_scope.py index b47c2cadc2..a1d13b0176 100644 --- a/tests/test_organization_commercial_readiness_loop_secret_scope.py +++ b/tests/test_organization_commercial_readiness_loop_secret_scope.py @@ -19,3 +19,13 @@ def test_maintainer_token_is_scoped_only_to_the_dispatch_step() -> None: assert "PR_REVIEW_MERGE_TOKEN" not in before_dispatch assert "GH_TOKEN:" not in before_dispatch assert "env:\n GH_TOKEN: ${{ secrets.PR_REVIEW_MERGE_TOKEN }}" in dispatch_step + + +def test_missing_maintainer_token_is_an_auditable_noop() -> None: + """Absent cross-repository authority must not create a failing empty receipt.""" + source = WORKFLOW_PATH.read_text(encoding="utf-8") + + assert '"status": "skipped_credential_unavailable"' in source + assert "organization-commercial-readiness-loop.json" in source + assert "Provision PR_REVIEW_MERGE_TOKEN" in source + assert "No cross-repository dispatch was attempted" in source From dbc3eca51444e46ce7a3a07ea818c72ad8bf124a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 20 Aug 2026 22:42:40 +0900 Subject: [PATCH 2/5] test: document coordinator credential scope --- .../test_organization_commercial_readiness_loop_secret_scope.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/test_organization_commercial_readiness_loop_secret_scope.py b/tests/test_organization_commercial_readiness_loop_secret_scope.py index a1d13b0176..de520ab860 100644 --- a/tests/test_organization_commercial_readiness_loop_secret_scope.py +++ b/tests/test_organization_commercial_readiness_loop_secret_scope.py @@ -1,3 +1,5 @@ +"""Verify that the hourly coordinator keeps cross-repository credentials scoped.""" + from pathlib import Path From 0dd3471c61fdba23e7b791bac4014df0975f4b02 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 21 Aug 2026 19:38:13 +0900 Subject: [PATCH 3/5] docs: complete coordinator client docstring --- scripts/ci/organization_commercial_readiness_loop.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/ci/organization_commercial_readiness_loop.py b/scripts/ci/organization_commercial_readiness_loop.py index c00cfa1e0a..2e72f08eb6 100644 --- a/scripts/ci/organization_commercial_readiness_loop.py +++ b/scripts/ci/organization_commercial_readiness_loop.py @@ -239,6 +239,7 @@ class GitHubClient: """Use the GitHub CLI as an authenticated, bounded REST transport.""" def __init__(self, token: str, *, timeout_seconds: int = 60) -> None: + """Initialize the client with the dedicated coordination credential.""" if not token: raise GitHubError("GH_TOKEN is required for organization coordination") self._token = token @@ -853,4 +854,4 @@ def main( if __name__ == "__main__": # pragma: no cover - exercised through main() - raise SystemExit(main()) \ No newline at end of file + raise SystemExit(main()) From 01087080a0926cbb95287b807820a67021af6bcb Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 22 Aug 2026 03:36:14 +0900 Subject: [PATCH 4/5] test(coverage): document commercial readiness fixture initializer --- organization_commercial_readiness_fixtures.py | 1 + 1 file changed, 1 insertion(+) diff --git a/organization_commercial_readiness_fixtures.py b/organization_commercial_readiness_fixtures.py index d865961962..3b903eb977 100644 --- a/organization_commercial_readiness_fixtures.py +++ b/organization_commercial_readiness_fixtures.py @@ -90,6 +90,7 @@ def __init__( repositories: list[dict[str, Any]], snapshots: dict[str, list[RepositorySnapshot | Exception]], ) -> None: + """Configure deterministic repository snapshots and dispatch records.""" self.repositories = repositories self.snapshots = snapshots self.dispatched_repairs: list[tuple[str, str]] = [] From 93eed1bb752492c0fdc1f5900d70ca479a7a7e1a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 22 Aug 2026 04:06:19 +0900 Subject: [PATCH 5/5] test: align scheduler contract and audit runtime --- requirements-pip-audit-ci-hashes.txt | 6 +++--- scripts/ci/test_strix_quick_gate.sh | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/requirements-pip-audit-ci-hashes.txt b/requirements-pip-audit-ci-hashes.txt index ade197a49a..0ae099d8fe 100644 --- a/requirements-pip-audit-ci-hashes.txt +++ b/requirements-pip-audit-ci-hashes.txt @@ -213,9 +213,9 @@ packaging==26.2 \ # via # pip-audit # pip-requirements-parser -pip==26.1.2 \ - --hash=sha256:382ff9f685ee3bc25864f820aa50505825f10f5458ffff07e30a6d96e5715cab \ - --hash=sha256:f49cd134c61cf2fd75e0ce2676db03e4054504a5a4986d00f8299ae632dc4605 +pip==26.2.1 \ + --hash=sha256:71138adf1f4ca900cdb7d289c21b7494329f2332b6d85f0e1c42108c0384ed3e \ + --hash=sha256:f6ad667e89a1fe78046c8f13232b247200f5258d7828f3f7883d660878e0813f # via pip-api pip-api==0.0.34 \ --hash=sha256:8b2d7d7c37f2447373aa2cf8b1f60a2f2b27a84e1e9e0294a3f6ef10eb3ba6bb \ diff --git a/scripts/ci/test_strix_quick_gate.sh b/scripts/ci/test_strix_quick_gate.sh index ac9ce1d8bd..04f58bf316 100755 --- a/scripts/ci/test_strix_quick_gate.sh +++ b/scripts/ci/test_strix_quick_gate.sh @@ -1506,8 +1506,8 @@ assert_pr_review_merge_scheduler_uses_github_actions_bot_token() { assert_file_contains "$workflow_file" "github.event_name == 'pull_request_target' && format('pr-{0}', github.event.pull_request.number)" "scheduler scopes pull_request_target concurrency to the active PR" assert_file_contains "$workflow_file" "github.event_name == 'workflow_run' && github.event.workflow_run.pull_requests[0].number && format('pr-{0}', github.event.workflow_run.pull_requests[0].number)" "scheduler scopes workflow_run concurrency to the completed review PR" assert_file_contains "$workflow_file" "github.event_name == 'schedule' && format('schedule-{0}', github.event.schedule)" "scheduler isolates the 15-minute organization sweep from the separate 30-minute scheduled scan" - assert_file_contains "$workflow_file" "github.event_name == 'repository_dispatch' && github.run_id" "scheduler keeps manual queue scans isolated per run" - assert_file_contains "$workflow_file" "cancel-in-progress: \${{ github.event_name == 'pull_request_target' || github.event_name == 'pull_request_review' || github.event_name == 'repository_dispatch' }}" "scheduler cancels stale PR/review/manual queue scans instead of accumulating merge/update attempts" + assert_file_contains "$workflow_file" "github.event_name == 'repository_dispatch' && format('repo-dispatch-{0}', github.repository)" "scheduler keeps manual queue scans isolated per repository dispatch target" + assert_file_contains "$workflow_file" "cancel-in-progress: \${{ github.event_name == 'pull_request_target' || github.event_name == 'pull_request_review' || github.event_name == 'repository_dispatch' || (github.event_name == 'workflow_run' && !github.event.workflow_run.pull_requests[0].number) }}" "scheduler cancels stale PR/review/manual queue scans instead of accumulating merge/update attempts" assert_file_contains "$workflow_file" "timeout-minutes: 60" "organization sweep has enough headroom to finish the complete repository walk" assert_file_contains "$workflow_file" "ORG_SWEEP_TRIGGER_REVIEWS: \${{ github.event_name == 'schedule' ||" "scheduled organization sweeps retry missing current-head OpenCode reviews" assert_file_contains "$workflow_file" "ORG_SWEEP_ENABLE_AUTO_MERGE: \${{ github.event_name == 'schedule' ||" "scheduled organization sweeps merge approved current heads"