feat: plane-2 tool-call intent validation (path containment slice)
Implements the full vertical slice for invariant #9 tool-call assessment: - core:toolintent — new module with ToolCallRule seam, ToolCallAssessor, WorldProbe/FileSystemWorldProbe, WorkspacePolicy, PathContainmentRule, and RiskMapping (assessment → RiskSummary / AssessedIssue) - core:tools — ToolCallAssessmentRecord + ToolInvocationRecord.assessment field; DefaultToolReducer handles ToolCallAssessedEvent (replay proof) - core:config — ToolsConfig gains workspaceRoot + privilegedLocations; ConfigLoader parses both; DEFAULT_PRIVILEGED_LOCATIONS built-in - core:kernel — OrchestratorEngines gains toolCallAssessor/workspacePolicy/ worldProbe fields; SessionOrchestrator.dispatchToolCalls runs runPlane2Assessment before the tier gate: BLOCK → hard-reject without executing; PROMPT_USER → elevates tier into approval path with plane2Risk in the ApprovalRequestedEvent - apps/server — constructs PathContainmentRule + ToolCallAssessor + WorkspacePolicy from config and wires them into OrchestratorEngines Assessment is recorded as ToolCallAssessedEvent (environment observed once, facts stored, replay reads events — invariant #9). Assessor and WorldProbe are only invoked on the live orchestrator path, never in replay.
This commit is contained in:
@@ -37,6 +37,7 @@ dependencies {
|
||||
implementation project(':infrastructure:inference:commons')
|
||||
implementation project(':core:router')
|
||||
implementation project(':core:tools')
|
||||
implementation project(':core:toolintent')
|
||||
implementation project(':infrastructure:tools')
|
||||
implementation project(':infrastructure:tools:filesystem')
|
||||
|
||||
|
||||
@@ -38,6 +38,9 @@ import com.correx.core.validation.pipeline.ValidationPipeline
|
||||
import com.correx.core.validation.semantic.SemanticValidator
|
||||
import com.correx.core.validation.semantic.rules.CycleExitRule
|
||||
import com.correx.core.validation.semantic.rules.MissingToolRule
|
||||
import com.correx.core.toolintent.ToolCallAssessor
|
||||
import com.correx.core.toolintent.WorkspacePolicy
|
||||
import com.correx.core.toolintent.rules.PathContainmentRule
|
||||
import com.correx.infrastructure.InfrastructureModule
|
||||
import com.correx.infrastructure.artifactscas.DefaultMaterializingArtifactWriter
|
||||
import com.correx.infrastructure.inference.DefaultProviderRegistry
|
||||
@@ -104,6 +107,14 @@ fun main() {
|
||||
|
||||
logToolInfo(sandboxRoot, workingDir, shellAllowedExecutables, toolRegistry)
|
||||
|
||||
val workspaceRoot = System.getenv("CORREX_WORKSPACE_ROOT")
|
||||
?.let { Path.of(it) }
|
||||
?: toolsConfig.workspaceRoot.takeIf { it.isNotEmpty() }?.let { Path.of(it) }
|
||||
?: workingDir
|
||||
val privilegedLocations = toolsConfig.privilegedLocations.map { Path.of(it) }
|
||||
val workspacePolicy = WorkspacePolicy(workspaceRoot, privilegedLocations)
|
||||
val toolCallAssessor = ToolCallAssessor(rules = listOf(PathContainmentRule()))
|
||||
|
||||
val inferenceRouter = DefaultInferenceRouter(infraRegistry, FirstAvailableRoutingStrategy())
|
||||
val engines = OrchestratorEngines(
|
||||
transitionResolver = DefaultTransitionResolver { condition, ctx -> condition.evaluate(ctx) },
|
||||
@@ -125,6 +136,8 @@ fun main() {
|
||||
promptResolver = { path -> InfrastructureModule.createPromptLoader().load(path) },
|
||||
toolRegistry = toolRegistry,
|
||||
toolExecutor = toolExecutor,
|
||||
toolCallAssessor = toolCallAssessor,
|
||||
workspacePolicy = workspacePolicy,
|
||||
)
|
||||
val orchestrator = DefaultSessionOrchestrator(
|
||||
repositories = repositories,
|
||||
|
||||
Reference in New Issue
Block a user