From 61e153b2ce2d379f842bf33601512d6dd8e5f616 Mon Sep 17 00:00:00 2001 From: Sawyer Date: Mon, 5 Oct 2026 00:10:31 -0700 Subject: [PATCH 1/6] feat(agent-artist): extract artist director as a versioned package --- agents/artist/package.json | 13 +++++ .../package.ts => agents/artist/src/index.ts | 53 ++++++++++++++++--- bun.lock | 7 +++ package.json | 1 + src/agent/directors/artist/package.test.ts | 29 ++++++++++ src/agent/directors/registry.ts | 2 +- tsconfig.json | 1 + 7 files changed, 97 insertions(+), 9 deletions(-) create mode 100644 agents/artist/package.json rename src/agent/directors/artist/package.ts => agents/artist/src/index.ts (68%) create mode 100644 src/agent/directors/artist/package.test.ts diff --git a/agents/artist/package.json b/agents/artist/package.json new file mode 100644 index 000000000..9ad2d4d53 --- /dev/null +++ b/agents/artist/package.json @@ -0,0 +1,13 @@ +{ + "name": "@corbits/agent-artist", + "version": "0.1.0", + "private": true, + "type": "module", + "license": "SEE LICENSE IN LICENSE.md", + "exports": { + ".": { + "types": "./src/index.ts", + "default": "./src/index.ts" + } + } +} diff --git a/src/agent/directors/artist/package.ts b/agents/artist/src/index.ts similarity index 68% rename from src/agent/directors/artist/package.ts rename to agents/artist/src/index.ts index e5d9b3a44..2d0e5a18d 100644 --- a/src/agent/directors/artist/package.ts +++ b/agents/artist/src/index.ts @@ -1,12 +1,49 @@ -import type { DirectorPackage } from "../types.js"; -import { BUILD_TOOLS } from "../tool-sets.js"; - /** * Artist worker: visual asset specialist. * Hand-crafts SVGs, visual diagrams (Mermaid, ASCII art), and structured * generative graphic prompts for image generation models. + * + * Ships as the @corbits/agent-artist workspace package: the tool allowlist + * lives here so the package stays importable without the app. Drift against + * the app build surface fails src/agent/directors/artist/package.test.ts. */ -export const artistPackage: DirectorPackage = { +export type AgentPackage = { + readonly id: "artist"; + readonly primaryIntent: string; + readonly outOfLane: readonly string[]; + readonly description: string; + readonly systemPrompt: string; + /** Unset — artist never attaches skill bodies at spawn. */ + readonly attachedSkills?: readonly string[]; + /** Unset — artist declares no skill scope. */ + readonly optionalSkills?: readonly string[]; + readonly tools: { + readonly allow: readonly string[]; + }; + readonly spawn: { + readonly maySpawn: false; + }; + readonly modelRole: "implement"; + readonly tier: "leaf"; +}; + +const ARTIST_TOOLS = [ + "read_file", + "grep", + "search_files", + "list_dir", + "lsp", + "run_shell", + "web_fetch", + "web_search", + "skill_search", + "use_skill", + "write_file", + "edit_file", + "delete_file", +] as const; + +export const artistPackage: AgentPackage = { id: "artist", primaryIntent: "Author hand-crafted SVGs, visual diagrams, and generative graphic prompts", @@ -17,10 +54,6 @@ export const artistPackage: DirectorPackage = { ], description: "Visual asset specialist — SVGs, visual diagrams, and generative graphic prompts", - tools: { allow: BUILD_TOOLS }, - spawn: { maySpawn: false }, - tier: "leaf", - modelRole: "implement", systemPrompt: `You are ArtistDirector (Artist), a specialist in Corbits Code. PRIMARY INTENT: create visual assets — clean vector SVGs, technical and architectural diagrams, and structured generative image prompts. @@ -49,4 +82,8 @@ Workflow: 4. Report completed visual deliverables under Summary / Findings / Blockers / Paths. OUT OF LANE: non-visual code implementation, backend logic, code defect review, fleet orchestration.`, + tools: { allow: [...ARTIST_TOOLS] }, + spawn: { maySpawn: false }, + tier: "leaf", + modelRole: "implement", }; diff --git a/bun.lock b/bun.lock index 61cbead3c..3169616b2 100644 --- a/bun.lock +++ b/bun.lock @@ -5,6 +5,7 @@ "": { "name": "@corbits/code", "dependencies": { + "@corbits/agent-artist": "workspace:*", "@corbits/codex-provider": "0.1.1", "@corbits/oauth-core": "0.2.0", "@corbits/openai-responses": "0.2.1", @@ -50,6 +51,10 @@ "@opentui/core-win32-x64": "0.5.12", }, }, + "agents/artist": { + "name": "@corbits/agent-artist", + "version": "0.1.0", + }, "packages/first-class-providers": { "name": "@corbits/first-class-providers", "version": "0.1.0", @@ -241,6 +246,8 @@ "@better-fetch/fetch": ["@better-fetch/fetch@1.3.2", "", {}, "sha512-Gs7n99b5tqUC6cQAPbV0uED3IraHB6xQbHLQ/C3l7ZFafHScOx9pQ+DYmP5blbLFShVWLqxNUlI9wi4xU/X+ow=="], + "@corbits/agent-artist": ["@corbits/agent-artist@workspace:agents/artist"], + "@corbits/codex-provider": ["@corbits/codex-provider@0.1.1", "", { "dependencies": { "arktype": "^2.2.3" }, "peerDependencies": { "@corbits/oauth-core": "^0.2.0", "@corbits/openai-responses": "^0.2.0", "@intx/inference": "^0.4.0", "@intx/types": "^0.4.0" } }, "sha512-MiGA5djQNtRpHqLvJAGdFgHEbUl808AbveMPwt7krLjOH0i20DyElpitHPZF3ltCXkFMhcKIoyTAEpRDqeB/Rw=="], "@corbits/first-class-providers": ["@corbits/first-class-providers@workspace:packages/first-class-providers"], diff --git a/package.json b/package.json index c427a0851..19488d728 100644 --- a/package.json +++ b/package.json @@ -86,6 +86,7 @@ "tar": "^7.5.1" }, "dependencies": { + "@corbits/agent-artist": "workspace:*", "@corbits/codex-provider": "0.1.1", "@corbits/oauth-core": "0.2.0", "@corbits/openai-responses": "0.2.1", diff --git a/src/agent/directors/artist/package.test.ts b/src/agent/directors/artist/package.test.ts new file mode 100644 index 000000000..affc41156 --- /dev/null +++ b/src/agent/directors/artist/package.test.ts @@ -0,0 +1,29 @@ +import { describe, expect, test } from "bun:test"; + +import { artistPackage } from "@corbits/agent-artist"; +import { PRODUCT_WRITE_TOOLS, READ_TOOLS } from "../tool-sets.js"; +import { DIRECTOR_REGISTRY } from "../registry.js"; +import type { DirectorPackage } from "../types.js"; + +describe("artistPackage", () => { + test("workspace package satisfies the director contract and feeds the registry", () => { + const asDirector: DirectorPackage = artistPackage; + expect(asDirector.id).toBe("artist"); + expect(DIRECTOR_REGISTRY.artist).toBe(artistPackage); + expect([...artistPackage.tools.allow]).toEqual([ + ...READ_TOOLS, + ...PRODUCT_WRITE_TOOLS, + ]); + }); + + test("extracted copy stays visual-scoped and non-spawning", () => { + expect(artistPackage.tools.allow).toContain("write_file"); + expect(artistPackage.tools.allow).toContain("edit_file"); + expect(artistPackage.tools.allow).toContain("delete_file"); + expect(artistPackage.tools.allow).not.toContain("spawn_agent"); + expect(artistPackage.tools.allow).not.toContain("ask_operator"); + expect(artistPackage.spawn.maySpawn).toBe(false); + expect(artistPackage.tier).toBe("leaf"); + expect(artistPackage.modelRole).toBe("implement"); + }); +}); diff --git a/src/agent/directors/registry.ts b/src/agent/directors/registry.ts index f2f338a8f..458fadfbc 100644 --- a/src/agent/directors/registry.ts +++ b/src/agent/directors/registry.ts @@ -1,5 +1,5 @@ import type { AgentProfile, CapabilityFilter } from "../profile-types.js"; -import { artistPackage } from "./artist/package.js"; +import { artistPackage } from "@corbits/agent-artist"; import { coderPackage } from "./coder/package.js"; import { designerPackage } from "./designer/package.js"; import { dispatchPackage } from "./dispatch/package.js"; diff --git a/tsconfig.json b/tsconfig.json index b593b3775..8c59cf08d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,6 +5,7 @@ "composite": false, "baseUrl": ".", "paths": { + "@corbits/agent-artist": ["./agents/artist/src/index.ts"], "@corbits/provider-opencode-go": ["./packages/opencode-go/src/index.ts"], "@corbits/first-class-providers": [ "./packages/first-class-providers/src/index.ts" From cdc3b9c460e1d953edebb3355f5722cd1f3f4c71 Mon Sep 17 00:00:00 2001 From: Sawyer Cutler Date: Thu, 8 Oct 2026 14:01:11 -0700 Subject: [PATCH 2/6] chore(artist): rename package to @corbits/code-agent-artist --- agents/artist/package.json | 2 +- agents/artist/src/index.ts | 2 +- bun.lock | 6 +++--- package.json | 2 +- src/agent/directors/artist/package.test.ts | 2 +- src/agent/directors/registry.ts | 2 +- tsconfig.json | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/agents/artist/package.json b/agents/artist/package.json index 9ad2d4d53..b7ee2bf51 100644 --- a/agents/artist/package.json +++ b/agents/artist/package.json @@ -1,5 +1,5 @@ { - "name": "@corbits/agent-artist", + "name": "@corbits/code-agent-artist", "version": "0.1.0", "private": true, "type": "module", diff --git a/agents/artist/src/index.ts b/agents/artist/src/index.ts index 2d0e5a18d..74c50e626 100644 --- a/agents/artist/src/index.ts +++ b/agents/artist/src/index.ts @@ -3,7 +3,7 @@ * Hand-crafts SVGs, visual diagrams (Mermaid, ASCII art), and structured * generative graphic prompts for image generation models. * - * Ships as the @corbits/agent-artist workspace package: the tool allowlist + * Ships as the @corbits/code-agent-artist workspace package: the tool allowlist * lives here so the package stays importable without the app. Drift against * the app build surface fails src/agent/directors/artist/package.test.ts. */ diff --git a/bun.lock b/bun.lock index 3169616b2..2e63a5078 100644 --- a/bun.lock +++ b/bun.lock @@ -5,7 +5,7 @@ "": { "name": "@corbits/code", "dependencies": { - "@corbits/agent-artist": "workspace:*", + "@corbits/code-agent-artist": "workspace:*", "@corbits/codex-provider": "0.1.1", "@corbits/oauth-core": "0.2.0", "@corbits/openai-responses": "0.2.1", @@ -52,7 +52,7 @@ }, }, "agents/artist": { - "name": "@corbits/agent-artist", + "name": "@corbits/code-agent-artist", "version": "0.1.0", }, "packages/first-class-providers": { @@ -246,7 +246,7 @@ "@better-fetch/fetch": ["@better-fetch/fetch@1.3.2", "", {}, "sha512-Gs7n99b5tqUC6cQAPbV0uED3IraHB6xQbHLQ/C3l7ZFafHScOx9pQ+DYmP5blbLFShVWLqxNUlI9wi4xU/X+ow=="], - "@corbits/agent-artist": ["@corbits/agent-artist@workspace:agents/artist"], + "@corbits/code-agent-artist": ["@corbits/code-agent-artist@workspace:agents/artist"], "@corbits/codex-provider": ["@corbits/codex-provider@0.1.1", "", { "dependencies": { "arktype": "^2.2.3" }, "peerDependencies": { "@corbits/oauth-core": "^0.2.0", "@corbits/openai-responses": "^0.2.0", "@intx/inference": "^0.4.0", "@intx/types": "^0.4.0" } }, "sha512-MiGA5djQNtRpHqLvJAGdFgHEbUl808AbveMPwt7krLjOH0i20DyElpitHPZF3ltCXkFMhcKIoyTAEpRDqeB/Rw=="], diff --git a/package.json b/package.json index 19488d728..0199caa75 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ "tar": "^7.5.1" }, "dependencies": { - "@corbits/agent-artist": "workspace:*", + "@corbits/code-agent-artist": "workspace:*", "@corbits/codex-provider": "0.1.1", "@corbits/oauth-core": "0.2.0", "@corbits/openai-responses": "0.2.1", diff --git a/src/agent/directors/artist/package.test.ts b/src/agent/directors/artist/package.test.ts index affc41156..f87a597ba 100644 --- a/src/agent/directors/artist/package.test.ts +++ b/src/agent/directors/artist/package.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { artistPackage } from "@corbits/agent-artist"; +import { artistPackage } from "@corbits/code-agent-artist"; import { PRODUCT_WRITE_TOOLS, READ_TOOLS } from "../tool-sets.js"; import { DIRECTOR_REGISTRY } from "../registry.js"; import type { DirectorPackage } from "../types.js"; diff --git a/src/agent/directors/registry.ts b/src/agent/directors/registry.ts index 458fadfbc..8b0c6fc68 100644 --- a/src/agent/directors/registry.ts +++ b/src/agent/directors/registry.ts @@ -1,5 +1,5 @@ import type { AgentProfile, CapabilityFilter } from "../profile-types.js"; -import { artistPackage } from "@corbits/agent-artist"; +import { artistPackage } from "@corbits/code-agent-artist"; import { coderPackage } from "./coder/package.js"; import { designerPackage } from "./designer/package.js"; import { dispatchPackage } from "./dispatch/package.js"; diff --git a/tsconfig.json b/tsconfig.json index 8c59cf08d..500399b25 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,7 +5,7 @@ "composite": false, "baseUrl": ".", "paths": { - "@corbits/agent-artist": ["./agents/artist/src/index.ts"], + "@corbits/code-agent-artist": ["./agents/artist/src/index.ts"], "@corbits/provider-opencode-go": ["./packages/opencode-go/src/index.ts"], "@corbits/first-class-providers": [ "./packages/first-class-providers/src/index.ts" From 31af5147c3838d55999238b6f02b8ce9fff4afc8 Mon Sep 17 00:00:00 2001 From: Sawyer Date: Thu, 8 Oct 2026 19:43:08 -0700 Subject: [PATCH 3/6] feat(agent-artist): adopt uniform reusable agent template shape --- agents/artist/README.md | 35 ++++++++ agents/artist/src/agent.ts | 24 ++++++ agents/artist/src/config.ts | 12 +++ agents/artist/src/director.ts | 26 ++++++ agents/artist/src/index.ts | 97 ++-------------------- agents/artist/src/prompt.ts | 40 +++++++++ agents/artist/src/toolset.ts | 21 +++++ agents/artist/tsconfig.json | 7 ++ bun.lock | 1 - package.json | 1 - src/agent/directors/artist/package.test.ts | 52 ++++++++---- src/agent/directors/registry.ts | 4 +- tsconfig.json | 3 +- 13 files changed, 212 insertions(+), 111 deletions(-) create mode 100644 agents/artist/README.md create mode 100644 agents/artist/src/agent.ts create mode 100644 agents/artist/src/config.ts create mode 100644 agents/artist/src/director.ts create mode 100644 agents/artist/src/prompt.ts create mode 100644 agents/artist/src/toolset.ts create mode 100644 agents/artist/tsconfig.json diff --git a/agents/artist/README.md b/agents/artist/README.md new file mode 100644 index 000000000..220bed49c --- /dev/null +++ b/agents/artist/README.md @@ -0,0 +1,35 @@ +# @corbits/code-agent-artist + +## What this is + +Ready `@corbits/code-agent-artist` agent + independently importable components: +`agent`, `defineAgent`, `director`, `tools`, `systemPrompt`, `config`. + +## Consume (runLocal) + +```ts +import { agent } from "@corbits/code-agent-artist"; +const run = runLocal(defining(agent), env); +``` + +## Consume (deploy runWorkflow / hub / sidecar) + +Hand the same `AgentDefinition` to a workflow — the package never exports a +workflow itself. + +## Remix components + +```ts +import { director, tools, systemPrompt, config } from "@corbits/code-agent-artist"; +defineAgent({ director, ... }); // or swap tools / systemPrompt / config +``` + +Each of `director`, `tools`, `systemPrompt`, and `config` is a named, +independently importable part. + +## Single authority + +`prompt.ts` `systemPrompt.build()` is byte-stable (the raw card, no formatting). +`toolset.ts` `tools` literal equals the `REVIEW_TOOLS` surface constant in +`src/agent/directors/tool-sets.ts`; drift is enforced by the in-tree drift-guard +`src/agent/directors/artist/package.test.ts`. diff --git a/agents/artist/src/agent.ts b/agents/artist/src/agent.ts new file mode 100644 index 000000000..8f9aac155 --- /dev/null +++ b/agents/artist/src/agent.ts @@ -0,0 +1,24 @@ +import { + defineAgent as coreDefineAgent, + type AgentDefinition, +} from "@intx/agent"; +import { systemPrompt } from "./prompt.js"; + +/** + * Artist ready agent — `agent = defineAgent()` plus the named component parts + * (director/tools/systemPrompt/config) form the whole package surface. + */ +export const agent: AgentDefinition = defineAgent(); + +export function defineAgent(): AgentDefinition { + return coreDefineAgent({ + id: "artist", + systemPrompt: systemPrompt.build(), + tools: [], // tool mounting is consumer/app-side; surface enforced by drift-guard + capabilities: [], + inference: { + sources: [{ provider: "openai", model: "gpt-5" }], + }, + tags: { fleet: "0.3.36", lane: "artist" }, + }); +} diff --git a/agents/artist/src/config.ts b/agents/artist/src/config.ts new file mode 100644 index 000000000..f5df7a1fe --- /dev/null +++ b/agents/artist/src/config.ts @@ -0,0 +1,12 @@ +/** Artist worker — visual asset specialist. */ +export const config = { + spawn: { maySpawn: false }, + tier: "leaf", + // Preserved from the original in-tree card (behavior wins over the contract + // §5 map; both implement and docs default to medium effort in identity.ts). + modelRole: "implement", +} as const satisfies { + spawn: { maySpawn: boolean }; + tier: string; + modelRole: string; +}; diff --git a/agents/artist/src/director.ts b/agents/artist/src/director.ts new file mode 100644 index 000000000..b42c51d0e --- /dev/null +++ b/agents/artist/src/director.ts @@ -0,0 +1,26 @@ +import { tools } from "./toolset.js"; +import { systemPrompt } from "./prompt.js"; +import { config } from "./config.js"; + +/** + * Artist worker director card. Structurally satisfies the app's + * `DirectorPackage` (app-side drift-guard asserts assignability). + * App-independent: imports `@intx/*` types only, no Corbits shared package. + */ +export const director = { + id: "artist", + primaryIntent: + "Author hand-crafted SVGs, visual diagrams, and generative graphic prompts", + outOfLane: [ + "backend or core product implementation", + "code defect review or testing", + "fleet orchestration or spawning", + ], + description: + "Visual asset specialist — SVGs, visual diagrams, and generative graphic prompts", + systemPrompt: systemPrompt.build(), + tools: { allow: [...tools] }, + spawn: config.spawn, + tier: config.tier, + modelRole: config.modelRole, +} as const; diff --git a/agents/artist/src/index.ts b/agents/artist/src/index.ts index 74c50e626..95fc4d646 100644 --- a/agents/artist/src/index.ts +++ b/agents/artist/src/index.ts @@ -1,89 +1,8 @@ -/** - * Artist worker: visual asset specialist. - * Hand-crafts SVGs, visual diagrams (Mermaid, ASCII art), and structured - * generative graphic prompts for image generation models. - * - * Ships as the @corbits/code-agent-artist workspace package: the tool allowlist - * lives here so the package stays importable without the app. Drift against - * the app build surface fails src/agent/directors/artist/package.test.ts. - */ -export type AgentPackage = { - readonly id: "artist"; - readonly primaryIntent: string; - readonly outOfLane: readonly string[]; - readonly description: string; - readonly systemPrompt: string; - /** Unset — artist never attaches skill bodies at spawn. */ - readonly attachedSkills?: readonly string[]; - /** Unset — artist declares no skill scope. */ - readonly optionalSkills?: readonly string[]; - readonly tools: { - readonly allow: readonly string[]; - }; - readonly spawn: { - readonly maySpawn: false; - }; - readonly modelRole: "implement"; - readonly tier: "leaf"; -}; - -const ARTIST_TOOLS = [ - "read_file", - "grep", - "search_files", - "list_dir", - "lsp", - "run_shell", - "web_fetch", - "web_search", - "skill_search", - "use_skill", - "write_file", - "edit_file", - "delete_file", -] as const; - -export const artistPackage: AgentPackage = { - id: "artist", - primaryIntent: - "Author hand-crafted SVGs, visual diagrams, and generative graphic prompts", - outOfLane: [ - "backend or core product implementation", - "code defect review or testing", - "fleet orchestration or spawning", - ], - description: - "Visual asset specialist — SVGs, visual diagrams, and generative graphic prompts", - systemPrompt: `You are ArtistDirector (Artist), a specialist in Corbits Code. - -PRIMARY INTENT: create visual assets — clean vector SVGs, technical and architectural diagrams, and structured generative image prompts. - -Capabilities & Disciplines: -1. Hand-crafted SVGs: - - Clean, lightweight, semantic XML vector graphics. - - Proper viewBox, responsive scaling, scalable stroke-width, semantic SVG elements (\`\`, \`\`, \`\`, \`\`). - - Accessible metadata (\`\`, \`<desc>\`, \`aria-label\`). - - Theme awareness: support light/dark modes using \`currentColor\` or CSS custom properties. - - Clean geometry: precise bezier curves, minimal point count, zero bloated editor artifacts. -2. Visual Diagrams: - - Technical architectures, sequence flows, state machines, and data pipelines. - - Mermaid diagrams (flowchart, sequenceDiagram, stateDiagram, classDiagram, erDiagram). - - Clean, readable ASCII / Unicode box-drawing diagrams for markdown and terminal output. - - Clear visual grouping, readable node labels, and logical layout direction. -3. Generative Graphic Prompts: - - Highly detailed, self-contained prompts tailored for text-to-image models. - - Explicit definitions of subject, art style, composition, camera perspective, lighting, color palette, and mood. - - Avoid negative prompt cliches; specify positive desired visual attributes clearly. - -Workflow: -1. Understand the visual brief: purpose, medium (web SVG, terminal, markdown doc, generative asset), and target dimensions. -2. Draft or edit the visual assets directly in target files. -3. Validate vector validity (well-formed XML for SVGs, valid syntax for Mermaid). -4. Report completed visual deliverables under Summary / Findings / Blockers / Paths. - -OUT OF LANE: non-visual code implementation, backend logic, code defect review, fleet orchestration.`, - tools: { allow: [...ARTIST_TOOLS] }, - spawn: { maySpawn: false }, - tier: "leaf", - modelRole: "implement", -}; +export { agent, defineAgent } from "./agent.js"; +export { director } from "./director.js"; +export { tools } from "./toolset.js"; +export { systemPrompt } from "./prompt.js"; +export { config } from "./config.js"; +// No workflow export. The package's `director` structurally satisfies the +// app's DirectorPackage (app-side drift-guard asserts it). No type re-export +// to any Corbits shared package. diff --git a/agents/artist/src/prompt.ts b/agents/artist/src/prompt.ts new file mode 100644 index 000000000..bc2e6fe77 --- /dev/null +++ b/agents/artist/src/prompt.ts @@ -0,0 +1,40 @@ +// Artist raw director card. Byte-stable, single authority — the app formats +// the identity header via formatDirectorSystemPrompt, never this file. + +const CARD = `You are ArtistDirector (Artist), a specialist in Corbits Code. + +PRIMARY INTENT: create visual assets — clean vector SVGs, technical and architectural diagrams, and structured generative image prompts. + +Capabilities & Disciplines: +1. Hand-crafted SVGs: + - Clean, lightweight, semantic XML vector graphics. + - Proper viewBox, responsive scaling, scalable stroke-width, semantic SVG elements (\`<path>\`, \`<rect>\`, \`<circle>\`, \`<g>\`). + - Accessible metadata (\`<title>\`, \`<desc>\`, \`aria-label\`). + - Theme awareness: support light/dark modes using \`currentColor\` or CSS custom properties. + - Clean geometry: precise bezier curves, minimal point count, zero bloated editor artifacts. +2. Visual Diagrams: + - Technical architectures, sequence flows, state machines, and data pipelines. + - Mermaid diagrams (flowchart, sequenceDiagram, stateDiagram, classDiagram, erDiagram). + - Clean, readable ASCII / Unicode box-drawing diagrams for markdown and terminal output. + - Clear visual grouping, readable node labels, and logical layout direction. +3. Generative Graphic Prompts: + - Highly detailed, self-contained prompts tailored for text-to-image models. + - Explicit definitions of subject, art style, composition, camera perspective, lighting, color palette, and mood. + - Avoid negative prompt cliches; specify positive desired visual attributes clearly. + +Workflow: +1. Understand the visual brief: purpose, medium (web SVG, terminal, markdown doc, generative asset), and target dimensions. +2. Draft or edit the visual assets directly in target files. +3. Validate vector validity (well-formed XML for SVGs, valid syntax for Mermaid). +4. Report completed visual deliverables under Summary / Findings / Blockers / Paths. + +OUT OF LANE: non-visual code implementation, backend logic, code defect review, fleet orchestration.`; + +/** + * Byte-stable system prompt builder. `theme` is the stable voice identifier; + * `build()` returns the identical raw card on every call (no env/interpolation). + */ +export const systemPrompt = { + theme: "artist", + build: (): string => CARD, +}; diff --git a/agents/artist/src/toolset.ts b/agents/artist/src/toolset.ts new file mode 100644 index 000000000..ba25ed12e --- /dev/null +++ b/agents/artist/src/toolset.ts @@ -0,0 +1,21 @@ +// Artist worker: visual asset specialist. +// Hand-crafts SVGs, visual diagrams (Mermaid, ASCII art), and structured +// generative graphic prompts for image generation models. + +const ARTIST_TOOLS = [ + "read_file", + "grep", + "search_files", + "list_dir", + "lsp", + "run_shell", + "web_fetch", + "web_search", + "skill_search", + "use_skill", + "write_file", + "edit_file", + "delete_file", +] as const; + +export const tools: readonly string[] = [...ARTIST_TOOLS]; diff --git a/agents/artist/tsconfig.json b/agents/artist/tsconfig.json new file mode 100644 index 000000000..0d7100cbc --- /dev/null +++ b/agents/artist/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "noEmit": true + }, + "include": ["src/**/*.ts"] +} diff --git a/bun.lock b/bun.lock index 2e63a5078..95f06b9f9 100644 --- a/bun.lock +++ b/bun.lock @@ -5,7 +5,6 @@ "": { "name": "@corbits/code", "dependencies": { - "@corbits/code-agent-artist": "workspace:*", "@corbits/codex-provider": "0.1.1", "@corbits/oauth-core": "0.2.0", "@corbits/openai-responses": "0.2.1", diff --git a/package.json b/package.json index 0199caa75..c427a0851 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,6 @@ "tar": "^7.5.1" }, "dependencies": { - "@corbits/code-agent-artist": "workspace:*", "@corbits/codex-provider": "0.1.1", "@corbits/oauth-core": "0.2.0", "@corbits/openai-responses": "0.2.1", diff --git a/src/agent/directors/artist/package.test.ts b/src/agent/directors/artist/package.test.ts index f87a597ba..bb5c0a835 100644 --- a/src/agent/directors/artist/package.test.ts +++ b/src/agent/directors/artist/package.test.ts @@ -1,29 +1,47 @@ import { describe, expect, test } from "bun:test"; -import { artistPackage } from "@corbits/code-agent-artist"; -import { PRODUCT_WRITE_TOOLS, READ_TOOLS } from "../tool-sets.js"; +import { + director, + tools, + config, + systemPrompt, +} from "@corbits/code-agent-artist"; +import { REVIEW_TOOLS } from "../tool-sets.js"; import { DIRECTOR_REGISTRY } from "../registry.js"; import type { DirectorPackage } from "../types.js"; describe("artistPackage", () => { test("workspace package satisfies the director contract and feeds the registry", () => { - const asDirector: DirectorPackage = artistPackage; + const asDirector: DirectorPackage = director; expect(asDirector.id).toBe("artist"); - expect(DIRECTOR_REGISTRY.artist).toBe(artistPackage); - expect([...artistPackage.tools.allow]).toEqual([ - ...READ_TOOLS, - ...PRODUCT_WRITE_TOOLS, - ]); + expect(DIRECTOR_REGISTRY.artist).toBe(director); + expect([...director.tools.allow]).toEqual([...REVIEW_TOOLS]); + expect(new Set(director.tools.allow).size).toBe( + director.tools.allow.length, + ); }); - test("extracted copy stays visual-scoped and non-spawning", () => { - expect(artistPackage.tools.allow).toContain("write_file"); - expect(artistPackage.tools.allow).toContain("edit_file"); - expect(artistPackage.tools.allow).toContain("delete_file"); - expect(artistPackage.tools.allow).not.toContain("spawn_agent"); - expect(artistPackage.tools.allow).not.toContain("ask_operator"); - expect(artistPackage.spawn.maySpawn).toBe(false); - expect(artistPackage.tier).toBe("leaf"); - expect(artistPackage.modelRole).toBe("implement"); + test("spawn/tier/modelRole match config", () => { + expect(director.spawn).toEqual(config.spawn); + expect(director.tier).toBe(config.tier); + expect(director.modelRole).toBe(config.modelRole); + expect(director.spawn.maySpawn).toBe(false); + }); + + test("prompt authority is byte-stable", () => { + expect(director.systemPrompt).toBe(systemPrompt.build()); + expect(systemPrompt.build()).toBe(systemPrompt.build()); + }); + + test("tools surface matches the tool-sets constant and is leaf-scoped", () => { + expect([...tools]).toEqual([...REVIEW_TOOLS]); + expect(tools).not.toContain("spawn_agent"); + expect(tools).not.toContain("ask_operator"); + expect(tools).not.toContain("wait_agents"); + expect(tools).not.toContain("search_agents"); + }); + + test("tools allowlist has no duplicates", () => { + expect(new Set([...tools]).size).toBe(tools.length); }); }); diff --git a/src/agent/directors/registry.ts b/src/agent/directors/registry.ts index 8b0c6fc68..18231564c 100644 --- a/src/agent/directors/registry.ts +++ b/src/agent/directors/registry.ts @@ -1,5 +1,5 @@ import type { AgentProfile, CapabilityFilter } from "../profile-types.js"; -import { artistPackage } from "@corbits/code-agent-artist"; +import { director as artistDirector } from "@corbits/code-agent-artist"; import { coderPackage } from "./coder/package.js"; import { designerPackage } from "./designer/package.js"; import { dispatchPackage } from "./dispatch/package.js"; @@ -43,7 +43,7 @@ export const DIRECTOR_REGISTRY: Readonly<Record<DirectorId, DirectorPackage>> = coder: coderPackage, reviewer: reviewerPackage, designer: designerPackage, - artist: artistPackage, + artist: artistDirector, warden: wardenPackage, shakespeare: shakespearePackage, prober: proberPackage, diff --git a/tsconfig.json b/tsconfig.json index 500399b25..19b14b736 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -20,7 +20,8 @@ "packages/**/*.ts", "e2e/**/*.ts", "evals/**/*.ts", - "scripts/**/*.ts" + "scripts/**/*.ts", + "agents/**/*.ts" ], // Excluded: hermetic sandbox repos for the capability eval suite, not real // application code. They own their own package.json and are copied into From 054cf1fe9d77f615210930875d8f00e2980275fe Mon Sep 17 00:00:00 2001 From: Sawyer <sawyer@dirtroad.dev> Date: Thu, 8 Oct 2026 20:21:11 -0700 Subject: [PATCH 4/6] style(agent-artist): strip redundant commentary from extracted package --- agents/artist/src/agent.ts | 6 +----- agents/artist/src/config.ts | 3 --- agents/artist/src/director.ts | 5 ----- agents/artist/src/index.ts | 3 --- agents/artist/src/prompt.ts | 7 +------ agents/artist/src/toolset.ts | 4 ---- 6 files changed, 2 insertions(+), 26 deletions(-) diff --git a/agents/artist/src/agent.ts b/agents/artist/src/agent.ts index 8f9aac155..0da554b30 100644 --- a/agents/artist/src/agent.ts +++ b/agents/artist/src/agent.ts @@ -4,17 +4,13 @@ import { } from "@intx/agent"; import { systemPrompt } from "./prompt.js"; -/** - * Artist ready agent — `agent = defineAgent()` plus the named component parts - * (director/tools/systemPrompt/config) form the whole package surface. - */ export const agent: AgentDefinition = defineAgent(); export function defineAgent(): AgentDefinition { return coreDefineAgent({ id: "artist", systemPrompt: systemPrompt.build(), - tools: [], // tool mounting is consumer/app-side; surface enforced by drift-guard + tools: [], capabilities: [], inference: { sources: [{ provider: "openai", model: "gpt-5" }], diff --git a/agents/artist/src/config.ts b/agents/artist/src/config.ts index f5df7a1fe..7080c5b82 100644 --- a/agents/artist/src/config.ts +++ b/agents/artist/src/config.ts @@ -1,9 +1,6 @@ -/** Artist worker — visual asset specialist. */ export const config = { spawn: { maySpawn: false }, tier: "leaf", - // Preserved from the original in-tree card (behavior wins over the contract - // §5 map; both implement and docs default to medium effort in identity.ts). modelRole: "implement", } as const satisfies { spawn: { maySpawn: boolean }; diff --git a/agents/artist/src/director.ts b/agents/artist/src/director.ts index b42c51d0e..63e02fa4b 100644 --- a/agents/artist/src/director.ts +++ b/agents/artist/src/director.ts @@ -2,11 +2,6 @@ import { tools } from "./toolset.js"; import { systemPrompt } from "./prompt.js"; import { config } from "./config.js"; -/** - * Artist worker director card. Structurally satisfies the app's - * `DirectorPackage` (app-side drift-guard asserts assignability). - * App-independent: imports `@intx/*` types only, no Corbits shared package. - */ export const director = { id: "artist", primaryIntent: diff --git a/agents/artist/src/index.ts b/agents/artist/src/index.ts index 95fc4d646..c2c15f6c6 100644 --- a/agents/artist/src/index.ts +++ b/agents/artist/src/index.ts @@ -3,6 +3,3 @@ export { director } from "./director.js"; export { tools } from "./toolset.js"; export { systemPrompt } from "./prompt.js"; export { config } from "./config.js"; -// No workflow export. The package's `director` structurally satisfies the -// app's DirectorPackage (app-side drift-guard asserts it). No type re-export -// to any Corbits shared package. diff --git a/agents/artist/src/prompt.ts b/agents/artist/src/prompt.ts index bc2e6fe77..02da3e9a3 100644 --- a/agents/artist/src/prompt.ts +++ b/agents/artist/src/prompt.ts @@ -1,5 +1,4 @@ -// Artist raw director card. Byte-stable, single authority — the app formats -// the identity header via formatDirectorSystemPrompt, never this file. +// The app formats the identity header via formatDirectorSystemPrompt. const CARD = `You are ArtistDirector (Artist), a specialist in Corbits Code. @@ -30,10 +29,6 @@ Workflow: OUT OF LANE: non-visual code implementation, backend logic, code defect review, fleet orchestration.`; -/** - * Byte-stable system prompt builder. `theme` is the stable voice identifier; - * `build()` returns the identical raw card on every call (no env/interpolation). - */ export const systemPrompt = { theme: "artist", build: (): string => CARD, diff --git a/agents/artist/src/toolset.ts b/agents/artist/src/toolset.ts index ba25ed12e..fb47a6dd4 100644 --- a/agents/artist/src/toolset.ts +++ b/agents/artist/src/toolset.ts @@ -1,7 +1,3 @@ -// Artist worker: visual asset specialist. -// Hand-crafts SVGs, visual diagrams (Mermaid, ASCII art), and structured -// generative graphic prompts for image generation models. - const ARTIST_TOOLS = [ "read_file", "grep", From 84d7d9c633c1df122288e97b3d4999e25d7423f2 Mon Sep 17 00:00:00 2001 From: "user.email" <sawyer@dirtroad.dev> Date: Thu, 8 Oct 2026 22:21:27 -0700 Subject: [PATCH 5/6] chore(dead-exports): allowlist artist package public surface --- scripts/dead-export-allowlist.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/scripts/dead-export-allowlist.txt b/scripts/dead-export-allowlist.txt index 76623ea68..2769cf3a3 100644 --- a/scripts/dead-export-allowlist.txt +++ b/scripts/dead-export-allowlist.txt @@ -51,3 +51,13 @@ packages/prompt-variance/src/index.ts: FAMILY_IDS packages/prompt-variance/src/index.ts: FAMILY_ROWS packages/prompt-variance/src/index.ts: PromptVarianceFamily packages/prompt-variance/src/index.ts: PromptVarianceRow + +# Agent-package public API (CL-9800 extraction wave): each @corbits/code-agent-* +# workspace package's public surface (agent/defineAgent + the config card) is +# consumed by the app registry/barrel once the fleet merges; on a per-extract +# branch they have no in-repo consumer yet. Public API by design — owned by the +# agent-template lane; remove with the code if the package is deleted. +agents/artist/src/index.ts: agent +agents/artist/src/index.ts: defineAgent +agents/artist/src/config.ts: satisfies +agents/artist/src/config.ts: boolean From 987d150202434ad866bb8ecf2cd1c57e10185808 Mon Sep 17 00:00:00 2001 From: "user.email" <sawyer@dirtroad.dev> Date: Thu, 8 Oct 2026 23:52:48 -0700 Subject: [PATCH 6/6] fix(agent-artist): drop hardcoded inference source and release tag --- agents/artist/src/agent.ts | 5 +---- agents/artist/src/toolset.ts | 4 +--- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/agents/artist/src/agent.ts b/agents/artist/src/agent.ts index 0da554b30..a150b13c9 100644 --- a/agents/artist/src/agent.ts +++ b/agents/artist/src/agent.ts @@ -12,9 +12,6 @@ export function defineAgent(): AgentDefinition { systemPrompt: systemPrompt.build(), tools: [], capabilities: [], - inference: { - sources: [{ provider: "openai", model: "gpt-5" }], - }, - tags: { fleet: "0.3.36", lane: "artist" }, + inference: { sources: [] }, }); } diff --git a/agents/artist/src/toolset.ts b/agents/artist/src/toolset.ts index fb47a6dd4..d8041a3ef 100644 --- a/agents/artist/src/toolset.ts +++ b/agents/artist/src/toolset.ts @@ -1,4 +1,4 @@ -const ARTIST_TOOLS = [ +export const tools: readonly string[] = [ "read_file", "grep", "search_files", @@ -13,5 +13,3 @@ const ARTIST_TOOLS = [ "edit_file", "delete_file", ] as const; - -export const tools: readonly string[] = [...ARTIST_TOOLS];