feat(tasks): cite-before-claim gate on completion
Completing a task that declared affected_paths but saw no matching write this
session is now blocked ("marked done without doing it"), escapable with force.
TaskUpdateTool reads the session's writes through a SessionWrites port whose
adapter folds SessionContext (writes = recorded receipt.affectedEntities), and
matches them against the task's affected_paths globs.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -63,6 +63,7 @@ import com.correx.core.toolintent.rules.NetworkHostRule
|
||||
import com.correx.core.toolintent.rules.PathContainmentRule
|
||||
import com.correx.core.toolintent.rules.ReadBeforeWriteRule
|
||||
import com.correx.core.toolintent.rules.ReferenceExistsRule
|
||||
import com.correx.core.toolintent.rules.WriteScopeRule
|
||||
import com.correx.apps.server.freestyle.FreestyleDriver
|
||||
import com.correx.apps.server.inference.summarizeWithInference
|
||||
import com.correx.core.kernel.orchestration.JournalCompactionService
|
||||
@@ -239,6 +240,7 @@ fun main() {
|
||||
taskArtifactResolver,
|
||||
taskSessionResolver,
|
||||
com.correx.apps.server.tasks.EventStoreSessionFactRecorder(eventStore),
|
||||
com.correx.apps.server.tasks.EventStoreSessionWrites(eventStore),
|
||||
)
|
||||
val toolRegistry = InfrastructureModule.createToolRegistry(
|
||||
buildToolConfig(
|
||||
@@ -266,6 +268,7 @@ fun main() {
|
||||
PathContainmentRule(),
|
||||
ReadBeforeWriteRule(),
|
||||
ReferenceExistsRule(),
|
||||
WriteScopeRule(),
|
||||
ManifestContainmentRule(),
|
||||
ExecInterpreterRule(toolsConfig.interpreterExecutables.toSet()),
|
||||
NetworkHostRule(
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.correx.apps.server.tasks
|
||||
|
||||
import com.correx.core.events.stores.EventStore
|
||||
import com.correx.core.events.types.SessionId
|
||||
import com.correx.core.toolintent.SessionContextProjection
|
||||
import com.correx.infrastructure.tools.task.SessionWrites
|
||||
|
||||
/**
|
||||
* Adapter for the [SessionWrites] port: folds a session's events through
|
||||
* [SessionContextProjection] and returns its writes (the recorded receipt.affectedEntities).
|
||||
* Powers the cite-before-claim gate. Replay-safe (reads the log, never live state).
|
||||
*/
|
||||
class EventStoreSessionWrites(private val eventStore: EventStore) : SessionWrites {
|
||||
|
||||
override fun pathsWritten(sessionId: SessionId): Set<String> {
|
||||
val projection = SessionContextProjection(sessionId)
|
||||
return eventStore.read(sessionId)
|
||||
.fold(projection.initial()) { acc, event -> projection.apply(acc, event) }
|
||||
.writes
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user