feat(engine): ctx.findAstNodes() generic AST node collector#486
Conversation
#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>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (10)
📜 Recent review details⏰ Context from checks skipped due to timeout. (3)
🧰 Additional context used📓 Path-based instructions (21)src/**/*.ts📄 CodeRabbit inference engine (.archgate/adrs/ARCH-004-no-barrel-files.md)
Files:
**/*.{ts,tsx,js,jsx,mjs,cjs}📄 CodeRabbit inference engine (.archgate/adrs/ARCH-006-dependency-policy.md)
Files:
src/**/!(*platform).ts📄 CodeRabbit inference engine (.archgate/adrs/ARCH-009-platform-detection-helper.md)
Files:
{src,tests}/**/*.ts📄 CodeRabbit inference engine (.archgate/adrs/LEGAL-001-spdx-license-headers.md)
Files:
src/{helpers,engine}/**/*.ts📄 CodeRabbit inference engine (.archgate/adrs/ARCH-002-error-handling.md)
Files:
src/helpers/rules-shim.ts📄 CodeRabbit inference engine (.archgate/adrs/ARCH-022-ast-aware-rule-context.md)
Files:
**⚙️ CodeRabbit configuration file
Files:
src/engine/**/*.ts📄 CodeRabbit inference engine (.archgate/adrs/ARCH-023-engine-file-listing-via-in-memory-git-tracked-matching.md)
Files:
src/engine/runner.ts📄 CodeRabbit inference engine (.archgate/adrs/ARCH-022-ast-aware-rule-context.md)
Files:
src/engine/**/*.{ts,tsx}📄 CodeRabbit inference engine (.archgate/adrs/ARCH-022-ast-aware-rule-context.md)
Files:
tests/**/*.ts📄 CodeRabbit inference engine (.archgate/adrs/ARCH-009-platform-detection-helper.md)
Files:
tests/**/*.test.ts📄 CodeRabbit inference engine (.archgate/adrs/ARCH-005-testing-standards.md)
Files:
docs/src/content/docs/**/*.mdx📄 CodeRabbit inference engine (.archgate/adrs/GEN-001-documentation-site.md)
Files:
{docs/src/content/docs/**/*.mdx,docs/astro.config.mjs}📄 CodeRabbit inference engine (.archgate/adrs/GEN-001-documentation-site.md)
Files:
docs/src/content/docs/**📄 CodeRabbit inference engine (.archgate/adrs/GEN-001-documentation-site.md)
Files:
docs/src/content/docs/**/*.{mdx,md}📄 CodeRabbit inference engine (.archgate/adrs/GEN-002-docs-i18n.md)
Files:
docs/src/content/docs/nb/**/*.{mdx,md}📄 CodeRabbit inference engine (.archgate/adrs/GEN-002-docs-i18n.md)
Files:
docs/src/content/docs/pt-br/**/*.{mdx,md}📄 CodeRabbit inference engine (.archgate/adrs/GEN-002-docs-i18n.md)
Files:
docs/src/content/docs/reference/**/*.mdx📄 CodeRabbit inference engine (.archgate/adrs/GEN-001-documentation-site.md)
Files:
src/formats/**/*.ts📄 CodeRabbit inference engine (CLAUDE.md)
Files:
src/formats/rules.ts📄 CodeRabbit inference engine (.archgate/adrs/ARCH-022-ast-aware-rule-context.md)
Files:
🧠 Learnings (1)📚 Learning: 2026-07-02T16:03:33.031ZApplied to files:
🪛 LanguageTooldocs/src/content/docs/pt-br/reference/rule-api.mdx[uncategorized] ~214-~214: Pontuação duplicada (DOUBLE_PUNCTUATION_XML) [uncategorized] ~247-~247: Pontuação duplicada (DOUBLE_PUNCTUATION_XML) [uncategorized] ~274-~274: Se é uma abreviatura, falta um ponto. Se for uma expressão, coloque entre aspas. (ABREVIATIONS_PUNCTUATION) [uncategorized] ~274-~274: Pontuação duplicada (DOUBLE_PUNCTUATION_XML) [uncategorized] ~274-~274: Se é uma abreviatura, falta um ponto. Se for uma expressão, coloque entre aspas. (ABREVIATIONS_PUNCTUATION) [uncategorized] ~274-~274: Pontuação duplicada (DOUBLE_PUNCTUATION_XML) [typographical] ~274-~274: Símbolo sem par: “"” aparentemente está ausente (UNPAIRED_BRACKETS) [uncategorized] ~274-~274: Se é uma abreviatura, falta um ponto. Se for uma expressão, coloque entre aspas. (ABREVIATIONS_PUNCTUATION) [uncategorized] ~274-~274: Se é uma abreviatura, falta um ponto. Se for uma expressão, coloque entre aspas. (ABREVIATIONS_PUNCTUATION) [locale-violation] ~274-~274: “template” é um estrangeirismo. É preferível dizer “modelo”. (PT_BARBARISMS_REPLACE_TEMPLATE) [style] ~274-~274: “dentro de um” é uma expressão prolixa. É preferível dizer “num” ou “em um”. (PT_WORDINESS_REPLACE_DENTRO_DE_UM) 🔇 Additional comments (10)
📝 WalkthroughWalkthroughAdds 🚥 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 |
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Deploying archgate-cli with
|
| 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 |
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_8f924c71-3d60-4661-98bd-053dcd6f77a0) |
There was a problem hiding this comment.
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
📒 Files selected for processing (10)
docs/public/llms-full.txtdocs/src/content/docs/nb/reference/rule-api.mdxdocs/src/content/docs/pt-br/reference/rule-api.mdxdocs/src/content/docs/reference/rule-api.mdxsrc/engine/ast-support.tssrc/engine/runner.tssrc/formats/rules.tssrc/helpers/rules-shim.tstests/engine/ast-support.test.tstests/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
##[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
##[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 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/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/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/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/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/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/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.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/nb/reference/rule-api.mdxsrc/helpers/rules-shim.tsdocs/src/content/docs/reference/rule-api.mdxtests/engine/ast-support.test.tssrc/engine/runner.tsdocs/public/llms-full.txtdocs/src/content/docs/pt-br/reference/rule-api.mdxtests/engine/runner-find-ast-nodes.test.tssrc/formats/rules.tssrc/engine/ast-support.ts
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/helpers/rules-shim.tssrc/engine/runner.tssrc/formats/rules.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/helpers/rules-shim.tstests/engine/ast-support.test.tssrc/engine/runner.tstests/engine/runner-find-ast-nodes.test.tssrc/formats/rules.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/helpers/rules-shim.tssrc/engine/runner.tssrc/formats/rules.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/helpers/rules-shim.tstests/engine/ast-support.test.tssrc/engine/runner.tstests/engine/runner-find-ast-nodes.test.tssrc/formats/rules.tssrc/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 generatedRuleContextshim for.rules.tsauthors must mirror the singleast(path, language)method and not introduce per-language variants.
Document in the generated shim thatRuleContext.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(), orconsole.info()directly in helper or engine files; uselogInfo()orlogWarn()instead.
Files:
src/helpers/rules-shim.tssrc/engine/runner.tssrc/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 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/ast-support.test.tstests/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 mutatingprocess.platformdirectly.
Files:
tests/engine/ast-support.test.tstests/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: Implementctx.ast(path, language)insidecreateRuleContext()with all dispatch hidden from rule authors.
Forlanguage: "typescript"and"javascript",ctx.ast()must reuse the existing in-processmeriyahparser; no subprocess may be spawned for these branches.
Factor the duplicatedparseModule()logic into a shared helper that is used by bothrule-scanner.tsand thectx.ast()TypeScript/JavaScript branch.
Forlanguage: "python"and"ruby",ctx.ast()must useBun.spawnwith 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 samesafePath()sandboxing asreadFile/globbefore 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 percheckinvocation, cache the result, and reuse the first working candidate executable name.
On Windows, the interpreter probe must consider platform-appropriate candidates in order (includingpyviaisWindows()); 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 returnnullor any other sentinel value.
The thrown error messages fromctx.ast()must distinguish interpreter-unavailable failures from parse-failure errors.
ctx.ast()must not exposeBun.spawn,child_process, or any other raw subprocess primitive onRuleContext; 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 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.
Files:
src/engine/runner.tssrc/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:RuleContextmust expose exactly oneast(path, language)method, with no per-language variants such aspythonAst()orrubyAst().
Document in theRuleContext.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, usesafeParse(), and reuseAdrFrontmatterSchema.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
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_259fcd29-4736-4d5c-a38c-5790718b2278) |
Code Coverage
Full HTML report available in workflow artifacts. Per-directory breakdown
|
## 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>
…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>
|
Addressed the CodeRabbit review:
|
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>
|
@coderabbitai resume |
✅ Action performedReviews 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>
# 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>
Closes #483
Summary
Adds
ctx.findAstNodes(tree, ...types)toRuleContext: a generic, language-agnostic collector that recursively gathers every node in actx.ast()tree whose type-discriminant field matches one of the given names. It replaces the ~15-line recursive walker every AST-based.rules.tsfile had to hand-roll (and could not share, since the sandbox module allowlist blocks imports between rule files).Design decisions
src/engine/ast-support.tsand exposed throughcreateRuleContext()insrc/engine/runner.ts, exactly likectx.glob/ctx.readFile.ALLOWED_MODULESinrule-scanner.tsis untouched — the sandbox posture does not change._type(Pythonast) ortype(ESTree TS/JS)._typeis preferred when both are strings, because a Python node can legitimately carry an unrelated field namedtype(e.g.ExceptHandler's exception type), while ESTree nodes never carry_type.Ripper.sexpemits 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 generatedrules.d.tsshim, and all three doc locales.WeakSetcycle guard is added as cheap defensive insurance (also deduplicates a node reachable through two parents).RuleContext(mirroring howast()narrows per language literal) returnEsTreeNode[]for ESTree inputs,PythonAstNode[]for Python inputs, and the union for anything else — no parallel interfaces introduced; the existing node types fromsrc/formats/rules.tsare reused. The generatedrules.d.tsshim (src/helpers/rules-shim.ts) declares the same surface.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:
tree.commentsfall within[startLine, endLine]"), andlineno/col_offset/loc/rangerecursively).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.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 afindAstNodessection with the before/aftercollectFunctionDefsexample.tests/engine/ast-support.test.tsrewrites the issue'scollectFunctionDefsexample tofindAstNodes(tree, "FunctionDef", "AsyncFunctionDef");tests/engine/runner-find-ast-nodes.test.tsdoes the same end-to-end throughrunChecksfor TypeScript and (interpreter-gated) real Pythonastoutput.Validation
bun run validatepasses (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-methodis unaffected —findAstNodesis not a per-language*Ast()variant and the singleast()signature is unchanged).