Skip to content

feat(miner): synthesize deny-hook rules from blocker history (#4522) - #4525

Merged
JSONbored merged 2 commits into
JSONbored:mainfrom
andriypolanski:feat/miner-deny-hook-synthesis-4522
Jul 10, 2026
Merged

feat(miner): synthesize deny-hook rules from blocker history (#4522)#4525
JSONbored merged 2 commits into
JSONbored:mainfrom
andriypolanski:feat/miner-deny-hook-synthesis-4522

Conversation

@andriypolanski

Copy link
Copy Markdown
Contributor

Closes #4522

Summary

  • Add packages/gittensory-miner/lib/deny-hook-synthesis.js: derive proposal-only deny-hook rules from a repo's blocker-code + changed-path history, shaped to match DEFAULT_DENY_RULES (matcher, pathPattern, reason).
  • Add initDenyHookSynthesisStore() for refreshable local SQLite persistence with an explicit proposed → approved gate — synthesized rules never block tool calls until approved; unapproved proposals merge nowhere.
  • Export resolveEffectiveDenyRules() to merge DEFAULT_DENY_RULES + approved synthesized rules for maintainer: PreToolUse-hook-enforced house rules (deny even under bypassPermissions) #2343's PreToolUse consumption surface.

Companion to #2343 (enforce a rule list) — this issue owns automatic derivation + audit trail; #2343 owns live hook wiring.

Scope

  • Path-frequency synthesis (N blocks touching path X**/path deny rule)
  • Audit metadata on every proposal (occurrence count, blocker codes, path)
  • Opt-in: only approved proposals affect resolveEffectiveDenyRules
  • Empty history → static defaults only
  • Skip paths already covered by built-in defaults (.github/workflows/**, etc.)
  • No UI changes — UI Evidence not required

Test plan

  • test/unit/miner-deny-hook-synthesis.test.ts — synthesis shape, default fallback, approved merge blocks matching writes, store refresh preserves approval
  • npm run build:miner
  • npm run test:ci green
  • npm audit --audit-level=moderate clean

Validation

git diff --check
npm run typecheck
npx vitest run test/unit/miner-deny-hook-synthesis.test.ts
npm run build:miner
npm run test:ci
npm audit --audit-level=moderate

Changed files

File Change
packages/gittensory-miner/lib/deny-hook-synthesis.js New: synthesis + SQLite proposal store
packages/gittensory-miner/lib/deny-hook-synthesis.d.ts Type declarations
packages/gittensory-miner/package.json Syntax-check new module
test/unit/miner-deny-hook-synthesis.test.ts Unit tests

@andriypolanski
andriypolanski requested a review from JSONbored as a code owner July 9, 2026 22:37
@andriypolanski
andriypolanski marked this pull request as draft July 9, 2026 22:37
@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@codecov

codecov Bot commented Jul 9, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.04%. Comparing base (95e9ec6) to head (b460626).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #4525   +/-   ##
=======================================
  Coverage   94.04%   94.04%           
=======================================
  Files         422      422           
  Lines       37600    37600           
  Branches    13736    13736           
=======================================
  Hits        35362    35362           
  Misses       1583     1583           
  Partials      655      655           
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@andriypolanski
andriypolanski marked this pull request as ready for review July 9, 2026 22:48
@loopover-orb loopover-orb Bot added the gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier. label Jul 9, 2026
@loopover-orb

loopover-orb Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Tip

🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩

✅ Gittensory review result - approve/merge recommended

Review updated: 2026-07-10 00:02:05 UTC

3 files · 1 AI reviewer · no blockers · readiness 100/100 · CI green · clean

✅ Suggested Action - Approve/Merge

  • safe to merge

Review summary
This PR adds a proposal-only deny-hook rule synthesizer (path-frequency over blocker history) plus a local SQLite store with an explicit proposed→approved gate; `resolveEffectiveDenyRules` only merges rules whose status is exactly `approved`, so nothing here can affect `evaluateDenyHooks` until a maintainer acts, which matches the description and the #2343 hand-off. The persistence layer mirrors the existing `claim-ledger.js` local-SQLite pattern (mkdir 0o700, chmod 0o600, `UNIQUE`-style upsert), and the test suite exercises synthesis shape, default-coverage skipping, threshold gating, approval-merge blocking, and store refresh-preserves-approval — the core paths are real, not fabricated.

Nits — 5 non-blocking
  • packages/gittensory-miner/lib/deny-hook-synthesis.js:147 — every synthesized rule hardcodes `matcher: "*"`, denying ALL tool calls (including reads) against the path regardless of what the underlying blocker actually was; worth a line explaining why write-scoped matching isn't used, or scope it like the tool-specific entries in `DEFAULT_DENY_RULES`.
  • packages/gittensory-miner/lib/deny-hook-synthesis.js:281-303 `refreshProposals` only upserts paths that still clear the current threshold — a previously-approved proposal whose supporting history ages out is never removed or flagged stale, so it silently persists in `resolveEffectiveRules` forever; consider marking/pruning proposals that drop out of the current synthesis run.
  • Error paths aren't covered by the new test file: `normalizeRepoFullName` throwing on a malformed repo string, `setProposalStatuses` given a `Map` instead of a plain object, and the `GITTENSORY_MINER_DENY_HOOK_SYNTHESIS_DB`/`GITTENSORY_MINER_CONFIG_DIR`/`XDG_CONFIG_HOME` fallback branches in `resolveDenyHookSynthesisDbPath` all have zero direct assertions.
  • Magic numbers `20` (maxProposals), `16` (hash slice length), and `0o700`/`0o600` (lib/deny-hook-synthesis.js:19,134,264,266) would read better as named constants, consistent with `DEFAULT_SYNTHESIS_CONFIG`'s existing style for `minPathOccurrences`.
  • packages/gittensory-miner/lib/deny-hook-synthesis.js:97 nests to depth 5 in `synthesizeDenyRuleProposals`'s loop body — consider extracting the per-path dedupe-and-push step into a small helper for readability.
Signal Result Evidence
Code review ✅ No blockers 1 reviewer
Linked issue ✅ Linked #4522
Related work ✅ No active overlap found No same-issue or scoped active PR overlap found.
Change scope ✅ 20/20 Low review scope from cached public metadata (1 linked issue).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 136 registered-repo PR(s), 84 merged, 25 issue(s).
Contributor context ✅ Confirmed Gittensor contributor andriypolanski; Gittensor profile; 136 PR(s), 25 issue(s).
Gate result ✅ Passing No configured blocker found.
Linked issue satisfaction

Partially addressed
The PR delivers the core synthesis algorithm, an approved/proposed audit-trailed rule store, and tests matching the requested synthetic-history and default-fallback cases, directly addressing most of the issue's deliverables. However, it stops short of actually wiring a job to the review stack's real blocker-code/close-reason history (e.g. blocker_codes_json in src/db/schema.ts) or integrating res

Review context
  • Author: andriypolanski
  • Role context: outside_contributor
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: not available
  • Official Gittensor activity: 136 PR(s), 25 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Keep the PR focused and include validation evidence before maintainer review.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Change scope = cached public metadata such as size labels, draft state, and review-burden hints.
  • Validation posture = whether the PR provides enough public validation/test evidence for maintainer review.
  • Contributor workload = public contributor activity and cleanup pressure, not a repo-wide quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.

🟩 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.

  • Re-run Gittensory review

@loopover-orb loopover-orb Bot added the manual-review Gittensor contributor context label Jul 9, 2026
@JSONbored
JSONbored merged commit 15b7c4d into JSONbored:main Jul 10, 2026
10 checks passed
@loopover-orb loopover-orb Bot added gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier. and removed gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier. labels Jul 10, 2026
@JSONbored JSONbored added gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier. and removed gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier. labels Jul 11, 2026
@andriypolanski
andriypolanski deleted the feat/miner-deny-hook-synthesis-4522 branch July 16, 2026 15:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier. manual-review Gittensor contributor context

Development

Successfully merging this pull request may close these issues.

feat(miner): synthesize PreToolUse deny-hook rules from the review stack's own per-repo close/blocker finding-category history

2 participants