refactor(acr): ACR Store 1 as a disposable memo, not a durable side-store (#305)

The shipped Store 1 persisted repo-file descriptors in a new SqliteObservationStore
— a second, unsynchronized SQLite writer on the event-log DB (no WAL/busy_timeout,
one shared Connection across coroutines) holding a fact the log already carries. That
violates "the event log is the only source of truth" (inv #1/#8): an Observation is
just FileWrittenEvent.path + postImageHash + describe(bytes).render(), and render is a
pure function of content-addressed CAS bytes.

Replace the whole durable apparatus with an in-process memo (descriptorMemo, keyed on
repoRoot+path+contentHash) on the orchestrator, next to the existing artifactContentCache.
Rebuilt from the log on restart, disposable, no external store. Preserves the perf win
(skip CAS read + regex on repeat describes) with none of the concurrency/lock risk.

Deletes: ObservationStore/InMemoryObservationStore/SqliteObservationStore (+ tests),
InfrastructureModule.createObservationStore, the FileReadTool priming path (which never
hit anyway — it keyed on a workspace-relative path while every consumer looks up the
absolute FileWrittenEvent.path), the FileReadConfig/SessionOrchestrator plumbing, and
five orphaned build.gradle deps.

Store 2 (soft-confidence hints) unchanged — it was correct.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HMbPmZZjcXhR2crU82zZ8S
This commit is contained in:
2026-07-21 18:42:47 +04:00
parent 8806de1628
commit 12775d56da
16 changed files with 9 additions and 267 deletions
@@ -1,6 +1,5 @@
package com.correx.infrastructure.tools
import com.correx.core.context.observation.ObservationStore
import com.correx.core.tools.contract.Tool
import com.correx.infrastructure.tools.filesystem.FileDeleteTool
import com.correx.infrastructure.tools.filesystem.FileEditTool
@@ -40,9 +39,6 @@ data class FileReadConfig(
val enabled: Boolean = false,
val allowedPaths: Set<Path> = emptySet(),
val workingDir: Path? = null,
// ACR Store 1 hot-path priming (docs/plans/2026-07-21-acr-knowledge-accretion.md); both null is a no-op.
val observationStore: ObservationStore? = null,
val repoRoot: String? = null,
)
data class FileWriteConfig(
val enabled: Boolean = false,
@@ -79,8 +75,6 @@ fun ToolConfig.buildTools(): List<Tool> = buildList {
FileReadTool(
allowedPaths = fileRead.allowedPaths,
workingDir = fileRead.workingDir,
observationStore = fileRead.observationStore,
repoRoot = fileRead.repoRoot,
),
)
// list_dir is read-only enumeration; shares the reader's jail + anchor and the same toggle.