Intelligence

Artifacts

Browse the repository, read documents, and manage the governance folders. Source, runtime, and infrastructure are read-only.

Repository
README.md
CONSTITUTION_COMPLIANCE_AUDIT_V1.mdREADME.md
repositories/aaf-holdings/hq01/lib/mission-control/overview.ts
8.0 KB
import { listMissions } from "@/lib/missions/manager";
import { readHistory } from "@/lib/missions/store";
import { listObjectives, missionProgress } from "@/lib/missions/objectives";
import { listWorkOrders } from "@/lib/missions/work-orders";
import { listAssignments } from "@/lib/missions/assignments";
import { listReportsForMission } from "@/lib/missions/reports";
import {
  listRisks,
  listDependencies,
  listKpis,
  missionBlockReasons,
} from "@/lib/missions/governance";
import { listAssets } from "@/lib/assets/ledger";
import { listInstances } from "@/lib/workers/instances";
import { getTemplate } from "@/lib/workers/templates";
import { listSessions, getSession } from "@/lib/sessions/manager";
import { loadRegistry } from "@/lib/executives/registry";
import type {
  Mission,
  MissionStatus,
  Report,
} from "@/lib/missions/types";
import type { WorkerInstance } from "@/lib/workers/types";
import type { Asset } from "@/lib/assets/types";

/**
 * Mission Control composition (PASS M8). Read-only: it composes the existing
 * Mission OS into the headquarters view and never creates or stores new data.
 * The mission/assignment pages remain the place where state is reconciled and
 * mutated; this view reflects current state and cross-checks session liveness
 * so "running" is honest.
 */

const OPEN_STATES: MissionStatus[] = [
  "Draft", "Proposed", "Approved", "Planning", "Active", "Blocked", "Review",
];
const NON_TERMINAL = (s: MissionStatus) => s !== "Archived" && s !== "Cancelled";

function durationFrom(start: string | null, end: string | null): string {
  if (!start) return "—";
  const endMs = end ? Date.parse(end) : Date.now();
  const secs = Math.max(0, Math.round((endMs - Date.parse(start)) / 1000));
  return secs >= 60 ? `${Math.floor(secs / 60)}m ${secs % 60}s` : `${secs}s`;
}

export interface PortfolioRow {
  mission: Mission;
  progress: { completed: number; total: number; percentage: number };
  workerCount: number;
  openRisks: number;
  blockReasons: number;
  recentActivity: string | null;
}

export interface WorkerRow {
  instance: WorkerInstance;
  templateName: string;
  missionTitle: string;
  runtime: string;
  reportStatus: string;
}

export interface ExecRow {
  id: string;
  displayName: string;
  office: string;
  status: string;
  missionCount: number;
  workerCount: number;
  lastReport: string | null;
  lastActivity: string | null;
}

export interface MissionControl {
  header: { activeSessions: number; runningWorkers: number; openMissions: number };
  portfolio: PortfolioRow[];
  execution: { running: WorkerRow[]; recentCompleted: WorkerRow[]; failed: WorkerRow[] };
  attention: {
    blockedMissions: Mission[];
    criticalRisks: { missionId: string; title: string }[];
    activeBlockingDeps: { missionId: string; detail: string }[];
    offTrackKpis: { missionId: string; name: string }[];
    reviewRequired: Mission[];
  };
  executives: ExecRow[];
  recentReports: Report[];
  recentAssets: Asset[];
  health: {
    byState: Record<string, number>;
    objectivesCompletePct: number;
    openWorkOrders: number;
    assignments: number;
    workerInstances: number;
  };
}

