fix(world): missions were never really on the wire
Three bugs in one query, each hiding the next, plus one that made the whole rich layer dead code. `active_missions` joined `team_members` on `missions.team_id` — the LEGACY pointer at the first minted team, superseded by the `mission_teams` junction in 0056. It was an INNER JOIN, and `mission_orchestrator::on_launch` deliberately mints no team for a microVM mission, so the platform's primary execution tier was dropped by a join and the World has been showing nothing at all for it. And it selected only `status='running'`, while missions finish in minutes, so the scene was empty almost always. Now: join `mission_teams`, LEFT so teamless missions survive (their `agent_id` is NULL and no pawn beams at them, which is the truth — nothing on this platform ran that phase except a VM), and include missions finished in the last 24h carrying `status`/`template_kind` so the client can draw a finished map instead of animating a corpse. `?mission=` scopes the feed server-side. The whole phase plan now ships as `mission.phase`, including phases that have not started: a phase list that appeared only as phases began made a five-phase mission look like a one-phase mission until it was nearly over. Attribution reuses `phase_runner::purposes_for` rather than copying it — two copies would let the picture disagree with the machine about who is working on what, which presents as a rendering bug and is really a lie. Deleted the checkpoint tail. It read `topology_runs` keyed by an `agent_runs` id; mission phases live in `topology_runs` under independently generated ids, so it ran every poll and matched nothing, for every mission, forever. That is why no mission has ever shown tool or file activity. Not repointed at `topology_runs`: its only per-step content is the agent's own prose, and a tool name in prose cannot be told from an agent talking about a tool. The a2a `run_events` tail is kept — it genuinely works for the path that writes it. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5
parent
b210acf3c2
commit
5f85dbb718
@@ -52,9 +52,48 @@ export interface TaxonomyEvents {
|
||||
/** Observe → a claw delegated a sub-task to another claw (A→B handoff). */
|
||||
"agent.delegate": { fromAgentId: string; toAgentId: string; toName?: string; task?: string; ts?: string };
|
||||
/** World → Live (Gource): the agent pawn retargets to nodeId and beams. */
|
||||
"world.touch": { agentId: string; nodeId: string; kind?: "service" | "event"; weight?: number };
|
||||
/** World → node glow/pulse intensity. */
|
||||
"node.activity": { nodeId: string; label?: string; kind?: "service" | "event"; heat?: number };
|
||||
"world.touch": {
|
||||
agentId: string;
|
||||
nodeId: string;
|
||||
kind?: "service" | "event" | "mission" | "phase";
|
||||
weight?: number;
|
||||
};
|
||||
/** World → node glow/pulse intensity.
|
||||
*
|
||||
* `kind` gained "mission" and "phase" because the server was already sending
|
||||
* "mission" while this union forbade it — the contract was describing a
|
||||
* feed that had not matched it for some time. */
|
||||
"node.activity": {
|
||||
nodeId: string;
|
||||
label?: string;
|
||||
kind?: "service" | "event" | "mission" | "phase" | "finding";
|
||||
heat?: number;
|
||||
};
|
||||
/** World → the mission landmark. Stateful: a late subscriber must receive the
|
||||
* mission it is looking at rather than waiting for it to change.
|
||||
* `completedAt` present ⇒ draw the finished map, do not animate. */
|
||||
"mission.update": {
|
||||
missionId: string;
|
||||
title: string;
|
||||
status: "running" | "completed" | "failed" | "cancelled";
|
||||
templateKind?: string;
|
||||
completedAt?: string | null;
|
||||
};
|
||||
/** World → one orb per phase, INCLUDING phases that have not started, so the
|
||||
* mission's whole shape is drawn upfront and lights as it progresses.
|
||||
* Stateful per phaseId. `agentIds` is empty for a teamless (microVM) phase —
|
||||
* that phase draws no pawns, which is accurate rather than missing. */
|
||||
"mission.phase": {
|
||||
missionId: string;
|
||||
phaseId: string;
|
||||
kind: "research" | "coding" | "benchmark" | "security_scan";
|
||||
orderIdx: number;
|
||||
status: "pending" | "running" | "evaluating" | "completed" | "failed" | "skipped";
|
||||
iteration: number;
|
||||
startedAt?: string | null;
|
||||
completedAt?: string | null;
|
||||
agentIds: string[];
|
||||
};
|
||||
/** World → re-layout (add/remove org units, agents, projects). */
|
||||
"topology.update": {
|
||||
formation: "hierarchy" | "flat" | "live";
|
||||
@@ -97,6 +136,8 @@ export const TAXONOMY_TYPES: TaxonomyType[] = [
|
||||
"agent.delegate",
|
||||
"world.touch",
|
||||
"node.activity",
|
||||
"mission.update",
|
||||
"mission.phase",
|
||||
"topology.update",
|
||||
"telemetry",
|
||||
"routine.update",
|
||||
@@ -110,6 +151,8 @@ export const STATEFUL_TYPES = new Set<TaxonomyType>([
|
||||
"agent.task.update",
|
||||
"agent.memory",
|
||||
"node.activity",
|
||||
"mission.update",
|
||||
"mission.phase",
|
||||
"telemetry",
|
||||
"topology.update",
|
||||
"routine.update",
|
||||
@@ -121,6 +164,11 @@ export function stateKey<T extends TaxonomyType>(type: T, d: TaxonomyPayload<T>)
|
||||
return `${type}:${(d as TaxonomyEvents["agent.status"]).agentId}`;
|
||||
if (type === "node.activity") return `${type}:${(d as TaxonomyEvents["node.activity"]).nodeId}`;
|
||||
if (type === "routine.update") return `${type}:${(d as TaxonomyEvents["routine.update"]).routineId}`;
|
||||
// One retained value per mission / per phase: the plan is replayed whole to a
|
||||
// late subscriber, which is what lets the scene draw a mission's shape the
|
||||
// moment it is pinned rather than on the next phase transition.
|
||||
if (type === "mission.update") return `${type}:${(d as TaxonomyEvents["mission.update"]).missionId}`;
|
||||
if (type === "mission.phase") return `${type}:${(d as TaxonomyEvents["mission.phase"]).phaseId}`;
|
||||
if (type === "telemetry") {
|
||||
const a = (d as TaxonomyEvents["telemetry"]).agentId;
|
||||
return a ? `telemetry:${a}` : "telemetry"; // per-agent slice vs workspace-wide
|
||||
|
||||
Reference in New Issue
Block a user