diff --git a/README.md b/README.md index 0a16dd8c62..7092cce277 100644 --- a/README.md +++ b/README.md @@ -157,10 +157,40 @@ FNXC:Docs 2026-06-21-19:55: README must lead with a smaller wordmark and a visual showcase of the latest surfaces (Command Center, selectable workflows, agent chat, multi-agent chat rooms, agent mail) so the value lands fast. Each feature pairs a short looping GIF with value copy; Command Center additionally carries real fleet stats, the token/productivity/team graph trio, and the 70+-theme grid (incl. shadcn light/mono/orange/black) to make the data pop. Media lives in demo/assets/ (committed, GitHub-inline GIFs); stat numbers are sourced from a live seeded fleet โ€” refresh them if the captures are re-shot. -Each feature keeps its original Tokyo Night capture and adds a Shadcn Light + Shadcn Dark Gray pair; the theme showcase is split into a light-themes grid and a dark-themes grid. Workflow GIFs feature the Stepwise coding graph with node-level zoom/pan. +Each feature keeps its original Tokyo Night capture and adds a Shadcn Light + Shadcn Dark Gray + Ember trio; the theme showcase is split into a light-themes grid and a dark-themes grid. Workflow GIFs feature the Stepwise coding graph with node-level zoom/pan. --> -The newest surfaces in Fusion, at a glance โ€” mission control, visual workflows, agent chat, multi-agent rooms, and inter-agent mail. +The newest surfaces in Fusion, at a glance โ€” the live board, your agent team, mission control, visual workflows, agent chat, multi-agent rooms, and inter-agent mail. + +### ๐Ÿ“‹ The board & your agent team โ€” live, from a real fleet + +
+ Fusion board: Triage, Todo, In Progress, In Review, Done columns with live task cards across the Tokyo Night theme +
+ +Every task, every column, every step โ€” live. Cards carry GitHub links, step counts, review levels, and promote/move/archive actions. Switch to the **Graph** view to see task dependencies as an interactive node graph: + + + + + + +
Fusion board: Triage, Todo, In Progress, In Review, Done columns with live task cards
Board โ€” kanban columns
Fusion graph view: task dependency graph with connected nodes
Graph โ€” dependency map
+ +Here is the same fleet re-skinned into the **Ember** theme (dark graphite with an orange accent), alongside the **Agents** roster: + + + + + + +
Fusion board in the Ember theme
Board โ€” Ember
Fusion Agents view: CEO, Product Manager, CTO, and engineers with roles and heartbeat status
Agents โ€” Tokyo Night
+ +Import a team and every agent shows up here โ€” role, reports-to chain, heartbeat, and token share. The **Agents** roster in Ember: + +
+ Fusion Agents view in the Ember theme +
### ๐Ÿ›ฐ๏ธ Command Center โ€” mission control for your agent fleet @@ -168,7 +198,13 @@ The newest surfaces in Fusion, at a glance โ€” mission control, visual workflows Fusion Command Center: live concurrency gauges, token charts, and fleet telemetry across tabs -One screen for everything your agents are doing. Tune live scheduler capacity, watch token spend by model in real time, and prove the value with hard numbers. +One screen for everything your agents are doing. Tune live scheduler capacity, watch token spend by model in real time, and prove the value with hard numbers. The **Overview** tab opens with live gauges and charts: + +
+ Fusion Command Center Overview: concurrency gauges, engine status, and fleet charts +
+ +Every tab is a different lens on the same live fleet: @@ -176,16 +212,22 @@ One screen for everything your agents are doing. Tune live scheduler capacity, w + + + + +
Productivity: commits, human-hours saved, task duration percentiles, and files by language
Productivity โ€” outcomes, duration percentiles, language mix.
Agent org chart with token share and tokens-by-agent breakdown
Team โ€” agent org chart and token share per agent.
Activity: task throughput and event timeline charts
Activity โ€” task throughput and event timelines.
Signals: anomaly detection and fleet signal charts
Signals โ€” anomaly detection and fleet health.
Command Center tab
More โ€” Tools ยท Ecosystem ยท GitHub ยท System ยท Reliability.
> Tokens ยท Tools ยท Activity ยท Productivity ยท Team ยท Ecosystem ยท GitHub ยท Signals ยท System ยท Reliability ยท Mission Control โ€” every tab is a different lens on the same live fleet. -**The same fleet, your way** โ€” Command Center (and the whole dashboard) re-skins live across **70+ color themes**. Here it is in Shadcn Light and Shadcn Dark Gray: +**The same fleet, your way** โ€” Command Center (and the whole dashboard) re-skins live across **70+ color themes**. Here it is in Shadcn Light, Shadcn Dark Gray, and Ember: - - + + +
Command Center in Shadcn Light theme
Shadcn Light
Command Center in Shadcn Dark Gray theme
Shadcn Dark Gray
Command Center in Shadcn Light theme
Shadcn Light
Command Center in Shadcn Dark Gray theme
Shadcn Dark Gray
Command Center in Ember theme
Ember
@@ -210,12 +252,13 @@ One screen for everything your agents are doing. Tune live scheduler capacity, w A task's journey from idea to merge is a **workflow** โ€” and it's yours to choose and shape. Pick a built-in (Coding, Quick fix, Review-heavy, Stepwise, PR lifecycle, Compound engineering, and more), inspect its graph, then duplicate and customize columns, gates, model lanes, and review policy in the visual [Workflow Editor](./docs/workflow-editor.md). No engine fork required. -Here's the **Stepwise coding** graph โ€” plan, execute, and review every step before the next โ€” explored node-by-node in Shadcn Light and Dark Gray: +Here's the **Stepwise coding** graph โ€” plan, execute, and review every step before the next โ€” explored node-by-node in Shadcn Light, Dark Gray, and Ember: - - + + +
Stepwise coding workflow graph in Shadcn Light, panning across nodes
Shadcn Light
Stepwise coding workflow graph in Shadcn Dark Gray, panning across nodes
Shadcn Dark Gray
Stepwise coding workflow graph in Shadcn Light, panning across nodes
Shadcn Light
Stepwise coding workflow graph in Shadcn Dark Gray, panning across nodes
Shadcn Dark Gray
Stepwise coding workflow graph in Ember, panning across nodes
Ember
@@ -244,8 +287,9 @@ Put multiple agents in a room and let them coordinate. Mention a member and it r - - + + +
Multi-agent chat room in Shadcn Light
Shadcn Light
Multi-agent chat room in Shadcn Dark Gray
Shadcn Dark Gray
Multi-agent chat room in Shadcn Light
Shadcn Light
Multi-agent chat room in Shadcn Dark Gray
Shadcn Dark Gray
Multi-agent chat room in Ember
Ember
@@ -259,8 +303,9 @@ A built-in mailbox for delegation, clarification, and hand-offs. Agents file tri - - + + +
Agent mailbox in Shadcn Light
Shadcn Light
Agent mailbox in Shadcn Dark Gray
Shadcn Dark Gray
Agent mailbox in Shadcn Light
Shadcn Light
Agent mailbox in Shadcn Dark Gray
Shadcn Dark Gray
Agent mailbox in Ember
Ember
diff --git a/demo/assets/agent-chat-gray.png b/demo/assets/agent-chat-gray.png index f5e88bf890..5af071f110 100644 Binary files a/demo/assets/agent-chat-gray.png and b/demo/assets/agent-chat-gray.png differ diff --git a/demo/assets/agent-chat-light.png b/demo/assets/agent-chat-light.png index 4295b05dd7..73f99bbff6 100644 Binary files a/demo/assets/agent-chat-light.png and b/demo/assets/agent-chat-light.png differ diff --git a/demo/assets/agent-chat.gif b/demo/assets/agent-chat.gif index 96274d3a79..26e5b61d4c 100644 Binary files a/demo/assets/agent-chat.gif and b/demo/assets/agent-chat.gif differ diff --git a/demo/assets/agent-mail-ember.gif b/demo/assets/agent-mail-ember.gif new file mode 100644 index 0000000000..243df37a5a Binary files /dev/null and b/demo/assets/agent-mail-ember.gif differ diff --git a/demo/assets/agent-mail-gray.gif b/demo/assets/agent-mail-gray.gif index cc15df10d8..693f402217 100644 Binary files a/demo/assets/agent-mail-gray.gif and b/demo/assets/agent-mail-gray.gif differ diff --git a/demo/assets/agent-mail-light.gif b/demo/assets/agent-mail-light.gif index 2c4a98f22c..5cd7c6f655 100644 Binary files a/demo/assets/agent-mail-light.gif and b/demo/assets/agent-mail-light.gif differ diff --git a/demo/assets/agent-mail.gif b/demo/assets/agent-mail.gif index ac567a9268..7f23d14dab 100644 Binary files a/demo/assets/agent-mail.gif and b/demo/assets/agent-mail.gif differ diff --git a/demo/assets/agents-ember.png b/demo/assets/agents-ember.png new file mode 100644 index 0000000000..3cb36116c0 Binary files /dev/null and b/demo/assets/agents-ember.png differ diff --git a/demo/assets/agents-tokyo.png b/demo/assets/agents-tokyo.png new file mode 100644 index 0000000000..438fff7b65 Binary files /dev/null and b/demo/assets/agents-tokyo.png differ diff --git a/demo/assets/chat-rooms-ember.gif b/demo/assets/chat-rooms-ember.gif new file mode 100644 index 0000000000..da0305aec4 Binary files /dev/null and b/demo/assets/chat-rooms-ember.gif differ diff --git a/demo/assets/chat-rooms-gray.gif b/demo/assets/chat-rooms-gray.gif index 714feab7ae..0083fd3ca7 100644 Binary files a/demo/assets/chat-rooms-gray.gif and b/demo/assets/chat-rooms-gray.gif differ diff --git a/demo/assets/chat-rooms-light.gif b/demo/assets/chat-rooms-light.gif index 966f2569bd..b52a08d028 100644 Binary files a/demo/assets/chat-rooms-light.gif and b/demo/assets/chat-rooms-light.gif differ diff --git a/demo/assets/chat-rooms.gif b/demo/assets/chat-rooms.gif index 14bd038474..78dfbf7808 100644 Binary files a/demo/assets/chat-rooms.gif and b/demo/assets/chat-rooms.gif differ diff --git a/demo/assets/command-center-activity.png b/demo/assets/command-center-activity.png new file mode 100644 index 0000000000..7012fb68ef Binary files /dev/null and b/demo/assets/command-center-activity.png differ diff --git a/demo/assets/command-center-ember.gif b/demo/assets/command-center-ember.gif new file mode 100644 index 0000000000..1d4cc6f826 Binary files /dev/null and b/demo/assets/command-center-ember.gif differ diff --git a/demo/assets/command-center-gray.gif b/demo/assets/command-center-gray.gif index f27e8eab01..6e49b6e460 100644 Binary files a/demo/assets/command-center-gray.gif and b/demo/assets/command-center-gray.gif differ diff --git a/demo/assets/command-center-light.gif b/demo/assets/command-center-light.gif index 52baa72bce..5138cd5db7 100644 Binary files a/demo/assets/command-center-light.gif and b/demo/assets/command-center-light.gif differ diff --git a/demo/assets/command-center-overview.png b/demo/assets/command-center-overview.png new file mode 100644 index 0000000000..34b252e4b2 Binary files /dev/null and b/demo/assets/command-center-overview.png differ diff --git a/demo/assets/command-center-productivity.png b/demo/assets/command-center-productivity.png index 5f6b20f89f..788254fbde 100644 Binary files a/demo/assets/command-center-productivity.png and b/demo/assets/command-center-productivity.png differ diff --git a/demo/assets/command-center-signals.png b/demo/assets/command-center-signals.png new file mode 100644 index 0000000000..b1dd7455a8 Binary files /dev/null and b/demo/assets/command-center-signals.png differ diff --git a/demo/assets/command-center-team.png b/demo/assets/command-center-team.png index b0bad24c43..7b8d3eeab2 100644 Binary files a/demo/assets/command-center-team.png and b/demo/assets/command-center-team.png differ diff --git a/demo/assets/command-center-tokens.png b/demo/assets/command-center-tokens.png index 524cd87cdf..bfe3e4c2d4 100644 Binary files a/demo/assets/command-center-tokens.png and b/demo/assets/command-center-tokens.png differ diff --git a/demo/assets/command-center.gif b/demo/assets/command-center.gif index bda701786a..79e41f6c9a 100644 Binary files a/demo/assets/command-center.gif and b/demo/assets/command-center.gif differ diff --git a/demo/assets/dashboard-ember.png b/demo/assets/dashboard-ember.png new file mode 100644 index 0000000000..b2c6566ea0 Binary files /dev/null and b/demo/assets/dashboard-ember.png differ diff --git a/demo/assets/dashboard-graph.png b/demo/assets/dashboard-graph.png new file mode 100644 index 0000000000..07c36316e8 Binary files /dev/null and b/demo/assets/dashboard-graph.png differ diff --git a/demo/assets/dashboard-tokyo.png b/demo/assets/dashboard-tokyo.png new file mode 100644 index 0000000000..84d89d085e Binary files /dev/null and b/demo/assets/dashboard-tokyo.png differ diff --git a/demo/assets/mobile-agents.png b/demo/assets/mobile-agents.png index 9d2ad46810..75a3cb8c8d 100644 Binary files a/demo/assets/mobile-agents.png and b/demo/assets/mobile-agents.png differ diff --git a/demo/assets/mobile-board.png b/demo/assets/mobile-board.png index 472f687af4..2903186063 100644 Binary files a/demo/assets/mobile-board.png and b/demo/assets/mobile-board.png differ diff --git a/demo/assets/mobile-chat-list.png b/demo/assets/mobile-chat-list.png index ecb2891e53..b9e899adb3 100644 Binary files a/demo/assets/mobile-chat-list.png and b/demo/assets/mobile-chat-list.png differ diff --git a/demo/assets/mobile-chat.png b/demo/assets/mobile-chat.png index 3a6dd1128a..03921dfd51 100644 Binary files a/demo/assets/mobile-chat.png and b/demo/assets/mobile-chat.png differ diff --git a/demo/assets/mobile-command-center.png b/demo/assets/mobile-command-center.png index ac13aaf792..ebc171d48c 100644 Binary files a/demo/assets/mobile-command-center.png and b/demo/assets/mobile-command-center.png differ diff --git a/demo/assets/mobile-missions.png b/demo/assets/mobile-missions.png index 90a1fc2b7d..c0fe88035e 100644 Binary files a/demo/assets/mobile-missions.png and b/demo/assets/mobile-missions.png differ diff --git a/demo/assets/workflows-ember.gif b/demo/assets/workflows-ember.gif new file mode 100644 index 0000000000..2f15088d1b Binary files /dev/null and b/demo/assets/workflows-ember.gif differ diff --git a/demo/assets/workflows-gray.gif b/demo/assets/workflows-gray.gif index a1f08916af..212e667b10 100644 Binary files a/demo/assets/workflows-gray.gif and b/demo/assets/workflows-gray.gif differ diff --git a/demo/assets/workflows-light.gif b/demo/assets/workflows-light.gif index 7283151cdb..cea22cc18d 100644 Binary files a/demo/assets/workflows-light.gif and b/demo/assets/workflows-light.gif differ diff --git a/demo/assets/workflows.gif b/demo/assets/workflows.gif index 09b2865637..691f449fcd 100644 Binary files a/demo/assets/workflows.gif and b/demo/assets/workflows.gif differ diff --git a/demo/seed.ts b/demo/seed.ts index b33ffd35e6..3ac97bb2f5 100644 --- a/demo/seed.ts +++ b/demo/seed.ts @@ -10,6 +10,7 @@ * - Planning: raw ideas just landing */ import { TaskStore } from "../packages/core/src/index.js"; +import { AgentStore, ChatStore, MessageStore } from "../packages/core/src/index.js"; import type { WorkflowIr } from "../packages/core/src/workflow-ir-types.js"; import { writeFile } from "node:fs/promises"; import { join } from "node:path"; @@ -291,29 +292,38 @@ async function main() { ] as const; for (const t of browserDemo) { - const task = await store.createTask({ description: t.desc, title: t.title }); - await store.updateTask(task.id, { size: "S", reviewLevel: 0 }); - await store.selectTaskWorkflowAndReconcile(task.id, browserDemoWorkflow.id); + try { + const task = await store.createTask({ description: t.desc, title: t.title }); + await store.updateTask(task.id, { size: "S", reviewLevel: 0 }); + await store.selectTaskWorkflowAndReconcile(task.id, browserDemoWorkflow.id); - const steps = generateSteps(t.title); - await writePrompt(store, task.id, t.title, t.desc, steps); + const steps = generateSteps(t.title); + await writePrompt(store, task.id, t.title, t.desc, steps); - if (t.currentStep !== null) { - for (let i = 0; i < Math.min(t.currentStep, steps.length); i++) { - await store.updateStep(task.id, i, "done"); - } - if (t.currentStep < steps.length) { - await store.updateStep(task.id, t.currentStep, "in-progress"); - } + if (t.currentStep !== null) { + for (let i = 0; i < Math.min(t.currentStep, steps.length); i++) { + await store.updateStep(task.id, i, "done"); + } + if (t.currentStep < steps.length) { + await store.updateStep(task.id, t.currentStep, "in-progress"); + } } const lifecyclePath = ["todo", "in-progress", "in-review", "qa", "publish"] as const; const targetIndex = lifecyclePath.indexOf(t.column); - for (const column of lifecyclePath.slice(1, targetIndex + 1)) { + // FNXC:DemoSeed 2026-06-23-20:05: Walk the full lifecycle from "todo" so the + // transition validator accepts every hop (triage only allows โ†’ todo directly). + for (const column of lifecyclePath.slice(0, targetIndex + 1)) { await store.moveTask(task.id, column, { moveSource: "user", allowDirectInReviewMove: true }); } - await addLogs(store, task.id, t.column); + await addLogs(store, task.id, t.column); + } catch (e) { + // FNXC:DemoSeed 2026-06-23-20:10: The Browser Demo Lifecycle workflow uses + // custom qa/publish columns whose transitions aren't in the default graph; + // skip cards that can't advance rather than aborting the whole seed. + console.warn(` (skipped browser demo card "${t.title}": ${(e as Error).message})`); + } } // โ”€โ”€ Planning โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ @@ -340,6 +350,9 @@ async function main() { await store.createTask({ description: t.desc }); } + // โ”€โ”€ Agents, chat, and agent mail โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + await seedAgentsChatAndMail(store); + const tasks = await store.listTasks(); const byColumn: Record = {}; for (const t of tasks) { @@ -357,6 +370,131 @@ async function main() { console.log(`\nRun "kb dashboard" to see the board, including the browser demo lifecycle columns.`); } +// โ”€โ”€ Agents, chat, and agent mail โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +/* +FNXC:DemoSeed 2026-06-23-19:50: +The README showcase needs realistic agent chat threads, a multi-agent chat room, +and an inter-agent mailbox with delegation/approval/triage content so the Agent +Chat, Chat Rooms, and Agent Mail GIFs have believable data. This seeds durable +agents (CEO, Product Manager, CTO, engineers), a direct chat session, a #leads +room where the leadership trio coordinates, and mailbox messages covering +triage summaries, approvals, and hand-offs. +*/ +async function seedAgentsChatAndMail(store: TaskStore) { + const fusionDir = store.getFusionDir(); + const db = store.getDatabase(); + const agentStore = new AgentStore({ rootDir: fusionDir }); + const chatStore = new ChatStore(fusionDir, db); + const messageStore = new MessageStore(db); + + const roleDefs: Array<{ name: string; role: "engineer" | "custom"; title: string; reportsTo?: string }> = [ + { name: "CEO", role: "custom", title: "Chief Executive Officer" }, + { name: "Product Manager", role: "custom", title: "Product Manager", reportsTo: "CEO" }, + { name: "CTO", role: "engineer", title: "Chief Technology Officer", reportsTo: "CEO" }, + { name: "Fullstack Engineer", role: "engineer", title: "Fullstack Engineer", reportsTo: "CTO" }, + { name: "Frontend Engineer", role: "engineer", title: "Frontend Engineer", reportsTo: "CTO" }, + ]; + + const agentIds: Record = {}; + for (const def of roleDefs) { + try { + const agent = await agentStore.createAgent({ + name: def.name, + role: def.role, + title: def.title, + reportsTo: def.reportsTo ? undefined : undefined, + metadata: { description: def.title }, + }); + agentIds[def.name] = agent.id; + } catch { + // agent may already exist; look it up + const existing = await agentStore.findAgentByName(def.name); + if (existing) agentIds[def.name] = existing.id; + } + } + + // wire up reportsTo now that all ids exist + for (const def of roleDefs) { + if (def.reportsTo && agentIds[def.name] && agentIds[def.reportsTo]) { + try { + await agentStore.updateAgent(agentIds[def.name], { reportsTo: agentIds[def.reportsTo] }); + } catch { + // best effort + } + } + } + + // โ”€โ”€ Direct chat session: user asks the Fullstack Engineer about a stuck task โ”€โ”€ + const session = chatStore.createSession({ + agentId: agentIds["Fullstack Engineer"], + title: "FN-6917 is stuck landing โ€” what's going on?", + }); + const chatThread: Array<[string, string]> = [ + ["user", "FN-6917 has been sitting in In Review for 40 minutes. The auto-merge didn't fire โ€” any idea why?"], + ["assistant", "Looking at the logs now. The pre-squash diff-volume gate tripped because the worktree picked up an unrelated `pnpm-lock.yaml` regeneration. The actual code delta is only 12 lines."], + ["user", "Can we force it through, or do we need to rebase?"], + ["assistant", "Safest path is a rebase onto main to drop the lockfile churn, then the gate passes cleanly. I can do that now โ€” want me to proceed?"], + ["user", "Yes, go ahead. Ping me when it's green."], + ["assistant", "On it. Rebasing `fusion/FN-6917` onto `origin/main` now. I'll post the merge result in #leads when it lands."], + ]; + for (const [role, content] of chatThread) { + chatStore.addMessage(session.id, { role: role as "user" | "assistant", content }); + } + + // โ”€โ”€ Multi-agent chat room: #leads โ€” CEO, PM, CTO coordinate โ”€โ”€ + const room = chatStore.createRoom({ + name: "leads", + description: "Leadership sync โ€” mission ownership and blockers", + memberAgentIds: [agentIds["CEO"], agentIds["Product Manager"], agentIds["CTO"]].filter(Boolean) as string[], + }); + const roomThread: Array<{ sender: string; mentions?: string[]; content: string }> = [ + { sender: "CEO", content: "Q3 mission is `Ship multi-repo workspaces`. PM โ€” can you break that into milestones by EOD?" }, + { sender: "Product Manager", mentions: ["CTO"], content: "On it. @CTO what's the rough engineering lift? Need it to size the slices." }, + { sender: "CTO", content: "Core work is the CentralCore project-path resolver + a migration. Maybe 3 features, ~8 tasks. Frontend is a settings tab." }, + { sender: "Product Manager", content: "Perfect. Three milestones: infra, migration, UI. I'll file the mission now and assign the infra slice to @CTO." }, + { sender: "CEO", content: "Great. Let's autopilot the infra slice and gate the migration slice on manual review. Don't want data loss risk." }, + { sender: "CTO", mentions: ["Fullstack Engineer"], content: "Agreed. @Fullstack Engineer will take the settings tab in parallel once the resolver lands." }, + ]; + for (const msg of roomThread) { + const senderId = agentIds[msg.sender]; + if (!senderId) continue; + chatStore.addRoomMessage(room.id, { + role: "assistant", + content: msg.content, + senderAgentId: senderId, + mentions: msg.mentions?.map((m) => agentIds[m]).filter(Boolean), + }); + } + + // โ”€โ”€ Agent mailbox: triage summaries, approvals, hand-offs โ”€โ”€ + const mailMessages: Array<{ + from: string; to: string; type: "agent-to-agent" | "agent-to-user"; content: string; + }> = [ + { from: "Product Manager", to: "CTO", type: "agent-to-agent", content: "Triage complete for the inbox batch: 3 actionable issues filed as tasks (FN-6920, FN-6921, FN-6922), 2 duplicates closed, 1 needs your input on the schema migration approach. Summary attached." }, + { from: "CTO", to: "Fullstack Engineer", type: "agent-to-agent", content: "FN-6920 (LOC backfill controls) is yours. Scope is `packages/dashboard/app/components/ProductivityView.tsx` plus the analytics resolver. Aim for review-level 1." }, + { from: "Fullstack Engineer", to: "CTO", type: "agent-to-agent", content: "Approval requested: the productivity backfill needs a new `POST /api/productivity/backfill` route. OK to add it, or should I route through the existing insights endpoint?" }, + { from: "CTO", to: "Product Manager", type: "agent-to-agent", content: "Hand-off: FN-6917 landed after a rebase. The auto-merge gate caught a bogus lockfile delta โ€” I've filed FN-6923 to harden the diff-volume check. Milestone 1 is unblocked." }, + { from: "Product Manager", to: "user", type: "agent-to-user", content: "Weekly triage digest: 12 issues processed, 7 filed as tasks, 3 closed as duplicates, 2 escalated. Net backlog delta: +2. Full report in Artifacts." }, + { from: "Frontend Engineer", to: "CTO", type: "agent-to-agent", content: "Settings tab for multi-repo is wired up and behind the experimental flag. Ready for review whenever you have a window โ€” no rush, infra slice isn't merged yet." }, + ]; + for (const msg of mailMessages) { + const fromId = agentIds[msg.from] ?? "user"; + const toId = agentIds[msg.to] ?? "user"; + messageStore.sendMessage({ + fromId, + fromType: msg.from === "user" ? "user" : "agent", + toId, + toType: msg.to === "user" ? "user" : "agent", + content: msg.content, + type: msg.type, + }); + } + + console.log(` Agents: ${Object.keys(agentIds).length}`); + console.log(` Chat: 1 session (${chatThread.length} msgs), 1 room (${roomThread.length} msgs)`); + console.log(` Mailbox: ${mailMessages.length} messages`); +} + // โ”€โ”€ Helpers โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ function generateSteps(_title: string): string[] {