/** * Calvana Ship Log Extension * * Automatically tracks what you're shipping and updates the live Calvana site. * * Tools (LLM-callable): * - calvana_ship: Add/update/complete shipping log entries * - calvana_oops: Log mistakes and fixes * - calvana_deploy: Push changes to the live site * * Commands (user): * /ships — View current shipping log * /ship-deploy — Force deploy to calvana.quikcue.com * * How it works: * 1. When you work on tasks, the LLM uses calvana_ship to track progress * 2. If something breaks, calvana_oops logs it * 3. calvana_deploy rebuilds the /live page HTML and pushes it to the server * 4. The extension auto-injects context so the LLM knows to track ships * * Edit the SSH/deploy config in the DEPLOY_CONFIG section below. */ import { StringEnum } from "@mariozechner/pi-ai"; import type { ExtensionAPI, ExtensionContext, Theme } from "@mariozechner/pi-coding-agent"; import { Text, truncateToWidth, matchesKey } from "@mariozechner/pi-tui"; import { Type } from "@sinclair/typebox"; // ════════════════════════════════════════════════════════════════════ // CONFIGURATION — Edit these to change deploy target, copy, links // ════════════════════════════════════════════════════════════════════ const DEPLOY_CONFIG = { sshHost: "root@159.195.60.33", sshPort: "22", container: "qc-server-new", sitePath: "/opt/calvana/html", domain: "calvana.quikcue.com", }; const SITE_CONFIG = { title: "Calvana", tagline: "I break rules. Not production.", email: "omair@quikcue.com", referralLine: "PS — Umar pointed me here. If this turns into a hire, I want him to get paid.", }; // ════════════════════════════════════════════════════════════════════ // TYPES // ════════════════════════════════════════════════════════════════════ type ShipStatus = "planned" | "shipping" | "shipped"; interface ShipEntry { id: number; title: string; status: ShipStatus; timestamp: string; metric: string; prLink: string; deployLink: string; loomLink: string; } interface OopsEntry { id: number; description: string; fixTime: string; commitLink: string; timestamp: string; } interface ShipLogState { ships: ShipEntry[]; oops: OopsEntry[]; nextShipId: number; nextOopsId: number; lastDeployed: string | null; } // ════════════════════════════════════════════════════════════════════ // TOOL SCHEMAS // ════════════════════════════════════════════════════════════════════ const ShipParams = Type.Object({ action: StringEnum(["add", "update", "list"] as const), title: Type.Optional(Type.String({ description: "Ship title (for add)" })), id: Type.Optional(Type.Number({ description: "Ship ID (for update)" })), status: Type.Optional(StringEnum(["planned", "shipping", "shipped"] as const)), metric: Type.Optional(Type.String({ description: "What moved — metric line" })), prLink: Type.Optional(Type.String({ description: "PR link" })), deployLink: Type.Optional(Type.String({ description: "Deploy link" })), loomLink: Type.Optional(Type.String({ description: "Loom clip link" })), }); const OopsParams = Type.Object({ action: StringEnum(["add", "list"] as const), description: Type.Optional(Type.String({ description: "What broke and how it was fixed" })), fixTime: Type.Optional(Type.String({ description: "Time to fix, e.g. '3 min'" })), commitLink: Type.Optional(Type.String({ description: "Link to the fix commit" })), }); const DeployParams = Type.Object({ dryRun: Type.Optional(Type.Boolean({ description: "If true, generate HTML but don't deploy" })), }); // ════════════════════════════════════════════════════════════════════ // EXTENSION // ════════════════════════════════════════════════════════════════════ export default function (pi: ExtensionAPI) { // ── State ── let state: ShipLogState = { ships: [], oops: [], nextShipId: 1, nextOopsId: 1, lastDeployed: null, }; // ── State reconstruction: DB first, session fallback ── const reconstructFromDb = async () => { try { const sshBase = `ssh -o ConnectTimeout=5 -p ${DEPLOY_CONFIG.sshPort} ${DEPLOY_CONFIG.sshHost}`; const pgContainer = "$(docker ps --format '{{.Names}}' | grep dokploy-postgres)"; const shipsResult = await pi.exec("bash", ["-c", `${sshBase} "incus exec ${DEPLOY_CONFIG.container} -- bash -c 'docker exec ${pgContainer} psql -U dokploy -d calvana -t -A -F \\\"|||\\\" -c \\\"SELECT id, title, status, COALESCE(metric, chr(45)), created_at::text FROM ships ORDER BY id\\\"'" 2>/dev/null` ], { timeout: 15000 }); if (shipsResult.code === 0 && shipsResult.stdout.trim()) { state.ships = []; let maxId = 0; for (const line of shipsResult.stdout.trim().split("\n")) { if (!line.trim()) continue; const parts = line.split("|||"); if (parts.length >= 5) { const id = parseInt(parts[0]); if (id > maxId) maxId = id; state.ships.push({ id, title: parts[1], status: parts[2] as ShipStatus, timestamp: parts[4], metric: parts[3], prLink: "#pr", deployLink: "#deploy", loomLink: "#loomclip", }); } } state.nextShipId = maxId + 1; } const oopsResult = await pi.exec("bash", ["-c", `${sshBase} "incus exec ${DEPLOY_CONFIG.container} -- bash -c 'docker exec ${pgContainer} psql -U dokploy -d calvana -t -A -F \\\"|||\\\" -c \\\"SELECT id, description, COALESCE(fix_time, chr(45)), COALESCE(commit_link, chr(35)), created_at::text FROM oops ORDER BY id\\\"'" 2>/dev/null` ], { timeout: 15000 }); if (oopsResult.code === 0 && oopsResult.stdout.trim()) { state.oops = []; let maxOopsId = 0; for (const line of oopsResult.stdout.trim().split("\n")) { if (!line.trim()) continue; const parts = line.split("|||"); if (parts.length >= 4) { const id = parseInt(parts[0]); if (id > maxOopsId) maxOopsId = id; state.oops.push({ id, description: parts[1], fixTime: parts[2], commitLink: parts[3], timestamp: parts[4] || "", }); } } state.nextOopsId = maxOopsId + 1; } } catch { // DB unavailable — fall through to session reconstruction } }; const reconstructState = async (ctx: ExtensionContext) => { state = { ships: [], oops: [], nextShipId: 1, nextOopsId: 1, lastDeployed: null }; // Always try DB first — this is the source of truth await reconstructFromDb(); // If DB returned data, we're done if (state.ships.length > 0) return; // Fallback: reconstruct from session history (when DB is unreachable) for (const entry of ctx.sessionManager.getBranch()) { if (entry.type !== "message") continue; const msg = entry.message; if (msg.role !== "toolResult") continue; if (msg.toolName === "calvana_ship" || msg.toolName === "calvana_oops" || msg.toolName === "calvana_deploy") { const details = msg.details as { state?: ShipLogState } | undefined; if (details?.state) { state = details.state; } } } }; pi.on("session_start", async (_event, ctx) => { await reconstructState(ctx); if (ctx.hasUI) { const theme = ctx.ui.theme; const shipCount = state.ships.length; const shipped = state.ships.filter(s => s.status === "shipped").length; ctx.ui.setStatus("calvana", theme.fg("dim", `🚀 ${shipped}/${shipCount} shipped (DB)`)); } }); pi.on("session_switch", async (_event, ctx) => await reconstructState(ctx)); pi.on("session_fork", async (_event, ctx) => await reconstructState(ctx)); pi.on("session_tree", async (_event, ctx) => await reconstructState(ctx)); // ── Inject context so LLM knows about ship tracking ── pi.on("before_agent_start", async (event, _ctx) => { const shipContext = ` [Calvana Ship Log Extension Active — DB-backed] Ship log is persisted in PostgreSQL (calvana DB on dokploy-postgres). State survives across sessions — the DB is the source of truth, not session history. Tools: - calvana_ship: Track shipping progress (add/update/list). Writes to DB. - calvana_oops: Log mistakes and fixes. Writes to DB. - calvana_deploy: Queries DB for ALL historical entries, generates HTML, deploys to https://${DEPLOY_CONFIG.domain}/live Rules: - When you START working on a task, use calvana_ship to add or update it to "shipping". - When you COMPLETE a task, update it to "shipped" with a metric. - If something BREAKS, log it with calvana_oops. - After significant changes, use calvana_deploy to push updates live. - calvana_deploy reads from the DATABASE — it shows ALL ships ever, not just this session. Current state from DB: ${state.ships.length} ships (${state.ships.filter(s => s.status === "shipped").length} shipped), ${state.oops.length} oops `; return { systemPrompt: event.systemPrompt + shipContext, }; }); // ── Update status bar on turn end ── pi.on("turn_end", async (_event, ctx) => { if (ctx.hasUI) { const theme = ctx.ui.theme; const shipped = state.ships.filter(s => s.status === "shipped").length; const shipping = state.ships.filter(s => s.status === "shipping").length; const total = state.ships.length; let statusText = `🚀 ${shipped}/${total} shipped`; if (shipping > 0) statusText += ` · ${shipping} in flight`; if (state.lastDeployed) statusText += ` · last deploy ${state.lastDeployed}`; ctx.ui.setStatus("calvana", theme.fg("dim", statusText)); } }); // ════════════════════════════════════════════════════════════════ // TOOL: calvana_ship // ════════════════════════════════════════════════════════════════ pi.registerTool({ name: "calvana_ship", label: "Ship Log", description: "Track shipping progress. Actions: add (new entry), update (change status/links), list (show all). Use this whenever you start, progress, or finish a task.", parameters: ShipParams, async execute(_toolCallId, params, _signal, _onUpdate, _ctx) { const now = new Date().toISOString().replace("T", " ").slice(0, 19) + " GMT+8"; switch (params.action) { case "add": { if (!params.title) { return { content: [{ type: "text", text: "Error: title required" }], details: { state: { ...state }, error: "title required" }, }; } const entry: ShipEntry = { id: state.nextShipId++, title: params.title, status: (params.status as ShipStatus) || "planned", timestamp: now, metric: params.metric || "—", prLink: params.prLink || "#pr", deployLink: params.deployLink || "#deploy", loomLink: params.loomLink || "#loomclip", }; state.ships.push(entry); // Persist to PostgreSQL const addTitle = entry.title.replace(/'/g, "''"); const addMetric = (entry.metric || "—").replace(/'/g, "''"); const addStatus = entry.status; try { const dbResult = await pi.exec("bash", ["-c", `ssh -o ConnectTimeout=10 -p ${DEPLOY_CONFIG.sshPort} ${DEPLOY_CONFIG.sshHost} "incus exec ${DEPLOY_CONFIG.container} -- bash -c 'docker exec \$(docker ps --format {{.Names}} | grep dokploy-postgres) psql -U dokploy -d calvana -t -c \\\"INSERT INTO ships (title, status, metric) VALUES (\\x27${addTitle}\\x27, \\x27${addStatus}\\x27, \\x27${addMetric}\\x27) RETURNING id\\\"'"` ], { timeout: 15000 }); const dbId = parseInt((dbResult.stdout || "").trim()); if (dbId > 0) entry.id = dbId; } catch { /* DB write failed, local state still updated */ } return { content: [{ type: "text", text: `Ship #${entry.id} added: "${entry.title}" [${entry.status}]` }], details: { state: { ...state, ships: [...state.ships] } }, }; } case "update": { if (params.id === undefined) { return { content: [{ type: "text", text: "Error: id required for update" }], details: { state: { ...state }, error: "id required" }, }; } const ship = state.ships.find(s => s.id === params.id); if (!ship) { return { content: [{ type: "text", text: `Ship #${params.id} not found` }], details: { state: { ...state }, error: `#${params.id} not found` }, }; } if (params.status) ship.status = params.status as ShipStatus; if (params.metric) ship.metric = params.metric; if (params.prLink) ship.prLink = params.prLink; if (params.deployLink) ship.deployLink = params.deployLink; if (params.loomLink) ship.loomLink = params.loomLink; ship.timestamp = now; // Persist update to PostgreSQL const setClauses: string[] = []; if (params.status) setClauses.push(`status='${params.status}'`); if (params.metric) setClauses.push(`metric='${(params.metric || "").replace(/'/g, "''")}'`); setClauses.push("updated_at=now()"); try { await pi.exec("bash", ["-c", `ssh -o ConnectTimeout=10 -p ${DEPLOY_CONFIG.sshPort} ${DEPLOY_CONFIG.sshHost} "incus exec ${DEPLOY_CONFIG.container} -- bash -c 'docker exec \$(docker ps --format {{.Names}} | grep dokploy-postgres) psql -U dokploy -d calvana -c \\\"UPDATE ships SET ${setClauses.join(", ")} WHERE id=${params.id}\\\"'"` ], { timeout: 15000 }); } catch { /* DB write failed, local state still updated */ } return { content: [{ type: "text", text: `Ship #${ship.id} updated: "${ship.title}" [${ship.status}]` }], details: { state: { ...state, ships: [...state.ships] } }, }; } case "list": { if (state.ships.length === 0) { return { content: [{ type: "text", text: "No ships logged yet." }], details: { state: { ...state } }, }; } const lines = state.ships.map(s => `#${s.id} [${s.status.toUpperCase()}] ${s.title} (${s.timestamp}) — ${s.metric}` ); return { content: [{ type: "text", text: lines.join("\n") }], details: { state: { ...state } }, }; } default: return { content: [{ type: "text", text: `Unknown action: ${params.action}` }], details: { state: { ...state } }, }; } }, renderCall(args, theme) { let text = theme.fg("toolTitle", theme.bold("🚀 ship ")); text += theme.fg("muted", args.action || ""); if (args.title) text += " " + theme.fg("dim", `"${args.title}"`); if (args.id !== undefined) text += " " + theme.fg("accent", `#${args.id}`); if (args.status) text += " → " + theme.fg("accent", args.status); return new Text(text, 0, 0); }, renderResult(result, { expanded }, theme) { const details = result.details as { state?: ShipLogState; error?: string } | undefined; if (details?.error) return new Text(theme.fg("error", `Error: ${details.error}`), 0, 0); const st = details?.state; if (!st || st.ships.length === 0) return new Text(theme.fg("dim", "No ships"), 0, 0); const shipped = st.ships.filter(s => s.status === "shipped").length; const total = st.ships.length; let text = theme.fg("success", `${shipped}/${total} shipped`); if (expanded) { for (const s of st.ships) { const badge = s.status === "shipped" ? theme.fg("success", "✓") : s.status === "shipping" ? theme.fg("warning", "●") : theme.fg("dim", "○"); text += `\n ${badge} ${theme.fg("accent", `#${s.id}`)} ${theme.fg("muted", s.title)}`; } } return new Text(text, 0, 0); }, }); // ════════════════════════════════════════════════════════════════ // TOOL: calvana_oops // ════════════════════════════════════════════════════════════════ pi.registerTool({ name: "calvana_oops", label: "Oops Log", description: "Log mistakes and fixes. Actions: add (new oops entry), list (show all). Use when something breaks during a task.", parameters: OopsParams, async execute(_toolCallId, params, _signal, _onUpdate, _ctx) { const now = new Date().toISOString().replace("T", " ").slice(0, 19) + " GMT+8"; switch (params.action) { case "add": { if (!params.description) { return { content: [{ type: "text", text: "Error: description required" }], details: { state: { ...state }, error: "description required" }, }; } const entry: OopsEntry = { id: state.nextOopsId++, description: params.description, fixTime: params.fixTime || "—", commitLink: params.commitLink || "#commit", timestamp: now, }; state.oops.push(entry); // Persist to PostgreSQL const oopsDesc = entry.description.replace(/'/g, "''"); const oopsTime = (entry.fixTime || "-").replace(/'/g, "''"); const oopsCommit = (entry.commitLink || "#commit").replace(/'/g, "''"); try { const dbResult = await pi.exec("bash", ["-c", `ssh -o ConnectTimeout=10 -p ${DEPLOY_CONFIG.sshPort} ${DEPLOY_CONFIG.sshHost} "incus exec ${DEPLOY_CONFIG.container} -- bash -c 'docker exec \$(docker ps --format {{.Names}} | grep dokploy-postgres) psql -U dokploy -d calvana -t -c \\\"INSERT INTO oops (description, fix_time, commit_link) VALUES (\\x27${oopsDesc}\\x27, \\x27${oopsTime}\\x27, \\x27${oopsCommit}\\x27) RETURNING id\\\"'"` ], { timeout: 15000 }); const dbId = parseInt((dbResult.stdout || "").trim()); if (dbId > 0) entry.id = dbId; } catch { /* DB write failed, local state still updated */ } return { content: [{ type: "text", text: `Oops #${entry.id}: "${entry.description}" (fixed in ${entry.fixTime})` }], details: { state: { ...state, oops: [...state.oops] } }, }; } case "list": { if (state.oops.length === 0) { return { content: [{ type: "text", text: "No oops entries. Clean run so far." }], details: { state: { ...state } }, }; } const lines = state.oops.map(o => `#${o.id} ${o.description} — fixed in ${o.fixTime}` ); return { content: [{ type: "text", text: lines.join("\n") }], details: { state: { ...state } }, }; } default: return { content: [{ type: "text", text: `Unknown action: ${params.action}` }], details: { state: { ...state } }, }; } }, renderCall(args, theme) { let text = theme.fg("toolTitle", theme.bold("💥 oops ")); text += theme.fg("muted", args.action || ""); if (args.description) text += " " + theme.fg("dim", `"${args.description}"`); return new Text(text, 0, 0); }, renderResult(result, _options, theme) { const details = result.details as { state?: ShipLogState; error?: string } | undefined; if (details?.error) return new Text(theme.fg("error", `Error: ${details.error}`), 0, 0); const text = result.content[0]; return new Text(theme.fg("warning", text?.type === "text" ? text.text : ""), 0, 0); }, }); // ════════════════════════════════════════════════════════════════ // TOOL: calvana_deploy // ════════════════════════════════════════════════════════════════ pi.registerTool({ name: "calvana_deploy", label: "Deploy Calvana", description: `Regenerate the /live page with current ship log and deploy to https://${DEPLOY_CONFIG.domain}. Call this after adding/updating ships or oops entries to push changes live.`, parameters: DeployParams, async execute(_toolCallId, params, signal, onUpdate, _ctx) { onUpdate?.({ content: [{ type: "text", text: "Querying database for full ship log..." }] }); // ── Build a helper script on the remote server to avoid quoting hell ── // This is the ONLY way to reliably run psql inside docker inside incus inside ssh. // Previous approach with nested escaping silently returned empty results. const sshBase = `ssh -o ConnectTimeout=10 -p ${DEPLOY_CONFIG.sshPort} ${DEPLOY_CONFIG.sshHost}`; const HELPER_SCRIPT = ` PG_CONTAINER=$(incus exec ${DEPLOY_CONFIG.container} -- bash -c "docker ps --format '{{.Names}}' | grep dokploy-postgres") if [ -z "$PG_CONTAINER" ]; then echo "ERR:NO_PG_CONTAINER"; exit 1; fi SHIPS=$(incus exec ${DEPLOY_CONFIG.container} -- bash -c "docker exec $PG_CONTAINER psql -U dokploy -d calvana -t -A -F '|||' -c \\"SELECT id, title, status, COALESCE(metric,'-'), COALESCE(details,' '), created_at::text, COALESCE(updated_at::text, created_at::text) FROM ships ORDER BY id\\"") OOPS=$(incus exec ${DEPLOY_CONFIG.container} -- bash -c "docker exec $PG_CONTAINER psql -U dokploy -d calvana -t -A -F '|||' -c \\"SELECT id, description, COALESCE(fix_time,'-'), COALESCE(commit_link,'#commit'), created_at::text FROM oops ORDER BY id\\"") echo "===SHIPS===" echo "$SHIPS" echo "===OOPS===" echo "$OOPS" echo "===END===" `.trim(); try { // 1. Run the helper script via SSH to get ALL ships + oops from DB const dbResult = await pi.exec("bash", ["-c", `${sshBase} 'bash -s' << 'DBEOF'\n${HELPER_SCRIPT}\nDBEOF` ], { signal, timeout: 30000 }); if (dbResult.code !== 0) { return { content: [{ type: "text", text: `DB query failed (code ${dbResult.code}): ${dbResult.stderr}\nstdout: ${dbResult.stdout?.slice(0, 200)}` }], details: { state: { ...state }, error: dbResult.stderr }, isError: true, }; } const output = dbResult.stdout || ""; if (output.includes("ERR:NO_PG_CONTAINER")) { return { content: [{ type: "text", text: `ABORT: PostgreSQL container not found. Refusing to deploy.` }], details: { state: { ...state }, error: "PG container not found" }, isError: true, }; } // 2. Parse the structured output const shipsSection = output.split("===SHIPS===")[1]?.split("===OOPS===")[0]?.trim() || ""; const oopsSection = output.split("===OOPS===")[1]?.split("===END===")[0]?.trim() || ""; const dbShips: Array<{ id: number; title: string; status: string; metric: string; details: string; created: string; updated: string }> = []; for (const line of shipsSection.split("\n")) { if (!line.trim()) continue; const parts = line.split("|||"); if (parts.length >= 6) { dbShips.push({ id: parseInt(parts[0]), title: parts[1], status: parts[2], metric: parts[3], details: parts[4], created: parts[5], updated: parts[6] || parts[5], }); } } const dbOops: Array<{ id: number; description: string; fixTime: string; commitLink: string; created: string }> = []; for (const line of oopsSection.split("\n")) { if (!line.trim()) continue; const parts = line.split("|||"); if (parts.length >= 4) { dbOops.push({ id: parseInt(parts[0]), description: parts[1], fixTime: parts[2], commitLink: parts[3], created: parts[4] || "", }); } } // ── SAFETY GATE: refuse to deploy if DB returned 0 ships ── // The DB has 48+ entries. If we get 0, the query broke silently. if (dbShips.length === 0) { return { content: [{ type: "text", text: `ABORT: DB query returned 0 ships. This would wipe the live site.\nRaw output (first 500 chars): ${output.slice(0, 500)}\n\nRefusing to deploy. Fix the DB query first.` }], details: { state: { ...state }, error: "0 ships from DB — refusing to deploy" }, isError: true, }; } onUpdate?.({ content: [{ type: "text", text: `Found ${dbShips.length} ships + ${dbOops.length} oops from DB. Generating HTML...` }] }); // 3. Generate HTML from DB data const liveHtml = generateLivePageFromDb(dbShips, dbOops); if (params.dryRun) { return { content: [{ type: "text", text: `Dry run — ${dbShips.length} ships, ${dbOops.length} oops, ${liveHtml.length} bytes HTML.\n\n${liveHtml.slice(0, 500)}...` }], details: { state: { ...state }, dryRun: true }, }; } onUpdate?.({ content: [{ type: "text", text: `Deploying ${dbShips.length} ships to server...` }] }); // 4. Deploy via base64 const b64Html = Buffer.from(liveHtml).toString("base64"); const deployResult = await pi.exec("bash", ["-c", `${sshBase} "incus exec ${DEPLOY_CONFIG.container} -- bash -c 'echo ${b64Html} | base64 -d > ${DEPLOY_CONFIG.sitePath}/live/index.html'"` ], { signal, timeout: 30000 }); if (deployResult.code !== 0) { return { content: [{ type: "text", text: `Deploy failed: ${deployResult.stderr}` }], details: { state: { ...state }, error: deployResult.stderr }, isError: true, }; } // 5. Rebuild and update docker service const rebuildResult = await pi.exec("bash", ["-c", `${sshBase} "incus exec ${DEPLOY_CONFIG.container} -- bash -c 'cd /opt/calvana && docker build -t calvana:latest . 2>&1 | tail -2 && docker service update --force calvana 2>&1 | tail -2'"` ], { signal, timeout: 60000 }); const now = new Date().toISOString().replace("T", " ").slice(0, 19); state.lastDeployed = now; return { content: [{ type: "text", text: `✓ Deployed to https://${DEPLOY_CONFIG.domain}/live\n${dbShips.length} ships + ${dbOops.length} oops from database\n${rebuildResult.stdout}` }], details: { state: { ...state, lastDeployed: now } }, }; } catch (err: any) { return { content: [{ type: "text", text: `Deploy error: ${err.message}` }], details: { state: { ...state }, error: err.message }, isError: true, }; } }, renderCall(_args, theme) { return new Text(theme.fg("toolTitle", theme.bold("🌐 deploy calvana")), 0, 0); }, renderResult(result, _options, theme) { const details = result.details as { error?: string } | undefined; if (details?.error) return new Text(theme.fg("error", `✗ ${details.error}`), 0, 0); return new Text(theme.fg("success", `✓ Live at https://${DEPLOY_CONFIG.domain}/live`), 0, 0); }, }); // ════════════════════════════════════════════════════════════════ // COMMAND: /ships // ════════════════════════════════════════════════════════════════ pi.registerCommand("ships", { description: "View current Calvana shipping log", handler: async (_args, ctx) => { if (!ctx.hasUI) { ctx.ui.notify("Requires interactive mode", "error"); return; } await ctx.ui.custom((_tui, theme, _kb, done) => { return new ShipLogComponent(state, theme, () => done()); }); }, }); // ════════════════════════════════════════════════════════════════ // COMMAND: /ship-deploy // ════════════════════════════════════════════════════════════════ pi.registerCommand("ship-deploy", { description: "Force deploy the Calvana site with current ship log", handler: async (_args, ctx) => { const ok = await ctx.ui.confirm("Deploy?", `Push ship log to https://${DEPLOY_CONFIG.domain}/live?`); if (!ok) return; // Queue a deploy via the LLM pi.sendUserMessage("Use calvana_deploy to push the current ship log to the live site.", { deliverAs: "followUp" }); }, }); } // ════════════════════════════════════════════════════════════════════ // UI COMPONENT: /ships viewer // ════════════════════════════════════════════════════════════════════ class ShipLogComponent { private state: ShipLogState; private theme: Theme; private onClose: () => void; private cachedWidth?: number; private cachedLines?: string[]; constructor(state: ShipLogState, theme: Theme, onClose: () => void) { this.state = state; this.theme = theme; this.onClose = onClose; } handleInput(data: string): void { if (matchesKey(data, "escape") || matchesKey(data, "ctrl+c")) { this.onClose(); } } render(width: number): string[] { if (this.cachedLines && this.cachedWidth === width) return this.cachedLines; const lines: string[] = []; const th = this.theme; lines.push(""); lines.push(truncateToWidth( th.fg("borderMuted", "─".repeat(3)) + th.fg("accent", " 🚀 Calvana Ship Log ") + th.fg("borderMuted", "─".repeat(Math.max(0, width - 26))), width )); lines.push(""); // Ships if (this.state.ships.length === 0) { lines.push(truncateToWidth(` ${th.fg("dim", "No ships yet.")}`, width)); } else { const shipped = this.state.ships.filter(s => s.status === "shipped").length; lines.push(truncateToWidth( ` ${th.fg("muted", `${shipped}/${this.state.ships.length} shipped`)}`, width )); lines.push(""); for (const s of this.state.ships) { const badge = s.status === "shipped" ? th.fg("success", "✓ SHIPPED ") : s.status === "shipping" ? th.fg("warning", "● SHIPPING") : th.fg("dim", "○ PLANNED "); lines.push(truncateToWidth( ` ${badge} ${th.fg("accent", `#${s.id}`)} ${th.fg("text", s.title)}`, width )); lines.push(truncateToWidth( ` ${th.fg("dim", s.timestamp)} · ${th.fg("dim", s.metric)}`, width )); } } // Oops if (this.state.oops.length > 0) { lines.push(""); lines.push(truncateToWidth(` ${th.fg("warning", "💥 Oops Log")}`, width)); for (const o of this.state.oops) { lines.push(truncateToWidth( ` ${th.fg("error", "─")} ${th.fg("muted", o.description)} ${th.fg("dim", `(${o.fixTime})`)}`, width )); } } lines.push(""); if (this.state.lastDeployed) { lines.push(truncateToWidth(` ${th.fg("dim", `Last deployed: ${this.state.lastDeployed}`)}`, width)); } lines.push(truncateToWidth(` ${th.fg("dim", "Press Escape to close")}`, width)); lines.push(""); this.cachedWidth = width; this.cachedLines = lines; return lines; } invalidate(): void { this.cachedWidth = undefined; this.cachedLines = undefined; } } // ════════════════════════════════════════════════════════════════════ // HTML GENERATOR — Builds the /live page from current state // ════════════════════════════════════════════════════════════════════ // Keep the old function signature for backward compat but it's no longer called by deploy function generateLivePageHtml(state: ShipLogState): string { return generateLivePageFromDb( state.ships.map(s => ({ id: s.id, title: s.title, status: s.status, metric: s.metric, details: "", created: s.timestamp, updated: s.timestamp })), state.oops.map(o => ({ id: o.id, description: o.description, fixTime: o.fixTime, commitLink: o.commitLink, created: o.timestamp })) ); } function generateLivePageFromDb( ships: Array<{ id: number; title: string; status: string; metric: string; details: string; created: string; updated: string }>, oops: Array<{ id: number; description: string; fixTime: string; commitLink: string; created: string }> ): string { const now = new Date().toISOString(); const shipped = ships.filter(s => s.status === "shipped").length; const shipping = ships.filter(s => s.status === "shipping").length; // Group ships by date (newest first) const shipsByDate = new Map(); for (const s of [...ships].reverse()) { const date = s.created.split(" ")[0] || s.created.split("T")[0] || "Unknown"; if (!shipsByDate.has(date)) shipsByDate.set(date, []); shipsByDate.get(date)!.push(s); } const formatDate = (dateStr: string) => { try { const d = new Date(dateStr); return d.toLocaleDateString("en-GB", { weekday: "long", day: "numeric", month: "long", year: "numeric" }); } catch { return dateStr; } }; let shipSections = ""; for (const [date, dateShips] of shipsByDate) { const cards = dateShips.map(s => { const badgeClass = s.status === "shipped" ? "badge-shipped" : s.status === "shipping" ? "badge-shipping" : "badge-planned"; const badgeLabel = s.status.charAt(0).toUpperCase() + s.status.slice(1); // If details has HTML (from DB), use it; otherwise use metric const hasDetails = s.details && s.details.trim().length > 10 && s.details.includes("<"); const detailsBlock = hasDetails ? `\n
${s.details}
` : ""; return `
#${s.id} ${escapeHtml(s.title)} ${badgeLabel}

