Skip to content

feat(lint): migrate to TypeScript 7 and adopt oxlint type-aware linting - #534

Merged
rhuanbarreto merged 18 commits into
mainfrom
claude/warm-watching-hollerith
Jul 27, 2026
Merged

feat(lint): migrate to TypeScript 7 and adopt oxlint type-aware linting#534
rhuanbarreto merged 18 commits into
mainfrom
claude/warm-watching-hollerith

Conversation

@rhuanbarreto

Copy link
Copy Markdown
Contributor

Summary

Supersedes #529 (Renovate's TypeScript v7 peer-range bump). That PR alone widened peerDependencies.typescript but did nothing else — TypeScript was never pinned as an explicit devDependency, so nothing would actually start using TS7. This PR does the real migration:

  • Pins typescript (7.0.2) and adds oxlint-tsgolint (7.0.2001) as explicit, exact-pinned devDependencies — previously TypeScript resolved only transitively from the peer range.
  • Enables oxlint's new type-aware linting engine (options.typeAware: true) with 58 of the 59 currently-implemented typescript/* type-aware rules at "error". typescript/prefer-readonly-parameter-types is excluded (not in typescript-eslint's own recommended/strict presets; alone accounted for ~930 of ~3546 trial findings). require-await (both forms) is disabled — it directly contradicts typescript/promise-function-async for the common "async mock trivially resolving a value" shape.
  • Activates typescript/no-deprecated for the first time — it was already configured in .oxlintrc.json but silently inert since type-aware linting was never available before TS7.
  • Fixes every finding the new rules surfaced across src/, tests/, lint/, and .archgate/adrs/*.rules.ts: precise Mock<T> typing for bun:test spies (replacing untyped ReturnType<typeof spyOn>), real zod-schema narrowing in place of unchecked JSON.parse casts, explicit boolean coercion for nullable env/string checks per ARCH-014, async/await correctness, and narrow justified suppressions only for deliberately-fake test fixtures or genuine tsgolint/tsc parity gaps (documented inline).
  • Scopes shims/ (untyped distribution CJS) and docs/ (separate sub-project, deps not installed at root) out of type-aware analysis via .oxlintrc.json overrides/ignorePatterns.
  • Adds ARCH-026 (new ADR) documenting the type-aware linting policy, and extends ARCH-014/ARCH-019 with caveats surfaced during the migration.

Test plan

  • bun run lint — clean, zero findings
  • bun run typecheck — clean
  • bun run format:check — clean (repo-tracked files)
  • bun run test — 1812 pass / 22 skip / 0 fail across 1834 tests
  • bun run check — 50/50 ADR rules pass, including new ARCH-026 companion rule
  • bun run knip — clean
  • bun run build:check — clean
  • Fully synced with origin/main (no divergence)

Supersedes PR #529's peer-range widening. Pins an explicit typescript@7.0.2
devDependency (previously resolved only transitively), adds oxlint-tsgolint,
and enables oxlint's type-aware engine (options.typeAware) with 58 of the
59 currently-implemented typescript/* type-aware rules at "error"
(prefer-readonly-parameter-types excluded — not in typescript-eslint's own
recommended/strict presets, accounted for ~930 of ~3546 trial findings).

This activates typescript/no-deprecated for the first time — it was already
configured in .oxlintrc.json but silently inert since type-aware linting
was never available before TS7.

Fixes every finding the new rules surfaced across src/, tests/, lint/, and
the .archgate/adrs/*.rules.ts companion files: precise Mock<T> typing for
bun:test spies (replacing untyped ReturnType<typeof spyOn>), real zod-schema
narrowing in place of unchecked JSON.parse casts, explicit boolean coercion
for nullable env/string checks per ARCH-014, async/await correctness, and
narrow justified suppressions only for deliberately-fake test fixtures or
genuine tsgolint/tsc parity gaps (documented inline).

Scopes shims/ (untyped distribution CJS) and docs/ (separate sub-project,
dependencies not installed at root) out of type-aware analysis via
.oxlintrc.json overrides/ignorePatterns.

Signed-off-by: Claude <noreply@anthropic.com>
Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
Accidentally included in the previous commit.

Signed-off-by: Claude <noreply@anthropic.com>
Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
…hollerith

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

# Conflicts:
#	knip.json
… migration

- New ARCH-026 (Type-Aware TypeScript Linting): documents the TypeScript 7 +
  oxlint-tsgolint adoption decision, the explicit devDependency pinning
  rationale, the 58-of-59 rule-selection policy (prefer-readonly-parameter-types
  and require-await excluded, with reasoning), scope exclusions (shims/,
  docs/, .simple-release.js), and the Mock<T>/async/suppression conventions
  the fix pass established. Companion rule verifies .oxlintrc.json's
  options.typeAware and the paired devDependencies stay present.
- ARCH-014: adds the Boolean()-as-sole-condition vs eslint(no-extra-boolean-cast)
  caveat surfaced by enabling strict-boolean-expressions.
- ARCH-019: adds a worked example for keeping withPromptFix adjacent to
  inquirer.prompt() when the prompt body is too long to stay inline (a real
  false-positive hit during the migration).
- Agent memory: records that parallel subagents sharing one working
  directory (no worktree isolation) can have their uncommitted work silently
  wiped by any single agent's stray git stash/rebase/reset — observed twice
  during this session's 12-agent fix campaign.

Signed-off-by: Claude <noreply@anthropic.com>
Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
…hollerith

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

# Conflicts:
#	.archgate/adrs/ARCH-020-glob-scan-include-dotfiles.rules.ts
#	.archgate/adrs/ARCH-023-engine-file-listing-via-in-memory-git-tracked-matching.rules.ts
@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 193 files, which is 93 over the limit of 100.

To get a review, narrow the scope:
• coderabbit review --committed # exclude uncommitted changes
• coderabbit review --dir # limit to a subdirectory
• coderabbit review --base # compare against a closer base

Upgrade to a paid plan to raise the limit.

This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 8b50d712-8805-4e50-841f-e282f6118206

📥 Commits

Reviewing files that changed from the base of the PR and between 0dbc4b3 and 85dbdbb.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (193)
  • .archgate/adrs/ARCH-001-command-structure.rules.ts
  • .archgate/adrs/ARCH-002-error-handling.rules.ts
  • .archgate/adrs/ARCH-003-output-formatting.rules.ts
  • .archgate/adrs/ARCH-005-testing-standards.rules.ts
  • .archgate/adrs/ARCH-007-cross-platform-subprocess-execution.rules.ts
  • .archgate/adrs/ARCH-008-typed-command-options.rules.ts
  • .archgate/adrs/ARCH-009-platform-detection-helper.rules.ts
  • .archgate/adrs/ARCH-010-prefer-bun-built-in-json-parsing.rules.ts
  • .archgate/adrs/ARCH-012-command-error-boundaries.rules.ts
  • .archgate/adrs/ARCH-013-version-synchronization.rules.ts
  • .archgate/adrs/ARCH-014-prefer-bun-env.md
  • .archgate/adrs/ARCH-014-prefer-bun-env.rules.ts
  • .archgate/adrs/ARCH-017-multi-ecosystem-distribution.rules.ts
  • .archgate/adrs/ARCH-018-lazy-load-heavy-dependencies.rules.ts
  • .archgate/adrs/ARCH-019-inquirer-prompt-fix.md
  • .archgate/adrs/ARCH-020-glob-scan-include-dotfiles.rules.ts
  • .archgate/adrs/ARCH-022-ast-aware-rule-context.rules.ts
  • .archgate/adrs/ARCH-023-engine-file-listing-via-in-memory-git-tracked-matching.rules.ts
  • .archgate/adrs/CI-001-pin-github-actions-by-hash.rules.ts
  • .archgate/adrs/GEN-002-docs-i18n.rules.ts
  • .archgate/adrs/LEGAL-001-spdx-license-headers.rules.ts
  • .archgate/adrs/LEGAL-002-dependency-license-compatibility.rules.ts
  • .archgate/lint/concise-comments.ts
  • .archgate/lint/oxlint.ts
  • .claude/agent-memory/archgate-developer/MEMORY.md
  • .claude/agent-memory/archgate-developer/feedback_parallel_agents_shared_worktree.md
  • .claude/agent-memory/archgate-developer/feedback_prefer_tests_over_adr_rules.md
  • .claude/agent-memory/archgate-developer/feedback_validate_from_fresh_clone.md
  • .oxlintrc.json
  • .simple-release.js
  • lint/expect-expect.ts
  • lint/no-bare-env-restore.ts
  • package.json
  • scripts/ensure-rules-dts.ts
  • src/cli.ts
  • src/commands/adr/create.ts
  • src/commands/adr/domain/add.ts
  • src/commands/adr/domain/list.ts
  • src/commands/adr/domain/remove.ts
  • src/commands/adr/import.ts
  • src/commands/adr/list.ts
  • src/commands/adr/sync.ts
  • src/commands/adr/update.ts
  • src/commands/check.ts
  • src/commands/doctor.ts
  • src/commands/init.ts
  • src/commands/login.ts
  • src/commands/review-context.ts
  • src/commands/upgrade.ts
  • src/engine/adr-sections.ts
  • src/engine/ast-support.ts
  • src/engine/context.ts
  • src/engine/git-files.ts
  • src/engine/glob-utils.ts
  • src/engine/js-parser.ts
  • src/engine/loader.ts
  • src/engine/reporter.ts
  • src/engine/rule-scanner.ts
  • src/engine/runner.ts
  • src/engine/source-positions.ts
  • src/engine/suppressions.ts
  • src/engine/yaml-utils.ts
  • src/formats/adr.ts
  • src/formats/pack.ts
  • src/helpers/adr-import.ts
  • src/helpers/adr-templates.ts
  • src/helpers/adr-writer.ts
  • src/helpers/auth.ts
  • src/helpers/binary-upgrade.ts
  • src/helpers/claude-settings.ts
  • src/helpers/cli-options.ts
  • src/helpers/credential-store.ts
  • src/helpers/doctor.ts
  • src/helpers/editor-detect.ts
  • src/helpers/exit.ts
  • src/helpers/git.ts
  • src/helpers/init-project.ts
  • src/helpers/install-info.ts
  • src/helpers/log.ts
  • src/helpers/login-flow.ts
  • src/helpers/opencode-settings.ts
  • src/helpers/output.ts
  • src/helpers/pack-recommend.ts
  • src/helpers/paths.ts
  • src/helpers/platform.ts
  • src/helpers/plugin-install.ts
  • src/helpers/project-config.ts
  • src/helpers/prompt.ts
  • src/helpers/registry.ts
  • src/helpers/repo-probe.ts
  • src/helpers/repo.ts
  • src/helpers/rules-shim.ts
  • src/helpers/sentry.ts
  • src/helpers/session-context-copilot.ts
  • src/helpers/session-context-opencode.ts
  • src/helpers/session-context.ts
  • src/helpers/signup.ts
  • src/helpers/stack-detect.ts
  • src/helpers/telemetry-config.ts
  • src/helpers/telemetry.ts
  • src/helpers/update-check.ts
  • src/helpers/vscode-settings.ts
  • tests/commands/adr.test.ts
  • tests/commands/adr/create.test.ts
  • tests/commands/adr/domain/add.test.ts
  • tests/commands/adr/domain/list.test.ts
  • tests/commands/adr/domain/remove.test.ts
  • tests/commands/adr/import.test.ts
  • tests/commands/adr/list.test.ts
  • tests/commands/adr/show.test.ts
  • tests/commands/adr/sync.test.ts
  • tests/commands/adr/update.test.ts
  • tests/commands/check-action.test.ts
  • tests/commands/clean.test.ts
  • tests/commands/doctor.test.ts
  • tests/commands/login.test.ts
  • tests/commands/plugin/install.test.ts
  • tests/commands/plugin/shared.test.ts
  • tests/commands/plugin/url.test.ts
  • tests/commands/review-context.test.ts
  • tests/commands/session-context/claude-code.test.ts
  • tests/commands/session-context/copilot.test.ts
  • tests/commands/session-context/cursor.test.ts
  • tests/commands/session-context/opencode.test.ts
  • tests/commands/telemetry.test.ts
  • tests/commands/upgrade-action.test.ts
  • tests/commands/upgrade.test.ts
  • tests/engine/adr-sections.test.ts
  • tests/engine/ast-support.test.ts
  • tests/engine/check-case.test.ts
  • tests/engine/context.test.ts
  • tests/engine/git-files.test.ts
  • tests/engine/glob-utils.test.ts
  • tests/engine/loader-security.test.ts
  • tests/engine/loader.test.ts
  • tests/engine/reporter.test.ts
  • tests/engine/rule-scanner-positions.test.ts
  • tests/engine/runner-ast-base.test.ts
  • tests/engine/runner-ast-cache.test.ts
  • tests/engine/runner-ast-comments.test.ts
  • tests/engine/runner-ast.test.ts
  • tests/engine/runner-file-filter.test.ts
  • tests/engine/runner-find-ast-nodes.test.ts
  • tests/engine/runner-gitignore.test.ts
  • tests/engine/runner.test.ts
  • tests/fixtures/rules/TEST-001-sample.rules.ts
  • tests/formats/rules.test.ts
  • tests/helpers/adr-import.test.ts
  • tests/helpers/adr-writer.test.ts
  • tests/helpers/auth.test.ts
  • tests/helpers/binary-upgrade.test.ts
  • tests/helpers/claude-settings.test.ts
  • tests/helpers/cli-options.test.ts
  • tests/helpers/copilot-settings.test.ts
  • tests/helpers/credential-store.test.ts
  • tests/helpers/cursor-settings.test.ts
  • tests/helpers/doctor.test.ts
  • tests/helpers/editor-detect.test.ts
  • tests/helpers/exit.test.ts
  • tests/helpers/git.test.ts
  • tests/helpers/init-base-branch.test.ts
  • tests/helpers/init-project.test.ts
  • tests/helpers/log.test.ts
  • tests/helpers/login-flow.test.ts
  • tests/helpers/opencode-settings.test.ts
  • tests/helpers/pack-recommend.test.ts
  • tests/helpers/platform.test.ts
  • tests/helpers/plugin-install-cleanup.test.ts
  • tests/helpers/plugin-install.test.ts
  • tests/helpers/project-config.test.ts
  • tests/helpers/prompt.test.ts
  • tests/helpers/registry.test.ts
  • tests/helpers/repo-probe.test.ts
  • tests/helpers/sentry.test.ts
  • tests/helpers/session-context-cursor.test.ts
  • tests/helpers/session-context-opencode.test.ts
  • tests/helpers/session-context.test.ts
  • tests/helpers/signup.test.ts
  • tests/helpers/stack-detect-frameworks.test.ts
  • tests/helpers/telemetry-config.test.ts
  • tests/helpers/telemetry.test.ts
  • tests/helpers/update-check.test.ts
  • tests/helpers/vscode-settings.test.ts
  • tests/integration/adr-show-update.test.ts
  • tests/integration/adr.test.ts
  • tests/integration/check-max-warnings.test.ts
  • tests/integration/check.test.ts
  • tests/integration/cli-harness.ts
  • tests/integration/import.test.ts
  • tests/integration/review-context.test.ts
  • tests/lint/no-bare-env-restore.test.ts
  • tests/test-utils.ts
  • tsconfig.json

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


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 26, 2026

Copy link
Copy Markdown

Deploying archgate-cli with  Cloudflare Pages  Cloudflare Pages

Latest commit: 85dbdbb
Status: ✅  Deploy successful!
Preview URL: https://09620bfc.archgate-cli.pages.dev
Branch Preview URL: https://claude-warm-watching-holleri.archgate-cli.pages.dev

View logs

@rhuanbarreto rhuanbarreto left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

General comment about type guards. This is super brittle. We should actually check if it is instead of a generic object.

Comment thread .archgate/adrs/ARCH-008-typed-command-options.rules.ts Outdated
…eckout

CI failed on this PR with ~1127 findings, every ctx.* access in
.archgate/adrs/*.rules.ts resolving to any/error instead of RuleContext.
Root cause: .archgate/rules.d.ts is gitignored and only regenerated as a
side effect of `archgate check`, but `bun run validate` runs `lint` before
`check` — a fresh checkout (any new clone, or CI) has neither the shim nor
tsconfig coverage for .archgate/ and scripts/ (neither dir was ever in
tsconfig's include), so type-aware analysis of those files silently
degrades to `any`. Never caught locally because this session's working
directory generated the shim early on and it persisted for the rest of the
session, papering over the ordering dependency. Reproduced by cloning the
pushed branch fresh and running `bun install --frozen-lockfile` there,
matching CI exactly.

- tsconfig.json: add .archgate/ and scripts/ to include.
- scripts/ensure-rules-dts.ts: new script wrapping the existing
  ensureRulesShim() helper (already used by `archgate check`/`init`).
- package.json: `lint` now runs the script before oxlint.
- ARCH-005's companion rule was the only .rules.ts file with a real import
  (node:path) and is the only one that still failed after the above —
  tsc --build resolves it fine, tsgolint doesn't (a parity gap, same
  category ARCH-026 documents). Replaced with two local string-based
  helpers instead, matching every other .rules.ts file's zero-import,
  ctx-sandboxed convention; fire-tested against a real missing-test-file
  case to confirm identical behavior.
- ARCH-026 + agent memory updated with both root causes.

Signed-off-by: Claude <noreply@anthropic.com>
Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
@github-actions

github-actions Bot commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Code Coverage

Metric Value
Lines 91.1% (8557 / 9398)
Threshold 90% minimum — met
Platforms Linux + Windows

Full HTML report available in workflow artifacts.

Per-directory breakdown
Directory Coverage Lines
src/commands/ 88.9% 2020 / 2271
src/engine/ 93.7% 2292 / 2446
src/formats/ 98.7% 148 / 150
src/helpers/ 90.4% 4097 / 4531

Investigated and confirmed dead configuration: it was load-bearing only
until an early PR (well before this session) removed the `./rules` export
and `defineRules()` helper it originally protected — consumers no longer
type-check against archgate's own source. Every actual consumer touchpoint
today is TypeScript-version-agnostic: the published npm shim
(shims/npm/archgate.cjs, the only file in package.json's `files` array)
never references TypeScript, and .rules.ts files load via Bun's own
runtime transpilation (src/engine/loader.ts's `await import(...)`), never
touching a consumer's installed typescript package. Since PR #86 it was
only ever mechanically widened by Renovate with no functional purpose.

Updated ARCH-026 (written earlier this session, before this was
investigated) to stop describing the peer range as a still-existing,
separate consumer-facing contract.

Signed-off-by: Claude <noreply@anthropic.com>
Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
Addresses review feedback: the isEsTreeNode() type guard introduced by the
type-aware lint fix pass only checked "is this a non-null object" — it
never verified the `type: string` field every real ESTree node carries,
so asEsTreeNode()/asEsTreeNodeArray() would silently narrow ANY object
(e.g. a `loc` position object) as if it were a genuine AST node.

Fixed across all 5 companion rule files that had it (ARCH-008, ARCH-012,
ARCH-020, ARCH-022, ARCH-023). For the 3 files with a custom walk()
(ARCH-008, ARCH-012, ARCH-022), split the old loose check into two:
isPlainObject() (unchanged, still gates walk()'s tree descent so it keeps
recursing into every object/array exactly as before) and a now-strict
isEsTreeNode() (requires `type: string`, used everywhere a value is
actually narrowed and treated as a node). ARCH-020/ARCH-023 have no custom
walk — isEsTreeNode() there only ever narrowed, so it's fixed directly
with no behavior-preservation concern.

Fire-tested ARCH-012's async-action-error-boundary rule against two real
probe violations (missing try-catch; an await escaping an existing
try-catch, exercising containsDirectAwait()'s AST traversal specifically)
to confirm the stricter check didn't regress detection.

Signed-off-by: Claude <noreply@anthropic.com>
Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 26, 2026
…l ADR

Per direct feedback: .oxlintrc.json's own inline comments already document
every decision ARCH-026 restated (rule selection, exclusions, version
pinning), and the config file itself is the enforcement layer — a
companion rule asserting "options.typeAware === true" can only ever
confirm the config still says what it says, never catch anything the
config wouldn't also just silently reflect. Removed the ADR and its
companion rule, and the cross-references added to ARCH-014/ARCH-019 (their
own substantive content — Boolean()/no-extra-boolean-cast,
withPromptFix-adjacency — stays; only the pointer to the now-deleted ADR
is removed).

Signed-off-by: Claude <noreply@anthropic.com>
Signed-off-by: Rhuan Barreto <rhuan@barreto.work>

@rhuanbarreto rhuanbarreto left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

First batch. Those comments are valid across the entire repo.

Comment thread lint/expect-expect.ts Outdated
Comment thread src/commands/adr/domain/remove.ts Outdated
Comment thread src/commands/adr/create.ts Outdated
Comment thread src/commands/adr/import.ts Outdated
…dback

Address the first batch of PR review comments (valid across the repo):
- lint/expect-expect.ts: replace the object+cast type guard with a real
  `isAstNode()` predicate using `in` narrowing, matching the .rules.ts
  pattern already fixed for the same brittleness.
- adr/create.ts: validate --title/--domain at the Commander option level
  via argParser, so blank values fail fast instead of being sensed with
  string comparisons downstream.
- adr/domain/remove.ts: derive existingPrefix from an `in`-guarded
  ternary instead of manually widening the Record's value type.
- adr/import.ts: extract the version-presence check to a const before
  the ternary, per ARCH-014's Boolean()-as-sole-condition caveat.

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 26, 2026
Sweep the codebase for the same two review-feedback patterns fixed in
24405bb and apply them wherever they recur, per "those comments are
valid across the entire repo":

- lint/no-bare-env-restore.ts had the identical object+cast type guard
  as lint/expect-expect.ts before its fix — replaced with the same
  isAstNode() predicate using `in` narrowing.
- adr/list.ts (--domain) and adr/update.ts (--title/--domain/--files)
  had the same unvalidated-CLI-option gap as adr/create.ts — extracted
  the argParser into a shared src/helpers/cli-options.ts (rejectBlank),
  reused by all three commands plus create.ts itself, with a test file.
- adr/sync.ts's findLocalAdr() had a dead `!== ""` check on a value
  that can never be empty by construction — dropped it.

Left alone: credential-store.ts's Record<string, string | undefined>
(legitimately spreads Bun.env, different case), several generic
isRecord/isJsonRecord/isAstNodeLike guards that are correctly typed as
generic objects (not falsely narrower), the no-unsafe-type-assertion
casts in ast-support.ts/runner.ts/binary-upgrade.ts (genuinely
irreducible, already justified inline), and check/review-context's
internal --adr/--base/--domain engine plumbing (shared with non-CLI
callers and tests, so a Commander-level fix wouldn't remove the
internal checks the way it did for the adr subcommand family).

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
Comment thread tests/integration/import.test.ts Outdated
Comment thread lint/expect-expect.ts Outdated
Comment thread src/commands/adr/domain/remove.ts Outdated
Comment thread src/commands/adr/create.ts Outdated
Comment thread src/commands/adr/import.ts Outdated
Comment thread src/commands/upgrade.ts Outdated
Comment thread src/commands/upgrade.ts Outdated
Comment thread src/engine/ast-support.ts
Comment thread src/engine/ast-support.ts
Comment thread src/engine/context.ts Outdated
Comment thread src/engine/context.ts Outdated
…use zod for AST guards

Third round of review feedback (--base/--domain/--adr option validation,
unbounded ancestor loops, brittle AST-shape checks, non-idiomatic test
matcher):

- check.ts's --base/--adr and review-context.ts's --base/--domain now
  validate via the shared rejectBlank argParser (ARCH-008), same as the
  adr subcommand family. Lets context.ts's buildReviewContext() and
  loader.ts's loadRuleAdrs() drop their now-redundant `!== ""` checks
  on the resolved values.
- upgrade.ts's findPackageRoot() and paths.ts's findProjectRoot() had
  identical unbounded `for (;;)` ancestor walks; both now cap at
  MAX_ANCESTOR_DEPTH (1000) as a hard stop against a pathological
  dirname() result, on top of the existing self-referential-root check.
- upgrade.ts's install-method match logic replaced a single compound
  `c !== null && c.binDir !== null && c.binDir !== "" && ...` predicate
  with two explicit filter() type predicates before find() — the
  literal `filter(Boolean)` suggested doesn't narrow away null under
  strict TS, so explicit predicates were needed instead.
- ast-support.ts's isAstNodeLike()/isPlainObject() now validate via
  zod schemas (z.record/z.union, matching the existing PlainObjectSchema
  pattern in formats/adr.ts) instead of hand-rolled typeof checks.
- tests/integration/import.test.ts's expectKeys() helper now asserts
  via Bun's toContainKey matcher (subset semantics, matching the
  original `k in v` check) instead of a hand-rolled throw — not
  toContainAllKeys, which is an exact-match matcher and would have
  broken the multi-key-object call sites.

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 26, 2026
…ing at the flagged spots

Prompted by "did you do a workflow to verify on the rest of the repo as
well?" — round 3 only touched the exact files named in review comments
plus two structural siblings noticed in passing. A real repo-wide grep
for the same patterns turned up more:

- .archgate/lint/oxlint.ts's isAstNode() had the identical `typeof ===
  "object"` + `as {type?:unknown}` cast shape as lint/expect-expect.ts
  and lint/no-bare-env-restore.ts before their earlier fixes (missed
  because that sweep only checked lint/ at the repo root, not
  .archgate/lint/) — same `"type" in value` narrowing fix applied.
- src/engine/loader.ts's isRecord() and src/helpers/init-project.ts's
  isJsonRecord() had the same generic-object shape ast-support.ts's
  isAstNodeLike()/isPlainObject() were converted to zod for — both now
  validate via the same z.record(z.string(), z.unknown()) schema.
- Also DRY'd out along the way, per direct feedback ("do you actually
  need to repeat it all? DRY it!"): a JSON-narrowing test helper
  (isRecord/expectKeys, or a hasKeys boolean variant) was copy-pasted
  with minor variations across 7 test files. Consolidated into one
  canonical isRecord/expectKeys/expectArray in tests/test-utils.ts;
  cli-harness.ts now re-exports expectKeys/expectArray from there
  instead of defining its own, and every call site across the 7 files
  was rewritten to the shared version (same assertions, same matcher
  choice as the earlier toContainKey fix).

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
includeServerName defaults to true in @sentry/node-core, so every event
sent os.hostname() as server_name regardless of the sendDefaultPii/
dataCollection settings already in place — Sentry's own option docs flag
this as the CLI-app PII case. The prior comment claimed hostnames were
already excluded by default, which was incorrect.

Signed-off-by: Rhuan Barreto <rhuan.barreto@gmail.com>
Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
Comment thread src/engine/yaml-utils.ts
Comment thread src/helpers/binary-upgrade.ts Outdated
Comment thread src/engine/source-positions.ts
Comment thread src/helpers/install-info.ts
Comment thread src/helpers/plugin-install.ts
Comment thread .oxlintrc.json
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 27, 2026
…r typing

- yaml-utils.ts / plugin-install.ts: isYamlValue() and isCursorHookArray()
  were hand-written recursive/shape guards; replace with zod schemas
  (z.lazy() for the recursive YamlValue case) mirroring the established
  PlainObjectSchema pattern used elsewhere in this PR.
- binary-upgrade.ts: the previous double-cast-through-unknown for the
  stream reader was based on an incorrect diagnosis (claimed lib.dom was
  missing Bun's readMany augmentation). The real cause: this repo's
  tsconfig excludes the DOM lib, so Response.body resolves through
  undici-types to node:stream/web's own ReadableStream<any>. Fixed by
  importing ReadableStreamDefaultReader directly from node:stream/web and
  narrowing with a single, still-necessary justified cast.

Addresses PR review feedback on #534.

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

Copy link
Copy Markdown
Contributor Author

@coderabbitai approve

@rhuanbarreto
rhuanbarreto enabled auto-merge (squash) July 27, 2026 12:28
@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown
✅ Action performed

Comments resolved and changes approved.

@rhuanbarreto
rhuanbarreto merged commit 29daad8 into main Jul 27, 2026
23 checks passed
@rhuanbarreto
rhuanbarreto deleted the claude/warm-watching-hollerith branch July 27, 2026 12:28
@archgatebot archgatebot Bot mentioned this pull request Jul 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant