perf(rules-injector): cache compiled glob matchers

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
YeonGyu-Kim
2026-05-18 11:52:44 +09:00
parent a7e5a657e9
commit 1ab1b54ce6
2 changed files with 97 additions and 1 deletions
+70
View File
@@ -0,0 +1,70 @@
/// <reference path="../../../bun-test.d.ts" />
import { beforeEach, describe, expect, it } from "bun:test"
import {
createContentHash,
getMatcherCacheStats,
isDuplicateByContentHash,
isDuplicateByRealPath,
resetMatcherCache,
shouldApplyRule,
} from "./matcher"
describe("shouldApplyRule", () => {
beforeEach(() => {
resetMatcherCache()
})
it("#given repeated glob metadata #when matching many files #then compiles each pattern once", () => {
// given
const metadata = { globs: ["src/**/*.ts", "test/**/*.ts"] }
const projectRoot = "/workspace/project"
// when
for (let index = 0; index < 20; index += 1) {
shouldApplyRule(metadata, `${projectRoot}/src/file-${index}.ts`, projectRoot)
shouldApplyRule(metadata, `${projectRoot}/test/file-${index}.ts`, projectRoot)
}
// then
expect(getMatcherCacheStats()).toEqual({ entries: 2 })
})
it("#given matching glob #when path is under project root #then returns matching reason", () => {
// given / when
const result = shouldApplyRule({ globs: "src/**/*.ts" }, "/workspace/project/src/index.ts", "/workspace/project")
// then
expect(result).toEqual({ applies: true, reason: "glob: src/**/*.ts" })
})
it("#given always apply metadata #when no globs exist #then applies without compiling matchers", () => {
// given / when
const result = shouldApplyRule({ alwaysApply: true }, "/workspace/project/src/index.ts", "/workspace/project")
// then
expect(result).toEqual({ applies: true, reason: "alwaysApply" })
expect(getMatcherCacheStats()).toEqual({ entries: 0 })
})
})
describe("rule duplicate helpers", () => {
it("#given real path cache #when path exists #then reports duplicate", () => {
// given
const cache = new Set(["/workspace/project/AGENTS.md"])
// when / then
expect(isDuplicateByRealPath("/workspace/project/AGENTS.md", cache)).toBe(true)
expect(isDuplicateByRealPath("/workspace/project/src/AGENTS.md", cache)).toBe(false)
})
it("#given content #when hashing #then duplicate helper uses truncated hash", () => {
// given
const hash = createContentHash("rule-content")
const cache = new Set([hash])
// when / then
expect(hash).toHaveLength(16)
expect(isDuplicateByContentHash(hash, cache)).toBe(true)
})
})
+27 -1
View File
@@ -3,11 +3,37 @@ import { relative } from "node:path"
import picomatch from "picomatch"
import type { RuleMetadata } from "./types"
type PathMatcher = (path: string) => boolean
export interface MatchResult {
applies: boolean
reason?: string
}
export interface MatcherCacheStats {
entries: number
}
const PICOMATCH_OPTIONS = { dot: true, bash: true } as const
const matcherCache = new Map<string, PathMatcher>()
function matcherFor(pattern: string): PathMatcher {
const cached = matcherCache.get(pattern)
if (cached) return cached
const matcher = picomatch(pattern, PICOMATCH_OPTIONS)
matcherCache.set(pattern, matcher)
return matcher
}
export function resetMatcherCache(): void {
matcherCache.clear()
}
export function getMatcherCacheStats(): MatcherCacheStats {
return { entries: matcherCache.size }
}
/**
* Check if a rule should apply to the current file based on metadata
*/
@@ -33,7 +59,7 @@ export function shouldApplyRule(
const relativePath = projectRoot ? relative(projectRoot, currentFilePath) : currentFilePath
for (const pattern of patterns) {
if (picomatch.isMatch(relativePath, pattern, { dot: true, bash: true })) {
if (matcherFor(pattern)(relativePath)) {
return { applies: true, reason: `glob: ${pattern}` }
}
}