Intelligence
Artifacts
Browse the repository, read documents, and manage the governance folders. Source, runtime, and infrastructure are read-only.
Repository
assignment-dispatch-button.tsxassignment-status-badge.tsxassignments-panel.tsxcreate-mission-form.tsxgovernance-panels.tsxmission-dispatch.tsxmission-edit.tsxmission-state-actions.tsxmission-status-badge.tsxobjective-edit.tsxobjective-status-badge.tsxobjective-status-select.tsxobjectives-panel.tsxreport-list.tsxwork-orders-panel.tsx
README.md
CONSTITUTION_COMPLIANCE_AUDIT_V1.mdREADME.md
repositories/aaf-holdings/hq01/components/executives/instruct-hq01.tsx
15.5 KB
"use client";
import { useState } from "react";
import { useRouter } from "next/navigation";
import Link from "next/link";
import {
Send,
Loader2,
ArrowRight,
Building2,
FileText,
AlertTriangle,
CheckCircle2,
Play,
ClipboardCheck,
X,
CornerUpRight,
} from "lucide-react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Card } from "@/components/ui/card";
import { cn } from "@/lib/utils";
import type {
Briefing,
Confidence,
ExecutiveProposal,
RoutingResult,
} from "@/lib/executives/types";
const CONFIDENCE_STYLE: Record<Confidence, string> = {
high: "bg-emerald-50 text-emerald-700",
medium: "bg-amber-50 text-amber-700",
low: "bg-red-50 text-red-700",
};
/**
* "Instruct HQ01" — the CEO types an instruction, HQ01 routes it to the right
* executive office, and offers dispatch (existing office) or an approval-gated
* proposal (unstaffed office).
*/
export function InstructHQ01() {
const router = useRouter();
const [instruction, setInstruction] = useState("");
const [repository, setRepository] = useState("");
const [busy, setBusy] = useState<string | null>(null);
const [error, setError] = useState<string | null>(null);
const [routing, setRouting] = useState<RoutingResult | null>(null);
const [briefing, setBriefing] = useState<Briefing | null>(null);
const [proposal, setProposal] = useState<ExecutiveProposal | null>(null);
const [approved, setApproved] = useState(false);
async function call(url: string, init?: RequestInit): Promise<any> {
const res = await fetch(url, init);
const data = await res.json().catch(() => ({}));
if (!res.ok || data.ok === false) {
throw new Error(data.error ?? `Request failed (HTTP ${res.status}).`);
}
return data;
}
function resetDownstream() {
setBriefing(null);
setProposal(null);
setApproved(false);
setError(null);
}
async function routeInstruction(preferredExecutiveId?: string) {
if (!instruction.trim()) return;
setBusy("route");
resetDownstream();
try {
const data = await call("/api/router/route", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
instruction,
repository: repository || undefined,
preferredExecutiveId,
}),
});
setRouting(data.result as RoutingResult);
} catch (err) {
setError(err instanceof Error ? err.message : "Routing failed.");
} finally {
setBusy(null);
}
}
async function previewBriefing() {
if (!routing) return;
setBusy("briefing");
setError(null);
try {
const data = await call("/api/router/briefing", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
executiveId: routing.recommendedExecutiveId,
instruction,
routingReason: routing.routingReason,
}),
});
setBriefing(data.briefing as Briefing);
} catch (err) {
setError(err instanceof Error ? err.message : "Could not load briefing.");
} finally {
setBusy(null);
}
}
// Dispatch now happens from a Mission (PASS M0): a dispatch must belong to a
// mission, so this routing surface previews and hands off to Mission Control.
async function createProposal() {
if (!routing) return;
setBusy("proposal");
setError(null);
try {
const data = await call("/api/executives/proposals", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
proposedExecutiveId: routing.recommendedExecutiveId,
reason: routing.routingReason,
originatingInstruction: instruction,
}),
});
setProposal(data.proposal as ExecutiveProposal);
} catch (err) {
setError(err instanceof Error ? err.message : "Could not create proposal.");
} finally {
setBusy(null);
}
}
async function decideProposal(decision: "approve" | "reject") {
if (!proposal) return;
setBusy(decision);
setError(null);
try {
const data = await call(
`/api/executives/proposals/${encodeURIComponent(proposal.id)}/${decision}`,
{ method: "POST" },
);
setProposal(data.proposal as ExecutiveProposal);
if (decision === "approve") {
setApproved(true);
// Re-route so dispatch becomes available now the office is active.
await routeInstruction();
}
} catch (err) {
setError(err instanceof Error ? err.message : "Action failed.");
} finally {
setBusy(null);
}
}
const triageHold =
routing && !routing.dispatchAllowed && !routing.requiresNewExecutiveProposal;
return (
<div className="space-y-6">
{/* Instruction input */}
<Card className="p-5">
<label className="mb-1.5 block text-[11px] font-semibold uppercase tracking-[0.08em] text-muted-foreground">
Instruction
</label>
<textarea
value={instruction}
onChange={(e) => setInstruction(e.target.value)}
placeholder="e.g. Fix the billing deploy script before we break live"
rows={3}
className="flex w-full rounded-md border border-input bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1"
/>
<div className="mt-3 flex flex-wrap items-end gap-3">
<div className="min-w-[16rem] flex-1">
<label className="mb-1.5 block text-[11px] font-semibold uppercase tracking-[0.08em] text-muted-foreground">
Repository (optional)
</label>
<Input
value={repository}
onChange={(e) => setRepository(e.target.value)}
placeholder="defaults to aaf-holdings"
className="h-9 font-mono text-xs"
/>
</div>
<Button
type="button"
onClick={() => routeInstruction()}
disabled={busy !== null || !instruction.trim()}
>
{busy === "route" ? (
<Loader2 className="h-4 w-4 animate-spin" />
) : (
<Send className="h-4 w-4" />
)}
Route Instruction
</Button>
</div>
</Card>
{error && (
<div className="flex items-center gap-2 rounded-md bg-destructive/10 px-4 py-2.5 text-[13px] text-destructive">
<AlertTriangle className="h-4 w-4 shrink-0" />
{error}
</div>
)}
{/* Routing result */}
{routing && (
<Card className="overflow-hidden">
<div className="flex items-center justify-between gap-3 border-b border-border bg-secondary/40 px-5 py-3">
<div className="flex items-center gap-2">
<Building2 className="h-4 w-4 text-muted-foreground" />
<span className="text-sm font-semibold">Routing result</span>
</div>
<span
className={cn(
"rounded-full px-2.5 py-0.5 text-xs font-medium",
CONFIDENCE_STYLE[routing.confidence],
)}
>
{routing.confidence} confidence
</span>
</div>
<div className="space-y-4 p-5">
<div className="flex flex-wrap items-baseline gap-x-3 gap-y-1">
<span className="text-lg font-semibold tracking-tight">
{routing.recommendedOffice}
</span>
<span className="font-mono text-xs text-muted-foreground">
{routing.recommendedExecutiveId} · {routing.department}
</span>
</div>
<p className="text-[14px] leading-relaxed text-foreground/90">
{routing.routingReason}
</p>
{routing.secondaryExecutives.length > 0 && (
<div className="flex flex-wrap items-center gap-2 text-[12px] text-muted-foreground">
<span>Also considered:</span>
{routing.secondaryExecutives.map((s) => (
<span
key={s.id}
className="rounded-full bg-secondary px-2 py-0.5 font-medium text-foreground/70"
>
{s.office}
</span>
))}
</div>
)}
{routing.warnings.length > 0 && (
<ul className="space-y-1">
{routing.warnings.map((w, i) => (
<li
key={i}
className="flex items-start gap-2 text-[12px] text-amber-700"
>
<AlertTriangle className="mt-0.5 h-3.5 w-3.5 shrink-0" />
{w}
</li>
))}
</ul>
)}
{/* Actions */}
<div className="flex flex-wrap items-center gap-2 border-t border-border pt-4">
{routing.dispatchAllowed ? (
<>
<span className="mr-1 inline-flex items-center gap-1.5 text-[12px] font-medium text-emerald-700">
<CheckCircle2 className="h-4 w-4" /> Office active
</span>
<Button
type="button"
variant="outline"
size="sm"
onClick={previewBriefing}
disabled={busy !== null}
>
{busy === "briefing" ? (
<Loader2 className="h-3.5 w-3.5 animate-spin" />
) : (
<FileText className="h-3.5 w-3.5" />
)}
Preview Briefing
</Button>
<Link
href="/mission-control"
className="inline-flex items-center gap-2 rounded-md bg-primary px-3 py-2 text-xs font-medium text-primary-foreground transition-colors hover:bg-primary/90"
>
Dispatch from a Mission <ArrowRight className="h-3.5 w-3.5" />
</Link>
</>
) : routing.requiresNewExecutiveProposal ? (
<ProposalFlow
routing={routing}
proposal={proposal}
approved={approved}
busy={busy}
onCreate={createProposal}
onApprove={() => decideProposal("approve")}
onReject={() => decideProposal("reject")}
onRouteToIvan={() => routeInstruction("ivan")}
/>
) : (
<span className="inline-flex items-center gap-1.5 text-[12px] text-muted-foreground">
<CornerUpRight className="h-4 w-4" />
Held for IVAN triage — IVAN is not yet executable, so this needs
CEO/COO review.
</span>
)}
</div>
</div>
{/* Briefing preview */}
{briefing && <BriefingPreview briefing={briefing} onClose={() => setBriefing(null)} />}
</Card>
)}
</div>
);
}
function ProposalFlow({
routing,
proposal,
approved,
busy,
onCreate,
onApprove,
onReject,
onRouteToIvan,
}: {
routing: RoutingResult;
proposal: ExecutiveProposal | null;
approved: boolean;
busy: string | null;
onCreate: () => void;
onApprove: () => void;
onReject: () => void;
onRouteToIvan: () => void;
}) {
if (approved) {
return (
<span className="inline-flex items-center gap-1.5 text-[12px] font-medium text-emerald-700">
<CheckCircle2 className="h-4 w-4" /> Office approved and activated — re-routed
for dispatch above.
</span>
);
}
return (
<div className="w-full space-y-3">
<div className="flex items-center gap-2 rounded-md bg-amber-50 px-3 py-2 text-[13px] text-amber-800">
<AlertTriangle className="h-4 w-4 shrink-0" />
This requires a new executive office proposal — {routing.recommendedOffice}{" "}
is not staffed yet.
</div>
{!proposal ? (
<div className="flex flex-wrap gap-2">
<Button type="button" size="sm" onClick={onCreate} disabled={busy !== null}>
{busy === "proposal" ? (
<Loader2 className="h-3.5 w-3.5 animate-spin" />
) : (
<ClipboardCheck className="h-3.5 w-3.5" />
)}
Create Proposal
</Button>
<Button
type="button"
variant="outline"
size="sm"
onClick={onRouteToIvan}
disabled={busy !== null}
>
<CornerUpRight className="h-3.5 w-3.5" /> Route to IVAN instead
</Button>
</div>
) : proposal.status === "rejected" ? (
<div className="flex items-center gap-2 text-[12px] text-muted-foreground">
<X className="h-4 w-4" /> Proposal rejected. The office stays unstaffed.
</div>
) : (
<div className="rounded-md border border-border p-3">
<div className="mb-2 font-mono text-[11px] text-muted-foreground">
proposal · {proposal.id} · {proposal.status}
</div>
<div className="mb-3 text-[12px] text-muted-foreground">
Approving creates the {proposal.office} office (status active) and its
constitution folder. It does not write the constitution.
</div>
<div className="flex flex-wrap gap-2">
<Button type="button" size="sm" onClick={onApprove} disabled={busy !== null}>
{busy === "approve" ? (
<Loader2 className="h-3.5 w-3.5 animate-spin" />
) : (
<CheckCircle2 className="h-3.5 w-3.5" />
)}
Approve Office
</Button>
<Button
type="button"
variant="outline"
size="sm"
onClick={onReject}
disabled={busy !== null}
>
<X className="h-3.5 w-3.5" /> Reject Proposal
</Button>
</div>
</div>
)}
</div>
);
}
function BriefingPreview({
briefing,
onClose,
}: {
briefing: Briefing;
onClose: () => void;
}) {
return (
<div className="border-t border-border">
<div className="flex items-center justify-between gap-3 bg-secondary/30 px-5 py-2.5">
<span className="text-[12px] font-semibold uppercase tracking-[0.08em] text-muted-foreground">
Briefing manifest
</span>
<button
type="button"
onClick={onClose}
className="rounded-md p-1 text-muted-foreground hover:bg-secondary"
>
<X className="h-4 w-4" />
</button>
</div>
<div className="space-y-3 px-5 py-4">
<div className="text-[12px] text-muted-foreground">
Constitution:{" "}
{briefing.constitutionLoaded ? (
<span className="text-foreground">
{briefing.constitutionFiles.map((f) => f.path).join(", ")}
</span>
) : (
<span className="text-amber-700">none filed yet</span>
)}
</div>
{briefing.warnings.map((w, i) => (
<div key={i} className="flex items-start gap-2 text-[12px] text-amber-700">
<AlertTriangle className="mt-0.5 h-3.5 w-3.5 shrink-0" />
{w}
</div>
))}
<pre className="max-h-80 overflow-auto rounded-md bg-[#0d1117] px-4 py-3 text-[12px] leading-relaxed text-[#c9d1d9]">
{briefing.systemPrompt}
</pre>
</div>
</div>
);
}
root · /srv/aaf