/** * Validate features.md format after any write/edit to the file. */ import type { ExtensionAPI } from "@mariozechner/pi-coding-agent"; import * as fs from "node:fs"; import * as path from "node:path"; import { parseFeaturesMd, validateFeaturesMd } from "../lib/features-parser.js"; export function registerValidationHooks(pi: ExtensionAPI) { let pendingValidation = false; pi.on("tool_call", async (event) => { if (event.toolName === "write" || event.toolName === "edit") { const input = event.input as { path?: string }; if (input.path && input.path.endsWith("features.md")) { pendingValidation = true; } } return { block: false }; }); pi.on("tool_result", async (_event, ctx) => { if (!pendingValidation) return; pendingValidation = false; try { const featuresPath = path.join(ctx.cwd, "features.md"); if (!fs.existsSync(featuresPath)) return; const content = fs.readFileSync(featuresPath, "utf-8"); const validation = validateFeaturesMd(content); if (!validation.valid) { ctx.ui.notify( `⚠ features.md format issues:\n${validation.issues.map((i) => ` - ${i}`).join("\n")}`, "warning", ); } else { const features = parseFeaturesMd(content); ctx.ui.notify(`features.md validated: ${features.length} features ✓`, "info"); } } catch { // Silent fail on validation } }); }