|
1 | 1 | import { describe, expect, it } from "bun:test"; |
2 | 2 | import { |
3 | 3 | buildChatSystemPrompt, |
| 4 | + buildGptNarrateBeforeToolsNote, |
4 | 5 | buildGrokLeafAntiThrashNote, |
5 | 6 | buildGuidelines, |
6 | 7 | buildPromptDisciplineBlock, |
@@ -370,3 +371,79 @@ describe("grok finish-bias residual gating (extends existing provider-family tes |
370 | 371 | expect(prompt.toLowerCase()).not.toContain("kimi"); |
371 | 372 | }); |
372 | 373 | }); |
| 374 | + |
| 375 | +describe("gpt narrate-before-tools residual (CL-8310)", () => { |
| 376 | + it("is a 3-line narrate-before-tools note, not manage_tasks ceremony", () => { |
| 377 | + const note = buildGptNarrateBeforeToolsNote(); |
| 378 | + expect(note).toContain("Narrate before tools (GPT worker):"); |
| 379 | + expect(note).toMatch(/before.*tool call.*one short line/is); |
| 380 | + expect(note).toMatch(/no narration between them/i); |
| 381 | + expect(note).toContain("write the report envelope"); |
| 382 | + expect(note.toLowerCase()).not.toContain("manage_tasks"); |
| 383 | + }); |
| 384 | + |
| 385 | + it("appears exactly once on a gpt leaf prompt", () => { |
| 386 | + const prompt = buildSubAgentSystemPrompt(undefined, undefined, undefined, { |
| 387 | + orchestrator: false, |
| 388 | + gptNarrateBeforeTools: true, |
| 389 | + }); |
| 390 | + const note = buildGptNarrateBeforeToolsNote(); |
| 391 | + expect(countOccurrences(prompt, note)).toBe(1); |
| 392 | + expect(prompt.trimEnd().endsWith(note)).toBe(true); |
| 393 | + }); |
| 394 | + |
| 395 | + it("appears exactly once on a gpt primary prompt", () => { |
| 396 | + const prompt = buildChatSystemPrompt( |
| 397 | + undefined, |
| 398 | + undefined, |
| 399 | + undefined, |
| 400 | + [], |
| 401 | + "orchestrator", |
| 402 | + undefined, |
| 403 | + undefined, |
| 404 | + { gptNarrateBeforeTools: true }, |
| 405 | + ); |
| 406 | + const note = buildGptNarrateBeforeToolsNote(); |
| 407 | + expect(countOccurrences(prompt, note)).toBe(1); |
| 408 | + }); |
| 409 | + |
| 410 | + it("is absent by default on both primary and leaf", () => { |
| 411 | + const leaf = buildSubAgentSystemPrompt(undefined, undefined, undefined, { |
| 412 | + orchestrator: false, |
| 413 | + grokAntiThrash: false, |
| 414 | + }); |
| 415 | + const primary = buildChatSystemPrompt( |
| 416 | + undefined, |
| 417 | + undefined, |
| 418 | + undefined, |
| 419 | + [], |
| 420 | + "orchestrator", |
| 421 | + ); |
| 422 | + expect(leaf).not.toContain("Narrate before tools (GPT worker):"); |
| 423 | + expect(primary).not.toContain("Narrate before tools (GPT worker):"); |
| 424 | + }); |
| 425 | + |
| 426 | + it("is absent on grok and claude prompts", () => { |
| 427 | + const grokLeaf = buildSubAgentSystemPrompt(undefined, undefined, undefined, { |
| 428 | + orchestrator: false, |
| 429 | + grokAntiThrash: true, |
| 430 | + }); |
| 431 | + const claudeLeaf = buildSubAgentSystemPrompt(undefined, undefined, undefined, { |
| 432 | + orchestrator: false, |
| 433 | + grokAntiThrash: false, |
| 434 | + }); |
| 435 | + const claudePrimary = buildChatSystemPrompt( |
| 436 | + undefined, |
| 437 | + undefined, |
| 438 | + undefined, |
| 439 | + [], |
| 440 | + "orchestrator", |
| 441 | + ); |
| 442 | + for (const prompt of [grokLeaf, claudeLeaf, claudePrimary]) { |
| 443 | + expect(prompt).not.toContain("Narrate before tools (GPT worker):"); |
| 444 | + expect(prompt).not.toContain("Narrate before tools (GPT"); |
| 445 | + } |
| 446 | + // The grok row keeps its own residual, untouched. |
| 447 | + expect(grokLeaf).toContain("Finish bias (xAI / Grok worker):"); |
| 448 | + }); |
| 449 | +}); |
0 commit comments