${escapeHtml(s.metric)}

${detailsBlock}
`; }).join("\n"); shipSections += `

${formatDate(date)} ${dateShips.length} ship${dateShips.length !== 1 ? "s" : ""}

${cards}
`; } const oopsEntries = oops.length > 0 ? oops.map(o => `
#${o.id} ${escapeHtml(o.description)}${o.fixTime !== "—" ? ` Fixed in ${escapeHtml(o.fixTime)}.` : ""} ${o.commitLink && o.commitLink !== "#commit" ? `→ commit` : ""}
`).join("\n") : `
Nothing broken yet. Give it time.
`; return ` Calvana — Live Shipping Log

Live Shipping Log

Intentional chaos. Full receipts. Every ship ever.

${shipped}
Shipped
${shipping}
In Flight
${ships.length}
Total
${oops.length}
Oops
${shipSections}

Rules I broke today

  • Didn't ask permission
  • Didn't wait for alignment
  • Didn't write a PRD
  • Didn't submit a normal application

Rules I refuse to break

  • No silent failures
  • No unbounded AI spend
  • No hallucinations shipped to users
  • No deploy without rollback path

Oops Log

If it's not here, I haven't broken it yet.

${oopsEntries}
`; } function escapeHtml(str: string): string { return str .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """) .replace(/'/g, "'") .replace(/\u2014/g, "—") // em dash .replace(/\u2013/g, "–") // en dash .replace(/\u2019/g, "’") // right single quote .replace(/\u2018/g, "‘") // left single quote .replace(/\u201c/g, "“") // left double quote .replace(/\u201d/g, "”") // right double quote .replace(/\u2026/g, "…") // ellipsis .replace(/\u2192/g, "→") // right arrow .replace(/\u00a3/g, "£") // pound sign .replace(/\u00d7/g, "×"); // multiplication sign }