/** * Purpose Gate — Forces the engineer to declare intent before working * * On session start, immediately asks "What is the purpose of this agent?" * via a text input dialog. A persistent widget shows the purpose for the * rest of the session, keeping focus. Blocks all prompts until answered. * * Usage: pi -e extensions/purpose-gate.ts */ import type { ExtensionAPI } from "@mariozechner/pi-coding-agent"; import { Text, truncateToWidth } from "@mariozechner/pi-tui"; import { applyExtensionDefaults } from "./themeMap.ts"; // synthwave: bgWarm #4a1e6a → rgb(74,30,106) function bg(s: string): string { return `\x1b[48;2;74;30;106m${s}\x1b[49m`; } // synthwave: pink #ff7edb function pink(s: string): string { return `\x1b[38;2;255;126;219m${s}\x1b[39m`; } // synthwave: cyan #36f9f6 function cyan(s: string): string { return `\x1b[38;2;54;249;246m${s}\x1b[39m`; } function bold(s: string): string { return `\x1b[1m${s}\x1b[22m`; } export default function (pi: ExtensionAPI) { let purpose: string | undefined; async function askForPurpose(ctx: any) { while (!purpose) { const answer = await ctx.ui.input( "What is the purpose of this agent?", "e.g. Refactor the auth module to use JWT" ); if (answer && answer.trim()) { purpose = answer.trim(); } else { ctx.ui.notify("Purpose is required.", "warning"); } } ctx.ui.setWidget("purpose", () => { return { render(width: number): string[] { const pad = bg(" ".repeat(width)); const label = pink(bold(" PURPOSE: ")); const msg = cyan(bold(purpose!)); const content = bg(truncateToWidth(label + msg + " ".repeat(width), width, "")); return [pad, content, pad]; }, invalidate() {}, }; }); } pi.on("session_start", async (_event, ctx) => { applyExtensionDefaults(import.meta.url, ctx); void askForPurpose(ctx); }); pi.on("before_agent_start", async (event) => { if (!purpose) return; return { systemPrompt: event.systemPrompt + `\n\n\nYour singular purpose this session: ${purpose}\nStay focused on this goal. If a request drifts from this purpose, gently remind the user.\n`, }; }); pi.on("input", async (_event, ctx) => { if (!purpose) { ctx.ui.notify("Set a purpose first.", "warning"); return { action: "handled" as const }; } return { action: "continue" as const }; }); }