Skip to content

feat(ui): 15-minute aggregation collapses repeated subnet-activity rows - #8466

Merged
JSONbored merged 1 commit into
mainfrom
feat/8366-activity-aggregation
Jul 28, 2026
Merged

feat(ui): 15-minute aggregation collapses repeated subnet-activity rows#8466
JSONbored merged 1 commit into
mainfrom
feat/8366-activity-aggregation

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

Closes #8366 — with a documented scope note posted first (#8366 (comment)): the shared-hook subscription and scoped LIVE affordance were already shipped (#8445/#8452, hardened by #8365); this PR is narrowly the one remaining requirement — the 15-minute aggregation rule itself.

What changed

aggregateActivityEvents (new, pure, unit-tested directly): groups CONSECUTIVE same-kind events — adjacent in the given newest-first order — into one row once they land within 15 minutes of the group's newest member. "Consecutive" is literal: a same-kind event that resumes after a different kind interrupts it starts a fresh group rather than retroactively merging into an earlier occurrence. An event missing observed_at never joins a group — no timestamp to prove the "within 15 minutes" claim.

Runs over whatever events array ActivityTableLoader already has — refreshed by a live stream event or the existing poll alike — so there's exactly one rendering path for both modes, per the issue's own text.

ActivityGroupRow: a group of one renders through the extracted ActivityEventRow completely unchanged (byte-for-byte identical to every row before this PR). A group of more than one collapses to a summary row — EventKindCell's own "× N · last Mm" (the issue's worked-example format), the newest member's block/time, and the shared hotkey when every member has the same one ("multiple" otherwise) — clickable to reveal the individual member rows nested beneath it.

Verified against live data

Confirmed against real production data via a running dev server: a genuine repeated-kind run ("Stake added × 4 · last 1m") collapses correctly, and clicking it expands to exactly 4 nested rows (row count 80 → 84, aria-expanded toggling false → true).

This also surfaced something worth knowing, flagged on the issue rather than worked around: this subnet's actual weight-setting traffic alternates "Timelocked weights revealed" and "Weights set" strictly back-to-back, so literal same-kind-adjacent grouping doesn't collapse that specific interleaved pattern — each kind interrupts the other before either repeats. That's the spec's own "consecutive" wording working exactly as written, not a bug — but it means the single most repetitive real pattern on this subnet isn't the one this aggregation shrinks. A "commit+reveal pair" heuristic would be a materially different, more speculative policy than what was asked for, so I didn't silently expand scope to cover it.

Not attempted here (noted on the issue): the entrance-animation portion of requirement 4 — a separate, smaller polish item for a follow-up rather than bundled into an already-substantial change. Requirement 4's other pieces (visibility gating, no per-row timers, fallback DOM parity) are already covered by #8365 for this same table.

Screenshots

Viewport · Theme Before After
Desktop · Light
Desktop · Dark
Tablet · Light
Tablet · Dark
Mobile · Light
Mobile · Dark

