diff --git a/.github/workflows/branch-patch-four-pillars-opencode-target.yml b/.github/workflows/branch-patch-four-pillars-opencode-target.yml new file mode 100644 index 000000000..70ba9b86c --- /dev/null +++ b/.github/workflows/branch-patch-four-pillars-opencode-target.yml @@ -0,0 +1,109 @@ +name: Branch Patch Four Pillars OpenCode Target + +on: + push: + branches: + - fix/four-pillars-opencode-target + paths: + - .github/workflows/branch-patch-four-pillars-opencode-target.yml + - .github/workflows/opencode-review-dispatch.yml + - tests/test_four_pillars_opencode_enrollment.py + +concurrency: + group: branch-patch-four-pillars-opencode-target + cancel-in-progress: true + +permissions: + contents: write + +jobs: + verify-red: + name: verify-red + runs-on: macos-latest + steps: + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 + with: + ref: fix/four-pillars-opencode-target + - name: Require the focused enrollment contract to fail before implementation + run: | + python3 - <<'PY' + import runpy + + namespace = runpy.run_path("tests/test_four_pillars_opencode_enrollment.py") + test = namespace[ + "test_four_pillars_is_explicitly_enrolled_without_replacing_dynamic_targets" + ] + try: + test() + except AssertionError: + print("Observed expected RED: Four Pillars is absent from the dispatcher allowlist.") + else: + raise SystemExit("Focused enrollment contract unexpectedly passed before patching.") + PY + + patch-workflow: + name: patch-workflow + needs: verify-red + runs-on: macos-latest + steps: + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 + with: + ref: fix/four-pillars-opencode-target + fetch-depth: 0 + - name: Append the exact Four Pillars target and document the enrollment + run: | + python3 - <<'PY' + from pathlib import Path + + workflow = Path(".github/workflows/opencode-review-dispatch.yml") + source = workflow.read_text(encoding="utf-8") + expression_open = chr(36) + "{{ " + old = ( + " ALLOWED_DISPATCH_TARGETS: " + + expression_open + + "vars.OPENCODE_REPOSITORY_DISPATCH_TARGETS }}" + ) + new = ( + " ALLOWED_DISPATCH_TARGETS: " + + expression_open + + "format('{0},ContextualWisdomLab/four-pillars', " + + "vars.OPENCODE_REPOSITORY_DISPATCH_TARGETS) }}" + ) + if new not in source: + if source.count(old) != 1: + raise SystemExit("Expected exactly one dispatcher allowlist expression.") + workflow.write_text(source.replace(old, new), encoding="utf-8") + + documentation = Path("docs/org-required-workflow-rollout.md") + text = documentation.read_text(encoding="utf-8") + marker = "## Explicit OpenCode dispatch enrollments" + section_lines = [ + "", + "", + marker, + "", + "The privileged dispatcher preserves the configurable exact-repository list in", + "`OPENCODE_REPOSITORY_DISPATCH_TARGETS` and also explicitly enrolls", + "`ContextualWisdomLab/four-pillars`. This repository ships the standalone Four", + "Pillars service and consumes the same central current-head OpenCode, independent", + "Noema, and guarded merge chain as organization modules. Enrollment remains an", + "exact `owner/name` match; no organization wildcard or fork authorization is", + "introduced.", + "", + ] + if marker not in text: + documentation.write_text( + text.rstrip() + "\n".join(section_lines), + encoding="utf-8", + ) + PY + - name: Remove the one-use branch patch workflow + run: git rm .github/workflows/branch-patch-four-pillars-opencode-target.yml + - name: Commit the least-privilege dispatcher update + run: | + git diff --check + git config user.name github-actions[bot] + git config user.email 41898282+github-actions[bot]@users.noreply.github.com + git add .github/workflows/opencode-review-dispatch.yml docs/org-required-workflow-rollout.md + git commit -m "fix: enroll Four Pillars in OpenCode dispatch" + git push origin HEAD:fix/four-pillars-opencode-target diff --git a/docs/superpowers/plans/2026-08-04-four-pillars-opencode-enrollment.md b/docs/superpowers/plans/2026-08-04-four-pillars-opencode-enrollment.md new file mode 100644 index 000000000..ca832f1a5 --- /dev/null +++ b/docs/superpowers/plans/2026-08-04-four-pillars-opencode-enrollment.md @@ -0,0 +1,35 @@ +# Four Pillars OpenCode Enrollment Implementation Plan + +**Goal:** Enroll `ContextualWisdomLab/four-pillars` in the central privileged OpenCode review dispatcher without weakening the exact-repository allowlist or changing the review/merge trust boundary. + +**Architecture:** Keep the organization variable `OPENCODE_REPOSITORY_DISPATCH_TARGETS` as the primary configurable allowlist and append the Four Pillars repository as one explicit exact target at expression-evaluation time. Preserve live PR metadata binding, actor/sender verification, exact string comparison, current-head review publication, independent Noema approval, and guarded merge behavior. + +**Tech stack:** GitHub Actions, Bash, Python contract tests, pytest, organization required workflows. + +## Constraints + +- No wildcard or organization-wide target authorization. +- No pull-request code execution with privileged review credentials. +- No new repository or organization secret. +- The existing configurable allowlist remains active. +- The target repository is compared by exact `owner/name` equality after whitespace normalization. +- Central workflow, documentation, and contract tests must agree. + +## Task 1: Lock the failing enrollment contract + +- Add a focused test requiring the dispatcher to preserve `vars.OPENCODE_REPOSITORY_DISPATCH_TARGETS` and explicitly include `ContextualWisdomLab/four-pillars`. +- Require the existing exact-match loop and rejection path. +- Verify the test fails on the unmodified workflow because the repository is not yet enrolled. + +## Task 2: Apply the least-privilege workflow change + +- Change only the `ALLOWED_DISPATCH_TARGETS` environment expression so it evaluates to the current organization-variable list plus the explicit Four Pillars repository. +- Do not change the actor gate, metadata gate, target regex, exact equality comparison, token exchange, review publication, or merge scheduler. +- Update the rollout documentation with the explicit enrollment and operational reason. + +## Task 3: Verify and merge + +- Run all central tests, shell/YAML contract checks, public docstring checks, and coverage gates. +- Review the complete diff and resolve every current-head finding. +- Merge only after all required reviews and checks pass. +- Confirm the next scheduler pass dispatches the actual OpenCode reviewer for Four Pillars PR #18, followed by independent Noema review and guarded exact-head merge. \ No newline at end of file diff --git a/tests/test_four_pillars_opencode_enrollment.py b/tests/test_four_pillars_opencode_enrollment.py new file mode 100644 index 000000000..64c46f9db --- /dev/null +++ b/tests/test_four_pillars_opencode_enrollment.py @@ -0,0 +1,31 @@ +"""Lock the exact-repository OpenCode enrollment for Four Pillars.""" + +from pathlib import Path + +WORKFLOW_PATH = Path(".github/workflows/opencode-review-dispatch.yml") +TARGET_REPOSITORY = "ContextualWisdomLab/four-pillars" + + +def _workflow_text() -> str: + """Return the privileged dispatcher source as UTF-8 text.""" + return WORKFLOW_PATH.read_text(encoding="utf-8") + + +def test_four_pillars_is_explicitly_enrolled_without_replacing_dynamic_targets() -> None: + """Keep the configurable allowlist and add Four Pillars as one exact target.""" + workflow = _workflow_text() + + assert "vars.OPENCODE_REPOSITORY_DISPATCH_TARGETS" in workflow + assert TARGET_REPOSITORY in workflow + assert "ALLOWED_DISPATCH_TARGETS:" in workflow + + +def test_dispatcher_retains_exact_match_and_fail_closed_target_validation() -> None: + """Reject every repository absent from the comma-delimited exact allowlist.""" + workflow = _workflow_text() + + assert 'IFS=\',\' read -r -a allowed_dispatch_targets' in workflow + assert '[ "$TARGET_REPOSITORY" = "$allowed_target" ]' in workflow + assert 'if [ "$target_allowed" -ne 1 ]; then' in workflow + assert "absent from the configured exact repository allowlist" in workflow + assert "ContextualWisdomLab/*" not in workflow