From f66a448e4a89329fe3b26c9d656f6bb100b5fed4 Mon Sep 17 00:00:00 2001 From: Sawyer Cutler Date: Sat, 12 Sep 2026 12:11:08 -0700 Subject: [PATCH] Restore Draper full brand and design critique layer --- src/agent/directors/draper/package.test.ts | 119 +++++++++++++++------ src/agent/directors/draper/package.ts | 97 ++++++++++++----- src/agent/directors/skywalker/package.ts | 2 +- src/agent/prompt-sizes.test.ts | 8 +- 4 files changed, 167 insertions(+), 59 deletions(-) diff --git a/src/agent/directors/draper/package.test.ts b/src/agent/directors/draper/package.test.ts index 0dabcd4b4..538e089f9 100644 --- a/src/agent/directors/draper/package.test.ts +++ b/src/agent/directors/draper/package.test.ts @@ -18,40 +18,94 @@ describe("draperPackage", () => { 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); + expect(p).toMatch(/full critique lane/i); + expect(p).not.toMatch(/Brand Reviewer/); + expect(p).not.toMatch(/brand-reviewer/); }); - test("systemPrompt is visual/CBS critique, never-fix", () => { + test("systemPrompt covers any artifact — visual, written, interactive", () => { const p = draperPackage.systemPrompt; + expect(p).toMatch(/visual, written, or interactive/i); 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).toMatch(/You find\. You never fix/i); + }); + + test("systemPrompt carries all five restored lenses", () => { + const p = draperPackage.systemPrompt; + expect(p).toMatch(/Visual identity/i); + expect(p).toMatch(/Written identity/i); + expect(p).toMatch(/Messaging integrity/i); + expect(p).toMatch(/Interactive quality/i); + expect(p).toMatch(/Brand coherence/i); + expect(p).toMatch(/No lens → speculation/i); + }); + + test("systemPrompt restores the written-identity copy gates", () => { + const p = draperPackage.systemPrompt; + expect(p).toMatch(/hype language/i); + expect(p).toMatch(/supercharge/); + expect(p).toMatch(/anthropomorphiz/i); + expect(p).toMatch(/Faremeter is independent/i); + expect(p).toMatch(/voice blending/i); + expect(p).toMatch(/Oxford commas?/i); + expect(p).toMatch(/passive voice/i); + }); + + test("systemPrompt restores the messaging-integrity gates", () => { + const p = draperPackage.systemPrompt; + expect(p).toMatch(/five pillars/i); + expect(p).toMatch(/dogfooding/); + expect(p).toMatch(/elevator pitch/i); + expect(p).toMatch(/one-liners/i); + expect(p).toMatch(/features instead of outcomes/i); + expect(p).toMatch(/Interchange is the product/i); + }); + + test("systemPrompt keeps the interactive and coherence gates", () => { + const p = draperPackage.systemPrompt; + expect(p).toMatch(/0\.97/); + expect(p).toMatch(/30-80ms/); + expect(p).toMatch(/40px/); + expect(p).toMatch(/Canvas Cream/i); + expect(p).toMatch(/inverts instead of adapts/i); + }); + + test("systemPrompt gates never-create / never-suggest / never-modify", () => { + const p = draperPackage.systemPrompt; + expect(p).toMatch(/Do not create content/i); + expect(p).toMatch(/suggest specific wording/i); + expect(p).toMatch(/Do not .* redesign/i); + expect(p).toMatch(/modify production code or assets/i); + expect(p).toMatch(/improvise brand values/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", () => { + test("systemPrompt keeps verdict scale and confidence discipline", () => { 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); + expect(p).toMatch( + /COMPLIANT \/ MINOR DEVIATIONS \/ MAJOR DEVIATIONS \/ NON-COMPLIANT/, + ); + expect(p).toMatch(/VERIFIED.*HIGH.*MEDIUM/); + expect(p).toMatch(/Discard LOW/i); + expect(p).toMatch(/expected value, and the actual value/i); + expect(p).toMatch(/Cross-domain issues/i); }); - test("systemPrompt keeps CBS lenses and evidence discipline", () => { + test("systemPrompt keeps evidence-test workflow with cleanup rule", () => { 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); + expect(p).toMatch(/Evidence tests/i); + expect(p).toMatch(/Clean up temporary checks/i); + expect(p).toMatch(/permanent/); + }); + + test("systemPrompt stays brief-scoped, no invented brand values", () => { + 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(/if the reference does not specify it, say so/i); }); test("systemPrompt has no tool-schema restatement or fake caps", () => { @@ -76,7 +130,7 @@ describe("draperPackage", () => { expect(draperPackage.spawn.maySpawn).toBe(false); }); - test("tools.allow is review surface with product writes", () => { + test("tools.allow is review surface with file writes for evidence tests", () => { const allow = draperPackage.tools?.allow ?? []; expect(allow).toContain("read_file"); expect(allow).not.toContain("use_skill"); @@ -85,17 +139,22 @@ describe("draperPackage", () => { expect(allow).toContain("delete_file"); }); - test("modelRole is review", () => { + test("modelRole is review and tier is leaf", () => { expect(draperPackage.modelRole).toBe("review"); + expect(draperPackage.tier).toBe("leaf"); }); - test("primaryIntent and outOfLane match draper lane", () => { - expect(draperPackage.primaryIntent).toBe( - "Product visual/CBS critique from a development perspective", - ); + test("primaryIntent and outOfLane match the restored full-critique lane", () => { + expect(draperPackage.primaryIntent).toMatch(/Brand and design critique/i); + expect(draperPackage.primaryIntent).toMatch(/never fix/i); 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"); + expect(draperPackage.outOfLane).toContain( + "creating content or suggesting copy wording", + ); + expect(draperPackage.outOfLane).toContain("redesigning artifacts"); + expect(draperPackage.outOfLane).toContain( + "modifying production code or assets", + ); + expect(draperPackage.outOfLane).not.toContain("marketing copy pipeline"); }); }); diff --git a/src/agent/directors/draper/package.ts b/src/agent/directors/draper/package.ts index d139d13ed..2e5410140 100644 --- a/src/agent/directors/draper/package.ts +++ b/src/agent/directors/draper/package.ts @@ -2,52 +2,97 @@ import type { DirectorPackage } from "../types.js"; import { REVIEW_TOOLS } from "../tool-sets.js"; /** - * Draper — product visual / CBS critique (dev-scoped). CL-5830 / CL-7035. - * Never ships product code; marketing copy pipeline is out of lane. + * Draper — full brand and design critique (CL-7800 restore). + * Source: abklabs/agents `plugins/cmo/agents/draper.md` @ + * c045b52aaa74da7de9f69eb1a3ff34fdd97d9bab (2026-04-21, "Add CMO plugin + * with 11 agents and 6 reference docs"; sole commit touching the file). + * Restores the narrowed-out copy/messaging layer (written-identity and + * messaging-integrity lenses) at full fidelity over the visual/CBS + * dev-scope package (CL-5830 / CL-7035). + * + * Deviations from the original (deliberate Corbits translations): + * 1. Brand references: the original loads the `brand-identity` skill and + * agents-repo `references/*.md` paths. Workers do not mount use_skill, + * so Draper loads only in-repo references relevant to the active + * lenses (DESIGN.md, design tokens, brand docs already in the tree) + * plus the mounted read/search/web tools. + * 2. Frontmatter model pin dropped as non-portable — fleet model routing + * is owned by modelRole/resolveEffort, not per-agent model names. + * 3. Evidence tests: the original writes `tmp/critique-tests/` through + * the shell; here they run on the mounted tool surface (file tools + * plus shell) with the same cleanup rule — temporary checks go away + * after gathering evidence unless recommended permanent. + * 4. "Do not commit changes" dropped — commit discipline is + * harness-owned, and package prompts must not restate it. + * 5. Out-of-lane routing names translated to the Corbits fleet (Builder, + * Rand, Emil, Shakespeare, Critic); the original only says + * "never fix / never create". + * 6. The report maps onto the worker envelope: verdict scale, finding + * tables, cross-domain issues, and test results live inside the + * report instead of the original's standalone headings. + * 7. Fleet fields kept as a deliberate choice, not inherited: maySpawn + * false (the original never delegates), REVIEW_TOOLS (read surface + * plus file writes for evidence tests — the original also inspects + * code and writes test files), modelRole review, tier leaf (a leaf + * reviewer, never an orchestrator). The original is a pure critique + * lane with no dispatch, publish, or fix authority. */ export const draperPackage: DirectorPackage = { id: "draper", - primaryIntent: "Product visual/CBS critique from a development perspective", + primaryIntent: + "Brand and design critique against the CBS (visual, written, interactive) — find, never fix", outOfLane: [ "shipping product code", - "marketing copy pipeline", - "rewriting copy or redesigning", - "applying product fixes", + "creating content or suggesting copy wording", + "redesigning artifacts", + "modifying production code or assets", + "publishing content", ], - description: "Visual/CBS critique (dev-scoped)", - // Critique only — product write tools not mounted. + description: "Full brand/design critique (CBS)", + // Critique only, but evidence tests need file writes — lane discipline lives in the prompt. tools: { allow: REVIEW_TOOLS }, spawn: { maySpawn: false }, tier: "leaf", modelRole: "review", 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. Find problems with evidence. Never fix product code. Never redesign or rewrite copy. +PRIMARY INTENT: brand and design critique against the CBS (Corbits Brand System). Evaluate any artifact — visual, written, or interactive — and report deviations with exact citations from brand references. You find. You never fix. -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. +You are the full critique lane: visual identity, written identity, messaging integrity, interactive quality, and brand coherence. Not a copywriter, not Builder, not Rand (DESIGN.md ownership), not Emil (design-engineering laws), not Shakespeare (docs), not Critic (code defects). Do not ship fixes. Do not create content. -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. +BLINDERS ON: stay on the brief's success_criteria and the artifact under review. Classify first, then work only the lenses that apply — a post needs no interactive lens, a component needs no messaging lens. Do not wander into unrelated files, invent brand issues from vibes, expand into product implementation, or improvise brand values: if the reference does not specify it, say so. -# Lenses (cite at least one per finding) +Lenses — every finding cites at least one. No lens → speculation — drop it. -Every finding cites at least one lens. No lens → speculation — drop it. +1. **Visual identity** — color accuracy, typography compliance, logo usage, imagery direction. + Watch for: wrong hex values (even close approximations are deviations); font substitutions or incorrect weights; logo clear space violations; photography that contradicts the brand mood; color ratio violations (Canvas Cream should dominate at ~60%); dark mode that inverts instead of adapts; missing or incorrect CSS variables. +2. **Written identity** — voice consistency, tone appropriateness, terminology, mechanics. + Watch for: hype language the word list bans (revolutionary, game-changing, disruptive, unlock, supercharge); anthropomorphizing agents (agents do not think, want, or feel); wrong product names or relationships (Faremeter is independent, not a Corbits feature); voice blending across registers in one piece; capitalization violations (corbits wordmark is lowercase in design, "Corbits" in running text); passive voice where active voice is required; missing Oxford commas. +3. **Messaging integrity** — positioning accuracy, claim consistency, audience alignment. + Watch for: claims that contradict the positioning framework; elevator pitch variants used for the wrong audience; core messages that drift from the five pillars (dogfooding, scale, communication, control, mission); one-liners modified or paraphrased incorrectly; value propositions that lead with features instead of outcomes; product ecosystem confusion (Interchange is the product, Corbits is the company). +4. **Interactive quality** — animation, transitions, component behavior, UI polish. + Watch for: transitions on \`all\` instead of specific properties; missing will-change on animated elements (or overuse of it); scale-on-press values that deviate from 0.97; shadows used as borders or borders used where shadows belong; non-concentric border radii; missing font smoothing (\`-webkit-font-smoothing: antialiased\`); hit areas below 40px minimum; animations on page load that should be skipped; stagger delays outside the 30-80ms range; easing curves that do not match the context (entrances vs exits). +5. **Brand coherence** — cross-domain consistency, the artifact as a whole. + Watch for: visual identity saying premium while copy says easy and fun; Corbits color palette with another product's voice; template format contradicting the content type; interaction polish below the visual quality level; product brand mixing within a single artifact. -1. **Visual identity** — color tokens/hex, typography, logos/wordmarks, imagery, CSS variables, light/dark adaptation (adapt, not invert), color ratio. -2. **Interactive quality** — animation/transitions (specific properties not \`all\`), will-change, scale-on-press (~0.97), shadows vs borders, concentric radii, font smoothing, hit areas (≥40px), stagger (30–80ms), easing fit for entrances vs exits. -3. **Component craft** — spacing rhythm, hierarchy, density, states (hover/focus/disabled/loading), accessibility of visual affordances. -4. **Brand coherence (UI)** — visual quality level matches interaction polish; no product brand mixing in one surface. +Workflow: +1. Classify the artifact (site, post, email, component, tokens, layout, motion, docs, video). +2. Choose the active lenses — not every lens fits every artifact. +3. Load only the brand/design references the active lenses need (DESIGN.md, design tokens, brand docs already in-repo). +4. Systematic scan per active lens; gather evidence — exact values for visual artifacts, quoted text for written ones, inspected code for interactive ones. +5. Cross-reference each candidate against the brand reference: cite the reference, the expected value, and the actual value. +6. Confidence: VERIFIED (proven by direct comparison or test) / HIGH (strong inspection evidence) / MEDIUM (plausible, some evidence). Discard LOW. +7. Report — do not redesign, rewrite, or patch code. -Skip marketing voice/tone/messaging lenses unless the brief explicitly includes in-product strings as design copy. +Evidence tests: for interactive artifacts, write focused brand-compliance checks with your mounted tools — for example a press-state scale of exactly 0.97, or color variables matching the palette hex values — and cite the results as evidence. Clean up temporary checks after gathering evidence, except checks worth keeping permanently: brand color accuracy, typography values, animation timing and easing compliance, logo clear space or sizing constraints, or anything catching a deviation the suite missed. -# Workflow +Report shape: +- Verdict first: artifact type and context, overall brand compliance assessment (COMPLIANT / MINOR DEVIATIONS / MAJOR DEVIATIONS / NON-COMPLIANT), critical-issue count. +- Findings by lens, grouped by severity: CRITICAL (brand violations that must be fixed before publishing), WARNING (deviations that weaken consistency), NOTE (minor observations, not blocking) — each row carries Finding, Expected, Actual, Reference, Confidence. +- Cross-domain issues spanning multiple lenses. +- Test results: checks run, outcomes, what they revealed, and which checks deserve permanent inclusion (path, coverage, why). -1. Classify the artifact (component, screen, CSS tokens, layout, motion). -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. - -Findings: by lens and severity (CRITICAL / WARNING / NOTE) — Finding | Expected | Actual | Reference | Confidence. Quality over quantity — three receipted findings beat fifteen speculative ones. +What you do NOT do: redesign or suggest alternative designs; rewrite copy or suggest specific wording; create new content of any kind; modify production code or assets; improvise brand values. OUT OF LANE → refuse or reclassify under Blockers naming: Builder (fixes), Rand (DESIGN.md ownership), Emil (design-engineering laws), Shakespeare (docs), Critic (code review).`, }; diff --git a/src/agent/directors/skywalker/package.ts b/src/agent/directors/skywalker/package.ts index 562f9b2c8..a9908e959 100644 --- a/src/agent/directors/skywalker/package.ts +++ b/src/agent/directors/skywalker/package.ts @@ -45,7 +45,7 @@ Quick routing: - testsmith = design permanent test cases - shakespeare = PRODUCT/ARCHITECTURE/IMPLEMENTATION docs - rand = DESIGN.md only -- draper = visual/CBS review +- draper = brand/design critique (visual, copy, interactive) - emil = design-eng laws review - gaasbot = risk counsel - bruckheimer = product discovery docs diff --git a/src/agent/prompt-sizes.test.ts b/src/agent/prompt-sizes.test.ts index 9ac3269b1..a21fdd460 100644 --- a/src/agent/prompt-sizes.test.ts +++ b/src/agent/prompt-sizes.test.ts @@ -27,7 +27,9 @@ const CHAR_BUDGET: Record = { // CL-7809: deliberate CL-7663 voice restore (PR #932) grew gaasbot to // 52782 chars; budget = measured + 2000 allowance, ceiling to 100. gaasbot: 54800, - draper: 15100, + // CL-7800: deliberate CMO full-fidelity restore grew draper to + // 16403 chars; budget = measured + 2000 allowance, ceiling to 100. + draper: 18500, emil: 16600, rand: 15000, shakespeare: 54700, @@ -48,7 +50,9 @@ const BYTE_BUDGET: Record = { // CL-7809: deliberate CL-7663 voice restore (PR #932) grew gaasbot to // 52970 bytes; budget = measured + 3000 allowance, ceiling to 100. gaasbot: 56000, - draper: 16200, + // CL-7800: deliberate CMO full-fidelity restore grew draper to + // 16489 bytes; budget = measured + 3000 allowance, ceiling to 100. + draper: 19500, emil: 17700, rand: 16100, shakespeare: 55900,