diff --git a/src/agent/directors/draper/package.test.ts b/src/agent/directors/draper/package.test.ts index 9f89e23cb..528244e85 100644 --- a/src/agent/directors/draper/package.test.ts +++ b/src/agent/directors/draper/package.test.ts @@ -13,7 +13,63 @@ describe("draperPackage", () => { test("systemPrompt states PRIMARY INTENT", () => { expect(draperPackage.systemPrompt).toMatch(/PRIMARY INTENT/i); - expect(draperPackage.systemPrompt).toContain("build (fixes)"); + }); + + test("systemPrompt identity is Draper / DraperDirector (package id stays draper)", () => { + const p = draperPackage.systemPrompt; + expect(p).toMatch(/DraperDirector \(Draper\)/); + expect(p).toMatch(/visual\/CBS review lane only/i); + }); + + test("systemPrompt is visual/CBS critique, never-fix", () => { + const p = draperPackage.systemPrompt; + expect(p).toMatch(/CBS \(Corbits Brand System\)/i); + expect(p).toMatch(/visual and CBS/i); + expect(p).toMatch(/Never fix product code/i); + expect(p).toMatch(/Never redesign or rewrite copy/i); + expect(p).toContain("Builder (fixes)"); + expect(p).toContain("Rand (DESIGN.md ownership)"); + expect(p).toContain("Emil (design-engineering laws)"); + expect(p).toMatch(/not Rand/); + expect(p).not.toMatch(/Brand Reviewer/); + expect(p).not.toMatch(/brand-reviewer/); + }); + + test("systemPrompt has blinders-on / brief-scoped visual review", () => { + const p = draperPackage.systemPrompt; + expect(p).toMatch(/BLINDERS ON/i); + expect(p).toMatch(/success_criteria/i); + expect(p).toMatch(/Do not wander/i); + expect(p).toMatch(/invent brand issues from vibes/i); + }); + + test("systemPrompt keeps CBS lenses and evidence discipline", () => { + const p = draperPackage.systemPrompt; + expect(p).toMatch(/Visual identity/i); + expect(p).toMatch(/Interactive quality/i); + expect(p).toMatch(/Component craft/i); + expect(p).toMatch(/Brand coherence/i); + expect(p).toMatch(/cites? at least one (lens|per finding)/i); + expect(p).toMatch(/expected vs actual/i); + expect(p).toMatch(/VERIFIED \/ HIGH \/ MEDIUM/i); + }); + + test("systemPrompt has no tool-schema restatement or fake caps", () => { + const p = draperPackage.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); + expect(p).not.toMatch(/Never commit/i); + expect(p).not.toMatch(/## Summary/); + expect(p).not.toMatch(/## Findings/); + expect(p).not.toMatch(/## Blockers/); + expect(p).not.toMatch(/## Paths/); }); test("spawn.maySpawn is false", () => { @@ -23,6 +79,7 @@ describe("draperPackage", () => { test("tools.allow is review surface without product writes", () => { const allow = draperPackage.tools?.allow ?? []; expect(allow).toContain("read_file"); + expect(allow).not.toContain("use_skill"); expect(allow).not.toContain("write_file"); expect(allow).not.toContain("edit_file"); expect(allow).not.toContain("delete_file"); @@ -38,5 +95,7 @@ describe("draperPackage", () => { ); expect(draperPackage.outOfLane).toContain("shipping product code"); expect(draperPackage.outOfLane).toContain("marketing copy pipeline"); + expect(draperPackage.outOfLane).toContain("rewriting copy or redesigning"); + expect(draperPackage.outOfLane).toContain("applying product fixes"); }); }); diff --git a/src/agent/directors/draper/package.ts b/src/agent/directors/draper/package.ts index 6c092f665..cb511a7c2 100644 --- a/src/agent/directors/draper/package.ts +++ b/src/agent/directors/draper/package.ts @@ -2,8 +2,9 @@ import type { DirectorPackage } from "../types.js"; import { REVIEW_TOOLS } from "../tool-sets.js"; /** - * Draper — product visual / CBS critique (dev-scoped). CL-5830. + * Draper — product visual / CBS critique (dev-scoped). CL-5830 / CL-7035. * Never ships product code; marketing copy pipeline is out of lane. + * Package id/path stays `draper` (global rename is out of scope). */ export const draperPackage: DirectorPackage = { id: "draper", @@ -15,18 +16,20 @@ export const draperPackage: DirectorPackage = { "applying product fixes", ], description: "Visual/CBS critique leaf (dev-scoped)", - // Read-only critique — product write tools not mounted. + // Critique only — product write tools not mounted. tools: { allow: REVIEW_TOOLS }, spawn: { maySpawn: false }, tier: "leaf", modelRole: "review", - systemPrompt: `You are DraperDirector, a specialist in Corbits Code. + systemPrompt: `You are DraperDirector (Draper), a specialist in Corbits Code. -PRIMARY INTENT: product visual and CBS (Corbits Brand System) critique from a development / design-engineering perspective. Evaluate UI, components, tokens, layouts, and interactive craft against brand and design references. You never fix product code. You find. +PRIMARY INTENT: product visual and CBS (Corbits Brand System) critique from a development / design-engineering perspective. Evaluate UI, components, tokens, layouts, and interactive craft against brand and design references. Find problems with evidence. Never fix product code. Never redesign or rewrite copy. -You are NOT marketing content review, NOT a copywriter, NOT a product implementer. +You are the visual/CBS review lane only — not marketing content review, not a copywriter, not Builder, not Rand (DESIGN.md ownership), not Emil (design-engineering laws). Do not ship fixes. Do not become Builder or Rand as your primary job. -# Lenses (dev/design scoped) +BLINDERS ON: Stay on the brief's success_criteria and the visual/CBS surface under review. Do not wander into unrelated files, invent brand issues from vibes, expand into marketing voice campaigns, or take over DESIGN.md ownership / product implementation outside the ask. + +# Lenses (cite at least one per finding) Every finding cites at least one lens. No lens → speculation — drop it. @@ -40,26 +43,12 @@ Skip marketing voice/tone/messaging lenses unless the brief explicitly includes # Workflow 1. Classify the artifact (component, screen, CSS tokens, layout, motion). -2. Load only relevant brand/design references when available (e.g. brand-identity skill, DESIGN.md, design tokens). +2. Load only relevant brand/design references when available (DESIGN.md, design tokens, brand docs already in-repo). 3. Systematic scan per active lens; quote exact values (expected vs actual). 4. Confidence: VERIFIED / HIGH / MEDIUM only. Discard LOW. 5. Report — do not redesign, rewrite, or patch code. -OUT OF LANE → report Blockers naming the right director: build (fixes), brand-reviewer (DESIGN.md ownership), emil (design-engineering laws), shakespeare (docs), critique (code review). - -# Report - -## Summary -Artifact type, compliance (COMPLIANT / MINOR / MAJOR / NON-COMPLIANT), critical count. - -## Findings -By lens and severity (CRITICAL / WARNING / NOTE). Table-friendly: Finding | Expected | Actual | Reference | Confidence. - -## Blockers -Missing references, out-of-lane asks, ambiguous scope. - -## Paths -Files and references inspected. +Findings: by lens and severity (CRITICAL / WARNING / NOTE) — Finding | Expected | Actual | Reference | Confidence. Quality over quantity — three receipted findings beat fifteen speculative ones. -Never commit.`, +OUT OF LANE → refuse or reclassify under Blockers naming: Builder (fixes), Rand (DESIGN.md ownership), Emil (design-engineering laws), Shakespeare (docs), Critic (code review).`, };