_version = 1 [workflow] graph = "code-review.fabro" [run.inputs] mode = "changes" effort = "medium" scope = "" base = "" commit = "" range = "" model = "kimi-k3" guidance = "" expected_min_findings = "" expected_file = "" expected_min_rule_findings = "" # Opt-in PR publishing (the publish_pr node). post_pr = "true" posts the # findings to the named pull request; everything else leaves the node a # no-op. pr_repo is the owner/name slug, pr_number the PR number. post_pr = "" pr_repo = "" pr_number = "" # Routing policy: findings at or below the severity (high|medium|low), or # in the listed categories (comma-separated), go to the summary comment # instead of inline. Empty disables that dimension; a malformed value # fails the plan (fail-closed). route_severity_below = "" route_categories = "" # Optional run-report URL included in the sticky summary. run_url = "" # Full history, for arbitrary base and range inputs. [run.clone] depth = 0 # A review is read-only and publishes nothing back to the repository; a # host project's defaults (for example .fabro/project.toml enabling pull # requests) must not turn a review run into a branch or PR. [run.run_branch] enabled = false [run.pull_request] enabled = false [run.model.fallbacks] "kimi-k3" = ["moonshot:kimi-k3", "modal:kimi-k3", "claude-opus-5"] [run.environment] id = "code-review" # The publish_pr node posts review comments, so the run needs a GitHub # token. Declaring these permissions makes Fabro mint a scoped # installation token and inject it as GITHUB_TOKEN into sandbox command # and agent execution; the grant is the minimum the publisher needs # (inline review comments and the sticky summary on the reviewed PR). # If the server has no GitHub integration, the run continues without a # token and publish_pr fails only when post_pr actually asks it to post. # Operating requirement (publisher spec R14): the launcher must not run # two publishing reviews of the same PR concurrently -- serialize runs # per repository+PR. [run.integrations.github.permissions] pull_requests = "write" [run.checkpoint] exclude_globs = [ "CODE-REVIEW-*/**", ".fabro/blobs/**", ".fabro/workflows/code-review/runtime", ] [run.artifacts] include = [ "CODE-REVIEW-*/.gitignore", "CODE-REVIEW-*/CODE-REVIEW-RESULTS.md", "CODE-REVIEW-*/CODE-REVIEW-RESULTS.html", "CODE-REVIEW-*/CODE-REVIEW-RESULTS.jsonl", "CODE-REVIEW-*/CODE-REVIEW-RESULTS.sarif", "CODE-REVIEW-*/evidence/review-manifest.json", "CODE-REVIEW-*/evidence/candidate-ledger.jsonl", "CODE-REVIEW-*/evidence/findings.json", "CODE-REVIEW-*/evidence/coverage.json", "CODE-REVIEW-*/evidence/votes.jsonl", "CODE-REVIEW-*/metadata/revision.json", "CODE-REVIEW-*/metadata/state.json", "CODE-REVIEW-*/metadata/review-meta.json", "CODE-REVIEW-*/pr-publish-plan.json", "CODE-REVIEW-*/pr-publish-outcome.json", ] [environments.code-review] provider = "daytona" # The review's agents search the tree constantly. The mirrored buildpack-deps # noble image is the Daytona default base. It ships grep but not ripgrep, # which respects .gitignore and is far faster on a large repository. # Every tier above low uses the rule loader and needs PyYAML; the pin and # hashes below must stay in lockstep with requirements-rules.txt (cp312 # manylinux wheels + sdist). [environments.code-review.image] dockerfile = """ FROM ghcr.io/lithoscomputer/docker-mirror/buildpack-deps:noble@sha256:1fdce57bbb1105e0e515f6523bd0c3eb1df8b601847cfea140483672f6484afa RUN apt-get update && apt-get install -y --no-install-recommends ripgrep python3-pip && rm -rf /var/lib/apt/lists/* RUN echo 'PyYAML==6.0.3 --hash=sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f --hash=sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc --hash=sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28' > /tmp/requirements-rules.txt && python3 -m pip install --break-system-packages --no-cache-dir --require-hashes -r /tmp/requirements-rules.txt && rm /tmp/requirements-rules.txt """ [environments.code-review.resources] cpu = 2 memory = "4GB"