Skip to content

Merge branch 'pingdotgg:main' into fix/git-status-cache-stable-lookups

MacroscopeApp / Macroscope - Effect Service Conventions failed Jul 30, 2026 in 2m 9s

Effect Service Conventions: 2 issues found

apps/server/src/vcs/GitVcsDriverCore.ts

  1. Lines 1124-1142 — the new defaultBranchCache / originExistsCache key on the raw cwd, unlike the sibling caches in this module which key on normalizeRepositoryPathsCacheKey(cwd) or repositoryPaths.gitCommonDir. Lookups in statusDetails and invalidations from withListRefsInvalidation can therefore use different keys for the same directory, and repository-level state (origin URL, refs/remotes/origin/HEAD) is not invalidated across worktrees of the same repository.
  2. Lines 2825-2832 — the PR changes backend behavior (status default branch and origin existence are now cached for 5 minutes and refreshed only through this invalidation hook) without any focused test in apps/server/src/vcs/GitVcsDriverCore.test.ts covering cache reuse or post-mutation invalidation.

Both findings were posted as inline review comments.

Details

Note

Your check run agent prompt is: .macroscope/check-run-agents/effect-service-conventions.md
More information about how Check Run Agents work can be found in our Help Center.

Scope reviewed: the single changed file apps/server/src/vcs/GitVcsDriverCore.ts plus its directly affected call sites (statusDetails, withListRefsInvalidation, initRepoWithListRefsInvalidation, invalidateListRefsSnapshot) and the existing test suite apps/server/src/vcs/GitVcsDriverCore.test.ts.

Conventions verified as satisfied (no findings):

  • Imports are subpath namespaces (import * as Cache from "effect/Cache", import * as Duration from "effect/Duration"); no consolidated named imports from "effect" were introduced.
  • Service definition shape is unchanged; the driver still returns GitVcsDriver.GitVcsDriver.of({...}) and members are typed via GitVcsDriver.GitVcsDriver["Service"][...].
  • No new service-instance parameters, Layer.succeed runtime-backed implementations, ManagedRuntime.make, runPromise, or runPromiseExit were added; the caches are constructed inside make with yield*, so dependencies remain in the Effect environment.
  • No error/predicate model changes; existing GitCommandError construction sites are untouched.
  • No file moves, re-export shims, or removed comments/invariants.

🔍 Agent activity — 1 tool call

