Skip to content

feat(engine): ctx.findAstNodes() generic AST node collector#486

Merged
rhuanbarreto merged 6 commits into
mainfrom
feat/find-ast-nodes
Jul 17, 2026
Merged

feat(engine): ctx.findAstNodes() generic AST node collector#486
rhuanbarreto merged 6 commits into
mainfrom
feat/find-ast-nodes

Conversation

@rhuanbarreto

Copy link
Copy Markdown
Contributor

Closes #483

Summary

Adds ctx.findAstNodes(tree, ...types) to RuleContext: a generic, language-agnostic collector that recursively gathers every node in a ctx.ast() tree whose type-discriminant field matches one of the given names. It replaces the ~15-line recursive walker every AST-based .rules.ts file had to hand-roll (and could not share, since the sandbox module allowlist blocks imports between rule files).

Design decisions

  • Lives in the trusted engine, not the sandbox. Implemented in src/engine/ast-support.ts and exposed through createRuleContext() in src/engine/runner.ts, exactly like ctx.glob/ctx.readFile. ALLOWED_MODULES in rule-scanner.ts is untouched — the sandbox posture does not change.
  • Discriminant handling checks whichever field is present per node: _type (Python ast) or type (ESTree TS/JS). _type is preferred when both are strings, because a Python node can legitimately carry an unrelated field named type (e.g. ExceptHandler's exception type), while ESTree nodes never carry _type.
  • Ruby behavior is documented, not papered over. Ripper.sexp emits nested arrays (["program", ...]) with the tag at element 0, not as an object field. A Ruby tree is recursed like any other value, but its array-shaped nodes carry no object discriminant and therefore never match. This is stated in the JSDoc, the generated rules.d.ts shim, and all three doc locales.
  • Traversal semantics match the hand-rolled walkers: own-enumerable object values and arrays are recursed, and the root argument itself is a match candidate. A WeakSet cycle guard is added as cheap defensive insurance (also deduplicates a node reachable through two parents).
  • Typing: overloaded signatures on RuleContext (mirroring how ast() narrows per language literal) return EsTreeNode[] for ESTree inputs, PythonAstNode[] for Python inputs, and the union for anything else — no parallel interfaces introduced; the existing node types from src/formats/rules.ts are reused. The generated rules.d.ts shim (src/helpers/rules-shim.ts) declares the same surface.
  • Synchronous — pure tree traversal, no I/O, matching the issue's proposed signature.

Deferred follow-ons (triaged, not silently dropped)

The issue names two additional helpers that showed up duplicated alongside the walker. Both are explicitly deferred to follow-up work per maintainer scoping, and are not part of this PR:

  • a comment-in-range check ("does any comment in tree.comments fall within [startLine, endLine]"), and
  • a position-field stripper for structural-equality comparisons (strip lineno/col_offset/loc/range recursively).

Acceptance criteria

  • ctx.findAstNodes(tree, ...types) returns all matching nodes for at least Python and TS/JS ESTree shapes (Ruby if its discriminant field is confirmed compatible). — Python (_type) and ESTree (type) covered by unit and runner-integration tests. Ruby confirmed not compatible: Ripper's array nodes carry no object discriminant, so they are recursed but never match — documented in the API docs and covered by a test asserting the empty result.
  • Matches the semantics of the hand-rolled walkers it replaces (arrays and nested objects are recursed; the tree itself is checked as an implicit root candidate). — Tests cover nested arrays, deep object nesting, and root-node matching; the only deliberate divergence is the cycle guard, which also collects a node reachable via two parents once instead of twice.
  • Documented in docs/*/reference/rule-api.mdx (all three locales) with an example rewriting a hand-rolled collector. — English, Norwegian bokmål, and Brazilian Portuguese each gain a findAstNodes section with the before/after collectFunctionDefs example.
  • At least one existing pattern rewritten in the docs/tests to demonstrate the boilerplate reduction. — tests/engine/ast-support.test.ts rewrites the issue's collectFunctionDefs example to findAstNodes(tree, "FunctionDef", "AsyncFunctionDef"); tests/engine/runner-find-ast-nodes.test.ts does the same end-to-end through runChecks for TypeScript and (interpreter-gated) real Python ast output.

Validation

  • bun run validate passes (lint, typecheck, format:check, tests, ADR check, knip, build check).
  • bun run src/cli.ts check: 44/44 rules pass, including ARCH-022's companion rules (single-ast-method is unaffected — findAstNodes is not a per-language *Ast() variant and the single ast() signature is unchanged).

#483)

Every .rules.ts file walking ctx.ast() output re-implemented the same
recursive find-nodes-by-type walker, and the sandbox module allowlist
means rule files cannot share a helper. Expose the collector as a
built-in on RuleContext instead, implemented in the trusted engine
(ast-support.ts) like ctx.glob.

- Matches whichever discriminant a node carries: _type (Python) or
  type (ESTree TS/JS), preferring _type since Python nodes can carry
  an unrelated field named "type" (e.g. ExceptHandler)
- Recurses own-enumerable object values and arrays; the root itself
  is a match candidate; WeakSet cycle guard as defensive insurance
- Ruby: Ripper.sexp arrays are recursed, but array-shaped nodes have
  no object discriminant and never match (documented explicitly)
- Overloaded signatures on RuleContext and in the generated
  rules.d.ts shim narrow the element type per tree shape
- Docs updated in all three locales with a before/after example
  replacing the hand-rolled collectFunctionDefs walker

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 5ce35ac9-5ea1-4619-901e-c90a96d48259

📥 Commits

Reviewing files that changed from the base of the PR and between bfee550 and 795a114.

📒 Files selected for processing (10)
  • docs/public/llms-full.txt
  • docs/src/content/docs/nb/reference/rule-api.mdx
  • docs/src/content/docs/pt-br/reference/rule-api.mdx
  • docs/src/content/docs/reference/rule-api.mdx
  • src/engine/ast-support.ts
  • src/engine/runner.ts
  • src/formats/rules.ts
  • src/helpers/rules-shim.ts
  • tests/engine/find-ast-nodes.test.ts
  • tests/engine/runner-find-ast-nodes.test.ts
📜 Recent review details
⏰ Context from checks skipped due to timeout. (3)
  • GitHub Check: Smoke Test (Windows) / Windows
  • GitHub Check: Analyze (csharp)
  • GitHub Check: Cloudflare Pages
🧰 Additional context used
📓 Path-based instructions (21)
src/**/*.ts

📄 CodeRabbit inference engine (.archgate/adrs/ARCH-004-no-barrel-files.md)

src/**/*.ts: Do not re-export symbols from another module in any source file; statements like export { X } from "./other" and export type { X } from "./other" are forbidden.
Import symbols directly from the module that defines them; do not import from a directory path such as ../formats expecting implicit index.ts resolution.

src/**/*.ts: Use await Bun.file(path).json() when reading JSON files in Bun TypeScript source code; do not use JSON.parse(await Bun.file(path).text()) or JSON.parse(fs.readFileSync(path, "utf-8")) for file reads.
Use Bun.JSONC.parse() when reading files that may contain comments, such as tsconfig.json, instead of plain JSON.parse() on file contents.
Reserve JSON.parse() for parsing JSON strings from non-file sources such as API responses or string variables; do not use it as the default for reading JSON files.

src/**/*.ts: In TypeScript source files under src/, use Bun.env instead of process.env for all environment variable reads and writes; process.env must not be used.
In TypeScript source files under src/, use nullish coalescing for environment-variable defaults, e.g. Bun.env.NODE_ENV ?? "production".
In TypeScript source files under src/, use Boolean(Bun.env.CI) for truthy checks on environment flags.
In TypeScript source files under src/, do not destructure Bun.env (for example, const { HOME } = Bun.env); access properties individually instead.
In TypeScript source files under src/, do not reference process.env even in comments that suggest using it.

src/**/*.ts: Heavy dependencies such as inquirer, posthog-node, @sentry/*, and any similarly expensive runtime-only dependency MUST be loaded with dynamic import() at the point of use, never as a static value import at module top level.
Type-only references to heavy modules must use import type (for example, import type { PostHog } from "posthog-node" or import type * as SentryNs from "@sentry/node-core/light"); type-only...

Files:

  • src/helpers/rules-shim.ts
  • src/engine/runner.ts
  • src/engine/ast-support.ts
  • src/formats/rules.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, use Bun.file() instead of fs.readFile() for simple reads.
Prefer node: built-in modules such as node:util, node:path, and node:fs over npm alternatives.
Do not use utility libraries for single functions, such as importing lodash for one helper like pick.
Do not use path aliases (tsconfig paths); use relative imports with Bun's native module resolution.
Do not install packages globally during development; use bunx for one-off tools.

Files:

  • src/helpers/rules-shim.ts
  • src/engine/runner.ts
  • tests/engine/find-ast-nodes.test.ts
  • tests/engine/runner-find-ast-nodes.test.ts
  • src/engine/ast-support.ts
  • src/formats/rules.ts
src/**/!(*platform).ts

📄 CodeRabbit inference engine (.archgate/adrs/ARCH-009-platform-detection-helper.md)

src/**/!(*platform).ts: In src/ TypeScript source files, do not read process.platform directly; use src/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 in src/ TypeScript source.
When behavior differs between Linux and Windows, account for WSL by using isWSL() rather than assuming `

Files:

  • src/helpers/rules-shim.ts
  • src/engine/runner.ts
  • src/engine/ast-support.ts
  • src/formats/rules.ts
{src,tests}/**/*.ts

📄 CodeRabbit inference engine (.archgate/adrs/LEGAL-001-spdx-license-headers.md)

{src,tests}/**/*.ts: Every TypeScript source file in src/ and tests/ must begin with // SPDX-License-Identifier: Apache-2.0 followed by // Copyright 2026 Archgate.
If a TypeScript file has a shebang line (for example #!/usr/bin/env bun in src/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/helpers/rules-shim.ts
  • src/engine/runner.ts
  • tests/engine/find-ast-nodes.test.ts
  • tests/engine/runner-find-ast-nodes.test.ts
  • src/engine/ast-support.ts
  • src/formats/rules.ts
src/{helpers,engine}/**/*.ts

📄 CodeRabbit inference engine (.archgate/adrs/ARCH-002-error-handling.md)

Do not use console.log(), console.warn(), or console.info() directly in helper or engine files; use logInfo() or logWarn() instead.

Files:

  • src/helpers/rules-shim.ts
  • src/engine/runner.ts
  • src/engine/ast-support.ts
src/helpers/rules-shim.ts

📄 CodeRabbit inference engine (.archgate/adrs/ARCH-022-ast-aware-rule-context.md)

The generated .rules.ts helper shim must mirror the single RuleContext.ast() API, including the optional AstOptions parameter.

Files:

  • src/helpers/rules-shim.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.ts file with automated checks that run via archgate check.

When reviewing, you must:

  1. Treat ADR violations as blocking issues, not suggestions.
  2. Cite the specific ADR ID when flagging a violation (e.g., "Violates ARCH-006").
  3. Focus on semantic and contextual violations that automated rules cannot catch —
    the .rules.ts files already cover syntactic/structural patterns.
  4. If you are unsure whether something violates an ADR, flag it as a question
    rather than approving it.

Files:

  • src/helpers/rules-shim.ts
  • src/engine/runner.ts
  • tests/engine/find-ast-nodes.test.ts
  • docs/public/llms-full.txt
  • docs/src/content/docs/nb/reference/rule-api.mdx
  • docs/src/content/docs/pt-br/reference/rule-api.mdx
  • tests/engine/runner-find-ast-nodes.test.ts
  • src/engine/ast-support.ts
  • docs/src/content/docs/reference/rule-api.mdx
  • src/formats/rules.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 through listMatchingFiles for rule-facing inputs or matchTrackedFiles for trusted ADR frontmatter patterns.
When the target is a Git repository and respectGitignore is not false, pass the tracked set from getGitTrackedFiles to matching operations.
Per-run RunCaches must 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 cache readJSON results 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.

Files:

  • src/engine/runner.ts
  • src/engine/ast-support.ts
src/engine/runner.ts

📄 CodeRabbit inference engine (.archgate/adrs/ARCH-022-ast-aware-rule-context.md)

Implement ctx.ast() dispatch internally in createRuleContext(); rule authors must not receive direct subprocess or filesystem primitives.

Files:

  • src/engine/runner.ts
src/engine/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.archgate/adrs/ARCH-022-ast-aware-rule-context.md)

src/engine/**/*.{ts,tsx}: For TypeScript and JavaScript, ctx.ast() must reuse the in-process meriyah parser and must not spawn a subprocess.
Python and Ruby AST parsing must use only their interpreters' standard-library facilities through guarded Bun.spawn invocations; no third-party parser, native binding, or WASM grammar may be introduced.
Before any Python or Ruby subprocess is spawned, execute guardrails in exactly this order: path safety via safePath(), language plausibility validation, interpreter availability probing, then guarded invocation.
Use array-based Bun.spawn arguments only for Python/Ruby AST execution; never shell-interpolate paths or file contents.
Run Python AST subprocesses with python -I -c ... isolation, and strip a leading UTF-8 BOM before parsing Python and Ruby source.
Cache Python/Ruby interpreter availability once per check invocation rather than probing once per file.
ctx.ast() must throw on missing interpreters and parse failures, with distinguishable error messages; it must never return null or another silent-failure sentinel.
Support ast(path, language, { rev: "base" }) and fileAtBase(path) using the merge base of --base and HEAD. Base AST access must throw for an unresolved base or missing base file, while fileAtBase() returns null for those cases.
When { comments: true } is requested, attach structured comments with type, delimiter-stripped value, and source loc; omit comments unless explicitly requested. Ruby comment extraction must currently throw as unsupported.
Extract TypeScript/JavaScript comments from the original source, not transpiled output, and do not treat regex literals as comment-aware; Python comments must use tokenize.
Do not trust node.loc for TypeScript AST results because parsing transpiled output changes positions; re-locate constructs in the original source before reporting lines. JavaScript locations are source-accurate.
Do not invoke Bun.spawn, child_process, git, ...

Files:

  • src/engine/runner.ts
  • src/engine/ast-support.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 mutating process.platform directly.

tests/**/*.ts: Use Bun's built-in bun:test runner for all tests; do not import test utilities from node:test.
Shared test helpers must also use restoreEnv when restoring environment variables.

Files:

  • tests/engine/find-ast-nodes.test.ts
  • tests/engine/runner-find-ast-nodes.test.ts
tests/**/*.test.ts

📄 CodeRabbit inference engine (.archgate/adrs/ARCH-005-testing-standards.md)

tests/**/*.test.ts: Place tests in tests/ mirroring the src/ directory structure, and name test files with the .test.ts suffix.
Test public module interfaces rather than private implementation details, use descriptive test names, and do not depend on network access.
Use isolated temporary directories created with mkdtemp for filesystem tests, and clean them up in afterEach or afterAll. Do not use hardcoded user or system paths.
Close external SDK instances such as servers, clients, and transports in afterEach or afterAll; manage their lifecycle in test hooks rather than individual test bodies.
When a temporary git repository performs commits, configure local user.email and user.name immediately after git init; do not rely on global git identity.
Every runnable test() or it() must contain at least one expect() assertion. Make implicit no-throw contracts explicit with not.toThrow() or resolves.toBeUndefined(). Use test.skip or test.todo for intentional placeholders.
Use test.skipIf(condition), test.skip, or test.todo for conditional or intentionally disabled tests; do not use bare early returns or empty callbacks to skip tests, and do not skip without a tracking issue.
When adding assertions to an older test file, import expect from bun:test.
Mock HTTP requests by assigning directly to globalThis.fetch, and restore the original fetch implementation or mock in afterEach; do not mock node:fetch.
Mock first-party modules with import * as mod and spyOn(mod, "fn"), restoring spies after each test; do not use process-global mock.module() for first-party modules.
Wrap inline spyOn or mockImplementation usage in try/finally so mockRestore() always runs, or manage spies in beforeEach and afterEach.
When redirecting user-scope paths, mock node:os's homedir() rather than relying on runtime HOME overrides; use environment overrides only for code that reads environment variables directly at call time.
Re...

Files:

  • tests/engine/find-ast-nodes.test.ts
  • tests/engine/runner-find-ast-nodes.test.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 under docs/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/nb/reference/rule-api.mdx
  • docs/src/content/docs/pt-br/reference/rule-api.mdx
  • docs/src/content/docs/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>.mdx and add the page to docs/astro.config.mjs sidebar configuration.

Files:

  • docs/src/content/docs/nb/reference/rule-api.mdx
  • docs/src/content/docs/pt-br/reference/rule-api.mdx
  • docs/src/content/docs/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/nb/reference/rule-api.mdx
  • docs/src/content/docs/pt-br/reference/rule-api.mdx
  • docs/src/content/docs/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 under docs/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, and link/href/slug attribute 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/nb/reference/rule-api.mdx
  • docs/src/content/docs/pt-br/reference/rule-api.mdx
  • docs/src/content/docs/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 du form and correct Norwegian characters (æ, ø, å).

Files:

  • docs/src/content/docs/nb/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/reference/rule-api.mdx
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, use safeParse(), and reuse AdrFrontmatterSchema.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)

RuleContext must expose exactly one language-agnostic ast(path: string, language: AstLanguage, opts?: AstOptions): Promise<AstNode> method, with no per-language AST methods. The returned node shape is language-native and may differ by language.

Files:

  • src/formats/rules.ts
🧠 Learnings (1)
📚 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
🪛 LanguageTool
docs/src/content/docs/pt-br/reference/rule-api.mdx

[uncategorized] ~214-~214: Pontuação duplicada
Context: ...a árvore retornada como somente leitura -- ela pode ser compartilhada com outras r...

(DOUBLE_PUNCTUATION_XML)


[uncategorized] ~247-~247: Pontuação duplicada
Context: ...e retornada carrega um array comments -- dados estruturados de comentário para r...

(DOUBLE_PUNCTUATION_XML)


[uncategorized] ~274-~274: 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] ~274-~274: Pontuação duplicada
Context: ...anspilado para TypeScript (veja AstNode): os comentários são varridos a partir d...

(DOUBLE_PUNCTUATION_XML)


[uncategorized] ~274-~274: 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] ~274-~274: Pontuação duplicada
Context: ... Python são sempre type: "line" (#) -- Python não tem comentários de bloco, e ...

(DOUBLE_PUNCTUATION_XML)


[typographical] ~274-~274: 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)


[uncategorized] ~274-~274: Se é uma abreviatura, falta um ponto. Se for uma expressão, coloque entre aspas.
Context: ...moção dos delimitadores /* */) e cujo loc vai da linha do =begin até a linha d...

(ABREVIATIONS_PUNCTUATION)


[uncategorized] ~274-~274: Se é uma abreviatura, falta um ponto. Se for uma expressão, coloque entre aspas.
Context: ...naté a linha do=end. As colunas de loc` dos comentários Ruby são deslocamentos...

(ABREVIATIONS_PUNCTUATION)


[locale-violation] ~274-~274: “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] ~274-~274: “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 (10)
src/formats/rules.ts (1)

