Skip to content

feat(miner-manage): loop-closure summary builder (pre-reentry, read-only) (#4282) - #4378

Merged
loopover-orb[bot] merged 2 commits into
JSONbored:mainfrom
davion-knight:feat/gittensory-loop-closure-summary
Jul 9, 2026
Merged

feat(miner-manage): loop-closure summary builder (pre-reentry, read-only) (#4282)#4378
loopover-orb[bot] merged 2 commits into
JSONbored:mainfrom
davion-knight:feat/gittensory-loop-closure-summary

Conversation

@davion-knight

Copy link
Copy Markdown
Contributor

Adds buildLoopClosureSummary(sources, options) in packages/gittensory-miner/lib/loop-closure.js — a pure, read-only aggregator that summarizes a completed discover → plan → prepare → manage cycle before the miner loop considers re-entering (idle → discovering again). In the spirit of manage-status.js's collectManageStatus: it never calls GitHub, writes a local store, or decides/performs the re-entry itself.

Design

  • Caller-supplied cycle boundary (deliberate, per the issue): options.sinceSeq is the event-ledger seq at the end of the prior cycle, so events with a strictly greater seq are "this cycle" — reusing event-ledger.js's own readEvents({ since }) cursor rather than inventing a new persisted boundary marker.
  • Generic type-tally: the event ledger stores an open type vocabulary (phase writers define concrete types), so events are counted generically by type — new phase event types (plans built, PRs prepared/opened, outcomes recorded — landing via sibling issues) surface in the tally automatically without a hardcoded list here.
  • Output: per-type event counts + lastSeq (the boundary a caller passes as the next cycle's sinceSeq), queue state by status at cycle end, and the current run-state. Split data-collection from any rendering, mirroring manage-status.js.
  • Out of scope (explicit): deciding whether to re-enter, or performing the re-entry (setRunState).

Adds the hand-written loop-closure.d.ts alongside the module, matching the package's per-lib .d.ts convention.

Tests

test/unit/miner-loop-closure.test.ts: invalid-sources rejection, empty cycle, generic multi-type tally + last-seq, the sinceSeq boundary excluding prior-cycle events, unknown fallback for missing event/queue kinds + non-integer seq ignored, run-state present/absent, and determinism. Typecheck clean, 100% branch coverage on the new module.

Closes #4282

…nly) (JSONbored#4282)

Add packages/gittensory-miner/lib/loop-closure.js exporting a pure, read-only
buildLoopClosureSummary(sources, options): aggregate what happened in a completed
discover->plan->prepare->manage cycle before the miner loop considers re-entering
(idle -> discovering again). In the spirit of manage-status.js's collectManageStatus
- it never calls GitHub, writes a store, or decides/performs the re-entry itself.

The cycle boundary is caller-supplied: options.sinceSeq is the event-ledger seq at
the end of the prior cycle, so events with a strictly greater seq are 'this cycle',
reusing event-ledger.js's readEvents({ since }) cursor rather than inventing a new
persisted boundary marker. The ledger stores an open type vocabulary, so events are
tallied generically by type (new phase event types surface automatically). Output:
per-type event counts + last seq (the next cycle's boundary), queue state by status
at cycle end, and the current run-state.

Adds the hand-written loop-closure.d.ts declaration alongside the module, matching
the package's per-lib .d.ts convention. Deciding whether to re-enter, and the
re-entry itself (setRunState), are explicitly out of scope.

Closes JSONbored#4282
@davion-knight
davion-knight requested a review from JSONbored as a code owner July 9, 2026 05:51
@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 93.96%. Comparing base (ca5576f) to head (af0ce1c).
⚠️ Report is 31 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #4378   +/-   ##
=======================================
  Coverage   93.96%   93.96%           
=======================================
  Files         401      401           
  Lines       36869    36869           
  Branches    13480    13480           
=======================================
  Hits        34644    34644           
  Misses       1569     1569           
  Partials      656      656           
🚀 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 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-09 17:17:36 UTC

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

✅ Suggested Action - Approve/Merge

  • safe to merge

Review summary
This adds a small, pure, read-only aggregator (`buildLoopClosureSummary`) that tallies event-ledger and portfolio-queue state between miner-loop cycles, explicitly out of scope for re-entry decisions — matching the stated design and the `manage-status.js` precedent. The `sinceSeq`/`readEvents({since})` boundary is used correctly against the actual ledger contract (strictly-greater seq, as implemented in `event-ledger.js`), and `lastSeq` correctly seeds from `sinceSeq` so an empty cycle round-trips the boundary unchanged. Tests exercise the real branches (multi-type tally, boundary exclusion, unknown fallback, run-state presence/absence, determinism) rather than fabricating unreachable states, and the PR closes the linked issue #4282 with no schema/migration surface touched.

Nits — 5 non-blocking
  • loop-closure.js:24 — the external brief flags ~20 cyclomatic complexity against a threshold of 10 for `buildLoopClosureSummary`; consider splitting the event-tally and queue-tally loops into small named helpers (e.g. `tallyEvents`, `tallyQueue`) to bring this under the repo's complexity bar without changing behavior.
  • loop-closure.js:33 — an invalid `options.sinceSeq` (non-integer or negative) silently falls back to `null`, which widens the read to 'everything since the beginning' rather than throwing; since callers are expected to pass back a prior `lastSeq`, a malformed value passed by a future caller would silently produce an inflated cycle summary instead of surfacing the bug — consider throwing `invalid_since_seq` to match the fail-loud style used for `invalid_event_ledger`/`invalid_portfolio_queue`.
  • The 'unknown' fallback and non-integer-seq guard in the tally loop (loop-closure.js:39-42) protect against data shapes the real SQLite-backed `event-ledger.js` schema (`seq INTEGER NOT NULL UNIQUE`) can't actually produce — reasonable given the generic `sources` interface, but worth a one-line comment noting it's defensive-for-interface-generality rather than a real observed failure mode, so a future reader doesn't chase a phantom bug.
  • Split the event/queue tally loops into named helper functions to reduce `buildLoopClosureSummary`'s branch count and make each tally independently testable (loop-closure.js:24-63).
  • Make invalid `sinceSeq` a thrown error rather than a silent null fallback, consistent with how `invalid_event_ledger`/`invalid_portfolio_queue` are already handled (loop-closure.js:33).
Signal Result Evidence
Code review ✅ No blockers 1 reviewer
Linked issue ✅ Linked #4282
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: 88 registered-repo PR(s), 51 merged, 4 issue(s).
Contributor context ✅ Confirmed Gittensor contributor davion-knight; Gittensor profile; 88 PR(s), 4 issue(s).
Gate result ✅ Passing No configured blocker found.
Linked issue satisfaction

Partially addressed
The PR delivers a pure, read-only buildLoopClosureSummary with the caller-supplied sinceSeq boundary, event-ledger tallying, queue snapshot, run-state, and matching unit tests exactly as designed in the issue's boundary discussion — but it omits one of the four explicitly listed inputs: collectManageStatus's managed-PR rows (manage-status.js:59), which the issue calls out by name as a required dat

Review context
  • Author: davion-knight
  • Role context: outside_contributor
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: Rust
  • Official Gittensor activity: 88 PR(s), 4 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 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gittensory approves — the gate is satisfied and CI is green.

@loopover-orb
loopover-orb Bot merged commit 7f12d95 into JSONbored:main Jul 9, 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 9, 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 9, 2026
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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(miner-manage): loop-closure summary builder (pre-reentry, read-only)

2 participants