Pull forward (from the roadmap's later Phase 5) the hook-enforced house-rule primitives: a small, pure evaluateDenyHooks(toolCall: { name: string; input: Record<string, unknown> }, rules: DenyRule[]): { allowed: boolean; reason?: string } mechanism modeled on Claude Code's PreToolUse deny-hook shape, so that even in this foundation phase, the miner package has a checked, testable place to enforce house rules ("never touch .github/workflows/**", "never run git push --force", "never read/write .env") BEFORE any later phase wires an actual coding-agent tool-call loop through it. This issue implements the deterministic rule-evaluator only — there is no live tool-call interception yet (that needs a real coding-agent driver, out of scope for Phase 0), but the primitive and its rule format exist and are fully tested so later phases just plug a real event source into it.
Deliverables
References
scripts/check-mcp-package.mjs (forbiddenPath/forbiddenContent regexes, lines 15-16) — existing house-rule-as-regex precedent in this exact repo to mirror for the built-in default rules.
src/settings/autonomy.ts (resolveAutonomy, isActingAutonomyLevel) — THE reusable autonomy dial the phase brief points to; this deny-hook module is a complementary, lower-level primitive (blocks specific dangerous actions outright) rather than a replacement for the autonomy level system (which gates whether acting is allowed AT ALL) — cite both so a reviewer understands they compose rather than duplicate.
- Phase brief: "pull forward hook-enforced house-rule primitives early (PreToolUse-style deny hooks) since the roadmap explicitly says to pull these forward from Phase 5."
- New path:
packages/gittensory-miner/lib/deny-hooks.js.
Pull forward (from the roadmap's later Phase 5) the hook-enforced house-rule primitives: a small, pure
evaluateDenyHooks(toolCall: { name: string; input: Record<string, unknown> }, rules: DenyRule[]): { allowed: boolean; reason?: string }mechanism modeled on Claude Code's PreToolUse deny-hook shape, so that even in this foundation phase, the miner package has a checked, testable place to enforce house rules ("never touch.github/workflows/**", "never rungit push --force", "never read/write.env") BEFORE any later phase wires an actual coding-agent tool-call loop through it. This issue implements the deterministic rule-evaluator only — there is no live tool-call interception yet (that needs a real coding-agent driver, out of scope for Phase 0), but the primitive and its rule format exist and are fully tested so later phases just plug a real event source into it.Deliverables
deny-hooksmodule exporting aDenyRuletype (e.g.{ matcher: string /* tool-name glob or exact */; pathPattern?: string /* glob against a path-shaped input field */; reason: string }) and a pureevaluateDenyHooks(toolCall, rules): { allowed: boolean; blockedBy?: DenyRule }..github/workflows/**,.env*, or any path matching**/secret*/**or**/*private*key*(mirroring the forbidden-path patterns already enforced inscripts/check-mcp-package.mjs), and block any shell-command-shaped tool call containing--forcecombined withpush(a conservative git-force-push guard).gittensory-miner doctor(from the CLI-entry-point issue) gains a line confirming the deny-hook module loads and its default rule set is non-empty, so "the safety primitive exists and is wired at least this far" is checkable from day one.References
scripts/check-mcp-package.mjs(forbiddenPath/forbiddenContentregexes, lines 15-16) — existing house-rule-as-regex precedent in this exact repo to mirror for the built-in default rules.src/settings/autonomy.ts(resolveAutonomy,isActingAutonomyLevel) — THE reusable autonomy dial the phase brief points to; this deny-hook module is a complementary, lower-level primitive (blocks specific dangerous actions outright) rather than a replacement for the autonomy level system (which gates whether acting is allowed AT ALL) — cite both so a reviewer understands they compose rather than duplicate.packages/gittensory-miner/lib/deny-hooks.js.