76-121: LGTM!

Also applies to: 122-130, 148-155, 174-191, 195-212, 213-247, 248-269

src/helpers/rules-shim.ts (1)

75-84: LGTM!

Also applies to: 99-102, 168-183, 207-208, 230-235, 236-253

docs/public/llms-full.txt (1)

5224-5224: LGTM!

Also applies to: 5445-5489

docs/src/content/docs/nb/reference/rule-api.mdx (1)

214-215: LGTM!

Also applies to: 247-248, 274-275, 433-434

docs/src/content/docs/pt-br/reference/rule-api.mdx (1)

214-215: LGTM!

Also applies to: 247-248, 274-275, 433-434

docs/src/content/docs/reference/rule-api.mdx (1)

214-215: LGTM!

Also applies to: 247-248, 274-275, 433-434

src/engine/ast-support.ts (1)

7-7: LGTM!

Also applies to: 147-211, 430-451, 452-513, 514-532

src/engine/runner.ts (1)

8-13: LGTM!

Also applies to: 25-27, 110-123, 215-216, 244-337, 338-355, 426-428, 431-436, 514-521

tests/engine/find-ast-nodes.test.ts (1)

1-121: LGTM!

tests/engine/runner-find-ast-nodes.test.ts (1)

4-4: LGTM!

