fix(context,tools): context hygiene + tool ergonomics from freestyle QA
Found while live-QAing freestyle_planning on a 12B local model: - list_dir tool: recursive, .gitignore-aware listing so weak models stop flooding context with `ls -R` over node_modules/build/dist. Wired into the fileRead toggle + advertised to the planner (architect_freestyle). - ContextClassifier: assistantToolCall turns are STRUCTURED, so the token pruner never shreds the model's own tool-call history — that was causing amnesia loops (re-issuing calls it had already made). - Retire instruction-doc LLMLingua pruning (DOC_SOURCE_TYPES emptied): it fused load-bearing procedural text into unparseable soup. The static block stays small by dropping CLAUDE.md at the loader instead. - AgentInstructionsLoader: load only AGENTS.md, not CLAUDE.md — the latter targets the outer assistant and polluted the agent's stage context. - DefaultSessionReducer: WorkflowFailed flips session status to FAILED (was stuck ACTIVE forever, so clients/approval loops never saw a terminal). - ShellTool: run shell command lines (cd/&&/pipes) via `sh -c`; unrunnable program is recoverable instead of an uncaught IOException killing the stage; malformed argv (non-string/collapsed-array) rejected with guidance. - llmlingua sidecar: cap force_tokens to max_force_token (big docs blew the assert and 500'd, so doc pruning silently failed open). Tests added/updated across all of the above.
This commit is contained in:
@@ -8,6 +8,7 @@ import com.correx.core.events.events.StageCompletedEvent
|
||||
import com.correx.core.events.events.StageFailedEvent
|
||||
import com.correx.core.events.events.StoredEvent
|
||||
import com.correx.core.events.events.TransitionExecutedEvent
|
||||
import com.correx.core.events.events.WorkflowFailedEvent
|
||||
|
||||
class DefaultSessionReducer : SessionReducer {
|
||||
|
||||
@@ -22,6 +23,14 @@ class DefaultSessionReducer : SessionReducer {
|
||||
is StageFailedEvent ->
|
||||
SessionStatus.FAILED
|
||||
|
||||
// A failed workflow is terminal for the session: no current workflow recovers after
|
||||
// one fails (freestyle's planning→execution handoff only fires on WorkflowCompleted).
|
||||
// Without this, an exhausted-retry WorkflowFailed left the session ACTIVE forever, so
|
||||
// clients/approval loops never saw a terminal state. WorkflowCompleted is deliberately
|
||||
// NOT mapped here — planning emits its own mid-session, so it isn't session-terminal.
|
||||
is WorkflowFailedEvent ->
|
||||
SessionStatus.FAILED
|
||||
|
||||
is StageCompletedEvent,
|
||||
is TransitionExecutedEvent ->
|
||||
SessionStatus.ACTIVE
|
||||
|
||||
@@ -57,6 +57,19 @@ class DefaultSessionReducerTest {
|
||||
assertNull(initialState.boundProfile)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `WorkflowFailedEvent flips session status to FAILED`() {
|
||||
val event = stored(
|
||||
com.correx.core.events.events.WorkflowFailedEvent(
|
||||
sessionId = sessionId,
|
||||
stageId = com.correx.core.events.types.StageId("define_styling_tokens"),
|
||||
reason = "did not produce declared artifacts",
|
||||
retryExhausted = true,
|
||||
),
|
||||
)
|
||||
assertEquals(SessionStatus.FAILED, reducer.reduce(initialState, event).status)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `unrelated event leaves boundProfile unchanged`() {
|
||||
val state = initialState.copy(
|
||||
|
||||
Reference in New Issue
Block a user