Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 93 additions & 0 deletions .github/workflows/apply-contextual-orchestrator-policy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
name: Apply contextual-orchestrator adaptive-default governance

on:
push:
branches:
- agent/contextual-orchestrator-adaptive-policy
paths:
- scripts/ci/stage_contextual_orchestrator_policy_test.py
- scripts/ci/apply_contextual_orchestrator_policy.py
- .github/workflows/apply-contextual-orchestrator-policy.yml

permissions:
contents: write

concurrency:
group: apply-contextual-orchestrator-policy-${{ github.ref }}
cancel-in-progress: false

jobs:
red-green-verify:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout exact branch head
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # actions/checkout@v4
with:
fetch-depth: 0
persist-credentials: true

- name: Set up Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # actions/setup-python@v6
with:
python-version: "3.12"

- name: Stage scanner unit tests before implementation
run: python scripts/ci/stage_contextual_orchestrator_policy_test.py

- name: Prove tests are red while the scanner is missing
shell: bash
run: |
set -euo pipefail
set +e
python -m unittest tests.ci.test_contextual_orchestrator_defaults > /tmp/policy-red.log 2>&1
status=$?
set -e
cat /tmp/policy-red.log
test "$status" -ne 0

- name: Apply scanner, reusable workflow, and ADR
run: python scripts/ci/apply_contextual_orchestrator_policy.py

- name: Pin upload-artifact in the reusable workflow
shell: bash
run: |
python - <<'PY'
from pathlib import Path
path = Path('.github/workflows/contextual-orchestrator-policy.yml')
text = path.read_text(encoding='utf-8')
text = text.replace(
'uses: actions/upload-artifact@v4',
'uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # actions/upload-artifact@v4',
)
path.write_text(text, encoding='utf-8')
PY

- name: Prove scanner tests are green
run: python -m unittest tests.ci.test_contextual_orchestrator_defaults

- name: Run all organization Python tests
run: python -m unittest discover -s tests -p 'test_*.py'

- name: Verify syntax and patch integrity
shell: bash
run: |
python -m compileall -q scripts tests
python scripts/ci/check_contextual_orchestrator_defaults.py .
git diff --check

- name: Publish the verified source commit
env:
TARGET_BRANCH: agent/contextual-orchestrator-adaptive-policy
shell: bash
run: |
set -euo pipefail
rm scripts/ci/stage_contextual_orchestrator_policy_test.py
rm scripts/ci/apply_contextual_orchestrator_policy.py
rm .github/workflows/apply-contextual-orchestrator-policy.yml
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add --all
git diff --cached --check
git commit -m "feat(governance): enforce adaptive orchestration defaults"
git push origin "HEAD:${TARGET_BRANCH}"
266 changes: 266 additions & 0 deletions scripts/ci/apply_contextual_orchestrator_policy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,266 @@
#!/usr/bin/env python3
"""Install the organization adaptive-orchestration policy scanner and workflow."""

from __future__ import annotations

from pathlib import Path

ROOT = Path(__file__).resolve().parents[2]
SCANNER_PATH = ROOT / "scripts" / "ci" / "check_contextual_orchestrator_defaults.py"
WORKFLOW_PATH = ROOT / ".github" / "workflows" / "contextual-orchestrator-policy.yml"
ADR_PATH = ROOT / "docs" / "adr" / "0012-adaptive-orchestration-default-governance.md"

