From d4526ff99a276d741a26ef00dc993331ea9e15db Mon Sep 17 00:00:00 2001 From: Sawyer Cutler Date: Mon, 24 Aug 2026 14:22:37 -0700 Subject: [PATCH] Overhaul Gaasbot prompt Rewrite Gaasbot as risk counsel with blinders-on lane discipline, ship-risk buckets, and no tool-schema restatement or fake caps. Keep package id/path gaasbot. Closes CL-7028 --- src/agent/directors/gaasbot/package.test.ts | 58 +++++++++++++++++++-- src/agent/directors/gaasbot/package.ts | 27 ++++++---- 2 files changed, 71 insertions(+), 14 deletions(-) diff --git a/src/agent/directors/gaasbot/package.test.ts b/src/agent/directors/gaasbot/package.test.ts index 3d4263f1d..d65fffee0 100644 --- a/src/agent/directors/gaasbot/package.test.ts +++ b/src/agent/directors/gaasbot/package.test.ts @@ -2,7 +2,7 @@ import { describe, expect, test } from "bun:test"; import { gaasbotPackage } from "./package.js"; describe("gaasbotPackage", () => { - test("id matches directory", () => { + test("id matches directory (keep gaasbot path; identity is Gaasbot)", () => { expect(gaasbotPackage.id).toBe("gaasbot"); }); @@ -15,6 +15,54 @@ describe("gaasbotPackage", () => { expect(gaasbotPackage.systemPrompt).toMatch(/PRIMARY INTENT/i); }); + test("systemPrompt identity is Gaasbot / GaasbotDirector (risk counsel)", () => { + const p = gaasbotPackage.systemPrompt; + expect(p).toMatch(/GaasbotDirector \(Gaasbot\)/); + expect(p).toMatch(/risk-counsel lane only|risk counsel/i); + expect(p).not.toMatch(/CTO advice leaf/i); + }); + + test("systemPrompt teaches sequencing / ship-risk buckets", () => { + const p = gaasbotPackage.systemPrompt; + expect(p).toMatch(/blocks a release|blocks a ship/i); + expect(p).toMatch(/ship with (an )?explicit note|ships with a note/i); + expect(p).toMatch(/filed for later/i); + expect(p).toMatch(/most likely getting wrong/i); + expect(p).toMatch(/do not ship/i); + expect(p).toMatch(/not a hard gate/i); + }); + + test("systemPrompt is blinders-on risk counsel (no implement / gate / plan / orchestrate)", () => { + const p = gaasbotPackage.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 Greybeard/i); + expect(p).toMatch(/not Counsel/i); + expect(p).toMatch(/not an orchestrator/i); + }); + + test("systemPrompt has DONE GATE for risk ask completeness", () => { + const p = gaasbotPackage.systemPrompt; + expect(p).toContain("DONE GATE"); + expect(p).toMatch(/[Ss]top when/); + expect(p).toContain("Blockers"); + }); + + test("systemPrompt has no tool-schema restatement or fake caps", () => { + const p = gaasbotPackage.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); + expect(p).not.toMatch(/Prefer grep\/search_files/i); + expect(p).not.toMatch(/Shell find\/rg/i); + expect(p).not.toMatch(/Write tools are not mounted/i); + expect(p).not.toMatch(/via run_shell/i); + }); + test("spawn.maySpawn is false", () => { expect(gaasbotPackage.spawn.maySpawn).toBe(false); }); @@ -35,9 +83,13 @@ describe("gaasbotPackage", () => { expect(gaasbotPackage.optionalSkills).toEqual(["philosophy"]); }); - test("primaryIntent and outOfLane match CTO advice lane", () => { - expect(gaasbotPackage.primaryIntent).toMatch(/CTO advice/i); + test("primaryIntent and outOfLane match risk counsel lane", () => { + expect(gaasbotPackage.primaryIntent).toMatch(/[Rr]isk counsel/i); + expect(gaasbotPackage.description).toMatch(/[Rr]isk counsel/i); expect(gaasbotPackage.outOfLane).toContain("blocking merges"); expect(gaasbotPackage.outOfLane).toContain("shipping product code as implementer"); + expect(gaasbotPackage.outOfLane).toContain("replacing greybeard architecture review"); + expect(gaasbotPackage.outOfLane).toContain("replacing plan eng change plans"); + expect(gaasbotPackage.outOfLane).toContain("applying product fixes"); }); }); diff --git a/src/agent/directors/gaasbot/package.ts b/src/agent/directors/gaasbot/package.ts index d7e60157f..e5992b0c1 100644 --- a/src/agent/directors/gaasbot/package.ts +++ b/src/agent/directors/gaasbot/package.ts @@ -2,12 +2,12 @@ import type { DirectorPackage } from "../types.js"; import { REVIEW_TOOLS } from "../tool-sets.js"; /** - * CTO advice leaf (CL-5826). - * Strategic risk/sequencing counsel — not a hard gate, not implement, not greybeard/plan. + * Risk counsel leaf (CL-7028). Package id/path remains `gaasbot`. + * Strategic risk/sequencing advice — not a hard gate, not implement, not Greybeard/Counsel. */ export const gaasbotPackage: DirectorPackage = { id: "gaasbot", - primaryIntent: "CTO advice — risk and sequencing; not a hard gate", + primaryIntent: "Risk counsel — sequencing and ship risk; not a hard gate", outOfLane: [ "blocking merges", "shipping product code as implementer", @@ -15,23 +15,28 @@ export const gaasbotPackage: DirectorPackage = { "replacing plan eng change plans", "applying product fixes", ], - description: "CTO advice leaf — strategic counsel, not a gate", + description: "Risk counsel leaf — strategic ship/sequencing advice, not a gate", optionalSkills: ["philosophy"], tools: { allow: REVIEW_TOOLS }, spawn: { maySpawn: false }, tier: "leaf", modelRole: "plan", - systemPrompt: `You are GaasbotDirector, a specialist in Corbits Code. + systemPrompt: `You are GaasbotDirector (Gaasbot), a specialist in Corbits Code. -PRIMARY INTENT: strategic CTO advice — risk, sequencing, what blocks a release, what ships with a note, what is filed for later. You are counsel, not a hard gate. +PRIMARY INTENT: risk counsel — sequencing, release risk, what blocks a ship, what ships with a note, what is filed for later. You are advice, not a hard gate. -You do not implement product code. You do not replace Greybeard (architecture review) or Plan (eng change plans). You do not block merges by force; you recommend clearly, including "do not ship" when warranted. +You are the risk-counsel lane only — not Builder, not Critic, not Greybeard, not Counsel, not an orchestrator. Do not spawn specialists. Do not implement product code. Do not own architecture sign-off or eng change plans. Do not block merges by force; recommend clearly, including "do not ship" when warranted. -Given findings from others (or the brief): what actually blocks a release? What ships with a note? What is filed? Ask what the team is most likely getting wrong that nobody raised. Prefer hearing "do not ship" early over a late surprise. +Blinders on — stay on the risk ask: +1. From the brief and any findings: what actually blocks a release? +2. What can ship with an explicit note? +3. What is filed for later? +4. Surface what the team is most likely getting wrong that nobody raised. +5. Prefer an early "do not ship" over a late surprise. -Load philosophy when judgment trade-offs matter. Stay advice-only. +DONE GATE: Stop when the brief's risk/sequencing ask is answered OR Blockers are explicit. Do not expand into implementation, architecture gate theater, eng-plan authorship, or fleet orchestration. -OUT OF LANE: implementing, architecture gate ownership, eng plan authorship as PlanDirector, merge-block theater without evidence. +OUT OF LANE: shipping product code, architecture gate ownership (Greybeard), eng plan authorship (Counsel), merge-block theater without evidence, becoming Builder/Critic/orchestrator as primary. -Findings: risk and sequencing advice.`, +Findings: risk and sequencing advice — blockers, ship-with-note, filed-for-later, and the unraised miss.`, };