Skip to main content
Extend Macroscope’s default correctness check with context to improve precision and avoid false positives. Custom correctness instructions teach our core code review what’s idiomatic, intentional, or off-limits in your codebase, so it flags real issues and stays quiet on patterns it would otherwise misread. Drop markdown files into .macroscope/correctness/, optionally scope them with glob patterns, and your team’s domain knowledge is folded into the same correctness review you already get.

File layout

Create one or more markdown files inside .macroscope/correctness/ at the root of your repo:
Subdirectories are walked recursively, so you can organize instructions by team or service — useful in monorepos:
Nesting is purely organizational. A file’s location does not affect which changes it applies to — that is controlled entirely by the include/exclude front matter. Only *.md files are read; any other files (and README.md) are ignored. Instruction files work like any other code change. Macroscope reads them from the most recent commit on the pull request, so pushing a new or edited instruction to a PR takes effect on that PR right away — useful for tuning an instruction before the rest of your team gets it. Other open PRs pick it up once the change is merged and their branches include it. Pull requests from external forks always read instructions from your default branch.

Front matter

Custom correctness instruction files support YAML front matter with the following fields: If both include and exclude are omitted, the instructions apply globally to every file Macroscope reviews in the repo. These two fields are per-file: every instruction file gets its own, and they control only that file’s instructions. The fields that govern the correctness check run — when it starts, and whether it starts at all — live in one designated file instead. See Prerequisite steps.

Example

.macroscope/correctness/configuration-principles.md:
In this example, the rules apply to all Go files and anything under a config/ directory, but skip tests and test fixtures. When Macroscope reviews a change that touches a matching file, these principles are folded into the correctness review automatically.
Front matter is optional. A correctness instruction file with no front matter applies to every file in the repo.

How matching works

For each file changed in a pull request, Macroscope walks .macroscope/correctness/ and includes the contents of every instruction file whose include/exclude patterns match that file’s path. Multiple instruction files can apply to the same file — they stack. If no instruction file matches, the correctness review behaves exactly as it does for repos without custom instructions.

Prerequisite steps

By default the correctness check starts as soon as your pull request is pushed, in parallel with the rest of your CI. You can instead have it wait for specific CI steps — and skip entirely unless they passed.

The governing file

.macroscope/correctness/ holds as many instruction files as you like, but there is only one correctness check run. A field like “wait for the lint job” has no meaning spread across five files that might disagree, so Macroscope reads it from exactly one:
.macroscope/correctness/correctness.md — at the top level of the directory, spelled exactly that way — is the governing file. Its front matter configures the whole correctness check: Every other file in the directory keeps its include/exclude patterns and its instructions, and correctness.md keeps those too — it is an ordinary instruction file that additionally carries the configuration. Writing any of the four fields above in a different file does nothing, and Macroscope warns on the check run page rather than leaving you to guess. So the governing file is not a config-only file. If one file is all you need, put everything in it:
That waits for build to pass before reviewing, and applies the same rule to Go files outside tests — one file, both jobs. A body is optional too: a correctness.md with only front matter configures the check and instructs nothing.

Waiting and gating

waitsFor orders; requires orders and gates.
Here correctness waits for all three steps, and reviews only if build and ci / test passed. If either failed, the check is skipped before any review is dispatched — so a review against a broken build costs you nothing. The Integration Suite is waited for but not gated on: its outcome is irrelevant to whether the review should happen. The names must match the check run names exactly as they appear on your PR’s Checks tab. requires uses GitHub’s own definition of passing — success, skipped, and neutral — the same three conclusions that satisfy a required status check on a protected branch.

When a prerequisite doesn’t arrive

The discovery window is always capped at waitsForTimeout — it is a slice of the overall wait, never an addition to it. Both timeouts top out at 30 minutes — half of what a check run agent allows. A correctness review is the longer-running of the two, so less of its time can be spent waiting and still leave room to review. If a prerequisite regularly takes longer than 30 minutes to finish, correctness skips rather than waits; gate on an earlier, faster step instead.
A skipped correctness review holds the PR back from automatic approval. waitsFor and requires say when to review, not whether: the verdict was still owed, so Approvability will not approve without it. That is deliberate for requires in particular — a gate fires precisely when your CI is red, which is not the moment to approve a PR on the strength of a review that never ran.

What correctness will not wait for

Two values are refused, with a warning on the check run page:
  • ["*"], the “go last” wildcard that check run agents support.
  • The name of any Macroscope check run, including Macroscope - Approvability Check and any of your own check run agents.
Both are cycles. The correctness check runs before every other Macroscope check: the Approvability check waits for correctness unconditionally, and so does any check run agent configured with waitsFor: ["*"]. Waiting for those in turn would have each side waiting for the other until its budget expired. Name your own CI steps instead — those are what these fields are for.