Skip to content

docs(adr): add AST-aware rule context ADR and PRD#451

Merged
rhuanbarreto merged 16 commits into
mainfrom
claude/playful-orbiting-reddy
Jul 5, 2026
Merged

docs(adr): add AST-aware rule context ADR and PRD#451
rhuanbarreto merged 16 commits into
mainfrom
claude/playful-orbiting-reddy

Conversation

@rhuanbarreto

Copy link
Copy Markdown
Contributor

Summary

  • Adds ARCH-022 — AST-Aware Rule Context, documenting the decision to expose ctx.ast(path, language) on RuleContext: reuses the existing in-process meriyah parser for TypeScript/JavaScript, and shells out via guarded Bun.spawn to each language's own standard-library AST facility (Python's ast module, Ruby's Ripper) for Python/Ruby — no new production dependency, no raw subprocess access ever exposed to rule authors.
  • Adds a companion PRD at .archgate/PRDs/ast-aware-rule-context.md (new folder) covering product scope, rollout sequencing (TS/JS first, replacing the fragile regex heuristics in ARCH-004/ARCH-008), failure-messaging requirements, and success criteria — kept separate from the ADR so architecture decisions and product requirements don't get conflated.
  • rules: false on ARCH-022 for now — this is a decision record ahead of implementation; a follow-up will add automated enforcement once ctx.ast() ships.

