Wave 2 features: A2A live view (CEO chime-in + reply budget) and prompter memory (#297)

* feat(a2a): live view — watch fleet conversations, CEO chime-in, reply budget

A2A_MESSAGE_SENT published from A2AService.send (excerpt-capped) and
fanned through the existing /ws/system bridge; CEO-only admin REST for
conversations/messages + a reply route on the publish-bearing send path;
panel /a2a page with live transcript and a composer gated on task-linked
conversations. The matrix gains its one asymmetric rule: CEO may message
anyone, nobody may target the CEO — and agent replies inside a
CEO-opened conversation are hard-budgeted to one per CEO message
(per conversation, per agent), rejected with wait-don't-retry guidance.
Built subagent-driven (Sonnet 5), reviewed; v1 seams documented in the
map delta.

* feat(prompter): intake remembers the task history

Intake spawns now carry a per-project chronological digest of recent
tasks (capped: 15 lines/project, 4000 chars total — ~300-1000 tokens)
merged into the ambient layer, and the interviewer gets a bounded
search_past_tasks tool (one shared implementation behind the grok MCP
tool and the Claude SDK in-process tool) to check precedent
mid-conversation. Informational memory only — the sequencing analyzer
keeps ownership of ordering. Built subagent-driven (Sonnet 5), reviewed;
pre-existing conventions-ambient MegaTask-scope gap flagged, untouched.

---------

Co-authored-by: Renn F <rennf93@users.noreply.github.com>
This commit is contained in:
Renzo F
2026-07-03 00:07:55 +02:00
committed by GitHub
co-authored by Renn F
parent 48f2944086
commit da563487b8
39 changed files with 3808 additions and 27 deletions
+44
View File
@@ -44,6 +44,18 @@ export interface NotificationMessage {
timestamp?: string;
}
export interface A2ASystemMessage {
type: "connected" | "a2a.message";
conversation_id?: string;
message_id?: string;
task_id?: string;
from_agent?: string;
to_agent?: string;
skill?: string | null;
body_excerpt?: string;
timestamp?: string;
}
export interface SessionMessage {
type: "connected" | "message.new";
message_id?: string;
@@ -296,6 +308,38 @@ export function useNotificationStream() {
};
}
/**
* Subscribe to live A2A traffic on the operator stream (`/ws/system`).
*
* The bridge publishes an `a2a.message` frame for every persisted
* agent<->agent chat message. Frames carry a capped `body_excerpt` only —
* consumers invalidate their REST queries for full bodies (the A2A live view
* idiom), never render the excerpt as the message.
*/
export function useA2ALiveStream() {
const {
state,
lastMessage,
messages,
clearMessages,
isConnected,
isConnecting,
} = useWebSocket<A2ASystemMessage>("/system", undefined, true);
// Filter to A2A frames (the system stream also carries rate-limit/usage).
const a2aMessages = messages.filter((m) => m.type === "a2a.message");
return {
state,
lastMessage,
a2aMessages,
allMessages: messages,
clearMessages,
isConnected,
isConnecting,
};
}
// =============================================================================
// Connection Status Hook (for UI indicators)
// =============================================================================