feat(augmentcode): add a checks adapter for code_review_guidelines.yaml - #2644
Merged
Conversation
Augment Code Review reads its custom guidelines from one YAML file of named areas, each rule an id/description/severity triple. Checks had no adapter for it, so the surface was unreachable from .rulesync/checks/. One check maps onto one rule, in an area of its own unless an `augmentcode.area` groups several together. Augment's scale tops out at high, so canonical critical folds onto it and does not come back; an unannotated check emits medium, since the field cannot be omitted. Generation merges per area key rather than replacing the file, because Augment tells users to hand-write it - and for the same reason the file is never deleted once it exists, since YAML carries no marker saying which areas are ours.
Two round-trip breakers found in review. The default globs list was a shared module-level array, so js-yaml wrote the second and later areas as `*ref_0` aliases pointing at an anchor on the first - in a file Augment tells users to hand-edit. Build the list per area and pass `noRefs`, matching every other dump call in the repo. An authored area key was slugified, which rewrites the underscores in Augment's own documented `memory_safety` example. Since import writes the key back verbatim, the next generate built a second area under the slugified spelling while the original stayed - the same rules twice. Only the file-stem default is slugified now. Also: an authored empty globs list is kept rather than widened to the catch-all, and two same-named checks in different subdirectories no longer collide on one rule id.
… safe Two follow-ups from review. A generated rule id could land on one a hand-written area in the same file already used. Augment reports findings by id, so the two rules are indistinguishable in its output; ids from preserved areas are now reserved before the generated ones are assigned. Preserving an authored empty globs list also swallowed the case where every entry was the wrong type: the filter emptied the list and the area regenerated as one matching nothing. Only a list that was empty as written is preserved; a malformed one falls back to the catch-all.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #2420.
Gaps 1, 2 and 4 of that issue (the
PromptSubmithook event, handlerargs/ matcher-groupmetadata, and the.agents/commands/import root) landed in #2444. Gap 3 — the.augment/code_review_guidelines.yamlchecks adapter — was the sole open item, and this is it.What Augment reads
Augment Code Review reads one YAML file at the repository root's
.augment/, grouping rules into named areas:Every field shown is required — area
description/globs/rules, and per-ruleid/description/severity. A top-levelfile_paths_to_ignoretakes doublestar globs.Mapping
One
.rulesync/checks/*.mdbecomes one rule. The body is the rule'sdescription(the check'sdescriptionwhen the body is empty, the file stem when neither is set); the rule lands in an area keyed by the check's file stem. Anaugmentcodefrontmatter block moves it:areagroups several checks under one key, withareaDescriptionandglobscoming from the first check to name that area (globsdefaults to["**"], matching Augment's example), andidoverrides the rule id.Like Cursor Bugbot, Rovo Dev and Takt, the whole set collapses into one file via
fromRulesyncChecksrather than a file per check. Registered project-scope only withcommittedOutput: true— the reviewer reads the file from the committed tree, and Augment documents no user-level equivalent.Severity mapping (an Augment-only call)
Canonical
criticalmaps tohigh. Augment's scale ishigh/medium/lowwith no band abovehigh, so the alternatives were dropping the rule or demoting it tomedium— either losing the check or understating the one severity a reviewer most wants raised. The fold is one-way: acriticalcheck generateshighand imports back ashigh, so the canonical value is not recoverable from Augment's file alone. A test asserts that asymmetry explicitly rather than leaving it implied.A check with no
severityemitsmedium, since the field cannot be omitted:highwould push every unannotated check past the ones deliberately markedmedium, andlowwould bury them.Documented in the adapter docstring and in
docs/reference/file-formats.md. Note this is the same severity-scale question shared with #2399/#2404; nothing here presumes an answer for those.Preservation, and what it costs
Augment's docs tell users to hand-write this file, so generation merges instead of replacing: only areas the current check set claims are rewritten, and every other area,
file_paths_to_ignore, and any key Augment adds later survive untouched.file_paths_to_ignoreis recognized and preserved but never authored or imported — the canonical check model has no ignore surface, and adding one is a separate design question the issue does not propose.The honest cost, stated in the docstring and docs rather than hidden: rulesync cannot tell its own leftovers from a hand-written area. Renaming a check strands the area under the old key, and when checks remain but none target AugmentCode the areas are left in place with a warning rather than guessed at.
canDeleteAuxiliaryFilestherefore returns false whenever the file exists — unlike the Markdown surfaces, YAML has no marker to distinguish generated content, since a rewrite drops comments and an unknown top-level key would risk Augment's own parser.Import
Each rule becomes its own check (an area of three rules is three checks, not one), carrying the area key, description and globs back in its
augmentcodeblock so the next generate regroups them exactly where they were. A test round-trips a hand-written two-rule area to a byte-equivalent document. A rule missingidordescriptionis left in the YAML rather than imported, and a rule id repeated across two areas is suffixed so the second check cannot overwrite the first.Tests
augmentcode-check.test.ts(19 cases) covers generation, area grouping, both severity behaviors, preservation vs. claimed-key rewrite, the no-targets warning, the deletion guard, and the import/round-trip paths.src/e2e/e2e-checks.spec.tsgains the matrix case, andchecks-processor.test.tspicks up the new target. Tables regenerated viapnpm run generate:tables.pnpm cicheckgreen;npx vitest run --config vitest.e2e.config.ts src/e2e/e2e-checks.spec.tsgreen.🤖 Generated with Claude Code