The authorize method in arcp-runtime/src/main/java/dev/arcp/runtime/lease/LeaseGuard.java around line 35 invokes the matches static method on line 53 for every allowed pattern, and matches calls globToRegex which constructs a fresh StringBuilder, walks the glob character by character, then calls java.util.regex.Pattern.compile on line 77. Pattern compilation is one of the heavier operations in the JDK regex package and is normally cached. Here it runs every single time a job invokes JobContext.authorize(namespace, pattern), multiplied by the number of allowed patterns in the lease's namespace. A typical agent may authorize dozens of file paths and tool calls per second; with a lease that grants a handful of patterns per namespace, this is hundreds of regex compilations per second of agent execution — pure overhead on the hot path.\n\nThe globs themselves never change for the lifetime of a Lease, so the compiled Patterns are trivially cacheable.\n\nFix prompt: In arcp-runtime/src/main/java/dev/arcp/runtime/lease/LeaseGuard.java introduce a private final ConcurrentHashMap<String, Pattern> compiledGlobs = new ConcurrentHashMap<>() field on the guard. Replace the matches helper with one that calls compiledGlobs.computeIfAbsent(pattern, LeaseGuard::globToRegex).matcher(value).matches(), and make globToRegex package-private static. Because LeaseGuard is constructed per-job (see SessionLoop.runJob around line 515 and issueContext around line 674), the cache will be discarded when the job ends — that is the right lifetime. If profiling shows the per-job allocation of the map itself is significant, hoist a Lease-level cache instead. Add a JMH benchmark (or a JUnit test that times 10 000 authorize calls against a lease with 8 patterns) that demonstrates the speedup, and ensure the existing ModelUseEnforcementTest still passes.
The authorize method in arcp-runtime/src/main/java/dev/arcp/runtime/lease/LeaseGuard.java around line 35 invokes the matches static method on line 53 for every allowed pattern, and matches calls globToRegex which constructs a fresh
StringBuilder, walks the glob character by character, then callsjava.util.regex.Pattern.compileon line 77. Pattern compilation is one of the heavier operations in the JDK regex package and is normally cached. Here it runs every single time a job invokesJobContext.authorize(namespace, pattern), multiplied by the number of allowed patterns in the lease's namespace. A typical agent may authorize dozens of file paths and tool calls per second; with a lease that grants a handful of patterns per namespace, this is hundreds of regex compilations per second of agent execution — pure overhead on the hot path.\n\nThe globs themselves never change for the lifetime of a Lease, so the compiled Patterns are trivially cacheable.\n\nFix prompt: In arcp-runtime/src/main/java/dev/arcp/runtime/lease/LeaseGuard.java introduce a private finalConcurrentHashMap<String, Pattern> compiledGlobs = new ConcurrentHashMap<>()field on the guard. Replace the matches helper with one that callscompiledGlobs.computeIfAbsent(pattern, LeaseGuard::globToRegex).matcher(value).matches(), and make globToRegex package-private static. Because LeaseGuard is constructed per-job (see SessionLoop.runJob around line 515 and issueContext around line 674), the cache will be discarded when the job ends — that is the right lifetime. If profiling shows the per-job allocation of the map itself is significant, hoist a Lease-level cache instead. Add a JMH benchmark (or a JUnit test that times 10 000 authorize calls against a lease with 8 patterns) that demonstrates the speedup, and ensure the existing ModelUseEnforcementTest still passes.