This branch also already carries a few unrelated prior commits ahead of main (release-pipeline CI fixes for publish-shims/release-binaries, gating the CLI's background update-check notice to interactive TTY sessions, and agent-memory notes) — included here since they were already on the branch.

Test plan

  • bun run cli check — 39/39 passing, no ADR violations
  • bun run format — applied to new markdown files
  • Reviewer confirms ARCH-022 doesn't overlap/conflict with ARCH-006/ARCH-007
  • Follow-up PR implements ctx.ast() per ARCH-022 and rewrites ARCH-004/ARCH-008 rules as validation

https://claude.ai/code/session_0111cP3vNZMpGRA8tcnGE7oc

…ng on release event

publish-shims.yml and release-binaries.yml both triggered on `release:
published`, racing each other: if the binary build needed a retry,
publish-shims.yml's fixed-budget wait-for-binaries poll timed out and
went `cancelled` (terminal) before the retry finished, silently
skipping shim publishing for that release.

publish-shims.yml is now workflow_dispatch-only; release-binaries.yml
dispatches it via `gh workflow run` once binaries + provenance succeed.

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

main() unconditionally printed an "update available" notice to stdout
after every command, with no gating. Any script, `| jq`, or agent
parsing stdout as JSON would have it corrupted whenever a newer
release happened to be available.

Add shouldPerformUpdateCheck() and use it to skip the check entirely
outside a genuine interactive terminal (piped output, CI, or the
upgrade command itself) — same guard shape as the existing
showFirstRunNoticeIfNeeded().

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
…ess feedback

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
…t rejected

git push origin "shims/go/\$TAG" was failing with "refusing to allow a
GitHub App to create or update workflow .github/workflows/release.yml
without workflows permission" — GitHub rejects any ref push reachable
through commits touching .github/workflows/*, even for an unrelated
tag, unless the token has workflows: write. Confirmed on v0.45.7's
publish-go-tag job log.

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
Document the decision to expose ctx.ast(path, language) on RuleContext,
reusing the existing meriyah parser for TS/JS and shelling out to each
language's own stdlib AST facility (Python's ast module, Ruby's Ripper)
for Python/Ruby, gated behind path-safety, language-plausibility, and
interpreter-availability guardrails so no raw subprocess access is ever
exposed to rule authors. Requires no new production dependency.

The PRD is kept separate to isolate product scope/rollout/success
criteria from the architectural decision itself.

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

coderabbitai Bot commented Jul 3, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR adds documentation-only changes across a new AST-aware RuleContext.ast() PRD and ADR, CI workflow validation guidance, agent-memory updates, hook and worktree contracts, release and CI gotchas, publishing notes, test isolation, Windows subprocess behavior, i18n quality, PR review triage, and the Cursor approval reference. It also updates MEMORY.md, CLAUDE.md, and several GitHub workflow files to reflect the documented rules and validation requirements.

Changes

Related Issues: None provided.

Related PRs: None provided.

Suggested labels: documentation, ci, adr, workflow

Suggested reviewers: None provided.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding an AST-aware rule context ADR and companion PRD.
Description check ✅ Passed The description is directly related to the ADR/PRD changes and accurately reflects the scope and rollout plan.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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

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

Copy link
Copy Markdown

Deploying archgate-cli with  Cloudflare Pages  Cloudflare Pages

Latest commit: 0273222
Status: ✅  Deploy successful!
Preview URL: https://b7c4a111.archgate-cli.pages.dev
Branch Preview URL: https://claude-playful-orbiting-redd.archgate-cli.pages.dev

View logs

@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: 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 @.claude/agent-memory/archgate-developer/project_release_pipeline_gotchas.md:
- Around line 8-13: The summary count is inconsistent with the body because the
intro says three issues while the list contains four numbered items. Update the
opening sentence in project_release_pipeline_gotchas.md to match the actual
number of bullets, and verify the numbering/wording stays aligned with the
sections describing publish-shims.yml, release-binaries.yml,
moonrepo/setup-toolchain, src/cli.ts with shouldPerformUpdateCheck(), and
publish-go-tag permissions.

In @.github/workflows/publish-shims.yml:
- Around line 60-62: The checkout steps in the non-pushing publish jobs still
persist git credentials, which is unnecessary and should be disabled. Update the
affected `actions/checkout` usages in the publish jobs that only build or
publish artifacts to set `persist-credentials: false`, while leaving
`publish-go-tag` unchanged since it needs push access. Use the
`actions/checkout` step in each job as the reference point when applying the
same change across the four non-pushing workflows.
- Around line 26-32: The `wait-for-binaries` and `publish-go-tag` steps are
using direct template interpolation for `TAG`, which triggers template-injection
warnings. Move `inputs.tag` into each step’s `env:` block in
`.github/workflows/publish-shims.yml`, then reference `TAG` from the shell
script body instead of assigning it with `${{ ... }}`. Keep the change scoped to
the affected steps and preserve the existing `REQUIRED_ASSETS` and tag-based
logic.
- Around line 106-121: The publish-go-tag job in publish-shims.yml is using an
unsupported workflows permission, which makes the workflow invalid. Remove the
workflows: write entry from the permissions block and keep only the required
permissions for the checkout and git push steps, using the publish-go-tag job
and its Create Go module tag step as the place to fix it.

In @.github/workflows/release-binaries.yml:
- Around line 174-190: Move the tag selection out of the shell body in
trigger-shim-publish and pass it via env: so the run script only references a
plain TAG variable, using the existing github.event.release.tag_name /
inputs.tag expression in the step environment instead of inline substitution.
Keep the gh workflow run command unchanged except for consuming that env var,
and add a brief comment near the actions: write permission in the same job
explaining why it is required.
🪄 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: ce5f6ddf-28d0-47ae-a505-9a1b94b3b5f5

📥 Commits

Reviewing files that changed from the base of the PR and between fc209b3 and 367e6da.

📒 Files selected for processing (11)
  • .archgate/PRDs/ast-aware-rule-context.md
  • .archgate/adrs/ARCH-022-ast-aware-rule-context.md
  • .claude/agent-memory/archgate-developer/MEMORY.md
  • .claude/agent-memory/archgate-developer/feedback_concise_comments.md
  • .claude/agent-memory/archgate-developer/project_release_pipeline_gotchas.md
  • .github/workflows/publish-shims.yml
  • .github/workflows/release-binaries.yml
  • CLAUDE.md
  • src/cli.ts
  • src/helpers/update-check.ts
  • tests/helpers/update-check.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (2)
  • GitHub Check: Smoke Test (Windows) / Windows
  • GitHub Check: Cloudflare Pages
⚠️ CI failures not shown inline (4)

GitHub Actions: DCO / 0_DCO Sign-off Check.txt: docs(adr): AST-aware RuleContext (ARCH-022) + PRD

Conclusion: failure

View job details

##[group]Run base="fc209b3cc8dca78685ee60b4794698d17e368ebf"
 �[36;1mbase="fc209b3cc8dca78685ee60b4794698d17e368ebf"�[0m
 �[36;1mhead="367e6da1a789dffb08e4d6c10b5cbd9bf8c11417"�[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 / DCO Sign-off Check: docs(adr): AST-aware RuleContext (ARCH-022) + PRD

Conclusion: failure

View job details

##[group]Run base="fc209b3cc8dca78685ee60b4794698d17e368ebf"
 �[36;1mbase="fc209b3cc8dca78685ee60b4794698d17e368ebf"�[0m
 �[36;1mhead="367e6da1a789dffb08e4d6c10b5cbd9bf8c11417"�[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: Code Quality: PR #451 / 3_Analyze (go).txt: Code Quality: PR #451

Conclusion: failure

View job details

Extracting types for package crypto/aes.
 [] [build-stderr] 2026/07/03 14:34:48 Done extracting types for package crypto/aes.
 [] [build-stderr] 2026/07/03 14:34:48 Processing package crypto/des.
 [] [build-stderr] 2026/07/03 14:34:48 Extracting types for package crypto/des.
 [] [build-stderr] 2026/07/03 14:34:48 Done extracting types for package crypto/des.
 [] [build-stderr] 2026/07/03 14:34:48 Processing package crypto/internal/fips140/nistec/fiat.
 [] [build-stderr] 2026/07/03 14:34:48 Extracting types for package crypto/internal/fips140/nistec/fiat.
 [] [build-stderr] 2026/07/03 14:34:48 Done extracting types for package crypto/internal/fips140/nistec/fiat.
 [] [build-stderr] 2026/07/03 14:34:48 Processing package crypto/internal/fips140/nistec.
 [] [build-stderr] 2026/07/03 14:34:48 Extracting types for package crypto/internal/fips140/nistec.
 [] [build-stderr] 2026/07/03 14:34:48 Done extracting types for package crypto/internal/fips140/nistec.
 [] [build-stderr] 2026/07/03 14:34:48 Processing package crypto/internal/fips140/ecdh.
 [] [build-stderr] 2026/07/03 14:34:48 Extracting types for package crypto/internal/fips140/ecdh.
 [] [build-stderr] 2026/07/03 14:34:48 Done extracting types for package crypto/internal/fips140/ecdh.
 [] [build-stderr] 2026/07/03 14:34:48 Processing package crypto/internal/fips140/edwards25519/field.
 [] [build-stderr] 2026/07/03 14:34:48 Extracting types for package crypto/internal/fips140/edwards25519/field.
 [] [build-stderr] 2026/07/03 14:34:48 Done extracting types for package crypto/internal/fips140/edwards25519/field.
 [] [build-stderr] 2026/07/03 14:34:48 Processing package crypto/ecdh.
 [] [build-stderr] 2026/07/03 14:34:48 Extracting types for package crypto/ecdh.
 [] [build-stderr] 2026/07/03 14:34:48 Done extracting types for package crypto/ecdh.
 [] [build-stderr] 2026/07/03 14:34:48 Processing package crypto/elliptic.
 [] [build-stderr] 2026/07/03 14:34:48 Extracting types for package crypto/elliptic.
 [] [build-st...

GitHub Actions: Code Quality: PR #451 / Analyze (go): Code Quality: PR #451

Conclusion: failure

View job details

,"bundleSupportsIncludeLogs":true,"bundleSupportsOverlay":true,"databaseInterpretResultsSupportsSarifRunProperty":true,"featuresInVersionResult":true,"indirectTracingSupportsStaticBinaries":false,"informsAboutUnsupportedPathFilters":true,"supportsPython312":true,"mrvaPackCreate":true,"threatModelOption":true,"traceCommandUseBuildMode":true,"v2ramSizing":true,"mrvaPackCreateMultipleQueries":true,"setsCodeqlRunnerEnvVar":true,"sarifMergeRunsFromEqualCategory":true,"forceOverwrite":true,"generateSummarySymbolMap":true,"pythonDefaultIsToNotExtractStdlib":true,"queryServerRunQueries":true,"queryServerTrimCacheWithMode":true,"builtinExtractorsSpecifyDefaultQueries":true,"bqrsDiffResultSets":true,"bundleSupportsIncludeOption":true,"suppressesMissingFileBaselineWarning":true}}}
   CODEQL_ACTION_GO_BINARY: /home/runner/work/_temp/codeql-action-go-tracing/bin/go
   CODEQL_RAM: 14575
   CODEQL_THREADS: 4
   CODEQL_PROXY_HOST:
   CODEQL_PROXY_PORT:
   CODEQL_PROXY_CA_CERTIFICATE:
   CODEQL_PROXY_URLS:
 ##[endgroup]
 ##[group]Attempting to automatically build go code
 [command]/opt/hostedtoolcache/CodeQL/2.25.6/x64/codeql/codeql database trace-command --use-build-mode --working-dir /home/runner/work/cli/cli /home/runner/work/_temp/codeql_databases/go
 Picked up JAVA_TOOL_OPTIONS:  -Dhttp.keepAlive=false -Dmaven.wagon.http.pool=false
 Running command in /home/runner/work/cli/cli: [/opt/hostedtoolcache/CodeQL/2.25.6/x64/codeql/go/tools/autobuild.sh]
 [] [build-stderr] 2026/07/03 14:34:39 Autobuilder was built with go1.26.0, environment has go1.24.13
 [] [build-stderr] 2026/07/03 14:34:39 LGTM_SRC is /home/runner/work/cli/cli
 [] [build-stderr] 2026/07/03 14:34:39 Found no go.work files in the workspace; looking for go.mod files...
 [] [build-stderr] 2026/07/03 14:34:39 Found 1 go.mod files in: shims/go/go.mod.
 [] [build-stderr] 2026/07/03 14:34:39 Found 1 go.mod file(s).
 [] [build-stderr] 2026/07/03 14:34:39 Import path is 'github.com/archgate/cli'
 [] [build-stderr] 2026/07/...
🧰 Additional context used
📓 Path-based instructions (14)
**

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

GitHub Act...

Files:

  • CLAUDE.md
  • tests/helpers/update-check.test.ts
  • src/cli.ts
  • src/helpers/update-check.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:

  • CLAUDE.md
  • tests/helpers/update-check.test.ts
  • src/cli.ts
  • src/helpers/update-check.ts
.github/workflows/*.yml

📄 CodeRabbit inference engine (.archgate/adrs/CI-001-pin-github-actions-by-hash.md)

.github/workflows/*.yml: In GitHub Actions workflow files under .github/workflows/*.yml, every third-party uses: reference must be pinned to a full 40-character commit SHA and include a human-readable version comment on the same line (for example, uses: owner/action@<40-char-sha> # v4).
In GitHub Actions workflow files under .github/workflows/*.yml, do not reference third-party actions or reusable workflows by tag, branch, or abbreviated SHA; only a full 40-character commit SHA is allowed for third-party uses: entries.
In GitHub Actions workflow files under .github/workflows/*.yml, local workflow references (uses: ./.github/workflows/...) and local composite action references (uses: ./.github/actions/...) are exempt from SHA pinning because they stay within the same repository trust boundary.
In GitHub Actions workflow files under .github/workflows/*.yml, the slsa-framework/slsa-github-generator/.github/workflows/* reusable workflow is exempt from SHA pinning and must be referenced by tag (for example, @v2.1.0).

.github/workflows/*.yml: In GitHub Actions, confirm whether repo configuration lives in secrets.* or vars.* before wiring a workflow step; if a continue-on-error: true step has an internal skip guard, use ::warning:: or higher instead of ::notice:: so misconfiguration is visible.
Be careful when using moonrepo/setup-toolchain cache restores: a restore-key hit can leave bun off PATH even though the action reports success.

Files:

  • .github/workflows/release-binaries.yml
  • .github/workflows/publish-shims.yml
.github/workflows/*

📄 CodeRabbit inference engine (.archgate/adrs/GEN-003-tool-invocation-via-scripts.md)

.github/workflows/*: Do not use direct lint/format binary invocations such as bunx prettier, bunx oxfmt, npx eslint, oxlint ., or similar in GitHub Actions workflows; call the repository scripts instead.
In GitHub Actions workflows, do not run bare bun test; use bun run test so the script-level flags from package.json are applied.

Files:

  • .github/workflows/release-binaries.yml
  • .github/workflows/publish-shims.yml
.github/workflows/{publish-shims.yml,release-binaries.yml,release.yml}

📄 CodeRabbit inference engine (CLAUDE.md)

Chain downstream release workflows instead of parallel-triggering them from the release: published event.

Files:

  • .github/workflows/release-binaries.yml
  • .github/workflows/publish-shims.yml
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/helpers/update-check.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, 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:

  • tests/helpers/update-check.test.ts
  • src/cli.ts
  • src/helpers/update-check.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/helpers/update-check.test.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:

  • tests/helpers/update-check.test.ts
  • src/cli.ts
  • src/helpers/update-check.ts
src/cli.ts

📄 CodeRabbit inference engine (.archgate/adrs/ARCH-001-command-structure.md)

src/cli.ts: The main entry point must explicitly import and register every command; no auto-discovery is allowed.
All async bootstrap logic in src/cli.ts must be wrapped in an async main() function and invoked with main().catch((err) => { logError(String(err)); process.exit(2); }); top-level await is forbidden.
The CLI must run in-process in the same Bun process as the entry point; command execution should not rely on child processes.

Files:

  • src/cli.ts
src/**/*.ts

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

src/**/*.ts: Use logError() from src/helpers/log.ts for user-facing errors instead of printing errors directly.
Exit with code 1 for expected failures such as missing config, invalid input, or validation violations.
Let unexpected errors crash naturally so they are treated as internal errors with exit code 2.
Include actionable suggestions in user-facing error messages whenever possible.
Write user-facing errors to stderr via logError(); do not send them to stdout.
When findProjectRoot() returns null for commands that do not require .archgate/, fall back to process.cwd() as the path key or working directory.
Catch ExitPromptError from Inquirer in the top-level error boundary and treat it as user cancellation: exit with code 130 without logging an error or sending it to Sentry.
Do not use console.error() directly; use logError() for consistent formatting.
Do not exit with codes other than 0, 1, 2, or 130.
Do not send user-cancellation errors such as Inquirer ExitPromptError to Sentry; filter them in beforeSend.

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

Files:

  • src/cli.ts
  • src/helpers/update-check.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/cli.ts
  • src/helpers/update-check.ts
.archgate/adrs/**

⚙️ CodeRabbit configuration file

.archgate/adrs/**: ---
id: ARCH-001
title: Command Structure
domain: architecture
rules: true
files: ["src/commands/**/*.ts"]

Context

The CLI needs a consistent pattern for defining and registering commands. As the command surface grows (init, check, adr, review-context, session-context, upgrade, clean), the registration mechanism must scale without introducing hidden coupling or making the dependency graph opaque.

Alternatives considered:

  • Auto-discovery via executableDir() — Commander.js supports automatic command discovery by scanning a directory for executable files. This eliminates manual imports but hides the dependency graph: adding or removing a command has no type-checked reference, making dead command detection impossible. It also requires each command to be a standalone executable, which prevents in-process testing and forces separate process spawning for every subcommand invocation.
  • Plugin-based registration — A plugin system where commands register themselves via a manifest or hook (similar to Oclif or Clipanion). This adds flexibility for third-party extensions but introduces significant complexity for an internal CLI with a known, finite set of commands. The indirection makes it harder to trace which code handles which command.
  • Single-file command map — Define all commands in a single file as a map of name-to-handler. Simple but creates a monolithic file that grows with every command, making merge conflicts frequent and readability poor.

The explicit register pattern strikes the right balance: each command owns its registration logic, the entry point makes all commands visible at a glance, and in-process execution enables straightforward testing without process spawning.

Decision

Commands live in src/commands/ and export a register*Command(program) function. The main entry point (src/cli.ts) explicitly imports and calls each register function. Subcommands (e.g., adr create, adr list) use nested directories wi...

Files:

  • .archgate/adrs/ARCH-022-ast-aware-rule-context.md
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. Command files are exempt because they are the I/O layer.

Files:

  • src/helpers/update-check.ts
src/helpers/update-check.ts

📄 CodeRabbit inference engine (CLAUDE.md)

shouldPerformUpdateCheck() must gate checkForUpdatesIfNeeded() so update notices only print in TTY-only, non-CI sessions and do not corrupt piped or agent JSON output.

Files:

  • src/helpers/update-check.ts
🧠 Learnings (3)
📓 Common learnings
Learnt from: CR
Repo: archgate/cli

Timestamp: 2026-07-03T14:34:43.522Z
Learning: `RuleContext` must expose exactly one `ast(path, language)` method, and its dispatch must be internal to `createRuleContext()` in `src/engine/runner.ts` so rule authors never see which mechanism produced the AST.
Learnt from: CR
Repo: archgate/cli

Timestamp: 2026-07-03T14:34:43.522Z
Learning: Do not expose `Bun.spawn`, `child_process`, or any other raw subprocess primitive on `RuleContext`; `ctx.ast()` must be the only sanctioned path to language tooling.
Learnt from: CR
Repo: archgate/cli

Timestamp: 2026-07-03T14:34:43.522Z
Learning: Do not add `tree-sitter`, `web-tree-sitter`, or any other new production dependency for this feature.
Learnt from: CR
Repo: archgate/cli

Timestamp: 2026-07-03T14:34:43.522Z
Learning: Do not normalize Python/Ruby AST output into a unified ESTree-like shape as part of this ADR.
Learnt from: CR
Repo: archgate/cli

Timestamp: 2026-07-03T14:34:43.522Z
Learning: Rule reviewers must verify that no subprocess invocation for this feature uses `Bun.$` or any shell-interpolated command string.
Learnt from: CR
Repo: archgate/cli

Timestamp: 2026-07-03T14:35:04.170Z
Learning: Use Bun (>=1.2.21) as the runtime; the project is not Node.js compatible.
Learnt from: CR
Repo: archgate/cli

Timestamp: 2026-07-03T14:35:04.170Z
Learning: Before any task is considered complete, `bun run validate` must pass; the validation pipeline is lint → typecheck → format → test → ADR check → knip → build check.
Learnt from: CR
Repo: archgate/cli

Timestamp: 2026-07-03T14:35:04.170Z
Learning: Commands should export `register*Command(program)` and handle I/O only; business logic belongs elsewhere.
Learnt from: CR
Repo: archgate/cli

Timestamp: 2026-07-03T14:35:04.170Z
Learning: Use `styleText()` from `node:util` for output, support `--json` for machine-readable output, auto-compact JSON in agent contexts, and do not use emoji.
Learnt from: CR
Repo: archgate/cli

Timestamp: 2026-07-03T14:35:04.170Z
Learning: Use the repo’s exit-code convention: `0` success, `1` violation, `2` internal error, `130` user cancellation.
Learnt from: CR
Repo: archgate/cli

Timestamp: 2026-07-03T14:35:04.170Z
Learning: Prefer Bun built-ins and keep dependencies minimal.
📚 Learning: 2026-06-11T12:50:28.661Z
Learnt from: rhuanbarreto
Repo: archgate/cli PR: 406
File: .claude/agent-memory/archgate-developer/feedback_prefer_tests_over_adr_rules.md:8-18
Timestamp: 2026-06-11T12:50:28.661Z
Learning: In `archgate/cli`, for markdown files under `.claude/agent-memory/`, follow the established convention: use YAML frontmatter (with a `name:` field used as the document title) and do not require a top-level `#` (H1) heading. During code review, do not flag missing first-line/first-top-level H1 headings (e.g., MD041) for these agent-memory files since markdownlint is not part of the repo’s `bun run validate` lint pipeline (oxlint/oxfmt only).

Applied to files:

  • .claude/agent-memory/archgate-developer/feedback_concise_comments.md
  • .claude/agent-memory/archgate-developer/project_release_pipeline_gotchas.md
  • .claude/agent-memory/archgate-developer/MEMORY.md
📚 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/update-check.ts
🪛 actionlint (1.7.12)
.github/workflows/publish-shims.yml

[error] 111-111: unknown permission scope "workflows". all available permission scopes are "actions", "artifact-metadata", "attestations", "checks", "contents", "deployments", "discussions", "id-token", "issues", "models", "packages", "pages", "pull-requests", "repository-projects", "security-events", "statuses"

(permissions)

🪛 LanguageTool
.claude/agent-memory/archgate-developer/feedback_concise_comments.md

[uncategorized] ~10-~10: The official name of this software platform is spelled with a capital “H”.
Context: ...on where I wrote long comment blocks in .github/workflows/*.yml and src/cli.ts (mult...

(GITHUB)


[grammar] ~14-~14: Use a hyphen to join words.
Context: ...h with incident timelines, confirmed-via citations, or full backstory. Link to a ...

(QB_NEW_EN_HYPHEN)

.archgate/PRDs/ast-aware-rule-context.md

[style] ~10-~10: Consider using a different adjective in this context to strengthen your wording.
Context: ...cture_ (not just text patterns) have no good option today. They fall back to line-ba...

(GOOD_ALTERNATIVE)

.claude/agent-memory/archgate-developer/project_release_pipeline_gotchas.md

[uncategorized] ~13-~13: The official name of this software platform is spelled with a capital “H”.
Context: ...push reachable through commits touching .github/workflows/* without that permission, e...

(GITHUB)

.archgate/adrs/ARCH-022-ast-aware-rule-context.md

[style] ~12-~12: Consider an alternative for the overused word “exactly”.
Context: ...fic three-argument call shape. Both are exactly the class of check that is fragile with...

(EXACTLY_PRECISELY)


[style] ~23-~23: This phrase is redundant. Consider using “outside”.
Context: ...or TypeScript/JavaScript sitting unused outside of rule-scanner.ts. The lowest-cost path...

(OUTSIDE_OF)


[style] ~38-~38: Consider removing “of” to be more concise
Context: ...nandBun.spawnSyncfrom rule code). All of the following MUST execute insidecreateRu...

(ALL_OF_THE)


[grammar] ~92-~92: Ensure spelling is correct
Context: ...nner.ts's existing BLOCKED_BUN_PROPSsandbst continues to prevent.rules.ts` files ...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

🪛 markdownlint-cli2 (0.22.1)
.claude/agent-memory/archgate-developer/feedback_concise_comments.md

[warning] 8-8: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)

.claude/agent-memory/archgate-developer/project_release_pipeline_gotchas.md

[warning] 8-8: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)

🪛 zizmor (1.26.1)
.github/workflows/release-binaries.yml

[error] 189-189: code injection via template expansion (template-injection): may expand into attacker-controllable code

(template-injection)


[error] 189-189: code injection via template expansion (template-injection): may expand into attacker-controllable code

(template-injection)


[warning] 183-183: permissions without explanatory comments (undocumented-permissions): needs an explanatory comment

(undocumented-permissions)

.github/workflows/publish-shims.yml

[error] 30-30: code injection via template expansion (template-injection): may expand into attacker-controllable code

(template-injection)


[info] 20-20: workflow or action definition without a name (anonymous-definition): this job

(anonymous-definition)


[warning] 60-62: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)


[warning] 83-85: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)


[warning] 113-115: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)


[error] 118-118: code injection via template expansion (template-injection): may expand into attacker-controllable code

(template-injection)


[warning] 110-110: permissions without explanatory comments (undocumented-permissions): needs an explanatory comment

(undocumented-permissions)


[warning] 129-131: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)


[warning] 158-160: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)

🔇 Additional comments (10)
.archgate/PRDs/ast-aware-rule-context.md (1)

43-48: 🎯 Functional Correctness

Reconcile the v1 scope.

Line 43 says Python/Ruby ship in v1, but Line 48 says they follow TS/JS later. Please pick one rollout model so the acceptance criteria and delivery order are unambiguous.

.archgate/adrs/ARCH-022-ast-aware-rule-context.md (2)

35-43: 🩺 Stability & Availability

Verify the Python interpreter lookup on Windows.

This hardcodes python3, which is not a universal PATH alias on Windows. Please confirm the implementation will probe the platform-appropriate executable name(s) before locking this contract.


45-46: 🎯 Functional Correctness

Define the visible failure category more precisely.

This says ctx.ast() errors reuse existing runner/reporter machinery, but the PRD requires users to distinguish parse failures, missing interpreters, and rule violations. Please verify the current reporter path preserves that distinction; otherwise spell out the new category here.

.github/workflows/publish-shims.yml (1)

3-6: LGTM!

Also applies to: 19-51, 62-62, 85-85, 131-131, 160-160

src/helpers/update-check.ts (1)

12-24: LGTM!

src/cli.ts (1)

42-45: LGTM!

Also applies to: 158-164

tests/helpers/update-check.test.ts (1)

8-56: LGTM!

.claude/agent-memory/archgate-developer/feedback_concise_comments.md (1)

1-17: LGTM!

.claude/agent-memory/archgate-developer/MEMORY.md (1)

30-30: LGTM!

Also applies to: 74-76

CLAUDE.md (1)

56-56: 📐 Maintainability & Code Quality

Confirm the full gate here.

shouldPerformUpdateCheck() is summarized as TTY/non-CI only. Please verify whether there is any additional command-state exclusion, and spell it out here if so. Based on the PR summary.

Comment thread .claude/agent-memory/archgate-developer/project_release_pipeline_gotchas.md Outdated
Comment thread .github/workflows/publish-shims.yml
Comment thread .github/workflows/publish-shims.yml
Comment thread .github/workflows/publish-shims.yml Outdated
Comment thread .github/workflows/release-binaries.yml
Origin/main (PR #450) independently refined the same update-check and
publish-shims/release-binaries work this branch had already done, so
those files take main's superseding versions verbatim (confirmed
byte-identical post-merge). Documentation conflicts (CLAUDE.md,
MEMORY.md, feedback_concise_comments.md) were near-duplicate content
from both sides; kept main's phrasing.

Also compacted MEMORY.md from 24.8KB to 5.5KB per the memory-index
size hook: moved long-form entries into topic files (oxlint gotchas,
test isolation, Windows subprocess quirks, CI workflow gotchas, rules
engine internals, i18n quality, CLI-skill flag sequencing) and left
one-line pointers in the index.

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 3, 2026
Trim incident-log narrative down to actionable facts across CLAUDE.md
and the largest memory topic files (worktree-create hook history,
session-context --skip fix history, shim publishing, cursor approval
agent, oxlint enforcement-layer feedback). No facts, paths, commands,
or error strings were dropped — only prose and blow-by-blow
verification narrative. Total agent-memory footprint: 49.4KB -> 36.3KB.
CLAUDE.md: 12.0KB -> 10.0KB.

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
…ent memory

Moved three gotcha-style sections (GitHub Actions secrets.*/vars.*
confusion, release pipeline gotchas, Claude Code hooks config) out of
CLAUDE.md and into .claude/agent-memory/archgate-developer/, since
they're incident history rather than standing project conventions.
CLAUDE.md now points to the memory index instead of inlining the
detail. Kept the "Adding a New Editor Target" checklist in CLAUDE.md
since it's evergreen task reference any contributor or non-memory
agent needs, not incident lore.

