From 184599dbc97b3dbdbf737e2b8e7896f86016c6d4 Mon Sep 17 00:00:00 2001 From: Sawyer Cutler Date: Mon, 24 Aug 2026 14:07:00 -0700 Subject: [PATCH] Overhaul Counsel prompt Rewrite the plan package identity as CounselDirector (Counsel) while keeping id/path plan. Teach ordered agent-proof eng plans with blinders-on lane discipline, no ship, and no tool-schema restatement or fake caps. Closes CL-7022 --- src/agent/directors/plan/package.test.ts | 56 ++++++++++++++++++++++-- src/agent/directors/plan/package.ts | 37 ++++++++++++---- 2 files changed, 82 insertions(+), 11 deletions(-) diff --git a/src/agent/directors/plan/package.test.ts b/src/agent/directors/plan/package.test.ts index 5bd548e46..b78fed582 100644 --- a/src/agent/directors/plan/package.test.ts +++ b/src/agent/directors/plan/package.test.ts @@ -2,7 +2,7 @@ import { describe, expect, test } from "bun:test"; import { planPackage } from "./package.js"; describe("planPackage", () => { - test("id matches directory", () => { + test("id matches directory (keep plan path; identity is Counsel)", () => { expect(planPackage.id).toBe("plan"); }); @@ -15,6 +15,53 @@ describe("planPackage", () => { expect(planPackage.systemPrompt).toMatch(/PRIMARY INTENT/i); }); + test("systemPrompt identity is Counsel / CounselDirector (not PlanDirector)", () => { + const p = planPackage.systemPrompt; + expect(p).toMatch(/CounselDirector \(Counsel\)/); + expect(p).toMatch(/plan lane only/i); + expect(p).not.toMatch(/PlanDirector/); + expect(p).not.toMatch(/You are Plan\b/); + }); + + test("systemPrompt teaches ordered eng plans with no ship", () => { + const p = planPackage.systemPrompt; + expect(p).toMatch(/ordered engineering change plans/i); + expect(p).toMatch(/agent-proof plan/i); + expect(p).toMatch(/acceptance criteria/i); + expect(p).toMatch(/Non-goals/i); + expect(p).toMatch(/Ordered steps/i); + expect(p).toMatch(/Do not implement product code/i); + expect(p).toMatch(/Do not ship the change yourself/i); + }); + + test("systemPrompt is blinders-on plan lane (no orchestrate / ship / review-as-primary)", () => { + const p = planPackage.systemPrompt; + expect(p).toMatch(/Blinders on/i); + expect(p).toMatch(/Do not spawn specialists/i); + expect(p).toMatch(/not Builder/i); + expect(p).toMatch(/not Critic/i); + expect(p).toMatch(/not Explorer/i); + expect(p).toMatch(/not an orchestrator/i); + expect(p).toMatch(/Greybeard/i); + }); + + test("systemPrompt has no tool-schema restatement or fake caps", () => { + const p = planPackage.systemPrompt; + expect(p).not.toMatch(/parameters?:/i); + expect(p).not.toMatch(/fan-out/i); + expect(p).not.toMatch(/at most \d+/i); + expect(p).not.toMatch(/turn budget/i); + expect(p).not.toMatch(/scheduler/i); + }); + + test("systemPrompt has DONE GATE for plan completeness", () => { + const p = planPackage.systemPrompt; + expect(p).toContain("DONE GATE"); + expect(p).toContain("success_criteria"); + expect(p).toMatch(/[Ss]top when/); + expect(p).toContain("Blockers"); + }); + test("spawn.maySpawn is false", () => { expect(planPackage.spawn.maySpawn).toBe(false); }); @@ -35,10 +82,13 @@ describe("planPackage", () => { expect(planPackage.optionalSkills).toEqual(["style", "philosophy", "interview"]); }); - test("primaryIntent and outOfLane match plan lane", () => { - expect(planPackage.primaryIntent).toBe("Author eng change plans; do not implement"); + test("primaryIntent and outOfLane match counsel / plan lane", () => { + expect(planPackage.primaryIntent).toBe("Author ordered eng change plans; do not implement"); + expect(planPackage.description).toMatch(/Counsel/i); expect(planPackage.outOfLane).toContain("shipping code"); expect(planPackage.outOfLane).toContain("architecture gate sign-off as Greybeard"); expect(planPackage.outOfLane).toContain("running the fleet"); + expect(planPackage.outOfLane).toContain("pure code review"); + expect(planPackage.outOfLane).toContain("becoming Builder or Critic"); }); }); diff --git a/src/agent/directors/plan/package.ts b/src/agent/directors/plan/package.ts index 9345c65ec..1366adb6a 100644 --- a/src/agent/directors/plan/package.ts +++ b/src/agent/directors/plan/package.ts @@ -1,23 +1,44 @@ import type { DirectorPackage } from "../types.js"; import { REVIEW_TOOLS } from "../tool-sets.js"; +/** + * Counsel leaf (CL-7022). Package id/path remains `plan` until the named-entity rename lands. + * Ordered eng change plans only — no ship, no architecture gate, no fleet. + */ export const planPackage: DirectorPackage = { id: "plan", - primaryIntent: "Author eng change plans; do not implement", - outOfLane: ["shipping code", "architecture gate sign-off as Greybeard", "running the fleet"], - description: "Planning leaf — eng plans only; Greybeard reviews", + primaryIntent: "Author ordered eng change plans; do not implement", + outOfLane: [ + "shipping code", + "architecture gate sign-off as Greybeard", + "running the fleet", + "pure code review", + "becoming Builder or Critic", + ], + description: "Counsel leaf — ordered eng plans only; Greybeard reviews", optionalSkills: ["style", "philosophy", "interview"], tools: { allow: REVIEW_TOOLS }, spawn: { maySpawn: false }, tier: "leaf", modelRole: "plan", - systemPrompt: `You are PlanDirector, a specialist in Corbits Code. + systemPrompt: `You are CounselDirector (Counsel), a specialist in Corbits Code. -PRIMARY INTENT: author concrete engineering change plans. Do not implement product code. Do not act as architecture gate (that is Greybeard). +PRIMARY INTENT: author concrete, ordered engineering change plans. Do not implement product code. Do not act as architecture gate (that is Greybeard). Do not run the fleet. -Plans must be agent-proof: files, acceptance criteria, non-goals, risks, ordered steps. When requirements are fuzzy, note the open questions under Blockers instead of guessing — you cannot ask the operator mid-run. +You are the plan lane only — not Builder, not Critic, not Explorer, not an orchestrator. Blinders on: stay on the plan. Do not spawn specialists. Do not ship the change yourself. Do not review or explore the codebase as your primary job. -OUT OF LANE: shipping the change yourself, pure code review, fleet orchestration. +Author an agent-proof plan: +1. Files / paths to touch +2. Acceptance criteria mapped from the brief (and success_criteria when present) +3. Non-goals +4. Risks and open questions +5. Ordered steps a Builder can execute without guessing -Findings: the plan itself.`, +When requirements are fuzzy, note open questions under Blockers instead of guessing — you cannot ask the operator mid-run. Prefer interview-skill awareness for discovery gaps; do not invent scope. + +DONE GATE: Stop when the plan covers every success_criteria item from the brief OR blockers are explicit. Do not expand into implementation, architecture essays, or review theater after the plan is complete. + +OUT OF LANE: shipping code, architecture gate sign-off, fleet orchestration, pure code review, becoming Builder/Critic/Greybeard/Explorer as primary. + +Findings: the plan itself — ordered steps, paths, acceptance criteria, non-goals, risks.`, };