From b1f9e48efb3b8f8cf69bb15de3845f12238aa070 Mon Sep 17 00:00:00 2001 From: Lex Date: Thu, 13 Aug 2026 06:40:37 +0800 Subject: [PATCH] test(memory): stamp the instance store with the already-resolved identity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dev push CI (linux Unit Tests) failed in MEM-PR01-R1-03: the first search returned "unavailable" in isolation while the same file passes locally. Root cause (CI log analysis + code trace): the test's "active" pre-condition depends on the InstanceStore's BOOT-TIME project resolution, which runs in a separate Effect graph (its own :memory: Database) and silently degrades to the shared global identity when a git subprocess fails transiently on a loaded runner (every git failure collapses to "exit 1, empty output" in core git.ts run()). The test body's own resolution milliseconds later returns the real root-commit identity, so the identity assertions pass while memory fails closed against the stale global context. Fix: resolve the identity once in the test body and hand it to the instance store (provideInstance now accepts a full LoadInput; boot skips its own fromDirectory when project+worktree are given). Applied to the three identity-scoped tests (R1-03, R1-23, R1-00 third) that assert active memory. Registered separately (product hardening, out of this PR): identity resolution should not silently degrade to the global identity on transient git errors — discover/rootCommits should retry or propagate instead of collapsing to exit 1. Co-Authored-By: Claude --- packages/opencode/test/fixture/fixture.ts | 6 +++-- .../memory/memory-global-identity.test.ts | 24 ++++++++++++------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/packages/opencode/test/fixture/fixture.ts b/packages/opencode/test/fixture/fixture.ts index f9898ede0d..8d483a904d 100644 --- a/packages/opencode/test/fixture/fixture.ts +++ b/packages/opencode/test/fixture/fixture.ts @@ -162,9 +162,11 @@ export function tmpdirScoped(options?: { } export const provideInstance = - (directory: string) => + (input: string | InstanceStore.LoadInput) => (self: Effect.Effect): Effect.Effect => - InstanceStore.Service.use((store) => store.provide({ directory }, self)) + InstanceStore.Service.use((store) => + store.provide(typeof input === "string" ? { directory: input } : input, self), + ) export const provideInstanceEffect = (directory: string) => diff --git a/packages/opencode/test/memory/memory-global-identity.test.ts b/packages/opencode/test/memory/memory-global-identity.test.ts index 2fa507113d..e62e9fb650 100644 --- a/packages/opencode/test/memory/memory-global-identity.test.ts +++ b/packages/opencode/test/memory/memory-global-identity.test.ts @@ -149,15 +149,21 @@ describe("MEM-PR01-R1-03: memory is inert once the identity row is retired", () () => Effect.gen(function* () { const dir = yield* tmpdirScoped({ git: true }) - yield* provideInstance(dir)( + // Resolve the identity ONCE and hand it to the instance store: the + // boot-time resolution runs in a separate Effect graph (own Database) + // and can transiently degrade to the global identity on loaded CI + // runners (git failures are silently swallowed), which would make the + // stamped context and this body disagree — failing the search closed. + const project = yield* Project.Service + const { project: info } = yield* project.fromDirectory(dir) + expect(info.id).not.toBe(ProjectV2.ID.global) + yield* provideInstance({ directory: dir, worktree: info.worktree, project: info })( Effect.gen(function* () { const project = yield* Project.Service const memory = yield* Memory.Service const configStore = yield* MemoryConfig.Service const { db } = yield* Database.Service - const { project: info } = yield* project.fromDirectory(dir) - expect(info.id).not.toBe(ProjectV2.ID.global) yield* project.setInitialized(info.id) yield* configStore.writeGlobal(baseConfig) @@ -193,14 +199,15 @@ describe("MEM-PR01-R1-23: the runtime admission snapshot covers every registered Effect.gen(function* () { const dir = yield* tmpdirScoped({ git: true }) const sandbox = yield* tmpdirScoped() - yield* provideInstance(dir)( + const project = yield* Project.Service + const { project: info } = yield* project.fromDirectory(dir) + yield* provideInstance({ directory: dir, worktree: info.worktree, project: info })( Effect.gen(function* () { const project = yield* Project.Service const memory = yield* Memory.Service const configStore = yield* MemoryConfig.Service const store = yield* MemoryStore.Service - const { project: info } = yield* project.fromDirectory(dir) yield* project.setInitialized(info.id) yield* project.addSandbox(info.id, sandbox) yield* configStore.writeGlobal(baseConfig) @@ -353,14 +360,15 @@ describe("MEM-PR01-00: memory is inert under the shared global identity", () => () => Effect.gen(function* () { const dir = yield* tmpdirScoped({ git: true }) - yield* provideInstance(dir)( + const project = yield* Project.Service + const { project: info } = yield* project.fromDirectory(dir) + expect(info.id).not.toBe(ProjectV2.ID.global) + yield* provideInstance({ directory: dir, worktree: info.worktree, project: info })( Effect.gen(function* () { const project = yield* Project.Service const memory = yield* Memory.Service const configStore = yield* MemoryConfig.Service - const { project: info } = yield* project.fromDirectory(dir) - expect(info.id).not.toBe(ProjectV2.ID.global) yield* project.setInitialized(info.id) yield* configStore.writeGlobal(baseConfig)