Also applies to: 53-53, 95-95


📝 Walkthrough

Walkthrough

Adds findAstNodes to RuleContext with typed overloads for ESTree, Python, and generic AST inputs. The implementation iteratively traverses objects and arrays, matches _type or type, avoids cycles and duplicate visits, and is exposed through rule execution. Documentation is added across supported locales and generated declarations. Tests cover traversal edge cases and TypeScript and Python rule execution.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning runner.ts also changes readJSON path handling, which is unrelated to findAstNodes and not part of #483. Remove the readJSON refactor or move it to a separate PR so this change stays focused on findAstNodes.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately names the new ctx.findAstNodes helper, which is the main change.
Description check ✅ Passed The description matches the feature and objectives, summarizing the new AST collector and its design.
Linked Issues check ✅ Passed The PR implements the shared AST collector, docs, typings, and tests required by #483 for Python and ESTree shapes.

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 16, 2026

Copy link
Copy Markdown

Deploying archgate-cli with  Cloudflare Pages  Cloudflare Pages

Latest commit: 795a114
Status: ✅  Deploy successful!
Preview URL: https://4ef5e477.archgate-cli.pages.dev
Branch Preview URL: https://feat-find-ast-nodes.archgate-cli.pages.dev

View logs

@rhuanbarreto
rhuanbarreto marked this pull request as ready for review July 16, 2026 21:17
@cursor