export function getMissionControl(): MissionControl {
  const missions = listMissions();
  const missionById = new Map(missions.map((m) => [m.id, m]));
  const allInstances = listInstances();
  const allAssets = listAssets();

  // A worker is genuinely running only if its session is still alive.
  const sessionAlive = new Map<string, boolean>();
  const aliveOf = (sid: string | null): boolean => {
    if (!sid) return false;
    if (!sessionAlive.has(sid)) {
      const s = getSession(sid);
      sessionAlive.set(sid, s?.status === "running" || s?.status === "starting");
    }
    return sessionAlive.get(sid)!;
  };

  const workerRow = (i: WorkerInstance): WorkerRow => ({
    instance: i,
    templateName: getTemplate(i.template_id)?.name ?? i.template_id,
    missionTitle: missionById.get(i.mission_id)?.title ?? i.mission_id,
    runtime: durationFrom(i.started_at, i.completed_at),
    reportStatus: i.report_id ? `report ${i.report_id.replace("REPORT-", "R-")}` : i.status,
  });

  const running = allInstances.filter((i) => i.status === "Running" && aliveOf(i.session_id));
  const recentCompleted = allInstances
    .filter((i) => i.status === "Terminated" || i.status === "Completed")
    .slice(0, 8);
  const failed = allInstances.filter((i) => i.status === "Failed").slice(0, 8);

  // Aggregate reports + governance across missions.
  const allReports: Report[] = [];
  const criticalRisks: { missionId: string; title: string }[] = [];
  const activeBlockingDeps: { missionId: string; detail: string }[] = [];
  const offTrackKpis: { missionId: string; name: string }[] = [];
  let openWorkOrders = 0;
  let assignmentCount = 0;
  let objCompleted = 0;
  let objTotal = 0;

  const portfolio: PortfolioRow[] = missions.map((m) => {
    const progress = missionProgress(m.id);
    objCompleted += progress.completed;
    objTotal += progress.total;

    const wos = listWorkOrders(m.id);
    openWorkOrders += wos.filter(
      (w) => !["Completed", "Cancelled", "Archived"].includes(w.status),
    ).length;
    assignmentCount += listAssignments(m.id).length;

    for (const r of listReportsForMission(m.id)) allReports.push(r);

    const risks = listRisks(m.id);
    const openRisks = risks.filter(
      (r) => !["Resolved", "Closed", "Accepted"].includes(r.status),
    ).length;
    for (const r of risks) {
      if (r.severity === "Critical" && !["Resolved", "Closed", "Accepted"].includes(r.status))
        criticalRisks.push({ missionId: m.id, title: r.title });
    }
    for (const d of listDependencies(m.id)) {
      if (d.blocking && d.status === "Active")
        activeBlockingDeps.push({ missionId: m.id, detail: `${d.type}: ${d.depends_on}` });
    }
    for (const k of listKpis(m.id)) {
      if (k.status === "Off Track") offTrackKpis.push({ missionId: m.id, name: k.name });
    }

    const hist = readHistory(m.id).sort((a, b) => b.at.localeCompare(a.at));
    const recentActivity = hist[0]
      ? `${hist[0].type.replace(/_/g, " ")} · ${new Date(hist[0].at).toLocaleString()}`
      : null;

    return {
      mission: m,
      progress,
      workerCount: running.filter((i) => i.mission_id === m.id).length,
      openRisks,
      blockReasons: missionBlockReasons(m.id).length,
      recentActivity,
    };
  });

  allReports.sort((a, b) => b.created_at.localeCompare(a.created_at));

  // Executives.
  const executives: ExecRow[] = loadRegistry().map((e) => {
    const execReports = allReports.filter((r) => r.executive === e.id);
    return {
      id: e.id,
      displayName: e.displayName,
      office: e.office,
      status: e.status,
      missionCount: missions.filter((m) => m.executive_owner === e.id && NON_TERMINAL(m.status)).length,
      workerCount: running.filter((i) => i.executive === e.id).length,
      lastReport: execReports[0]?.report_id ?? null,
      lastActivity: execReports[0]?.created_at ?? null,
    };
  });

  const byState: Record<string, number> = {};
  for (const m of missions) byState[m.status] = (byState[m.status] ?? 0) + 1;

  return {
    header: {
      activeSessions: listSessions().filter(
        (s) => s.status === "running" || s.status === "starting",
      ).length,
      runningWorkers: running.length,
      openMissions: missions.filter((m) => OPEN_STATES.includes(m.status)).length,
    },
    portfolio,
    execution: {
      running: running.map(workerRow),
      recentCompleted: recentCompleted.map(workerRow),
      failed: failed.map(workerRow),
    },
    attention: {
      blockedMissions: missions.filter((m) => m.status === "Blocked"),
      criticalRisks,
      activeBlockingDeps,
      offTrackKpis,
      reviewRequired: missions.filter((m) => m.status === "Review"),
    },
    executives,
    recentReports: allReports.slice(0, 8),
    recentAssets: allAssets.slice(0, 8),
    health: {
      byState,
      objectivesCompletePct: objTotal === 0 ? 0 : Math.round((objCompleted / objTotal) * 100),
      openWorkOrders,
      assignments: assignmentCount,
      workerInstances: allInstances.length,
    },
  };
}

root · /srv/aaf