Skip to content

Commit 72efaaa

Browse files
committed
feat(agents): rebuild claude task_guidance block from prompting docs
Rebuild the Claude XML residual end to end from Anthropic's prompting docs while keeping CL-7775's measured shape: rationale first, numbered approach, named output contract, one wrapper, leaf-only tail placement. Every line is positively framed and scope-explicit for Sonnet's literal instruction-following; per-line provenance in the PR body.
1 parent 3a62572 commit 72efaaa

5 files changed

Lines changed: 33 additions & 7 deletions

File tree

‎src/agent/model-family-policy.test.ts‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,10 +124,14 @@ describe("resolveModelFamilyPolicy", () => {
124124
orchestrator: true,
125125
});
126126
expect(orchestrator.promptResidual).toBeUndefined();
127+
// Default-family probe: anthropic/claude-sonnet-4 would hit the claude
128+
// row now, and the gpt row has NOT landed yet (#1135), so openai/gpt-4.1
129+
// is the probe that still resolves to the default family.
127130
const base = resolveModelFamilyPolicy({
128-
providerName: "anthropic",
129-
model: "claude-sonnet-4",
131+
providerName: "openai",
132+
model: "gpt-4.1",
130133
});
134+
expect(base.family).toBe("default");
131135
expect(base.promptResidual).toBeUndefined();
132136
});
133137
});

‎src/agent/model-family-policy.ts‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,9 +157,10 @@ export const GROK_PROMPT_RESIDUAL = [
157157
// verbatim so the prompt carries exactly one copy.
158158
export const CLAUDE_TASK_GUIDANCE_NOTE = [
159159
"<task_guidance>",
160-
"- Follow the dispatch brief exactly; its Success criteria are the done-definition.",
161-
"- When the done-definition is met, stop calling tools and write the structured report envelope.",
162-
"- Batch independent tool calls into a single turn; never re-read a file you already read this session.",
160+
"Autonomous coding turn: finish the work in this turn on your best judgment.",
161+
"1. Follow the dispatch brief exactly; its Success criteria are the done-definition.",
162+
"2. Batch independent tool calls into a single turn; work from files already read this session.",
163+
"3. Finish the task when the done-definition is met: prefer the structured report envelope over another tool call.",
163164
"</task_guidance>",
164165
].join("\n");
165166

‎src/agent/prompt-sizes.ts‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import {
1818
MAX_AGENTS_MD_BYTES,
1919
} from "./context-extensions.js";
2020
import { shouldApplyGrokAntiThrash } from "../subagent/provider-family.js";
21-
import { resolveModelFamilyPolicy } from "./model-family-policy.js";
2221
import { isCodexProviderName } from "../config/codex-providers.js";
2322
import { shellCollectDefinition } from "./background-shell-tool.js";
2423
import {

‎src/agent/prompts.test.ts‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,4 +431,24 @@ describe("claude XML task_guidance residual (provider residual, not a prompt for
431431
expect(countOccurrences(note, "</task_guidance>")).toBe(1);
432432
expect(note).not.toMatch(/<system_prompt>|<prompt>|<identity>/);
433433
});
434+
435+
it("keeps the measured CL-7775 shape: rationale first, numbered approach, named output contract, positively framed", () => {
436+
const lines = buildClaudeTaskGuidanceNote().split("\n");
437+
// Rationale first: the lead line frames the turn before any directive.
438+
expect(lines[1]).toMatch(/^Autonomous coding turn:/);
439+
// Numbered approach, not bullets.
440+
expect(lines.slice(2, 5).map((l) => l.split(".")[0])).toEqual([
441+
"1",
442+
"2",
443+
"3",
444+
]);
445+
// Named output contract.
446+
expect(buildClaudeTaskGuidanceNote()).toContain(
447+
"structured report envelope",
448+
);
449+
// Positive framing: no negative imperatives.
450+
expect(buildClaudeTaskGuidanceNote()).not.toMatch(
451+
/\b(do not|don't|never|stop calling)\b/i,
452+
);
453+
});
434454
});

‎src/agent/prompts.ts‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,9 @@ export function buildGrokLeafAntiThrashNote(): string {
526526
// Single XML residual for Claude-family workers: a prose residual did
527527
// nothing, but one <task_guidance> block cut Sonnet tokens. One block only —
528528
// never a full-prompt XML renderer, never applied outside the claude family.
529+
// Rebuilt end to end from Anthropic's prompting docs (CL-8309): rationale
530+
// first, numbered approach, named output contract; every line is positively
531+
// framed and scope-explicit for Sonnet's literal instruction-following.
529532
// Single source of truth is the CLAUDE_TASK_GUIDANCE_NOTE block in
530533
// model-family-policy.ts (policy owns data); this returns that block verbatim
531534
// so the prompt carries one claude residual with no line twice.
@@ -578,4 +581,3 @@ export function buildSubAgentSystemPrompt(
578581
}
579582
return joinSections(sections);
580583
}
581-
}

0 commit comments

Comments
 (0)