cursor Bot commented Jul 16, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot 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_8f924c71-3d60-4661-98bd-053dcd6f77a0)

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 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 426-448: Replace the recursive visit traversal in findAstNodes
with an explicit stack to avoid call-stack overflow on deeply nested trees.
Preserve the WeakSet visited guard, preorder traversal order, array handling,
discriminant matching, and pure in-process behavior.

In `@tests/engine/runner-find-ast-nodes.test.ts`:
- Around line 53-63: Replace the synchronous writeFileSync calls that create the
source fixtures in both test callbacks with awaited Bun.write calls, preserving
the existing file paths and fixture contents.
🪄 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: a84335d1-c023-4500-b03f-99f0de0bc8c6

📥 Commits

Reviewing files that changed from the base of the PR and between 0a4ec29 and bfee550.

📒 Files selected for processing (10)
  • docs/public/llms-full.txt
  • docs/src/content/docs/nb/reference/rule-api.mdx
  • docs/src/content/docs/pt-br/reference/rule-api.mdx
  • docs/src/content/docs/reference/rule-api.mdx
  • src/engine/ast-support.ts
  • src/engine/runner.ts
  • src/formats/rules.ts
  • src/helpers/rules-shim.ts
  • tests/engine/ast-support.test.ts
  • tests/engine/runner-find-ast-nodes.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: Cloudflare Pages
