diff --git a/apps/ui/src/agent-state.test.ts b/apps/ui/src/agent-state.test.ts index 94c853ea..872d71b9 100644 --- a/apps/ui/src/agent-state.test.ts +++ b/apps/ui/src/agent-state.test.ts @@ -6,8 +6,8 @@ import type { AgentState } from "./stub-data"; // agent-state.ts is the pure D9 projection: it maps the daemon's coarse, // authoritative `AgentSessionState` (compass.v1, #443) plus optional stream // refinements onto the fine-grained UI dot. These tests pin the projection -// row-by-row so a future edit to the switch, a leaked refinement, or a reorder -// of the `wardenPaused` override can't silently render the wrong dot. +// row-by-row so a future edit to the switch or a leaked refinement can't +// silently render the wrong dot. // The complete UI dot union (stub-data AgentState) as a membership table. // Enumerated on purpose: the return-type guard below asserts every branch lands @@ -131,51 +131,6 @@ describe("turnDoneUnopened refinement (READY → done)", () => { }); }); -describe("wardenPaused override (precedence)", () => { - // The strongest contract: a Warden pause is a Compass overlay that wins over - // the enum regardless of what the session was doing. `wardenPaused` is the - // first check in the function; moving it below the switch (so a WORKING/READY - // session returned early) would redden every row here. - for (const state of ALL_SESSION_STATES) { - test(`paused wins for ${AgentSessionState[state]}`, () => { - expect(agentDotState(state, { wardenPaused: true })).toBe("paused"); - }); - } - - // Precedence over the other refinements: pause beats an open ask and an - // unopened-done turn. If the override were reordered after the refinement - // branches, these would resolve to waiting/done instead. - test("paused beats awaitingInput", () => { - expect( - agentDotState(AgentSessionState.WORKING, { - wardenPaused: true, - awaitingInput: true, - }), - ).toBe("paused"); - }); - - test("paused beats turnDoneUnopened", () => { - expect( - agentDotState(AgentSessionState.READY, { - wardenPaused: true, - turnDoneUnopened: true, - }), - ).toBe("paused"); - }); - - // A falsy wardenPaused must NOT trigger the override — the enum mapping still - // governs. Guards against `if (refinement.wardenPaused !== undefined)` or a - // truthiness slip that treats an explicit `false` as a pause. - test("wardenPaused:false does not override the enum mapping", () => { - expect( - agentDotState(AgentSessionState.WORKING, { wardenPaused: false }), - ).toBe("working"); - expect( - agentDotState(AgentSessionState.READY, { wardenPaused: false }), - ).toBe("idle"); - }); -}); - describe("return type is always a valid AgentState", () => { // Totality guard: across every enum value and a spread of refinement combos, // the result is one of the seven union members. Catches a future branch that @@ -185,8 +140,6 @@ describe("return type is always a valid AgentState", () => { {}, { awaitingInput: true }, { turnDoneUnopened: true }, - { wardenPaused: true }, - { awaitingInput: true, turnDoneUnopened: true, wardenPaused: true }, ]; for (const state of ALL_SESSION_STATES) { diff --git a/apps/ui/src/agent-state.ts b/apps/ui/src/agent-state.ts index feb81e9d..4e549526 100644 --- a/apps/ui/src/agent-state.ts +++ b/apps/ui/src/agent-state.ts @@ -26,10 +26,6 @@ export interface AgentStreamRefinement { /** The agent completed a turn and no human has opened its view yet. Refines * `READY` → `done` (emerald check, deliberately not idle grey). */ turnDoneUnopened?: boolean; - /** A Warden security-pause is in force (compass-0.4 `pause_agent`) — a - * Compass overlay, not an ACP/`AgentSessionState` value. Wins over the enum - * mapping while set. */ - wardenPaused?: boolean; } /** @@ -47,15 +43,11 @@ export interface AgentStreamRefinement { * | UNSPECIFIED | idle (defensive; a well-behaved daemon never | * | | sends it as a live state) | * - * `wardenPaused` overrides to `paused` regardless of the enum, since a pause is - * a Compass overlay applied on top of whatever the session was doing. */ export function agentDotState( sessionState: AgentSessionState, refinement: AgentStreamRefinement = {}, ): AgentState { - if (refinement.wardenPaused) return "paused"; - switch (sessionState) { case AgentSessionState.STARTING: case AgentSessionState.WORKING: diff --git a/apps/ui/src/app.css b/apps/ui/src/app.css index aa4d7915..1c3b7de8 100644 --- a/apps/ui/src/app.css +++ b/apps/ui/src/app.css @@ -1,7 +1,7 @@ /* Compass ADE — dev UI styling. Dark, dense, board-first. An Orca-inspired * shell: a left folder tree of agents, a central Bridge (swimlane board) or * agent (ACP + terminals) view, and a right sidebar carrying the fleet - * conversations (Supervisor · Warden · Status) above the issue files/VCS/PR + * conversations (Supervisor · Status) above the issue files/VCS/PR * tabs, plus a bottom usage bar. All read one store. */ :root { @@ -528,9 +528,6 @@ button { .role-pip[data-role="supervisor"] { color: var(--accent); } -.role-pip[data-role="warden"] { - color: var(--purple); -} /* ── Main area ──────────────────────────────────────────────────────────── */ diff --git a/apps/ui/src/comms-stub.ts b/apps/ui/src/comms-stub.ts index 252f103d..16dc3e72 100644 --- a/apps/ui/src/comms-stub.ts +++ b/apps/ui/src/comms-stub.ts @@ -427,14 +427,6 @@ export const STUB_TOPICS: Topic[] = [ createdByAccountId: "acc-supervisor", archived: false, }, - { - id: "top-dm-warden", - channelId: "dm-warden", - name: "general", - createdAtUnixMs: min(69), - createdByAccountId: "acc-warden", - archived: false, - }, ]; export const STUB_MESSAGES: Message[] = [ @@ -623,7 +615,7 @@ export const STUB_MESSAGES: Message[] = [ blocks: [ { kind: "text", - text: "Fleet snapshot: cook + livingstone in review, cousteau waiting on a merge gate, warden holding the sandbox lane. No collisions on the compass-ui zone right now.", + text: "Fleet snapshot: cook + livingstone in review, cousteau waiting on a merge gate. No collisions on the compass-ui zone right now.", }, ], }, @@ -689,41 +681,6 @@ export const STUB_MESSAGES: Message[] = [ }, ], }, - - // ── DM: matt <-> warden ── - { - id: "msg-dm-war1", - topicId: "top-dm-warden", - authorAccountId: "acc-warden", - atUnixMs: min(70), - blocks: [ - { - kind: "text", - text: "Sandbox policy check: every worker is confined to its own clone under ~/agents/workspaces. No writes to main, allowlisted owners only.", - }, - ], - }, - { - id: "msg-dm-war2", - topicId: "top-dm-warden", - authorAccountId: MATT, - atUnixMs: min(73), - blocks: [ - { kind: "text", text: "Flag anything that reaches outside its lane." }, - ], - }, - { - id: "msg-dm-war3", - topicId: "top-dm-warden", - authorAccountId: "acc-warden", - atUnixMs: min(75), - blocks: [ - { - kind: "text", - text: "Will do — no boundary crossings observed this cycle.", - }, - ], - }, ]; /** The fixture as a `CommsState` — the shape `createAppStore` takes as diff --git a/apps/ui/src/components/AgentView.test.tsx b/apps/ui/src/components/AgentView.test.tsx index 55c44b02..dbf7ef24 100644 --- a/apps/ui/src/components/AgentView.test.tsx +++ b/apps/ui/src/components/AgentView.test.tsx @@ -190,7 +190,7 @@ describe("AgentView (T3)", () => { // a rendered placeholder — so every one would FAIL against the disabled variant. // // Fixture ground truth (verified from stub-data.ts STUB_AGENTS, quoted here): -// - acc-supervisor / acc-warden: `terminals: []` — ZERO fixture terminals, so +// - acc-supervisor: `terminals: []` — ZERO fixture terminals, so // `nextFreeTerminalPane` returns undefined from the first "+" click. The old // code disabled "+" immediately for them → the cleanest always-open proof. // - acc-cook: terminals `t-c1` + `t-c2` (2) — exhausted after two opens. @@ -203,9 +203,8 @@ describe("AgentView always-open '+'/split (regression)", () => { return agent.terminals.length; }; - test("fixture ground truth: supervisor/warden have zero terminals, cook has two", () => { + test("fixture ground truth: supervisor has zero terminals, cook has two", () => { expect(agentTerminalCount("acc-supervisor")).toBe(0); - expect(agentTerminalCount("acc-warden")).toBe(0); expect(agentTerminalCount("acc-cook")).toBe(2); }); @@ -294,10 +293,10 @@ describe("AgentView always-open '+'/split (regression)", () => { // disabled the split buttons the moment `nextFreeTerminalPane` was undefined. test("split stays open after fixtures: clicking a split button grows the tree with a placeholder pane", () => { const { store, container } = mountAgentView(); - store.openAgent("acc-warden"); + store.openAgent("acc-supervisor"); - // Open the warden's first (minted) terminal tab so its pane shows split - // buttons — warden has zero fixtures, so this pane is itself a placeholder. + // Open the supervisor's first (minted) terminal tab so its pane shows split + // buttons — supervisor has zero fixtures, so this pane is itself a placeholder. const newTab = container.querySelector(".av-tab-new"); if (!newTab) throw new Error("'+' new-tab button not rendered"); fireEvent.click(newTab); diff --git a/apps/ui/src/components/LeftSidebar.tsx b/apps/ui/src/components/LeftSidebar.tsx index 6e6b4437..d56a033c 100644 --- a/apps/ui/src/components/LeftSidebar.tsx +++ b/apps/ui/src/components/LeftSidebar.tsx @@ -48,7 +48,7 @@ const AgentLeaf: Component<{ agent: Agent; badge?: number }> = (props) => { {a().account.handle} - {a().role === "supervisor" ? "◆" : "🛡"} + ◆ diff --git a/apps/ui/src/components/RightSidebar.fleetpane.test.tsx b/apps/ui/src/components/RightSidebar.fleetpane.test.tsx index 95d71143..8bb08354 100644 --- a/apps/ui/src/components/RightSidebar.fleetpane.test.tsx +++ b/apps/ui/src/components/RightSidebar.fleetpane.test.tsx @@ -12,7 +12,7 @@ import { testQueryClient } from "../test-support"; import { RightSidebar } from "./RightSidebar"; // Render acceptance spec for the compass-0.7 fleet pane (design compass-0.7, -// FleetPane in RightSidebar.tsx). A fleet tab (Supervisor · Warden) used to +// FleetPane in RightSidebar.tsx). A fleet tab (Supervisor · Cook) used to // render CONTROL-ONLY — just a button into the agent's workspace. It now renders // the agent's home-DM conversation INLINE above a compact "Open workspace" // control, and — per Matt's kill-the-gate ruling (2026-07-20) — any ask in that @@ -54,11 +54,11 @@ function mountRightSidebar(): { store: AppStore; container: HTMLElement } { // The two visible fixture agents whose home-DM the fleet pane renders. The fleet // tabs are CONFIGURABLE PINS keyed `agent:${accountId}` (Record A §T2), not a -// hardcoded Supervisor · Warden pair. The pane arm reads the active tab's item +// hardcoded Supervisor · Cook pair. The pane arm reads the active tab's item // out of `rightTabGroups()` (SEA-1645 P2), which emits only PINNED agents, so a // test must pin the agent before activating its tab. Both ids resolve in the // fixture, so once pinned the pane renders their home-DM inline. -const FLEET_TABS = ["acc-supervisor", "acc-warden"] as const; +const FLEET_TABS = ["acc-supervisor", "acc-cook"] as const; // The agent account's home-DM channel id — resolved through the SAME account set // the store exposes (STUB_ACCOUNTS carries agent accounts with homeChannelId), @@ -191,8 +191,8 @@ describe("RightSidebar fleet pane (compass-0.7)", () => { // stops resolving a live agent. test("a resolved fleet tab renders the live pane, not the unreachable block", () => { const { store, container } = mountRightSidebar(); - store.pinAgent("acc-warden"); - store.setActiveRightTab("agent:acc-warden"); + store.pinAgent("acc-cook"); + store.setActiveRightTab("agent:acc-cook"); expect(container.querySelector(".fleet-pane")).not.toBeNull(); expect(container.querySelector(".fleet-unreachable")).toBeNull(); diff --git a/apps/ui/src/components/RightSidebar.test.ts b/apps/ui/src/components/RightSidebar.test.ts index 106cd462..9bc34ebc 100644 --- a/apps/ui/src/components/RightSidebar.test.ts +++ b/apps/ui/src/components/RightSidebar.test.ts @@ -146,7 +146,7 @@ describe("rightTabGroups() derivation (Record A §T2)", () => { // The two visible fixture agents to pin — both resolve in STUB_AGENTS, so the // derivation must surface a fleet item for each, in pin order. const SUP = "acc-supervisor"; - const WARDEN = "acc-warden"; + const LIVINGSTONE = "acc-livingstone"; // Fleet must sit ABOVE issue (D2). A swapped order renders the bar upside-down. test("orders the groups fleet-first, issue-second", () => { @@ -164,7 +164,7 @@ describe("rightTabGroups() derivation (Record A §T2)", () => { const ids = groups.flatMap((g) => g.items.map((item) => item.id)); expect(ids).toEqual([ `agent:${SUP}`, - `agent:${WARDEN}`, + `agent:${LIVINGSTONE}`, "status", "files", "vcs", @@ -173,7 +173,7 @@ describe("rightTabGroups() derivation (Record A §T2)", () => { // No duplicate, independent of order. expect(new Set(ids).size).toBe(ids.length); }, - [SUP, WARDEN], + [SUP, LIVINGSTONE], ); }); @@ -220,7 +220,7 @@ describe("rightTabGroups() derivation (Record A §T2)", () => { ); expect(withAgent.map((item) => item.id)).toEqual([ `agent:${SUP}`, - `agent:${WARDEN}`, + `agent:${LIVINGSTONE}`, ]); for (const item of withAgent) { expect(STUB_AGENTS.some((a) => a.account.id === item.agentId)).toBe( @@ -234,7 +234,7 @@ describe("rightTabGroups() derivation (Record A §T2)", () => { expect(status).toBeDefined(); expect(status?.agentId).toBeUndefined(); }, - [SUP, WARDEN], + [SUP, LIVINGSTONE], ); }); }); diff --git a/apps/ui/src/components/RightSidebar.tsx b/apps/ui/src/components/RightSidebar.tsx index 7c591930..5463e241 100644 --- a/apps/ui/src/components/RightSidebar.tsx +++ b/apps/ui/src/components/RightSidebar.tsx @@ -540,7 +540,7 @@ const StatusPane: Component = () => { /** The right sidebar (design D5, dock-in-sidebar D2/D3/D5): an icon-per-tab * activity bar mirroring Orca, grouped fleet-over-issue with a divider. - * Fleet tabs (Supervisor · Warden) render the agent's home-DM conversation + * Fleet tabs (Supervisor) render the agent's home-DM conversation * inline (read-only asks) above an open-workspace control; * issue tabs render the repo/branch dropdown + detail head above the pane * for the active tab — Files (with a search box), VCS (changed files + commit diff --git a/apps/ui/src/constants.ts b/apps/ui/src/constants.ts index c4ec5dd5..baa55d0b 100644 --- a/apps/ui/src/constants.ts +++ b/apps/ui/src/constants.ts @@ -72,7 +72,7 @@ export interface ActivityBarItem { * issue tabs (Files / VCS / PR). The agent conversation tabs are no longer * hardcoded here — they are derived per pin from the store's pin set * (`rightTabGroups()`), so the fleet group is a configurable pin layer, not a - * fixed Supervisor · Warden pair (Record A §T2). */ + * fixed Supervisor pin (Record A §T2). */ export type StaticRightTab = "status" | IssueTab; /** The static tabs in activity-bar order, keyed on the static-tab union in a @@ -98,7 +98,7 @@ export const RIGHT_SIDEBAR_ISSUE_ITEMS: readonly ActivityBarItem[] = * §T2; SEA-1645 P1). The tab id is the `agent:`-prefixed account id (the open * arm of `RightSidebarTab`); the icon is the agent handle's initial (matching * the UI's glyph-icon convention — a per-agent glyph, no hardcoded Supervisor - * ◆ / Warden 🛡), and the title is the LIVE agent handle. The item is left + * ◆), and the title is the LIVE agent handle. The item is left * unmarked (`unreachable` absent) so its `agentId` badges a real `StateDot`. * An unresolvable pin is built by `unreachableFleetItem` instead — so a * marked item can carry an `agentId` that resolves no agent. */ diff --git a/apps/ui/src/store.test.ts b/apps/ui/src/store.test.ts index 89bcbcae..4356667d 100644 --- a/apps/ui/src/store.test.ts +++ b/apps/ui/src/store.test.ts @@ -240,7 +240,7 @@ describe("openAgent", () => { // Switching to a *different* agent resets the per-agent view state: repo pick // and issue selection fall back to the new agent's defaults. An agent that - // owns nothing (warden) clears the issue selection and exposes no clone. + // owns nothing (supervisor) clears the issue selection and exposes no clone. test("switching agents resets selection and clears surfaces for an agent that owns none", () => { withStore((s) => { // Build up per-agent state on cook so the switch has something to reset. @@ -248,11 +248,11 @@ describe("openAgent", () => { s.setActiveBranch("cook-965-client-transport"); expect(s.activeRepo()?.currentBranch).toBe("cook-965-client-transport"); - // agent-warden is assigned zero issues. - s.openAgent("acc-warden"); + // acc-supervisor is assigned zero issues. + s.openAgent("acc-supervisor"); expect(s.view()).toBe("agent"); - expect(s.selectedAgentId()).toBe("acc-warden"); + expect(s.selectedAgentId()).toBe("acc-supervisor"); // No owned issues → no selection and no repo clone. expect(s.selectedIssueId()).toBeNull(); expect(s.agentRepos()).toEqual([]); @@ -515,8 +515,8 @@ describe("right sidebar tab (dock-in-sidebar T1; Record A §T2)", () => { // old issue-only type, or one stuck on its boot value, would fail one leg. test("setActiveRightTab round-trips a fleet pin and an issue value", () => { withStore((s) => { - s.setActiveRightTab("agent:acc-warden"); - expect(s.activeRightTab()).toBe("agent:acc-warden"); + s.setActiveRightTab("agent:acc-cook"); + expect(s.activeRightTab()).toBe("agent:acc-cook"); s.setActiveRightTab("vcs"); expect(s.activeRightTab()).toBe("vcs"); @@ -528,7 +528,7 @@ describe("agent pins (Record A §T2/T3/T5)", () => { // STUB_AGENTS fixture ids used across these tests. Both resolve to visible // agents (so they surface in rightTabGroups()); "acc-ghost" resolves to none. const SUP = "acc-supervisor"; - const WARDEN = "acc-warden"; + const LIVINGSTONE = "acc-livingstone"; const COOK = "acc-cook"; const GHOST = "acc-ghost"; const key = (workspace: string) => `compass.pinnedAgents.${workspace}`; @@ -579,13 +579,13 @@ describe("agent pins (Record A §T2/T3/T5)", () => { test("pins append in order; a re-pin is a no-op", () => { clearStorage(); withPinStore("ws-a", (s) => { - s.pinAgent(WARDEN); + s.pinAgent(LIVINGSTONE); s.pinAgent(SUP); s.pinAgent(COOK); - expect(s.pinnedAgentIds()).toEqual([WARDEN, SUP, COOK]); + expect(s.pinnedAgentIds()).toEqual([LIVINGSTONE, SUP, COOK]); // Re-pinning an existing id neither duplicates nor reorders. - s.pinAgent(WARDEN); - expect(s.pinnedAgentIds()).toEqual([WARDEN, SUP, COOK]); + s.pinAgent(LIVINGSTONE); + expect(s.pinnedAgentIds()).toEqual([LIVINGSTONE, SUP, COOK]); }); clearStorage(); }); @@ -626,12 +626,12 @@ describe("agent pins (Record A §T2/T3/T5)", () => { test("two workspace keys do not cross-hydrate", () => { clearStorage(); globalThis.localStorage.setItem(key("ws-1"), JSON.stringify([SUP])); - globalThis.localStorage.setItem(key("ws-2"), JSON.stringify([WARDEN])); + globalThis.localStorage.setItem(key("ws-2"), JSON.stringify([LIVINGSTONE])); withPinStore("ws-1", (s) => { expect(s.pinnedAgentIds()).toEqual([SUP]); }); withPinStore("ws-2", (s) => { - expect(s.pinnedAgentIds()).toEqual([WARDEN]); + expect(s.pinnedAgentIds()).toEqual([LIVINGSTONE]); }); clearStorage(); }); @@ -683,10 +683,10 @@ describe("agent pins (Record A §T2/T3/T5)", () => { clearStorage(); globalThis.localStorage.setItem( key("ws-boot2"), - JSON.stringify([GHOST, WARDEN]), + JSON.stringify([GHOST, LIVINGSTONE]), ); withPinStore("ws-boot2", (s) => { - expect(s.activeRightTab()).toBe("agent:acc-warden"); + expect(s.activeRightTab()).toBe("agent:acc-livingstone"); }); clearStorage(); }); diff --git a/apps/ui/src/stub-data.ts b/apps/ui/src/stub-data.ts index 8a11e807..12307a92 100644 --- a/apps/ui/src/stub-data.ts +++ b/apps/ui/src/stub-data.ts @@ -55,7 +55,7 @@ export type AgentState = | "disconnected"; /** The kind of agent — the moat agents plus leveraged worker agents. */ -export type AgentRole = "supervisor" | "warden" | "worker"; +export type AgentRole = "supervisor" | "worker"; /** Priority of an issue, drives the card accent. */ export type Priority = "urgent" | "high" | "medium" | "low"; @@ -480,22 +480,6 @@ export const STUB_AGENTS: Agent[] = [ cwd: "~/agents/workspaces/supervisor/sealed", terminals: [], }, - { - account: { - id: "acc-warden", - handle: "warden", - displayName: "warden", - kind: "agent", - ownerUserId: "acc-matt", - homeChannelId: "dm-warden", - }, - lifecycle: "working", - activity: "auditing push-guard denials", - role: "warden", - model: "seal-wasm-runtime", - cwd: "(sandboxed)", - terminals: [], - }, { account: { id: "acc-cook", @@ -1258,7 +1242,7 @@ export const STUB_ASSIGNED_ISSUES: Issue[] = [ forge: LINEAR_FORGE, repo: "SEA", number: 1201, - title: "Warden audit-log retention policy — design", + title: "Audit-log retention policy — design", body: "", forgeState: "open", url: "https://linear.app/sealed/issue/SEA-1201",