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/missions/store.ts
4.7 KB
import fs from "node:fs";
import path from "node:path";
import { MISSIONS_ROOT } from "./config";
import type { Mission, MissionEvent, MissionReport } from "./types";

/**
 * Filesystem store for the Mission Registry — the source of truth.
 *
 * Layout:
 *   /srv/aaf/missions/MISSION-000001/
 *     mission.json          the mission record
 *     history/log.jsonl     append-only event history
 *     reports/              execution reports stored under the mission
 *     artifacts/            durable assets owned by the mission
 */

const ID_RE = /^MISSION-\d{6}$/;

export function isValidMissionId(id: string): boolean {
  return ID_RE.test(id);
}

export function missionDir(id: string): string {
  return path.join(MISSIONS_ROOT, id);
}
export function missionJsonPath(id: string): string {
  return path.join(missionDir(id), "mission.json");
}
export function historyDir(id: string): string {
  return path.join(missionDir(id), "history");
}
export function historyLogPath(id: string): string {
  return path.join(historyDir(id), "log.jsonl");
}
export function reportsDir(id: string): string {
  return path.join(missionDir(id), "reports");
}
export function artifactsDir(id: string): string {
  return path.join(missionDir(id), "artifacts");
}

/** Create the full directory skeleton for a mission. */
export function ensureMissionDirs(id: string): void {
  fs.mkdirSync(historyDir(id), { recursive: true });
  fs.mkdirSync(reportsDir(id), { recursive: true });
  fs.mkdirSync(artifactsDir(id), { recursive: true });
}

function writeJsonAtomic(file: string, data: unknown): void {
  fs.mkdirSync(path.dirname(file), { recursive: true });
  const tmp = `${file}.tmp`;
  fs.writeFileSync(tmp, JSON.stringify(data, null, 2) + "\n", "utf8");
  fs.renameSync(tmp, file);
}

export function writeMission(mission: Mission): void {
  writeJsonAtomic(missionJsonPath(mission.id), mission);
}

export function readMission(id: string): Mission | null {
  if (!isValidMissionId(id)) return null;
  try {
    return JSON.parse(fs.readFileSync(missionJsonPath(id), "utf8")) as Mission;
  } catch {
    return null;
  }
}

export function listMissionIds(): string[] {
  let entries: fs.Dirent[];
  try {
    entries = fs.readdirSync(MISSIONS_ROOT, { withFileTypes: true });
  } catch {
    return [];
  }
  return entries
    .filter((e) => e.isDirectory() && isValidMissionId(e.name))
    .map((e) => e.name)
    .filter((id) => fs.existsSync(missionJsonPath(id)));
}

/** Next sequential, human-readable mission id (MISSION-000001, …). */
export function nextMissionId(): string {
  let max = 0;
  for (const id of listMissionIds()) {
    const n = Number(id.slice("MISSION-".length));
    if (Number.isFinite(n) && n > max) max = n;
  }
  return `MISSION-${String(max + 1).padStart(6, "0")}`;
}

/** Append an event to a mission's append-only history log. */
export function appendEvent(id: string, event: MissionEvent): void {
  fs.mkdirSync(historyDir(id), { recursive: true });
  fs.appendFileSync(historyLogPath(id), JSON.stringify(event) + "\n", "utf8");
}

export function readHistory(id: string): MissionEvent[] {
  let raw: string;
  try {
    raw = fs.readFileSync(historyLogPath(id), "utf8");
  } catch {
    return [];
  }
  return raw
    .split("\n")
    .filter(Boolean)
    .map((line) => {
      try {
        return JSON.parse(line) as MissionEvent;
      } catch {
        return null;
      }
    })
    .filter((e): e is MissionEvent => Boolean(e));
}

export function listReports(id: string): MissionReport[] {
  let names: string[];
  try {
    names = fs.readdirSync(reportsDir(id));
  } catch {
    return [];
  }
  const out: MissionReport[] = [];
  for (const name of names) {
    if (!name.endsWith(".md")) continue;
    const full = path.join(reportsDir(id), name);
    let stat: fs.Stats;
    try {
      stat = fs.statSync(full);
    } catch {
      continue;
    }
    const stem = name.replace(/\.md$/, "");
    out.push({
      id: stem,
      file: name,
      session_id: stem || null,
      stored_at: stat.mtime.toISOString(),
      size: stat.size,
    });
  }
  return out.sort((a, b) => b.stored_at.localeCompare(a.stored_at));
}

/** True if a report with this id has already been stored (idempotency guard). */
export function reportStored(id: string, reportId: string): boolean {
  return fs.existsSync(path.join(reportsDir(id), `${reportId}.md`));
}

/** Store a report file under the mission. */
export function storeReport(id: string, reportId: string, content: string): void {
  fs.mkdirSync(reportsDir(id), { recursive: true });
  writeJsonAtomicText(path.join(reportsDir(id), `${reportId}.md`), content);
}

function writeJsonAtomicText(file: string, content: string): void {
  const tmp = `${file}.tmp`;
  fs.writeFileSync(tmp, content, "utf8");
  fs.renameSync(tmp, file);
}

root · /srv/aaf