The desktop-light "after" shows a real collapsed row in the captured data ("Stake added × 2 · last 0m" with the collapse chevron) — the expand/collapse interaction itself (screenshots can't show a click) was verified directly against the DOM as described above.

Validation

npm run lint --workspace=apps/ui            # 0 errors
npm run format:check --workspace=apps/ui    # clean
npm run typecheck --workspace=apps/ui       # clean
npm test --workspace=apps/ui                # 1650 passed, 1 skipped (11 new)
npm run test:e2e --workspace=apps/ui        # 40 passed
npm run build --workspace=apps/ui           # clean

No API, schema, or generated-contract surface touched.

@loopover-orb

loopover-orb Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Important

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

⏳ LoopOver is waiting…

LoopOver has seen this pull request and is waiting on CI checks to finish before reviewing it. This comment will update once the review runs.

🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed · 🟨 Waiting

@superagent-security

Copy link
Copy Markdown

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

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 27, 2026

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
metagraphed-ui a71cdcc Commit Preview URL

Branch Preview URL
Jul 28 2026, 05:12 AM

@codecov

codecov Bot commented Jul 27, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.82%. Comparing base (edee55a) to head (a71cdcc).
⚠️ Report is 2 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #8466   +/-   ##
=======================================
  Coverage   97.82%   97.82%           
=======================================
  Files         419      419           
  Lines       29179    29179           
  Branches    10958    10958           
=======================================
  Hits        28545    28545           
  Misses        143      143           
  Partials      491      491           
🚀 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 manual-review Gittensor contributor context label Jul 27, 2026
@JSONbored
JSONbored changed the base branch from main to fix/8365-stream-hook-hardening July 28, 2026 00:52
JSONbored added a commit that referenced this pull request Jul 28, 2026
A clean main build measures 339.25 KB gzipped against the 340 KB budget --
Math.ceil rounds to 340, zero headroom -- the same trap the 320 -> 340 bump
(#8266) already fixed once, one tier later. Two unrelated open PRs (#8465,
#8466) both failed on this simultaneously with real measured deltas under
100 bytes each, confirming the gate was blocking on ordinary build-to-build
gzip variance, not either PR's own regression.

360 restores ~6% headroom, matching the 320 -> 340 bump's own margin.
Verified against a fresh local build: 340 KB / 360 KB budget.

Closes #8468
@JSONbored
JSONbored force-pushed the fix/8365-stream-hook-hardening branch from ee4be0e to b8c5ecb Compare July 28, 2026 01:21
@JSONbored
JSONbored force-pushed the feat/8366-activity-aggregation branch from 9e1e941 to 91b487e Compare July 28, 2026 01:23
Base automatically changed from fix/8365-stream-hook-hardening to main July 28, 2026 02:16
Subnet detail's Recent Activity/Activity tab showed five near-identical
rows whenever a busy epoch fired the same event kind repeatedly -- the
audit's own monotony finding. #8445/#8452 already wired the shared-hook
subscription and a scoped LIVE affordance for this table; #8365 hardened
it further (visibility gating, a shared ticker instead of per-row timers,
a zero-layout-shift status chip). The one requirement a verification pass
found still missing was the aggregation rule itself.

aggregateActivityEvents (new, pure, unit-tested directly): groups
CONSECUTIVE same-kind events -- adjacent in the given (newest-first) order
-- into one row once they land within 15 minutes of the group's newest
member. "Consecutive" is literal: a same-kind event that resumes after a
different kind interrupts it starts a fresh group rather than retroactively
merging into an earlier, unrelated occurrence of the same kind. An event
missing observed_at never joins a group -- there's no timestamp to prove
the "within 15 minutes" claim, matching this app's own "never assert
something unverifiable" convention elsewhere (registry-ticker's "never a
fabricated number", etc.).

Runs over whatever `events` array ActivityTableLoader already has --
refreshed by a live stream event or the existing poll alike -- so exactly
one rendering path covers both modes, per the issue's own requirement.

ActivityGroupRow: a group of one renders through the extracted
ActivityEventRow completely unchanged (byte-for-byte identical to every
row before this PR). A group of more than one collapses to a summary row
-- EventKindCell's own "× N · last Mm" (the issue's worked-example format),
the newest member's block/time, and the shared hotkey when every member
has the SAME one ("multiple" otherwise) -- clickable to reveal the
individual member rows nested beneath it.

Verified against live production data: a real repeated-kind run ("Stake
added × 4 · last 1m") collapses and expands correctly. Also surfaced (and
flagged on the issue, not silently worked around) that this subnet's
weight-setting traffic alternates two different kinds strictly back-to-
back, so literal same-kind-adjacent grouping doesn't collapse that
specific interleaved pattern -- correct per the issue's own "consecutive"
wording, not a bug, but worth knowing.

Not attempted here (noted on the issue): the entrance-animation portion of
requirement 4 -- a separate, smaller polish item left for a follow-up
rather than bundled into an already-substantial aggregation change.

Closes #8366
@JSONbored
JSONbored force-pushed the feat/8366-activity-aggregation branch from 91b487e to a71cdcc Compare July 28, 2026 05:08
@JSONbored
JSONbored merged commit 538a672 into main Jul 28, 2026
9 checks passed
@JSONbored
JSONbored deleted the feat/8366-activity-aggregation branch July 28, 2026 05:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

manual-review Gittensor contributor context

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(ui): subnet detail live activity + global LIVE affordance

1 participant