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:
- File read from disk
- TypeScript transpilation
- Module evaluation
- 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:
- On
archgate check, compute hash(file_content) for each .rules.ts
- Compare against a cached hash (in-memory or on disk at
.archgate/.cache/rules-hash.json)
- If unchanged, reuse the previously loaded
RuleSet (skip import + parse + validate)
- 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
Context
Each
archgate checkinvocation dynamically imports every.rules.tsfile via: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 cachesimport()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:
RuleSetProposal
Approach: Hash-based caching
Instead of always cache-busting, compute a content hash of each
.rules.tsfile and only re-import when the hash changes:archgate check, computehash(file_content)for each.rules.ts.archgate/.cache/rules-hash.json)RuleSet(skip import + parse + validate)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 inittimeBundle all
.rules.tsinto a single module duringarchgate initor a newarchgate compile-rulescommand. Thecheckcommand would import one file instead of N. Downside: requires a build step and introduces staleness risk.Considerations
scanRuleFile) runs before import — its results could also be cached by hashRuleSetSchema.safeParse()validation could be skipped for cached modulesImpact
Files to modify
src/engine/loader.ts— add hash-based caching around theimport()callsrc/helpers/paths.ts— add cache directory path