/**
* rGov applet definitions — Signoff Gate + Governance Circuit.
*/
import type { AppletDefinition, AppletLiveData, AppletSubNode, AppletSubEdge } from "../../shared/applet-types";
import type { PortDescriptor } from "../../lib/data-types";
const signoffGate: AppletDefinition = {
id: "signoff-gate",
label: "Signoff Gate",
icon: "⚖️",
accentColor: "#7c3aed",
ports: [
{ name: "decision-in", type: "json", direction: "input" },
{ name: "gate-out", type: "json", direction: "output" },
],
renderCompact(data: AppletLiveData): string {
const { snapshot } = data;
const title = (snapshot.title as string) || "Signoff Required";
const satisfied = !!snapshot.satisfied;
const assignee = (snapshot.assignee as string) || "anyone";
const statusColor = satisfied ? "#22c55e" : "#f59e0b";
const statusText = satisfied ? "SATISFIED" : "WAITING";
const checkIcon = satisfied ? "✓" : "○";
return `
${title}
Assignee: ${assignee}
${checkIcon}
${statusText}
`;
},
onInputReceived(portName, value, ctx) {
if (portName === "decision-in" && value && typeof value === "object") {
const decision = value as Record;
ctx.emitOutput("gate-out", {
satisfied: !!decision.approved,
source: "decision-in",
timestamp: Date.now(),
});
}
},
};
const governanceCircuit: AppletDefinition = {
id: "governance-circuit",
label: "Governance Circuit",
icon: "🔀",
accentColor: "#6366f1",
ports: [
{ name: "proposal-in", type: "json", direction: "input" },
{ name: "decision-out", type: "json", direction: "output" },
],
renderCompact(data: AppletLiveData): string {
const { snapshot } = data;
const gateCount = (snapshot.gateCount as number) || 0;
const satisfiedCount = (snapshot.satisfiedCount as number) || 0;
const name = (snapshot.circuitName as string) || "Circuit";
return `
${name}
${satisfiedCount}/${gateCount}
gates satisfied
`;
},
getCircuit(space: string): { nodes: AppletSubNode[]; edges: AppletSubEdge[] } {
// Demo circuit — in production this would read from the space's governance doc
return {
nodes: [
{
id: "gate-1", type: "signoff", label: "Community Approval",
icon: "✓", position: { x: 50, y: 40 },
config: { assignee: "Community", satisfied: false },
},
{
id: "gate-2", type: "threshold", label: "Budget Threshold",
icon: "📊", position: { x: 50, y: 160 },
config: { target: 1000, current: 650, unit: "$" },
},
{
id: "project", type: "project", label: "Project Decision",
icon: "🎯", position: { x: 350, y: 100 },
config: { gatesSatisfied: 0, gatesTotal: 2 },
},
],
edges: [
{ id: "e1", fromNode: "gate-1", fromPort: "out", toNode: "project", toPort: "in" },
{ id: "e2", fromNode: "gate-2", fromPort: "out", toNode: "project", toPort: "in" },
],
};
},
};
export const govApplets: AppletDefinition[] = [signoffGate, governanceCircuit];