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:
@@ -5,12 +5,17 @@ import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
|
||||
/**
|
||||
* Discovers standing agent instructions (`CLAUDE.md`, `AGENTS.md`) at the bound workspace
|
||||
* root only — no parent walk, no nested lookup. Mirrors [ProjectProfileLoader]: the loaded
|
||||
* snapshot is bound as an event so replay reads the recorded fact, never the live file.
|
||||
* Discovers standing agent instructions (`AGENTS.md`) at the bound workspace root only — no
|
||||
* parent walk, no nested lookup. Mirrors [ProjectProfileLoader]: the loaded snapshot is bound
|
||||
* as an event so replay reads the recorded fact, never the live file.
|
||||
*
|
||||
* CLAUDE.md is deliberately excluded: it targets the outer assistant (agent-dispatch / model-
|
||||
* selection guidance) and is noise to an in-workflow execution agent — injecting it bloated and
|
||||
* polluted the stage context. AGENTS.md holds the correx-agent operating contract (the numbered
|
||||
* how-to-finish-a-stage steps), which is what the agent actually needs.
|
||||
*/
|
||||
object AgentInstructionsLoader {
|
||||
private val FILE_NAMES = listOf("CLAUDE.md", "AGENTS.md")
|
||||
private val FILE_NAMES = listOf("AGENTS.md")
|
||||
|
||||
fun load(workspaceRoot: String): AgentInstructions {
|
||||
val sections = mutableListOf<String>()
|
||||
|
||||
@@ -11,17 +11,18 @@ import java.nio.file.Path
|
||||
class AgentInstructionsLoaderTest {
|
||||
|
||||
@Test
|
||||
fun `both files present yields both sections and sources`(@TempDir root: Path) {
|
||||
fun `AGENTS is loaded and CLAUDE is ignored`(@TempDir root: Path) {
|
||||
// CLAUDE.md is deliberately not an agent-instruction source: it targets the outer assistant
|
||||
// and polluted the stage context. Only AGENTS.md (the agent operating contract) is loaded.
|
||||
Files.writeString(root.resolve("CLAUDE.md"), "Claude rules")
|
||||
Files.writeString(root.resolve("AGENTS.md"), "Agents rules")
|
||||
|
||||
val loaded = AgentInstructionsLoader.load(root.toString())
|
||||
|
||||
assertEquals(listOf("CLAUDE.md", "AGENTS.md"), loaded.sources)
|
||||
assertTrue(loaded.content.contains("# CLAUDE.md"), "content: ${loaded.content}")
|
||||
assertTrue(loaded.content.contains("Claude rules"), "content: ${loaded.content}")
|
||||
assertEquals(listOf("AGENTS.md"), loaded.sources)
|
||||
assertTrue(loaded.content.contains("# AGENTS.md"), "content: ${loaded.content}")
|
||||
assertTrue(loaded.content.contains("Agents rules"), "content: ${loaded.content}")
|
||||
assertFalse(loaded.content.contains("Claude rules"), "content: ${loaded.content}")
|
||||
assertFalse(loaded.isEmpty())
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user