💭 Looking at the diff to understand how Cache is being used in GitVcsDriverCore.ts and checking where it's imported from and whether it follows the project's conventions. I'm noticing that the cache lookup functions reference some const arrow functions defined later in the generator, but since the Cache stores lazy lookup functions that only get invoked at retrieval time, the temporal dead zone won't be an issue—by the time Cache.get calls them, those consts will already be initialized. Now I need to check whether the behavior actually changed: the old approach computed the default branch via a symbolic ref lookup and prefix stripping, while the new one calls resolveDefaultBranchName directly. That's a potential behavior difference, so I should look at the relevant code sections to understand what's happening. I need to check how the cache key normalization works across different caches. The existing repositoryPaths cache normalizes the working directory through normalizeRepositoryPathsCacheKey, but the new caches are using the raw cwd as their key directly. Looking at the invalidation point around line 2825 where invalidateListRefsSnapshot is called with cwd, I should verify whether that function resolves gitCommonDir and what cwd value gets passed for the status cache operations. The cache key mismatch between normalized and raw cwd could cause invalidation to miss, which is a correctness bug. But the review scope is specifically about Effect service conventions, not general correctness issues. I'm evaluating whether this violates any stated conventions — the use of Effect.gen in invalidateStatusStaticCaches might not align with simpler patterns like Effect.all or Effect.andThen, though that's not explicitly listed as a convention. The bigger question is whether the behavior change from the new default branch resolution logic and the 5-minute TTL constitute a staleness issue that requires focused test coverage. I'm thinking through which conventions apply here—the caching approach keeps dependencies out of module globals which is good, but there's a potential correctness issue where cache keys use raw cwd strings while the repository paths cache normalizes them, meaning ensureRemote and fetchRemote invalidation calls might pass different string formats than what statusDetails uses, leading to cache misses or stale data. The PR title mentions "stable lookups" and there's precedent in the file for normalizing cache keys, but that's more of a correctness bug than a convention violation. However, the real convention issue is that this PR changes backend behavior—adding five-minute caching for default branch and origin existence—without adding tests, which violates the "Change discipline" convention requiring focused tests when backend behavior changes. I should check if there are existing tests for GitVcsDriver status details that could be updated, and whether the diff shows any test modifications. I should check if the existing tests in GitVcsDriverCore.test.ts have assertions around command counts for statusDetails, since the caching behavior being added might affect those counts and potentially break tests. Let me search for any symbolic-ref related test assertions. I'm looking at the test coverage for statusDetails with the default branch—specifically lines 886-898 where symbolic-ref gets set before calling status. The concern is that caching could interfere if refs change mid-test within the same driver instance. Now I'm weighing whether this PR violates the "focused tests" convention: since statusDetails behavior is changing, I need to determine if focused tests are actually required here. The cache invalidation on mutating operations seems reasonable, but there's a real gap—no new tests cover the cache behavior itself or its invalidation logic. That's a concrete violation under the change discipline rule. I'm also noticing the cache keys aren't normalized while sibling caches are, which could cause invalidation misses if the cwd is spelled differently, though that's more of a correctness issue than a convention violation. There's also the magic number 2_048 used inline instead of a named constant like REPOSITORY_PAT, which is inconsistent with the codebase style. Let me verify that resolveDefaultBranchName is semantically equivalent to the old parseDefaultBranchFromRemoteHeadRef logic—if it is, then caching is the only behavioral change. I also need to check whether the caches actually work in this environment since Cache.makeWith depends on executeGit, which requires ChildProcessSpawner from the context. In Effect, the cache lookup effects should have their requirements satisfied by the construction context. There's also a potential temporal dead zone issue: defaultBranchCache is created at line 1124 but references resolveDefaultBranchName declared later at 1216 as a const. The lookup arrow captures the binding lazily, so it should be fine since Cache.makeWith doesn't invoke immediately. The TypeScript scoping is valid—block-scoped variables used before declaration inside function bodies don't trigger errors. However, the missing tests are a real issue: the Change discipline explicitly requires focused tests when backend behavior changes, and caching the status and origin-existence results for 5 minutes is definitely an observable behavior change. Consumers will see stale values after operations like git remote add performed outside the driver or after initRepo, which doesn't invalidate these caches. Additionally, initRepoWithListRefsInvalidation doesn't invalidate the new caches either, which is an inconsistency worth flagging. worktree-specific cache invalidation might not work properly since the default branch is stored at the repository level, not per-worktree. I need to check how invalidateListRefsSnapshot keys its entries to see if it accounts for the git common directory. The real issue here is that invalidateListRefsSnapshot normalizes using gitCommonDir while the new status cache keys off the raw cwd, creating an inconsistency that breaks cross-worktree invalidation. Looking at the listed conventions though, this doesn't actually violate any of them—not the import rules, service definitions, error handling, or dependency constraints. The only relevant rule is requiring focused tests when backend behavior changes, so I need to decide whether that's enough to fail the check, which defaults to failure anyway. The missing test coverage is legitimate: there's a concrete behavior change with the new five-minute caching and invalidation logic that has zero tests. That's exactly what the convention list explicitly requires. I should also flag the key-normalization bug since it's an observable correctness defect in the invalidation path that the PR introduces—a test would catch it. I'll post two inline comments: one on the cache lines about the unnormalized keys, and another explaining why tests are needed for this behavior change. gestion. I'll skip the diff and just post the comment without a code suggestion since the fix spans multiple sites. For the second comment on line 2829, I'll request a focused test for cache reuse and invalidation behavior, checking that the tests in GitVcsDriverCore.test.ts cover this scenario. Let me verify that statusDetails caching also affects statusDetailsRemote and statusDetailsLocal — they share the core implementation, so the change applies consistently. I'll keep both comments concise.

1. modify_pr — Two findings on the new status caches in apps/server/src/vcs/GitVcsDriverCore.ts: the cache keys are not normalized/repo-scoped the way the sibling caches in this module are, and the new caching behavior lands without any focused test.


Agent Credits: 62 credits