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/router.ts
6.3 KB
import { TRIAGE_EXECUTIVE_ID } from "./config";
import { EXECUTIVE_OFFICES, officeById } from "./offices";
import { getEntry, isActive } from "./registry";
import type {
Confidence,
ExecutiveOffice,
RoutingInput,
RoutingMatch,
RoutingResult,
} from "./types";
/**
* Deterministic executive router (v1). Classifies a CEO instruction by keyword
* matching against each office's vocabulary, with no LLM dependency. The scoring
* is intentionally simple and centralised so it can be swapped for a smarter
* classifier later without changing callers.
*/
/**
* Curated match vocabulary per office: lowercase substrings checked against the
* instruction. Seeded from each office's routes and extended with common
* stems/synonyms so everyday phrasing routes correctly.
*/
const KEYWORDS: Record<string, string[]> = {
"agent-z": [
"cod", "repo", "architect", "bug", "fix", "debug", "audit", "refactor",
"infrastructure", "deploy", "integrat", "schema", "api", "endpoint",
"ui ", "frontend", "backend", "script", "server", "database", "migration",
"build", "ci/cd", "pipeline", "release", "test", "feature", "implement",
],
"strategy-executive": [
"brainstorm", "new product", "product idea", "business model", "market position",
"positioning strategy", "expansion", "company structure", "roadmap",
"competitive strategy", "go to market", "go-to-market", "new business",
"product for", "monetiz", "pivot",
],
"marketing-executive": [
"campaign", "content strategy", "lead magnet", "social media", "brand",
"funnel", "advertis", " ads", "seo", "email marketing", "newsletter",
"audience", "copywrit", "launch announcement",
],
"finance-executive": [
"pricing", "price", "billing", "unit economics", "budget", "financial model",
"subscription", "margin", "revenue", "cost per", "forecast", "cash flow",
"p&l", "invoic",
],
ivan: [
"process design", "process", "sop", "standard operating", "prioriti",
"operating system", "sequenc", "risk triage", "coordinat", "workflow",
"org structure", "operating procedure",
],
"research-executive": [
"competitor", "research", "tool research", "vendor", "comparison", "compare ",
"market research", "evaluate options", "investigate", "benchmark", "landscape",
],
};
interface Scored extends RoutingMatch {}
function scoreOffices(instruction: string): Scored[] {
const text = ` ${instruction.toLowerCase()} `;
return EXECUTIVE_OFFICES.map((office) => {
const keys = KEYWORDS[office.id] ?? [];
const matched = keys.filter((k) => text.includes(k));
return {
id: office.id,
office: office.office,
department: office.department,
score: matched.length,
matched,
};
}).sort((a, b) => b.score - a.score);
}
function confidenceOf(top: Scored, second: Scored | undefined): Confidence {
if (top.score === 0) return "low";
if (top.score >= 2 && (!second || second.score < top.score)) return "high";
if (top.score >= 2) return "medium"; // strong but tied
return "medium"; // single hit
}
function describe(matched: string[]): string {
const cleaned = matched.map((m) => m.trim()).filter(Boolean);
return cleaned.length ? cleaned.join(", ") : "no specific signals";
}
export function route(input: RoutingInput): RoutingResult {
const instruction = (input.instruction ?? "").trim();
const mode = input.mode ?? "preview";
const warnings: string[] = [];
const scored = scoreOffices(instruction);
const top = scored[0];
const second = scored[1];
let recommendedId: string;
let confidence: Confidence;
let reason: string;
let lowConfidenceTriage = false;
// 1) Explicit CEO override wins, if it names a real office.
if (input.preferredExecutiveId && officeById(input.preferredExecutiveId)) {
recommendedId = input.preferredExecutiveId;
confidence = "high";
reason = "CEO specified this executive explicitly.";
const auto = scored.find((s) => s.id === recommendedId);
if (auto && auto.score > 0 && auto.id !== top.id) {
warnings.push(
`Routing would have suggested ${top.office} (${describe(top.matched)}).`,
);
}
} else if (!instruction) {
recommendedId = TRIAGE_EXECUTIVE_ID;
confidence = "low";
lowConfidenceTriage = true;
reason = "No instruction provided; held for IVAN triage.";
warnings.push("Empty instruction.");
} else if (top.score === 0) {
// 2) Nothing matched — default to IVAN for triage (safety rule).
recommendedId = TRIAGE_EXECUTIVE_ID;
confidence = "low";
lowConfidenceTriage = true;
reason =
"No strong signal for a specific office; routed to IVAN (operations) for triage.";
warnings.push("Low routing confidence — defaulted to IVAN.");
} else {
recommendedId = top.id;
confidence = confidenceOf(top, second);
reason = `Matched ${top.office} on: ${describe(top.matched)}.`;
if (confidence === "medium" && second && second.score === top.score) {
warnings.push(
`Ambiguous: also matched ${second.office} (${describe(second.matched)}).`,
);
}
if (confidence === "low") {
lowConfidenceTriage = true;
recommendedId = TRIAGE_EXECUTIVE_ID;
}
}
const office = officeById(recommendedId) as ExecutiveOffice;
const entry = getEntry(recommendedId);
const exists = isActive(recommendedId);
// A confident route to an unstaffed office becomes a proposal; the IVAN triage
// fallback is a hold (no proposal), per the governance rules.
const requiresNewExecutiveProposal = !exists && !lowConfidenceTriage;
const dispatchAllowed = exists;
if (!exists && lowConfidenceTriage) {
warnings.push("IVAN office is not yet staffed; this is a triage hold.");
} else if (!exists) {
warnings.push(
`The ${office.office} office is not staffed yet — approval required before dispatch.`,
);
}
const secondaryExecutives = scored
.filter((s) => s.id !== recommendedId && s.score > 0)
.slice(0, 3);
return {
instruction,
mode,
recommendedExecutiveId: recommendedId,
recommendedOffice: office.office,
department: office.department,
confidence,
routingReason: reason,
secondaryExecutives,
exists,
requiresNewExecutiveProposal,
proposedExecutiveOffice: requiresNewExecutiveProposal ? office : undefined,
dispatchAllowed,
warnings,
};
}
root · /srv/aaf