feat(miner): add PreToolUse-style deny-hook primitives#2700
Conversation
Add a pure, deterministic evaluateDenyHooks(toolCall, rules) decision function plus a non-empty DEFAULT_DENY_RULES set to @jsonbored/gittensory-miner, so the package has a checked, testable place to enforce house rules before a later phase wires a real coding-agent tool-call loop through it. No live interception in this phase — the module never executes, intercepts, or mutates anything. Built-in rules mirror the forbidden paths in scripts/check-mcp-package.mjs (.github/workflows/**, .env*, secret-bearing paths, private key material) plus a conservative git force-push guard (a command carrying both push and --force). An empty rule set, or a call matching no rule, always allows. Closes JSONbored#2295.
|
🚨 Contributor flagged. Click here for more info: Superagent Dashboard |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #2700 +/- ##
==========================================
- Coverage 96.15% 96.13% -0.03%
==========================================
Files 240 240
Lines 26867 26985 +118
Branches 9751 9792 +41
==========================================
+ Hits 25833 25941 +108
- Misses 424 433 +9
- Partials 610 611 +1 🚀 New features to boost your workflow:
|
|
Warning 🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨 ⏸️ Gittensory review result - manual review recommendedReview updated: 2026-07-03 07:22:38 UTC
⏸️ Suggested Action - Manual Review Review summary Nits — 5 non-blocking
Review context
Contributor next steps
Signal definitions
🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed 💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.
|
Summary
Adds the PreToolUse-style deny-hook primitives to
@jsonbored/gittensory-miner: a pure, deterministicevaluateDenyHooks(toolCall, rules)decision function plus a non-empty built-inDEFAULT_DENY_RULESset, so the miner package has a checked, testable place to enforce house rules before any later phase wires a real coding-agent tool-call loop through it.This is the deterministic rule-evaluator only — there is no live tool-call interception in this phase (that needs a real coding-agent driver, out of scope here). The module never executes, intercepts, or mutates anything; a later phase's real hook wiring calls the verdict.
A
DenyRuleis{ matcher, pathPattern?, inputIncludesAll?, reason }. A rule fires when its tool-namematchermatches and every constraint it declares matches:pathPattern(a glob) against any path-shaped string in the tool-call input, and/orinputIncludesAll(substrings that must all appear in one string field, e.g. a shell command). Path globs are tested against both the whole input value and each whitespace-separated token of it, so a protected path embedded as a command argument (e.g.git add .github/workflows/ci.yml) is caught without relying on a later caller to tokenize the command first. The built-in rules mirror the forbidden-path regex inscripts/check-mcp-package.mjs— block.github/workflows/**,.env*,**/secret*/**,**/*private*key*— plus a conservative git force-push guard (a command carrying bothpushand--force). An empty rule set, or a call matching no rule, always allows.inputIncludesAllis a minimal, data-driven extension of the exampleDenyRuleshape: the required force-push guard is a command-content check that a path glob cannot express, so it is modeled generally (order-independent substring set) rather than as a one-off special case.Closes #2295.
Follow-up (not in scope here)
The issue also lists wiring a status line into
gittensory-miner doctor. That command does not exist yet — it comes from the CLI-entry-point issue (#2288), which is still open (and #2614 is an open PR for the laptop-mode doctor). Adding adoctorcommand here would duplicate/overlap that work, so the one-line "deny-hook module loads, default rule set non-empty" check is deferred to land alongside the CLI entry point. The primitive and its default set are complete and ready to wire; the non-empty invariant is already pinned by a test here.Scope
type(scope): short summaryConventional Commit format.CONTRIBUTING.mdand does not reintroduce GitHub Pages, VitePress,site/, orCNAME.Validation
git diff --checknpm run typechecknpm run test:coveragelocally — the newtest/unit/miner-deny-hooks.test.tspasses; the whole suite is green. (This change lives entirely inpackages/**, which Codecov does not measure, so it carries nocodecov/patchobligation; the logic is nonetheless covered on both sides of every built-in rule.)node --check lib/deny-hooks.jsvianpm run --workspace @jsonbored/gittensory-miner buildnpm audit --audit-level=moderate— this PR adds no dependencies, so dependency-review has nothing new to evaluate.If any required check was skipped, explain why:
packages/gittensory-miner/libplus its test — nosrc/**, UI, API schema, DB, or Cloudflare-binding surface is touched.Safety
UI Evidencesection. — n/a: no visible UI, frontend, docs, or extension change.Notes
Additive: two new files (
lib/deny-hooks.js+ itslib/deny-hooks.d.ts) mirroring the package's existing hand-authored JS+.d.tspattern (lib/opportunity-fanout.*), one line added to the packagebuild(node --check) gate, and one new test file. No existing code is modified.