/** * 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];