Skip to content

Extract deny-hook pure logic into gittensory-engine #5667

Description

@JSONbored

Context

lib/deny-hooks.js's rule evaluator and lib/deny-hook-synthesis.js's proposal-synthesis logic are pure, deterministic business logic (each self-documented as such — "no IO, no globals, no Date/random") but live directly in the self-host gittensory-miner package with no gittensory-engine counterpart. This is unlike every other business-logic module in the miner package — governor/chokepoint, portfolio-queue selection, worktree planning, attempt-log event shape, coding-agent drivers — which already follow a "pure engine function + thin miner-lib persistence wrapper" split. A hosted service wanting per-tenant deny-hook enforcement would have to depend on the whole SQLite-backed miner package just to reach one pure function, or duplicate the file.

Dependencies

None — independently shippable refactor.

Requirements

  1. Move lib/deny-hooks.js's rule evaluator into gittensory-engine/src, mirroring governor/chokepoint.ts's own pure-function-plus-miner-wrapper split (the engine half computes a verdict with no IO; the existing miner lib file becomes a thin wrapper calling into it).
  2. Move lib/deny-hook-synthesis.js's synthesizeDenyRuleProposals/aggregateBlockerHistory/resolveEffectiveDenyRules the same way.
  3. Inject the clock into buildPathProposal's audit-stamp construction (an injectable nowMs, not a direct new Date() call) to match iterate-loop.ts's own convention, so the extracted logic is fully deterministic given its inputs.
  4. Re-export the extracted functions through gittensory-engine's public barrel.
  5. Out of scope: no new deny-hook rule types, no schema change, no behavior change to existing rule evaluation or proposal synthesis.

Deliverables / Acceptance Criteria

  • Pure deny-hook rule-evaluation and proposal-synthesis functions live in gittensory-engine/src, re-exported through its public barrel
  • packages/gittensory-miner/lib/deny-hooks.js and deny-hook-synthesis.js reduced to thin persistence wrappers calling the engine functions, with existing behavior unchanged
  • Existing deny-hook/deny-hook-synthesis test suites pass unchanged against the refactored call path
  • The extracted engine functions have no IO, no globals, and no direct Date/random calls (clock/randomness injected)

Test Coverage Requirements

This PR must ship with full test coverage for every changed line and branch — the repo's Codecov patch gate requires 99%+ coverage. A pure refactor with no behavior change should carry over existing test coverage; add a regression test asserting the extracted functions are callable from @loopover/engine alone (no @loopover/miner/SQLite dependency).

Expected Outcome

Closes the one concrete "should be portable, isn't" gap in the self-host/hosted architecture seam: a hosted service can now reuse deny-hook enforcement without depending on the SQLite-backed self-host stack.

Links & Resources

Metadata

Metadata

Assignees

No one assigned

    Labels

    gittensor:featureGittensor-scored feature linked to a feature issue — scores a 0.25x multiplier.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions