[ef-9] perf/fix: simplify codebase, fix bugs, optimize hot paths#8
Conversation
Bug fixes: - lib/resolve-subagent-path: fix inverted error handling (ENOENT should continue, not non-ENOENT); non-ENOENT errors now break the search - lib/log-entries: clamp durationMs to 0 to prevent negative durations from clock skew producing outputs like "-0.3s" Performance: - src/hooks/builtin-policies: hoist all static regex literals to module-level constants so they are compiled once, not per-call - src/hooks/builtin-policies: cache git branch per cwd in blockWorkOnMain to avoid repeated synchronous execSync (up to 3s block per call) - src/hooks/policy-registry: add lazy index cache to getPoliciesForEvent so filter+sort runs once per (eventType, toolName) pair instead of on every tool event - lib/projects: replace unbounded Promise.all with batchAll(concurrency=16) in getProjectFolders and getSessionFiles to avoid fd exhaustion - lib/runtime-cache: remove TTL refresh on cache hits (was causing hot keys to live in cache indefinitely, defeating the revalidateSeconds contract); eviction is now insertion-order (FIFO) Simplification: - lib/format-duration: extract shared formatRelativeTime utility - app/policies/hooks-client: remove duplicate formatRelativeTime, import from lib/format-duration - app/components/session-hooks-panel: remove duplicate formatRelativeTime and local CopyButton reimplementation; use shared components Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Free Run ID: 📒 Files selected for processing (11)
💤 Files with no reviewable changes (1)
📝 WalkthroughWalkthroughThe PR consolidates duplicate formatting utilities into shared modules, optimizes caching strategies across runtime and policy registries, hoists compiled regular expressions to module-level constants, introduces git branch caching, refactors async promise handling with concurrency limits, adjusts error handling logic, and updates tests to reflect new cache behaviors. Changes
Sequence Diagram(s)sequenceDiagram
participant Caller as Policy Event Handler
participant Registry as getPoliciesForEvent()
participant Cache as Index Cache
participant Store as Policy Registry Store
Caller->>Registry: getPoliciesForEvent(eventType, toolName)
Registry->>Cache: Check cache key (eventType, toolName)
alt Cache Hit
Cache-->>Registry: Return cached policies array
Registry-->>Caller: Return policies
else Cache Miss
Registry->>Store: Query policies from registry
Store-->>Registry: Return unfiltered policies
Registry->>Registry: Filter by event type & tool name
Registry->>Registry: Sort by priority
Registry->>Cache: Store result in cache
Cache-->>Registry: Cache updated
Registry-->>Caller: Return policies
end
Estimated Code Review Effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
Note 🎁 Summarized by CodeRabbit FreeYour organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Pro by visiting https://app.coderabbit.ai/login. Comment |
Summary
resolveSubagentPath(non-ENOENT errors silently continued); negativedurationMsfrom clock skew in log enrichmentgit rev-parsecached per-cwd inblockWorkOnMain(avoids repeated 3s synchronous block); policy registry lookup now uses a lazy index cache;Promise.allin project/session listing replaced with boundedbatchAll(16)to prevent fd exhaustion; removed TTL refresh on cache hits inruntimeCache(was defeating therevalidateSecondscontract)formatRelativeTimetolib/format-duration.ts; removed duplicate implementations inhooks-client.tsxandsession-hooks-panel.tsx; replaced localCopyButtonreimplementation with the shared componentTest plan
bun run build— passes, no TypeScript errorsbun run test:run— 709/709 tests passblockWorkOnMaintwice on the same repo — second call should be instant (no execSync)🤖 Generated with Claude Code
Summary by CodeRabbit
Release Notes
Performance
Bug Fixes