CLAUDE.md: 10.0KB -> 7.9KB.

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

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 3, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@rhuanbarreto rhuanbarreto changed the title docs(adr): AST-aware RuleContext (ARCH-022) + PRD docs(adr): add AST-aware rule context ADR and PRD Jul 3, 2026
@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Code Coverage

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

Full HTML report available in workflow artifacts.

Per-directory breakdown
Directory Coverage Lines
src/commands/ 88.7% 1994 / 2249
src/engine/ 90.9% 1463 / 1610
src/formats/ 100.0% 142 / 142
src/helpers/ 90.1% 3597 / 3991

- project_release_pipeline_gotchas.md: fix "three issues" wording to
  match the actual four numbered items, and complete the
  shouldPerformUpdateCheck() gate description (was missing the
  non-upgrade exclusion).
- PRD: reconcile the contradictory v1 scope statement — TS/JS ship in
  v1, Python/Ruby follow per the rollout sequencing section, not both
  in v1 as the requirements line previously implied.
- ARCH-022: fix "sandbst" typo; require the interpreter-availability
  probe to try platform-appropriate candidate names (python3 is not a
  universal PATH alias on Windows) per ARCH-009; clarify that the two
  ctx.ast() throw cases (missing interpreter vs. parse failure) must
  be distinguishable in the error message text even though they share
  exit code 2.

Workflow-file findings (persist-credentials, template-injection, TAG
interpolation) from the same review were already resolved by the
origin/main merge in a prior commit — verified against current file
state, no further changes needed there.

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

@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: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.archgate/adrs/ARCH-022-ast-aware-rule-context.md (1)

36-43: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use the probed interpreter instead of hard-coding python3
The Python example should reference the interpreter selected by the availability probe; python is the resolved binary on some Windows installs, and the guardrail section already requires platform-specific candidate selection.

Suggested wording
-- Python's built-in `ast` module (`python3 -c "..."`, serializing the tree to JSON)
+- Python's built-in `ast` module (the interpreter selected by the availability probe, running `-c "..."` and serializing the tree to JSON)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.archgate/adrs/ARCH-022-ast-aware-rule-context.md around lines 36 - 43, The
AST guardrail text hard-codes `python3` in the Python example, but the
interpreter should come from the availability probe instead. Update the
`createRuleContext()` / `ctx.ast()` guidance to reference the probed executable
selected by the platform-specific candidate check (using `isWindows()`-based
ordering), so the example matches the cached interpreter used for both probe and
real `Bun.spawn` invocation.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
@.claude/agent-memory/archgate-developer/feedback_prefer_tests_over_adr_rules.md:
- Line 10: The ADR reference in the reasoning is incorrect: ARCH-019 refers to
the withPromptFix prompt ADR, not the allowlist-rule discussion. Update the
sentence in the affected markdown so it points to the correct ADR from the
repository’s ADR list and matches the actual decision that led to the custom
oxlint rule, using the relevant ARCH identifier and the surrounding wording in
this document to keep the historical reference accurate.

---

Outside diff comments:
In @.archgate/adrs/ARCH-022-ast-aware-rule-context.md:
- Around line 36-43: The AST guardrail text hard-codes `python3` in the Python
example, but the interpreter should come from the availability probe instead.
Update the `createRuleContext()` / `ctx.ast()` guidance to reference the probed
executable selected by the platform-specific candidate check (using
`isWindows()`-based ordering), so the example matches the cached interpreter
used for both probe and real `Bun.spawn` invocation.
🪄 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: 2ea451f2-87b5-4bf5-b60c-6da8e1a81222

📥 Commits

Reviewing files that changed from the base of the PR and between 367e6da and c0e88a6.

📒 Files selected for processing (18)
  • .archgate/PRDs/ast-aware-rule-context.md
  • .archgate/adrs/ARCH-022-ast-aware-rule-context.md
  • .claude/agent-memory/archgate-developer/MEMORY.md
  • .claude/agent-memory/archgate-developer/feedback_prefer_tests_over_adr_rules.md
  • .claude/agent-memory/archgate-developer/project_ci_workflow_gotchas.md
  • .claude/agent-memory/archgate-developer/project_claude_code_hooks_config.md
  • .claude/agent-memory/archgate-developer/project_cli_skill_flag_sequencing.md
  • .claude/agent-memory/archgate-developer/project_i18n_translation_quality.md
  • .claude/agent-memory/archgate-developer/project_oxlint_gotchas.md
  • .claude/agent-memory/archgate-developer/project_release_pipeline_gotchas.md
  • .claude/agent-memory/archgate-developer/project_rules_engine_internals.md
  • .claude/agent-memory/archgate-developer/project_session_context_skip_root_fix.md
  • .claude/agent-memory/archgate-developer/project_shim_publishing.md
  • .claude/agent-memory/archgate-developer/project_test_isolation_gotchas.md
  • .claude/agent-memory/archgate-developer/project_windows_subprocess_gotchas.md
  • .claude/agent-memory/archgate-developer/project_worktree_create_hook_contract.md
  • .claude/agent-memory/archgate-developer/reference_cursor_approval_agent.md
  • CLAUDE.md
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: Cloudflare Pages
⚠️ CI failures not shown inline (14)

