feat(engine): base-revision + comment access for ctx.ast() (closes #479)#480
Conversation
Rules can now inspect a file at its base git revision, not only the working
tree — the capability whose absence forced rule authors to shell out to a
subprocess (the escape ARCH-024 closed). This restores it through the
sanctioned ctx.ast() door.
New surface:
- ast(path, language, { rev: "base" }) parses the file at the comparison base
commit instead of the working tree, same shapes and throw contract.
- fileAtBase(path): Promise<string | null> returns the raw base source, or
null when no base is resolved or the file did not exist at the base.
The base is the merge base of --base and HEAD — the same commit changedFiles
diffs against (three-dot ref...HEAD) — resolved once per run in git-files.ts.
No new privileged path: the git reads (git merge-base, git show) live in the
already-sanctioned git-files.ts site, and all four ast() guardrails run in
order for a base parse. TS/JS base source parses in-process via a shared
parseTsOrJsSource helper (factored into js-parser.ts). Python/Ruby base
content is written to an OS-temp file — outside the project tree — and handed
to the unchanged serializers with the same mandatory -I isolation.
ast({ rev: "base" }) throws (distinguishably) when no base is resolved or the
file was added since the base; fileAtBase reports both as null so a rule can
branch on "is there a base?" without a try/catch.
This unblocks documentation-only / no-op change detection (compare base and
working-tree ASTs; comments and formatting drop out of both shapes) with zero
subprocess use. Amends ARCH-022; behavioural coverage in
tests/engine/runner-ast-base.test.ts.
Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_a719d6ee-8668-41ea-8825-d4ccd374694d) |
|
Warning Review limit reached
Next review available in: 14 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (21)
📝 WalkthroughWalkthroughThe rule context now supports merge-base file reads, base-revision AST parsing, and structured comment extraction. Git helpers provide nullable revision operations; JavaScript and TypeScript sources are parsed directly, while Python and Ruby base sources use temporary files with cleanup. AST options, public declarations, generated typings, documentation, runner wiring, grep matching, ADR guidance, and tests were updated. Base AST failures throw for unavailable revisions or missing files, whereas 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Deploying archgate-cli with
|
| Latest commit: |
73d245b
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://7c68ee52.archgate-cli.pages.dev |
| Branch Preview URL: | https://claude-ctx-ast-base-and-comm.archgate-cli.pages.dev |
Code Coverage
Full HTML report available in workflow artifacts. Per-directory breakdown
|
There was a problem hiding this comment.
Actionable comments posted: 7
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/engine/ast-support.ts`:
- Around line 239-274: Update writeTempSourceFile to create a private temporary
directory securely, then exclusively create the source file inside it with mode
0600 rather than using the predictable PID/counter path and direct
writeFileSync. Return the file path and make cleanup remove the file and its
private directory in a finally-safe, best-effort manner, including cleanup when
file creation fails.
In `@src/engine/runner.ts`:
- Around line 435-442: The check flow must reuse baseRevPromise’s resolved
merge-base SHA when computing changedFiles instead of independently calling
getFilesChangedSinceRef with options.base. Update the changedFiles setup to diff
the resolved SHA against HEAD while preserving staged/default behavior and
inclusion of working-tree and untracked files; ensure baseRevPromise remains the
single base-resolution operation for the run.
In `@src/formats/rules.ts`:
- Around line 70-79: Update the RuleContext.ast() documentation in
src/formats/rules.ts lines 70-79 to state that callers must compare a structural
projection excluding location metadata, rather than promising identical ESTree
or Python AST trees for comment or formatting-only changes. Apply the same
qualification to the capability described in
.archgate/adrs/ARCH-022-ast-aware-rule-context.md line 107, preserving ARCH-022
as the governing semantic reference.
- Around line 187-197: The language-agnostic RuleContext.ast overload currently
omits optional AstOptions. Update the AstLanguage overload in
src/formats/rules.ts lines 187-197 and mirror the same opts?: AstOptions
parameter in src/helpers/rules-shim.ts lines 183-193, preserving the existing
language-specific overloads and return types.
In `@tests/engine/runner-ast-base.test.ts`:
- Line 4: Replace every writeFileSync call in the async tests with awaited
Bun.write calls using the existing joined paths and content, while retaining the
node:fs import only for mkdtempSync and mkdirSync.
- Around line 304-350: Extend the AST equivalence test matrix beside the
existing Python case with JavaScript and Ruby comparisons. Add a JavaScript
base-versus-working-tree AST check, and add a Ruby equivalent guarded by skipIf
for the Ruby interpreter, using the appropriate language identifiers, source
files, and serializers while preserving the existing doc-only versus real-edit
assertions.
- Around line 232-260: Update the comparison in the check callback of the
“typescript: a comment-only edit yields structurally identical trees” test to
recursively remove location fields from both complete ASTs and compare the
resulting trees, rather than comparing only top-level node types. Preserve the
existing comment-only scenario while ensuring changes such as `v = 1` versus `v
= 2` are detected.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 0f42d986-b8e5-4669-90d6-21aaf9c959b1
📒 Files selected for processing (8)
.archgate/adrs/ARCH-022-ast-aware-rule-context.mdsrc/engine/ast-support.tssrc/engine/git-files.tssrc/engine/js-parser.tssrc/engine/runner.tssrc/formats/rules.tssrc/helpers/rules-shim.tstests/engine/runner-ast-base.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (3)
- GitHub Check: Smoke Test (Windows) / Windows
- GitHub Check: Smoke Test (Linux) / Linux
- GitHub Check: Cloudflare Pages
🧰 Additional context used
📓 Path-based instructions (18)
src/**/*.ts
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-003-output-formatting.md)
src/**/*.ts: UsestyleText(format, text)fromnode:utilfor all terminal colors and formatting in CLI source files; do not use raw ANSI escape codes or third-party color libraries.
Commands that produce structured results and support--jsonmust emit machine-readable JSON to stdout with no colors or decorative formatting.
When a command supports--json, useformatJSON()fromsrc/helpers/output.tsfor JSON serialization, and passforcePretty: truewhen the user explicitly provided--json.
UseisAgentContext()fromsrc/helpers/output.tsto enable auto-JSON behavior for commands that support both human-readable and JSON output modes.
CLI output must not include emoji; use text symbols and colors instead.
Send normal command output to stdout withconsole.log(), and send errors, warnings, and debug messages to stderr vialogError(),logWarn(), andlogDebug().
Keep CLI output concise and scannable by using whitespace and alignment instead of long text blocks.
RespectNO_COLORautomatically by relying onstyleText; do not add custom color-environment handling in CLI code.
Do not output progress spinners unless there is a TTY check.
Do not assume piped output means agent context whenCIis set; CI runners should still receive human-readable output.
src/**/*.ts: Do not re-export symbols from another module in any source file; statements likeexport { X } from "./other"andexport type { X } from "./other"are forbidden.
Import symbols directly from the module that defines them; do not import from a directory path such as../formatsexpecting implicitindex.tsresolution.Make large production thresholds injectable via an optional parameter that defaults to the module constant, so tests can supply a small value instead of generating huge fixtures.
src/**/*.ts: Useawait Bun.file(path).json()when reading JSON files in Bun TypeScript source code; do not useJSON.parse(await Bun.file(path).text())or `JSON.parse(fs.readFile...
Files:
src/engine/ast-support.tssrc/formats/rules.tssrc/engine/git-files.tssrc/helpers/rules-shim.tssrc/engine/runner.tssrc/engine/js-parser.ts
**/*.{ts,tsx,js,jsx,mjs,cjs}
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-006-dependency-policy.md)
**/*.{ts,tsx,js,jsx,mjs,cjs}: Use Bun built-ins for file I/O (Bun.file,Bun.write), HTTP, subprocess execution (Bun.spawn), globbing (Bun.Glob), and testing (bun:test).
Do not use Node.js-specific APIs when Bun alternatives exist; for example, useBun.file()instead offs.readFile()for simple reads.
Prefernode:built-in modules such asnode:util,node:path, andnode:fsover npm alternatives.
Do not use utility libraries for single functions, such as importing lodash for one helper likepick.
Do not use path aliases (tsconfig paths); use relative imports with Bun's native module resolution.
Do not install packages globally during development; usebunxfor one-off tools.
Files:
src/engine/ast-support.tssrc/formats/rules.tssrc/engine/git-files.tssrc/helpers/rules-shim.tstests/engine/runner-ast-base.test.tssrc/engine/runner.tssrc/engine/js-parser.ts
src/**/!(*platform).ts
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-009-platform-detection-helper.md)
src/**/!(*platform).ts: Insrc/TypeScript source files, do not readprocess.platformdirectly; usesrc/helpers/platform.ts(isWindows(),isMacOS(),isLinux(),isWSL(),getPlatformInfo()) for all platform detection.
Use the centralized platform helper instead of duplicating OS/WSL detection logic inline anywhere insrc/TypeScript source.
When behavior differs between Linux and Windows, account for WSL by usingisWSL()rather than assuming `
Files:
src/engine/ast-support.tssrc/formats/rules.tssrc/engine/git-files.tssrc/helpers/rules-shim.tssrc/engine/runner.tssrc/engine/js-parser.ts
{src,tests}/**/*.ts
📄 CodeRabbit inference engine (.archgate/adrs/LEGAL-001-spdx-license-headers.md)
{src,tests}/**/*.ts: Every TypeScript source file insrc/andtests/must begin with// SPDX-License-Identifier: Apache-2.0followed by// Copyright 2026 Archgate.
If a TypeScript file has a shebang line (for example#!/usr/bin/env buninsrc/cli.ts), the SPDX license header must appear immediately after the shebang.
Use single-line//comments for the SPDX header; do not use block comments (/* */) or alternate license identifiers.
Files:
src/engine/ast-support.tssrc/formats/rules.tssrc/engine/git-files.tssrc/helpers/rules-shim.tstests/engine/runner-ast-base.test.tssrc/engine/runner.tssrc/engine/js-parser.ts
src/{helpers,engine}/**/*.ts
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-002-error-handling.md)
Do not use
console.log(),console.warn(), orconsole.info()directly in helper or engine files; uselogInfo()orlogWarn()instead.
Files:
src/engine/ast-support.tssrc/engine/git-files.tssrc/helpers/rules-shim.tssrc/engine/runner.tssrc/engine/js-parser.ts
src/engine/**/*.ts
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-023-engine-file-listing-via-in-memory-git-tracked-matching.md)
src/engine/**/*.ts: In the rules engine, list project files by matching glob patterns in memory against the git-tracked file set rather than walking the filesystem.
Route new engine file listings throughlistMatchingFilesfor rule-facing inputs ormatchTrackedFilesfor trusted ADR frontmatter patterns.
When the target is a Git repository andrespectGitignoreis not false, pass the tracked set fromgetGitTrackedFilesto matching operations.
Per-runRunCachesmust share glob results keyed by pattern and tracked mode and file text keyed by absolute path; cached promises should share in-flight work, and returned glob arrays must be copied before exposing them to rules.
Do not cachereadJSONresults because rules receive mutable objects whose shared mutation could leak between rules.
Do not filter filesystem scan results against the tracked set as a substitute for in-memory matching, and do not hardcode ignore directories; use the Git-derived tracked set instead.
src/engine/**/*.ts: Engine code must not add unsanctioned subprocess mechanisms:child_processimports are prohibited, andBun.spawn/Bun.spawnSynccalls must remain confined to the sanctioned AST and git helpers.
Do not introduce tree-sitter, web-tree-sitter, native parser bindings, WASM grammars, or other new production dependencies for this AST feature.
Do not normalize Python or Ruby AST results into ESTree; document that AST node shapes are language-native and distinct.
For TypeScript AST results parsed from transpiled output, consumers must not treatnode.locas source-accurate; source locations are directly reliable only for JavaScript, so TypeScript locations must be re-located against the original source.
Files:
src/engine/ast-support.tssrc/engine/git-files.tssrc/engine/runner.tssrc/engine/js-parser.ts
src/engine/{runner,ast-support}.ts
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-022-ast-aware-rule-context.md)
TypeScript and JavaScript AST parsing must reuse the shared in-process
meriyahparser helper; Python and Ruby parsing must use their standard-library AST facilities through guardedBun.spawncalls with array arguments.
Files:
src/engine/ast-support.tssrc/engine/runner.ts
**
⚙️ CodeRabbit configuration file
**: This project uses Archgate — an AI governance framework based on
Architecture Decision Records (ADRs). The ADRs in.archgate/adrs/
are the authoritative rules for this codebase. Each ADR has a companion
.rules.tsfile with automated checks that run viaarchgate check.When reviewing, you must:
- Treat ADR violations as blocking issues, not suggestions.
- Cite the specific ADR ID when flagging a violation (e.g., "Violates ARCH-006").
- Focus on semantic and contextual violations that automated rules cannot catch —
the.rules.tsfiles already cover syntactic/structural patterns.- If you are unsure whether something violates an ADR, flag it as a question
rather than approving it.
Files:
src/engine/ast-support.tssrc/formats/rules.tssrc/engine/git-files.tssrc/helpers/rules-shim.tstests/engine/runner-ast-base.test.tssrc/engine/runner.tssrc/engine/js-parser.ts
src/formats/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Use Zod schemas as the single source of truth; derive types with
z.infer<>instead of defining separate interfaces, usesafeParse(), and reuseAdrFrontmatterSchema.shape.*to avoid duplicating enums.
Files:
src/formats/rules.ts
src/formats/rules.ts
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-022-ast-aware-rule-context.md)
RuleContextmust expose exactly oneast(path, language, opts?)method, with language valuestypescript,javascript,python, orruby; it must not expose per-language AST methods or raw subprocess primitives.
Files:
src/formats/rules.ts
src/engine/git-files.ts
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-023-engine-file-listing-via-in-memory-git-tracked-matching.md)
getGitTrackedFilesmust define the tracked-file universe usinggit ls-files --cached --others --exclude-standardminusgit ls-files --deleted; the deleted-file subtraction is mandatory.
Files:
src/engine/git-files.ts
src/engine/{glob-utils,git-files}.ts
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-023-engine-file-listing-via-in-memory-git-tracked-matching.md)
src/engine/{glob-utils,git-files}.ts:Bun.Glob#scan()is permitted only as a fallback when no tracked set exists, such as for non-Git targets or whenrespectGitignore: false; no other engine file may call it.
All remainingBun.Glob#scan()fallback calls must pass{ dot: true }.
Files:
src/engine/git-files.ts
src/engine/{runner,git-files}.ts
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-022-ast-aware-rule-context.md)
src/engine/{runner,git-files}.ts: Base-revision AST access must use the merge base of--baseand HEAD, preserve the same guardrail ordering, and confine git reads togit-files.ts;ast(..., { rev: "base" })must throw on missing bases or absent files, whilefileAtBase()must returnnull.
Rule code must access base content only throughast(path, language, { rev: "base" })orfileAtBase()and must never spawn git or interpreters directly.
Files:
src/engine/git-files.tssrc/engine/runner.ts
src/helpers/rules-shim.ts
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-022-ast-aware-rule-context.md)
The generated
.rules.tsauthoring shim must mirror the singleRuleContext.ast()API and must not expose raw subprocess or filesystem primitives.
Files:
src/helpers/rules-shim.ts
tests/**/*.test.ts
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-005-testing-standards.md)
tests/**/*.test.ts: Use Bun's built-in test runner (bun:test) for all test files, and place tests undertests/mirroring thesrc/directory structure with<module-name>.test.tsnaming.
Use temp directories (mkdtemp) for filesystem tests, and clean them up inafterEachorafterAll.
Close external SDK instances (servers, clients, transports, connections) inafterEachorafterAll, managing their lifecycle in hooks rather than inside individual test bodies.
When a test creates a temporary git repository and runsgit commit, configure localuser.emailanduser.nameimmediately aftergit init.
Test public module interfaces, not private implementation details.
Use descriptive test names that explain the expected behavior.
Every runnabletest()/it()must contain at least oneexpect()assertion; smoke tests must make the contract explicit withexpect(() => fn()).not.toThrow()orawait expect(promise).resolves.toBeUndefined().
Usetest.skip,test.skipIf, ortest.todofor intentionally empty or disabled tests; do not use barereturnor empty callbacks to skip work.
If the firstexpect()is being added to a previously assertion-less test file, addexpectto thebun:testimport.
When mockingfetchin tests, assign directly toglobalThis.fetchand restore the original or usemock.restore()afterward.
WrapspyOn()and inlinemockImplementation()usage intry/finally, or create and restore spies in hooks, somockRestore()always runs.
Only raise a per-test timeout above the globalbun test --timeout 60000; never set a shorter per-test timeout.
Mock first-party modules withimport * as modplusspyOn(mod, "fn"), notmock.module().
When a test needs to redirect user-scope paths, mockos.homedir()instead of relying onHOME/Bun.env.HOME; restore the spy in test hooks.
Do not depend on network access in unit tests.
Do not leave temp files after test runs.
Do not leave external SDK instances open after tests...
Files:
tests/engine/runner-ast-base.test.ts
tests/**/*.ts
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-009-platform-detection-helper.md)
In test files, use
_resetPlatformCache()to simulate different platforms instead of mocking or mutatingprocess.platformdirectly.
Files:
tests/engine/runner-ast-base.test.ts
tests/engine/runner-ast*.test.ts
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-022-ast-aware-rule-context.md)
AST behavior must be covered by tests, including per-language parsing, BOM handling, interpreter and parse failures, guardrail behavior, isolation from shadow modules, base-revision parsing, structural equivalence, and
ast()throw versusfileAtBase()null semantics.
Files:
tests/engine/runner-ast-base.test.ts
src/engine/runner.ts
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-022-ast-aware-rule-context.md)
src/engine/runner.ts:createRuleContext()must implement AST dispatch internally, and Python/Ruby AST requests must perform guardrails in this exact order before spawning: path safety, language plausibility, interpreter availability, and guarded invocation.
Python AST subprocesses must use isolated mode (python -I -c ...), and Python/Ruby interpreter availability must be probed once and cached percheckinvocation.
ctx.ast()must throw on missing interpreters or parse failures, with distinguishable error messages; it must never returnnullor silently downgrade failures.
AST parsing must strip a leading UTF-8 BOM for Python and Ruby sources before parsing.
Files:
src/engine/runner.ts
🧠 Learnings (2)
📚 Learning: 2026-07-02T16:03:33.031Z
Learnt from: rhuanbarreto
Repo: archgate/cli PR: 446
File: src/helpers/session-context-opencode.ts:81-100
Timestamp: 2026-07-02T16:03:33.031Z
Learning: For synchronous helper functions that use Bun’s sqlite sync API (i.e., they must remain synchronous), it’s acceptable to use `existsSync` from `node:fs` to check whether the SQLite database file exists. Avoid using `Bun.file(path).exists()` for this purpose because it’s async and would force the helper to become async (no equivalent synchronous Bun alternative). If the DB file is missing, throw/return a clear, actionable "No database found" error (per ARCH-006) rather than letting the sqlite open fail with a generic DB-open error.
Applied to files:
src/helpers/rules-shim.ts
📚 Learning: 2026-07-11T13:03:15.386Z
Learnt from: rhuanbarreto
Repo: archgate/cli PR: 467
File: .archgate/adrs/ARCH-011-consistent-project-root-resolution.md:0-0
Timestamp: 2026-07-11T13:03:15.386Z
Learning: For Markdown files formatted by oxfmt (especially ADRs), avoid inline code spans that contain escaped backticks, e.g. `\`...\`` inside a single `` `...` `` span. oxfmt may mis-parse these and, on re-format, can collapse spaces after later inline code spans on the same line, effectively removing any manually re-added spacing. Instead, rephrase the text so the message stays plain quoted text, and put any embedded command/fragment that needs code formatting (e.g., `archgate init`) in its own separate inline code span; keep surrounding punctuation/spacing outside the code span.
Applied to files:
.archgate/adrs/ARCH-022-ast-aware-rule-context.md
🪛 LanguageTool
.archgate/adrs/ARCH-022-ast-aware-rule-context.md
[style] ~97-~97: Consider an alternative for the overused word “exactly”.
Context: ...reter from a .rules.ts file — that is exactly the sandbox escape [ARCH-024](./ARCH-02...
(EXACTLY_PRECISELY)
[style] ~98-~98: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...eAtBase()are the sanctioned path. - **DON'T** returnnullfromast({ rev: "ba...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
🔇 Additional comments (7)
src/formats/rules.ts (1)
80-82: LGTM!Also applies to: 158-165
src/helpers/rules-shim.ts (1)
75-84: LGTM!Also applies to: 156-162
.archgate/adrs/ARCH-022-ast-aware-rule-context.md (1)
51-65: LGTM!Also applies to: 83-85, 97-98, 126-127, 140-141, 161-161
src/engine/git-files.ts (1)
321-345: LGTM!Also applies to: 357-364, 377-383
src/engine/ast-support.ts (1)
211-237: LGTM!Also applies to: 276-302
src/engine/js-parser.ts (1)
42-69: LGTM!src/engine/runner.ts (1)
8-8: LGTM!Also applies to: 25-41, 142-143, 187-216, 238-242, 266-306, 392-406, 474-478, 527-528
…e }) Comment-governance rules can now work against structured comment tokens instead of fragile line-by-line regex — the comments-in-AST half of #479. The returned tree carries a `comments` array of { type: "line" | "block"; value: string; loc } when the flag is set. Folded into ast() rather than a separate method, so it runs inside the same four-guardrail flow (ast-guardrail-ordering covers it) and single-ast-method stays satisfied — the catch-all signature is unchanged. - typescript/javascript/python supported; ruby throws a clear "not supported yet" (Ripper.lex is a deferred follow-up). - value has delimiters stripped (//, /* */, #); Python has only line comments. - TS/JS comments are scanned from the ORIGINAL source (extractJsComments in js-parser.ts), because Bun.Transpiler strips them before meriyah — which makes comment loc original-source-accurate even for TS, unlike the tree's transpiled-relative loc. String/template aware; regex literals are a known blind spot. - Python comments come from tokenize via a second serializer that prints {_tree, comments}, unwrapped by the engine; same convert() preamble, same mandatory -I isolation. No new subprocess site and no new guardrail. Also dedups the grep line-scan into glob-utils.matchLines. Amends ARCH-022; coverage in tests/engine/runner-ast-comments.test.ts. Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_63e8f7a2-fa7d-4815-a0f2-0e9a56322361) |
… allowlist Covers the user-facing surface of this PR and the previously-undocumented sandbox change from #477, across all three locales (en, nb, pt-br) per the GEN-002 same-changeset i18n requirement. reference/rule-api.mdx - fileAtBase() method; AstOptions { rev, comments }; CommentToken type - ast() section: base-revision parsing, comment collection (original-source loc, string-awareness, Python line-only), the two new throw cases - AstNode: note the opt-in comments array guides/writing-rules.mdx - ctx.ast opts + ctx.fileAtBase entries - worked examples: documentation-only-change detection via { rev: "base" }, and comment governance via { comments: true } - note that rule files may import only the safe four modules guides/security.mdx (#477 gap — was still describing the old denylist) - rewrite the sandbox section from denylist to allowlist model - correct the now-wrong claims (literal dynamic imports ARE blocked; the scanner sees through escapes) and add require/import.meta.require, process.binding, Trojan-Source Unicode, and imported-rule scanning - reframe the "review untrusted rules" note: strong first line of defense, not a complete sandbox (Reflect.get indirection remains a residual) Cross-page anchors normalized to be locale-agnostic. llms-full.txt regenerated. Validated: 44/44 ADR rules incl. GEN-002 i18n parity + drift. Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_81f00788-7675-47f5-a512-382bca52448c) |
There was a problem hiding this comment.
Actionable comments posted: 10
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/src/content/docs/guides/security.mdx`:
- Around line 46-53: Qualify the capability restrictions in
docs/src/content/docs/guides/security.mdx:46-53 and
docs/src/content/docs/nb/guides/security.mdx:46-53 as blocking recognized or
direct access paths, rather than guaranteeing a complete sandbox. Keep and align
the existing global-object indirection bypass warnings at
docs/src/content/docs/guides/security.mdx:133-136 and
docs/src/content/docs/nb/guides/security.mdx:133-136 with that qualification,
preserving equivalent English and Norwegian Bokmål meaning.
In `@docs/src/content/docs/guides/writing-rules.mdx`:
- Line 480: Update the no-base explanation near the Archgate command example:
state that ctx.changedFiles may include auto-detected working-tree changes, but
the rule becomes a no-op because ctx.fileAtBase(file) returns null without a
base reference. Keep the existing explanation about git and interpreter access
unchanged.
- Around line 450-452: Update the “Comparing against the base revision”
documentation to remove Python docstrings from the claim that comment-only edits
produce identical ASTs. Limit the example to comments and formatting, or
explicitly describe normalizing Python docstrings before comparing the ASTs.
In `@docs/src/content/docs/nb/reference/rule-api.mdx`:
- Around line 220-236: Document how to normalize positional metadata such as
loc, range, lineno, and related fields before comparing ASTs, or expose a
structural comparator that performs this normalization, in
docs/src/content/docs/nb/reference/rule-api.mdx lines 220-236. Update the
examples in docs/src/content/docs/nb/guides/writing-rules.mdx lines 450-467 and
docs/src/content/docs/pt-br/guides/writing-rules.mdx lines 450-467 to use the
normalized structural comparison instead of full AST equality.
In `@docs/src/content/docs/pt-br/guides/security.mdx`:
- Line 22: Update the security guide sentence describing rule execution to
remove the “sandbox de runtime” claim and instead reference the restricted
RuleContext API alongside the static security scanner. Preserve the explanation
that rules run in-process with the invoking user’s privileges and that imports
are controlled by an allowlist.
In `@docs/src/content/docs/pt-br/reference/rule-api.mdx`:
- Around line 227-233: The example’s changed-file comparison must guard the base
AST lookup with fileAtBase() before calling ctx.ast(..., { rev: "base" }).
Update the loop around structurallyEqual so files absent at the base, or runs
without a resolved base, are skipped when fileAtBase() returns null; retain
comparison and reporting for files present at the base.
In `@src/engine/glob-utils.ts`:
- Around line 15-33: Update matchLines to clone the supplied RegExp and use
exec() per line, resetting lastIndex before each execution, so global patterns
retain their actual match index. Preserve the existing GrepMatch construction
and one-based line and column values.
In `@src/engine/js-parser.ts`:
- Around line 87-97: Update the line-comment scanning loop in the JavaScript
parser to stop advancing on either "\n" or "\r", so comment values exclude all
line terminators while preserving the existing location and comment handling.
In `@src/engine/runner.ts`:
- Around line 222-225: Move the Ruby comment rejection in
createRuleContext()/ctx.ast() to after the language plausibility check. Preserve
ARCH-022 ordering: safePath, language-versus-extension/content plausibility
validation, interpreter availability probing, then guarded invocation; only
perform commentsUnsupportedError(language, path) after plausibility succeeds.
In `@tests/engine/runner-ast-comments.test.ts`:
- Around line 98-123: Extend the test “typescript: a comment marker inside a
string is not a comment” to include a TypeScript template literal containing
both // and /* ... */ markers, plus one genuine surrounding comment. Assert that
comment extraction returns only the real comment, preserving coverage for
template-aware original-source scanning required by ARCH-022.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 02f17d64-3242-4d23-b53a-1bd2750d956d
📒 Files selected for processing (18)
.archgate/adrs/ARCH-022-ast-aware-rule-context.mddocs/public/llms-full.txtdocs/src/content/docs/guides/security.mdxdocs/src/content/docs/guides/writing-rules.mdxdocs/src/content/docs/nb/guides/security.mdxdocs/src/content/docs/nb/guides/writing-rules.mdxdocs/src/content/docs/nb/reference/rule-api.mdxdocs/src/content/docs/pt-br/guides/security.mdxdocs/src/content/docs/pt-br/guides/writing-rules.mdxdocs/src/content/docs/pt-br/reference/rule-api.mdxdocs/src/content/docs/reference/rule-api.mdxsrc/engine/ast-support.tssrc/engine/glob-utils.tssrc/engine/js-parser.tssrc/engine/runner.tssrc/formats/rules.tssrc/helpers/rules-shim.tstests/engine/runner-ast-comments.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (2)
- GitHub Check: Smoke Test (Windows) / Windows
- GitHub Check: Cloudflare Pages
🧰 Additional context used
📓 Path-based instructions (26)
src/**/*.ts
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-003-output-formatting.md)
src/**/*.ts: UsestyleText(format, text)fromnode:utilfor all terminal colors and formatting in CLI source files; do not use raw ANSI escape codes or third-party color libraries.
Commands that produce structured results and support--jsonmust emit machine-readable JSON to stdout with no colors or decorative formatting.
When a command supports--json, useformatJSON()fromsrc/helpers/output.tsfor JSON serialization, and passforcePretty: truewhen the user explicitly provided--json.
UseisAgentContext()fromsrc/helpers/output.tsto enable auto-JSON behavior for commands that support both human-readable and JSON output modes.
CLI output must not include emoji; use text symbols and colors instead.
Send normal command output to stdout withconsole.log(), and send errors, warnings, and debug messages to stderr vialogError(),logWarn(), andlogDebug().
Keep CLI output concise and scannable by using whitespace and alignment instead of long text blocks.
RespectNO_COLORautomatically by relying onstyleText; do not add custom color-environment handling in CLI code.
Do not output progress spinners unless there is a TTY check.
Do not assume piped output means agent context whenCIis set; CI runners should still receive human-readable output.
src/**/*.ts: Do not re-export symbols from another module in any source file; statements likeexport { X } from "./other"andexport type { X } from "./other"are forbidden.
Import symbols directly from the module that defines them; do not import from a directory path such as../formatsexpecting implicitindex.tsresolution.Make large production thresholds injectable via an optional parameter that defaults to the module constant, so tests can supply a small value instead of generating huge fixtures.
src/**/*.ts: Useawait Bun.file(path).json()when reading JSON files in Bun TypeScript source code; do not useJSON.parse(await Bun.file(path).text())or `JSON.parse(fs.readFile...
Files:
src/engine/glob-utils.tssrc/engine/js-parser.tssrc/helpers/rules-shim.tssrc/formats/rules.tssrc/engine/runner.tssrc/engine/ast-support.ts
**/*.{ts,tsx,js,jsx,mjs,cjs}
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-006-dependency-policy.md)
**/*.{ts,tsx,js,jsx,mjs,cjs}: Use Bun built-ins for file I/O (Bun.file,Bun.write), HTTP, subprocess execution (Bun.spawn), globbing (Bun.Glob), and testing (bun:test).
Do not use Node.js-specific APIs when Bun alternatives exist; for example, useBun.file()instead offs.readFile()for simple reads.
Prefernode:built-in modules such asnode:util,node:path, andnode:fsover npm alternatives.
Do not use utility libraries for single functions, such as importing lodash for one helper likepick.
Do not use path aliases (tsconfig paths); use relative imports with Bun's native module resolution.
Do not install packages globally during development; usebunxfor one-off tools.
Files:
src/engine/glob-utils.tstests/engine/runner-ast-comments.test.tssrc/engine/js-parser.tssrc/helpers/rules-shim.tssrc/formats/rules.tssrc/engine/runner.tssrc/engine/ast-support.ts
src/**/!(*platform).ts
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-009-platform-detection-helper.md)
src/**/!(*platform).ts: Insrc/TypeScript source files, do not readprocess.platformdirectly; usesrc/helpers/platform.ts(isWindows(),isMacOS(),isLinux(),isWSL(),getPlatformInfo()) for all platform detection.
Use the centralized platform helper instead of duplicating OS/WSL detection logic inline anywhere insrc/TypeScript source.
When behavior differs between Linux and Windows, account for WSL by usingisWSL()rather than assuming `
Files:
src/engine/glob-utils.tssrc/engine/js-parser.tssrc/helpers/rules-shim.tssrc/formats/rules.tssrc/engine/runner.tssrc/engine/ast-support.ts
{src,tests}/**/*.ts
📄 CodeRabbit inference engine (.archgate/adrs/LEGAL-001-spdx-license-headers.md)
{src,tests}/**/*.ts: Every TypeScript source file insrc/andtests/must begin with// SPDX-License-Identifier: Apache-2.0followed by// Copyright 2026 Archgate.
If a TypeScript file has a shebang line (for example#!/usr/bin/env buninsrc/cli.ts), the SPDX license header must appear immediately after the shebang.
Use single-line//comments for the SPDX header; do not use block comments (/* */) or alternate license identifiers.
Files:
src/engine/glob-utils.tstests/engine/runner-ast-comments.test.tssrc/engine/js-parser.tssrc/helpers/rules-shim.tssrc/formats/rules.tssrc/engine/runner.tssrc/engine/ast-support.ts
src/{helpers,engine}/**/*.ts
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-002-error-handling.md)
Do not use
console.log(),console.warn(), orconsole.info()directly in helper or engine files; uselogInfo()orlogWarn()instead.
Files:
src/engine/glob-utils.tssrc/engine/js-parser.tssrc/helpers/rules-shim.tssrc/engine/runner.tssrc/engine/ast-support.ts
src/engine/**/*.ts
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-023-engine-file-listing-via-in-memory-git-tracked-matching.md)
src/engine/**/*.ts: In the rules engine, list project files by matching glob patterns in memory against the git-tracked file set rather than walking the filesystem.
Route new engine file listings throughlistMatchingFilesfor rule-facing inputs ormatchTrackedFilesfor trusted ADR frontmatter patterns.
When the target is a Git repository andrespectGitignoreis not false, pass the tracked set fromgetGitTrackedFilesto matching operations.
Per-runRunCachesmust share glob results keyed by pattern and tracked mode and file text keyed by absolute path; cached promises should share in-flight work, and returned glob arrays must be copied before exposing them to rules.
Do not cachereadJSONresults because rules receive mutable objects whose shared mutation could leak between rules.
Do not filter filesystem scan results against the tracked set as a substitute for in-memory matching, and do not hardcode ignore directories; use the Git-derived tracked set instead.
src/engine/**/*.ts: Engine code MUST NOT introduce unsanctioned subprocess access: do not usechild_process,Bun.$, or shell-interpolated commands; subprocesses for AST parsing belong only to the sanctioned AST support, and git subprocesses belong only togit-files.ts.
Rule execution code MUST NOT expose or directly invokeBun.spawn,child_process, interpreters, or git from.rules.ts; rules must usectx.ast()orfileAtBase()for structural and base-revision access.
Python and Ruby serializers MUST strip a leading UTF-8 BOM before parsing; Python AST subprocesses MUST use the standard-library facility under-Iisolation, and Ruby must use built-in Ripper/JSON serialization.
Files:
src/engine/glob-utils.tssrc/engine/js-parser.tssrc/engine/runner.tssrc/engine/ast-support.ts
src/engine/glob-utils.ts
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-023-engine-file-listing-via-in-memory-git-tracked-matching.md)
src/engine/glob-utils.ts:matchTrackedFilesandlistMatchingFilesmust perform tracked-file matching withBun.Glob#match().
listMatchingFilesmust validate the original pattern and every brace-expanded alternative withsafeGlobbefore either matching tracked files or scanning fallback files.
Files:
src/engine/glob-utils.ts
src/engine/{glob-utils,git-files}.ts
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-023-engine-file-listing-via-in-memory-git-tracked-matching.md)
src/engine/{glob-utils,git-files}.ts:Bun.Glob#scan()is permitted only as a fallback when no tracked set exists, such as for non-Git targets or whenrespectGitignore: false; no other engine file may call it.
All remainingBun.Glob#scan()fallback calls must pass{ dot: true }.
Files:
src/engine/glob-utils.ts
**
⚙️ CodeRabbit configuration file
**: This project uses Archgate — an AI governance framework based on
Architecture Decision Records (ADRs). The ADRs in.archgate/adrs/
are the authoritative rules for this codebase. Each ADR has a companion
.rules.tsfile with automated checks that run viaarchgate check.When reviewing, you must:
- Treat ADR violations as blocking issues, not suggestions.
- Cite the specific ADR ID when flagging a violation (e.g., "Violates ARCH-006").
- Focus on semantic and contextual violations that automated rules cannot catch —
the.rules.tsfiles already cover syntactic/structural patterns.- If you are unsure whether something violates an ADR, flag it as a question
rather than approving it.
Files:
src/engine/glob-utils.tsdocs/src/content/docs/pt-br/guides/security.mdxdocs/src/content/docs/guides/security.mdxdocs/src/content/docs/nb/guides/security.mdxdocs/src/content/docs/pt-br/guides/writing-rules.mdxdocs/src/content/docs/guides/writing-rules.mdxdocs/src/content/docs/nb/guides/writing-rules.mdxtests/engine/runner-ast-comments.test.tssrc/engine/js-parser.tsdocs/src/content/docs/nb/reference/rule-api.mdxsrc/helpers/rules-shim.tsdocs/src/content/docs/reference/rule-api.mdxsrc/formats/rules.tssrc/engine/runner.tsdocs/public/llms-full.txtdocs/src/content/docs/pt-br/reference/rule-api.mdxsrc/engine/ast-support.ts
docs/src/content/docs/**/*.mdx
📄 CodeRabbit inference engine (.archgate/adrs/GEN-001-documentation-site.md)
docs/src/content/docs/**/*.mdx: Use MDX (.mdx) for all content pages underdocs/src/content/docs/.
Escape literal curly braces in MDX when showing template syntax; do not use bare{}in prose or code-fence labels.
Files:
docs/src/content/docs/pt-br/guides/security.mdxdocs/src/content/docs/guides/security.mdxdocs/src/content/docs/nb/guides/security.mdxdocs/src/content/docs/pt-br/guides/writing-rules.mdxdocs/src/content/docs/guides/writing-rules.mdxdocs/src/content/docs/nb/guides/writing-rules.mdxdocs/src/content/docs/nb/reference/rule-api.mdxdocs/src/content/docs/reference/rule-api.mdxdocs/src/content/docs/pt-br/reference/rule-api.mdx
{docs/src/content/docs/**/*.mdx,docs/astro.config.mjs}
📄 CodeRabbit inference engine (.archgate/adrs/GEN-001-documentation-site.md)
When adding a new documentation page, create the MDX file in
docs/src/content/docs/<category>/<slug>.mdxand add the page todocs/astro.config.mjssidebar configuration.
Files:
docs/src/content/docs/pt-br/guides/security.mdxdocs/src/content/docs/guides/security.mdxdocs/src/content/docs/nb/guides/security.mdxdocs/src/content/docs/pt-br/guides/writing-rules.mdxdocs/src/content/docs/guides/writing-rules.mdxdocs/src/content/docs/nb/guides/writing-rules.mdxdocs/src/content/docs/nb/reference/rule-api.mdxdocs/src/content/docs/reference/rule-api.mdxdocs/src/content/docs/pt-br/reference/rule-api.mdx
docs/src/content/docs/**
📄 CodeRabbit inference engine (.archgate/adrs/GEN-001-documentation-site.md)
Do not create documentation content files outside
docs/src/content/docs/; Starlight content must live in that exact directory structure.
Files:
docs/src/content/docs/pt-br/guides/security.mdxdocs/src/content/docs/guides/security.mdxdocs/src/content/docs/nb/guides/security.mdxdocs/src/content/docs/pt-br/guides/writing-rules.mdxdocs/src/content/docs/guides/writing-rules.mdxdocs/src/content/docs/nb/guides/writing-rules.mdxdocs/src/content/docs/nb/reference/rule-api.mdxdocs/src/content/docs/reference/rule-api.mdxdocs/src/content/docs/pt-br/reference/rule-api.mdx
docs/src/content/docs/**/*.{mdx,md}
📄 CodeRabbit inference engine (.archgate/adrs/GEN-002-docs-i18n.md)
docs/src/content/docs/**/*.{mdx,md}: For every English docs page underdocs/src/content/docs/, create a translated file in each locale directory with the exact same relative path and filename, and ensure every locale file corresponds to an existing root file (no orphan translations).
When adding or modifying English documentation content, update the corresponding locale files in the same pull request.
Translate all user-facing prose in docs pages, including titles, descriptions, headings, paragraphs, list items, table text, and admonition content.
Translate user-visible text props in Starlight components such as<Card title="...">and<LinkCard description="...">.
Keep code blocks, CLI commands, file paths, TypeScript identifiers, technical terms, import statements, component names, andlink/href/slugattribute values in English.
Keep internal links unchanged and do not add locale prefixes (for example, use/guides/...rather than/pt-br/guides/...).
Preserve MDX curly-brace escaping (\{\}) in translated content.
Preserve Starlight component import statements identically in translated files.
Files:
docs/src/content/docs/pt-br/guides/security.mdxdocs/src/content/docs/guides/security.mdxdocs/src/content/docs/nb/guides/security.mdxdocs/src/content/docs/pt-br/guides/writing-rules.mdxdocs/src/content/docs/guides/writing-rules.mdxdocs/src/content/docs/nb/guides/writing-rules.mdxdocs/src/content/docs/nb/reference/rule-api.mdxdocs/src/content/docs/reference/rule-api.mdxdocs/src/content/docs/pt-br/reference/rule-api.mdx
docs/src/content/docs/pt-br/**/*.{mdx,md}
📄 CodeRabbit inference engine (.archgate/adrs/GEN-002-docs-i18n.md)
Use correct Portuguese diacritical marks in Brazilian Portuguese translations; never write unaccented Portuguese.
Files:
docs/src/content/docs/pt-br/guides/security.mdxdocs/src/content/docs/pt-br/guides/writing-rules.mdxdocs/src/content/docs/pt-br/reference/rule-api.mdx
docs/src/content/docs/nb/**/*.{mdx,md}
📄 CodeRabbit inference engine (.archgate/adrs/GEN-002-docs-i18n.md)
Use Norwegian Bokmål (not Nynorsk) for Norwegian translations, with the informal
duform and correct Norwegian characters (æ,ø,å).
Files:
docs/src/content/docs/nb/guides/security.mdxdocs/src/content/docs/nb/guides/writing-rules.mdxdocs/src/content/docs/nb/reference/rule-api.mdx
tests/**/*.test.ts
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-005-testing-standards.md)
tests/**/*.test.ts: Use Bun's built-in test runner (bun:test) for all test files, and place tests undertests/mirroring thesrc/directory structure with<module-name>.test.tsnaming.
Use temp directories (mkdtemp) for filesystem tests, and clean them up inafterEachorafterAll.
Close external SDK instances (servers, clients, transports, connections) inafterEachorafterAll, managing their lifecycle in hooks rather than inside individual test bodies.
When a test creates a temporary git repository and runsgit commit, configure localuser.emailanduser.nameimmediately aftergit init.
Test public module interfaces, not private implementation details.
Use descriptive test names that explain the expected behavior.
Every runnabletest()/it()must contain at least oneexpect()assertion; smoke tests must make the contract explicit withexpect(() => fn()).not.toThrow()orawait expect(promise).resolves.toBeUndefined().
Usetest.skip,test.skipIf, ortest.todofor intentionally empty or disabled tests; do not use barereturnor empty callbacks to skip work.
If the firstexpect()is being added to a previously assertion-less test file, addexpectto thebun:testimport.
When mockingfetchin tests, assign directly toglobalThis.fetchand restore the original or usemock.restore()afterward.
WrapspyOn()and inlinemockImplementation()usage intry/finally, or create and restore spies in hooks, somockRestore()always runs.
Only raise a per-test timeout above the globalbun test --timeout 60000; never set a shorter per-test timeout.
Mock first-party modules withimport * as modplusspyOn(mod, "fn"), notmock.module().
When a test needs to redirect user-scope paths, mockos.homedir()instead of relying onHOME/Bun.env.HOME; restore the spy in test hooks.
Do not depend on network access in unit tests.
Do not leave temp files after test runs.
Do not leave external SDK instances open after tests...
Files:
tests/engine/runner-ast-comments.test.ts
tests/**/*.ts
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-009-platform-detection-helper.md)
In test files, use
_resetPlatformCache()to simulate different platforms instead of mocking or mutatingprocess.platformdirectly.
Files:
tests/engine/runner-ast-comments.test.ts
**/*.{test,spec}.ts
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-022-ast-aware-rule-context.md)
AST context behavior MUST be covered by tests, including per-language parsing, guardrail behavior, interpreter failures, base-revision throw-versus-null semantics, comment extraction, original-source locations, and Ruby comment rejection.
Files:
tests/engine/runner-ast-comments.test.ts
src/engine/{runner,ast-support,js-parser}.ts
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-022-ast-aware-rule-context.md)
TypeScript and JavaScript AST parsing MUST reuse the existing in-process
meriyahparser. The duplicatedparseModule()logic inrule-scanner.tsMUST be factored into one shared exported helper used by both the scanner andctx.ast().
Files:
src/engine/js-parser.tssrc/engine/runner.tssrc/engine/ast-support.ts
src/helpers/rules-shim.ts
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-022-ast-aware-rule-context.md)
The generated
.rules.tsauthoring shim MUST mirror the singleRuleContext.ast()method and must not expose raw subprocess or filesystem primitives.
Files:
src/helpers/rules-shim.ts
docs/src/content/docs/reference/**/*.mdx
📄 CodeRabbit inference engine (.archgate/adrs/GEN-001-documentation-site.md)
Keep reference pages accurate to the CLI source code; when CLI APIs change, update the corresponding reference docs in the same PR.
Files:
docs/src/content/docs/reference/rule-api.mdx
src/formats/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Use Zod schemas as the single source of truth; derive types with
z.infer<>instead of defining separate interfaces, usesafeParse(), and reuseAdrFrontmatterSchema.shape.*to avoid duplicating enums.
Files:
src/formats/rules.ts
src/formats/rules.ts
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-022-ast-aware-rule-context.md)
RuleContextMUST expose exactly oneast(path, language, opts?)method supportingtypescript,javascript,python, andruby; do not add per-language AST methods.
Files:
src/formats/rules.ts
src/engine/runner.ts
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-022-ast-aware-rule-context.md)
src/engine/runner.ts:createRuleContext()MUST implementctx.ast()dispatch internally and execute guardrails in this order before subprocess invocation:safePath, language plausibility validation, interpreter availability probing, then guarded invocation.
Python and Ruby AST parsing MUST useBun.spawnwith array-based arguments; Python MUST run in isolated mode with-I, and interpreter candidates MUST be platform-appropriate and cached once per check invocation.
ctx.ast()MUST reject implausible language/file combinations before invoking Python or Ruby; for example, a Python request forconfig.jsonmust fail without invoking the interpreter.
ctx.ast()MUST throw on missing interpreters and parse failures, with distinguishable error messages; it must never returnnullor another silent-failure sentinel.
Files:
src/engine/runner.ts
src/engine/{runner,ast-support,git-files}.ts
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-022-ast-aware-rule-context.md)
Base-revision AST access MUST use the resolved merge base of
--baseand HEAD; git reads must remain ingit-files.ts, while parsing must continue through the same AST guardrails and sanctioned helpers.
Files:
src/engine/runner.tssrc/engine/ast-support.ts
src/engine/{runner,ast-support}.ts
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-022-ast-aware-rule-context.md)
src/engine/{runner,ast-support}.ts:ast(path, language, { rev: "base" })MUST throw distinguishable errors when no base exists or the file did not exist at the base;fileAtBase(path)MUST returnnullfor those absence cases.
With{ comments: true },ast()MUST attach structured comments as{ type, value, loc }; comments are opt-in, Ruby comments are currently unsupported and must throw, and TypeScript/JavaScript locations must be derived from the original source.
The returned AST shape MUST remain language-native: ESTree for TypeScript/JavaScript, Python's standardastrepresentation, and Ruby's Ripper s-expression; do not normalize Python or Ruby into ESTree.
Files:
src/engine/runner.tssrc/engine/ast-support.ts
🧠 Learnings (2)
📚 Learning: 2026-07-02T16:03:33.031Z
Learnt from: rhuanbarreto
Repo: archgate/cli PR: 446
File: src/helpers/session-context-opencode.ts:81-100
Timestamp: 2026-07-02T16:03:33.031Z
Learning: For synchronous helper functions that use Bun’s sqlite sync API (i.e., they must remain synchronous), it’s acceptable to use `existsSync` from `node:fs` to check whether the SQLite database file exists. Avoid using `Bun.file(path).exists()` for this purpose because it’s async and would force the helper to become async (no equivalent synchronous Bun alternative). If the DB file is missing, throw/return a clear, actionable "No database found" error (per ARCH-006) rather than letting the sqlite open fail with a generic DB-open error.
Applied to files:
src/helpers/rules-shim.ts
📚 Learning: 2026-07-11T13:03:15.386Z
Learnt from: rhuanbarreto
Repo: archgate/cli PR: 467
File: .archgate/adrs/ARCH-011-consistent-project-root-resolution.md:0-0
Timestamp: 2026-07-11T13:03:15.386Z
Learning: For Markdown files formatted by oxfmt (especially ADRs), avoid inline code spans that contain escaped backticks, e.g. `\`...\`` inside a single `` `...` `` span. oxfmt may mis-parse these and, on re-format, can collapse spaces after later inline code spans on the same line, effectively removing any manually re-added spacing. Instead, rephrase the text so the message stays plain quoted text, and put any embedded command/fragment that needs code formatting (e.g., `archgate init`) in its own separate inline code span; keep surrounding punctuation/spacing outside the code span.
Applied to files:
.archgate/adrs/ARCH-022-ast-aware-rule-context.md
🪛 LanguageTool
docs/src/content/docs/pt-br/guides/security.mdx
[uncategorized] ~24-~24: Pontuação duplicada
Context: ...o import é rejeitado, em qualquer forma -- estático (import ... from), dinâmico ...
(DOUBLE_PUNCTUATION_XML)
[misspelling] ~35-~35: ‘Alias’ é uma forma do verbo ‘aliar’. O advérbio escreve-se “aliás”.
Context: ...ing(), process.dlopen()(em qualquer alias deprocess`) | Sim | | Acesso c...
(EASILY_CONFUSED_RARE_WORDS)
[grammar] ~36-~36: Possível erro de concordância de número.
Context: ...ess) | Sim | | Acesso computado a propriedades (Bun[variável], globalThis[variável]...
(GENERAL_NUMBER_AGREEMENT_ERRORS)
[uncategorized] ~37-~37: Conjunções alternativas ou disjuntivas devem ser separadas por vírgulas.
Context: ...Sim | | Atribuição a globalThis ou process.env | Sim | | Caracteres Unicode bidirecionais ou invisíveis ("Trojan Source") |...
(ALTERNATIVE_CONJUNCTIONS_COMMA)
[uncategorized] ~38-~38: Esta locução deve ser separada por vírgulas.
Context: ...u invisíveis ("Trojan Source") | Sim | Se qualquer um desses padrões ...
(VERB_COMMA_CONJUNCTION)
[style] ~42-~42: Para conferir mais clareza ao seu texto, busque usar uma linguagem mais concisa.
Context: ...ore de sintaxe já parseada, ele enxerga através de escapes: await import("\x6e...") reso...
(ATRAVES_DE_POR_VIA)
[uncategorized] ~44-~44: Se é uma abreviatura, falta um ponto. Se for uma expressão, coloque entre aspas.
Context: ...do você importa regras de terceiros com archgate adr import, cada .rules.ts é escaneado -- com u...
(ABREVIATIONS_PUNCTUATION)
[uncategorized] ~50-~50: Esta conjunção deve ser separada por vírgulas e só deve ser utilizada no início duma frase para efeitos de estilo.
Context: ...ext` é somente leitura. Regras reportam violações mas não podem modificar o codebase. - **Esc...
(VERB_COMMA_CONJUNCTION)
[style] ~51-~51: “segundos de tempo” é um pleonasmo. É preferível dizer “segundos”
Context: ...dos** -- cada regra é encerrada após 30 segundos de tempo de execução. - Afetar outras regras...
(PT_REDUNDANCY_REPLACE_SEGUNDOS_DE_TEMPO)
[uncategorized] ~52-~52: Esta conjunção deve ser separada por vírgulas e só deve ser utilizada no início duma frase para efeitos de estilo.
Context: ...* -- regras de ADRs diferentes rodam em paralelo mas não compartilham estado mutável através...
(VERB_COMMA_CONJUNCTION)
docs/src/content/docs/pt-br/guides/writing-rules.mdx
[uncategorized] ~179-~179: Pontuação duplicada
Context: ...falha de parse ou interpretador ausente -- nunca retorna null. ```typescript co...
(DOUBLE_PUNCTUATION_XML)
[uncategorized] ~194-~194: Se é uma abreviatura, falta um ponto. Se for uma expressão, coloque entre aspas.
Context: ...ase do git** -- a base de merge entre a ref --base e HEAD. Retorna null quand...
(ABREVIATIONS_PUNCTUATION)
[uncategorized] ~194-~194: Pontuação duplicada
Context: ...lquando nenhuma base é resolvida (sem--base`) ou o arquivo não existia na base ...
(DOUBLE_PUNCTUATION_XML)
[uncategorized] ~452-~452: Pontuação duplicada
Context: ... uma alteração é apenas de documentação -- a estrutura executável permanece intoca...
(DOUBLE_PUNCTUATION_XML)
[uncategorized] ~480-~480: Se é uma abreviatura, falta um ponto. Se for uma expressão, coloque entre aspas.
Context: ...} satisfies RuleSet; ``` Isso roda com archgate check --base <ref>; sem uma base, `ctx.changedFiles` fic...
(ABREVIATIONS_PUNCTUATION)
[uncategorized] ~484-~484: Se é uma abreviatura, falta um ponto. Se for uma expressão, coloque entre aspas.
Context: ...m tokens estruturados (type, value, loc) em vez de regex linha a linha. As pos...
(ABREVIATIONS_PUNCTUATION)
[uncategorized] ~499-~499: Pontuação duplicada
Context: ...ent.loc.start.line, }); } } ``` :::note Arquivos de regra podem importar ap...
(DOUBLE_PUNCTUATION_XML)
[uncategorized] ~500-~500: Esta locução deve ser separada por vírgulas, e só deve ser utilizada no início duma frase para efeitos de estilo.
Context: ...e:crypto`. Qualquer coisa que uma regra precise além disso -- parsear uma linguagem, ler uma revis...
(VERB_COMMA_CONJUNCTION)
[uncategorized] ~501-~501: Pontuação duplicada
Context: ...des/security/) para entender o porquê. ::: ## Níveis de severidade Cada regra po...
(DOUBLE_PUNCTUATION_XML)
.archgate/adrs/ARCH-022-ast-aware-rule-context.md
[style] ~108-~108: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...leAtBase()reports them asnull. - **DON'T** expect a comments` array without ...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~109-~109: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ... it is opt-in and absent otherwise. - DON'T request { comments: true } for `...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~110-~110: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...ipper.lex) is a deferred follow-up. - DON'T treat the TS/JS comment scan as re...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~130-~130: Consider an alternative for the overused word “exactly”.
Context: ...t is a mild departure from "the tree is exactly the language-native shape," particularl...
(EXACTLY_PRECISELY)
docs/src/content/docs/pt-br/reference/rule-api.mdx
[uncategorized] ~164-~164: Se é uma abreviatura, falta um ponto. Se for uma expressão, coloque entre aspas.
Context: ...comparação** -- a base de merge entre a ref --base e HEAD, o mesmo commit contr...
(ABREVIATIONS_PUNCTUATION)
[uncategorized] ~222-~222: Pontuação duplicada
Context: ...ileatbase) em vez da árvore de trabalho -- tudo o mais (formato de retorno, contra...
(DOUBLE_PUNCTUATION_XML)
[uncategorized] ~240-~240: Pontuação duplicada
Context: ...e retornada carrega um array comments -- dados estruturados de comentário para r...
(DOUBLE_PUNCTUATION_XML)
[uncategorized] ~267-~267: Se é uma abreviatura, falta um ponto. Se for uma expressão, coloque entre aspas.
Context: ...é uma vantagem deliberada em relação ao loc da própria árvore, que é relativo ao t...
(ABREVIATIONS_PUNCTUATION)
[uncategorized] ~267-~267: Pontuação duplicada
Context: ...anspilado para TypeScript (veja AstNode): os comentários são varridos a partir d...
(DOUBLE_PUNCTUATION_XML)
[uncategorized] ~267-~267: Se é uma abreviatura, falta um ponto. Se for uma expressão, coloque entre aspas.
Context: ...-fonte antes da transpilação, então seu loc nunca diverge. Comentários em Python s...
(ABREVIATIONS_PUNCTUATION)
[uncategorized] ~267-~267: Pontuação duplicada
Context: ... Python são sempre type: "line" (#) -- Python não tem comentários de bloco, e ...
(DOUBLE_PUNCTUATION_XML)
[typographical] ~267-~267: Símbolo sem par: “"” aparentemente está ausente
Context: ... tem comentários de bloco, e docstrings """ são expressões de string na árvore, ...
(UNPAIRED_BRACKETS)
[locale-violation] ~267-~267: “template” é um estrangeirismo. É preferível dizer “modelo”.
Context: ...cript reconhece literais de string e de template, mas não rastreia literais de expressão...
(PT_BARBARISMS_REPLACE_TEMPLATE)
[style] ~267-~267: “dentro de um” é uma expressão prolixa. É preferível dizer “num” ou “em um”.
Context: ...lar, então um delimitador de comentário dentro de um literal regex é um ponto cego conhecido...
(PT_WORDINESS_REPLACE_DENTRO_DE_UM)
🔇 Additional comments (16)
src/formats/rules.ts (1)
70-105: LGTM!Also applies to: 129-130, 153-154, 184-191, 207-223
src/helpers/rules-shim.ts (1)
75-102: LGTM!Also applies to: 126-127, 150-151, 178-184, 199-215
.archgate/adrs/ARCH-022-ast-aware-rule-context.md (1)
51-72: LGTM!Also applies to: 90-94, 106-110, 119-120, 130-130, 140-143, 156-159, 179-179
docs/public/llms-full.txt (1)
2084-2115: LGTM!Also applies to: 2195-2199, 2881-2905, 3153-3204, 5202-5204, 5293-5316, 5336-5343, 5355-5414, 5516-5517
docs/src/content/docs/reference/rule-api.mdx (1)
67-69: LGTM!Also applies to: 158-181, 201-208, 220-279, 382-383
src/engine/ast-support.ts (2)
303-338: The existing secure temporary-file comment still applies.The PID/counter filename and non-exclusive write retain the previously reported symlink and source-disclosure risk.
10-43: LGTM!Also applies to: 73-141, 275-301, 340-387
docs/src/content/docs/guides/writing-rules.mdx (1)
177-201: LGTM!Also applies to: 482-501
docs/src/content/docs/pt-br/reference/rule-api.mdx (1)
67-69: LGTM!Also applies to: 158-208, 220-226, 236-279, 382-383
tests/engine/runner-ast-comments.test.ts (1)
1-97: LGTM!Also applies to: 125-261
docs/src/content/docs/nb/guides/writing-rules.mdx (1)
177-201: LGTM!Also applies to: 482-502
docs/src/content/docs/nb/reference/rule-api.mdx (2)
158-180: LGTM!Also applies to: 201-208, 382-383
67-69: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winAdd
opts?: AstOptionsto theAstLanguageoverload insrc/formats/rules.ts.
Union-typed callers can’t pass the documented options unless this fallback signature includesopts, and the docs already reflect that API.Suggested change
-ast(path: string, language: AstLanguage): Promise<AstNode>; +ast(path: string, language: AstLanguage, opts?: AstOptions): Promise<AstNode>;> Likely an incorrect or invalid review comment.docs/src/content/docs/pt-br/guides/security.mdx (1)
23-53: LGTM!Also applies to: 133-137
docs/src/content/docs/pt-br/guides/writing-rules.mdx (1)
177-201: LGTM!Also applies to: 482-502
src/engine/runner.ts (1)
22-29: LGTM!Also applies to: 45-45, 138-221, 227-393
…dent The "review untrusted rules" note cited Reflect.get(Bun, "spawn") as a residual bypass. The scanner-hardening PR (#481) closes reflective access, so that example would become stale. Replace it with the durable residual — anything built at runtime (a computed property name, a code string) is opaque to a source scan — which holds regardless of which PR merges first. en + nb + pt-br (GEN-002). llms-full regenerated. Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_87341365-b885-424e-b5b9-90956358f7c8) |
…x escapes (#481) ## Summary The module allowlist (#477) stopped rule files from *importing* dangerous modules — but `Bun`, `process`, and the global object are **live globals** in the rule runtime, reachable with no import at all. The scanner blocked the shapes `Bun.spawn` and `Bun[x]`, which is the same losing game a module denylist was. Two fire-tested RCEs walked straight around it, both reported `"pass": true` by `archgate check`: ```js // (1) reflection / aliasing / destructuring / global-object aliases Reflect.get(Bun, "spawn")([...]); // also: const {spawn}=Bun; const B=Bun; // globalThis.Bun.spawn / global.Bun.spawn / self.Bun.spawn // (2) Function constructor via the .constructor chain === eval — bypasses even the module allowlist (() => {}).constructor("return import('node:child_process')")(); ``` ## The fix — apply the allowlist philosophy to globals Block **naming the capability source**, not the shapes of using it. Any code reference to `Bun`, `process`, `globalThis`, `global`, `self`, `Reflect`, `eval`, `Function`, `fetch`, `WebSocket`, `XMLHttpRequest`, `EventSource`, or `require` is refused — in any position except a property-key slot (`foo.process`, `{ process: 1 }` name a property, not the global, and are fine). Blocking the *identifier* closes aliasing, destructuring, and reflection in one rule. `global`/`self` are included because Bun binds the global object under all three names. Additionally block **`.constructor`** access (dotted + computed-literal) on any receiver — the property-chain route to the `Function` constructor (= eval). **This simplified the scanner** (net **−157 lines**): the per-shape `Bun`/`process` member denylists and the separate `eval`/`Function`/`fetch`/`require` call checks are gone, subsumed by the single identifier block. First-party and imported scans **converge** — `scanImportedRuleSource()` now delegates — because a first-party rule runs with full privilege too and a malicious PR can add one. An audit confirmed **zero** of the repo's own `.rules.ts` reference these globals as executable code (every mention is a searched-for string), so there are **no false positives**. ## Known residual (documented + regression-tested) A property name built at runtime — `const c = "constructor"; (() => {})[c]` — is unknowable to a static scanner, and blocking *all* computed access would reject ordinary `arr[i]`/`obj[key]`. That route to eval is left to **execution-time isolation**; the scan is defense-in-depth that raises the bar from a trivial one-liner to runtime string construction, not a jail. A test asserts this residual explicitly so it's a deliberate, known gap. ## Test plan - [x] `tests/engine/rule-scanner-escapes.test.ts` — new "reflective and aliased access to runtime globals" block: aliasing, destructuring, `Reflect.get`, the three global-object aliases, `Object.getOwnPropertyDescriptor`, the Function-constructor chain (dotted + computed-literal), eval/Function/fetch/require aliasing; plus "legitimate global-adjacent code still passes" (`Object.keys`, a property named `process`, a normal `ctx`-only rule) and the explicit computed-variable residual - [x] Fire test — both RCEs now refused end-to-end (`"pass": false`), no payload written - [x] `bun run validate` — 44/44 ADR rules (dogfooded on the repo's own rules), 1527 tests, lint, typecheck, build > [!WARNING] > **BREAKING:** rule files may no longer name `Bun`/`process`/`globalThis`/etc., even for benign reads (`Bun.env`, `process.platform`, `Bun.Glob`). Rules interact with the project only through `ctx`; a rule that genuinely needs such data is a `ctx` feature request. Small false-positive surface: a rule using one of these names as a local variable (`self`, `global`) must rename. ## ADR Amends [ARCH-024](https://github.com/archgate/cli/blob/main/.archgate/adrs/ARCH-024-rule-file-sandbox-boundary.md), clause 4: rewrites the "escapes that name no module" model to "block naming the global," documents the `.constructor` closure, the scan convergence, and the computed-variable-key residual as the static-analysis limit that execution-time isolation answers. ## Doc coordination `guides/security.mdx` currently names `Reflect.get(Bun,"spawn")` as a residual bypass (on `main`, and reworded in #480's rewrite). This PR closes that specific residual, so that note should be updated to reflect the *new* residual (a runtime-computed `.constructor` key). To avoid editing soon-replaced text and redundant trilingual i18n churn here, I'll make that doc update on the #480 branch (which owns the rewritten security section) so the two don't conflict — flagging for whoever sequences the merges. --------- Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_42f369e5-93d1-4cb8-b26f-ddae827a4caf) |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
docs/public/llms-full.txt (1)
5362-5364: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winAlign all base-AST guidance with ARCH-022.
The documentation conflates
ctx.changedFilesdetection with availability of a parseable comparison base, and it shows an unguarded{ rev: "base" }call even though ARCH-022 requires that API to throw for unresolved bases and added files.
docs/public/llms-full.txt#L5362-L5364: checkfileAtBase(file)and require a resolved base before calling base AST parsing.docs/public/llms-full.txt#L3183-L3183: replace the “changedFiles is empty” claim with the actual no-base/throw behavior.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/public/llms-full.txt` around lines 5362 - 5364, Update docs/public/llms-full.txt at lines 5362-5364 to guard base AST parsing with fileAtBase(file), calling ctx.ast(..., { rev: "base" }) only when a resolved base exists; update lines 3183-3183 to describe the actual no-base behavior, including that base parsing throws for unresolved bases or added files rather than claiming changedFiles is empty.Source: Path instructions
docs/src/content/docs/guides/security.mdx (1)
22-22: 🔒 Security & Privacy | 🟠 MajorCorrect the runtime-sandbox wording in both locales.
Rules execute in-process with the invoking user’s privileges; the restricted
RuleContextAPI and static scanner are the relevant controls, not a runtime sandbox.
docs/src/content/docs/guides/security.mdx#L22-L22: replace “runtime sandbox” with accurateRuleContext/static-scanner wording.docs/src/content/docs/nb/guides/security.mdx#L22-L22: apply the equivalent correction in Norwegian Bokmål.Violates ARCH-024.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/src/content/docs/guides/security.mdx` at line 22, Update the security wording in docs/src/content/docs/guides/security.mdx at lines 22-22 to remove the runtime-sandbox claim and describe the restricted RuleContext API and static scanner as the relevant controls; apply the equivalent correction in Norwegian Bokmål at docs/src/content/docs/nb/guides/security.mdx lines 22-22.Source: Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@docs/public/llms-full.txt`:
- Around line 5362-5364: Update docs/public/llms-full.txt at lines 5362-5364 to
guard base AST parsing with fileAtBase(file), calling ctx.ast(..., { rev: "base"
}) only when a resolved base exists; update lines 3183-3183 to describe the
actual no-base behavior, including that base parsing throws for unresolved bases
or added files rather than claiming changedFiles is empty.
In `@docs/src/content/docs/guides/security.mdx`:
- Line 22: Update the security wording in
docs/src/content/docs/guides/security.mdx at lines 22-22 to remove the
runtime-sandbox claim and describe the restricted RuleContext API and static
scanner as the relevant controls; apply the equivalent correction in Norwegian
Bokmål at docs/src/content/docs/nb/guides/security.mdx lines 22-22.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 68cdbad1-b224-419f-8428-ed06ce5b32fe
📒 Files selected for processing (4)
docs/public/llms-full.txtdocs/src/content/docs/guides/security.mdxdocs/src/content/docs/nb/guides/security.mdxdocs/src/content/docs/pt-br/guides/security.mdx
📜 Review details
⏰ Context from checks skipped due to timeout. (3)
- GitHub Check: Analyze (csharp)
- GitHub Check: Smoke Test (Windows) / Windows
- GitHub Check: Cloudflare Pages
🧰 Additional context used
📓 Path-based instructions (7)
docs/src/content/docs/**/*.mdx
📄 CodeRabbit inference engine (.archgate/adrs/GEN-001-documentation-site.md)
docs/src/content/docs/**/*.mdx: Use MDX (.mdx) for all content pages underdocs/src/content/docs/.
Escape literal curly braces in MDX when showing template syntax; do not use bare{}in prose or code-fence labels.
Files:
docs/src/content/docs/guides/security.mdxdocs/src/content/docs/nb/guides/security.mdxdocs/src/content/docs/pt-br/guides/security.mdx
{docs/src/content/docs/**/*.mdx,docs/astro.config.mjs}
📄 CodeRabbit inference engine (.archgate/adrs/GEN-001-documentation-site.md)
When adding a new documentation page, create the MDX file in
docs/src/content/docs/<category>/<slug>.mdxand add the page todocs/astro.config.mjssidebar configuration.
Files:
docs/src/content/docs/guides/security.mdxdocs/src/content/docs/nb/guides/security.mdxdocs/src/content/docs/pt-br/guides/security.mdx
docs/src/content/docs/**
📄 CodeRabbit inference engine (.archgate/adrs/GEN-001-documentation-site.md)
Do not create documentation content files outside
docs/src/content/docs/; Starlight content must live in that exact directory structure.
Files:
docs/src/content/docs/guides/security.mdxdocs/src/content/docs/nb/guides/security.mdxdocs/src/content/docs/pt-br/guides/security.mdx
docs/src/content/docs/**/*.{mdx,md}
📄 CodeRabbit inference engine (.archgate/adrs/GEN-002-docs-i18n.md)
docs/src/content/docs/**/*.{mdx,md}: For every English docs page underdocs/src/content/docs/, create a translated file in each locale directory with the exact same relative path and filename, and ensure every locale file corresponds to an existing root file (no orphan translations).
When adding or modifying English documentation content, update the corresponding locale files in the same pull request.
Translate all user-facing prose in docs pages, including titles, descriptions, headings, paragraphs, list items, table text, and admonition content.
Translate user-visible text props in Starlight components such as<Card title="...">and<LinkCard description="...">.
Keep code blocks, CLI commands, file paths, TypeScript identifiers, technical terms, import statements, component names, andlink/href/slugattribute values in English.
Keep internal links unchanged and do not add locale prefixes (for example, use/guides/...rather than/pt-br/guides/...).
Preserve MDX curly-brace escaping (\{\}) in translated content.
Preserve Starlight component import statements identically in translated files.
Files:
docs/src/content/docs/guides/security.mdxdocs/src/content/docs/nb/guides/security.mdxdocs/src/content/docs/pt-br/guides/security.mdx
**
⚙️ CodeRabbit configuration file
**: This project uses Archgate — an AI governance framework based on
Architecture Decision Records (ADRs). The ADRs in.archgate/adrs/
are the authoritative rules for this codebase. Each ADR has a companion
.rules.tsfile with automated checks that run viaarchgate check.When reviewing, you must:
- Treat ADR violations as blocking issues, not suggestions.
- Cite the specific ADR ID when flagging a violation (e.g., "Violates ARCH-006").
- Focus on semantic and contextual violations that automated rules cannot catch —
the.rules.tsfiles already cover syntactic/structural patterns.- If you are unsure whether something violates an ADR, flag it as a question
rather than approving it.
Files:
docs/src/content/docs/guides/security.mdxdocs/src/content/docs/nb/guides/security.mdxdocs/public/llms-full.txtdocs/src/content/docs/pt-br/guides/security.mdx
docs/src/content/docs/nb/**/*.{mdx,md}
📄 CodeRabbit inference engine (.archgate/adrs/GEN-002-docs-i18n.md)
Use Norwegian Bokmål (not Nynorsk) for Norwegian translations, with the informal
duform and correct Norwegian characters (æ,ø,å).
Files:
docs/src/content/docs/nb/guides/security.mdx
docs/src/content/docs/pt-br/**/*.{mdx,md}
📄 CodeRabbit inference engine (.archgate/adrs/GEN-002-docs-i18n.md)
Use correct Portuguese diacritical marks in Brazilian Portuguese translations; never write unaccented Portuguese.
Files:
docs/src/content/docs/pt-br/guides/security.mdx
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: archgate/cli
Timestamp: 2026-07-16T14:15:19.264Z
Learning: Any proposal to add a bundled multi-language parser or grammar must be documented in a separate ADR, reviewed under the dependency-approval process, and approved before implementation.
🔇 Additional comments (4)
docs/public/llms-full.txt (1)
2084-2115: LGTM!Also applies to: 2195-2199, 2881-2905, 3153-3182, 3185-3204, 5202-5204, 5293-5316, 5336-5343, 5355-5361, 5365-5369, 5373-5414, 5516-5517
docs/src/content/docs/guides/security.mdx (1)
24-53: LGTM!Also applies to: 135-137
docs/src/content/docs/nb/guides/security.mdx (1)
24-46: LGTM!Also applies to: 135-137
docs/src/content/docs/pt-br/guides/security.mdx (1)
48-53: LGTM!Also applies to: 135-137
…l order Addresses CodeRabbit review on PR #480: - ast-support: write base-revision temp sources into a per-call private directory (mkdtempSync, 0700) with exclusive create (`wx`, mode 0600), and remove the whole directory on cleanup — closes the predictable-path symlink/disclosure risk on shared temp dirs. - runner: resolve the merge base once and reuse that SHA for changedFiles, so the change set and base AST reads can never diff different commits. - runner: move the Ruby-comment feature guard after the language plausibility guardrail (ARCH-022 ordering). - glob-utils: matchLines uses a cloned regex + exec() so a global (`/g`) pattern reports the true column instead of collapsing to 1. - js-parser: line comments stop on `\r` too, so `\r\n` files don't leave a trailing carriage return in the comment value. Tests: Bun.write over writeFileSync; recursive location-free AST compare; JavaScript + Ruby base-revision matrix cases; template-literal comment markers; matchLines column regressions. Docs (en/nb/pt-br): teach a location-free structural AST comparison (raw serialization shifts with loc/lineno), guard base-parse examples with fileAtBase(), correct the no-base explanation (fileAtBase null, not empty changedFiles), and qualify the scanner as a static gate rather than a complete runtime sandbox. Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_4fd214c7-5741-4e4e-9c21-c473e9fdc80b) |
…s JSDoc The `AstOptions` doc claimed a comment-only edit "yields an identical tree", but node positions (loc/range, lineno/col_offset) remain in the tree, so a raw comparison differs. Match the guide docs: compare a location-free projection. No behavior change. Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_f81db83c-83de-4881-8c34-2bee84a08746) |
The three literal-language overloads on RuleContext.ast() (typescript |
javascript, python, ruby) all accept opts?: AstOptions, but the
language-agnostic catch-all did not. A caller holding a dynamically-typed
AstLanguage — not a string literal — resolves to that catch-all and got
no editor completion for opts, and could not pass { rev: "base" } or
{ comments: true } to it at all.
Widened the catch-all in both src/formats/rules.ts and
src/helpers/rules-shim.ts (which mirror each other exactly), and updated
ARCH-022's single-ast-method rule to enforce the new byte-exact
three-parameter signature instead of the old two-parameter one.
Purely additive (opts stays optional) — no call site can break.
Fire-tested: reverting the catch-all to the old signature makes the rule
fail with the new message; restoring it passes 4/4 ARCH-022 checks.
Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_2f40b46d-5586-42cd-b032-ead63b964566) |
# archgate ## [0.49.0](v0.48.4...v0.49.0) (2026-07-16) ### ⚠ BREAKING CHANGES * **engine:** block naming runtime globals to close reflective sandbox escapes (#481) * **engine:** close rule-file sandbox escapes via module allowlist (#477) * **cli:** emit lean agent-facing JSON payloads by default (#476) ### Features * **cli:** emit lean agent-facing JSON payloads by default ([#476](#476)) ([04affa3](04affa3)) * **engine:** base-revision + comment access for ctx.ast() (closes [#479](#479)) ([#480](#480)) ([49feb1f](49feb1f)), closes [#477](#477) ### Bug Fixes * **engine:** block naming runtime globals to close reflective sandbox escapes ([#481](#481)) ([6666df2](6666df2)), closes [#477](#477) [#480](#480) * **engine:** close rule-file sandbox escapes via module allowlist ([#477](#477)) ([18db14d](18db14d)) --- This PR was generated with [simple-release](https://github.com/TrigenSoftware/simple-release). <details> <summary>📄 Cheatsheet</summary> <br> You can configure the bot's behavior through a pull request comment using the `!simple-release/set-options` command. ### Command Format ````md !simple-release/set-options ```json { "bump": {}, "publish": {} } ``` ```` ### Useful Parameters #### Bump | Parameter | Type | Description | |-----------|------|-------------| | `version` | `string` | Force set specific version | | `as` | `'major' \| 'minor' \| 'patch' \| 'prerelease'` | Release type | | `prerelease` | `string` | Pre-release identifier (e.g., "alpha", "beta") | | `firstRelease` | `boolean` | Whether this is the first release | | `skip` | `boolean` | Skip version bump | | `byProject` | `Record<string, object>` | Per-project bump options for monorepos | #### Publish | Parameter | Type | Description | |-----------|------|-------------| | `skip` | `boolean` | Skip publishing | | `access` | `'public' \| 'restricted'` | Package access level | | `tag` | `string` | Tag for npm publication | ### Usage Examples #### Force specific version ````md !simple-release/set-options ```json { "bump": { "version": "2.0.0" } } ``` ```` #### Force major bump ````md !simple-release/set-options ```json { "bump": { "as": "major" } } ``` ```` #### Create alpha pre-release ````md !simple-release/set-options ```json { "bump": { "prerelease": "alpha" } } ``` ```` #### Publish with specific access and tag ````md !simple-release/set-options ```json { "bump": { "prerelease": "beta" }, "publish": { "access": "public", "tag": "beta" } } ``` ```` ### Access Restrictions The command can only be used by users with permissions: - repository owner - organization member - collaborator ### Notes - The last comment with `!simple-release/set-options` command takes priority - JSON must be valid, otherwise the command will be ignored - Parameters apply only to the current release execution - The command can be updated by editing the comment or adding a new one </details> <!-- Please do not edit this comment. simple-release-pull-request: true simple-release-branch-from: release simple-release-branch-to: main --> Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Closes #479. Both capability gaps that the sandbox tightening (#477 / ARCH-024) exposed, delivered through the sanctioned
ctx.ast()door. Two commits, reviewable separately.Front A — base-revision access (
39e511f)Rules can inspect a file at its base git revision, not only the working tree — the capability whose absence forced rule authors to shell out to a subprocess.
ast(path, language, { rev: "base" })— parses the file at the comparison base commit. Same shapes, same throw contract.fileAtBase(path): Promise<string | null>— raw base source, ornullwhen no base is resolved or the file was added since the base.The base is the merge base of
--baseand HEAD (the commitchangedFilesdiffs against). No new privileged path: git reads live in the already-sanctionedgit-files.ts; all fourast()guardrails run in order; TS/JS parse in-process, Python/Ruby base content goes to an OS-temp file outside the project tree with the same-Iisolation.ast({rev:'base'})throws distinguishably (no-base vs added-file);fileAtBasereturnsnullso a rule can branch without atry/catch.Unblocks documentation-only / no-op change detection with zero subprocess use.
Front B — comment access (
95db9bd)Comment-governance rules can work against structured comment tokens instead of fragile line-regex.
ast(path, language, { comments: true })attaches acommentsarray of{ type: "line" | "block"; value; loc }to the tree.valuehas delimiters stripped. TS/JS comments are scanned from the ORIGINAL source (Bun.Transpiler strips them before meriyah) — so commentlocis original-source-accurate even for TS, unlike the tree's own transpiled-relativeloc. String/template aware; regex literals are a known blind spot.tokenizevia a second serializer ({_tree, comments}), sameconvert()preamble, same-I.Folded into
ast()(not a new method) so it rides the existing four-guardrail flow andsingle-ast-methodstays satisfied. No new subprocess site, no new guardrail.Why this is safe
Both features add no new subprocess site and no new guardrail. ARCH-022's four companion rules (
ast-guardrail-ordering,no-unsanctioned-engine-subprocess,single-ast-method,python-subprocess-isolated) all still pass — the new code rides entirely inside them.Test plan
tests/engine/runner-ast-base.test.ts— 10 cases: git reads,fileAtBase, TS{rev:'base'}vs working tree, comment-only structural equivalence, both throw cases, Python doc-only detectiontests/engine/runner-ast-comments.test.ts— 7 cases: TS line/block extraction (stripped values + original-source loc), string-awareness, JS, opt-in-only, ruby-throws, Python tokenize (incl.#-in-string exclusion + base+comments composition)bun run validate— 44/44 ADR rules, 1523 tests, lint, typecheck, format, knip, buildADR
Amends ARCH-022 with both surfaces, their guardrail-compliance arguments, the throw-vs-null contract, the original-source-loc advantage for TS comments, the honest limitations (regex blind spot;
commentsas a mild root-shape addition), and cross-references to ARCH-024.