⚠️ CI failures not shown inline (2)

GitHub Actions: Validate / Validate Code: feat(engine): ctx.findAstNodes() generic AST node collector

Conclusion: failure

View job details

##[group]Run # shim-tests is skipped when no shim files changed — treat skipped as success.
 �[36;1m# shim-tests is skipped when no shim files changed — treat skipped as success.�[0m
 �[36;1mSHIM_OK="skipped"�[0m
 �[36;1mif [[ "$SHIM_OK" == "skipped" ]]; then SHIM_OK="success"; fi�[0m
 �[36;1m�[0m
 �[36;1mif [[ "skipped" != "success" ]] || \�[0m
 �[36;1m   [[ "$SHIM_OK" != "success" ]] || \�[0m
 �[36;1m   [[ "skipped" != "success" ]] || \�[0m
 �[36;1m   [[ "skipped" != "success" ]] || \�[0m
 �[36;1m   [[ "skipped" != "success" ]] || \�[0m
 �[36;1m   [[ "skipped" != "success" ]] || \�[0m
 �[36;1m   [[ "skipped" != "success" ]]; then�[0m
 �[36;1m  echo "::error::One or more jobs failed:"�[0m

GitHub Actions: Validate / 0_Validate Code.txt: feat(engine): ctx.findAstNodes() generic AST node collector

Conclusion: failure

View job details

##[group]Run # shim-tests is skipped when no shim files changed — treat skipped as success.
 �[36;1m# shim-tests is skipped when no shim files changed — treat skipped as success.�[0m
 �[36;1mSHIM_OK="skipped"�[0m
 �[36;1mif [[ "$SHIM_OK" == "skipped" ]]; then SHIM_OK="success"; fi�[0m
 �[36;1m�[0m
 �[36;1mif [[ "skipped" != "success" ]] || \�[0m
 �[36;1m   [[ "$SHIM_OK" != "success" ]] || \�[0m
 �[36;1m   [[ "skipped" != "success" ]] || \�[0m
 �[36;1m   [[ "skipped" != "success" ]] || \�[0m
 �[36;1m   [[ "skipped" != "success" ]] || \�[0m
 �[36;1m   [[ "skipped" != "success" ]] || \�[0m
 �[36;1m   [[ "skipped" != "success" ]]; then�[0m
 �[36;1m  echo "::error::One or more jobs failed:"�[0m
🧰 Additional context used
📓 Path-based instructions (20)
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 under docs/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/nb/reference/rule-api.mdx
  • docs/src/content/docs/reference/rule-api.mdx
  • docs/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>.mdx and add the page to docs/astro.config.mjs sidebar configuration.

Files:

  • docs/src/content/docs/nb/reference/rule-api.mdx
  • docs/src/content/docs/reference/rule-api.mdx
  • docs/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/nb/reference/rule-api.mdx
  • docs/src/content/docs/reference/rule-api.mdx
  • docs/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 under docs/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, and link/href/slug attribute 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/nb/reference/rule-api.mdx
  • docs/src/content/docs/reference/rule-api.mdx
  • docs/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 du form and correct Norwegian characters (æ, ø, å).

Files:

  • docs/src/content/docs/nb/reference/rule-api.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.ts file with automated checks that run via archgate check.

When reviewing, you must:

  1. Treat ADR violations as blocking issues, not suggestions.
  2. Cite the specific ADR ID when flagging a violation (e.g., "Violates ARCH-006").
  3. Focus on semantic and contextual violations that automated rules cannot catch —
    the .rules.ts files already cover syntactic/structural patterns.
  4. If you are unsure whether something violates an ADR, flag it as a question
    rather than approving it.

Files:

  • docs/src/content/docs/nb/reference/rule-api.mdx
  • src/helpers/rules-shim.ts
  • docs/src/content/docs/reference/rule-api.mdx
  • tests/engine/ast-support.test.ts
  • src/engine/runner.ts
  • docs/public/llms-full.txt
  • docs/src/content/docs/pt-br/reference/rule-api.mdx
  • tests/engine/runner-find-ast-nodes.test.ts
  • src/formats/rules.ts
  • src/engine/ast-support.ts
src/**/*.ts

📄 CodeRabbit inference engine (.archgate/adrs/ARCH-003-output-formatting.md)

src/**/*.ts: Use styleText(format, text) from node:util for 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 --json must emit machine-readable JSON to stdout with no colors or decorative formatting.
When a command supports --json, use formatJSON() from src/helpers/output.ts for JSON serialization, and pass forcePretty: true when the user explicitly provided --json.
Use isAgentContext() from src/helpers/output.ts to 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 with console.log(), and send errors, warnings, and debug messages to stderr via logError(), logWarn(), and logDebug().
Keep CLI output concise and scannable by using whitespace and alignment instead of long text blocks.
Respect NO_COLOR automatically by relying on styleText; 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 when CI is set; CI runners should still receive human-readable output.

src/**/*.ts: Do not re-export symbols from another module in any source file; statements like export { X } from "./other" and export type { X } from "./other" are forbidden.
Import symbols directly from the module that defines them; do not import from a directory path such as ../formats expecting implicit index.ts resolution.

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: Use await Bun.file(path).json() when reading JSON files in Bun TypeScript source code; do not use JSON.parse(await Bun.file(path).text()) or `JSON.parse(fs.readFile...

Files:

  • src/helpers/rules-shim.ts
  • src/engine/runner.ts
  • src/formats/rules.ts
  • src/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, use Bun.file() instead of fs.readFile() for simple reads.
Prefer node: built-in modules such as node:util, node:path, and node:fs over npm alternatives.
Do not use utility libraries for single functions, such as importing lodash for one helper like pick.
Do not use path aliases (tsconfig paths); use relative imports with Bun's native module resolution.
Do not install packages globally during development; use bunx for one-off tools.

Files:

  • src/helpers/rules-shim.ts
  • tests/engine/ast-support.test.ts
  • src/engine/runner.ts
  • tests/engine/runner-find-ast-nodes.test.ts
  • src/formats/rules.ts
  • src/engine/ast-support.ts
src/**/!(*platform).ts

📄 CodeRabbit inference engine (.archgate/adrs/ARCH-009-platform-detection-helper.md)

src/**/!(*platform).ts: In src/ TypeScript source files, do not read process.platform directly; use src/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 in src/ TypeScript source.
When behavior differs between Linux and Windows, account for WSL by using isWSL() rather than assuming `

Files:

  • src/helpers/rules-shim.ts
  • src/engine/runner.ts
  • src/formats/rules.ts
  • src/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 in src/ and tests/ must begin with // SPDX-License-Identifier: Apache-2.0 followed by // Copyright 2026 Archgate.
If a TypeScript file has a shebang line (for example #!/usr/bin/env bun in src/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/helpers/rules-shim.ts
  • tests/engine/ast-support.test.ts
  • src/engine/runner.ts
  • tests/engine/runner-find-ast-nodes.test.ts
  • src/formats/rules.ts
  • src/engine/ast-support.ts
src/helpers/rules-shim.ts

📄 CodeRabbit inference engine (.archgate/adrs/ARCH-022-ast-aware-rule-context.md)

src/helpers/rules-shim.ts: The generated RuleContext shim for .rules.ts authors must mirror the single ast(path, language) method and not introduce per-language variants.
Document in the generated shim that RuleContext.ast() returns language-specific node shapes rather than a unified AST type.

Files:

  • src/helpers/rules-shim.ts
src/{helpers,engine}/**/*.ts

📄 CodeRabbit inference engine (.archgate/adrs/ARCH-002-error-handling.md)

Do not use console.log(), console.warn(), or console.info() directly in helper or engine files; use logInfo() or logWarn() instead.

Files:

  • src/helpers/rules-shim.ts
  • src/engine/runner.ts
  • src/engine/ast-support.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
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 under tests/ mirroring the src/ directory structure with <module-name>.test.ts naming.
Use temp directories (mkdtemp) for filesystem tests, and clean them up in afterEach or afterAll.
Close external SDK instances (servers, clients, transports, connections) in afterEach or afterAll, managing their lifecycle in hooks rather than inside individual test bodies.
When a test creates a temporary git repository and runs git commit, configure local user.email and user.name immediately after git init.
Test public module interfaces, not private implementation details.
Use descriptive test names that explain the expected behavior.
Every runnable test()/it() must contain at least one expect() assertion; smoke tests must make the contract explicit with expect(() => fn()).not.toThrow() or await expect(promise).resolves.toBeUndefined().
Use test.skip, test.skipIf, or test.todo for intentionally empty or disabled tests; do not use bare return or empty callbacks to skip work.
If the first expect() is being added to a previously assertion-less test file, add expect to the bun:test import.
When mocking fetch in tests, assign directly to globalThis.fetch and restore the original or use mock.restore() afterward.
Wrap spyOn() and inline mockImplementation() usage in try/finally, or create and restore spies in hooks, so mockRestore() always runs.
Only raise a per-test timeout above the global bun test --timeout 60000; never set a shorter per-test timeout.
Mock first-party modules with import * as mod plus spyOn(mod, "fn"), not mock.module().
When a test needs to redirect user-scope paths, mock os.homedir() instead of relying on HOME/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/ast-support.test.ts
  • tests/engine/runner-find-ast-nodes.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 mutating process.platform directly.

Files:

  • tests/engine/ast-support.test.ts
  • tests/engine/runner-find-ast-nodes.test.ts
src/engine/runner.ts

📄 CodeRabbit inference engine (.archgate/adrs/ARCH-022-ast-aware-rule-context.md)

src/engine/runner.ts: Implement ctx.ast(path, language) inside createRuleContext() with all dispatch hidden from rule authors.
For language: "typescript" and "javascript", ctx.ast() must reuse the existing in-process meriyah parser; no subprocess may be spawned for these branches.
Factor the duplicated parseModule() logic into a shared helper that is used by both rule-scanner.ts and the ctx.ast() TypeScript/JavaScript branch.
For language: "python" and "ruby", ctx.ast() must use Bun.spawn with array-based arguments only, with no shell interpolation.
Before any Python/Ruby interpreter is invoked, ctx.ast() must run the guardrail sequence in order: path safety, language plausibility check, interpreter availability probe, then guarded invocation.
ctx.ast() must use the same safePath() sandboxing as readFile/glob before accessing a target file.
ctx.ast() must reject files whose extension and/or leading content do not plausibly match the requested language before running an interpreter.
ctx.ast() must probe interpreter availability once per check invocation, cache the result, and reuse the first working candidate executable name.
On Windows, the interpreter probe must consider platform-appropriate candidates in order (including py via isWindows()); on non-Windows, it must use the non-Windows candidate order.
The Python branch must run in isolated mode (python -I -c ...) to prevent the working directory from shadowing standard-library imports.
The Python and Ruby serializers must strip a leading UTF-8 BOM before parsing.
ctx.ast() must throw on missing interpreter or parse failure, and must not return null or any other sentinel value.
The thrown error messages from ctx.ast() must distinguish interpreter-unavailable failures from parse-failure errors.
ctx.ast() must not expose Bun.spawn, child_process, or any other raw subprocess primitive on RuleContext; it is the only sanctioned tooling entrypoint.
`ctx.ast(...

Files:

  • src/engine/runner.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 through listMatchingFiles for rule-facing inputs or matchTrackedFiles for trusted ADR frontmatter patterns.
When the target is a Git repository and respectGitignore is not false, pass the tracked set from getGitTrackedFiles to matching operations.
Per-run RunCaches must 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 cache readJSON results 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.

Files:

  • src/engine/runner.ts
  • src/engine/ast-support.ts
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/reference/rule-api.mdx
src/formats/rules.ts

📄 CodeRabbit inference engine (.archgate/adrs/ARCH-022-ast-aware-rule-context.md)

src/formats/rules.ts: RuleContext must expose exactly one ast(path, language) method, with no per-language variants such as pythonAst() or rubyAst().
Document in the RuleContext.ast() type signature or JSDoc that the returned node shape differs by language.

Files:

  • src/formats/rules.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, use safeParse(), and reuse AdrFrontmatterSchema.shape.* to avoid duplicating enums.

Files:

  • src/formats/rules.ts
🧠 Learnings (1)
📚 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
🪛 LanguageTool
docs/src/content/docs/pt-br/reference/rule-api.mdx

[uncategorized] ~296-~296: Pontuação duplicada
Context: ...per cobre todas as linguagens. Síncrono -- não precisa de await. - **Agnóstico ...

(DOUBLE_PUNCTUATION_XML)


[grammar] ~300-~300: Possível erro de concordância de número.
Context: ... ("FunctionDef"/"AsyncFunctionDef", variantes síncrona/assíncrona). - Ruby: nós de `Ripper...

(GENERAL_NUMBER_AGREEMENT_ERRORS)


[uncategorized] ~303-~303: Pontuação duplicada
Context: ... Ripper contra a gramática dele. Antes -- o coletor que cada arquivo de regras pr...

(DOUBLE_PUNCTUATION_XML)

🔇 Additional comments (10)
src/formats/rules.ts (1)

227-246: LGTM!

src/helpers/rules-shim.ts (1)

217-232: LGTM!

docs/src/content/docs/nb/reference/rule-api.mdx (1)

70-70: LGTM!

Also applies to: 290-333

docs/src/content/docs/pt-br/reference/rule-api.mdx (1)

70-70: LGTM!

Also applies to: 290-333

docs/src/content/docs/reference/rule-api.mdx (1)

70-70: LGTM!

Also applies to: 290-333

docs/public/llms-full.txt (1)

5224-5224: LGTM!

Also applies to: 5443-5486

src/engine/ast-support.ts (1)

7-7: LGTM!

src/engine/runner.ts (1)

27-27: LGTM!

Also applies to: 399-402

tests/engine/ast-support.test.ts (1)

11-18: LGTM!

Also applies to: 298-398

tests/engine/runner-find-ast-nodes.test.ts (1)

1-50: LGTM!

Also applies to: 65-90, 107-128

Comment thread src/engine/ast-support.ts Outdated
Comment thread tests/engine/runner-find-ast-nodes.test.ts Outdated
@cursor

cursor Bot commented Jul 17, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot 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_259fcd29-4736-4d5c-a38c-5790718b2278)

@github-actions

github-actions Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Code Coverage

Metric Value
Lines 91.3% (8148 / 8924)
Threshold 90% minimum — met
Platforms Linux + Windows

Full HTML report available in workflow artifacts.

Per-directory breakdown
Directory Coverage Lines
src/commands/ 89.0% 1959 / 2200
src/engine/ 93.9% 2031 / 2163
src/formats/ 98.7% 148 / 150
src/helpers/ 90.9% 4010 / 4411

rhuanbarreto added a commit that referenced this pull request Jul 17, 2026
## Problem

`code-pull-request.yml` and `dco.yml` gate every job on
`github.event.pull_request.draft == false`, but their `pull_request`
triggers only listed `[opened, edited, synchronize, reopened]`. A PR
opened as draft therefore got a run where every job was skipped — which
made the "Validate Code" fan-in gate report failure — and marking the PR
ready for review never triggered a fresh run, since `ready_for_review`
was not in the trigger list. The PR stayed stuck with a spurious
failed/skipped check until an unrelated push. This surfaced on #485,
#486, and #487.

## Fix

Add `ready_for_review` to the `pull_request` trigger `types` in both
workflows, so promoting a draft to ready triggers a run whose jobs
actually execute. Two-line diff, nothing else changed.

## Validation

- `bun run validate` passes (lint, typecheck, format:check, 1558 tests,
ADR check, knip, build check)
- `bun run cli check` clean: 44/44 rules pass, 0 warnings

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
@archgatebot archgatebot Bot mentioned this pull request Jul 17, 2026
…rflow

A deeply nested tree could exhaust the JS call stack in the recursive
walker, turning a valid rule into an exit-code-2 execution error.
Replace recursion with an explicit LIFO stack; children are pushed in
reverse so preorder match ordering, the WeakSet cycle guard, and the
_type-before-type discriminant preference are all preserved. Add a
regression test collecting a leaf from a ~100k-deep tree.

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
Both test callbacks are async, so fixture writes can use the Bun
file-I/O built-in instead of node:fs writeFileSync, per the repo
guideline to prefer Bun built-ins.

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
@rhuanbarreto

Copy link
Copy Markdown
Contributor Author

Addressed the CodeRabbit review:

  • src/engine/ast-support.ts: findAstNodes traversal is now iterative (explicit LIFO stack) instead of recursive, so deeply nested trees can no longer overflow the call stack. Children are pushed in reverse index order to preserve preorder match ordering; the WeakSet cycle guard and the _type-before-type discriminant preference are unchanged. Added a regression test that collects a leaf from a ~100k-deep tree (d916c18's parent, f525025).
  • tests/engine/runner-find-ast-nodes.test.ts: fixture writes now use await Bun.write(...) instead of writeFileSync, and the unused writeFileSync import was dropped (d916c18).

bun run validate passes in full (lint, typecheck, format, 1570 tests, ADR check 44/44, knip, build check).

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 17, 2026
@rhuanbarreto
rhuanbarreto enabled auto-merge (squash) July 17, 2026 03:00
Integrates the per-run ctx.ast() parse cache (RunCaches.astResults,
parseUncached, astCacheKey) with the new ctx.findAstNodes() collector:

- src/engine/ast-support.ts: keep both additions — the iterative
  findAstNodes collector and main's astCacheKey helper
- src/engine/runner.ts: keep main's caching architecture; expose
  findAstNodes on the rule context next to ast, and compact two lines
  to stay within the max-lines lint cap
- docs/public/llms-full.txt: regenerated from the merged docs

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
@rhuanbarreto

Copy link
Copy Markdown
Contributor Author

@coderabbitai resume

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown
✅ Action performed

Reviews resumed.

Integrates Ruby { comments: true } support (#485) with ctx.findAstNodes():
- tests/engine/ast-support.test.ts: kept both new suites; moved the
  findAstNodes unit tests to tests/engine/find-ast-nodes.test.ts to stay
  under the oxlint max-lines cap
- docs/public/llms-full.txt regenerated from the merged docs

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
@rhuanbarreto
rhuanbarreto merged commit f14b73b into main Jul 17, 2026
23 checks passed
@rhuanbarreto
rhuanbarreto deleted the feat/find-ast-nodes branch July 17, 2026 03:39
rhuanbarreto pushed a commit that referenced this pull request Jul 17, 2026
# archgate

## [0.50.0](v0.49.0...v0.50.0)
(2026-07-17)

### Features

* **engine:** cache ctx.ast() parse results within a single check run
([#487](#487))
([40b39d3](40b39d3)),
closes [#482](#482)
* **engine:** ctx.findAstNodes() generic AST node collector
([#486](#486))
([f14b73b](f14b73b)),
closes [#483](#483)
* **engine:** support { comments: true } for ctx.ast() Ruby
([#485](#485))
([36b891f](36b891f)),
closes [#484](#484)

### Bug Fixes

* **ci:** run PR workflows when a draft is marked ready for review
([#488](#488))
([ab1fc96](ab1fc96)),
closes [#485](#485)
[#486](#486)

---
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ctx.findAstNodes(): generic AST node collector to cut rule boilerplate

1 participant