SCANNER_PATH.write_text(
'''#!/usr/bin/env python3
"""Fail closed when a production consumer forces or omits orchestration policy."""

from __future__ import annotations

import argparse
import fnmatch
import json
import re
from dataclasses import dataclass
from pathlib import Path
from typing import Iterable

SOURCE_SUFFIXES = frozenset(
{".py", ".js", ".mjs", ".cjs", ".ts", ".tsx", ".rs", ".go", ".java", ".kt", ".cs"}
)
EXCLUDED_PARTS = frozenset(
{
".git",
".github",
"build",
"dist",
"docs",
"examples",
"fixtures",
"migrations",
"node_modules",
"scripts",
"spec",
"specs",
"target",
"test",
"tests",
"vendor",
}
)
ORCHESTRATOR_MARKERS = ("contextual-orchestrator", "contextual_orchestrator")
CHAT_ENDPOINT_MARKERS = ("/v1/chat/completions", "/chat/completions", "chat/completions")
FORCED_ROUTE_PATTERN = re.compile(
r"(?:orchestration_mode|mode)(?:\s*:\s*str)?\s*[:=]\s*[\"']route[\"']",
re.IGNORECASE,
)
AUTO_PATTERN = re.compile(
r"(?:orchestration_mode|mode)(?:\s*:\s*str)?\s*[:=]\s*[\"']auto[\"']",
re.IGNORECASE,
)


@dataclass(frozen=True)
class Finding:
"""One source-backed policy violation."""

finding_code: str
source_path: str
message: str

def as_dict(self) -> dict[str, str]:
"""Return the stable JSON representation."""
return {
"finding_code": self.finding_code,
"source_path": self.source_path,
"message": self.message,
}


def _load_policy(root: Path) -> dict[str, list[str]]:
path = root / ".cwl" / "contextual_orchestrator_policy.json"
if not path.exists():
return {"allowed_fixed_mode_paths": [], "request_constructor_exemptions": []}
value = json.loads(path.read_text(encoding="utf-8"))
if not isinstance(value, dict):
raise ValueError("contextual_orchestrator_policy.json must contain an object")
policy: dict[str, list[str]] = {}
for key in ("allowed_fixed_mode_paths", "request_constructor_exemptions"):
entries = value.get(key, [])
if not isinstance(entries, list) or any(not isinstance(item, str) for item in entries):
raise ValueError(f"{key} must be an array of path globs")
policy[key] = entries
return policy


def _matches(path: str, patterns: Iterable[str]) -> bool:
return any(fnmatch.fnmatch(path, pattern) for pattern in patterns)


def _production_sources(root: Path) -> Iterable[Path]:
for path in sorted(root.rglob("*")):
if not path.is_file() or path.suffix.lower() not in SOURCE_SUFFIXES:
continue
relative = path.relative_to(root)
lowered_parts = {part.lower() for part in relative.parts}
if lowered_parts & EXCLUDED_PARTS:
continue
yield path


def inspect_repository(root: Path) -> list[Finding]:
"""Return every forced-route or implicit-mode production violation."""
policy = _load_policy(root)
findings: list[Finding] = []
for path in _production_sources(root):
relative = path.relative_to(root).as_posix()
text = path.read_text(encoding="utf-8", errors="strict")
lowered = text.lower()
if not any(marker in lowered for marker in ORCHESTRATOR_MARKERS):
continue
fixed_allowed = _matches(relative, policy["allowed_fixed_mode_paths"])
constructor_exempt = _matches(
relative, policy["request_constructor_exemptions"]
)
if FORCED_ROUTE_PATTERN.search(text) and not fixed_allowed:
findings.append(
Finding(
"forced_single_route",
relative,
"production contextual-orchestrator code forces route instead of delegating to auto",
)
)
constructs_chat_request = any(marker in lowered for marker in CHAT_ENDPOINT_MARKERS)
names_gateway_model = "contextual-orchestrator" in lowered
if (
constructs_chat_request
and names_gateway_model
and not AUTO_PATTERN.search(text)
and not constructor_exempt
and not fixed_allowed
):
findings.append(
Finding(
"implicit_orchestration_mode",
relative,
"production chat request must explicitly select contextual-orchestrator auto",
)
)
return findings


def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("repository_root", nargs="?", default=".")
parser.add_argument("--json-output")
args = parser.parse_args()
root = Path(args.repository_root).resolve()
findings = inspect_repository(root)
payload = {
"policy_name": "contextual_orchestrator_adaptive_default",
"repository_root": str(root),
"finding_count": len(findings),
"findings": [finding.as_dict() for finding in findings],
}
rendered = json.dumps(payload, ensure_ascii=False, indent=2, sort_keys=True)
print(rendered)
if args.json_output:
Path(args.json_output).write_text(rendered + "\n", encoding="utf-8")
return 1 if findings else 0


if __name__ == "__main__":
raise SystemExit(main())
''',
encoding="utf-8",
)

WORKFLOW_PATH.parent.mkdir(parents=True, exist_ok=True)
WORKFLOW_PATH.write_text(
'''name: Contextual Orchestrator Adaptive Default

on:
workflow_call:

permissions:
contents: read

jobs:
adaptive-default-policy:
name: contextual-orchestrator adaptive default
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout consumer repository exact ref
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # actions/checkout@v4
with:
path: consumer
persist-credentials: false

- name: Checkout central governance scanner
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # actions/checkout@v4
with:
repository: ContextualWisdomLab/.github
ref: main
path: governance
persist-credentials: false

- name: Enforce explicit adaptive orchestration defaults
run: >-
python governance/scripts/ci/check_contextual_orchestrator_defaults.py
consumer
--json-output contextual-orchestrator-policy.json

- name: Upload bounded policy evidence
if: always()
uses: actions/upload-artifact@v4
with:
name: contextual-orchestrator-policy-${{ github.sha }}
path: contextual-orchestrator-policy.json
if-no-files-found: ignore
retention-days: 14
''',
encoding="utf-8",
)

ADR_PATH.parent.mkdir(parents=True, exist_ok=True)
ADR_PATH.write_text(
'''# ADR-0012: Organization governance requires explicit adaptive orchestration defaults

- Status: Accepted
- Date: 2026-08-16

## Context

Consumer repositories can unintentionally bypass contextual-orchestrator by
hard-coding `route`, omitting the mode at a request constructor, or copying a direct
provider model. This makes quality/cost policy drift invisible and forces each product
to rediscover the same control. Controlled live-conformance and ablation fixtures
still need explicit fixed modes.

## Decision

The central `.github` repository provides a reusable fail-closed workflow and scanner.
Production source that constructs a contextual-orchestrator chat request must
explicitly select `auto`; a fixed `route` is rejected. Tests, documentation, examples,
and fixtures are excluded. A repository may declare narrow path-glob exceptions in
`.cwl/contextual_orchestrator_policy.json` for controlled ablation or a request
constructor whose mode is injected by a separately tested wrapper.

`auto` means quality and safety requirements are satisfied first; known cost is used
only among capability-equivalent choices, and unpriced models are not treated as
free. The gateway remains responsible for route/verify/conduct selection.

## Consequences

The guard prevents future regressions after consumer migration without forcing all
work through an expensive workflow. It does not certify semantic quality, provider
pricing, or production SLOs; those require measured evaluation and telemetry.

## References

Omidvar, H., & Akhlaghi, V. (2026). *A communication-theoretic framework for LLM agents: Cost-aware adaptive reliability* [Preprint]. arXiv. https://doi.org/10.48550/arXiv.2605.09121

Tang, Y., Cetin, E., Xu, J., Sun, Q., Nielsen, S., Richard, V., Goda, H., Tymchenko, I., Nguyen, N., Lee, H., Ashiga, M., Kotyan, S., Kuroki, S., & Clanuwat, T. (2026). *Sakana Fugu technical report* [Technical report]. arXiv. https://doi.org/10.48550/arXiv.2606.21228
''',
encoding="utf-8",
)
Loading
Loading