From e19833a0f8457719f2ea63b8ba5e8eff13dce7e3 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 21 Aug 2026 05:02:25 +0900 Subject: [PATCH 1/4] chore: schedule contextual orchestrator review repair --- ...tual-orchestrator-hourly-review-repair.yml | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 .github/workflows/contextual-orchestrator-hourly-review-repair.yml diff --git a/.github/workflows/contextual-orchestrator-hourly-review-repair.yml b/.github/workflows/contextual-orchestrator-hourly-review-repair.yml new file mode 100644 index 000000000..d7575ee5a --- /dev/null +++ b/.github/workflows/contextual-orchestrator-hourly-review-repair.yml @@ -0,0 +1,31 @@ +name: Contextual Orchestrator Hourly Review Repair + +on: + schedule: + # Minute 17 is reserved for this gateway repository in the CWL hourly loop. + - cron: "17 * * * *" + +concurrency: + group: contextual-orchestrator-hourly-review-repair + # A complete exact-head review can exceed one hour; keep it alive for the next heartbeat. + cancel-in-progress: false + +permissions: + contents: read + +jobs: + dispatch-review-repair: + permissions: + contents: read + id-token: write + uses: ./.github/workflows/pr-review-fix-scheduler.yml + with: + target_repository: ContextualWisdomLab/contextual-orchestrator + base_branch: main + max_prs: "50" + max_dispatches: "1" + resolve_unreviewed_conflicts: true + retry_hours: "2" + secrets: + PR_REVIEW_MERGE_TOKEN: ${{ secrets.PR_REVIEW_MERGE_TOKEN }} + OPENCODE_APPROVE_TOKEN: ${{ secrets.OPENCODE_APPROVE_TOKEN }} From 7bcd7dcf639be74c7687b363111af9a36a3a7aff Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 21 Aug 2026 05:09:34 +0900 Subject: [PATCH 2/4] test: cover contextual orchestrator hourly caller --- .../hourly-nvidia-nim-review-repair.yml | 7 ++ ...xtual-orchestrator-hourly-review-caller.md | 60 +++++++++++++ ...xtual_orchestrator_hourly_review_caller.py | 85 +++++++++++++++++++ 3 files changed, 152 insertions(+) create mode 100644 docs/doctoring/contextual-orchestrator-hourly-review-caller.md create mode 100644 tests/test_contextual_orchestrator_hourly_review_caller.py diff --git a/.github/workflows/hourly-nvidia-nim-review-repair.yml b/.github/workflows/hourly-nvidia-nim-review-repair.yml index 702942708..a2b96b7f6 100644 --- a/.github/workflows/hourly-nvidia-nim-review-repair.yml +++ b/.github/workflows/hourly-nvidia-nim-review-repair.yml @@ -8,6 +8,7 @@ on: - .github/workflows/pr-review-autofix.yml - .github/workflows/bandscope-hourly-review-repair.yml - .github/workflows/clearfolio-hourly-review-repair.yml + - .github/workflows/contextual-orchestrator-hourly-review-repair.yml - .github/workflows/disksage-hourly-review-repair.yml - .github/workflows/fast-mlsirm-hourly-review-repair.yml - .github/workflows/github-hourly-review-repair.yml @@ -19,6 +20,7 @@ on: - scripts/ci/pr_review_conflict_scope.py - scripts/ci/pr_review_autofix_context.py - tests/test_bandscope_hourly_review_caller.py + - tests/test_contextual_orchestrator_hourly_review_caller.py - tests/test_disksage_hourly_review_caller.py - tests/test_fast_mlsirm_hourly_review_caller.py - tests/test_github_hourly_conflict_repair.py @@ -42,6 +44,7 @@ on: - docs/automation/hourly-review-repair.md - docs/doctoring/bandscope-hourly-review-caller.md - docs/doctoring/clearfolio-hourly-review-caller.md + - docs/doctoring/contextual-orchestrator-hourly-review-caller.md - docs/doctoring/conflict-control-evidence-isolation.md - docs/doctoring/disksage-hourly-review-caller.md - docs/doctoring/fast-mlsirm-hourly-review-caller.md @@ -58,6 +61,7 @@ on: - .github/workflows/pr-review-autofix.yml - .github/workflows/bandscope-hourly-review-repair.yml - .github/workflows/clearfolio-hourly-review-repair.yml + - .github/workflows/contextual-orchestrator-hourly-review-repair.yml - .github/workflows/disksage-hourly-review-repair.yml - .github/workflows/fast-mlsirm-hourly-review-repair.yml - .github/workflows/github-hourly-review-repair.yml @@ -69,6 +73,7 @@ on: - scripts/ci/pr_review_conflict_scope.py - scripts/ci/pr_review_autofix_context.py - tests/test_bandscope_hourly_review_caller.py + - tests/test_contextual_orchestrator_hourly_review_caller.py - tests/test_disksage_hourly_review_caller.py - tests/test_fast_mlsirm_hourly_review_caller.py - tests/test_github_hourly_conflict_repair.py @@ -92,6 +97,7 @@ on: - docs/automation/hourly-review-repair.md - docs/doctoring/bandscope-hourly-review-caller.md - docs/doctoring/clearfolio-hourly-review-caller.md + - docs/doctoring/contextual-orchestrator-hourly-review-caller.md - docs/doctoring/conflict-control-evidence-isolation.md - docs/doctoring/disksage-hourly-review-caller.md - docs/doctoring/fast-mlsirm-hourly-review-caller.md @@ -149,6 +155,7 @@ jobs: scripts/ci/pr_review_autofix_context.py \ tests/test_pr_review_conflict_scope.py \ tests/test_bandscope_hourly_review_caller.py \ + tests/test_contextual_orchestrator_hourly_review_caller.py \ tests/test_disksage_hourly_review_caller.py \ tests/test_fast_mlsirm_hourly_review_caller.py \ tests/test_github_hourly_conflict_repair.py \ diff --git a/docs/doctoring/contextual-orchestrator-hourly-review-caller.md b/docs/doctoring/contextual-orchestrator-hourly-review-caller.md new file mode 100644 index 000000000..a8748a156 --- /dev/null +++ b/docs/doctoring/contextual-orchestrator-hourly-review-caller.md @@ -0,0 +1,60 @@ +# Contextual Orchestrator Hourly Review-Repair Caller + +## Customer action + +Keep `ContextualWisdomLab/contextual-orchestrator` on the protected `main` +branch, then confirm the central autofix gateway contract in +`ContextualWisdomLab/.github#1168` is merged before enabling this scheduled +caller. After the caller runs, inspect the target PR's exact-head review, +Checks, and independent approval; merge only through the protected normal path. + +## Runtime boundary + +The workflow runs at minute 17 of every hour and calls the central +`pr-review-fix-scheduler.yml` reusable workflow. It scans at most 50 open PRs, +dispatches one bounded repair, permits unresolved conflict repair, and waits +two hours before retrying the same head. Non-cancelling concurrency preserves a +long-running exact-head OpenCode, Noema, or security operation. + +The caller grants read-only contents access and OIDC token exchange only. It +forwards the established `PR_REVIEW_MERGE_TOKEN` and +`OPENCODE_APPROVE_TOKEN` paths explicitly; it does not inherit all secrets and +does not receive `NVIDIA_NIM_API_KEY` or `COPILOT_GITHUB_TOKEN`. The central +target allowlist must include `ContextualWisdomLab/contextual-orchestrator` in +`OPENCODE_REPOSITORY_DISPATCH_TARGETS`. + +## Gateway dependency and evidence + +The reusable scheduler dispatches the default-branch central autofix workflow. +Merge `ContextualWisdomLab/.github#1168` first so that this caller's write path +uses the contextual-orchestrator gateway's automatic model discovery and +bounded OpenCode tool loop. The worker must keep provider credentials in the +gateway KV boundary and must fail closed when gateway configuration is absent. + +Every dispatched repair is diagnostic until the target PR's live head is +revalidated. A changed head invalidates earlier review and Checks evidence. +Queued, cancelled, unavailable, or synthetic evidence never authorizes a +merge. A customer should open the target PR, resolve actionable review threads, +wait for terminal required Checks, obtain an independent review and non-author approval, +and then use the repository's protected merge control. + +## Verification + +Run the caller contract test and `actionlint` against the exact commit before +changing the target allowlist or credential bindings: + +```text +python3 -m pytest -q tests/test_contextual_orchestrator_hourly_review_caller.py +actionlint .github/workflows/contextual-orchestrator-hourly-review-repair.yml +``` + +## APA 7th references + +GitHub. (n.d.). *Events that trigger workflows*. Retrieved August 21, 2026, +from https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows + +GitHub. (n.d.). *Reuse workflows*. Retrieved August 21, 2026, from +https://docs.github.com/en/actions/how-tos/reuse-automations/reuse-workflows + +OpenCode. (n.d.). *Permissions*. Retrieved August 21, 2026, from +https://opencode.ai/docs/permissions diff --git a/tests/test_contextual_orchestrator_hourly_review_caller.py b/tests/test_contextual_orchestrator_hourly_review_caller.py new file mode 100644 index 000000000..fddec5d9c --- /dev/null +++ b/tests/test_contextual_orchestrator_hourly_review_caller.py @@ -0,0 +1,85 @@ +"""Contract tests for the contextual-orchestrator hourly repair caller.""" + +from pathlib import Path + + +CALLER = Path( + ".github/workflows/contextual-orchestrator-hourly-review-repair.yml" +) +DOCTORING = Path( + "docs/doctoring/contextual-orchestrator-hourly-review-caller.md" +) +QUALITY_WORKFLOW = Path(".github/workflows/hourly-nvidia-nim-review-repair.yml") +CONTRACT = Path("tests/test_contextual_orchestrator_hourly_review_caller.py") + + +def _read(path: Path) -> str: + """Return one required contract file as UTF-8 text.""" + assert path.is_file(), f"missing required contract file: {path}" + return path.read_text(encoding="utf-8") + + +def test_caller_is_hourly_bounded_and_non_cancelling() -> None: + """Give the target repository one bounded repair scan per hour.""" + caller = _read(CALLER) + + assert 'cron: "17 * * * *"' in caller + assert "group: contextual-orchestrator-hourly-review-repair" in caller + assert "cancel-in-progress: false" in caller + assert "uses: ./.github/workflows/pr-review-fix-scheduler.yml" in caller + assert "target_repository: ContextualWisdomLab/contextual-orchestrator" in caller + assert "base_branch: main" in caller + assert 'max_prs: "50"' in caller + assert 'max_dispatches: "1"' in caller + assert "resolve_unreviewed_conflicts: true" in caller + assert 'retry_hours: "2"' in caller + + +def test_caller_preserves_oidc_and_explicit_scheduler_secret_scope() -> None: + """Forward only established scheduler credentials to the reusable workflow.""" + caller = _read(CALLER) + workflow_scope, jobs_scope = caller.split("\njobs:\n", maxsplit=1) + + assert "\npermissions:\n contents: read\n" in workflow_scope + assert "\n permissions:\n contents: read\n id-token: write\n" in jobs_scope + assert "PR_REVIEW_MERGE_TOKEN: ${{ secrets.PR_REVIEW_MERGE_TOKEN }}" in caller + assert "OPENCODE_APPROVE_TOKEN: ${{ secrets.OPENCODE_APPROVE_TOKEN }}" in caller + assert "secrets: inherit" not in caller + assert "NVIDIA_NIM_API_KEY" not in caller + assert "COPILOT_GITHUB_TOKEN" not in caller + for forbidden in ( + "actions: write", + "contents: write", + "issues: write", + "pull-requests: write", + "statuses: write", + ): + assert forbidden not in caller + + +def test_doctoring_records_gateway_dependency_and_customer_next_action() -> None: + """Tell operators which gateway PR must land before this caller is enabled.""" + doctoring = _read(DOCTORING) + + for phrase in ( + "ContextualWisdomLab/contextual-orchestrator", + "#1168", + "contextual-orchestrator gateway", + "exact-head", + "independent review", + "OPENCODE_REPOSITORY_DISPATCH_TARGETS", + "PR_REVIEW_MERGE_TOKEN", + "OPENCODE_APPROVE_TOKEN", + "NVIDIA_NIM_API_KEY", + "COPILOT_GITHUB_TOKEN", + "APA 7th references", + ): + assert phrase in doctoring + + +def test_quality_workflow_tracks_caller_test_and_doctoring() -> None: + """Run the focused quality gate when any caller contract changes.""" + quality = _read(QUALITY_WORKFLOW) + for path in (CALLER, DOCTORING, CONTRACT): + assert quality.count(str(path)) >= 2 + assert str(CONTRACT) in quality[quality.index("python -m compileall"):] From 4601c545407df0edb1831ea048bac0acbb97cb60 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 21 Aug 2026 16:54:12 +0900 Subject: [PATCH 3/4] docs: complete commercial readiness 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 c00cfa1e0..b03cac15f 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: + """Configure the client with an explicit review-control 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 bdec3132d8a6febca26f1553e6c91b79d0c2bccf Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 21 Aug 2026 17:18:32 +0900 Subject: [PATCH 4/4] docs: clarify hourly scheduler slot sharing --- .../workflows/contextual-orchestrator-hourly-review-repair.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/contextual-orchestrator-hourly-review-repair.yml b/.github/workflows/contextual-orchestrator-hourly-review-repair.yml index d7575ee5a..3c1bcbb91 100644 --- a/.github/workflows/contextual-orchestrator-hourly-review-repair.yml +++ b/.github/workflows/contextual-orchestrator-hourly-review-repair.yml @@ -2,7 +2,8 @@ name: Contextual Orchestrator Hourly Review Repair on: schedule: - # Minute 17 is reserved for this gateway repository in the CWL hourly loop. + # Run at minute 17 each hour; the slot is shared with the three-hourly + # pr-auto-rebase workflow, so both workflows use independent concurrency groups. - cron: "17 * * * *" concurrency: