Skip to content

feat(miner-governor): persist governor cross-attempt state (#5134) - #5203

Merged
JSONbored merged 1 commit into
mainfrom
feat/governor-state-persistence-5134
Jul 12, 2026
Merged

feat(miner-governor): persist governor cross-attempt state (#5134)#5203
JSONbored merged 1 commit into
mainfrom
feat/governor-state-persistence-5134

Conversation

@JSONbored

@JSONbored JSONbored commented Jul 12, 2026

Copy link
Copy Markdown
Owner

Summary

  • Advances Persist governor cross-attempt state (rate-limit, budget, convergence, reputation, self-plagiarism) #5134 (persistence infra only -- attempt-runner.js still calls the unwired evaluateGovernorChokepointGate; wiring the real CLI caller is separate follow-up work, tracked as the epic's own note below points out) (maintainer-only, safety-critical, epic Epic: Miner Wave 3.5 — Wire the autonomous loop end-to-end #5130): every governor-*.js wrapper (governor-write-rate-limit.js, governor-chokepoint.js) is a pure in/out transform — it computes and returns updated rate-limit buckets/backoff attempts/cap usage but nothing writes them to disk, so the mutable counters that should gate the next decision reset to zero on every process start.
  • Adds governor-state.js: a real SQLite store (mirroring local-store.js/claim-ledger.js's existing conventions — GITTENSORY_MINER_GOVERNOR_STATE_DB env var, ~/.config/gittensory-miner/governor-state.sqlite3 default, 0700/0600 permissions) holding rate-limit buckets + backoff attempts, budget/turn/termination cap usage, per-repo reputation history, and own-submission history (for self-plagiarism checks).
  • Adds governor-chokepoint-persisted.js: evaluateGovernorChokepointGatePersisted(input, options) composes this persistence with the existing, unmodified evaluateGovernorChokepointGate — loads rate-limit/backoff/capUsage before evaluating (unless the caller already supplied an explicit override), saves the returned mutated rate-limit state after. evaluateGovernorChokepointGate itself, and every one of its 25 existing tests, is untouched — kept as a separate composing wrapper rather than a behavior change to an already-relied-upon function, given this issue's own "needs its own dedicated review" flag.
  • capUsage is loaded but deliberately not saved by this wrapper: budget-cap.ts's GovernorCapUsage has no mutator (unlike the rate-limit buckets), since only the caller knows how much an attempt actually spent — known after it runs, not at gate-check time. Saving the next capUsage stays the caller's job via the exported saveCapUsage.
  • Deliberately out of scope: convergence-history persistence. non-convergence.ts's own doc comment says its counters belong on the portfolio-queue table (a pre-existing store), once that table grows attempt-history columns — inventing a second, competing store for the same concept here would violate the same non-duplication principle the ledger/state split (acceptance criterion 2) is built on. Reputation/self-plagiarism persistence primitives are built and tested (loadReputationHistory/saveReputationHistory/recordOwnSubmission/listRecentOwnSubmissions) but not yet auto-wired into the persisted gate the way rate-limit/cap-usage are — those are per-actionClass === "open_pr"-scoped optional fields on GovernorChokepointInput already, and wiring them up is natural work for whoever builds the real attempt-lifecycle caller (Build the autonomous repeat/supervising loop (discover → attempt → manage → repeat) #5135) alongside constructing the rest of that input.

Acceptance criteria (from #5134)

  • Two sequential CLI invocations correctly accumulate rate-limit/budget state — a limit tripped in invocation 1 is honored (and observable) in invocation 2. Directly tested: test/unit/miner-governor-chokepoint-persisted.test.ts's "ACCEPTANCE CRITERION" test opens a governor-state handle, runs one gate check, closes it, opens a brand new handle on the same on-disk file (simulating a fresh CLI process), and confirms the second invocation now denies.
  • governor-ledger.js's audit trail remains the authoritative history log; this adds decision-input state, not a second history log. governor-ledger.js is untouched.
  • evaluateGovernorChokepoint's precedence ladder is unchanged. The engine's pure calculator and the miner-lib evaluateGovernorChokepointGate wrapper are both untouched (25 existing tests for the latter still pass unmodified).

Scope

  • The PR title follows type(scope): short summary Conventional Commit format.
  • This PR is focused and does not mix unrelated backend, UI, MCP, docs, dependency, and deploy changes.
  • This follows CONTRIBUTING.md and does not reintroduce GitHub Pages, VitePress, site/, or CNAME.
  • Maintainer-only PR (epic Epic: Miner Wave 3.5 — Wire the autonomous loop end-to-end #5130, milestone "Miner Wave 3.5") — linked-issue-nit not applicable.

Validation

  • git diff --check
  • npm run typecheck
  • npm run test:coverage locally (736 test files, 0 failures, 14,596 tests passed). packages/gittensory-miner/** is outside vitest's coverage.include glob (only src/** + packages/gittensory-engine/src/** are collected), so codecov/patch cannot measure this diff — full unit coverage was still written as real correctness verification (44 new tests across the 2 new files, plus confirmed zero regression on the 25 existing governor-chokepoint.js tests).
  • npm run build:miner + npm run test:miner-pack — also fixed a pre-existing gap found in the process: packages/gittensory-miner/package.json's build script's node --check file list is hand-maintained, not generated from the directory, and was missing entries for new files (a separate follow-up fixes the same gap for the not-yet-merged Wire CLI dispatch for the real attempt pipeline (attempt command) #5132 PR).
  • npx tsx scripts/check-engine-parity.ts
  • npm audit --audit-level=moderate
  • npm run test:workers / npm run build:mcp / npm run test:mcp-pack / npm run ui:* — skipped, no src/**, apps/**, or MCP-surface files touched.
  • New behavior has unit tests for new branches, fallback paths, and error paths (empty-state defaults, per-repo isolation, override-vs-persisted-default precedence, malformed input rejection, cross-process-simulated accumulation).

If any required check was skipped, explain why:

  • Workers/MCP/UI checks skipped: this diff only touches packages/gittensory-miner/** and test/unit/*.ts.

Safety

  • No secrets, wallet details, hotkeys, coldkeys, user PATs, private keys, raw trust scores, private rankings, or private maintainer evidence are exposed.
  • Public GitHub text stays sanitized, low-noise, and does not imply compensation guarantees or optimization tactics.
  • N/A — no auth/cookie/CORS/GitHub App/Cloudflare/session changes.
  • N/A — no API/OpenAPI/MCP surface changes.
  • N/A — no UI changes.
  • N/A — no visible UI changes.
  • N/A — no public docs/changelog changes needed.

Notes

Every governor-*.js wrapper (governor-write-rate-limit.js,
governor-chokepoint.js) is a pure in/out transform: it computes and
returns updated rate-limit buckets/backoff attempts/cap usage but
nothing writes them to disk, so they reset to zero on every process
start. Adds governor-state.js (a real SQLite store, mirroring the
package's local-store.js/claim-ledger.js conventions) holding
rate-limit buckets/backoff, budget/turn/termination cap usage,
per-repo reputation history, and own-submission history for
self-plagiarism checks.

governor-chokepoint-persisted.js composes this with the existing,
UNMODIFIED evaluateGovernorChokepointGate (every prior caller/test of
it is untouched) rather than changing that function directly, since
this issue is flagged as the safety-critical core of its gap-fill
batch and a wrapper is a smaller, more isolated surface to review.

Convergence-history persistence is deliberately out of scope: it
belongs on the portfolio-queue table per non-convergence.ts's own doc
comment, not a new competing store.

Closes #5134
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
gittensory-ui f296936 Commit Preview URL

Branch Preview URL
Jul 12 2026, 09:12 AM

@superagent-security

Copy link
Copy Markdown
Contributor

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

@codecov

codecov Bot commented Jul 12, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.34%. Comparing base (87ab6d6) to head (f296936).
⚠️ Report is 8 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #5203   +/-   ##
=======================================
  Coverage   94.34%   94.34%           
=======================================
  Files         473      473           
  Lines       39963    39963           
  Branches    14569    14569           
=======================================
  Hits        37702    37702           
  Misses       1585     1585           
  Partials      676      676           
Flag Coverage Δ
shard-1 46.33% <ø> (-0.01%) ⬇️
shard-2 34.25% <ø> (-0.42%) ⬇️
shard-3 31.02% <ø> (-0.99%) ⬇️
shard-4 33.18% <ø> (+1.26%) ⬆️
shard-5 33.66% <ø> (-0.09%) ⬇️
shard-6 45.05% <ø> (+0.21%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@loopover-orb loopover-orb Bot added the gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier. label Jul 12, 2026
@JSONbored JSONbored self-assigned this Jul 12, 2026
@loopover-orb

loopover-orb Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Warning

🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨

⏸️ Gittensory review result - manual review recommended

Review updated: 2026-07-12 09:26:23 UTC

7 files · 2 AI reviewers · 1 blocker · readiness 100/100 · CI green · unstable

⏸️ Suggested Action - Manual Review

  • AI reviewers agree on a likely critical defect: packages/gittensory-miner/lib/attempt-runner.js:4 still imports evaluateGovernorChokepointGate and packages/gittensory-miner/lib/attempt-runner.js:111 still calls that pure function, so the real attempt pipeline never loads or saves the new governor-state buckets/backoff and the Persist governor cross-attempt state (rate-limit, budget, convergence, reputation, self-plagiarism) #5134 reset-on-process-start failure remains
  • change the import/call to evaluateGovernorChokepointGatePersisted and pass a GovernorState or let the wrapper open the default store. — Resolve the flagged defect, or override if the AI reviewers are mistaken, then re-run the gate.

Review summary
This adds a new SQLite-backed governor-state store and a composing wrapper (evaluateGovernorChokepointGatePersisted) that loads rate-limit/backoff/capUsage before calling the existing, unmodified evaluateGovernorChokepointGate and saves rate-limit state after — a well-scoped, additive way to fix the real cross-attempt-state-reset bug described in #5134. The existing chokepoint gate and its 25 tests are untouched, capUsage is deliberately not persisted here (documented as the caller's responsibility via saveCapUsage), and the new store follows local-store.js/claim-ledger.js conventions (env var override, permissioned SQLite file, UPSERT-based scalar row). Tests exercise cross-process persistence (separate store instances), override-vs-persisted precedence for both rate-limit and capUsage fields, and denial-path persistence, which matches the real integration surface rather than fabricated states.

Blockers

  • packages/gittensory-miner/lib/attempt-runner.js:4 still imports evaluateGovernorChokepointGate and packages/gittensory-miner/lib/attempt-runner.js:111 still calls that pure function, so the real attempt pipeline never loads or saves the new governor-state buckets/backoff and the Persist governor cross-attempt state (rate-limit, budget, convergence, reputation, self-plagiarism) #5134 reset-on-process-start failure remains; change the import/call to evaluateGovernorChokepointGatePersisted and pass a GovernorState or let the wrapper open the default store.
Nits — 6 non-blocking
  • packages/gittensory-miner/lib/governor-state.js: nothing in this diff actually calls saveReputationHistory/recordOwnSubmission/listRecentOwnSubmissions from the persisted chokepoint wrapper, so reputation history and self-plagiarism submission history remain unwired to the actual gate flow despite being persisted — worth a follow-up issue or at least a comment noting this is deliberately future work.
  • packages/gittensory-miner/lib/governor-state.js:186 uses an unnamed magic number `200` as the default submission-list limit; a named constant (e.g. `DEFAULT_SUBMISSION_LIST_LIMIT`) would match the file's existing `DEFAULT_*` constant style.
  • packages/gittensory-miner/lib/governor-chokepoint-persisted.js: `evaluateGovernorChokepointGatePersisted` always calls `saveRateLimitState` even when the gate denies for a non-rate-limit reason (e.g. kill switch) — confirm this is intended, since it means every call touches the DB regardless of stage, not just rate-limit-affecting ones (tests do cover the denial-persists case, so this looks intentional, but worth a one-line comment).
  • Consider wiring `saveReputationHistory`/`recordOwnSubmission` into a follow-up self-reputation-throttle / self-plagiarism persisted wrapper (mirroring `governor-chokepoint-persisted.js`) so this issue's stated scope (reputation history, self-plagiarism history) is fully closed, not just rate-limit/capUsage.
  • packages/gittensory-miner/lib/governor-state.js:186 — name the `200` default limit as a module constant for consistency with `DEFAULT_RATE_LIMIT_BUCKETS` etc.
  • PR author also opened the linked issue — Link an issue that was opened by a different contributor, or provide a rationale for why this self-authored issue represents genuine discovery work.

Concerns raised — review before merging

  • packages/gittensory-miner/lib/attempt-runner.js:4 still imports evaluateGovernorChokepointGate and packages/gittensory-miner/lib/attempt-runner.js:111 still calls that pure function, so the real attempt pipeline never loads or saves the new governor-state buckets/backoff and the Persist governor cross-attempt state (rate-limit, budget, convergence, reputation, self-plagiarism) #5134 reset-on-process-start failure remains; change the import/call to evaluateGovernorChokepointGatePersisted and pass a GovernorState or let the wrapper open the default store.
Signal Result Evidence
Code review ❌ 1 blocker 2 reviewers, synthesized
Linked issue ✅ Linked #5134
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: 45 registered-repo PR(s), 37 merged, 409 issue(s).
Contributor context ✅ Confirmed Gittensor contributor JSONbored; Gittensor profile; 45 PR(s), 409 issue(s).
Gate result ❌ Blocking Repo-configured hard blocker found.
Improvement ✅ Minor risk: clean · value: minor — Code changes are accompanied by test evidence. LLM value judgment: moderate — The store and wrapper are a useful foundation for durable governor decisions, but the improvement is incomplete until the production attempt path actually uses them.
Review context
  • Author: JSONbored
  • Role context: owner (maintainer lane)
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: not available
  • Official Gittensor activity: 45 PR(s), 409 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Treat this as maintainer-lane context rather than normal contributor-lane activity.
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.
[BETA] Chat with Gittensory

Ask Gittensory a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.

  • @gittensory ask &lt;question&gt; answers contribution-quality Q&A with source citations and freshness.
  • @gittensory chat &lt;question&gt; answers in natural prose from cached decision-pack facts via local inference (maintainer/collaborator; read-only).
  • A plain-language @gittensory mention with a real question is routed to the closest matching read-only command automatically -- no exact syntax required.

Full command reference: https://gittensory.aethereal.dev/docs/gittensory-commands

🟩 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 12, 2026
@loopover-orb

loopover-orb Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

An AI reviewer flagged a likely defect, but its confidence was below this repository's configured close-confidence floor, so this is held for a maintainer to confirm instead of closing automatically. Resolve the flagged defect (see the review notes), or ask a maintainer to override.

@JSONbored
JSONbored merged commit a78edc8 into main Jul 12, 2026
20 checks passed
@JSONbored
JSONbored deleted the feat/governor-state-persistence-5134 branch July 12, 2026 09:38
@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 12, 2026
JSONbored added a commit that referenced this pull request Jul 12, 2026
…rnor state (#5134) (#5214)

#5203 added evaluateGovernorChokepointGatePersisted and governor-
state.js, but attempt-runner.js -- the one real production caller --
still imported and called the old, non-persisting
evaluateGovernorChokepointGate directly, so the reset-on-process-
start bug #5134 was filed to fix was never actually fixed for the
real pipeline, only the infrastructure to fix it existed.

Switches the import/call to evaluateGovernorChokepointGatePersisted,
adds an optional AttemptDeps.governorState field, and loosens
AttemptGovernorContext's rateLimitBuckets/rateLimitBackoffAttempts/
capUsage to optional (via the new GovernorChokepointInputPersisted
type) -- without that, callers would still be forced to hand-thread
honest-but-stale zero defaults on every invocation, silently
defeating the persistence an explicit input value always overrides.

Flagged by the gittensory review gate on #5203 after it had already
merged; recovered as this fresh PR since pushing to the merged
branch would have orphaned the commit.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier. manual-review Gittensor contributor context

Development

Successfully merging this pull request may close these issues.

1 participant