refactor: decomposition WIP (orchestrator/server/execution-plan)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DhFXmKe4WisSSPf9LrmmTg
This commit is contained in:
+1
@@ -24,6 +24,7 @@ class FileSystemContractEvaluator : ContractAssertionEvaluator {
|
||||
|
||||
// allowComments/allowTrailingComma make tsconfig.json (JSONC — comments + trailing commas are
|
||||
// legal and tsc/Vite parse them) pass valid_json instead of false-failing a valid config file.
|
||||
@OptIn(kotlinx.serialization.ExperimentalSerializationApi::class)
|
||||
private val json = Json {
|
||||
ignoreUnknownKeys = true
|
||||
isLenient = true
|
||||
|
||||
+40
-4
@@ -16,6 +16,7 @@ import com.correx.core.events.events.RepoMapComputedEvent
|
||||
import com.correx.core.events.events.OrchestrationPausedEvent
|
||||
import com.correx.core.events.events.OrchestrationResumedEvent
|
||||
import com.correx.core.events.events.ExecutionPlanLockedEvent
|
||||
import com.correx.core.events.events.InitialIntentEvent
|
||||
import com.correx.core.events.events.SteeringNoteAddedEvent
|
||||
import com.correx.core.events.types.ArtifactId
|
||||
import com.correx.core.events.types.ClarificationRequestId
|
||||
@@ -120,8 +121,43 @@ internal suspend fun SessionOrchestrator.buildSteeringNoteEntries(sessionId: Ses
|
||||
}
|
||||
|
||||
/**
|
||||
* Injects the operator's answers to a stage's open questions as an L2 USER entry, so the stage
|
||||
* sees its own questions resolved on the clarification re-run. Correlates each answer's
|
||||
* Injects the initial user intent (the freeform request that started the run) as a pinned L0
|
||||
* SYSTEM entry present in EVERY stage's context (architecture-conformance, 2026-07-14). The intent
|
||||
* is the single most load-bearing constraint of a run, yet it previously reached normal stages only
|
||||
* as a repo-map retrieval seed (repoKnowledgeQuery) or, on the rare Tier-2 recovery path, the
|
||||
* arbiter ticket — so an implementer could drift from the goal with the goal itself absent from its
|
||||
* authoritative context. Standing at L0/SYSTEM it is weighted as an instruction and never dropped
|
||||
* under budget. Absent for fixed-task workflows (no InitialIntentEvent) → empty.
|
||||
*/
|
||||
|
||||
internal suspend fun SessionOrchestrator.buildIntentEntry(sessionId: SessionId): List<ContextEntry> {
|
||||
val intent = initialIntent(sessionId)?.takeIf { it.isNotBlank() } ?: return emptyList()
|
||||
val content = "## Authoritative intent\nThe operator's request that started this run. Everything " +
|
||||
"you produce must serve it; do not drift from it or expand its scope:\n$intent"
|
||||
return listOf(
|
||||
ContextEntry(
|
||||
id = ContextEntryId(UUID.randomUUID().toString()),
|
||||
layer = ContextLayer.L0,
|
||||
content = content,
|
||||
sourceType = "initialIntent",
|
||||
sourceId = sessionId.value,
|
||||
tokenEstimate = estimateTokens(content),
|
||||
role = EntryRole.SYSTEM,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
/** The freeform request that started the run, or null for a fixed-task workflow. */
|
||||
internal fun SessionOrchestrator.initialIntent(sessionId: SessionId): String? =
|
||||
eventStore.read(sessionId)
|
||||
.mapNotNull { it.payload as? InitialIntentEvent }
|
||||
.firstOrNull()?.intent?.trim()
|
||||
|
||||
/**
|
||||
* Injects the operator's answers to a stage's open questions as a pinned L0 SYSTEM entry, so the
|
||||
* stage sees its own questions resolved on the clarification re-run. The prompt calls these answers
|
||||
* "authoritative", so they are placed as authoritative standing instructions (L0/SYSTEM), not a
|
||||
* droppable L2 USER turn — matching the mechanics to the stated authority. Correlates each answer's
|
||||
* questionId back to the prompt recorded on the [ClarificationRequestedEvent].
|
||||
*/
|
||||
|
||||
@@ -141,12 +177,12 @@ internal suspend fun SessionOrchestrator.buildClarificationAnswerEntries(session
|
||||
return listOf(
|
||||
ContextEntry(
|
||||
id = ContextEntryId(UUID.randomUUID().toString()),
|
||||
layer = ContextLayer.L2,
|
||||
layer = ContextLayer.L0,
|
||||
content = content,
|
||||
sourceType = "clarificationAnswer",
|
||||
sourceId = sessionId.value,
|
||||
tokenEstimate = estimateTokens(content),
|
||||
role = EntryRole.USER,
|
||||
role = EntryRole.SYSTEM,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
+2
-1
@@ -144,6 +144,7 @@ internal suspend fun SessionOrchestrator.executeStage(
|
||||
?: ResponseFormat.Text
|
||||
|
||||
val schemaEntries = buildSchemaEntries(responseFormat, stageId)
|
||||
val intentEntries = buildIntentEntry(sessionId)
|
||||
val steeringEntries = buildSteeringNoteEntries(sessionId)
|
||||
val clarificationEntries = buildClarificationAnswerEntries(sessionId)
|
||||
|
||||
@@ -238,7 +239,7 @@ internal suspend fun SessionOrchestrator.executeStage(
|
||||
?.let { buildRemainingDeltaEntry(contractFailureItems(it)) }
|
||||
?.let { listOf(it) } ?: emptyList()
|
||||
var accumulatedEntries = stampBuckets(
|
||||
systemPrompt + profileEntries + projectProfileEntries + agentInstructionsEntries +
|
||||
systemPrompt + intentEntries + profileEntries + projectProfileEntries + agentInstructionsEntries +
|
||||
journalEntries + repoMapEntries + claimedTaskEntries +
|
||||
needsEntries + schemaEntries + vocabularyEntries + promptEntries + steeringEntries +
|
||||
clarificationEntries + retryFeedbackEntries + recoveryTicketEntries + remainingDeltaEntries,
|
||||
|
||||
+16
-5
@@ -190,11 +190,22 @@ internal suspend fun SessionOrchestrator.runReviewGate(
|
||||
val files = stageWrittenPaths(sessionId, stageId)
|
||||
if (files.isEmpty()) return StageExecutionResult.Success(emptyList())
|
||||
|
||||
val objective = stageConfig.needs
|
||||
.mapNotNull { artifactContentCache["${sessionId.value}:${it.value}"] }
|
||||
.joinToString("\n\n")
|
||||
.ifBlank { "Stage '${stageId.value}' produced the files below; review them for defects." }
|
||||
.take(REVIEW_OBJECTIVE_CAP)
|
||||
// Goal-conformance framing (architecture-conformance 2026-07-14): lead the reviewer with the
|
||||
// authoritative intent and the stage's declared scope so it can judge whether the files serve
|
||||
// the goal (and stay within scope), not just whether they are internally defect-free — the
|
||||
// deterministic gates already cover mechanical correctness. Absent intent/scope degrade to the
|
||||
// prior upstream-artifact objective.
|
||||
val intentHeader = initialIntent(sessionId)?.takeIf { it.isNotBlank() }
|
||||
?.let { "## Authoritative intent (the goal these files must serve)\n$it\n\n" } ?: ""
|
||||
val scopeHeader = stageConfig.touches.takeIf { it.isNotEmpty() }
|
||||
?.let { "## This stage's declared scope\n${it.joinToString(", ")}\n\n" } ?: ""
|
||||
val objective = (
|
||||
intentHeader + scopeHeader +
|
||||
stageConfig.needs
|
||||
.mapNotNull { artifactContentCache["${sessionId.value}:${it.value}"] }
|
||||
.joinToString("\n\n")
|
||||
.ifBlank { "Stage '${stageId.value}' produced the files below; review them for defects." }
|
||||
).take(REVIEW_OBJECTIVE_CAP)
|
||||
|
||||
val outcome = reviewer.review(sessionId, stageId, workspaceRoot, files, objective)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user