Intelligence
Artifacts
Browse the repository, read documents, and manage the governance folders. Source, runtime, and infrastructure are read-only.
Repository
repositories/aaf-holdings/hq01/lib/executives/registry.ts
3.3 KB
import fs from "node:fs";
import path from "node:path";
import {
CONSTITUTIONS_DIR,
ORGANIZATION,
REGISTRY_FILE,
REGISTRY_ROOT,
} from "./config";
import { EXECUTIVE_OFFICES, INITIAL_ACTIVE_IDS } from "./offices";
import type { ExecutiveOffice, RegistryEntry } from "./types";
/**
* Filesystem-first registry of executive offices. The registry is the runtime
* source of truth (which offices exist, and which are active/executable). It is
* seeded once from the office catalogue and thereafter mutated only through
* approved proposals.
*/
function entryFromOffice(office: ExecutiveOffice): RegistryEntry {
return {
id: office.id,
office: office.office,
displayName: office.displayName,
department: office.department,
parent: office.parent,
organization: ORGANIZATION,
constitutionPath: path.join(CONSTITUTIONS_DIR, office.id) + path.sep,
allowedRepositories: ["*"],
allowedTools: [
"claude-cli",
"filesystem-read",
"filesystem-write-approved",
"session-manager",
],
routes: office.routes,
status: INITIAL_ACTIVE_IDS.has(office.id) ? "active" : "inactive",
};
}
function writeRegistry(entries: RegistryEntry[]): void {
fs.mkdirSync(REGISTRY_ROOT, { recursive: true });
const tmp = `${REGISTRY_FILE}.tmp`;
fs.writeFileSync(tmp, JSON.stringify(entries, null, 2) + "\n", "utf8");
fs.renameSync(tmp, REGISTRY_FILE);
}
/**
* Load the registry, seeding it on first use. Any office in the catalogue that
* is missing from the registry is added (inactive) so new offices appear without
* losing existing activation state — additive by construction.
*/
export function loadRegistry(): RegistryEntry[] {
let entries: RegistryEntry[] = [];
try {
entries = JSON.parse(fs.readFileSync(REGISTRY_FILE, "utf8")) as RegistryEntry[];
} catch {
entries = [];
}
const byId = new Map(entries.map((e) => [e.id, e]));
let changed = entries.length === 0;
for (const office of EXECUTIVE_OFFICES) {
if (!byId.has(office.id)) {
byId.set(office.id, entryFromOffice(office));
changed = true;
}
}
const merged = [...byId.values()];
if (changed) writeRegistry(merged);
return merged;
}
export function getEntry(id: string): RegistryEntry | undefined {
return loadRegistry().find((e) => e.id === id);
}
export function isActive(id: string): boolean {
return getEntry(id)?.status === "active";
}
/** Persist a single entry (insert or replace by id). */
export function upsertEntry(entry: RegistryEntry): void {
const entries = loadRegistry();
const idx = entries.findIndex((e) => e.id === entry.id);
if (idx >= 0) entries[idx] = entry;
else entries.push(entry);
writeRegistry(entries);
}
/** Activate an office (used when a proposal is approved). Returns the entry. */
export function activateOffice(
id: string,
patch: Partial<RegistryEntry> = {},
): RegistryEntry {
const existing = getEntry(id);
const office = EXECUTIVE_OFFICES.find((o) => o.id === id);
const base = existing ?? (office ? entryFromOffice(office) : undefined);
if (!base) {
throw new Error(`No office definition for "${id}".`);
}
const entry: RegistryEntry = { ...base, ...patch, status: "active" };
// Ensure the constitution folder exists for the now-active office.
fs.mkdirSync(entry.constitutionPath, { recursive: true });
upsertEntry(entry);
return entry;
}
root · /srv/aaf