Commit b1dcdd81fe80

Vincent Demeester <vincent@sbr.pm>
2026-02-05 17:14:07
feat(path-validator): write full policy output to temp file
Widget display may truncate long output. Now also writes plain text version to /tmp/path-policies-*.txt and notifies user of the path for full viewing with cat/less. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent a20d843
Changed files (1)
dots
pi
agent
extensions
path-validator
dots/pi/agent/extensions/path-validator/index.ts
@@ -16,7 +16,7 @@
 
 import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
 import { existsSync } from "node:fs";
-import { readFile } from "node:fs/promises";
+import { readFile, writeFile } from "node:fs/promises";
 import { join } from "node:path";
 import { homedir } from "node:os";
 
@@ -373,7 +373,8 @@ export default function (pi: ExtensionAPI) {
 				return;
 			}
 
-			const widgetLines: string[] = [
+			// Build output lines
+			const lines: string[] = [
 				theme.bold(`๐Ÿ“‹ Path Policies${filter ? ` (${filter})` : ""} [${filteredPolicies.length}/${policies.length}]`),
 				theme.fg("dim", "โ”€".repeat(60)),
 			];
@@ -386,38 +387,46 @@ export default function (pi: ExtensionAPI) {
 				);
 
 				// Compact: name + status + action on one line
-				widgetLines.push(`${theme.fg("accent", "โ€ข")} ${theme.bold(policy.name)} [${status}] ${action}`);
+				lines.push(`${theme.fg("accent", "โ€ข")} ${theme.bold(policy.name)} [${status}] ${action}`);
 
 				if (verbose) {
 					// Verbose: show all details
 					if (policy.description) {
-						widgetLines.push(`  ${theme.fg("dim", policy.description)}`);
+						lines.push(`  ${theme.fg("dim", policy.description)}`);
 					}
 					if (policy.filenamePattern) {
-						widgetLines.push(`  ${theme.fg("dim", `Filename: ${policy.filenamePattern}`)}`);
+						lines.push(`  ${theme.fg("dim", `Filename: ${policy.filenamePattern}`)}`);
 					}
 					if (policy.pathPattern) {
-						widgetLines.push(`  ${theme.fg("dim", `Path: ${policy.pathPattern}`)}`);
+						lines.push(`  ${theme.fg("dim", `Path: ${policy.pathPattern}`)}`);
 					}
 					if (policy.requiredFilenameFormat) {
-						widgetLines.push(`  ${theme.fg("dim", `Format: ${policy.formatDescription || policy.requiredFilenameFormat}`)}`);
+						lines.push(`  ${theme.fg("dim", `Format: ${policy.formatDescription || policy.requiredFilenameFormat}`)}`);
 					}
 					if (policy.blockedPaths?.length) {
-						widgetLines.push(`  ${theme.fg("dim", `Blocked: ${policy.blockedPaths.join(", ")}`)}`);
+						lines.push(`  ${theme.fg("dim", `Blocked: ${policy.blockedPaths.join(", ")}`)}`);
 					}
 					if (policy.suggestedPath) {
-						widgetLines.push(`  ${theme.fg("accent", `โ†’ ${policy.suggestedPath}`)}`);
+						lines.push(`  ${theme.fg("accent", `โ†’ ${policy.suggestedPath}`)}`);
 					}
-					widgetLines.push("");
+					lines.push("");
 				}
 			}
 
 			if (!verbose) {
-				widgetLines.push(theme.fg("dim", "Use --verbose for details"));
+				lines.push(theme.fg("dim", "Use --verbose for details"));
 			}
-			widgetLines.push(theme.fg("dim", `Config: ${CONFIG_PATH}`));
+			lines.push(theme.fg("dim", `Config: ${CONFIG_PATH}`));
 
-			ctx.ui.setWidget("path-policies", widgetLines);
+			// Write to temp file for full viewing
+			const tmpFile = `/tmp/path-policies-${Date.now()}.txt`;
+			// Strip ANSI codes for file
+			const plainLines = lines.map((l) => l.replace(/\x1b\[[0-9;]*m/g, ""));
+			await writeFile(tmpFile, plainLines.join("\n"), "utf-8");
+
+			// Show in widget (may truncate) + notify about file
+			ctx.ui.setWidget("path-policies", lines);
+			ctx.ui.notify(`Full output: ${tmpFile}`, "info");
 
 			// Longer timeout for verbose mode
 			setTimeout(() => {