diff --git a/.github/workflows/koru-code-review.yml b/.github/workflows/koru-code-review.yml new file mode 100644 index 0000000..cfe9b28 --- /dev/null +++ b/.github/workflows/koru-code-review.yml @@ -0,0 +1,210 @@ +name: koru-code-review + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + workflow_dispatch: + inputs: + base_sha: + description: Exact base commit to compare + required: true + type: string + head_sha: + description: Exact head commit to review + required: true + type: string + +permissions: + contents: read + id-token: write + attestations: write + +concurrency: + group: koru-code-review-${{ github.event.pull_request.number || github.run_id }} + cancel-in-progress: true + +jobs: + review: + name: koru / code-review + if: github.event_name == 'workflow_dispatch' || github.event.pull_request.draft == false + runs-on: ubuntu-latest + timeout-minutes: 20 + env: + KORU_VERSION: '0.1.444' + VALLM_VERSION: '0.1.94' + REVIEW_MODEL: openrouter/deepseek/deepseek-v4-pro + OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} + BASE_SHA: ${{ inputs.base_sha || github.event.pull_request.base.sha }} + HEAD_SHA: ${{ inputs.head_sha || github.event.pull_request.head.sha }} + steps: + - name: Check out the exact reviewed commit + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + fetch-depth: 0 + ref: ${{ env.HEAD_SHA }} + + - name: Set up Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 + with: + python-version: '3.12' + + - name: Install pinned review tools + shell: bash + run: | + set -euo pipefail + python -m pip install --disable-pip-version-check \ + "koru==${KORU_VERSION}" \ + "vallm[llm,security]==${VALLM_VERSION}" + test "$(koru --version)" = "koru ${KORU_VERSION}" + python - <<'PY' + from importlib.metadata import version + import sys + + expected = {"koru": "0.1.444", "vallm": "0.1.94"} + actual = {name: version(name) for name in expected} + if actual != expected: + raise SystemExit(f"review tool version mismatch: {actual}") + sys.stdout.write(f"review tools pinned: {actual}\n") + PY + + - name: Resolve the exact changed source set + id: files + shell: bash + run: | + set -euo pipefail + git cat-file -e "${BASE_SHA}^{commit}" + git cat-file -e "${HEAD_SHA}^{commit}" + test "$(git rev-parse HEAD)" = "$(git rev-parse "${HEAD_SHA}^{commit}")" + mkdir -p .koru-review/vallm + git diff --diff-filter=ACMR --name-only -z "${BASE_SHA}" "${HEAD_SHA}" -- \ + '*.c' '*.cc' '*.cpp' '*.cxx' '*.go' '*.java' '*.js' '*.jsx' \ + '*.php' '*.py' '*.rs' '*.ts' '*.tsx' \ + | while IFS= read -r -d '' path; do + case "$path" in + dist/*|node_modules/*|project/*|.intent*/*|test/fixtures/*|tests/fixtures/*) ;; + *) printf '%s\n' "$path" ;; + esac + done > .koru-review/files.txt + sort -u -o .koru-review/files.txt .koru-review/files.txt + count="$(wc -l < .koru-review/files.txt | tr -d ' ')" + printf 'count=%s\n' "$count" >> "$GITHUB_OUTPUT" + printf 'Reviewed base: `%s`\nReviewed head: `%s`\nSelected source files: `%s`\n' \ + "$BASE_SHA" "$HEAD_SHA" "$count" >> "$GITHUB_STEP_SUMMARY" + + - name: Require semantic-review credentials + if: steps.files.outputs.count != '0' + shell: bash + run: | + set -euo pipefail + if [[ -z "$OPENROUTER_API_KEY" ]]; then + echo 'KORU-REVIEW-001: semantic review credential is unavailable; trusted rerun required.' >&2 + exit 1 + fi + + - name: Prepare the read-only Koru command + shell: bash + run: | + set -euo pipefail + command_path="$RUNNER_TEMP/koru-review-command" + cat > "$command_path" <<'BASH' + #!/usr/bin/env bash + set -euo pipefail + mapfile -t files < .koru-review/files.txt + if (( ${#files[@]} == 0 )); then + printf '%s\n' '{"summary":{"total_files":0,"passed":0,"failed":0,"success_rate":1.0},"files":[],"failed_files":[]}' \ + > .koru-review/vallm/validation.json + exit 0 + fi + export VALLM_LLM_PROVIDER=litellm + export VALLM_LLM_MODEL="$REVIEW_MODEL" + export VALLM_LLM_BASE_URL=https://openrouter.ai/api/v1 + vallm batch "${files[@]}" \ + --semantic --security --regression \ + --model "$REVIEW_MODEL" \ + --format json --output .koru-review/vallm --show-issues + BASH + chmod 0700 "$command_path" + printf 'KORU_REVIEW_COMMAND=%s\n' "$command_path" >> "$GITHUB_ENV" + + - name: Run one bounded Koru review round + id: koru + shell: bash + run: | + set -uo pipefail + set +e + koru \ + --workspace "$(dirname "$GITHUB_WORKSPACE")" \ + --include "$(basename "$GITHUB_WORKSPACE")" \ + --max-rounds 1 \ + --command "$KORU_REVIEW_COMMAND" \ + 2>&1 | tee .koru-review/koru.log + review_exit="${PIPESTATUS[0]}" + set -e + printf 'exit_code=%s\n' "$review_exit" >> "$GITHUB_OUTPUT" + exit 0 + + - name: Build commit-bound review report + if: always() + shell: bash + env: + KORU_EXIT_CODE: ${{ steps.koru.outputs.exit_code || '1' }} + run: | + set -euo pipefail + mkdir -p .koru-review/vallm + test -f .koru-review/files.txt || : > .koru-review/files.txt + if [[ ! -f .koru-review/vallm/validation.json ]]; then + printf '%s\n' '{"summary":{"total_files":0,"passed":0,"failed":1,"success_rate":0.0},"files":[],"failed_files":[{"error":"review did not produce a report"}]}' \ + > .koru-review/vallm/validation.json + fi + jq -n \ + --arg schema 't2c.koru-code-review/v1' \ + --arg repository "$GITHUB_REPOSITORY" \ + --arg baseSha "$BASE_SHA" \ + --arg headSha "$HEAD_SHA" \ + --arg koruVersion "$KORU_VERSION" \ + --arg vallmVersion "$VALLM_VERSION" \ + --arg model "$REVIEW_MODEL" \ + --argjson exitCode "$KORU_EXIT_CODE" \ + --rawfile selectedFiles .koru-review/files.txt \ + --slurpfile validation .koru-review/vallm/validation.json \ + '{ + schema: $schema, + repository: $repository, + baseSha: $baseSha, + headSha: $headSha, + tools: {koru: $koruVersion, vallm: $vallmVersion, model: $model}, + selectedFiles: ($selectedFiles | split("\n") | map(select(length > 0))), + verdict: (if $exitCode == 0 then "pass" else "reject" end), + exitCode: $exitCode, + validation: $validation[0] + }' > .koru-review/review.json + jq '{schema, repository, baseSha, headSha, tools, selectedFiles, verdict, exitCode}' \ + .koru-review/review.json >> "$GITHUB_STEP_SUMMARY" + + - name: Upload Koru review evidence + if: always() + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: koru-code-review-${{ github.run_id }} + path: .koru-review/ + include-hidden-files: true + if-no-files-found: error + retention-days: 14 + + - name: Attest the commit-bound review report + if: always() && hashFiles('.koru-review/review.json') != '' + uses: actions/attest-build-provenance@e8998f949152b193b063cb0ec769d69d929409be # v2.4.0 + with: + subject-path: .koru-review/review.json + + - name: Enforce the Koru verdict + if: always() + shell: bash + env: + KORU_EXIT_CODE: ${{ steps.koru.outputs.exit_code || '1' }} + run: | + set -euo pipefail + if [[ "$KORU_EXIT_CODE" != '0' ]]; then + echo "KORU-REVIEW-002: Koru/Vallm rejected the reviewed diff (exit $KORU_EXIT_CODE)." >&2 + exit 1 + fi diff --git a/TODO.md b/TODO.md index 21f9a79..def51fa 100644 --- a/TODO.md +++ b/TODO.md @@ -21,9 +21,10 @@ validator, trusted approval boundary, reusable governance CI, stack-specific gates and pinned adoption in `todo2code`; extend it with safe concurrent workstreams, dependency-aware intents and non-overlapping write scopes. - Current state: `BLOCKED`; AC-11..AC-16 pass, while AC-17 is blocked by the - concurrent Rust SDK 0.5.1 manifest versus ignored 0.5.0 Cargo lock. Immutable - central publication and external Ruleset/CODEOWNERS also remain open. + Current state: `IN_PROGRESS / EDIT` for the approved AC-18..AC-25: add a + pinned, read-only and attested `koru / code-review` PR check plus a required ruleset. + Earlier AC-11..AC-16 pass; AC-17 and the pre-existing publication/external + governance blockers remain recorded separately. ## Completed tickets diff --git a/project/ticket-018/README.md b/project/ticket-018/README.md index 9bb7f0b..b5802ee 100644 --- a/project/ticket-018/README.md +++ b/project/ticket-018/README.md @@ -2,8 +2,8 @@ - **ID**: ticket-018 - **Owner**: unresolved:human -- **Status**: BLOCKED -- **Workflow state**: VALIDATION +- **Status**: IN_PROGRESS +- **Workflow state**: EDIT - **Created**: 2026-08-01 ## Goal and scope @@ -66,6 +66,30 @@ existing ticket. - Preserve deterministic enforcement. LLM analysis may explain a divergence, but cannot classify it away or approve a scope expansion. +## Planned Koru code-review extension + +The user requested automated code review through Koru. The implementation will +add a read-only GitHub check named `koru / code-review`, run for pull requests +and explicit historical-review dispatches. It will pin Koru 0.1.444 and Vallm +0.1.94, select only changed supported source files, and let Koru execute one +bounded Vallm review round. The review combines deterministic syntax, +complexity and security checks with an OpenRouter semantic judge supplied by +the existing organization-level `OPENROUTER_API_KEY` secret. + +The workflow will never use `pull_request_target`, check out untrusted code +with a write-capable token, modify source, auto-fix, commit, push or submit a +GitHub `APPROVE` review. A missing secret or semantic-provider failure is an +explicit non-passing outcome rather than a silent deterministic fallback. +Forked pull requests therefore require a trusted maintainer rerun in a safe +context instead of receiving organization secrets. + +The machine-readable report will be bound to repository, base SHA, head SHA, +tool versions and verdict, uploaded as a CI artifact and covered by a GitHub +artifact attestation. A repository ruleset will require both the existing +governance check and `koru / code-review`; the Koru attestation is independent +read-only review evidence, not evidence that the implementation author or this +agent self-approved. + ## Acceptance criteria - [x] AC-01: A human approves this understanding and execution checklist before @@ -116,6 +140,30 @@ existing ticket. - [ ] AC-17: Existing application and Docker E2E checks still pass; unrelated concurrent changes in `.env.example`, `src/`, `test/` and `tests/fixtures/` are neither modified nor attributed to this ticket. +- [x] AC-18: A human approves the Koru review design, bounded scope and + AC-18..AC-25 before the workflow or repository rules are changed. +- [x] AC-19: A pinned pull-request/workflow-dispatch job exposes the stable + required-check name `koru / code-review` and resolves exact base/head + SHAs without evaluating a merge-ambiguous working tree. +- [x] AC-20: Koru 0.1.444 runs exactly one read-only Vallm 0.1.94 review round + over changed supported source files; auto-fix, commit, push and mutable + dependency versions are absent. +- [ ] AC-21: Deterministic syntax/complexity/security checks and semantic + LLM-as-judge review fail closed on findings, missing credentials, + malformed output or provider failure, with no secret value in logs. +- [ ] AC-22: The structured report records repository, base/head SHA, selected + files, tool/model versions and verdict, is uploaded with fixed retention, + and receives GitHub artifact provenance attestation. +- [ ] AC-23: The workflow uses least-privilege read permissions, never uses + `pull_request_target`, and treats fork PRs without secrets as requiring a + trusted rerun rather than exposing organization credentials. +- [ ] AC-24: A repository ruleset requires `governance / enforce` and + `koru / code-review`, blocks direct updates to `main`, dismisses stale + evidence after new commits and cannot be bypassed by the implementation + agent. +- [ ] AC-25: Workflow syntax, local Koru/Vallm probes, negative failure paths, + `npm run verify`, governance and relevant Docker checks pass; the + pre-existing ticket-019 findings remain separately attributed. ## Participants diff --git a/project/ticket-018/ai-codex-logs.txt b/project/ticket-018/ai-codex-logs.txt index 668dd0b..fa464e3 100644 --- a/project/ticket-018/ai-codex-logs.txt +++ b/project/ticket-018/ai-codex-logs.txt @@ -141,3 +141,66 @@ agent. The scopes do not overlap on implementation paths. $ bash project/governance-check.sh --actor agent GOV-PASS: passed (0 errors, 0 warnings) This final workspace check included the concurrently created untracked ticket. + +2026-08-01 KORU CODE-REVIEW PLAN +$ koru --version +installed PATH version: 0.1.398 +local Koru development venv: 0.1.443 +published pinned target: 0.1.444 + +$ python -m pip index versions vallm +installed version: 0.1.92 +published pinned target: 0.1.94 + +$ koru --doctor --project . --format json +result: project is not initialised for planfile queue mode; loop mode remains +available without repository mutation. Two expected setup failures were +reported for missing .planfile config/sprints. + +$ gh secret list --org semcod +The organization-level OpenRouter credential is available to all repositories; +its value was not read or logged. + +$ inspect GitHub repository controls for semcod/todo2code +main branch protection: absent +repository rulesets: none +PR/review for commit 06a2faa: none +CI verify/JDK/build/deploy: PASS +CI governance/enforce: FAIL on ticket-019 state + +Decision: reuse unfinished governance ticket-018. Plan AC-18..AC-25 only and +stop in WAIT_FOR_APPROVAL. No CI, source, test, ruleset or human-owned content +was changed. + +2026-08-01 KORU CODE-REVIEW APPROVAL +User response: tak, wykonaj +Transition: PLAN / WAIT_FOR_APPROVAL -> IN_PROGRESS / EDIT. +Scope approved: AC-18..AC-25 recorded in ticket-018. + +2026-08-01 KORU CODE-REVIEW LOCAL IMPLEMENTATION +$ uvx --from koru==0.1.444 --with vallm[llm,security]==0.1.94 koru --version +koru 0.1.444 + +$ Koru loop positive probe (one repository, one round, command=true) +koru: repos=1 succeeded=1 failed=0 rounds=1 +exit=0 + +$ Koru loop negative Vallm probe (intake-service.ts, security, fail on review) +koru: repos=1 succeeded=0 failed=1 rounds=1 +exit=1 + +$ query current OpenRouter model catalog +deepseek/deepseek-v4-pro: available + +$ npm run verify:workflows +Workflow YAML verified: 2 file(s), no duplicate top-level keys. + +$ npm run verify +tests 335; pass 334; fail 0; skipped 1 (local JDK unavailable) +module boundaries: 114 modules, 521 internal imports, no cycles +workflow, schema, no-LLM and generated-analysis gates: PASS + +$ make governance +Four existing ticket-019 findings remain: GOV-CONFLICT-001, +GOV-DEPENDENCY-002, GOV-WORKSTREAM-003 and GOV-WORKSTREAM-004. +No new ticket-018 secret, path or scope finding was emitted. diff --git a/project/ticket-018/ai-codex.md b/project/ticket-018/ai-codex.md index e7c7e5b..84502e2 100644 --- a/project/ticket-018/ai-codex.md +++ b/project/ticket-018/ai-codex.md @@ -29,6 +29,12 @@ ticket dependency DAG. Divergence that changes a shared contract is routed to an explicit integration ticket and fresh approval; it is never absorbed by retroactively widening one agent's scope. +The current follow-up asks Koru to provide automated code review. This is a +read-only second-AI boundary: Koru orchestrates pinned Vallm checks for the +exact PR diff, produces a commit-bound attested report, and exposes a required +GitHub status. It may reject a change but may not edit it, push it or impersonate +a human `APPROVE` review. + Current verified baseline: - Docker CLI and engine are available; engine version reported `29.1.3`. @@ -77,6 +83,21 @@ Current verified baseline: in `todo2code` and prove parallel non-overlap plus rejected overlap. 14. Validate in Docker, run existing E2E gates, review only ticket-018 paths and preserve all concurrent application changes. +15. Return to `PLAN / WAIT_FOR_APPROVAL` for the Koru review extension before + changing workflows or external rules; record AC-18..AC-25 and the current + tool/secret/ruleset baseline. +16. Add a least-privilege `pull_request` plus `workflow_dispatch` workflow with + stable check name `koru / code-review`, exact base/head resolution and + immutable action/tool pins. +17. Use Koru 0.1.444 loop mode for one read-only Vallm 0.1.94 round over changed + supported source files, with deterministic and OpenRouter semantic checks. +18. Generate a sanitized structured review report, upload it with bounded + retention and create a GitHub provenance attestation bound to the reviewed + commit. +19. Exercise passing and failing review probes, missing-secret/provider failure, + workflow validation, existing Node/Docker gates and scoped governance. +20. Configure a `main` ruleset requiring governance and Koru review only after + the check exists; verify direct pushes and stale evidence are rejected. ## Actual changes @@ -108,6 +129,17 @@ Current verified baseline: non-overlapping and remains untouched; the final whole-workspace gate accepts ticket-018 (`governance`) and ticket-019 (`sdk`) as parallel PLAN/VALIDATION records while routing this implementation diff uniquely to ticket-018. +- Planned only the Koru code-review extension requested by the user. Verified + published Koru 0.1.444 and Vallm 0.1.94, an organization-level OpenRouter + secret visible to this repository, and the absence of branch protection, + rulesets or an existing PR review for commit `06a2faa`. No workflow, source, + test, external ruleset or human-owned file was changed in this plan phase. +- After explicit approval, added `.github/workflows/koru-code-review.yml` with + immutable action pins, exact base/head selection, changed-source filtering, + one Koru/Vallm round, fail-closed credential handling, structured evidence, + bounded artifact retention and GitHub provenance attestation. The job is + read-only with respect to repository contents and cannot approve or mutate a + pull request. ## Blockers @@ -121,6 +153,8 @@ Current verified baseline: reusable-workflow SHA exists yet. - GitHub Ruleset and CODEOWNERS need a trusted human/team identity and external repository configuration. +- AC-18 requires explicit approval of the new Koru design after this plan is + visible. Until then, CI and external repository rules remain unchanged. - AC-17: concurrent commit `9928699` bumped the Rust SDK manifest to 0.5.1, but the ignored local Cargo lock still identifies the root package as 0.5.0. Official full Docker E2E fails closed at `cargo fetch --locked` (exit 101). @@ -129,10 +163,8 @@ Current verified baseline: ## Approval boundary -- Current state: `BLOCKED / VALIDATION`. AC-11..AC-16 are implemented and verified; AC-17, - immutable central publication and external Ruleset/CODEOWNERS remain open. +- Current state: `IN_PROGRESS / EDIT` for approved AC-18..AC-25. AC-11..AC-16 are + implemented; AC-17 and the earlier publication/external blockers remain open. - Required response from: `unresolved:human`. -- The user supplied the requested fresh explicit approval in chat. It - authorizes local implementation for this session; merge-time trust still - requires an external GitHub review/ruleset and is not inferred from this - agent-written record. +- The user explicitly approved AC-18..AC-25 in chat. This authorizes the + implementation workflow but is not itself merge-time review evidence. diff --git a/project/ticket-018/changelog.md b/project/ticket-018/changelog.md index 7b32eb1..e7635fc 100644 --- a/project/ticket-018/changelog.md +++ b/project/ticket-018/changelog.md @@ -15,6 +15,14 @@ E2E pass. - Transitioned to `BLOCKED` because concurrent Rust SDK version drift prevents official full E2E before tests; no out-of-scope Cargo artifact was rewritten. +- Planned an AC-18..AC-25 extension for pinned Koru/Vallm pull-request review, + fail-closed semantic validation, an attested review artifact and a required + `main` ruleset; no CI or external repository setting changed in this phase. +- Recorded explicit human approval of AC-18..AC-25 and transitioned to + `IN_PROGRESS / EDIT` before changing CI or repository rules. +- Added the pinned `koru / code-review` workflow with exact diff selection, + one bounded semantic/security review round, structured evidence, artifact + upload and GitHub provenance attestation. ## [0.1.0] - 2026-08-01 diff --git a/project/ticket-018/intent.json b/project/ticket-018/intent.json index f9b700b..2ca605e 100644 --- a/project/ticket-018/intent.json +++ b/project/ticket-018/intent.json @@ -1,7 +1,7 @@ { "schema": "new-project.intent/v2", "ticket": "ticket-018", - "summary": "Adopt deterministic governance policy-as-code with concurrent workstreams, dependency-aware tickets and non-overlapping write scopes", + "summary": "Adopt deterministic governance policy-as-code with concurrent workstreams and an attested Koru code-review gate", "workstream": "governance", "allowedPaths": [ ".governance/**", @@ -24,6 +24,7 @@ ], "stacks": [ "node", + "python", "docker" ], "dependsOn": [], diff --git a/project/ticket-018/preprompt.md b/project/ticket-018/preprompt.md index be5ddee..e290ef2 100644 --- a/project/ticket-018/preprompt.md +++ b/project/ticket-018/preprompt.md @@ -6,3 +6,10 @@ Keep executable implementation outside this governance/evidence directory. Read a human-owned user-*.md file only when one exists. + +The user requested automated code review using Koru. Plan a read-only, pinned +and attested pull-request check which cannot mutate source or self-approve, +uses the existing organization OpenRouter secret only in the safe +`pull_request` context, fails closed, and becomes a required `main` ruleset +check. Stop again in `WAIT_FOR_APPROVAL` before editing CI or external +repository rules.