Skip to content

perf: pre-transpile .rules.ts files to avoid per-run dynamic import overhead #345

Description

@rhuanbarreto

Context

Each archgate check invocation dynamically imports every .rules.ts file via:

// src/engine/loader.ts, line 314-315
const rulesUrl = `${pathToFileURL(rulesFile).href}?t=${Date.now()}`;
const mod = await import(rulesUrl);

The ?t=${Date.now()} cache-buster forces Bun to re-parse and re-evaluate each rule file on every run. This is necessary because Bun caches import() per-process, and rules may have changed between invocations.

For projects with many ADRs (10–30+), this means 10–30 separate dynamic imports per check, each requiring:

  1. File read from disk
  2. TypeScript transpilation
  3. Module evaluation
  4. Zod schema validation of the exported RuleSet

Proposal

Approach: Hash-based caching

Instead of always cache-busting, compute a content hash of each .rules.ts file and only re-import when the hash changes:

  1. On archgate check, compute hash(file_content) for each .rules.ts
  2. Compare against a cached hash (in-memory or on disk at .archgate/.cache/rules-hash.json)
  3. If unchanged, reuse the previously loaded RuleSet (skip import + parse + validate)
  4. If changed, import fresh and update the cache

This preserves correctness (rules always reflect the latest file content) while skipping redundant work in the common case where rules haven't changed since the last check.

Alternative: Pre-bundle at archgate init time

Bundle all .rules.ts into a single module during archgate init or a new archgate compile-rules command. The check command would import one file instead of N. Downside: requires a build step and introduces staleness risk.

Considerations

  • The security scanner (scanRuleFile) runs before import — its results could also be cached by hash
  • RuleSetSchema.safeParse() validation could be skipped for cached modules
  • Watch mode (if added later) would invalidate the cache on file change events

Impact

  • Primary beneficiary: Projects with many ADRs/rules (10+ rule files)
  • Expected improvement: ~50–200ms reduction in check latency (depending on rule count and file sizes)
  • Risk: Medium — cache invalidation bugs could cause stale rules to run. Mitigate with hash verification.

Files to modify

  • src/engine/loader.ts — add hash-based caching around the import() call
  • Possibly src/helpers/paths.ts — add cache directory path

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions