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:
+1
-3
@@ -7,7 +7,6 @@ import com.correx.core.inference.Tokenizer
|
||||
import com.correx.core.journal.DefaultDecisionJournalRepository
|
||||
import com.correx.core.artifacts.kind.ArtifactKindRegistry
|
||||
import com.correx.core.artifactstore.ArtifactStore
|
||||
import com.correx.core.context.observation.ObservationStore
|
||||
import com.correx.core.events.events.ApprovalDecisionResolvedEvent
|
||||
import com.correx.core.events.events.ArtifactContentStoredEvent
|
||||
import com.correx.core.events.events.ClarificationAnswer
|
||||
@@ -112,8 +111,7 @@ class DefaultSessionOrchestrator(
|
||||
readyTaskCounter: ReadyTaskCounter? = null,
|
||||
taskClaimCoordinator: TaskClaimCoordinator? = null,
|
||||
tuning: OrchestrationTuning = OrchestrationTuning(),
|
||||
observationStore: ObservationStore? = null,
|
||||
) : SessionOrchestrator(repositories, engines, artifactStore, decisionJournalRepository, artifactKindRegistry = artifactKindRegistry, repoKnowledgeRetriever = repoKnowledgeRetriever, readyTaskCounter = readyTaskCounter, taskClaimCoordinator = taskClaimCoordinator, tuning = tuning, observationStore = observationStore), ApprovalGateway {
|
||||
) : SessionOrchestrator(repositories, engines, artifactStore, decisionJournalRepository, artifactKindRegistry = artifactKindRegistry, repoKnowledgeRetriever = repoKnowledgeRetriever, readyTaskCounter = readyTaskCounter, taskClaimCoordinator = taskClaimCoordinator, tuning = tuning), ApprovalGateway {
|
||||
override val tokenizer: Tokenizer? = tokenizer
|
||||
override val cancellations: ConcurrentHashMap<SessionId, AtomicBoolean> =
|
||||
ConcurrentHashMap<SessionId, AtomicBoolean>()
|
||||
|
||||
+5
-2
@@ -8,7 +8,6 @@ import com.correx.core.artifacts.kind.KindInference
|
||||
import com.correx.core.artifactstore.ArtifactStore
|
||||
import com.correx.core.context.builder.ContextPackBuilder
|
||||
import com.correx.core.context.model.ContextPack
|
||||
import com.correx.core.context.observation.ObservationStore
|
||||
import com.correx.core.events.events.ClarificationAnswer
|
||||
import com.correx.core.events.events.ClarificationAnsweredEvent
|
||||
import com.correx.core.events.events.ClarificationRequestedEvent
|
||||
@@ -203,7 +202,6 @@ abstract class SessionOrchestrator(
|
||||
internal val readyTaskCounter: ReadyTaskCounter? = null,
|
||||
internal val taskClaimCoordinator: TaskClaimCoordinator? = null,
|
||||
internal val tuning: OrchestrationTuning = OrchestrationTuning(),
|
||||
internal val observationStore: ObservationStore? = null,
|
||||
) {
|
||||
internal val log = LoggerFactory.getLogger(this::class.java)
|
||||
internal val eventStore: EventStore = repositories.eventStore
|
||||
@@ -250,6 +248,11 @@ abstract class SessionOrchestrator(
|
||||
*/
|
||||
internal val artifactContentCache: ConcurrentHashMap<String, String> = ConcurrentHashMap()
|
||||
|
||||
// ACR Store 1: in-process memo of describe().render(), keyed on (repoRoot, path, contentHash).
|
||||
// Disposable — the source of truth is FileWrittenEvent + CAS; this only skips recomputing a pure
|
||||
// function of content-addressed bytes. Empty string = a computed "no descriptor" (negative cache).
|
||||
internal val descriptorMemo: ConcurrentHashMap<String, String> = ConcurrentHashMap()
|
||||
|
||||
/** Drops a terminated session's cached artifact contents (the heaviest per-session state — full
|
||||
* file/JSON payloads). Safe: rehydrateArtifactContentCache rebuilds it from durable events if the
|
||||
* session is ever resumed. Called on WorkflowCompleted/WorkflowFailed. */
|
||||
|
||||
BIN
Binary file not shown.
Reference in New Issue
Block a user