diff --git a/apps/dashboard/smoke/frontstage-route-smoke.ts b/apps/dashboard/smoke/frontstage-route-smoke.ts index ca0b7c60..fd0b5a3b 100644 --- a/apps/dashboard/smoke/frontstage-route-smoke.ts +++ b/apps/dashboard/smoke/frontstage-route-smoke.ts @@ -99,6 +99,18 @@ includes(frontstageSource, "resolveFrontstageOpsStatusUrl", "ops status URL reso includes(frontstageSource, "statusContractFreshnessIssue", "schema freshness gate"); includes(frontstageSource, "localDashboardApiCapabilities", "local capability projection"); includes(frontstageSource, "Ops statusUrl accepts only relative or loopback sources.", "ops source guard helper copy"); +includes(frontstageSource, 'data-testid="frontstage-management-surface-mock"', "management surface mock"); +includes(frontstageSource, 'data-testid={`frontstage-management-${card.id}`}', "management surface card ids"); +includes(frontstageSource, "Mission Bar", "management surface mission bar"); +includes(frontstageSource, "Team Roster", "management surface team roster"); +includes(frontstageSource, "Ticket Board", "management surface ticket board"); +includes(frontstageSource, "Gate Inbox", "management surface gate inbox"); +includes(frontstageSource, "Cadence / Budget", "management surface cadence budget"); +includes(frontstageSource, "Evidence Timeline", "management surface evidence timeline"); +includes(frontstageSource, "goal_id + next_action", "management surface mission source"); +includes(frontstageSource, "user_todos + agent_todos", "management surface ticket source"); +includes(frontstageSource, "quota + scheduler hints", "management surface budget source"); +includes(frontstageSource, "recent_events + artifacts", "management surface evidence source"); includes(frontstageSource, 'data-testid="frontstage-user-todos"', "user todo lane"); includes(frontstageSource, 'data-testid="frontstage-agent-todos"', "agent todo lane"); includes(frontstageSource, 'data-testid="frontstage-todo-discovery"', "todo discovery controls"); diff --git a/apps/dashboard/src/views/frontstage-page.tsx b/apps/dashboard/src/views/frontstage-page.tsx index f13c45a3..ef7461e2 100644 --- a/apps/dashboard/src/views/frontstage-page.tsx +++ b/apps/dashboard/src/views/frontstage-page.tsx @@ -272,7 +272,7 @@ function uniqueClaimOwners(projection: GoalChannelProjection) { [ ...projection.agent_todos.map((todo) => todo.claimed_by), ...projection.active_leases.map((lease) => lease.owner_agent), - ].filter(Boolean), + ].filter((value): value is string => Boolean(value)), ), ); } @@ -477,6 +477,116 @@ function Panel({ ); } +type ManagementSurfaceCard = { + body: string; + icon: React.ComponentType<{ className?: string }>; + id: string; + label: string; + source: string; + value: string; +}; + +function FrontstageManagementSurfaceMock({ + claimOwners, + claimedAgentTodos, + openAgentTodos, + openUserTodos, + projection, + quotaUsed, +}: { + claimOwners: string[]; + claimedAgentTodos: number; + openAgentTodos: number; + openUserTodos: number; + projection: GoalChannelProjection; + quotaUsed: string; +}) { + const firstGate = projection.open_gates[0]; + const latestEvent = projection.recent_events[0]; + const cards: ManagementSurfaceCard[] = [ + { + body: projection.next_action, + icon: LayoutDashboard, + id: "mission", + label: "Mission Bar", + source: "goal_id + next_action", + value: projection.display_name, + }, + { + body: claimOwners.length ? claimOwners.slice(0, 3).join(", ") : "No claimed owner projected.", + icon: Users, + id: "team", + label: "Team Roster", + source: "active_leases + claimed_by", + value: `${claimOwners.length} visible agents`, + }, + { + body: `${openUserTodos} user todo, ${openAgentTodos} agent todo; ${claimedAgentTodos} claimed.`, + icon: ListChecks, + id: "tickets", + label: "Ticket Board", + source: "user_todos + agent_todos", + value: `${openUserTodos + openAgentTodos} open tickets`, + }, + { + body: firstGate ? `${firstGate.kind} blocks ${(firstGate.blocks ?? []).join(", ") || "delivery"}.` : "No open gate in this projection.", + icon: CircleAlert, + id: "gates", + label: "Gate Inbox", + source: "decision_frame + open_gates", + value: projection.decision_frame.user_action_required ? "decision visible" : "clear", + }, + { + body: `${artifactDisplayValue(projection.quota.spend_policy)}; state=${stringifyScalar(projection.quota.state)}.`, + icon: Clock3, + id: "cadence", + label: "Cadence / Budget", + source: "quota + scheduler hints", + value: quotaUsed, + }, + { + body: latestEvent ? `${latestEvent.classification ?? "event"}: ${latestEvent.summary ?? latestEvent.generated_at ?? "recorded"}` : "No compact event projected.", + icon: ShieldCheck, + id: "evidence", + label: "Evidence Timeline", + source: "recent_events + artifacts", + value: `${projection.recent_events.length} events`, + }, + ]; + + return ( + +
+ {cards.map((card) => { + const Icon = card.icon; + return ( +
+
+
+ + + +
+
{card.label}
+
{card.source}
+
+
+ kernel +
+
{card.value}
+

{card.body}

+
+ ); + })} +
+
+ ); +} + function EfficiencyEvidencePanel() { const workload = selfIterationShowcase?.workload_signal; const model = workload?.efficiency_model; @@ -1833,6 +1943,17 @@ function FrontstageRoute({ + {isOpsMode ? ( + + ) : null} + {!isDeveloperMode ? : null} {isShowcaseMode ? : null} diff --git a/docs/product/frontstage-dashboard-interaction-baseline.md b/docs/product/frontstage-dashboard-interaction-baseline.md index 99025133..57e0d473 100644 --- a/docs/product/frontstage-dashboard-interaction-baseline.md +++ b/docs/product/frontstage-dashboard-interaction-baseline.md @@ -98,6 +98,10 @@ The route currently exposes these durable anchors: - `frontstage-ops-command-strip` for search/filter/result-count controls. - `frontstage-todo-search`, `frontstage-todo-lane-filter`, and `frontstage-todo-result-count` for reviewable todo projection slices. +- `frontstage-management-surface-mock` for the low-fidelity ops projection + that maps kernel state into mission, team roster, ticket board, gate inbox, + cadence/budget, and evidence timeline without introducing a parallel state + model. - `frontstage-role-map`, `frontstage-active-claims`, `frontstage-open-gates`, `frontstage-artifacts`, and `frontstage-timeline` for the operator workspace. - `frontstage-showcase-motion-beam` and `frontstage-state-flow-beam` for