Skip to content

feat(miner-governor): budget/turn/termination cap calculator (pure) #4288

Description

@JSONbored

No budget/turn/termination cap calculator exists yet. A repo-wide search for budget-cap/turn-cap/termination-cap variants under packages/ and src/ turns up nothing on point — the one incidental hit, effectiveIssueCapForAccountAge in src/queue/account-age-throttle.ts:23-26, is an unrelated repo-side account-age issue-cap, not governor/miner code.

This is a SIBLING to packages/gittensory-engine/src/governor/rate-limit.ts, not something built on top of it. rate-limit.ts computes a different metric — a rolling-WINDOW request rate (evaluateLocalRateLimit(bucket, config, nowMs), rate-limit.ts:53) plus jittered backoff (jitteredBackoffMs, rate-limit.ts:84) — while this issue's caps are cumulative, monotonic counters across a whole run (total budget spent, total turns taken, elapsed session time vs. a termination ceiling): a different shape of math with no rolling window to reset. What they should share is placement (same packages/gittensory-engine/src/governor/ directory) and header discipline: pure, no IO, no internally-read clock (elapsed/usage values are caller-supplied, exactly like rate-limit.ts's injected nowMs/randomFn), and every numeric input normalized so a non-finite or negative value can never produce a NaN or negative verdict (mirror rate-limit.ts:41-45's finiteNonNegativeInt helper).

The audit ledger at packages/gittensory-miner/lib/governor-ledger.js (#2328) is the other neighboring piece, and it is explicitly NOT this issue either — its header says outright it "does not enforce governor policy; it only persists structured events other phases will emit" (governor-ledger.js:9). This issue's calculator is what would eventually PRODUCE one of the events that ledger records; it doesn't write to the ledger itself. For vocabulary consistency with that later wiring, this calculator's verdict should align with the immutable decision vocabulary already defined at packages/gittensory-engine/src/governor-ledger.ts:2-7 (GOVERNOR_LEDGER_EVENT_TYPES = ["allowed", "denied", "throttled", "kill_switch"]) rather than inventing a parallel one.

This is a pure calculator only — it computes a verdict from typed inputs and does nothing else. It does not store state, schedule anything, or gate a write action. The actual enforcement wiring — composing this calculator with rate-limit and the non-convergence detector into one real allow/deny chokepoint in front of every miner write action — is separate, maintainer-owned work tracked in #2340 ("wire the fail-closed Governor chokepoint before every write action," milestone 13), which names exactly this trio ("rate-limit, budget caps, non-convergence detector") as the calculators it composes. This issue builds one of those three pieces in isolation.

Deliverables

  • New packages/gittensory-engine/src/governor/budget-cap.ts exporting types for the three independent cap dimensions (budget/cost ceiling, turn/iteration-count ceiling, termination — e.g. max elapsed session time) plus a current-usage snapshot type, and a pure evaluateGovernorCaps(usage, limits)-style function
  • Each dimension evaluated independently and combined into one verdict; verdict vocabulary aligned with GOVERNOR_LEDGER_EVENT_TYPES (packages/gittensory-engine/src/governor-ledger.ts:2-7) rather than a new ad hoc set
  • No IO, no internal Date.now()/clock read — elapsed time and usage counts are caller-supplied inputs, matching rate-limit.ts's injected-clock pattern (rate-limit.ts:53,84)
  • Every numeric input normalized (non-finite/negative → safe default) so the function can never return NaN or a negative remaining-budget/turns value, mirroring finiteNonNegativeInt (rate-limit.ts:41-45)
  • Unit tests per dimension (under cap, at cap, over cap, non-finite/negative input) plus combined-verdict tests
  • Export from the package's public entrypoint (packages/gittensory-engine/src/index.ts, alongside the existing export * from "./governor/rate-limit.js"; at line 131)
  • Doc comment stating explicitly this is a pure calculator with no state/scheduling/enforcement, and naming maintainer: wire the fail-closed Governor chokepoint before every write action #2340 as the future (separate, maintainer-only) consumer — mirror the equivalent disclaimer already in rate-limit.ts:5-6 and governor-ledger.js:9

References

  • packages/gittensory-engine/src/governor/rate-limit.ts (whole file, esp. :1-8 header, :41-45 normalization helper, :53 and :84 injected-clock/random pattern) — the sibling pure calculator whose placement and discipline this mirrors, without inheriting from it
  • packages/gittensory-miner/lib/governor-ledger.js:9 — the audit ledger's own "does not enforce policy" disclaimer, the pattern this issue's disclaimer should match
  • packages/gittensory-engine/src/governor-ledger.ts:2-7 (GOVERNOR_LEDGER_EVENT_TYPES) — the decision vocabulary this calculator's verdict should align with
  • packages/gittensory-engine/src/index.ts:131 — where the new module should be re-exported, alongside rate-limit.js
  • src/queue/account-age-throttle.ts:23-26 — the one incidental "cap" hit in the repo, confirmed unrelated (repo-side account-age issue cap, not governor/miner)
  • maintainer: wire the fail-closed Governor chokepoint before every write action #2340 (milestone 13, maintainer-only) — the fail-closed chokepoint that composes this calculator with rate-limit and the non-convergence detector; explicitly not this issue

Metadata

Metadata

Assignees

No one assigned

    Labels

    gittensor:featureGittensor-scored feature linked to a feature issue — scores a 0.25x multiplier.help wantedExtra attention is needed

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions