From 3dce4c8341a88f8f6755125f4b16eb3f9d71dcec Mon Sep 17 00:00:00 2001 From: Sawyer Date: Sun, 4 Oct 2026 23:47:26 -0700 Subject: [PATCH 1/7] feat(warden): ship warden as a workspace agent package Extract @corbits/agent-warden following the agents/explorer precedent (PR #1339): byte-identical prompt, order-identical tools, registry imports the workspace dep, in-tree package.ts deleted with no shim, co-located drift test, tsconfig paths + workspaces dep + bun.lock. Fixes CL-9803 --- agents/warden/package.json | 13 +++++ .../package.ts => agents/warden/src/index.ts | 53 ++++++++++++++++--- bun.lock | 5 ++ src/agent/directors/registry.ts | 2 +- src/agent/directors/warden/package.test.ts | 25 +++++++++ tsconfig.json | 1 + 6 files changed, 90 insertions(+), 9 deletions(-) create mode 100644 agents/warden/package.json rename src/agent/directors/warden/package.ts => agents/warden/src/index.ts (66%) create mode 100644 src/agent/directors/warden/package.test.ts diff --git a/agents/warden/package.json b/agents/warden/package.json new file mode 100644 index 000000000..e4d1221b3 --- /dev/null +++ b/agents/warden/package.json @@ -0,0 +1,13 @@ +{ + "name": "@corbits/agent-warden", + "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/warden/package.ts b/agents/warden/src/index.ts similarity index 66% rename from src/agent/directors/warden/package.ts rename to agents/warden/src/index.ts index 25b598498..dd569a532 100644 --- a/src/agent/directors/warden/package.ts +++ b/agents/warden/src/index.ts @@ -1,11 +1,48 @@ -import type { DirectorPackage } from "../types.js"; -import { REVIEW_TOOLS } from "../tool-sets.js"; - /** * Warden trust-review worker (CL-7657). * Permission / provider-auth / plugin-loader diffs only; findings, never fixes. + * + * Ships as the @corbits/agent-warden 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/warden/package.test.ts. */ -export const wardenPackage: DirectorPackage = { +export type AgentPackage = { + readonly id: "warden"; + readonly primaryIntent: string; + readonly outOfLane: readonly string[]; + readonly description: string; + readonly systemPrompt: string; + /** Unset — warden never attaches skill bodies at spawn. */ + readonly attachedSkills?: readonly string[]; + /** Unset — warden declares no skill scope. */ + readonly optionalSkills?: readonly string[]; + readonly tools: { + readonly allow: readonly string[]; + }; + readonly spawn: { + readonly maySpawn: false; + }; + readonly modelRole: "review"; + readonly tier: "leaf"; +}; + +const WARDEN_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 wardenPackage: AgentPackage = { id: "warden", primaryIntent: "Trust review of permission, provider-auth, and plugin-loader diffs; never fix product code", @@ -16,10 +53,6 @@ export const wardenPackage: DirectorPackage = { "feature design", ], description: "Permission and trust review worker", - tools: { allow: REVIEW_TOOLS }, - spawn: { maySpawn: false }, - tier: "leaf", - modelRole: "review", systemPrompt: `You are WardenDirector (Warden), a specialist in Corbits Code. PRIMARY INTENT: trust review of permission, provider-auth, and plugin-loader diffs. Find trust defects with evidence; never fix product code. Cite path, line or symbol, what breaks, and the concrete input or sequence that triggers it. @@ -45,4 +78,8 @@ OUT OF LANE → refuse or reclassify under Blockers: - implementing fixes (route to coder) - general code review outside trust paths (route to reviewer) - feature requirements or planning (route to planner)`, + tools: { allow: [...WARDEN_TOOLS] }, + spawn: { maySpawn: false }, + tier: "leaf", + modelRole: "review", }; diff --git a/bun.lock b/bun.lock index 2d4d50072..a010e93d7 100644 --- a/bun.lock +++ b/bun.lock @@ -64,6 +64,10 @@ "name": "@corbits/code-agent-dispatch", "version": "0.1.0", }, + "agents/warden": { + "name": "@corbits/agent-warden", + "version": "0.1.0", + }, "packages/first-class-providers": { "name": "@corbits/first-class-providers", "version": "0.1.0", @@ -259,6 +263,7 @@ "@corbits/code-agent-shakespeare": ["@corbits/code-agent-shakespeare@workspace:agents/shakespeare"], "@corbits/code-agent-prober": ["@corbits/code-agent-prober@workspace:agents/prober"], "@corbits/code-agent-dispatch": ["@corbits/code-agent-dispatch@workspace:agents/dispatch"], + "@corbits/agent-warden": ["@corbits/agent-warden@workspace:agents/warden"], "@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/src/agent/directors/registry.ts b/src/agent/directors/registry.ts index 8741a0318..0ad57627e 100644 --- a/src/agent/directors/registry.ts +++ b/src/agent/directors/registry.ts @@ -9,7 +9,7 @@ import { explorerPackage } from "./explorer/package.js"; import { plannerPackage } from "./planner/package.js"; import { qaLeadPackage } from "./qa-lead/package.js"; import { reviewerPackage } from "./reviewer/package.js"; -import { wardenPackage } from "./warden/package.js"; +import { wardenPackage } from "@corbits/agent-warden"; import { formatDirectorSystemPrompt } from "./identity.js"; import { DIRECTOR_IDS, diff --git a/src/agent/directors/warden/package.test.ts b/src/agent/directors/warden/package.test.ts new file mode 100644 index 000000000..775cb538b --- /dev/null +++ b/src/agent/directors/warden/package.test.ts @@ -0,0 +1,25 @@ +import { describe, expect, test } from "bun:test"; + +import { wardenPackage } from "@corbits/agent-warden"; +import { REVIEW_TOOLS } from "../tool-sets.js"; +import { DIRECTOR_REGISTRY } from "../registry.js"; +import type { DirectorPackage } from "../types.js"; + +describe("wardenPackage", () => { + test("workspace package satisfies the director contract and feeds the registry", () => { + const asDirector: DirectorPackage = wardenPackage; + expect(asDirector.id).toBe("warden"); + expect(DIRECTOR_REGISTRY.warden).toBe(wardenPackage); + expect([...wardenPackage.tools.allow]).toEqual([...REVIEW_TOOLS]); + }); + + test("extracted copy stays trust-review-scoped and non-spawning", () => { + expect(wardenPackage.tools.allow).toContain("read_file"); + expect(wardenPackage.tools.allow).toContain("grep"); + expect(wardenPackage.tools.allow).not.toContain("spawn_agent"); + expect(wardenPackage.tools.allow).not.toContain("ask_operator"); + expect(wardenPackage.spawn.maySpawn).toBe(false); + expect(wardenPackage.tier).toBe("leaf"); + expect(wardenPackage.modelRole).toBe("review"); + }); +}); diff --git a/tsconfig.json b/tsconfig.json index 1cb912592..ed07acd98 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,6 +9,7 @@ "@corbits/code-agent-shakespeare": ["./agents/shakespeare/src/index.ts"], "@corbits/code-agent-prober": ["./agents/prober/src/index.ts"], "@corbits/code-agent-dispatch": ["./agents/dispatch/src/index.ts"], + "@corbits/agent-warden": ["./agents/warden/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 73ca891b8130359651bbaf527951b19a4f3da5fe Mon Sep 17 00:00:00 2001 From: Sawyer Cutler Date: Thu, 8 Oct 2026 14:00:19 -0700 Subject: [PATCH 2/7] chore(warden): rename package to @corbits/code-agent-warden --- agents/warden/package.json | 2 +- agents/warden/src/index.ts | 2 +- bun.lock | 5 +++-- package.json | 4 ++++ src/agent/directors/registry.ts | 2 +- src/agent/directors/warden/package.test.ts | 2 +- tsconfig.json | 2 +- 7 files changed, 12 insertions(+), 7 deletions(-) diff --git a/agents/warden/package.json b/agents/warden/package.json index e4d1221b3..f61823571 100644 --- a/agents/warden/package.json +++ b/agents/warden/package.json @@ -1,5 +1,5 @@ { - "name": "@corbits/agent-warden", + "name": "@corbits/code-agent-warden", "version": "0.1.0", "private": true, "type": "module", diff --git a/agents/warden/src/index.ts b/agents/warden/src/index.ts index dd569a532..74549ebdc 100644 --- a/agents/warden/src/index.ts +++ b/agents/warden/src/index.ts @@ -2,7 +2,7 @@ * Warden trust-review worker (CL-7657). * Permission / provider-auth / plugin-loader diffs only; findings, never fixes. * - * Ships as the @corbits/agent-warden workspace package: the tool allowlist + * Ships as the @corbits/code-agent-warden 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/warden/package.test.ts. */ diff --git a/bun.lock b/bun.lock index a010e93d7..c57a1aa13 100644 --- a/bun.lock +++ b/bun.lock @@ -5,6 +5,7 @@ "": { "name": "@corbits/code", "dependencies": { + "@corbits/code-agent-warden": "workspace:*", "@corbits/codex-provider": "0.1.1", "@corbits/oauth-core": "0.2.0", "@corbits/openai-responses": "0.2.1", @@ -65,7 +66,7 @@ "version": "0.1.0", }, "agents/warden": { - "name": "@corbits/agent-warden", + "name": "@corbits/code-agent-warden", "version": "0.1.0", }, "packages/first-class-providers": { @@ -263,7 +264,7 @@ "@corbits/code-agent-shakespeare": ["@corbits/code-agent-shakespeare@workspace:agents/shakespeare"], "@corbits/code-agent-prober": ["@corbits/code-agent-prober@workspace:agents/prober"], "@corbits/code-agent-dispatch": ["@corbits/code-agent-dispatch@workspace:agents/dispatch"], - "@corbits/agent-warden": ["@corbits/agent-warden@workspace:agents/warden"], + "@corbits/code-agent-warden": ["@corbits/code-agent-warden@workspace:agents/warden"], "@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 c427a0851..53d83c099 100644 --- a/package.json +++ b/package.json @@ -86,6 +86,10 @@ "tar": "^7.5.1" }, "dependencies": { +<<<<<<< HEAD +======= + "@corbits/code-agent-warden": "workspace:*", +>>>>>>> 591094cd (chore(warden): rename package to @corbits/code-agent-warden) "@corbits/codex-provider": "0.1.1", "@corbits/oauth-core": "0.2.0", "@corbits/openai-responses": "0.2.1", diff --git a/src/agent/directors/registry.ts b/src/agent/directors/registry.ts index 0ad57627e..e8dfaf4f0 100644 --- a/src/agent/directors/registry.ts +++ b/src/agent/directors/registry.ts @@ -1,6 +1,7 @@ import { director as shakespeareDirector } from "@corbits/code-agent-shakespeare"; import { director as proberDirector } from "@corbits/code-agent-prober"; import { director as dispatchDirector } from "@corbits/code-agent-dispatch"; +import { wardenPackage } from "@corbits/code-agent-warden"; import type { AgentProfile, CapabilityFilter } from "../profile-types.js"; import { director as artistDirector } from "@corbits/code-agent-artist"; import { coderPackage } from "./coder/package.js"; @@ -9,7 +10,6 @@ import { explorerPackage } from "./explorer/package.js"; import { plannerPackage } from "./planner/package.js"; import { qaLeadPackage } from "./qa-lead/package.js"; import { reviewerPackage } from "./reviewer/package.js"; -import { wardenPackage } from "@corbits/agent-warden"; import { formatDirectorSystemPrompt } from "./identity.js"; import { DIRECTOR_IDS, diff --git a/src/agent/directors/warden/package.test.ts b/src/agent/directors/warden/package.test.ts index 775cb538b..699f7637c 100644 --- a/src/agent/directors/warden/package.test.ts +++ b/src/agent/directors/warden/package.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { wardenPackage } from "@corbits/agent-warden"; +import { wardenPackage } from "@corbits/code-agent-warden"; import { REVIEW_TOOLS } from "../tool-sets.js"; import { DIRECTOR_REGISTRY } from "../registry.js"; import type { DirectorPackage } from "../types.js"; diff --git a/tsconfig.json b/tsconfig.json index ed07acd98..10efbac6e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,7 +9,7 @@ "@corbits/code-agent-shakespeare": ["./agents/shakespeare/src/index.ts"], "@corbits/code-agent-prober": ["./agents/prober/src/index.ts"], "@corbits/code-agent-dispatch": ["./agents/dispatch/src/index.ts"], - "@corbits/agent-warden": ["./agents/warden/src/index.ts"], + "@corbits/code-agent-warden": ["./agents/warden/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 29796eb0d3f38b36a8d73089897e6fd3b8a86e6d Mon Sep 17 00:00:00 2001 From: Sawyer Date: Thu, 8 Oct 2026 19:47:12 -0700 Subject: [PATCH 3/7] feat(agent-warden): adopt uniform reusable agent template shape --- agents/warden/README.md | 47 +++++++++++ agents/warden/src/agent.ts | 26 ++++++ agents/warden/src/config.ts | 13 +++ agents/warden/src/director.ts | 27 +++++++ agents/warden/src/index.ts | 94 +++------------------- agents/warden/src/prompt.ts | 37 +++++++++ agents/warden/src/toolset.ts | 22 +++++ agents/warden/tsconfig.json | 7 ++ bun.lock | 1 - package.json | 3 + src/agent/directors/registry.ts | 4 +- src/agent/directors/warden/package.test.ts | 48 ++++++++--- 12 files changed, 229 insertions(+), 100 deletions(-) create mode 100644 agents/warden/README.md create mode 100644 agents/warden/src/agent.ts create mode 100644 agents/warden/src/config.ts create mode 100644 agents/warden/src/director.ts create mode 100644 agents/warden/src/prompt.ts create mode 100644 agents/warden/src/toolset.ts create mode 100644 agents/warden/tsconfig.json diff --git a/agents/warden/README.md b/agents/warden/README.md new file mode 100644 index 000000000..cc69c882e --- /dev/null +++ b/agents/warden/README.md @@ -0,0 +1,47 @@ +# @corbits/code-agent-warden + +## What this is + +A ready-to-go Corbits agent for the **warden** role (`@corbits/code-agent-warden`) +plus its named component parts so a consumer can recreate or remix it. Warden is +the trust-review worker: it reviews permission, provider-auth, and plugin-loader +diffs only, and never fixes product code. + +## Consume (runLocal) + +```ts +import { agent } from "@corbits/code-agent-warden"; +const run = runLocal(defining(agent), env); +``` + +## Consume (deploy runWorkflow / hub / sidecar) + +Hand the same `AgentDefinition` (`agent`) to a workflow, hub, or sidecar. The +package never exports a workflow itself — a workflow _consumes_ `agent`. + +## Remix components + +```ts +import { + director, + tools, + systemPrompt, + config, + defineAgent, +} from "@corbits/code-agent-warden"; + +// Swap components at the consumer side. +defineAgent({ director, tools, systemPrompt, config }); // or spread overrides +``` + +Each of `agent`, `defineAgent`, `director`, `tools`, `systemPrompt`, `config` is a +named, independently importable part. + +## Byte-stability & single authority + +- `systemPrompt.build()` is pure and byte-stable — identical string every call. +- `tools` is the literal expansion of the app's `REVIEW_TOOLS` surface constant + (`src/agent/directors/tool-sets.ts`); the in-tree drift-guard + (`src/agent/directors/warden/package.test.ts`) enforces they match. +- This package is the single prompt authority for warden; the in-tree + `src/agent/directors/warden/package.ts` is deleted. diff --git a/agents/warden/src/agent.ts b/agents/warden/src/agent.ts new file mode 100644 index 000000000..b84385070 --- /dev/null +++ b/agents/warden/src/agent.ts @@ -0,0 +1,26 @@ +// Warden assembled agent — ready unit + package defineAgent wrapper. +// Calls `@intx/agent`'s `defineAgent` directly (no Corbits bridge/helper layer). +// Tool mounting is consumer/app-side: `tools` here is [] (the allowlist surface +// is exported from `./toolset.js` and wired by the app harness). + +import { + defineAgent as coreDefineAgent, + type AgentDefinition, +} from "@intx/agent"; + +import { systemPrompt } from "./prompt.js"; + +/** The assembled warden agent — ready to hand to `runLocal` / `runWorkflow`. */ +export const agent: AgentDefinition = defineAgent(); + +/** Package convenience wrapper → `AgentDefinition` for `runLocal` authoring. */ +export function defineAgent(): AgentDefinition { + return coreDefineAgent({ + id: "warden", + systemPrompt: systemPrompt.build(), + tools: [], + capabilities: [], + inference: { sources: [] }, + tags: { fleet: "0.3.36", lane: "warden" }, + }); +} diff --git a/agents/warden/src/config.ts b/agents/warden/src/config.ts new file mode 100644 index 000000000..eeb2be03d --- /dev/null +++ b/agents/warden/src/config.ts @@ -0,0 +1,13 @@ +// Warden config — uniform `{ spawn, tier, modelRole }` shape (§5). +// warden is a leaf trust-review worker: maySpawn false, no allowlist. +export const config = { + spawn: { + maySpawn: false, + }, + tier: "leaf", + modelRole: "review", +} as const satisfies { + spawn: { maySpawn: boolean; allowlist?: readonly string[] }; + tier: string; + modelRole: string; +}; diff --git a/agents/warden/src/director.ts b/agents/warden/src/director.ts new file mode 100644 index 000000000..7db1bec81 --- /dev/null +++ b/agents/warden/src/director.ts @@ -0,0 +1,27 @@ +// Warden director card — the `DirectorPackage` data, extracted byte-for-byte +// from the in-tree `src/agent/directors/warden/package.ts` (now deleted). +// Structurally satisfies the app's `DirectorPackage` (asserted in-tree by +// `src/agent/directors/warden/package.test.ts`); it imports @intx/* only. + +import { tools } from "./toolset.js"; +import { systemPrompt } from "./prompt.js"; +import { config } from "./config.js"; + +/** The assembled warden director card. */ +export const director = { + id: "warden", + primaryIntent: + "Trust review of permission, provider-auth, and plugin-loader diffs; never fix product code", + outOfLane: [ + "implementing fixes", + "general code review outside trust paths", + "architecture judgment without trust evidence", + "feature design", + ], + description: "Permission and trust review worker", + systemPrompt: systemPrompt.build(), + tools: { allow: tools }, + spawn: config.spawn, + modelRole: config.modelRole, + tier: config.tier, +} as const; diff --git a/agents/warden/src/index.ts b/agents/warden/src/index.ts index 74549ebdc..bd370bcbb 100644 --- a/agents/warden/src/index.ts +++ b/agents/warden/src/index.ts @@ -1,85 +1,9 @@ -/** - * Warden trust-review worker (CL-7657). - * Permission / provider-auth / plugin-loader diffs only; findings, never fixes. - * - * Ships as the @corbits/code-agent-warden 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/warden/package.test.ts. - */ -export type AgentPackage = { - readonly id: "warden"; - readonly primaryIntent: string; - readonly outOfLane: readonly string[]; - readonly description: string; - readonly systemPrompt: string; - /** Unset — warden never attaches skill bodies at spawn. */ - readonly attachedSkills?: readonly string[]; - /** Unset — warden declares no skill scope. */ - readonly optionalSkills?: readonly string[]; - readonly tools: { - readonly allow: readonly string[]; - }; - readonly spawn: { - readonly maySpawn: false; - }; - readonly modelRole: "review"; - readonly tier: "leaf"; -}; - -const WARDEN_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 wardenPackage: AgentPackage = { - id: "warden", - primaryIntent: - "Trust review of permission, provider-auth, and plugin-loader diffs; never fix product code", - outOfLane: [ - "implementing fixes", - "general code review outside trust paths", - "architecture judgment without trust evidence", - "feature design", - ], - description: "Permission and trust review worker", - systemPrompt: `You are WardenDirector (Warden), a specialist in Corbits Code. - -PRIMARY INTENT: trust review of permission, provider-auth, and plugin-loader diffs. Find trust defects with evidence; never fix product code. Cite path, line or symbol, what breaks, and the concrete input or sequence that triggers it. - -TRIGGER — written paths only. Review only when the diff touches permission, provider-auth, or plugin-loader code. Anything else is out of lane: say so under Blockers and stop. Do not expand into general code review. - -You are the trust lane only — not an implementer, not an explorer, not an orchestrator. Do not ship fixes. Do not become Reviewer (general defects) or Planner as your primary job. - -Findings lens — rank each as blocking, should-fix, or file-for-later: -- grant-matching holes (permission grants that over- or under-match the request) -- secret-guard bypass (secrets or credentials reachable past the guard) -- arktype boundary skips (unvalidated input crossing a trust boundary) -- shell-policy peel gaps (shell policy peeled or bypassed by a wrapper layer) -- plugin trust (untrusted plugin code gaining capability it was not granted) - -Evidence rules: -- Every claim needs path + line/symbol + reproduction shape (input, sequence, missing branch). -- "This is genuinely fine" is a valid finding when true. -- Call out gaps: what you did not cover so the parent does not assume closed. -- Recommend permanent regression tests that Coder should land. - -OUT OF LANE → refuse or reclassify under Blockers: -- implementing fixes (route to coder) -- general code review outside trust paths (route to reviewer) -- feature requirements or planning (route to planner)`, - tools: { allow: [...WARDEN_TOOLS] }, - spawn: { maySpawn: false }, - tier: "leaf", - modelRole: "review", -}; +// Public surface — re-exports only (no logic). Exports exactly +// `agent, defineAgent, director, tools, systemPrompt, config`. No `workflow` +// export. No Corbits shared package is re-exported; the package's `director` +// structurally satisfies the app's `DirectorPackage` (app-side drift-guard). +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"; diff --git a/agents/warden/src/prompt.ts b/agents/warden/src/prompt.ts new file mode 100644 index 000000000..d4802bbcb --- /dev/null +++ b/agents/warden/src/prompt.ts @@ -0,0 +1,37 @@ +// Warden card — the single prompt authority, extracted byte-for-byte from the +// in-tree `src/agent/directors/warden/package.ts` (now deleted). `build()` is +// pure and byte-stable: it returns an identical string on every call. +const CARD = `You are WardenDirector (Warden), a specialist in Corbits Code. + +PRIMARY INTENT: trust review of permission, provider-auth, and plugin-loader diffs. Find trust defects with evidence; never fix product code. Cite path, line or symbol, what breaks, and the concrete input or sequence that triggers it. + +TRIGGER — written paths only. Review only when the diff touches permission, provider-auth, or plugin-loader code. Anything else is out of lane: say so under Blockers and stop. Do not expand into general code review. + +You are the trust lane only — not an implementer, not an explorer, not an orchestrator. Do not ship fixes. Do not become Reviewer (general defects) or Planner as your primary job. + +Findings lens — rank each as blocking, should-fix, or file-for-later: +- grant-matching holes (permission grants that over- or under-match the request) +- secret-guard bypass (secrets or credentials reachable past the guard) +- arktype boundary skips (unvalidated input crossing a trust boundary) +- shell-policy peel gaps (shell policy peeled or bypassed by a wrapper layer) +- plugin trust (untrusted plugin code gaining capability it was not granted) + +Evidence rules: +- Every claim needs path + line/symbol + reproduction shape (input, sequence, missing branch). +- "This is genuinely fine" is a valid finding when true. +- Call out gaps: what you did not cover so the parent does not assume closed. +- Recommend permanent regression tests that Coder should land. + +OUT OF LANE → refuse or reclassify under Blockers: +- implementing fixes (route to coder) +- general code review outside trust paths (route to reviewer) +- feature requirements or planning (route to planner)`; + +/** Stable identifier of the package's voice. */ +export const theme = "warden"; + +/** Byte-stable builder: returns the raw warden card, identical every call. */ +export const systemPrompt = { + theme, + build: (): string => CARD, +}; diff --git a/agents/warden/src/toolset.ts b/agents/warden/src/toolset.ts new file mode 100644 index 000000000..d6e31d7ab --- /dev/null +++ b/agents/warden/src/toolset.ts @@ -0,0 +1,22 @@ +// Warden trust-review: review surface (read + product writes) — REVIEW_TOOLS. +// Literal expansion of the `REVIEW_TOOLS` constant in +// `src/agent/directors/tool-sets.ts` (the single tool authority). Drift is +// enforced by the in-tree `src/agent/directors/warden/package.test.ts`. +const REVIEW_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; + +/** The warden tool allowlist — literal equal to the in-tree `REVIEW_TOOLS`. */ +export const tools: readonly string[] = [...REVIEW_TOOLS]; diff --git a/agents/warden/tsconfig.json b/agents/warden/tsconfig.json new file mode 100644 index 000000000..0d7100cbc --- /dev/null +++ b/agents/warden/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 c57a1aa13..46e1bed4f 100644 --- a/bun.lock +++ b/bun.lock @@ -5,7 +5,6 @@ "": { "name": "@corbits/code", "dependencies": { - "@corbits/code-agent-warden": "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 53d83c099..5697d8bdd 100644 --- a/package.json +++ b/package.json @@ -87,9 +87,12 @@ }, "dependencies": { <<<<<<< HEAD +<<<<<<< HEAD ======= "@corbits/code-agent-warden": "workspace:*", >>>>>>> 591094cd (chore(warden): rename package to @corbits/code-agent-warden) +======= +>>>>>>> 624db538 (feat(agent-warden): adopt uniform reusable agent template shape) "@corbits/codex-provider": "0.1.1", "@corbits/oauth-core": "0.2.0", "@corbits/openai-responses": "0.2.1", diff --git a/src/agent/directors/registry.ts b/src/agent/directors/registry.ts index e8dfaf4f0..ddf5fc0b3 100644 --- a/src/agent/directors/registry.ts +++ b/src/agent/directors/registry.ts @@ -1,7 +1,7 @@ import { director as shakespeareDirector } from "@corbits/code-agent-shakespeare"; import { director as proberDirector } from "@corbits/code-agent-prober"; import { director as dispatchDirector } from "@corbits/code-agent-dispatch"; -import { wardenPackage } from "@corbits/code-agent-warden"; +import { director as wardenDirector } from "@corbits/code-agent-warden"; import type { AgentProfile, CapabilityFilter } from "../profile-types.js"; import { director as artistDirector } from "@corbits/code-agent-artist"; import { coderPackage } from "./coder/package.js"; @@ -44,7 +44,7 @@ export const DIRECTOR_REGISTRY: Readonly> = reviewer: reviewerPackage, designer: designerPackage, artist: artistDirector, - warden: wardenPackage, + warden: wardenDirector, shakespeare: shakespeareDirector, prober: proberDirector, "qa-lead": qaLeadPackage, diff --git a/src/agent/directors/warden/package.test.ts b/src/agent/directors/warden/package.test.ts index 699f7637c..0d906042f 100644 --- a/src/agent/directors/warden/package.test.ts +++ b/src/agent/directors/warden/package.test.ts @@ -1,25 +1,49 @@ import { describe, expect, test } from "bun:test"; -import { wardenPackage } from "@corbits/code-agent-warden"; +import { + director, + tools, + config, + systemPrompt, +} from "@corbits/code-agent-warden"; import { REVIEW_TOOLS } from "../tool-sets.js"; import { DIRECTOR_REGISTRY } from "../registry.js"; import type { DirectorPackage } from "../types.js"; describe("wardenPackage", () => { test("workspace package satisfies the director contract and feeds the registry", () => { - const asDirector: DirectorPackage = wardenPackage; + const asDirector: DirectorPackage = director; expect(asDirector.id).toBe("warden"); - expect(DIRECTOR_REGISTRY.warden).toBe(wardenPackage); - expect([...wardenPackage.tools.allow]).toEqual([...REVIEW_TOOLS]); + expect(DIRECTOR_REGISTRY.warden).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 trust-review-scoped and non-spawning", () => { - expect(wardenPackage.tools.allow).toContain("read_file"); - expect(wardenPackage.tools.allow).toContain("grep"); - expect(wardenPackage.tools.allow).not.toContain("spawn_agent"); - expect(wardenPackage.tools.allow).not.toContain("ask_operator"); - expect(wardenPackage.spawn.maySpawn).toBe(false); - expect(wardenPackage.tier).toBe("leaf"); - expect(wardenPackage.modelRole).toBe("review"); + 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); + expect(director.tier).toBe("leaf"); + expect(director.modelRole).toBe("review"); + }); + + test("prompt authority is byte-stable", () => { + expect(director.systemPrompt).toBe(systemPrompt.build()); + expect(systemPrompt.build()).toBe(systemPrompt.build()); + }); + + test("tools surface matches REVIEW_TOOLS 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); }); }); From 9c4253ce63bb245f754f7847391369b77fbf65ba Mon Sep 17 00:00:00 2001 From: Sawyer Date: Thu, 8 Oct 2026 20:21:49 -0700 Subject: [PATCH 4/7] style(agent-warden): strip redundant commentary from extracted package --- agents/warden/src/agent.ts | 7 ------- agents/warden/src/config.ts | 3 +-- agents/warden/src/director.ts | 6 ------ agents/warden/src/index.ts | 4 ---- agents/warden/src/prompt.ts | 7 ++----- agents/warden/src/toolset.ts | 6 +----- 6 files changed, 4 insertions(+), 29 deletions(-) diff --git a/agents/warden/src/agent.ts b/agents/warden/src/agent.ts index b84385070..550e36bef 100644 --- a/agents/warden/src/agent.ts +++ b/agents/warden/src/agent.ts @@ -1,8 +1,3 @@ -// Warden assembled agent — ready unit + package defineAgent wrapper. -// Calls `@intx/agent`'s `defineAgent` directly (no Corbits bridge/helper layer). -// Tool mounting is consumer/app-side: `tools` here is [] (the allowlist surface -// is exported from `./toolset.js` and wired by the app harness). - import { defineAgent as coreDefineAgent, type AgentDefinition, @@ -10,10 +5,8 @@ import { import { systemPrompt } from "./prompt.js"; -/** The assembled warden agent — ready to hand to `runLocal` / `runWorkflow`. */ export const agent: AgentDefinition = defineAgent(); -/** Package convenience wrapper → `AgentDefinition` for `runLocal` authoring. */ export function defineAgent(): AgentDefinition { return coreDefineAgent({ id: "warden", diff --git a/agents/warden/src/config.ts b/agents/warden/src/config.ts index eeb2be03d..566d4d3aa 100644 --- a/agents/warden/src/config.ts +++ b/agents/warden/src/config.ts @@ -1,5 +1,4 @@ -// Warden config — uniform `{ spawn, tier, modelRole }` shape (§5). -// warden is a leaf trust-review worker: maySpawn false, no allowlist. +// Warden is a leaf trust-review worker: maySpawn false, no allowlist. export const config = { spawn: { maySpawn: false, diff --git a/agents/warden/src/director.ts b/agents/warden/src/director.ts index 7db1bec81..0d73ea35c 100644 --- a/agents/warden/src/director.ts +++ b/agents/warden/src/director.ts @@ -1,13 +1,7 @@ -// Warden director card — the `DirectorPackage` data, extracted byte-for-byte -// from the in-tree `src/agent/directors/warden/package.ts` (now deleted). -// Structurally satisfies the app's `DirectorPackage` (asserted in-tree by -// `src/agent/directors/warden/package.test.ts`); it imports @intx/* only. - import { tools } from "./toolset.js"; import { systemPrompt } from "./prompt.js"; import { config } from "./config.js"; -/** The assembled warden director card. */ export const director = { id: "warden", primaryIntent: diff --git a/agents/warden/src/index.ts b/agents/warden/src/index.ts index bd370bcbb..c2c15f6c6 100644 --- a/agents/warden/src/index.ts +++ b/agents/warden/src/index.ts @@ -1,7 +1,3 @@ -// Public surface — re-exports only (no logic). Exports exactly -// `agent, defineAgent, director, tools, systemPrompt, config`. No `workflow` -// export. No Corbits shared package is re-exported; the package's `director` -// structurally satisfies the app's `DirectorPackage` (app-side drift-guard). export { agent, defineAgent } from "./agent.js"; export { director } from "./director.js"; export { tools } from "./toolset.js"; diff --git a/agents/warden/src/prompt.ts b/agents/warden/src/prompt.ts index d4802bbcb..ebadb65af 100644 --- a/agents/warden/src/prompt.ts +++ b/agents/warden/src/prompt.ts @@ -1,6 +1,4 @@ -// Warden card — the single prompt authority, extracted byte-for-byte from the -// in-tree `src/agent/directors/warden/package.ts` (now deleted). `build()` is -// pure and byte-stable: it returns an identical string on every call. +// Warden card — the single prompt authority. `build()` is byte-stable. const CARD = `You are WardenDirector (Warden), a specialist in Corbits Code. PRIMARY INTENT: trust review of permission, provider-auth, and plugin-loader diffs. Find trust defects with evidence; never fix product code. Cite path, line or symbol, what breaks, and the concrete input or sequence that triggers it. @@ -27,10 +25,9 @@ OUT OF LANE → refuse or reclassify under Blockers: - general code review outside trust paths (route to reviewer) - feature requirements or planning (route to planner)`; -/** Stable identifier of the package's voice. */ export const theme = "warden"; -/** Byte-stable builder: returns the raw warden card, identical every call. */ +// Byte-stable (see prompt authority test). export const systemPrompt = { theme, build: (): string => CARD, diff --git a/agents/warden/src/toolset.ts b/agents/warden/src/toolset.ts index d6e31d7ab..e04485155 100644 --- a/agents/warden/src/toolset.ts +++ b/agents/warden/src/toolset.ts @@ -1,7 +1,4 @@ -// Warden trust-review: review surface (read + product writes) — REVIEW_TOOLS. -// Literal expansion of the `REVIEW_TOOLS` constant in -// `src/agent/directors/tool-sets.ts` (the single tool authority). Drift is -// enforced by the in-tree `src/agent/directors/warden/package.test.ts`. +// REVIEW_TOOLS literal; drift-guarded against src/agent/directors/tool-sets.ts. const REVIEW_TOOLS = [ "read_file", "grep", @@ -18,5 +15,4 @@ const REVIEW_TOOLS = [ "delete_file", ] as const; -/** The warden tool allowlist — literal equal to the in-tree `REVIEW_TOOLS`. */ export const tools: readonly string[] = [...REVIEW_TOOLS]; From 3f6982facd1f2d81468c266e457a78aaf1e6f088 Mon Sep 17 00:00:00 2001 From: "user.email" Date: Thu, 8 Oct 2026 22:22:02 -0700 Subject: [PATCH 5/7] chore(dead-exports): allowlist cl-9803-extract-corbits-agent-warden package public surface --- scripts/dead-export-allowlist.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/dead-export-allowlist.txt b/scripts/dead-export-allowlist.txt index 03b4b8571..0c6bcaf8f 100644 --- a/scripts/dead-export-allowlist.txt +++ b/scripts/dead-export-allowlist.txt @@ -47,6 +47,10 @@ agents/dispatch/src/index.ts: agent agents/dispatch/src/index.ts: defineAgent agents/dispatch/src/config.ts: satisfies agents/dispatch/src/config.ts: boolean +agents/warden/src/index.ts: agent +agents/warden/src/index.ts: defineAgent +agents/warden/src/config.ts: satisfies +agents/warden/src/config.ts: boolean # Versioned prompt-variance package public surface (CL-8269 lane, # agent-owned). Family rows data re-exported through the package entry point; From b7eab608fda703c8c49bf6e4bb7f21e05a66384d Mon Sep 17 00:00:00 2001 From: "user.email" Date: Thu, 8 Oct 2026 23:52:07 -0700 Subject: [PATCH 6/7] fix(agent-warden): drop hardcoded inference source and release tag --- agents/warden/src/agent.ts | 1 - agents/warden/src/toolset.ts | 4 +--- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/agents/warden/src/agent.ts b/agents/warden/src/agent.ts index 550e36bef..f0bc34894 100644 --- a/agents/warden/src/agent.ts +++ b/agents/warden/src/agent.ts @@ -14,6 +14,5 @@ export function defineAgent(): AgentDefinition { tools: [], capabilities: [], inference: { sources: [] }, - tags: { fleet: "0.3.36", lane: "warden" }, }); } diff --git a/agents/warden/src/toolset.ts b/agents/warden/src/toolset.ts index e04485155..4a230a9af 100644 --- a/agents/warden/src/toolset.ts +++ b/agents/warden/src/toolset.ts @@ -1,5 +1,5 @@ // REVIEW_TOOLS literal; drift-guarded against src/agent/directors/tool-sets.ts. -const REVIEW_TOOLS = [ +export const tools = [ "read_file", "grep", "search_files", @@ -14,5 +14,3 @@ const REVIEW_TOOLS = [ "edit_file", "delete_file", ] as const; - -export const tools: readonly string[] = [...REVIEW_TOOLS]; From 154c2a90ba0ea5e9d5656958031381da14ea2050 Mon Sep 17 00:00:00 2001 From: "user.email" Date: Fri, 9 Oct 2026 00:11:52 -0700 Subject: [PATCH 7/7] fix(agent-warden): repair corrupted root package.json after rebase --- package.json | 7 ------- 1 file changed, 7 deletions(-) diff --git a/package.json b/package.json index 5697d8bdd..c427a0851 100644 --- a/package.json +++ b/package.json @@ -86,13 +86,6 @@ "tar": "^7.5.1" }, "dependencies": { -<<<<<<< HEAD -<<<<<<< HEAD -======= - "@corbits/code-agent-warden": "workspace:*", ->>>>>>> 591094cd (chore(warden): rename package to @corbits/code-agent-warden) -======= ->>>>>>> 624db538 (feat(agent-warden): adopt uniform reusable agent template shape) "@corbits/codex-provider": "0.1.1", "@corbits/oauth-core": "0.2.0", "@corbits/openai-responses": "0.2.1",