Fix #283: explore ordered by recent commit #299

Merged
crueber merged 4 commits from fix/issue-283 into main 2026-09-10 19:21:13 +00:00
Owner

Fixes #283 — owner sections on /explore now rank by most-recent-commit repo instead of the newestFirst name proxy.

How: each OwnerSection reports ownerActivity(doc) (max last_commit_time over its #247 detailed rows) upward; the page orders via orderOwnersByActivity (known desc, unknown last, name tiebreak). Zero extra GETs — ranking reuses the detailed docs each section already fetches; no backend/SDK/API change (GET /api/v1/owners still returns name strings; a server-side rollup would remove the first-paint shift but was deliberately out of scope). newestFirst retired from the page, kept as a documented legacy export. First paint trails not-yet-loaded owners by name, then settles (documented in code + docs/go/12_web_ui.md).

Tests: node --test green (576/576, incl. 5 new #283 cases: mixed known/unknown, ties, single-owner, empty, non-array, slice-after-rank); vite build green. Browser proof open (shared-daemon loopback guard — no private daemon per workspace rules). No new deps.

Fixes #283 — owner sections on /explore now rank by most-recent-commit repo instead of the newestFirst name proxy. How: each OwnerSection reports ownerActivity(doc) (max last_commit_time over its #247 detailed rows) upward; the page orders via orderOwnersByActivity (known desc, unknown last, name tiebreak). Zero extra GETs — ranking reuses the detailed docs each section already fetches; no backend/SDK/API change (GET /api/v1/owners still returns name strings; a server-side rollup would remove the first-paint shift but was deliberately out of scope). newestFirst retired from the page, kept as a documented legacy export. First paint trails not-yet-loaded owners by name, then settles (documented in code + docs/go/12_web_ui.md). Tests: node --test green (576/576, incl. 5 new #283 cases: mixed known/unknown, ties, single-owner, empty, non-array, slice-after-rank); vite build green. Browser proof open (shared-daemon loopback guard — no private daemon per workspace rules). No new deps.
Client-side rank over the #247 detailed docs each section already
fetches (zero extra GETs): ownerActivity + orderOwnersByActivity in
web/src/lib/owners.js, Owners.jsx re-ranks as docs land, unknowns last.
newestFirst retired from the page (kept as documented legacy export).
Docs: 12_web_ui.md §2.3 + Decisions.
The client re-rank is correct for <=50 owners but cannot see past the
MAX_OWNERS cap (unmounted sections never report) and first paint lies.
Serve the ordering instead; keep the client rank as fallback.

- internal/sizecatalog: derived per-owner max-commit rollup
  (OwnerRollups — max LastCommitTime per owner over the catalog entries)
  + SortOwners (known in direction, unknowns always last, name tiebreak —
  the FilterSort total order). Derived, not stored: one comparison per
  repo in memory, no new bucket keys, no proto/codec/fixture change; a
  new push moves its owner's max without a rescan via the #247
  per-repo incrementality (pinned by TestOwnerRollupHealsIncrementally).
- internal/api: ?sort=activity&order= on the frozen []string owners list
  (default byte-identical, no catalog read; absent catalog degrades to
  name order, corrupt is 503) + NEW object-row endpoint
  GET /api/v1/owners/detailed (triple twins + discovery + SDK) carrying
  {name, last_commit_sha|null, last_commit_time|null} per owner.
- web: SDK owners.list(query) + owners.listDetailed(query) (no-store,
  issue #200); Owners.jsx fetches sort=activity&order=desc — first paint
  ordered, ranking covers ALL owners before the slice; the
  orderOwnersByActivity re-rank stays as fallback/enhancement for
  missing/stale values (decided + documented, not removed).
- docs: Decisions entries in 07_api.md, 12_web_ui.md, 14_extensibility.md
  (law 12); §8 + §2.3.1 body updated with the change.
- tests: table-driven rollup/sort (ties/unknowns/backfill), handler
  matrix (sort values, twins, discovery, degrade, 503s, nil store);
  sdk-surface + sdk-nostore pins. Coverage: api 95.3%, sizecatalog
  97.7%; -race clean; gofmt/vet clean.
Sign in to join this conversation.
No description provided.