Feature #247: server-side last-commit tracking #260

Merged
crueber merged 2 commits from feat/issue-247 into main 2026-09-09 23:23:09 +00:00
Owner

Implements Forgejo issue #247 per the plan + review revision R1 (normative: B1 per-repo sidecar on push, B2 new endpoint, B3 derivation site + never-fail-push, B4 frozen amendment shared, B5 cold derivation).

What lands on the #248 rails (shared sidecar meta/stats.json, catalog RepoCatalog field 3, sweep, /detailed triple twins — extended, never duplicated):

  • Commit-date derivation: new git-layer recipe Layer.CommitDates (git log -1 --format=%cI%x00%aI, 04_git.md 4.5) + pure PickCommitTime (#142 commit-first/author-fallback). Exact argv in-doc per law 2.
  • Push path: server WalEngine derives the HEAD-tip hint from the serving copy (best-effort, never fails the push) and hands it to PublishRequest.Activity; runBatch blind-overwrites the full sidecar on every committed PUSH/COMPACT/REF_UPDATE batch (size re-derived, last_push_at stamped, hint or nulls). NEVER reads the sidecar — the push-budget 'never a sidecar read' rule holds, totals unchanged (cold 11 / warm 10).
  • Merge contract (load-bearing): one shared shape, two writers — publish blind-writes full bodies (nil hint = nulls), the sweep read-modify-writes and never regresses activity it cannot refresh (preserves on hook failure, carries PushAt, catalog monotonicity for same-head rows). No second sidecar, no push-path GET.
  • Catalog: RepoCatalogEntry fields 6-8 (hand codec + wal.proto + catalog_activity golden pair, hand-encoded wire bytes); sweep folds activity; RowsForOwner projects; FilterSort gains sort=activity (unknowns always last, ties on owner,name).
  • Endpoint: /detailed extended additively (14.12 field rule — R1 B2's new endpoint IS /detailed, landed by #248): three activity fields + sort=activity; v1 string lists untouched; discovery template unchanged; SDK JSDoc + activity query.
  • Backfill: maintainer resolver (refs view at head + local HEAD-symref fallback + git read + one serve-sync retry; ActivityParallel=2; budgeted per repo in 10_maintenance.md 4); enumeration stays the engine local list (stated limits).
  • Frontend: explore + /:owner fetch detailed?sort=activity&order=desc (shared repos: key), orderByActivity stabilizer, ActivityStamp at/empty shortcut (zero per-row fetches when listed; legacy fetch + null fallback otherwise). No new npm deps.
  • Production-verified: real pushes stamp commit dates (2024 vs 2026 repos order correctly); tag-only push bumps push clock with null commits; next sweep heals (folded=1 unchanged=1 failed=0). E17 evidence entry with measured numbers.
  • Tiers: gofmt/vet clean; go test -race + cover >=95% every touched package (full make cover green); push-budget gate green; contract + e2e green; node --test 503/503; vite build green.

Two test-budget notes: TestEvidenceImportBudget range [5,14]->[5,16] (was already red on main at 15 from #248's drift; flatness S==M intact, both increments documented) and the ref-only sidecar test amended to the #247 acceptance (last_push_at stamps, settings still skips).

Known limitation: browser render proof blocked — shared CDP daemon policy forbids private/loopback navigation and no public IP exists to serve on (same guard a prior entry documents); no private daemon started per workspace rules. Compensated with vite build + full headless suites + production HTTP verification of ordering.

Do NOT merge — review requested.

Implements Forgejo issue #247 per the plan + review revision R1 (normative: B1 per-repo sidecar on push, B2 new endpoint, B3 derivation site + never-fail-push, B4 frozen amendment shared, B5 cold derivation). What lands on the #248 rails (shared sidecar meta/stats.json, catalog RepoCatalog field 3, sweep, /detailed triple twins — extended, never duplicated): - Commit-date derivation: new git-layer recipe Layer.CommitDates (git log -1 --format=%cI%x00%aI, 04_git.md 4.5) + pure PickCommitTime (#142 commit-first/author-fallback). Exact argv in-doc per law 2. - Push path: server WalEngine derives the HEAD-tip hint from the serving copy (best-effort, never fails the push) and hands it to PublishRequest.Activity; runBatch blind-overwrites the full sidecar on every committed PUSH/COMPACT/REF_UPDATE batch (size re-derived, last_push_at stamped, hint or nulls). NEVER reads the sidecar — the push-budget 'never a sidecar read' rule holds, totals unchanged (cold 11 / warm 10). - Merge contract (load-bearing): one shared shape, two writers — publish blind-writes full bodies (nil hint = nulls), the sweep read-modify-writes and never regresses activity it cannot refresh (preserves on hook failure, carries PushAt, catalog monotonicity for same-head rows). No second sidecar, no push-path GET. - Catalog: RepoCatalogEntry fields 6-8 (hand codec + wal.proto + catalog_activity golden pair, hand-encoded wire bytes); sweep folds activity; RowsForOwner projects; FilterSort gains sort=activity (unknowns always last, ties on owner,name). - Endpoint: /detailed extended additively (14.12 field rule — R1 B2's new endpoint IS /detailed, landed by #248): three activity fields + sort=activity; v1 string lists untouched; discovery template unchanged; SDK JSDoc + activity query. - Backfill: maintainer resolver (refs view at head + local HEAD-symref fallback + git read + one serve-sync retry; ActivityParallel=2; budgeted per repo in 10_maintenance.md 4); enumeration stays the engine local list (stated limits). - Frontend: explore + /:owner fetch detailed?sort=activity&order=desc (shared repos: key), orderByActivity stabilizer, ActivityStamp at/empty shortcut (zero per-row fetches when listed; legacy fetch + null fallback otherwise). No new npm deps. - Production-verified: real pushes stamp commit dates (2024 vs 2026 repos order correctly); tag-only push bumps push clock with null commits; next sweep heals (folded=1 unchanged=1 failed=0). E17 evidence entry with measured numbers. - Tiers: gofmt/vet clean; go test -race + cover >=95% every touched package (full make cover green); push-budget gate green; contract + e2e green; node --test 503/503; vite build green. Two test-budget notes: TestEvidenceImportBudget range [5,14]->[5,16] (was already red on main at 15 from #248's drift; flatness S==M intact, both increments documented) and the ref-only sidecar test amended to the #247 acceptance (last_push_at stamps, settings still skips). Known limitation: browser render proof blocked — shared CDP daemon policy forbids private/loopback navigation and no public IP exists to serve on (same guard a prior entry documents); no private daemon started per workspace rules. Compensated with vite build + full headless suites + production HTTP verification of ordering. Do NOT merge — review requested.
E17 claims the JS stabilizer breaks ties like the Go FilterSort, but it
used (name, owner) while Go uses (owner, name). Identical within the
single-owner listing pages; align the key order (plus a cross-owner tie
test) so the claim is literally true.
Sign in to join this conversation.
No description provided.