Skip to content

fix: handle parse errors in rule scanner and loader gracefully#432

Merged
rhuanbarreto merged 1 commit into
mainfrom
claude/focused-mcclintock-edfb80
Jun 27, 2026
Merged

fix: handle parse errors in rule scanner and loader gracefully#432
rhuanbarreto merged 1 commit into
mainfrom
claude/focused-mcclintock-edfb80

Conversation

@rhuanbarreto

Copy link
Copy Markdown
Contributor

Summary

  • Fix unhandled AggregateError: Parse error crash during archgate check when user .rules.ts files contain syntax errors (Sentry #130690158)
  • Wrap Bun.Transpiler.transformSync(), meriyah.parseModule(), and dynamic import() in try-catch blocks in the rule scanner and loader
  • Return structured blocked results with actionable violation messages instead of crashing

Context

When a .rules.ts file has a syntax error, Bun.Transpiler.transformSync() throws an AggregateError with BuildMessage inner errors. This was unhandled in both scanRuleSource() and scanImportedRuleSource(). Similarly, the import() call in loadRuleAdrs() was unhandled — if a file somehow passes the scanner but fails at import time, it would also crash.

The fix ensures all three error paths return violations pointing at line 1 of the offending file, surfacing the first inner error message for diagnostic clarity.

Test plan

  • New tests: scanRuleSource returns violation for unparseable source (2 cases)
  • New tests: scanImportedRuleSource returns violation for unparseable source
  • New test: loadRuleAdrs returns blocked result for .rules.ts with syntax errors
  • All 1310 existing tests pass
  • bun run validate passes (lint, typecheck, format, test, ADR check, build)

Bun.Transpiler.transformSync() and import() throw AggregateError when
.rules.ts files contain syntax errors. These were unhandled, causing
archgate check to crash instead of reporting the file as blocked.

Wrap transpiler, parser, and dynamic import calls in try-catch blocks
and return structured violation results so the error surfaces as a
check failure rather than an unhandled exception.

Fixes Sentry issue 130690158.

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

coderabbitai Bot commented Jun 27, 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: a09b6f93-fc4c-435c-81b6-4f30f7c1cf5c

📥 Commits

Reviewing files that changed from the base of the PR and between 3959a33 and 775c544.

📒 Files selected for processing (4)
  • src/engine/loader.ts
  • src/engine/rule-scanner.ts
  • tests/engine/loader.test.ts
  • tests/engine/rule-scanner.test.ts
📜 Recent review details
⏰ Context from checks skipped due to timeout. (11)
  • GitHub Check: Cursor Bugbot
  • GitHub Check: Lint, Test & Check
  • GitHub Check: Smoke Test (Windows) / Windows
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (actions)
  • GitHub Check: Analyze (csharp)
  • GitHub Check: Analyze (python)
  • GitHub Check: Analyze (java-kotlin)
  • GitHub Check: Analyze (go)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Cloudflare Pages
⚠️ CI failures not shown inline (2)

GitHub Actions: DCO / DCO Sign-off Check: fix: handle parse errors in rule scanner and loader gracefully

Conclusion: failure

View job details

##[group]Run base="3959a330766b3688a384868d80a0a62534ddae10"
 �[36;1mbase="3959a330766b3688a384868d80a0a62534ddae10"�[0m
 �[36;1mhead="775c544c8c1e441b3946c2b3c8e18476040e5775"�[0m
 �[36;1mfailed=0�[0m
 �[36;1m�[0m
 �[36;1mfor sha in $(git rev-list --no-merges "$base".."$head"); do�[0m
 �[36;1m  if ! git log -1 --format='%B' "$sha" | grep -qiE '^Signed-off-by: .+ <.+>'; then�[0m
 �[36;1m    echo "::error::Commit $sha is missing a DCO Signed-off-by line."�[0m

GitHub Actions: DCO / 0_DCO Sign-off Check.txt: fix: handle parse errors in rule scanner and loader gracefully

Conclusion: failure

View job details

##[group]Run base="3959a330766b3688a384868d80a0a62534ddae10"
 �[36;1mbase="3959a330766b3688a384868d80a0a62534ddae10"�[0m
 �[36;1mhead="775c544c8c1e441b3946c2b3c8e18476040e5775"�[0m
 �[36;1mfailed=0�[0m
 �[36;1m�[0m
 �[36;1mfor sha in $(git rev-list --no-merges "$base".."$head"); do�[0m
 �[36;1m  if ! git log -1 --format='%B' "$sha" | grep -qiE '^Signed-off-by: .+ <.+>'; then�[0m
 �[36;1m    echo "::error::Commit $sha is missing a DCO Signed-off-by line."�[0m
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Use TypeScript strict mode, ESNext target, and ES modules throughout
Use safeParse() when validating with Zod schemas
Use minimal dependencies; prefer Bun built-ins per ARCH-006

Files:

  • tests/engine/loader.test.ts
  • tests/engine/rule-scanner.test.ts
  • src/engine/loader.ts
  • src/engine/rule-scanner.ts
tests/**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Test files must mirror src/ directory structure with fixtures in tests/fixtures/

Files:

  • tests/engine/loader.test.ts
  • tests/engine/rule-scanner.test.ts
**/*.{ts,tsx,json}

📄 CodeRabbit inference engine (CLAUDE.md)

Runtime must use Bun (>=1.2.21), not Node.js compatible

Files:

  • tests/engine/loader.test.ts
  • tests/engine/rule-scanner.test.ts
  • src/engine/loader.ts
  • src/engine/rule-scanner.ts
**

⚙️ CodeRabbit configuration file

**: # CLAUDE.md

Archgate is a CLI tool for AI governance via Architecture Decision Records (ADRs) — combining human-readable docs with machine-checkable rules. The CLI dogfoods itself via ADRs in .archgate/adrs/. AI features are delivered as a Claude Code plugin (../plugins/claude-code), not via direct API calls.

Technology Stack

  • Runtime: Bun (>=1.2.21) — not Node.js compatible
  • Language: TypeScript (strict mode, ESNext, ES modules)
  • CLI framework: Commander.js (@commander-js/extra-typings)
  • Linter: Oxlint | Formatter: Oxfmt | Dead exports: Knip | Commits: Conventional Commits

Commands

bun run src/cli.ts <command>  # run CLI locally
bun run lint                  # oxlint
bun run typecheck             # tsc --build
bun run format                # oxfmt --write
bun run format:check          # oxfmt --check
bun run test                  # all tests (not bare `bun test` — picks up --timeout; see GEN-003)
bun run knip                  # dead export detection
bun run validate              # MANDATORY: lint + typecheck + format + test + ADR check + knip + build check
bun run build:check            # verify build compiles (CI builds binaries via release workflow)
bun run commit                # conventional commit wizard

Validation Gate

bun run validate must pass before any task is considered complete. Fail-fast pipeline: lint → typecheck → format → test → ADR check → knip → build check. Mirrors CI in .github/workflows/code-pull-request.yml.

Git Hooks (Git 2.54+)

Config-based hooks in .githooks run validation locally before commits and pushes:

  • pre-commit: lint + typecheck + format:check (~15s)
  • pre-push: full bun run validate (~60s, mirrors CI)

Activate once per clone:

git config --local include.path ../.githooks

Opt out of a specific hook: git config --local hook.<name>.enabled false. Skip all hooks for a single commit: git commit --no-verify.

Architectu...

Files:

  • tests/engine/loader.test.ts
  • tests/engine/rule-scanner.test.ts
  • src/engine/loader.ts
  • src/engine/rule-scanner.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:

  • tests/engine/loader.test.ts
  • tests/engine/rule-scanner.test.ts
  • src/engine/loader.ts
  • src/engine/rule-scanner.ts
src/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

AI features must be delivered as a Claude Code plugin (../plugins/claude-code), not via direct API calls

Files:

  • src/engine/loader.ts
  • src/engine/rule-scanner.ts
🔇 Additional comments (4)
src/engine/rule-scanner.ts (1)

49-87: LGTM!

Also applies to: 244-279

tests/engine/rule-scanner.test.ts (1)

257-273: LGTM!

Also applies to: 423-431

src/engine/loader.ts (1)

312-342: LGTM!

tests/engine/loader.test.ts (1)

208-233: LGTM!


📝 Walkthrough

Walkthrough

scanRuleSource and scanImportedRuleSource in src/engine/rule-scanner.ts now wrap the Bun transformSync transpilation and parseModule AST steps in try/catch blocks, returning a single ScanViolation with a Parse error: message and position at line 1/column 0 instead of throwing. loadRuleAdrs in src/engine/loader.ts similarly wraps each dynamic import() of companion .rules.ts files in a try/catch, converting failures into a blocked LoadResult with a violation at line 1. New tests in both test files verify these error paths.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: graceful handling of parse errors in the rule scanner and loader.
Description check ✅ Passed The description matches the changeset and explains the error handling fix, affected code paths, and added tests.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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.

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying archgate-cli with  Cloudflare Pages  Cloudflare Pages

Latest commit: 775c544
Status: ✅  Deploy successful!
Preview URL: https://d974146b.archgate-cli.pages.dev
Branch Preview URL: https://claude-focused-mcclintock-ed.archgate-cli.pages.dev

View logs

@github-actions

Copy link
Copy Markdown
Contributor

Code Coverage

Metric Value
Lines 90.0% (6933 / 7706)
Threshold 90% minimum — met
Platforms Linux + Windows

Full HTML report available in workflow artifacts.

Per-directory breakdown
Directory Coverage Lines
src/commands/ 88.1% 1874 / 2128
src/engine/ 90.9% 1463 / 1610
src/formats/ 100.0% 142 / 142
src/helpers/ 90.3% 3454 / 3826

@rhuanbarreto rhuanbarreto merged commit 7c384d2 into main Jun 27, 2026
20 checks passed
@rhuanbarreto rhuanbarreto deleted the claude/focused-mcclintock-edfb80 branch June 27, 2026 19:39
@archgatebot archgatebot Bot mentioned this pull request Jun 27, 2026
rhuanbarreto pushed a commit that referenced this pull request Jun 27, 2026
# archgate

## [0.45.7](v0.45.6...v0.45.7)
(2026-06-27)

### Bug Fixes

* **deps:** update docs dependencies
([#437](#437))
([e8f10c1](e8f10c1))
* handle parse errors in rule scanner and loader gracefully
([#432](#432))
([7c384d2](7c384d2)),
closes [#130690158](https://github.com/archgate/cli/issues/130690158)
* resolve all knip unused dependency and unlisted binary warnings
([#434](#434))
([d7690b2](d7690b2))

---
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.

1 participant