feat(engine): support { comments: true } for ctx.ast() Ruby#485
Conversation
Closes #484 Mirror Python's two-pass approach: RUBY_AST_WITH_COMMENTS_PROGRAM runs Ripper.sexp for the tree plus a second Ripper.lex pass for comments, emitting the same {_tree, comments} envelope the Python with-comments serializer uses. # comments become type "line" tokens (leading # stripped, newline chomped); each =begin/=end region becomes ONE type "block" token with the marker lines stripped and loc spanning =begin through =end. A Ripper.lex failure on otherwise-parseable source degrades to an empty comment list instead of failing the parse. Ruby's tree is an array, so the comments array rides on the returned sexp as a non-index property (typed via the new RubyAstProgram root type, mirrored in the rules shim). The early commentsUnsupportedError throw in runner.ts is removed and the helper deleted — Ruby was its last remaining case. Docs updated in all three locales; llms-full.txt regenerated. Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
|
Warning Review limit reached
Next review available in: 19 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (10)
📝 WalkthroughWalkthroughRuby AST parsing now supports 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Deploying archgate-cli with
|
| Latest commit: |
1d94f0d
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://73b35117.archgate-cli.pages.dev |
| Branch Preview URL: | https://feat-ruby-ast-comments.archgate-cli.pages.dev |
…comments Ripper reports byte-offset columns, and the with-comments serializer mixed them with character lengths, so comment locs were wrong on non-ASCII lines under every convention. Convert byte columns to character offsets so Ruby comment locs share the Python/TS unit; the sexp tree's own node positions stay byte-based as Ripper emits them. Also normalize CRLF to LF inside =begin/=end block values: Windows text-mode reads already strip the CR while POSIX preserves it, so the same checked-in CRLF file produced platform-dependent values. Update ARCH-022, the CommentToken JSDoc/shim, and all three doc locales to pin both conventions, with end-to-end tests for each. Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_d6be18d2-b0f8-4814-a151-5e10ee834598) |
Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_41833cd2-47ad-4789-97d5-b81202de2bcb) |
Code Coverage
Full HTML report available in workflow artifacts. Per-directory breakdown
|
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 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/formats/rules.ts`:
- Around line 180-183: Update the AstNode union in src/formats/rules.ts:180-183
and src/helpers/rules-shim.ts:173-177 to use RubyAstProgram instead of
RubyAstNode, alongside EsTreeProgram and PythonAstModule, so the non-literal
AstLanguage overload exposes the comments property.
In `@tests/engine/ast-support.test.ts`:
- Around line 326-456: Replace all five changed writeFileSync fixture writes in
tests/engine/ast-support.test.ts lines 326-456 and both changed writeFileSync
calls in tests/engine/runner-ast-comments.test.ts lines 201-251 with awaited
Bun.write calls, preserving each existing file path and content.
- Around line 326-338: Replace the fixture-writing writeFileSync calls in the
affected async tests with await Bun.write(file, content), preserving each
existing content value and file target. Update all occurrences in the test cases
represented by the listed ranges, including the shown fixture block.
- Around line 369-390: Add a test near the existing comment-free source test
that supplies Ruby input causing Ripper.lex to raise, then run the same
RUBY_AST_WITH_COMMENTS_PROGRAM subprocess flow and assert exitCode is 0, the
parsed envelope has a valid _tree, and envelope.comments equals [].
In `@tests/engine/runner-ast-comments.test.ts`:
- Around line 201-213: Replace both test-fixture writeFileSync calls in the
async test callbacks with awaited Bun.write calls, preserving the existing file
paths and 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: 1c1c89d7-70c3-4125-b79c-2374077e6f40
📒 Files selected for processing (11)
.archgate/adrs/ARCH-022-ast-aware-rule-context.mddocs/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-ast-comments.test.ts
📜 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 (25)
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-ast-comments.test.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:
tests/engine/ast-support.test.tssrc/helpers/rules-shim.tssrc/formats/rules.tstests/engine/runner-ast-comments.test.tssrc/engine/runner.tssrc/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 mutatingprocess.platformdirectly.
Files:
tests/engine/ast-support.test.tstests/engine/runner-ast-comments.test.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:
tests/engine/ast-support.test.tssrc/helpers/rules-shim.tssrc/formats/rules.tstests/engine/runner-ast-comments.test.tssrc/engine/runner.tssrc/engine/ast-support.ts
tests/engine/{runner-ast,runner-ast-base,runner-ast-comments,ast-support}.test.ts
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-022-ast-aware-rule-context.md)
Test AST parsing, guardrail behavior, throw-versus-null base semantics, Python isolation, comment extraction, original-source locations, Ruby character offsets, and BOM handling.
Files:
tests/engine/ast-support.test.tstests/engine/runner-ast-comments.test.ts
**
⚙️ CodeRabbit configuration file
**: This project uses Archgate — an AI governance framework based on
Architecture Decision Records (ADRs). The ADRs in.archgate/adrs/
are the authoritative rules for this codebase. Each ADR has a companion
.rules.tsfile with automated checks that run viaarchgate check.When reviewing, you must:
- Treat ADR violations as blocking issues, not suggestions.
- Cite the specific ADR ID when flagging a violation (e.g., "Violates ARCH-006").
- Focus on semantic and contextual violations that automated rules cannot catch —
the.rules.tsfiles already cover syntactic/structural patterns.- If you are unsure whether something violates an ADR, flag it as a question
rather than approving it.
Files:
tests/engine/ast-support.test.tsdocs/public/llms-full.txtsrc/helpers/rules-shim.tsdocs/src/content/docs/pt-br/reference/rule-api.mdxdocs/src/content/docs/reference/rule-api.mdxsrc/formats/rules.tstests/engine/runner-ast-comments.test.tssrc/engine/runner.tsdocs/src/content/docs/nb/reference/rule-api.mdxsrc/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/formats/rules.tssrc/engine/runner.tssrc/engine/ast-support.ts
src/**/!(*platform).ts
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-009-platform-detection-helper.md)
src/**/!(*platform).ts: Insrc/TypeScript source files, do not readprocess.platformdirectly; usesrc/helpers/platform.ts(isWindows(),isMacOS(),isLinux(),isWSL(),getPlatformInfo()) for all platform detection.
Use the centralized platform helper instead of duplicating OS/WSL detection logic inline anywhere insrc/TypeScript source.
When behavior differs between Linux and Windows, account for WSL by usingisWSL()rather than assuming `
Files:
src/helpers/rules-shim.tssrc/formats/rules.tssrc/engine/runner.tssrc/engine/ast-support.ts
src/{helpers,engine}/**/*.ts
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-002-error-handling.md)
Do not use
console.log(),console.warn(), orconsole.info()directly in helper or engine files; uselogInfo()orlogWarn()instead.
Files:
src/helpers/rules-shim.tssrc/engine/runner.tssrc/engine/ast-support.ts
src/helpers/rules-shim.ts
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-022-ast-aware-rule-context.md)
Keep the generated
.rules.tshelper shim aligned withRuleContext, exposing exactly one AST method with the optionalAstOptionsparameter.
Files:
src/helpers/rules-shim.ts
docs/src/content/docs/**/*.mdx
📄 CodeRabbit inference engine (.archgate/adrs/GEN-001-documentation-site.md)
docs/src/content/docs/**/*.mdx: Use MDX (.mdx) for all content pages underdocs/src/content/docs/.
Escape literal curly braces in MDX when showing template syntax; do not use bare{}in prose or code-fence labels.
Files:
docs/src/content/docs/pt-br/reference/rule-api.mdxdocs/src/content/docs/reference/rule-api.mdxdocs/src/content/docs/nb/reference/rule-api.mdx
{docs/src/content/docs/**/*.mdx,docs/astro.config.mjs}
📄 CodeRabbit inference engine (.archgate/adrs/GEN-001-documentation-site.md)
When adding a new documentation page, create the MDX file in
docs/src/content/docs/<category>/<slug>.mdxand add the page todocs/astro.config.mjssidebar configuration.
Files:
docs/src/content/docs/pt-br/reference/rule-api.mdxdocs/src/content/docs/reference/rule-api.mdxdocs/src/content/docs/nb/reference/rule-api.mdx
docs/src/content/docs/**
📄 CodeRabbit inference engine (.archgate/adrs/GEN-001-documentation-site.md)
Do not create documentation content files outside
docs/src/content/docs/; Starlight content must live in that exact directory structure.
Files:
docs/src/content/docs/pt-br/reference/rule-api.mdxdocs/src/content/docs/reference/rule-api.mdxdocs/src/content/docs/nb/reference/rule-api.mdx
docs/src/content/docs/**/*.{mdx,md}
📄 CodeRabbit inference engine (.archgate/adrs/GEN-002-docs-i18n.md)
docs/src/content/docs/**/*.{mdx,md}: For every English docs page underdocs/src/content/docs/, create a translated file in each locale directory with the exact same relative path and filename, and ensure every locale file corresponds to an existing root file (no orphan translations).
When adding or modifying English documentation content, update the corresponding locale files in the same pull request.
Translate all user-facing prose in docs pages, including titles, descriptions, headings, paragraphs, list items, table text, and admonition content.
Translate user-visible text props in Starlight components such as<Card title="...">and<LinkCard description="...">.
Keep code blocks, CLI commands, file paths, TypeScript identifiers, technical terms, import statements, component names, andlink/href/slugattribute values in English.
Keep internal links unchanged and do not add locale prefixes (for example, use/guides/...rather than/pt-br/guides/...).
Preserve MDX curly-brace escaping (\{\}) in translated content.
Preserve Starlight component import statements identically in translated files.
Files:
docs/src/content/docs/pt-br/reference/rule-api.mdxdocs/src/content/docs/reference/rule-api.mdxdocs/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, usesafeParse(), and reuseAdrFrontmatterSchema.shape.*to avoid duplicating enums.
Files:
src/formats/rules.ts
src/formats/rules.ts
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-022-ast-aware-rule-context.md)
Expose exactly one
RuleContext.ast(path: string, language: AstLanguage, opts?: AstOptions): Promise<AstNode>method, withtypescript,javascript,python, andrubylanguage support; do not add per-language AST methods.
Files:
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 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
src/engine/runner.ts
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-022-ast-aware-rule-context.md)
src/engine/runner.ts: Implement AST dispatch internally increateRuleContext(); rule authors must not directly access subprocess or filesystem primitives.
Do not trustnode.locfor TypeScript parsed throughBun.Transpiler; re-locate findings in the original source. JavaScript locations are source-accurate.
Files:
src/engine/runner.ts
src/engine/{runner,ast-support}.ts
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-022-ast-aware-rule-context.md)
src/engine/{runner,ast-support}.ts: For Python and Ruby AST parsing, perform guardrails in exactly this order before spawning: safe path validation, language plausibility validation, cached interpreter availability probing, then guarded invocation.
UseBun.spawnwith array-based arguments only for Python/Ruby AST subprocesses; never use shell interpolation,Bun.$, or raw command strings.
Run Python AST subprocesses with isolated mode (python -I -c ...) to prevent the target project's working directory from shadowing standard-library modules.
Probe platform-appropriate Python executable names (python3/pythonon non-Windows;python/python3/pyon Windows usingisWindows()), select the first available executable, and cache the result once per check invocation.
Reject files whose extension or leading content is implausible for the requested AST language before invoking Python or Ruby.
ctx.ast()must throw on missing interpreters and parse failures, with distinguishable error messages; it must never returnnullor another silent-failure sentinel.
For base Python/Ruby parsing, use a temporary file and the same guarded serializer invocation; do not bypass path safety, language checks, interpreter probing, or Python-Iisolation.
Strip a leading UTF-8 BOM before Python and Ruby parsing using UTF-8-with-BOM handling.
Python comments must usetokenize, Ruby comments must use a secondRipper.lexpass, and tokenizer/lexing failures on otherwise parseable files must degrade to an empty comment list.
Do not normalize Python or Ruby AST output into ESTree; return each language's native AST shape, documenting that shapes differ by language.
Files:
src/engine/runner.tssrc/engine/ast-support.ts
src/engine/{runner,ast-support,js-parser}.ts
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-022-ast-aware-rule-context.md)
src/engine/{runner,ast-support,js-parser}.ts: TypeScript and JavaScript AST parsing must reuse the existing in-processmeriyahparser; factor duplicatedparseModule()calls inrule-scanner.tsinto one shared exported helper used by both scanner andctx.ast().
Implement opt-in{ comments: true }onast()with a rootcommentsarray of{ type, value, loc }; omit the array unless requested.
Files:
src/engine/runner.tssrc/engine/ast-support.ts
src/engine/{runner,ast-support,git-files}.ts
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-022-ast-aware-rule-context.md)
Support
ast(path, language, { rev: "base" })andfileAtBase(path)using the merge base of--baseand HEAD; base AST parsing must retain the same guardrails and failure semantics.
Files:
src/engine/runner.tssrc/engine/ast-support.ts
src/engine/**
📄 CodeRabbit inference engine (.archgate/adrs/ARCH-022-ast-aware-rule-context.md)
src/engine/**: Do not addtree-sitter,web-tree-sitter, native language bindings, WASM grammars, or other new production parser dependencies under this decision.
Do not addBun.spawn,Bun.spawnSync, orchild_processsubprocess calls outside the sanctioned AST support andgit-files.tssites; rule code must not shell out to git or interpreters.
Files:
src/engine/runner.tssrc/engine/ast-support.ts
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
🧠 Learnings (2)
📚 Learning: 2026-07-02T16:03:33.031Z
Learnt from: rhuanbarreto
Repo: archgate/cli PR: 446
File: src/helpers/session-context-opencode.ts:81-100
Timestamp: 2026-07-02T16:03:33.031Z
Learning: For synchronous helper functions that use Bun’s sqlite sync API (i.e., they must remain synchronous), it’s acceptable to use `existsSync` from `node:fs` to check whether the SQLite database file exists. Avoid using `Bun.file(path).exists()` for this purpose because it’s async and would force the helper to become async (no equivalent synchronous Bun alternative). If the DB file is missing, throw/return a clear, actionable "No database found" error (per ARCH-006) rather than letting the sqlite open fail with a generic DB-open error.
Applied to files:
src/helpers/rules-shim.ts
📚 Learning: 2026-07-11T13:03:15.386Z
Learnt from: rhuanbarreto
Repo: archgate/cli PR: 467
File: .archgate/adrs/ARCH-011-consistent-project-root-resolution.md:0-0
Timestamp: 2026-07-11T13:03:15.386Z
Learning: For Markdown files formatted by oxfmt (especially ADRs), avoid inline code spans that contain escaped backticks, e.g. `\`...\`` inside a single `` `...` `` span. oxfmt may mis-parse these and, on re-format, can collapse spaces after later inline code spans on the same line, effectively removing any manually re-added spacing. Instead, rephrase the text so the message stays plain quoted text, and put any embedded command/fragment that needs code formatting (e.g., `archgate init`) in its own separate inline code span; keep surrounding punctuation/spacing outside the code span.
Applied to files:
.archgate/adrs/ARCH-022-ast-aware-rule-context.md
🪛 LanguageTool
docs/src/content/docs/pt-br/reference/rule-api.mdx
[uncategorized] ~244-~244: Pontuação duplicada
Context: ...e retornada carrega um array comments -- dados estruturados de comentário para r...
(DOUBLE_PUNCTUATION_XML)
[uncategorized] ~271-~271: 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] ~271-~271: Pontuação duplicada
Context: ...anspilado para TypeScript (veja AstNode): os comentários são varridos a partir d...
(DOUBLE_PUNCTUATION_XML)
[uncategorized] ~271-~271: 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] ~271-~271: Pontuação duplicada
Context: ... Python são sempre type: "line" (#) -- Python não tem comentários de bloco, e ...
(DOUBLE_PUNCTUATION_XML)
[typographical] ~271-~271: 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] ~271-~271: 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] ~271-~271: 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] ~271-~271: “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] ~271-~271: “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)
.archgate/adrs/ARCH-022-ast-aware-rule-context.md
[style] ~111-~111: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ... it is opt-in and absent otherwise. - DON'T expect Ruby comment loc columns ...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
🔇 Additional comments (13)
tests/engine/ast-support.test.ts (2)
11-11: LGTM!
297-325: LGTM!Also applies to: 339-368, 391-425, 430-455, 457-470
tests/engine/runner-ast-comments.test.ts (2)
19-27: LGTM!
198-200: LGTM!Also applies to: 214-250, 252-269
src/formats/rules.ts (1)
242-246: LGTM!src/helpers/rules-shim.ts (1)
230-234: LGTM!docs/public/llms-full.txt (1)
5425-5425: LGTM!docs/src/content/docs/nb/reference/rule-api.mdx (1)
271-271: LGTM!docs/src/content/docs/pt-br/reference/rule-api.mdx (1)
271-271: LGTM!docs/src/content/docs/reference/rule-api.mdx (1)
271-271: LGTM!.archgate/adrs/ARCH-022-ast-aware-rule-context.md (1)
66-72: LGTM!src/engine/ast-support.ts (1)
147-211: LGTM!src/engine/runner.ts (1)
288-294: LGTM!
## 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>
- widen the AstNode fallback union to RubyAstProgram in rules.ts and rules-shim.ts so non-literal-language callers get typed access to the comments property (RubyAstNode stays exported for nested nodes) - use Bun.write instead of writeFileSync in the new async test callbacks, per the Bun built-ins guideline - add a Ripper.lex-failure test covering the rescue-StandardError degrade path: parse still exits 0 with a valid tree and an empty comments list Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
|
Addressed review feedback in d86a6c3: the AstNode fallback union in rules.ts and rules-shim.ts now uses RubyAstProgram (RubyAstNode stays exported for nested-node typing); the new async test callbacks in ast-support.test.ts and runner-ast-comments.test.ts write fixtures via Bun.write; and a new test forces Ripper.lex to raise (monkey-patch prelude, shipped program unmodified) to cover the rescue-StandardError degrade path — exit 0, valid _tree, comments: []. |
|
@coderabbitai resume |
✅ Action performedReviews resumed. |
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 #484
Summary
ctx.ast(path, "ruby", { comments: true })now returns theRipper.sexptree with acomments: CommentToken[]array attached, instead of throwingcommentsUnsupportedError. Ruby was the lastAstLanguagewithout comment access.Design decisions
RUBY_AST_WITH_COMMENTS_PROGRAMinsrc/engine/ast-support.tsrunsRipper.sexpfor the tree plus a second, independentRipper.lexpass for comments, emitting the exact{"_tree", "comments"}envelope the Python with-comments serializer uses. The sharedfinalizeAstResult()unwrap now handles both languages.:on_commentlex events becometype: "line"tokens: leading#stripped, trailing newline chomped,locfrom the(line, col)lex tuple with the end column at the chomped token end — matching Python/TS-JS value and position semantics.=begin/=endblock comments are INCLUDED (explicit decision, not scoped out): the:on_embdoc_beg/:on_embdoc/:on_embdoc_endevents of each region are combined into ONEtype: "block"token whosevalueis the inner content (marker lines stripped, analogous to TS/JS stripping/* */) and whoselocspans the=beginline through the=endline.rescue StandardError, resetting to an empty comment list, so a lex failure on otherwise-parseable source never fails the whole parse (matches Python's tokenizer-error fallback).commentsrides on the returned sexp as a non-index property. A newRubyAstProgramroot type (extendsArray<unknown>, optionalcomments) types this insrc/formats/rules.tsand the generated rules shim, mirroringEsTreeProgram/PythonAstModule.runner.tsis gone, andcommentsUnsupportedErroris deleted entirely: the Ruby guard was its only remaining call site.Ripper.lexreports columns as byte offsets, which drift from the Python/TS character convention on non-ASCII lines. The serializer converts them to character offsets (via abytesliceof the source line), so commentloccolumns share one unit across all four languages; the sexp tree's own node positions stay byte-based, as Ripper emits them. Pinned by a non-ASCII end-to-end test.\rfrom CRLF files while POSIX preserves it, so the same checked-in file would have produced platform-dependent=begin/=endvalues. Blockvalueline endings are now normalized to LF on every OS, pinned by a CRLF end-to-end test.{ comments: true }throws / deferred follow-up" prose (this issue IS that follow-up) is replaced with the shipped behavior, including the column-unit and LF-normalization conventions.Acceptance criteria
ctx.ast(path, "ruby", { comments: true })returns the tree withcomments: CommentToken[]instead of throwing — covered bytests/engine/runner-ast-comments.test.tsthroughrunChecks.valuehas the leading#stripped (and trailing newline chomped), matching Python/TS-JS convention.rescue StandardErrorin the serializer, mirroring Python'stokenizefallback). The fallback path itself is not unit-tested — same coverage level as the Python program, since a deterministicRipper.lex-only failure is not readily constructible.=begin/=end: included astype: "block", one token per region, marker lines stripped,locspanning=beginthrough=end— documented and tested.runner.ts's early throw removed;commentsUnsupportedErrordeleted (Ruby was its last case; knip is clean).docs/*/reference/rule-api.mdxin all three locales (en, nb, pt-br);llms-full.txtregenerated.#line comments (leading, trailing, and a#inside a string that must NOT match) and an=begin/=endblock verifyvalueandlocfor both token types, at both the serializer level (tests/engine/ast-support.test.ts) and throughrunChecks(tests/engine/runner-ast-comments.test.ts). Tests skip when norubyinterpreter is on PATH, following the existing pattern.Validation
bun run validatepasses (lint, typecheck, format:check, tests, ADR check, knip, build check);archgate checkreports 44/44 rules passing.