feat(router): replace bare refusal with triage directive in system prompt

This commit is contained in:
2026-06-11 11:15:59 +04:00
parent a32e9acac4
commit 72e7002623
2 changed files with 23 additions and 5 deletions
@@ -55,10 +55,18 @@ class DefaultRouterContextBuilder(
operator understand and steer what the engine is doing.
Ground every statement in the workflow state and conversation context you are given.
Never invent stages, tool results, file contents, or status you have not been shown;
if something is not in context, say you do not have it. Be concise and direct — plain
sentences, no filler. When the operator is steering an approval, help them state
clearly what they want changed.
Never invent stages, tool results, file contents, or status you have not been shown.
Be concise and direct — plain sentences, no filler. When the operator is steering
an approval, help them state clearly what they want changed.
When the operator's request is not something you can answer or steer directly:
do not simply refuse. Triage instead, citing only what appears in your context:
(a) if "## Available workflows" is present, suggest the best-fitting workflow and
say what it would accomplish for this request;
(b) if "## Project profile" is present and the request relates to the project,
point at the relevant conventions or commands;
(c) if recalled cross-session memory shows similar prior work, say so and reference it;
(d) otherwise offer to think the problem through together in chat.
""".trimIndent()
private val NARRATION_SYSTEM_PROMPT =
@@ -130,7 +130,8 @@ class RouterContextBuilderTest {
),
)
// Budget allows L0 + 2 long conversation turns; oldest 2 turns are dropped
val pack = runBlocking { builderWide.build(state, TokenBudget(limit = 500)) }
// Budget increased from 500 to 600 to account for larger system prompt with triage directive
val pack = runBlocking { builderWide.build(state, TokenBudget(limit = 600)) }
val l1Entries = pack.layers[ContextLayer.L1] ?: emptyList()
// Only the last 2 turns (oldest-first drop) should remain
assertEquals(2, l1Entries.size)
@@ -841,6 +842,15 @@ class RouterContextBuilderTest {
assertNull((pack.layers[ContextLayer.L0] ?: emptyList()).find { it.sourceType == "projectProfile" })
}
@Test
fun `system prompt contains triage directive not bare refusal`() {
val pack = buildPack(RouterState(), TokenBudget(limit = 10000))
val content = pack.layers[ContextLayer.L0]?.find { it.sourceType == "systemPrompt" }!!.content
assertFalse(content.contains("if something is not in context, say you do not have it"))
assertTrue(content.contains("Available workflows", ignoreCase = true))
assertTrue(content.contains("project profile", ignoreCase = true))
}
@Test
fun `truncatedLayers populated with affected layers when drops occur`() {
val longText = "x".repeat(800)