GitHub Actions: DCO / 0_DCO Sign-off Check.txt: docs(adr): add AST-aware rule context ADR and PRD

Conclusion: failure

View job details

##[group]Run base="3cb02b784e6f898a4fd3097f9c75255eb9631169"
 �[36;1mbase="3cb02b784e6f898a4fd3097f9c75255eb9631169"�[0m
 �[36;1mhead="c0e88a6448adb10438fe2de39010c92d426feb85"�[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 / DCO Sign-off Check: docs(adr): add AST-aware rule context ADR and PRD

Conclusion: failure

View job details

##[group]Run base="3cb02b784e6f898a4fd3097f9c75255eb9631169"
 �[36;1mbase="3cb02b784e6f898a4fd3097f9c75255eb9631169"�[0m
 �[36;1mhead="c0e88a6448adb10438fe2de39010c92d426feb85"�[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: Code Quality: PR #451 / 1_Analyze (go).txt: Code Quality: PR #451

Conclusion: failure

View job details

Extracting types for package crypto/aes.
 [] [build-stderr] 2026/07/03 15:43:28 Done extracting types for package crypto/aes.
 [] [build-stderr] 2026/07/03 15:43:28 Processing package crypto/des.
 [] [build-stderr] 2026/07/03 15:43:28 Extracting types for package crypto/des.
 [] [build-stderr] 2026/07/03 15:43:28 Done extracting types for package crypto/des.
 [] [build-stderr] 2026/07/03 15:43:28 Processing package crypto/internal/fips140/nistec/fiat.
 [] [build-stderr] 2026/07/03 15:43:28 Extracting types for package crypto/internal/fips140/nistec/fiat.
 [] [build-stderr] 2026/07/03 15:43:28 Done extracting types for package crypto/internal/fips140/nistec/fiat.
 [] [build-stderr] 2026/07/03 15:43:28 Processing package crypto/internal/fips140/nistec.
 [] [build-stderr] 2026/07/03 15:43:28 Extracting types for package crypto/internal/fips140/nistec.
 [] [build-stderr] 2026/07/03 15:43:28 Done extracting types for package crypto/internal/fips140/nistec.
 [] [build-stderr] 2026/07/03 15:43:28 Processing package crypto/internal/fips140/ecdh.
 [] [build-stderr] 2026/07/03 15:43:28 Extracting types for package crypto/internal/fips140/ecdh.
 [] [build-stderr] 2026/07/03 15:43:28 Done extracting types for package crypto/internal/fips140/ecdh.
 [] [build-stderr] 2026/07/03 15:43:28 Processing package crypto/internal/fips140/edwards25519/field.
 [] [build-stderr] 2026/07/03 15:43:28 Extracting types for package crypto/internal/fips140/edwards25519/field.
 [] [build-stderr] 2026/07/03 15:43:28 Done extracting types for package crypto/internal/fips140/edwards25519/field.
 [] [build-stderr] 2026/07/03 15:43:28 Processing package crypto/ecdh.
 [] [build-stderr] 2026/07/03 15:43:28 Extracting types for package crypto/ecdh.
 [] [build-stderr] 2026/07/03 15:43:28 Done extracting types for package crypto/ecdh.
 [] [build-stderr] 2026/07/03 15:43:28 Processing package crypto/elliptic.
 [] [build-stderr] 2026/07/03 15:43:28 Extracting types for package crypto/elliptic.
 [] [build-st...

GitHub Actions: Code Quality: PR #451 / Analyze (go): Code Quality: PR #451

Conclusion: failure

View job details

,"bundleSupportsIncludeLogs":true,"bundleSupportsOverlay":true,"databaseInterpretResultsSupportsSarifRunProperty":true,"featuresInVersionResult":true,"indirectTracingSupportsStaticBinaries":false,"informsAboutUnsupportedPathFilters":true,"supportsPython312":true,"mrvaPackCreate":true,"threatModelOption":true,"traceCommandUseBuildMode":true,"v2ramSizing":true,"mrvaPackCreateMultipleQueries":true,"setsCodeqlRunnerEnvVar":true,"sarifMergeRunsFromEqualCategory":true,"forceOverwrite":true,"generateSummarySymbolMap":true,"pythonDefaultIsToNotExtractStdlib":true,"queryServerRunQueries":true,"queryServerTrimCacheWithMode":true,"builtinExtractorsSpecifyDefaultQueries":true,"bqrsDiffResultSets":true,"bundleSupportsIncludeOption":true,"suppressesMissingFileBaselineWarning":true}}}
   CODEQL_ACTION_GO_BINARY: /home/runner/work/_temp/codeql-action-go-tracing/bin/go
   CODEQL_RAM: 14575
   CODEQL_THREADS: 4
   CODEQL_PROXY_HOST:
   CODEQL_PROXY_PORT:
   CODEQL_PROXY_CA_CERTIFICATE:
   CODEQL_PROXY_URLS:
 ##[endgroup]
 ##[group]Attempting to automatically build go code
 [command]/opt/hostedtoolcache/CodeQL/2.25.6/x64/codeql/codeql database trace-command --use-build-mode --working-dir /home/runner/work/cli/cli /home/runner/work/_temp/codeql_databases/go
 Picked up JAVA_TOOL_OPTIONS:  -Dhttp.keepAlive=false -Dmaven.wagon.http.pool=false
 Running command in /home/runner/work/cli/cli: [/opt/hostedtoolcache/CodeQL/2.25.6/x64/codeql/go/tools/autobuild.sh]
 [] [build-stderr] 2026/07/03 15:43:20 Autobuilder was built with go1.26.0, environment has go1.24.13
 [] [build-stderr] 2026/07/03 15:43:20 LGTM_SRC is /home/runner/work/cli/cli
 [] [build-stderr] 2026/07/03 15:43:20 Found no go.work files in the workspace; looking for go.mod files...
 [] [build-stderr] 2026/07/03 15:43:20 Found 1 go.mod files in: shims/go/go.mod.
 [] [build-stderr] 2026/07/03 15:43:20 Found 1 go.mod file(s).
 [] [build-stderr] 2026/07/03 15:43:20 Import path is 'github.com/archgate/cli'
 [] [build-stderr] 2026/07/...

GitHub Actions: Validate / Validate Code: docs(adr): add AST-aware rule context ADR and PRD

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 [[ "success" != "success" ]] || \�[0m
 �[36;1m   [[ "$SHIM_OK" != "success" ]] || \�[0m
 �[36;1m   [[ "success" != "success" ]] || \�[0m
 �[36;1m   [[ "success" != "success" ]] || \�[0m
 �[36;1m   [[ "success" != "success" ]] || \�[0m
 �[36;1m   [[ "success" != "success" ]]; then�[0m
 �[36;1m  echo "::error::One or more jobs failed:"�[0m

GitHub Actions: Validate / 0_Validate Code.txt: docs(adr): add AST-aware rule context ADR and PRD

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 [[ "success" != "success" ]] || \�[0m
 �[36;1m   [[ "$SHIM_OK" != "success" ]] || \�[0m
 �[36;1m   [[ "success" != "success" ]] || \�[0m
 �[36;1m   [[ "success" != "success" ]] || \�[0m
 �[36;1m   [[ "success" != "success" ]] || \�[0m
 �[36;1m   [[ "success" != "success" ]]; then�[0m
 �[36;1m  echo "::error::One or more jobs failed:"�[0m

GitHub Actions: Validate / Lint, Test & Check: docs(adr): add AST-aware rule context ADR and PRD

Conclusion: failure

View job details

##[group]Run bun run docs/scripts/generate-llms-full.ts
 �[36;1mbun run docs/scripts/generate-llms-full.ts�[0m
 �[36;1mgit diff --exit-code docs/public/llms-full.txt || {�[0m
 �[36;1m  echo "::error::docs/public/llms-full.txt is out of date. Run 'bun run docs/scripts/generate-llms-full.ts' and commit the result."�[0m

GitHub Actions: Validate / 6_Lint, Test & Check.txt: docs(adr): add AST-aware rule context ADR and PRD

Conclusion: failure

View job details

##[group]Run bun run docs/scripts/generate-llms-full.ts
 �[36;1mbun run docs/scripts/generate-llms-full.ts�[0m
 �[36;1mgit diff --exit-code docs/public/llms-full.txt || {�[0m
 �[36;1m  echo "::error::docs/public/llms-full.txt is out of date. Run 'bun run docs/scripts/generate-llms-full.ts' and commit the result."�[0m

GitHub Actions: Validate / Smoke Test (Linux) _ Linux: docs(adr): add AST-aware rule context ADR and PRD

Conclusion: failure

View job details

##[group]Run if [ -z "$ARCHGATE_VERSION" ]; then
 �[36;1mif [ -z "$ARCHGATE_VERSION" ]; then�[0m
 �[36;1m  # Find the newest release that already has the Linux asset uploaded.�[0m
 �[36;1m  # On release-commit pushes the Validate and Release workflows start�[0m
 �[36;1m  # concurrently, so the latest tag may exist before its binaries are�[0m
 �[36;1m  # uploaded by release-binaries.yml — hitting a 404.�[0m
 �[36;1m  asset="archgate-linux-x64.tar.gz"�[0m
 �[36;1m  tags="$(gh release list --limit 5 --json tagName --jq '.[].tagName' 2>/dev/null || true)"�[0m
 �[36;1m  if [ -z "$tags" ]; then�[0m
 �[36;1m    echo "::warning::No releases found, skipping install.sh smoke test"�[0m
 �[36;1m    exit 0�[0m
 �[36;1m  fi�[0m
 �[36;1m  found=""�[0m
 �[36;1m  for tag in $tags; do�[0m
 �[36;1m    assets="$(gh release view "$tag" --json assets --jq '.assets[].name' 2>/dev/null || true)"�[0m
 �[36;1m    if echo "$assets" | grep -qF "$asset"; then�[0m
 �[36;1m      ARCHGATE_VERSION="$tag"�[0m
 �[36;1m      found=1�[0m
 �[36;1m      break�[0m
 �[36;1m    fi�[0m
 �[36;1m  done�[0m
 �[36;1m  if [ -z "$found" ]; then�[0m
 �[36;1m    echo "::warning::No release with $asset found, skipping install.sh smoke test"�[0m
 �[36;1m    exit 0�[0m
 �[36;1m  fi�[0m
 �[36;1m  export ARCHGATE_VERSION�[0m
 �[36;1mfi�[0m
 �[36;1mecho "Testing install.sh with version $ARCHGATE_VERSION"�[0m
 �[36;1m�[0m
 �[36;1mexport ARCHGATE_INSTALL_DIR="$(mktemp -d)"�[0m
 �[36;1m�[0m
 �[36;1msh install.sh�[0m
 �[36;1m�[0m
 �[36;1mif [ ! -f "$ARCHGATE_INSTALL_DIR/archgate" ]; then�[0m
 �[36;1m  echo "::error::archgate binary not found at $ARCHGATE_INSTALL_DIR/archgate after install"�[0m

GitHub Actions: Validate / Coverage Report: docs(adr): add AST-aware rule context ADR and PRD

Conclusion: failure

View job details

##[group]Run COVERAGE="90.0"
 �[36;1mCOVERAGE="90.0"�[0m
 �[36;1mMIN_COVERAGE=90�[0m
 �[36;1mBELOW=$(awk "BEGIN{print ($COVERAGE < $MIN_COVERAGE) ? 1 : 0}")�[0m
 �[36;1mif [ "$BELOW" = "1" ]; then�[0m
 �[36;1m  echo "::error::Code coverage is ${COVERAGE}%, which is below the minimum threshold of ${MIN_COVERAGE}%."�[0m

GitHub Actions: Validate / 1_Coverage Report.txt: docs(adr): add AST-aware rule context ADR and PRD

Conclusion: failure

View job details

##[group]Run COVERAGE="90.0"
 �[36;1mCOVERAGE="90.0"�[0m
 �[36;1mMIN_COVERAGE=90�[0m
 �[36;1mBELOW=$(awk "BEGIN{print ($COVERAGE < $MIN_COVERAGE) ? 1 : 0}")�[0m
 �[36;1mif [ "$BELOW" = "1" ]; then�[0m
 �[36;1m  echo "::error::Code coverage is ${COVERAGE}%, which is below the minimum threshold of ${MIN_COVERAGE}%."�[0m

GitHub Actions: Validate / 3_Smoke Test (Linux) _ Linux.txt: docs(adr): add AST-aware rule context ADR and PRD

Conclusion: failure

View job details

##[group]Run if [ -z "$ARCHGATE_VERSION" ]; then
 �[36;1mif [ -z "$ARCHGATE_VERSION" ]; then�[0m
 �[36;1m  # Find the newest release that already has the Linux asset uploaded.�[0m
 �[36;1m  # On release-commit pushes the Validate and Release workflows start�[0m
 �[36;1m  # concurrently, so the latest tag may exist before its binaries are�[0m
 �[36;1m  # uploaded by release-binaries.yml — hitting a 404.�[0m
 �[36;1m  asset="archgate-linux-x64.tar.gz"�[0m
 �[36;1m  tags="$(gh release list --limit 5 --json tagName --jq '.[].tagName' 2>/dev/null || true)"�[0m
 �[36;1m  if [ -z "$tags" ]; then�[0m
 �[36;1m    echo "::warning::No releases found, skipping install.sh smoke test"�[0m
 �[36;1m    exit 0�[0m
 �[36;1m  fi�[0m
 �[36;1m  found=""�[0m
 �[36;1m  for tag in $tags; do�[0m
 �[36;1m    assets="$(gh release view "$tag" --json assets --jq '.assets[].name' 2>/dev/null || true)"�[0m
 �[36;1m    if echo "$assets" | grep -qF "$asset"; then�[0m
 �[36;1m      ARCHGATE_VERSION="$tag"�[0m
 �[36;1m      found=1�[0m
 �[36;1m      break�[0m
 �[36;1m    fi�[0m
 �[36;1m  done�[0m
 �[36;1m  if [ -z "$found" ]; then�[0m
 �[36;1m    echo "::warning::No release with $asset found, skipping install.sh smoke test"�[0m
 �[36;1m    exit 0�[0m
 �[36;1m  fi�[0m
 �[36;1m  export ARCHGATE_VERSION�[0m
 �[36;1mfi�[0m
 �[36;1mecho "Testing install.sh with version $ARCHGATE_VERSION"�[0m
 �[36;1m�[0m
 �[36;1mexport ARCHGATE_INSTALL_DIR="$(mktemp -d)"�[0m
 �[36;1m�[0m
 �[36;1msh install.sh�[0m
 �[36;1m�[0m
 �[36;1mif [ ! -f "$ARCHGATE_INSTALL_DIR/archgate" ]; then�[0m
 �[36;1m  echo "::error::archgate binary not found at $ARCHGATE_INSTALL_DIR/archgate after install"�[0m

GitHub Actions: Validate / 5_Zizmor (Workflow Security).txt: docs(adr): add AST-aware rule context ADR and PRD

Conclusion: failure

View job details

##[group]Run "${GITHUB_ACTION_PATH}/action.sh"
 �[36;1m"${GITHUB_ACTION_PATH}/action.sh"�[0m
 shell: /usr/bin/bash --noprofile --norc -e -o pipefail {0}
 env:
   ARCHGATE_TELEMETRY: 0
   GHA_ZIZMOR_INPUTS: .
   GHA_ZIZMOR_ONLINE_AUDITS: true
   GHA_ZIZMOR_PERSONA: regular
   GHA_ZIZMOR_MIN_SEVERITY:
   GHA_ZIZMOR_MIN_CONFIDENCE:
   GHA_ZIZMOR_VERSION: latest
   GHA_ZIZMOR_***REDACTED***
   GHA_ZIZMOR_ADVANCED_SECURITY: true
   GHA_ZIZMOR_COLOR: true
   GHA_ZIZMOR_ANNOTATIONS: false
   GHA_ZIZMOR_CONFIG: zizmor.yml
   GHA_ZIZMOR_FAIL_ON_NO_INPUTS: true
 ##[endgroup]
 Unable to find image 'ghcr.io/zizmorcore/zizmor:latest@sha256:***REDACTED***' locally
 ghcr.io/zizmorcore/zizmor@sha256:***REDACTED***: Pulling from zizmorcore/zizmor
 0514fcfd8680: Pulling fs layer
 7677d1f93ece: Pulling fs layer
 d3cc9d64a2f9: Pulling fs layer
 c920184a3208: Pulling fs layer
 9201e51fe8c1: Pulling fs layer
 69cbafd2417b: Pulling fs layer
 9041c2dcdd9f: Pulling fs layer
 8d99fd8fea9c: Pulling fs layer
 5f460b97a17e: Pulling fs layer
 cdea145aa115: Pulling fs layer
 5bb3233a44f9: Pulling fs layer
 85c67978dd22: Pulling fs layer
 9201e51fe8c1: Waiting
 8d99fd8fea9c: Waiting
 69cbafd2417b: Waiting
 9041c2dcdd9f: Waiting
 5f460b97a17e: Waiting
 cdea145aa115: Waiting
 5bb3233a44f9: Waiting
 85c67978dd22: Waiting
 c920184a3208: Waiting
 d3cc9d64a2f9: Download complete
 7677d1f93ece: Verifying Checksum
 7677d1f93ece: Download complete
 0514fcfd8680: Verifying Checksum
 0514fcfd8680: Download complete
 0514fcfd8680: Pull complete
 c920184a3208: Verifying Checksum
 c920184a3208: Download complete
 9201e51fe8c1: Verifying Checksum
 9201e51fe8c1: Download complete
 69cbafd2417b: Verifying Checksum
 69cbafd2417b: Download complete
 7677d1f93ece: Pull complete
 9041c2dcdd9f: Verifying Checksum
 9041c2dcdd9f: Download complete
 5f460b97a17e: Verifying Checksum
 5f460b97a17e: Download complete
 d3cc9d64a2f9: Pull complete
 8d99fd8fea9c: Verifying Checksum
 8d99fd8fea9c: Download complete
 c920184a3...

GitHub Actions: Validate / Zizmor (Workflow Security): docs(adr): add AST-aware rule context ADR and PRD

Conclusion: failure

View job details

##[group]Run "${GITHUB_ACTION_PATH}/action.sh"
 �[36;1m"${GITHUB_ACTION_PATH}/action.sh"�[0m
 shell: /usr/bin/bash --noprofile --norc -e -o pipefail {0}
 env:
   ARCHGATE_TELEMETRY: 0
   GHA_ZIZMOR_INPUTS: .
   GHA_ZIZMOR_ONLINE_AUDITS: true
   GHA_ZIZMOR_PERSONA: regular
   GHA_ZIZMOR_MIN_SEVERITY:
   GHA_ZIZMOR_MIN_CONFIDENCE:
   GHA_ZIZMOR_VERSION: latest
   GHA_ZIZMOR_***REDACTED***
   GHA_ZIZMOR_ADVANCED_SECURITY: true
   GHA_ZIZMOR_COLOR: true
   GHA_ZIZMOR_ANNOTATIONS: false
   GHA_ZIZMOR_CONFIG: zizmor.yml
   GHA_ZIZMOR_FAIL_ON_NO_INPUTS: true
 ##[endgroup]
 Unable to find image 'ghcr.io/zizmorcore/zizmor:latest@sha256:***REDACTED***' locally
 ghcr.io/zizmorcore/zizmor@sha256:***REDACTED***: Pulling from zizmorcore/zizmor
 0514fcfd8680: Pulling fs layer
 7677d1f93ece: Pulling fs layer
 d3cc9d64a2f9: Pulling fs layer
 c920184a3208: Pulling fs layer
 9201e51fe8c1: Pulling fs layer
 69cbafd2417b: Pulling fs layer
 9041c2dcdd9f: Pulling fs layer
 8d99fd8fea9c: Pulling fs layer
 5f460b97a17e: Pulling fs layer
 cdea145aa115: Pulling fs layer
 5bb3233a44f9: Pulling fs layer
 85c67978dd22: Pulling fs layer
 9201e51fe8c1: Waiting
 8d99fd8fea9c: Waiting
 69cbafd2417b: Waiting
 9041c2dcdd9f: Waiting
 5f460b97a17e: Waiting
 cdea145aa115: Waiting
 5bb3233a44f9: Waiting
 85c67978dd22: Waiting
 c920184a3208: Waiting
 d3cc9d64a2f9: Download complete
 7677d1f93ece: Verifying Checksum
 7677d1f93ece: Download complete
 0514fcfd8680: Verifying Checksum
 0514fcfd8680: Download complete
 0514fcfd8680: Pull complete
 c920184a3208: Verifying Checksum
 c920184a3208: Download complete
 9201e51fe8c1: Verifying Checksum
 9201e51fe8c1: Download complete
 69cbafd2417b: Verifying Checksum
 69cbafd2417b: Download complete
 7677d1f93ece: Pull complete
 9041c2dcdd9f: Verifying Checksum
 9041c2dcdd9f: Download complete
 5f460b97a17e: Verifying Checksum
 5f460b97a17e: Download complete
 d3cc9d64a2f9: Pull complete
 8d99fd8fea9c: Verifying Checksum
 8d99fd8fea9c: Download complete
 c920184a3...
🧰 Additional context used
📓 Path-based instructions (3)
.archgate/adrs/**/*.md

📄 CodeRabbit inference engine (CLAUDE.md)

ADR files must use YAML frontmatter with id, title, domain, rules, and optional files, and include the required sections: Context, Decision, Do's and Don'ts, Consequences, Compliance, and References.

Files:

  • .archgate/adrs/ARCH-022-ast-aware-rule-context.md
.archgate/adrs/**

⚙️ CodeRabbit configuration file

.archgate/adrs/**: ---
id: ARCH-001
title: Command Structure
domain: architecture
rules: true
files: ["src/commands/**/*.ts"]

Context

The CLI needs a consistent pattern for defining and registering commands. As the command surface grows (init, check, adr, review-context, session-context, upgrade, clean), the registration mechanism must scale without introducing hidden coupling or making the dependency graph opaque.

Alternatives considered:

  • Auto-discovery via executableDir() — Commander.js supports automatic command discovery by scanning a directory for executable files. This eliminates manual imports but hides the dependency graph: adding or removing a command has no type-checked reference, making dead command detection impossible. It also requires each command to be a standalone executable, which prevents in-process testing and forces separate process spawning for every subcommand invocation.
  • Plugin-based registration — A plugin system where commands register themselves via a manifest or hook (similar to Oclif or Clipanion). This adds flexibility for third-party extensions but introduces significant complexity for an internal CLI with a known, finite set of commands. The indirection makes it harder to trace which code handles which command.
  • Single-file command map — Define all commands in a single file as a map of name-to-handler. Simple but creates a monolithic file that grows with every command, making merge conflicts frequent and readability poor.

The explicit register pattern strikes the right balance: each command owns its registration logic, the entry point makes all commands visible at a glance, and in-process execution enables straightforward testing without process spawning.

Decision

Commands live in src/commands/ and export a register*Command(program) function. The main entry point (src/cli.ts) explicitly imports and calls each register function. Subcommands (e.g., adr create, adr list) use nested directories wi...

Files:

  • .archgate/adrs/ARCH-022-ast-aware-rule-context.md
**

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

GitHub Act...

Files:

  • CLAUDE.md

⚙️ 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:

  • CLAUDE.md
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
Repo: archgate/cli

Timestamp: 2026-07-03T15:46:20.000Z
Learning: `ctx.ast()` must support TypeScript, JavaScript, Python, and Ruby by dispatching internally based on the `language` argument.
Learnt from: CR
Repo: archgate/cli

Timestamp: 2026-07-03T15:46:20.000Z
Learning: Python and Ruby AST support must use the language's standard-library AST facility via subprocess, not tree-sitter, WASM grammars, or third-party parsers.
Learnt from: CR
Repo: archgate/cli

Timestamp: 2026-07-03T15:46:20.000Z
Learning: The returned AST node shape is language-specific and must not be normalized into a single cross-language schema.
Learnt from: CR
Repo: archgate/cli

Timestamp: 2026-07-03T15:46:20.000Z
Learning: `ctx.ast()` must remain the only way rule authors access subprocess-like language tooling, and the guardrail ordering must be preserved before any interpreter is invoked.
Learnt from: CR
Repo: archgate/cli

Timestamp: 2026-07-03T15:46:20.000Z
Learning: A future bundled multi-language parser or any expansion beyond this ADR's scope must be handled in a separate ADR and reviewed under the dependency policy.
📚 Learning: 2026-06-11T12:50:28.661Z
Learnt from: rhuanbarreto
Repo: archgate/cli PR: 406
File: .claude/agent-memory/archgate-developer/feedback_prefer_tests_over_adr_rules.md:8-18
Timestamp: 2026-06-11T12:50:28.661Z
Learning: In `archgate/cli`, for markdown files under `.claude/agent-memory/`, follow the established convention: use YAML frontmatter (with a `name:` field used as the document title) and do not require a top-level `#` (H1) heading. During code review, do not flag missing first-line/first-top-level H1 headings (e.g., MD041) for these agent-memory files since markdownlint is not part of the repo’s `bun run validate` lint pipeline (oxlint/oxfmt only).

Applied to files:

  • .claude/agent-memory/archgate-developer/project_cli_skill_flag_sequencing.md
  • .claude/agent-memory/archgate-developer/feedback_prefer_tests_over_adr_rules.md
  • .claude/agent-memory/archgate-developer/project_oxlint_gotchas.md
  • .claude/agent-memory/archgate-developer/project_test_isolation_gotchas.md
  • .claude/agent-memory/archgate-developer/project_windows_subprocess_gotchas.md
  • .claude/agent-memory/archgate-developer/project_ci_workflow_gotchas.md
  • .claude/agent-memory/archgate-developer/project_rules_engine_internals.md
  • .claude/agent-memory/archgate-developer/project_claude_code_hooks_config.md
  • .claude/agent-memory/archgate-developer/reference_cursor_approval_agent.md
  • .claude/agent-memory/archgate-developer/project_i18n_translation_quality.md
  • .claude/agent-memory/archgate-developer/project_release_pipeline_gotchas.md
  • .claude/agent-memory/archgate-developer/project_worktree_create_hook_contract.md
  • .claude/agent-memory/archgate-developer/project_session_context_skip_root_fix.md
  • .claude/agent-memory/archgate-developer/project_shim_publishing.md
  • .claude/agent-memory/archgate-developer/MEMORY.md
🪛 LanguageTool
.claude/agent-memory/archgate-developer/project_oxlint_gotchas.md

[uncategorized] ~16-~16: Did you mean the formatting language “Markdown” (= proper noun)?
Context: ...ral .scan() text. - oxfmt formats markdown tooformat:check runs over ALL fi...

(MARKDOWN_NNP)

.claude/agent-memory/archgate-developer/project_ci_workflow_gotchas.md

[uncategorized] ~8-~8: The official name of this software platform is spelled with a capital “H”.
Context: ....** A workflow pushing commits/PRs with github.token/secrets.GITHUB_TOKEN suppresse...

(GITHUB)

.claude/agent-memory/archgate-developer/project_release_pipeline_gotchas.md

[uncategorized] ~13-~13: The official name of this software platform is spelled with a capital “H”.
Context: ...push reachable through commits touching .github/workflows/* without that permission, e...

(GITHUB)

.claude/agent-memory/archgate-developer/project_worktree_create_hook_contract.md

[style] ~10-~10: Consider an alternative for the overused word “exactly”.
Context: ...bare bun install — that regression is exactly what broke it originally (21 stale empt...

(EXACTLY_PRECISELY)

CLAUDE.md

[uncategorized] ~54-~54: The official name of this software platform is spelled with a capital “H”.
Context: ...istory and the referenced source files (.github/workflows/release.yml, `publish-shims....

(GITHUB)

🪛 markdownlint-cli2 (0.22.1)
.claude/agent-memory/archgate-developer/project_cli_skill_flag_sequencing.md

[warning] 8-8: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)

.claude/agent-memory/archgate-developer/project_oxlint_gotchas.md

[warning] 8-8: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)

.claude/agent-memory/archgate-developer/project_test_isolation_gotchas.md

[warning] 8-8: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)

.claude/agent-memory/archgate-developer/project_windows_subprocess_gotchas.md

[warning] 8-8: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)

.claude/agent-memory/archgate-developer/project_ci_workflow_gotchas.md

[warning] 8-8: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)

.claude/agent-memory/archgate-developer/project_rules_engine_internals.md

[warning] 8-8: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)

.claude/agent-memory/archgate-developer/project_claude_code_hooks_config.md

[warning] 8-8: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)

.claude/agent-memory/archgate-developer/reference_cursor_approval_agent.md

[warning] 8-8: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)

.claude/agent-memory/archgate-developer/project_i18n_translation_quality.md

[warning] 8-8: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)

.claude/agent-memory/archgate-developer/project_release_pipeline_gotchas.md

[warning] 8-8: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)

.claude/agent-memory/archgate-developer/project_worktree_create_hook_contract.md

[warning] 8-8: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)

.claude/agent-memory/archgate-developer/project_session_context_skip_root_fix.md

[warning] 8-8: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)

🔇 Additional comments (17)
.archgate/PRDs/ast-aware-rule-context.md (1)

42-45: 🎯 Functional Correctness

Clarify whether ctx.ast() is scoped or project-root based.

Line 44 reads like the API is limited to scopedFiles/changedFiles, but the current safePath() contract only establishes project-root containment. Please confirm the intended boundary so the PRD matches the runtime contract.

As per path instructions, ctx.ast() should use the same sandboxing model as readFile/glob.

Source: Path instructions

.claude/agent-memory/archgate-developer/project_test_isolation_gotchas.md (1)

8-14: LGTM!

.claude/agent-memory/archgate-developer/project_windows_subprocess_gotchas.md (1)

8-11: LGTM!

.claude/agent-memory/archgate-developer/project_shim_publishing.md (2)

12-15: 📐 Maintainability & Code Quality

Verify the version-sensitive shim commands.

uv build --python 3.12, the Ruby working-directory/rake setup, and the Maven waitUntil/autoPublish knobs are all external-tool details that can drift with tool versions. Please confirm these exact flags against the pinned toolchain before this note is treated as authoritative.


16-20: LGTM!

.claude/agent-memory/archgate-developer/project_i18n_translation_quality.md (1)

1-10: LGTM!

.claude/agent-memory/archgate-developer/reference_cursor_approval_agent.md (1)

1-13: LGTM!

.claude/agent-memory/archgate-developer/project_claude_code_hooks_config.md (1)

8-12: LGTM!

.claude/agent-memory/archgate-developer/project_worktree_create_hook_contract.md (1)

8-20: LGTM!

.claude/agent-memory/archgate-developer/project_session_context_skip_root_fix.md (1)

8-16: LGTM!

.claude/agent-memory/archgate-developer/MEMORY.md (1)

11-12: LGTM!

Also applies to: 15-27, 36-48, 67-73

CLAUDE.md (1)

46-54: LGTM!

Also applies to: 112-114

.claude/agent-memory/archgate-developer/project_release_pipeline_gotchas.md (1)

8-16: LGTM!

.claude/agent-memory/archgate-developer/project_ci_workflow_gotchas.md (1)

8-10: LGTM!

.claude/agent-memory/archgate-developer/project_rules_engine_internals.md (1)

8-11: LGTM!

.claude/agent-memory/archgate-developer/project_oxlint_gotchas.md (1)

8-16: LGTM!

.claude/agent-memory/archgate-developer/project_cli_skill_flag_sequencing.md (1)

8-14: LGTM!

Comment thread .claude/agent-memory/archgate-developer/feedback_prefer_tests_over_adr_rules.md Outdated
… probe

CodeRabbit's follow-up review caught that the invocation description
still hardcoded python3 in the Python example even after the prior fix
required the guardrail probe to select from platform-appropriate
candidate names. Replaced the hardcoded literal with a reference to
the probed executable, and softened the remaining informal
python3/ruby mentions elsewhere in the ADR to avoid implying a fixed
command name.

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

Two remaining unresolved review threads:

1. publish-shims.yml's publish-go-tag job set `workflows: write` in its
   permissions block. Verified against GitHub's own workflow syntax
   docs and actionlint's schema: "workflows" is not a valid
   permissions-key scope and was never granting anything — the
   original v0.45.7 incident's "fix" was a no-op. Removed the invalid
   key (contents: write is the real requirement for pushing a tag) and
   replaced the comment with an accurate explanation plus the real
   workaround (PAT with the workflow OAuth scope, or a GitHub App
   token with the Workflows permission configured at the App level)
   if the underlying push rejection resurfaces. Corrected the
   memory file that had claimed this was fixed and confirmed working
   — that confirmation doesn't hold up; flagged as unverified pending
   the next real release.

2. feedback_prefer_tests_over_adr_rules.md cited "ARCH-019" as the
   rejected draft allowlist rule from the inquirer prompt-type
   incident, but ARCH-019 is actually "Interactive Prompts via
   withPromptFix" — an unrelated, already-shipped ADR. The draft rule
   was never assigned an ADR ID (it was rejected before merging);
   removed the incorrect citation.

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

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.claude/agent-memory/archgate-developer/project_release_pipeline_gotchas.md (1)

3-3: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Frontmatter description still says "Three causes".

The body now documents four failure modes (and Line 8 was updated to "Four distinct issues"), but the frontmatter description at Line 3 still reads "Three causes". Update it for consistency.

Suggested fix
-description: Three causes behind archgate/cli release publishing failures found 2026-07-03
+description: Four causes behind archgate/cli release publishing failures found 2026-07-03
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.claude/agent-memory/archgate-developer/project_release_pipeline_gotchas.md
at line 3, The frontmatter description is inconsistent with the document body
because it still says “Three causes” while the content now describes four
failure modes. Update the markdown frontmatter in
project_release_pipeline_gotchas.md so the description matches the revised “Four
distinct issues” wording, keeping the change limited to the description field.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In @.claude/agent-memory/archgate-developer/project_release_pipeline_gotchas.md:
- Line 3: The frontmatter description is inconsistent with the document body
because it still says “Three causes” while the content now describes four
failure modes. Update the markdown frontmatter in
project_release_pipeline_gotchas.md so the description matches the revised “Four
distinct issues” wording, keeping the change limited to the description field.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 7e7901fe-3fb3-4973-96a9-48c7bf00ec62

📥 Commits

Reviewing files that changed from the base of the PR and between c0e88a6 and 9703a8c.

📒 Files selected for processing (4)
  • .archgate/adrs/ARCH-022-ast-aware-rule-context.md
  • .claude/agent-memory/archgate-developer/feedback_prefer_tests_over_adr_rules.md
  • .claude/agent-memory/archgate-developer/project_release_pipeline_gotchas.md
  • .github/workflows/publish-shims.yml
📜 Review details
⏰ Context from checks skipped due to timeout. (5)
  • GitHub Check: Smoke Test (Windows) / Windows
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (csharp)
  • GitHub Check: Analyze (java-kotlin)
  • GitHub Check: Cloudflare Pages
⚠️ CI failures not shown inline (2)

GitHub Actions: DCO / DCO Sign-off Check: docs(adr): add AST-aware rule context ADR and PRD

Conclusion: failure

View job details

##[group]Run base="3cb02b784e6f898a4fd3097f9c75255eb9631169"
 �[36;1mbase="3cb02b784e6f898a4fd3097f9c75255eb9631169"�[0m
 �[36;1mhead="9703a8c900bf7a511ac57ee938fb63bf0b73fa1e"�[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: docs(adr): add AST-aware rule context ADR and PRD

Conclusion: failure

View job details

##[group]Run base="3cb02b784e6f898a4fd3097f9c75255eb9631169"
 �[36;1mbase="3cb02b784e6f898a4fd3097f9c75255eb9631169"�[0m
 �[36;1mhead="9703a8c900bf7a511ac57ee938fb63bf0b73fa1e"�[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 (4)
.github/workflows/*.yml

📄 CodeRabbit inference engine (.archgate/adrs/CI-001-pin-github-actions-by-hash.md)

.github/workflows/*.yml: In GitHub Actions workflow files under .github/workflows/*.yml, every third-party uses: reference must be pinned to a full 40-character commit SHA and include a human-readable version comment on the same line (for example, uses: owner/action@<40-char-sha> # v4).
In GitHub Actions workflow files under .github/workflows/*.yml, do not reference third-party actions or reusable workflows by tag, branch, or abbreviated SHA; only a full 40-character commit SHA is allowed for third-party uses: entries.
In GitHub Actions workflow files under .github/workflows/*.yml, local workflow references (uses: ./.github/workflows/...) and local composite action references (uses: ./.github/actions/...) are exempt from SHA pinning because they stay within the same repository trust boundary.
In GitHub Actions workflow files under .github/workflows/*.yml, the slsa-framework/slsa-github-generator/.github/workflows/* reusable workflow is exempt from SHA pinning and must be referenced by tag (for example, @v2.1.0).

Use the same validation order as the local fail-fast pipeline: lint → typecheck → format → test → ADR check → knip → build check.

Files:

  • .github/workflows/publish-shims.yml
.github/workflows/*

📄 CodeRabbit inference engine (.archgate/adrs/GEN-003-tool-invocation-via-scripts.md)

.github/workflows/*: Do not use direct lint/format binary invocations such as bunx prettier, bunx oxfmt, npx eslint, oxlint ., or similar in GitHub Actions workflows; call the repository scripts instead.
In GitHub Actions workflows, do not run bare bun test; use bun run test so the script-level flags from package.json are applied.

Files:

  • .github/workflows/publish-shims.yml
.archgate/adrs/**/*.md

📄 CodeRabbit inference engine (CLAUDE.md)

.archgate/adrs/**/*.md: Read the self-governance ADRs before making architectural changes.
ADR files must use YAML frontmatter with id, title, domain, rules, and optional files, and include the sections Context, Decision, Do's and Don'ts, Consequences, Compliance, and References.

Files:

  • .archgate/adrs/ARCH-022-ast-aware-rule-context.md
.archgate/adrs/**

⚙️ CodeRabbit configuration file

.archgate/adrs/**: ---
id: ARCH-001
title: Command Structure
domain: architecture
rules: true
files: ["src/commands/**/*.ts"]

Context

The CLI needs a consistent pattern for defining and registering commands. As the command surface grows (init, check, adr, review-context, session-context, upgrade, clean), the registration mechanism must scale without introducing hidden coupling or making the dependency graph opaque.

Alternatives considered:

  • Auto-discovery via executableDir() — Commander.js supports automatic command discovery by scanning a directory for executable files. This eliminates manual imports but hides the dependency graph: adding or removing a command has no type-checked reference, making dead command detection impossible. It also requires each command to be a standalone executable, which prevents in-process testing and forces separate process spawning for every subcommand invocation.
  • Plugin-based registration — A plugin system where commands register themselves via a manifest or hook (similar to Oclif or Clipanion). This adds flexibility for third-party extensions but introduces significant complexity for an internal CLI with a known, finite set of commands. The indirection makes it harder to trace which code handles which command.
  • Single-file command map — Define all commands in a single file as a map of name-to-handler. Simple but creates a monolithic file that grows with every command, making merge conflicts frequent and readability poor.

The explicit register pattern strikes the right balance: each command owns its registration logic, the entry point makes all commands visible at a glance, and in-process execution enables straightforward testing without process spawning.

Decision

Commands live in src/commands/ and export a register*Command(program) function. The main entry point (src/cli.ts) explicitly imports and calls each register function. Subcommands (e.g., adr create, adr list) use nested directories wi...

Files:

  • .archgate/adrs/ARCH-022-ast-aware-rule-context.md
🧠 Learnings (1)
📚 Learning: 2026-06-11T12:50:28.661Z
Learnt from: rhuanbarreto
Repo: archgate/cli PR: 406
File: .claude/agent-memory/archgate-developer/feedback_prefer_tests_over_adr_rules.md:8-18
Timestamp: 2026-06-11T12:50:28.661Z
Learning: In `archgate/cli`, for markdown files under `.claude/agent-memory/`, follow the established convention: use YAML frontmatter (with a `name:` field used as the document title) and do not require a top-level `#` (H1) heading. During code review, do not flag missing first-line/first-top-level H1 headings (e.g., MD041) for these agent-memory files since markdownlint is not part of the repo’s `bun run validate` lint pipeline (oxlint/oxfmt only).

Applied to files:

  • .claude/agent-memory/archgate-developer/feedback_prefer_tests_over_adr_rules.md
  • .claude/agent-memory/archgate-developer/project_release_pipeline_gotchas.md
🪛 LanguageTool
.archgate/adrs/ARCH-022-ast-aware-rule-context.md

[style] ~38-~38: Consider removing “of” to be more concise
Context: ...nandBun.spawnSyncfrom rule code). All of the following MUST execute insidecreateRu...

(ALL_OF_THE)

.claude/agent-memory/archgate-developer/project_release_pipeline_gotchas.md

[uncategorized] ~13-~13: The official name of this software platform is spelled with a capital “H”.
Context: ...shes reachable through commits touching .github/workflows/*, even for an unrelated tag...

(GITHUB)

🔇 Additional comments (5)
.claude/agent-memory/archgate-developer/project_release_pipeline_gotchas.md (1)

8-16: LGTM!

.github/workflows/publish-shims.yml (1)

111-122: LGTM!

.archgate/adrs/ARCH-022-ast-aware-rule-context.md (2)

29-31: 📐 Maintainability & Code Quality

Make the AstNode type reflect the per-language shape.

The prose says each language returns a different tree shape, but the signature still collapses everything into one AstNode. Please verify that AstNode is a discriminated union or a language-parameterized generic; otherwise rule authors will need casts and the API will be easy to misuse.


45-46: 🩺 Stability & Availability

Verify the failure semantics against runner.ts / reporter.ts.

This paragraph assumes ctx.ast() throws are isolated per rule and mapped to the intended exit code. Please confirm that runner.ts actually catches rule failures at that boundary; otherwise a missing interpreter or parse error could abort the whole check run or surface as the wrong failure class.

.claude/agent-memory/archgate-developer/feedback_prefer_tests_over_adr_rules.md (1)

10-10: LGTM!

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 3, 2026
zizmor (already in CI) covers security patterns in workflow files but
has no concept of GitHub's actual permissions/expression schema. That
gap is exactly what let PR #451's invalid `workflows: write`
permission scope merge undetected — it was only caught later by a
third-party reviewer's internal actionlint run, which is not a
dependable control.

Adds an `actionlint` job to code-pull-request.yml, required by the
`status` gate. Installs the binary via the maintainer's own pinned
download script (specific commit SHA + pinned version, not `latest`)
rather than adding a reviewdog wrapper Action, avoiding a new `uses:`
trust surface for a single static-check invocation. Verified locally:
passes cleanly against the current workflows and correctly flags the
old (already-fixed) invalid permission scope when run against the
pre-fix file.

Documents the decision as CI-002, since it's a distinct topic from
CI-001's `uses:` SHA-pinning scope. Also fixes a pre-existing
inaccuracy in CLAUDE.md/MEMORY.md ("format" -> "format:check" in the
validate pipeline description, caught during reviewer sub-agent
verification) and captures two session learnings: a GraphQL technique
for distinguishing resolved vs. outstanding PR review threads (the
REST API doesn't expose this), and a live-confirmed instance of the
installed lessons-learned skill (v0.13.1) still referencing the
removed --skip flag.

Reviewer: APPROVED (automated checks 39/39, CI domain PASS, General
domain PASS_WITH_WARNINGS - the format:check warning, now fixed).

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 4, 2026
My local verification of the new actionlint job used a Windows binary
that silently skips shellcheck (not bundled/found on that platform),
so it passed cleanly while the real Linux CI job failed against three
pre-existing shellcheck findings in files this PR didn't otherwise
touch. Re-verified with the actual Linux actionlint image via Docker
(rhysd/actionlint:1.7.12) before pushing this time.

- code-pull-request.yml (SC2086): PATHS was an unquoted space-joined
  string passed to `git diff -- $PATHS`, relying on word-splitting.
  Converted to a bash array (PATHS=(...)) expanded as "${PATHS[@]}" —
  preserves the intended multi-path behavior without relying on
  unquoted splitting.
- release-binaries.yml (SC2035): `cat *.sha256` could misinterpret a
  glob result starting with `-` as an option. Changed to `cat ./*.sha256`.
- smoke-test-linux.yml (SC2155): `export VAR="$(cmd)"` masks the
  command's exit status. Split into assignment then `export VAR`.

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
Comment thread .github/workflows/code-pull-request.yml Fixed
…mory

Per the project's own concise-comments convention: the workflows:write
removal comment and the actionlint job comments restated detail that
now lives in CI-002 and project_release_pipeline_gotchas.md. Cut to
one-line pointers.

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

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

♻️ Duplicate comments (1)
.github/workflows/code-pull-request.yml (1)

93-97: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Unresolved: template expansion into shell script (code injection).

Line 95 still interpolates ${{ github.base_ref }} directly into the run: script. This is the same finding already raised by GitHub Advanced Security (zizmor) on a previous commit at this line, and it's still flagged by the current zizmor static-analysis run — the array refactor didn't address it. Route context values through env: and reference them as shell variables instead of inline template expansion.

🔒 Proposed fix
       - name: Check for shim changes
         id: changes
+        env:
+          BASE_REF: ${{ github.base_ref }}
         run: |
           PATHS=(shims/ .github/workflows/publish-shims.yml .github/workflows/code-pull-request.yml)
           if [ "${{ github.event_name }}" = "pull_request" ]; then
-            CHANGED=$(git diff --name-only origin/${{ github.base_ref }}...HEAD -- "${PATHS[@]}" || true)
+            CHANGED=$(git diff --name-only "origin/$BASE_REF...HEAD" -- "${PATHS[@]}" || true)
           else
             CHANGED=$(git diff --name-only HEAD~1 -- "${PATHS[@]}" || true)
           fi
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/code-pull-request.yml around lines 93 - 97, The workflow
script still interpolates github.base_ref directly inside the run block, which
leaves the shell command vulnerable to template expansion issues. Update the
code-pull-request workflow so the pull_request branch uses an env variable for
the base ref and references that shell variable in the git diff command instead
of `${{ github.base_ref }}`. Keep the change localized to the `run:` step that
builds `CHANGED` and preserve the existing `PATHS` and `git diff` logic.

Source: Linters/SAST tools

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

Duplicate comments:
In @.github/workflows/code-pull-request.yml:
- Around line 93-97: The workflow script still interpolates github.base_ref
directly inside the run block, which leaves the shell command vulnerable to
template expansion issues. Update the code-pull-request workflow so the
pull_request branch uses an env variable for the base ref and references that
shell variable in the git diff command instead of `${{ github.base_ref }}`. Keep
the change localized to the `run:` step that builds `CHANGED` and preserve the
existing `PATHS` and `git diff` logic.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 725645f7-3baf-4fde-bd23-d34b29a6b664

📥 Commits

Reviewing files that changed from the base of the PR and between 6c1db77 and a248c23.

📒 Files selected for processing (4)
  • .github/workflows/code-pull-request.yml
  • .github/workflows/publish-shims.yml
  • .github/workflows/release-binaries.yml
  • .github/workflows/smoke-test-linux.yml
📜 Review details
⏰ Context from checks skipped due to timeout. (3)
  • GitHub Check: Cursor Bugbot
  • GitHub Check: Smoke Test (Windows) / Windows
  • GitHub Check: Cloudflare Pages
⚠️ CI failures not shown inline (4)

GitHub Actions: DCO / DCO Sign-off Check: docs(adr): add AST-aware rule context ADR and PRD

Conclusion: failure

View job details

##[group]Run base="3cb02b784e6f898a4fd3097f9c75255eb9631169"
 �[36;1mbase="3cb02b784e6f898a4fd3097f9c75255eb9631169"�[0m
 �[36;1mhead="a248c231adb7195330c81e0f6bc8eaf78ff726de"�[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: docs(adr): add AST-aware rule context ADR and PRD

Conclusion: failure

View job details

##[group]Run base="3cb02b784e6f898a4fd3097f9c75255eb9631169"
 �[36;1mbase="3cb02b784e6f898a4fd3097f9c75255eb9631169"�[0m
 �[36;1mhead="a248c231adb7195330c81e0f6bc8eaf78ff726de"�[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: Code Quality: PR #451 / Analyze (go): Code Quality: PR #451

Conclusion: failure

View job details

e,"bundleSupportsIncludeLogs":true,"bundleSupportsOverlay":true,"databaseInterpretResultsSupportsSarifRunProperty":true,"featuresInVersionResult":true,"indirectTracingSupportsStaticBinaries":false,"informsAboutUnsupportedPathFilters":true,"supportsPython312":true,"mrvaPackCreate":true,"threatModelOption":true,"traceCommandUseBuildMode":true,"v2ramSizing":true,"mrvaPackCreateMultipleQueries":true,"setsCodeqlRunnerEnvVar":true,"sarifMergeRunsFromEqualCategory":true,"forceOverwrite":true,"generateSummarySymbolMap":true,"pythonDefaultIsToNotExtractStdlib":true,"queryServerRunQueries":true,"queryServerTrimCacheWithMode":true,"builtinExtractorsSpecifyDefaultQueries":true,"bqrsDiffResultSets":true,"bundleSupportsIncludeOption":true,"suppressesMissingFileBaselineWarning":true}}}
   CODEQL_ACTION_GO_BINARY: /home/runner/work/_temp/codeql-action-go-tracing/bin/go
   CODEQL_RAM: 14575
   CODEQL_THREADS: 4
   CODEQL_PROXY_HOST:
   CODEQL_PROXY_PORT:
   CODEQL_PROXY_CA_CERTIFICATE:
   CODEQL_PROXY_URLS:
 ##[endgroup]
 ##[group]Attempting to automatically build go code
 [command]/opt/hostedtoolcache/CodeQL/2.25.6/x64/codeql/codeql database trace-command --use-build-mode --working-dir /home/runner/work/cli/cli /home/runner/work/_temp/codeql_databases/go
 Picked up JAVA_TOOL_OPTIONS:  -Dhttp.keepAlive=false -Dmaven.wagon.http.pool=false
 Running command in /home/runner/work/cli/cli: [/opt/hostedtoolcache/CodeQL/2.25.6/x64/codeql/go/tools/autobuild.sh]
 [] [build-stderr] 2026/07/04 15:01:46 Autobuilder was built with go1.26.0, environment has go1.24.13
 [] [build-stderr] 2026/07/04 15:01:46 LGTM_SRC is /home/runner/work/cli/cli
 [] [build-stderr] 2026/07/04 15:01:46 Found no go.work files in the workspace; looking for go.mod files...
 [] [build-stderr] 2026/07/04 15:01:46 Found 1 go.mod files in: shims/go/go.mod.
 [] [build-stderr] 2026/07/04 15:01:46 Found 1 go.mod file(s).
 [] [build-stderr] 2026/07/04 15:01:46 Import path is 'github.com/archgate/cli'
 [] [build-stderr] 2026/07...

GitHub Actions: Code Quality: PR #451 / 0_Analyze (go).txt: Code Quality: PR #451

Conclusion: failure

View job details

01:56 Extracting types for package crypto/aes.
 [] [build-stderr] 2026/07/04 15:01:56 Done extracting types for package crypto/aes.
 [] [build-stderr] 2026/07/04 15:01:56 Processing package crypto/des.
 [] [build-stderr] 2026/07/04 15:01:56 Extracting types for package crypto/des.
 [] [build-stderr] 2026/07/04 15:01:56 Done extracting types for package crypto/des.
 [] [build-stderr] 2026/07/04 15:01:56 Processing package crypto/internal/fips140/nistec/fiat.
 [] [build-stderr] 2026/07/04 15:01:56 Extracting types for package crypto/internal/fips140/nistec/fiat.
 [] [build-stderr] 2026/07/04 15:01:56 Done extracting types for package crypto/internal/fips140/nistec/fiat.
 [] [build-stderr] 2026/07/04 15:01:56 Processing package crypto/internal/fips140/nistec.
 [] [build-stderr] 2026/07/04 15:01:56 Extracting types for package crypto/internal/fips140/nistec.
 [] [build-stderr] 2026/07/04 15:01:56 Done extracting types for package crypto/internal/fips140/nistec.
 [] [build-stderr] 2026/07/04 15:01:56 Processing package crypto/internal/fips140/ecdh.
 [] [build-stderr] 2026/07/04 15:01:56 Extracting types for package crypto/internal/fips140/ecdh.
 [] [build-stderr] 2026/07/04 15:01:56 Done extracting types for package crypto/internal/fips140/ecdh.
 [] [build-stderr] 2026/07/04 15:01:56 Processing package crypto/internal/fips140/edwards25519/field.
 [] [build-stderr] 2026/07/04 15:01:56 Extracting types for package crypto/internal/fips140/edwards25519/field.
 [] [build-stderr] 2026/07/04 15:01:56 Done extracting types for package crypto/internal/fips140/edwards25519/field.
 [] [build-stderr] 2026/07/04 15:01:56 Processing package crypto/ecdh.
 [] [build-stderr] 2026/07/04 15:01:56 Extracting types for package crypto/ecdh.
 [] [build-stderr] 2026/07/04 15:01:56 Done extracting types for package crypto/ecdh.
 [] [build-stderr] 2026/07/04 15:01:56 Processing package crypto/elliptic.
 [] [build-stderr] 2026/07/04 15:01:56 Extracting types for package crypto/elliptic.
 [] [bu...
🧰 Additional context used
📓 Path-based instructions (3)
.github/workflows/*.yml

📄 CodeRabbit inference engine (.archgate/adrs/CI-001-pin-github-actions-by-hash.md)

.github/workflows/*.yml: In GitHub Actions workflow files under .github/workflows/*.yml, every third-party uses: reference must be pinned to a full 40-character commit SHA and include a human-readable version comment on the same line (for example, uses: owner/action@<40-char-sha> # v4).
In GitHub Actions workflow files under .github/workflows/*.yml, do not reference third-party actions or reusable workflows by tag, branch, or abbreviated SHA; only a full 40-character commit SHA is allowed for third-party uses: entries.
In GitHub Actions workflow files under .github/workflows/*.yml, local workflow references (uses: ./.github/workflows/...) and local composite action references (uses: ./.github/actions/...) are exempt from SHA pinning because they stay within the same repository trust boundary.
In GitHub Actions workflow files under .github/workflows/*.yml, the slsa-framework/slsa-github-generator/.github/workflows/* reusable workflow is exempt from SHA pinning and must be referenced by tag (for example, @v2.1.0).

Files:

  • .github/workflows/smoke-test-linux.yml
  • .github/workflows/release-binaries.yml
  • .github/workflows/publish-shims.yml
  • .github/workflows/code-pull-request.yml
.github/workflows/*

📄 CodeRabbit inference engine (.archgate/adrs/GEN-003-tool-invocation-via-scripts.md)

.github/workflows/*: Do not use direct lint/format binary invocations such as bunx prettier, bunx oxfmt, npx eslint, oxlint ., or similar in GitHub Actions workflows; call the repository scripts instead.
In GitHub Actions workflows, do not run bare bun test; use bun run test so the script-level flags from package.json are applied.

Files:

  • .github/workflows/smoke-test-linux.yml
  • .github/workflows/release-binaries.yml
  • .github/workflows/publish-shims.yml
  • .github/workflows/code-pull-request.yml
.github/workflows/code-pull-request.yml

📄 CodeRabbit inference engine (.archgate/adrs/CI-002-validate-workflow-syntax-with-actionlint.md)

.github/workflows/code-pull-request.yml: In .github/workflows/code-pull-request.yml, run actionlint as its own dedicated job and make it a required dependency of the status gate job via needs:, so workflow syntax validation is a hard blocker.
Install actionlint by fetching rhysd/actionlint/scripts/download-actionlint.bash from a specific 40-character commit SHA and passing an explicit pinned actionlint version argument, never latest or a branch ref.
Set persist-credentials: false on the job's actions/checkout step.
Treat all actionlint findings as hard blockers; the job must fail the pipeline on any finding and must not be advisory-only.
When upgrading actionlint, update the pinned download-script commit SHA and the actionlint version together.
Do not add a reviewdog/action-actionlint wrapper Action; install and run the binary directly instead.
Do not fetch download-actionlint.bash from a branch ref such as main, and do not omit the version argument so it defaults to latest.

Files:

  • .github/workflows/code-pull-request.yml
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: archgate/cli

Timestamp: 2026-07-04T15:01:47.137Z
Learning: Rule authors must not be able to reach subprocess or filesystem primitives directly; `ctx.ast()` is the only sanctioned door for language tooling.
Learnt from: CR
Repo: archgate/cli

Timestamp: 2026-07-04T15:01:47.137Z
Learning: Do not normalize Python/Ruby AST output into an ESTree-like shape as part of this ADR.
Learnt from: CR
Repo: archgate/cli

Timestamp: 2026-07-04T15:01:47.137Z
Learning: Do not add `tree-sitter`, `web-tree-sitter`, or any other new bundled multi-language parser under this decision.
Learnt from: CR
Repo: archgate/cli

Timestamp: 2026-07-04T15:01:47.137Z
Learning: A future bundled multi-language parser proposal must be documented as a separate ADR and reviewed under ARCH-006 before implementation.
Learnt from: CR
Repo: archgate/cli

Timestamp: 2026-07-04T15:01:47.137Z
Learning: `ctx.ast()` must use each language’s native AST facility for Python and Ruby rather than relying on third-party CLI output or a unified cross-language AST vocabulary.
Learnt from: CR
Repo: archgate/cli

Timestamp: 2026-07-04T15:01:57.170Z
Learning: For any change to the `actionlint` job, reviewers must verify the install script is pinned to a commit SHA, the version argument is explicit, the job remains in `status`'s `needs:` list, and the invocation still scans all `.github/workflows/` files.
Learnt from: CR
Repo: archgate/cli

Timestamp: 2026-07-04T15:02:14.540Z
Learning: Before any task is considered complete, `bun run validate` must pass (lint → typecheck → format:check → test → ADR check → knip → build check).
Learnt from: CR
Repo: archgate/cli

Timestamp: 2026-07-04T15:02:14.540Z
Learning: Use the configured Git hooks (`pre-commit` and `pre-push`) to run validation locally before commits and pushes.
🪛 GitHub Check: zizmor
.github/workflows/code-pull-request.yml

[failure] 95-95:
code injection via template expansion: may expand into attacker-controllable code

🔇 Additional comments (4)
.github/workflows/publish-shims.yml (1)

111-125: LGTM!

.github/workflows/release-binaries.yml (1)

145-158: LGTM!

.github/workflows/code-pull-request.yml (1)

214-233: LGTM!

.github/workflows/smoke-test-linux.yml (1)

97-98: LGTM!

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 4, 2026
Inlining `${{ github.base_ref }}` directly into the shim-changes run:
block tripped zizmor's template-injection check as a new error-level
finding on the PR. Pass it through env instead.

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
@rhuanbarreto rhuanbarreto enabled auto-merge (squash) July 5, 2026 00:50
@rhuanbarreto rhuanbarreto merged commit 21829b5 into main Jul 5, 2026
28 checks passed
@rhuanbarreto rhuanbarreto deleted the claude/playful-orbiting-reddy branch July 5, 2026 00:51
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.

2 participants