import type { Plugin, PluginInput, Hooks } from "@opencode-ai/plugin" const STATUS_SCRIPT = process.env.HOME + "/.automaton/scripts/status.py" const PROJECT_ROOT = process.cwd() async function checkCanEdit(file?: string): Promise<{ allowed: boolean; reason: string; task?: string }> { const { execSync } = await import("child_process") let cmd = `python3 "${STATUS_SCRIPT}" --can-edit --project "${PROJECT_ROOT}"` if (file) { cmd += ` --file "${file}"` } cmd += " --json" try { const output = execSync(cmd, { encoding: "utf-8", timeout: 5000 }) const lines = output.trim().split("\n") const jsonLine = lines[lines.length - 1] const result = JSON.parse(jsonLine) return { allowed: result.allowed, reason: result.reason, task: result.primary_task?.task } } catch (e: any) { if (e.status === 1) { const stderr = (e.stderr || "").trim() const stdout = (e.stdout || "").trim() const lines = (stdout || stderr).split("\n") const jsonLine = lines[lines.length - 1] try { const result = JSON.parse(jsonLine) return { allowed: false, reason: result.reason } } catch { return { allowed: false, reason: stderr || "Denied by automaton" } } } return { allowed: true, reason: "status.py not available, allowing edit" } } } export default (async ({ client, project, directory }: PluginInput): Promise => { return { "tool.execute.before": async (input, output) => { if (input.tool !== "edit" && input.tool !== "write") { return } const filePath = input.args?.file_path || input.args?.path || input.args?.[0] || "" if (!filePath) { return } const { allowed, reason, task } = await checkCanEdit(filePath) if (!allowed) { const msg = reason === "no_edit_tasks" ? `BLOCKED: No task in implement or doc_review phase. Create or transition a task first.` : reason === "out_of_scope" ? `BLOCKED: File is outside the project scope.` : reason === "wrong_phase" ? `BLOCKED: Current task is not in an edit-allowed phase. Transition it to implement or doc_review first.` : `BLOCKED: ${reason || "Edit denied by automaton framework"}`; throw new Error(`[AUTOMATON GUARD] ${msg}\n\nTo proceed:\n1. Create a task: python ~/.automaton/scripts/status.py --create-task --project ${directory}\n2. Transition it: python ~/.automaton/scripts/status.py --transition implement --task --project ${directory}`); } }, } }) satisfies Plugin