UNPKG

@blundergoat/goat-flow

Version:

AI coding agent harness and local dashboard for Claude Code, OpenAI Codex, Google Antigravity, and GitHub Copilot - setup audits, guardrails, structured skills, deny hooks, and persistent learning loops.

67 lines 3.04 kB
const HOOKS = [ { id: "deny-dangerous", displayName: "Deny dangerous hook", description: "Block risky shell operations, direct secret-path access, repository writes, and GitHub write operations through one PreToolUse dispatcher.", event: "PreToolUse", matcher: "Bash", scriptFiles: ["deny-dangerous.sh"], primaryScript: "deny-dangerous.sh", togglable: true, defaultEnabled: true, requiresConfirmDialog: true, }, { id: "gruff-code-quality", displayName: "gruff code quality", description: "Run gruff-* on each edited file and surface findings on changed lines inline.", event: "PostToolUse", matcher: "Edit|Write", scriptFiles: ["gruff-code-quality.sh"], primaryScript: "gruff-code-quality.sh", togglable: true, defaultEnabled: false, requiresConfirmDialog: false, // Above the script's internal 60s analyzer timeout so the hook's own // timeout/config diagnostics print before the runner kills the wrapper. timeoutSec: 90, unsupportedAgents: { codex: "Codex goat-flow hooks are PreToolUse-only until a supported post-tool lifecycle path is verified.", }, }, { id: "post-turn-safety", displayName: "Post-turn safety guard", description: "Scan changed content after an agent turn for built-in safety hazards such as obvious secrets, private keys, and merge conflict markers.", event: "Stop", matcher: "", scriptFiles: ["post-turn-safety.sh"], primaryScript: "post-turn-safety.sh", togglable: true, defaultEnabled: true, requiresConfirmDialog: false, timeoutSec: 60, unsupportedAgents: { copilot: "Copilot has no project-local post-turn hook event.", codex: "Codex Stop-hook delivery is unverified: registered .codex/hooks.json Stop hooks did not fire under codex exec 0.139.0.", antigravity: "Antigravity Stop-hook delivery is unverified: hook trust gates execution and no Stop payload was captured firing.", }, }, ]; const HOOKS_BY_IDENTIFIER = new Map(HOOKS.map((hook) => [hook.id, hook])); // Returns a defensive copy so callers may sort or filter without mutating the // canonical registry that getHookSpec / readAllHookStates read from. export function listHookSpecs() { return [...HOOKS]; } // Returns null (rather than throwing) for an unknown id so callers can treat a // missing hook as a 404-style branch instead of an exception path. export function getHookSpec(hookIdentifier) { return HOOKS_BY_IDENTIFIER.get(hookIdentifier) ?? null; } // Guards an id before it is used as a filesystem-safe key and URL segment: // lowercase-kebab only, so it can never escape a directory or need encoding. export function isValidHookIdShape(hookIdentifier) { return /^[a-z0-9][a-z0-9-]*$/u.test(hookIdentifier); } //# sourceMappingURL=hooks-registry.js.map