| Lane |
Model |
+ Mode |
Context |
$/1K out |
Tools |
@@ -464,6 +471,15 @@ export function CostTracker() {
)}
{isLoading && ...}
+
+
+ {laneSourceLabel(l.source)}
+
+ |
{formatCtx(l.context_window)} |
{l.cost_output_per_1k ? `$${l.cost_output_per_1k.toFixed(4)}` : '--'}
diff --git a/src/warroom/src/pages/FleetDashboard.tsx b/src/warroom/src/pages/FleetDashboard.tsx
new file mode 100644
index 0000000..cf31fa1
--- /dev/null
+++ b/src/warroom/src/pages/FleetDashboard.tsx
@@ -0,0 +1,662 @@
+import { useCallback, useEffect, useState } from 'react'
+import { usePageTitle, usePolling } from '@/hooks'
+import {
+ approveFederationDashboardApproval,
+ denyFederationDashboardApproval,
+ fetchFederationDashboard,
+ subscribeFederationDashboard,
+ type FleetActivityEvent,
+ type FleetApproval,
+ type FleetDashboardInstance,
+ type FleetTrustProposal,
+} from '@/api/federation'
+import { MetricCard } from '@/components/MetricCard'
+import { PageLoader } from '@/components/PageLoader'
+import { formatRelativeTime, formatTimestamp } from '@/utils/dateFormat'
+import { getErrorMessage } from '@/utils/errors'
+
+const STATE_STYLES: Record = {
+ healthy: {
+ border: 'border-state-healthy/70',
+ dot: 'bg-state-healthy',
+ text: 'text-state-healthy',
+ label: 'Healthy',
+ },
+ attention: {
+ border: 'border-state-warning/80',
+ dot: 'bg-state-warning',
+ text: 'text-state-warning',
+ label: 'Attention',
+ },
+ critical: {
+ border: 'border-state-error',
+ dot: 'bg-state-error',
+ text: 'text-state-error',
+ label: 'Critical',
+ },
+ paused: {
+ border: 'border-accent-primary',
+ dot: 'bg-accent-primary',
+ text: 'text-accent-primary',
+ label: 'Paused',
+ },
+}
+
+type DashboardDecision = 'approve' | 'deny'
+
+interface DecisionTarget {
+ decision: DashboardDecision
+ instanceId: string
+ approvalId: string
+ title: string
+ subtitle: string
+}
+
+function roleLabel(role: string): string {
+ if (!role) return 'PEER'
+ return role.toUpperCase()
+}
+
+function compactHash(hash: string): string {
+ return hash ? hash.slice(0, 10) : 'unavailable'
+}
+
+function formatHeartbeat(instance: FleetDashboardInstance): string {
+ if (instance.heartbeat_state === 'lost') return 'LOST'
+ if (instance.heartbeat_age_s === null) return instance.heartbeat_state.toUpperCase()
+ if (instance.heartbeat_age_s < 60) return `${Math.round(instance.heartbeat_age_s)}s ago`
+ return formatRelativeTime(instance.last_heartbeat_at)
+}
+
+function formatPct(value: number): string {
+ return `${Math.round(value)}%`
+}
+
+function instanceGridClass(count: number): string {
+ if (count <= 1) return 'grid grid-cols-1 gap-4 lg:max-w-2xl'
+ if (count === 2) return 'grid grid-cols-1 gap-4 lg:grid-cols-2 xl:max-w-5xl'
+ return 'grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-3'
+}
+
+function DetailPill({ label, value, tone = 'muted' }: {
+ label: string
+ value: string | number
+ tone?: 'muted' | 'warning' | 'error' | 'healthy'
+}) {
+ const toneClass = {
+ muted: 'text-text-secondary bg-surface-input',
+ warning: 'text-state-warning bg-state-warning/10',
+ error: 'text-state-error bg-state-error/10',
+ healthy: 'text-state-healthy bg-state-healthy/10',
+ }[tone]
+
+ return (
+
+ )
+}
+
+function InstanceCard({ instance }: { instance: FleetDashboardInstance }) {
+ const style = STATE_STYLES[instance.state]
+ const approvalTone = instance.pending_approvals > 0 ? 'warning' : 'muted'
+ const proposalTone = instance.trust_proposals > 0 ? 'warning' : 'muted'
+ const budgetTone = instance.budget_threshold === 'normal'
+ ? 'healthy'
+ : instance.budget_threshold === 'warning' || instance.budget_threshold === 'spawn_restricted'
+ ? 'warning'
+ : 'error'
+ const commandCenterUrl = instance.command_center_url || (instance.is_self ? '/war-room/command' : '')
+
+ return (
+
+
+
+
+
+ {instance.name}
+
+
+ {instance.instance_short_id || 'local'}
+
+
+
+ {style.label}
+
+ {instance.is_self ? 'SELF' : roleLabel(instance.role)}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Soul
+
+ {compactHash(instance.soul_version_hash)}
+
+
+
+
+
+
+
+ Latest Activity
+
+ {instance.recent_activity ? (
+
+ {instance.recent_activity}
+ {instance.recent_activity_at && (
+ ({formatRelativeTime(instance.recent_activity_at)})
+ )}
+
+ ) : (
+ No recent activity
+ )}
+
+
+ {instance.attention_reasons.length > 0 && (
+
+
+ Needs Attention
+
+ {instance.attention_reasons.slice(0, 4).map((reason) => (
+
+ {reason}
+
+ ))}
+
+ )}
+
+
+
+ )
+}
+
+function ApprovalsTable({
+ approvals,
+ onDecision,
+}: {
+ approvals: FleetApproval[]
+ onDecision: (target: DecisionTarget) => void
+}) {
+ if (approvals.length === 0) {
+ return (
+
+ Unified Approval Queue
+ No pending approvals
+
+ )
+ }
+
+ return (
+
+ Unified Approval Queue
+
+
+
+
+ | Instance |
+ Action |
+ Tier |
+ Capability |
+ Waiting |
+ Actions |
+
+
+
+ {approvals.map((item) => (
+
+ | {item.instance_name} |
+
+ {item.action_name}
+ {item.context && (
+
+ {item.context}
+
+ )}
+ |
+
+
+ {item.risk_tier || 'T3'}
+
+ |
+
+ {item.capability}
+ |
+ {formatRelativeTime(item.waiting_since || item.created_at)} |
+
+
+
+
+
+ |
+
+ ))}
+
+
+
+
+ )
+}
+
+function TrustTable({
+ proposals,
+ onDecision,
+}: {
+ proposals: FleetTrustProposal[]
+ onDecision: (target: DecisionTarget) => void
+}) {
+ if (proposals.length === 0) {
+ return (
+
+ Unified Trust Proposals
+ No pending trust proposals
+
+ )
+ }
+
+ return (
+
+ Unified Trust Proposals
+
+
+
+
+ | Instance |
+ Capability |
+ Current |
+ Proposed |
+ Successes |
+ Actions |
+
+
+
+ {proposals.map((item) => (
+
+ | {item.instance_name} |
+ {item.capability} |
+ T{item.current_tier} |
+ T{item.proposed_tier} |
+ {item.consecutive_successes} |
+
+
+
+
+
+ |
+
+ ))}
+
+
+
+
+ )
+}
+
+function ActivityFeed({ events }: { events: FleetActivityEvent[] }) {
+ return (
+
+ Fleet Activity
+ {events.length === 0 ? (
+ No recent fleet activity
+ ) : (
+
+ {events.slice(0, 40).map((event) => (
+
+
+
+ {event.description}
+ {event.instance_name} - {event.event_type}
+
+
+ {formatRelativeTime(event.timestamp)}
+
+
+
+ ))}
+
+ )}
+
+ )
+}
+
+function DecisionDialog({
+ target,
+ reason,
+ error,
+ submitting,
+ onReasonChange,
+ onCancel,
+ onConfirm,
+}: {
+ target: DecisionTarget | null
+ reason: string
+ error: Error | null
+ submitting: boolean
+ onReasonChange: (value: string) => void
+ onCancel: () => void
+ onConfirm: () => void
+}) {
+ if (!target) return null
+
+ const label = target.decision === 'approve' ? 'Approve' : 'Deny'
+ const confirmClass = target.decision === 'approve'
+ ? 'border-state-healthy/70 text-state-healthy hover:bg-state-healthy/10'
+ : 'border-state-error/70 text-state-error hover:bg-state-error/10'
+
+ return (
+
+
+
+ {label} Decision
+
+ {target.title}
+
+ {target.subtitle}
+
+
+
+
+
+ )
+}
+
+export function FleetDashboard() {
+ usePageTitle('Fleet Dashboard')
+ const [streamData, setStreamData] = useState> | null>(null)
+ const [streamConnected, setStreamConnected] = useState(false)
+ const [streamError, setStreamError] = useState(null)
+ const [decisionTarget, setDecisionTarget] = useState(null)
+ const [decisionReason, setDecisionReason] = useState('')
+ const [decisionError, setDecisionError] = useState(null)
+ const [decisionSubmitting, setDecisionSubmitting] = useState(false)
+ const pollingIntervalMs = Math.max(
+ 2000,
+ Math.round((streamData?.dashboard.poll_interval_s ?? 10) * 1000),
+ )
+ const { data: polledData, error: pollingError, loading, refetch } = usePolling({
+ fetcher: fetchFederationDashboard,
+ interval: pollingIntervalMs,
+ enabled: !streamConnected || !streamData,
+ })
+ const data = streamConnected && streamData ? streamData : polledData ?? streamData
+ const error = streamConnected ? streamError : pollingError ?? streamError
+
+ useEffect(() => subscribeFederationDashboard(
+ (snapshot) => {
+ setStreamData(snapshot)
+ setStreamError(null)
+ },
+ setStreamError,
+ setStreamConnected,
+ ), [])
+
+ const openDecision = useCallback((target: DecisionTarget) => {
+ setDecisionTarget(target)
+ setDecisionReason('')
+ setDecisionError(null)
+ }, [])
+
+ const closeDecision = useCallback(() => {
+ if (decisionSubmitting) return
+ setDecisionTarget(null)
+ setDecisionReason('')
+ setDecisionError(null)
+ }, [decisionSubmitting])
+
+ const confirmDecision = useCallback(async () => {
+ if (!decisionTarget || !decisionReason.trim()) return
+
+ setDecisionSubmitting(true)
+ setDecisionError(null)
+ try {
+ if (decisionTarget.decision === 'approve') {
+ await approveFederationDashboardApproval(
+ decisionTarget.instanceId,
+ decisionTarget.approvalId,
+ decisionReason,
+ )
+ } else {
+ await denyFederationDashboardApproval(
+ decisionTarget.instanceId,
+ decisionTarget.approvalId,
+ decisionReason,
+ )
+ }
+ setDecisionTarget(null)
+ setDecisionReason('')
+ if (streamConnected) {
+ setStreamData(await fetchFederationDashboard())
+ } else {
+ refetch()
+ }
+ } catch (err) {
+ setDecisionError(err instanceof Error ? err : new Error(String(err)))
+ } finally {
+ setDecisionSubmitting(false)
+ }
+ }, [decisionReason, decisionTarget, refetch, streamConnected])
+
+ if (loading && !data) return
+
+ if (!data && error) {
+ return (
+
+ Fleet Dashboard
+
+ {getErrorMessage(error, 'Failed to load fleet dashboard')}
+
+
+ )
+ }
+
+ if (!data) return null
+
+ if (!data.enabled) {
+ return (
+
+ Fleet Dashboard
+
+
+ {data.disabled_reason || 'Federation Dashboard is disabled'}
+
+
+
+ )
+ }
+
+ return (
+
+
+
+ Fleet Dashboard
+
+ Updated {formatTimestamp(data.generated_at)}
+
+ {streamConnected ? 'Live' : 'Polling'}
+
+
+
+ {error && (
+
+ {getErrorMessage(error, 'Latest refresh failed')}
+
+ )}
+
+
+
+
+
+
+
+
+
+
+
+ {data.errors.length > 0 && (
+
+ Remote Detail Warnings
+
+ {data.errors.map((item) => (
+
+ {item.instance_id}: {item.message}
+
+ ))}
+
+
+ )}
+
+
+
+ Instances
+
+ Soul {data.fleet.soul_consistency.toUpperCase()} - Budget {data.fleet.budget_threshold}
+
+
+
+ {data.instances.map((instance) => (
+
+ ))}
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/src/warroom/src/pages/LoginCallbackPage.tsx b/src/warroom/src/pages/LoginCallbackPage.tsx
index 2a1064e..9c15581 100644
--- a/src/warroom/src/pages/LoginCallbackPage.tsx
+++ b/src/warroom/src/pages/LoginCallbackPage.tsx
@@ -2,6 +2,15 @@ import { useEffect, useState } from 'react'
import { useNavigate } from 'react-router-dom'
import { exchangeOidcLogin } from '@/api/auth'
+function isSafeReturnPath(value: unknown): value is string {
+ return (
+ typeof value === 'string'
+ && value.startsWith('/')
+ && !value.startsWith('//')
+ && !value.startsWith('/login')
+ )
+}
+
export function LoginCallbackPage() {
const navigate = useNavigate()
const [error, setError] = useState('')
@@ -10,6 +19,13 @@ export function LoginCallbackPage() {
const hash = new URLSearchParams(window.location.hash.replace(/^#/, ''))
const exchangeCode = hash.get('exchange_code') || ''
const callbackError = hash.get('error') || ''
+ const hashReturnTo = hash.get('return_to')
+ const storedReturnTo = window.sessionStorage.getItem('warRoomReturnTo')
+ const returnTo = isSafeReturnPath(hashReturnTo)
+ ? hashReturnTo
+ : isSafeReturnPath(storedReturnTo)
+ ? storedReturnTo
+ : '/command'
if (callbackError) {
setError(callbackError.replace(/_/g, ' '))
@@ -23,7 +39,8 @@ export function LoginCallbackPage() {
exchangeOidcLogin(exchangeCode)
.then(() => {
- navigate('/command', { replace: true })
+ window.sessionStorage.removeItem('warRoomReturnTo')
+ navigate(returnTo, { replace: true })
})
.catch((err) => {
setError(err instanceof Error ? err.message : 'Enterprise login failed')
diff --git a/src/warroom/src/pages/LoginPage.tsx b/src/warroom/src/pages/LoginPage.tsx
index 5f8cb21..a1771f7 100644
--- a/src/warroom/src/pages/LoginPage.tsx
+++ b/src/warroom/src/pages/LoginPage.tsx
@@ -1,5 +1,5 @@
import { useEffect, useState, type FormEvent } from 'react'
-import { useNavigate } from 'react-router-dom'
+import { useLocation, useNavigate } from 'react-router-dom'
import {
getAuthConfig,
getOidcLoginUrl,
@@ -12,8 +12,18 @@ import { ApiClientError } from '@/api/client'
import logo from '@/assets/logo.jpeg'
import { getErrorMessage } from '@/utils/errors'
+function isSafeReturnPath(value: unknown): value is string {
+ return (
+ typeof value === 'string'
+ && value.startsWith('/')
+ && !value.startsWith('//')
+ && !value.startsWith('/login')
+ )
+}
+
export function LoginPage() {
const navigate = useNavigate()
+ const location = useLocation()
const [authConfig, setAuthConfig] = useState(null)
const [username, setUsername] = useState('')
const [password, setPassword] = useState('')
@@ -23,6 +33,13 @@ export function LoginPage() {
const [error, setError] = useState('')
const [loading, setLoading] = useState(false)
const [resetMode, setResetMode] = useState(false)
+ const stateReturnTo = (location.state as { returnTo?: unknown } | null)?.returnTo
+ const queryReturnTo = new URLSearchParams(location.search).get('return_to')
+ const returnTo = isSafeReturnPath(stateReturnTo)
+ ? stateReturnTo
+ : isSafeReturnPath(queryReturnTo)
+ ? queryReturnTo
+ : '/command'
useEffect(() => {
document.title = 'Sign In | Lancelot War Room'
@@ -36,7 +53,7 @@ export function LoginPage() {
validateSession()
.then((session) => {
if (!cancelled && session.valid) {
- navigate('/command', { replace: true })
+ navigate(returnTo, { replace: true })
}
})
.catch((error) => {
@@ -49,7 +66,7 @@ export function LoginPage() {
return () => {
cancelled = true
}
- }, [navigate])
+ }, [navigate, returnTo])
useEffect(() => {
let cancelled = false
@@ -77,7 +94,7 @@ export function LoginPage() {
setLoading(true)
try {
await login(username, password)
- navigate('/command', { replace: true })
+ navigate(returnTo, { replace: true })
} catch (err) {
setError(err instanceof Error ? err.message : 'Login failed')
} finally {
@@ -288,6 +305,9 @@ export function LoginPage() {
{
+ window.sessionStorage.setItem('warRoomReturnTo', returnTo)
+ }}
className="block w-full py-2.5 bg-accent-primary hover:bg-accent-primary/90 text-white text-sm font-medium rounded-lg transition-colors text-center"
>
{authConfig?.oidc.display_name || 'Continue with Enterprise SSO'}
diff --git a/src/warroom/src/pages/index.ts b/src/warroom/src/pages/index.ts
index a709780..9ab92f8 100644
--- a/src/warroom/src/pages/index.ts
+++ b/src/warroom/src/pages/index.ts
@@ -18,6 +18,7 @@ export { SkillsPanel } from './SkillsPanel'
export { HiveAgentMesh } from './HiveAgentMesh'
export { LoginPage } from './LoginPage'
export { LoginCallbackPage } from './LoginCallbackPage'
+export { FleetDashboard } from './FleetDashboard'
export { FederationOverview } from './FederationOverview'
export { GraphBuilder } from './GraphBuilder'
export { FederationAudit } from './FederationAudit'
diff --git a/tests/federation/test_api.py b/tests/federation/test_api.py
index 5b34c89..0c62a0d 100644
--- a/tests/federation/test_api.py
+++ b/tests/federation/test_api.py
@@ -40,7 +40,7 @@ def app():
auth_method="local",
ip_address="127.0.0.1",
),
- "capabilities": sorted({"warroom.login", "federation.admin"}),
+ "capabilities": sorted({"warroom.login", "federation.admin", "governance.admin"}),
"groups": [],
}
test_app = FastAPI()
@@ -904,6 +904,384 @@ def test_update_settings_rejects_invalid_address(self, client, identity, emitter
resp = client.put("/api/federation/settings", json={"self_address": "notaurl"})
assert resp.status_code == 400
+ def test_dashboard_returns_self_command_center_entry(self, client, identity, emitter, config, monkeypatch):
+ import feature_flags as ff
+
+ monkeypatch.setattr(ff, "FEATURE_FEDERATION", True)
+ monkeypatch.setattr(ff, "FEATURE_FEDERATION_DASHBOARD", True)
+ config.self_address = "https://root.example"
+ init_federation_api(identity, emitter, config)
+ emitter.emit_once()
+
+ resp = client.get("/api/federation/dashboard")
+
+ assert resp.status_code == 200
+ data = resp.json()
+ assert data["enabled"] is True
+ assert data["fleet"]["total_instances"] == 1
+ assert data["instances"][0]["is_self"] is True
+ assert data["instances"][0]["command_center_url"] == "/war-room/command"
+
+ def test_dashboard_activity_feed_uses_receipt_service_for_agent_events(self, client, identity, emitter, config, monkeypatch):
+ import feature_flags as ff
+ from src.core import receipts_api
+ from src.shared.receipts import ActionType, Receipt, ReceiptStatus
+
+ monkeypatch.setattr(ff, "FEATURE_FEDERATION", True)
+ monkeypatch.setattr(ff, "FEATURE_FEDERATION_DASHBOARD", True)
+ receipt = Receipt(
+ id="receipt-agent-1",
+ timestamp="2026-04-30T12:00:00+00:00",
+ action_type=ActionType.HIVE_AGENT_EVENT.value,
+ action_name="",
+ status=ReceiptStatus.SUCCESS.value,
+ metadata={"event": "hive_agent_spawned", "operator_id": "op-arthur"},
+ )
+
+ class FakeReceiptService:
+ def list(self, limit=100, **kwargs):
+ return [receipt]
+
+ monkeypatch.setattr(receipts_api, "_receipt_service", FakeReceiptService())
+ init_federation_api(identity, emitter, config)
+ emitter.emit_once()
+
+ resp = client.get("/api/federation/dashboard")
+
+ assert resp.status_code == 200
+ data = resp.json()
+ assert data["activity"][0]["id"] == "receipt-agent-1"
+ assert data["activity"][0]["event_type"] == ActionType.HIVE_AGENT_EVENT.value
+ assert data["activity"][0]["description"] == "hive_agent_spawned"
+ assert data["activity"][0]["operator"] == "op-arthur"
+ assert data["instances"][0]["recent_activity"] == "hive_agent_spawned"
+
+ def test_dashboard_approval_queue_includes_pending_sentry_request(self, client, identity, emitter, config, monkeypatch, tmp_path):
+ import feature_flags as ff
+ from src.core import governance_api
+ from src.integrations.mcp_sentry import MCPSentry
+
+ monkeypatch.setattr(ff, "FEATURE_FEDERATION", True)
+ monkeypatch.setattr(ff, "FEATURE_FEDERATION_DASHBOARD", True)
+ sentry = MCPSentry(data_dir=str(tmp_path))
+ pending = sentry.check_permission(
+ "connector.email.send_message",
+ {"recipient": "customer@example.com", "subject": "Fleet approval test"},
+ )
+ assert pending["status"] == "PENDING"
+ monkeypatch.setattr(governance_api, "_mcp_sentry", sentry)
+ init_federation_api(identity, emitter, config)
+ emitter.emit_once()
+
+ resp = client.get("/api/federation/dashboard")
+
+ assert resp.status_code == 200
+ data = resp.json()
+ approval = next(item for item in data["approvals"] if item["id"] == pending["request_id"])
+ assert approval["instance_id"] == identity.instance_id
+ assert approval["capability"] == "connector.email.send_message"
+ assert approval["risk_tier"] == "T3"
+ assert data["fleet"]["pending_approvals"] == 1
+ assert data["instances"][0]["pending_approvals"] == 1
+
+ def test_dashboard_ignores_stale_cost_for_unregistered_peers(self, client, identity, emitter, config, monkeypatch):
+ import feature_flags as ff
+
+ monkeypatch.setattr(ff, "FEATURE_FEDERATION", True)
+ monkeypatch.setattr(ff, "FEATURE_FEDERATION_DASHBOARD", True)
+ init_federation_api(identity, emitter, config)
+ federation_api._divergence_detector = SimpleNamespace(
+ state=SimpleNamespace(value="connected"),
+ get_divergence_duration_s=lambda: 0.0,
+ last_reconciliation=None,
+ )
+ init_federation_transport(
+ soul_transport=SimpleNamespace(
+ get_consistency_state=lambda: "synchronized",
+ get_active_propagations=lambda: [],
+ get_local_soul_hash=lambda: "root-soul",
+ ),
+ cost_reporter=SimpleNamespace(
+ running=True,
+ get_aggregate_status=lambda: {
+ "threshold": "normal",
+ "stale_instance_ids": ["retired-peer"],
+ },
+ ),
+ transport=SimpleNamespace(
+ started=True,
+ get_circuit_breaker_states=lambda: {},
+ ),
+ heartbeat_mesh=SimpleNamespace(
+ running=True,
+ get_subscription_status=lambda: {},
+ get_stream_outcome_status=lambda: {},
+ get_stream_errors=lambda: {},
+ divergence_evaluation_failed=False,
+ divergence_status_error=None,
+ ),
+ )
+ emitter.emit_once()
+
+ resp = client.get("/api/federation/dashboard")
+
+ assert resp.status_code == 200
+ data = resp.json()
+ local = data["instances"][0]
+ assert local["health"] == "healthy"
+ assert local["state"] == "healthy"
+ assert data["fleet"]["instances_needing_attention"] == 0
+ assert all("cost data stale" not in reason.lower() for reason in local["attention_reasons"])
+
+ def test_dashboard_formats_current_peer_cost_staleness_as_attention_notice(self, client, identity, emitter, config, monkeypatch):
+ import feature_flags as ff
+ from src.federation.topology import TopologyRegistry
+
+ monkeypatch.setattr(ff, "FEATURE_FEDERATION", True)
+ monkeypatch.setattr(ff, "FEATURE_FEDERATION_DASHBOARD", True)
+ topology = TopologyRegistry(identity.instance_id)
+ topology.register_peer(
+ "peer-1",
+ fingerprint="fp-1",
+ public_key_hex="abcd",
+ address="https://peer.example",
+ role="child",
+ soul_version_hash="root-soul",
+ )
+ init_federation_api(identity, emitter, config, topology_registry=topology)
+ federation_api._divergence_detector = SimpleNamespace(
+ state=SimpleNamespace(value="connected"),
+ get_divergence_duration_s=lambda: 0.0,
+ last_reconciliation=None,
+ )
+ init_federation_transport(
+ soul_transport=SimpleNamespace(
+ get_consistency_state=lambda: "synchronized",
+ get_active_propagations=lambda: [],
+ get_local_soul_hash=lambda: "root-soul",
+ ),
+ cost_reporter=SimpleNamespace(
+ running=True,
+ get_aggregate_status=lambda: {
+ "threshold": "normal",
+ "stale_instance_ids": ["peer-1"],
+ },
+ ),
+ transport=SimpleNamespace(
+ started=True,
+ get_circuit_breaker_states=lambda: {},
+ ),
+ heartbeat_mesh=SimpleNamespace(
+ running=True,
+ get_subscription_status=lambda: {},
+ get_stream_outcome_status=lambda: {},
+ get_stream_errors=lambda: {},
+ divergence_evaluation_failed=False,
+ divergence_status_error=None,
+ ),
+ )
+ emitter.emit_once()
+
+ resp = client.get("/api/federation/dashboard")
+
+ assert resp.status_code == 200
+ data = resp.json()
+ local = next(item for item in data["instances"] if item["is_self"])
+ assert local["health"] == "healthy"
+ assert "Cost telemetry stale for peer.example" in local["attention_reasons"]
+ assert all("Federation cost data stale" not in reason for reason in local["attention_reasons"])
+
+ def test_dashboard_surfaces_peer_command_center_fallback(self, client, identity, emitter, config, monkeypatch):
+ import feature_flags as ff
+ from src.federation.topology import TopologyRegistry
+
+ monkeypatch.setattr(ff, "FEATURE_FEDERATION", True)
+ monkeypatch.setattr(ff, "FEATURE_FEDERATION_DASHBOARD", True)
+ topology = TopologyRegistry(identity.instance_id)
+ topology.register_peer(
+ "peer-1",
+ fingerprint="fp-1",
+ public_key_hex="abcd",
+ address="https://peer.example",
+ role="child",
+ soul_version_hash="peer-soul",
+ )
+ topology.update_heartbeat("peer-1", soul_version_hash="peer-soul")
+ init_federation_api(identity, emitter, config, topology_registry=topology)
+ emitter.emit_once()
+
+ resp = client.get("/api/federation/dashboard")
+
+ assert resp.status_code == 200
+ data = resp.json()
+ peer = next(item for item in data["instances"] if item["instance_id"] == "peer-1")
+ assert peer["command_center_url"] == "https://peer.example/war-room/command"
+ assert peer["detail_status"] == "unavailable"
+ assert any("Remote detail unavailable" in reason for reason in peer["attention_reasons"])
+
+ def test_dashboard_local_approval_uses_operator_identity(self, client, identity, emitter, config, monkeypatch):
+ import feature_flags as ff
+ from src.core import governance_api
+
+ monkeypatch.setattr(ff, "FEATURE_FEDERATION", True)
+ monkeypatch.setattr(ff, "FEATURE_FEDERATION_DASHBOARD", True)
+ init_federation_api(identity, emitter, config)
+ recorded = {}
+
+ def fake_approve(approval_id, *, reason="", identity=None):
+ recorded["approval_id"] = approval_id
+ recorded["reason"] = reason
+ recorded["operator_id"] = identity.operator_id if identity else ""
+ return {"status": "approved", "id": approval_id, "type": "sentry"}
+
+ monkeypatch.setattr(governance_api, "_approve_item_direct", fake_approve)
+
+ resp = client.post(
+ f"/api/federation/dashboard/instances/{identity.instance_id}/approvals/ap-1/approve",
+ json={"reason": "operator reviewed the action"},
+ )
+
+ assert resp.status_code == 200
+ assert resp.json()["result"]["status"] == "approved"
+ assert recorded == {
+ "approval_id": "ap-1",
+ "reason": "operator reviewed the action",
+ "operator_id": "op-arthur",
+ }
+
+ def test_dashboard_remote_approval_proxies_operator_identity(self, client, identity, emitter, config, monkeypatch):
+ import feature_flags as ff
+ from src.federation.topology import TopologyRegistry
+
+ monkeypatch.setattr(ff, "FEATURE_FEDERATION", True)
+ monkeypatch.setattr(ff, "FEATURE_FEDERATION_DASHBOARD", True)
+ topology = TopologyRegistry(identity.instance_id)
+ topology.register_peer(
+ "peer-1",
+ fingerprint="fp-1",
+ public_key_hex="abcd",
+ address="https://peer.example",
+ role="child",
+ soul_version_hash="peer-soul",
+ )
+ init_federation_api(identity, emitter, config, topology_registry=topology)
+ recorded = {}
+
+ class FakeTransport:
+ async def send(self, **kwargs):
+ recorded.update(kwargs)
+ return SimpleNamespace(
+ success=True,
+ status_code=200,
+ body={
+ "success": True,
+ "result": {"status": "approved", "id": "ap-1", "type": "sentry"},
+ },
+ error="",
+ )
+
+ init_federation_transport(transport=FakeTransport())
+
+ resp = client.post(
+ "/api/federation/dashboard/instances/peer-1/approvals/ap-1/approve",
+ json={"reason": "operator reviewed the remote action"},
+ )
+
+ assert resp.status_code == 200
+ assert recorded["method"] == "POST"
+ assert recorded["path"] == "/api/federation/dashboard/local/approvals/ap-1/approve"
+ assert recorded["body"]["reason"] == "operator reviewed the remote action"
+ assert recorded["body"]["operator_identity"]["operator_id"] == "op-arthur"
+ assert recorded["body"]["source_instance_id"] == identity.instance_id
+
+ def test_dashboard_local_detail_rejects_non_root_peer(self, app, identity, emitter, config, monkeypatch):
+ import feature_flags as ff
+ from src.federation.topology import TopologyRegistry
+
+ monkeypatch.setattr(ff, "FEATURE_FEDERATION", True)
+ monkeypatch.setattr(ff, "FEATURE_FEDERATION_DASHBOARD", True)
+ api_auth.init_api_auth(lambda request: False)
+ client = TestClient(app)
+ topology = TopologyRegistry(identity.instance_id)
+ topology.register_peer(
+ "peer-1",
+ fingerprint="fp-1",
+ public_key_hex="abcd",
+ address="https://peer.example",
+ role="peer",
+ soul_version_hash="peer-soul",
+ )
+ init_federation_api(identity, emitter, config, topology_registry=topology)
+
+ class FakeAuth:
+ def verify_request(self, method, path, body, headers):
+ return SimpleNamespace(valid=True, reason="", instance_id="peer-1")
+
+ init_federation_transport(auth=FakeAuth())
+
+ resp = client.get("/api/federation/dashboard/local")
+
+ assert resp.status_code == 403
+ assert "ROOT" in resp.json()["detail"]
+
+ def test_dashboard_local_approval_accepts_root_peer_identity_payload(self, app, identity, emitter, config, monkeypatch):
+ import feature_flags as ff
+ from src.core import governance_api
+ from src.federation.topology import TopologyRegistry
+
+ monkeypatch.setattr(ff, "FEATURE_FEDERATION", True)
+ monkeypatch.setattr(ff, "FEATURE_FEDERATION_DASHBOARD", True)
+ api_auth.init_api_auth(lambda request: False)
+ client = TestClient(app)
+ topology = TopologyRegistry(identity.instance_id)
+ topology.register_peer(
+ "root-1",
+ fingerprint="fp-root",
+ public_key_hex="abcd",
+ address="https://root.example",
+ role="root",
+ soul_version_hash="root-soul",
+ )
+ init_federation_api(identity, emitter, config, topology_registry=topology)
+ recorded = {}
+
+ class FakeAuth:
+ def verify_request(self, method, path, body, headers):
+ return SimpleNamespace(valid=True, reason="", instance_id="root-1")
+
+ def fake_approve(approval_id, *, reason="", identity=None):
+ recorded["approval_id"] = approval_id
+ recorded["reason"] = reason
+ recorded["operator_id"] = identity.operator_id if identity else ""
+ return {"status": "approved", "id": approval_id, "type": "sentry"}
+
+ init_federation_transport(auth=FakeAuth())
+ monkeypatch.setattr(governance_api, "_approve_item_direct", fake_approve)
+
+ resp = client.post(
+ "/api/federation/dashboard/local/approvals/ap-1/approve",
+ json={
+ "reason": "root operator approved",
+ "operator_identity": {
+ "operator_id": "op-root",
+ "display_name": "Root Operator",
+ "session_id": "session-root",
+ "session_started_at": "2026-04-10T00:00:00Z",
+ "auth_method": "local",
+ "ip_address": "127.0.0.1",
+ },
+ "source_instance_id": "root-1",
+ },
+ )
+
+ assert resp.status_code == 200
+ assert resp.json()["result"]["status"] == "approved"
+ assert recorded == {
+ "approval_id": "ap-1",
+ "reason": "root operator approved",
+ "operator_id": "op-root",
+ }
+
class TestHeartbeatEndpoint:
"""Test the heartbeat snapshot endpoint."""
diff --git a/tests/test_composition_coverage.py b/tests/test_composition_coverage.py
index 1e03441..70f2143 100644
--- a/tests/test_composition_coverage.py
+++ b/tests/test_composition_coverage.py
@@ -616,11 +616,12 @@ async def test_boot_composition_root_registers_core_subsystems_without_optional_
)
try:
+ monkeypatch.setenv("LANCELOT_PROVIDER", "gemini")
result = await boot.boot(app, boot.BootConfig())
assert result.env.provider in {"", "gemini"}
assert librarian.started is True
- assert antigravity.started is True
+ assert antigravity.started is False
assert {"memory", "soul", "skills", "scheduler", "health_monitor", "hive"}.issubset(
subsystem_manager.registered
)
diff --git a/tests/test_providers_api.py b/tests/test_providers_api.py
index 6e1cdda..544926e 100644
--- a/tests/test_providers_api.py
+++ b/tests/test_providers_api.py
@@ -242,12 +242,12 @@ def test_refresh_and_switch_provider_handle_errors_and_initialize_discovery(monk
orchestrator = _FakeOrchestrator()
providers_api.init_provider_api(None, orchestrator)
monkeypatch.setenv("OPENAI_API_KEY", "openai-secret")
- monkeypatch.setattr(providers_api, "_provider_profile_lane_overrides", lambda provider: {"fast": "gpt-fast"})
+ monkeypatch.setattr(providers_api, "_provider_profile_lane_defaults", lambda provider: {"fast": "gpt-fast"})
created = []
class _ModelDiscovery:
- def __init__(self, provider, lane_overrides=None):
- created.append((provider, lane_overrides))
+ def __init__(self, provider, lane_overrides=None, fallback_lanes=None):
+ created.append((provider, lane_overrides, fallback_lanes))
self.provider_name = "openai"
self.lane_assignments = lane_overrides or {}
self.discovered_models = []
@@ -277,7 +277,8 @@ def get_stack(self):
assert body["message"] == "switched:openai"
assert body["stack"]["provider"] == "openai"
assert orchestrator.switch_calls == ["openai"]
- assert created[0][1] == {"fast": "gpt-fast"}
+ assert created[0][1] == {}
+ assert created[0][2] == {"fast": "gpt-fast"}
assert created[1] == "refresh"
assert providers_api.load_persisted_config()["active_provider"] == "openai"
diff --git a/tests/test_support_module_coverage.py b/tests/test_support_module_coverage.py
index af33df9..a1eb7b5 100644
--- a/tests/test_support_module_coverage.py
+++ b/tests/test_support_module_coverage.py
@@ -1788,6 +1788,64 @@ def list_models(self):
assert discovery.get_stack()["provider"] == "broken"
+def test_model_discovery_profile_fallbacks_do_not_pin_newer_models(tmp_path):
+ from providers.base import ModelInfo
+ from model_discovery import ModelDiscovery
+
+ profiles = tmp_path / "profiles.yaml"
+ profiles.write_text(
+ """
+profiles:
+ gpt-5.4:
+ capability_tier: deep
+ context_window: 1000000
+ supports_tools: true
+ cost_output_per_1k: 0.015
+ gpt-5.5:
+ capability_tier: deep
+ context_window: 1000000
+ supports_tools: true
+ cost_output_per_1k: 0.03
+""",
+ encoding="utf-8",
+ )
+
+ class Provider:
+ provider_name = "openai"
+
+ def list_models(self):
+ return [
+ ModelInfo(id="gpt-5.4", display_name="GPT-5.4", supports_tools=True),
+ ModelInfo(id="gpt-5.5", display_name="GPT-5.5", supports_tools=True),
+ ]
+
+ discovery = ModelDiscovery(
+ Provider(),
+ profiles_path=str(profiles),
+ fallback_lanes={"deep": "gpt-5.4"},
+ )
+ discovery.refresh()
+
+ assert discovery.get_lane_model("deep") == "gpt-5.5"
+ assert discovery.get_stack()["lanes"]["deep"]["source"] == "auto"
+
+ class FailingProvider:
+ provider_name = "openai"
+
+ def list_models(self):
+ raise RuntimeError("provider unavailable")
+
+ fallback = ModelDiscovery(
+ FailingProvider(),
+ profiles_path=str(profiles),
+ fallback_lanes={"deep": "gpt-5.4"},
+ )
+ fallback.refresh()
+
+ assert fallback.get_lane_model("deep") == "gpt-5.4"
+ assert fallback.get_stack()["lanes"]["deep"]["source"] == "fallback"
+
+
def test_soul_template_registry_loads_filters_applies_and_invalidates(tmp_path, monkeypatch):
from src.core.soul import amendments, linter, store, templates
|