Skip to content

fix(project-board): read every page of the metric lists - #2651

Merged
Birfy merged 1 commit into
mainfrom
dev/2650-project-metrics-paging
Nov 7, 2026
Merged

Birfy merged 1 commit into
mainfrom
dev/2650-project-metrics-paging

Conversation

@Birfy

@Birfy Birfy commented Nov 7, 2026

Copy link
Copy Markdown
Collaborator

Written-by: Dev

Fixes #2650
Owner: Dev
Reviewer: Reviewer
Tip SHA: 03d25f2
Base: b5394cf

What changed

readMetrics read exactly one page of /pulls and /issues, so the board's "last seven days" covered roughly the newest three. It now follows Link: rel="next" from the response headers until the list ends, and /pulls no longer sends a since that endpoint ignores. A 30-page cap keeps the rows read and answers truncated: true instead of claiming a complete window; a page that answers !ok stays a failed read (source.ok: false, read-failed: …), never a silent partial list. The five-minute cache, its field list, the withLive projection, summarizeMetrics arithmetic, the client and the metric names are unchanged.

Verification at the tip

Tip SHA: 03d25f2003a94059f8106336e86df34d6db0cb6d
Ran: cd core && TZ=UTC DSH_HARNESS=<harness> node --import ./test/harness-resolve.mjs --test test/project-metrics.test.js → 17 pass, 0 fail.
Red first: with core/src/host/project-metrics.js restored to the base blob, #2650 page-two, page-cap and failed-page cases fail (14 pass, 3 fail); back at the tip they pass.
Ran: node scripts/ds-bot-patches.mjs check → ok; node .github/scripts/changelog.mjs check → ok.
Ran: node scripts/build-client.mjs --check → ok (client.js untouched).
Not run: the full npm run verify (this machine cannot run two at once).
Docs: docs/subsystems/core-host.md updated for the page-by-page read.

Checkpoint

{
  "pr": 2651,
  "claim": "Dev",
  "issue": 2650,
  "summary": "readMetrics now follows Link rel=next for both GitHub lists instead of reading one page, so the seven-day counts and medians cover the whole window. /pulls no longer sends the since parameter that endpoint ignores. A 30-page cap keeps the rows read and answers truncated: true rather than claiming completeness. A failed page is still a failed read, never a partial list. Cache, projection, arithmetic and client are unchanged.",
  "files": ["core/src/host/project-metrics.js", "core/test/project-metrics.test.js", "patches/ds-bot/files/src/host/project-metrics.js", "patches/ds-bot/files/test/project-metrics.test.js", "docs/subsystems/core-host.md", "changelog.d/2650.fixed.md"],
  "checks": { "ran": "cd core && TZ=UTC node --import ./test/harness-resolve.mjs --test test/project-metrics.test.js; node scripts/ds-bot-patches.mjs check; node .github/scripts/changelog.mjs check; node scripts/build-client.mjs --check", "result": "green", "at": "03d25f2003a94059f8106336e86df34d6db0cb6d" },
  "next": "none — ready for review (T0, needs green tests-ok at the tip)"
}

readMetrics fetched one page of /pulls and /issues and never followed
Link: rel="next", so the board's "seven days" covered roughly the newest
three. /pulls also sent a since it ignores. Follow the pages (30-page cap,
truncated: true when the cap is hit) and keep a failed page a failed read.

Fixes #2650
@Birfy Birfy added the agent-pr Pull request opened by an agent label Nov 7, 2026
@Birfy Birfy self-assigned this Nov 7, 2026
@Birfy

Birfy commented Nov 7, 2026

Copy link
Copy Markdown
Collaborator Author

Verdict: PASS at 03d25f2
Written-by: Reviewer
Attestation: 03d25f2 role=Reviewer

Ran at this tip:

$ cd core && TZ=UTC DSH_HARNESS=/data/dsh/bot/workspace/d2607/repo/core/dev/harness node --import ./test/harness-resolve.mjs --test test/project-metrics.test.js
# tests 17  # pass 17  # fail 0
$ cp base/FlyBot-b5394cf4544ecb1589873403789ef6cbd35ab569/core/src/host/project-metrics.js FlyBot-03d25f2003a94059f8106336e86df34d6db0cb6d/core/src/host/project-metrics.js
$ cd core && TZ=UTC DSH_HARNESS=/data/dsh/bot/workspace/d2607/repo/core/dev/harness node --import ./test/harness-resolve.mjs --test test/project-metrics.test.js
# tests 17  # pass 14  # fail 3
# not ok: the metric lists are read page by page; a `next` that never ends stops at the page cap; a failed page is a failed read
$ node .github/scripts/changelog.mjs check
# changelog: 12 fragment(s) in changelog.d/ are well formed
$ node scripts/ds-bot-patches.mjs check
# ok 10 patches apply cleanly in order; ok core/ equals ds-bot/ + patches/ds-bot/

Red first: with only core/src/host/project-metrics.js swapped back to the base blob (base b5394cf4544ecb1589873403789ef6cbd35ab569) the three #2650 cases fail (14 pass, 3 fail); at the tip they pass (17/17).

Tier: risk-tier: T3; basis: core/src/host/project-metrics.js=T2, changelog.d/2650.fixed.md=T1, core/test/project-metrics.test.js=T1, patches/ds-bot/files/src/host/project-metrics.js=T1, patches/ds-bot/files/test/project-metrics.test.js=T1, docs/subsystems/core-host.md=T0 (recomputed from the PR diff with the gate's own judge(); the added https://api.github.com line in the source also hits a T3 diff pattern). So this tip needs a PASS even though the task said T0.

CI at this tip: all checks terminal; tests-ok success; enqueue-guard failure is only "no Verifier report names the tip" and is cleared by this PASS; no other failure.

Review:

  • Scope is exactly the six files above. No unrelated core/ or patches/ds-bot/ change; patches/ds-bot/files/ mirrors match core/ (patches check green).
  • readMetrics now follows Link: rel="next" per response (nextPage over response.headers.get('link')), so the header is read where the fetch happens; a foreign-host next is not followed with the token, and MAX_PAGES = 30 bounds a hostile/looping next.
  • /pulls no longer sends since (the endpoint ignores it); /issues keeps it. truncated: true is returned only when the cap is hit, and is not written into the shared cache entry, so a capped read never claims a complete window.
  • A failed page (!response.ok) still returns source.ok: false with reason: read-failed: … and is not cached — never a silent partial list.
  • Cache key/fields, withLive, summarizeMetrics, metric names and the client are untouched; the added truncated field is additive at the top level only.
  • Tests carry the deciding row on page two for both lists (merge and close today), assert the page-two count/median, the absent since on /pulls, the 30-page cap (truncated: true, rows kept) and the failed-page branch. Reverting the source turns them red.

Not run: node scripts/build-client.mjs --check (esbuild is not installed in a clean tarball checkout; the diff contains no core/src/client/ or client.js change), and the full npm run verify (one suite at a time on this box, per the task).

@github-actions github-actions Bot added the pass label Nov 7, 2026
@Birfy
Birfy added this pull request to the merge queue Nov 7, 2026
Merged via the queue into main with commit 8dd15c6 Nov 7, 2026
17 of 18 checks passed
@Birfy
Birfy deleted the dev/2650-project-metrics-paging branch November 7, 2026 23:46
@github-actions github-actions Bot removed the agent-pr Pull request opened by an agent label Nov 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Read every page of the metric lists so the Project board's seven-day numbers are the seven days

1 participant