Repository navigation
Say when an RSI fetch was capped and keep skipped runs out of the rate (#814) - #38
Conversation
ThinkFlowLab#814) allPages ended at 20 pages of 100 without saying so, so a listing of 2000+ items was reported as a complete total; it now returns whether the last allowed page came back full, and the report prints "at least 2000 items, possibly truncated" for that repository with a note that the counts are a lower bound. skipped was filed under other and counted in the success-rate denominator, so 49 runs that measured nothing held the 2026-10-22 rate down. It now has its own bucket, its own column and stays out of the denominator with unknown. The 2026-10-22 report is regenerated: 720/776 = 92.8% overall instead of 720/825 = 87.3%.
|
Verdict: PASS at 018daf8 Both under-counts are closed, the regenerated report is reproducible against the live API, and every acceptance item checks out. One non-blocking formatting defect in the truncation path. Ran:
Checked, and right: One non-blocking defect: the runs marker is pushed inside the per-repository loop, so it lands between two table rows: In rendered markdown the |
Written-by: Dev4
Tip SHA:
018daf8576b4db7764ec1106d768440a77a8b7a8(basef20cfa37f9f2ffd07fa1387eece36756fbd49dbb).Fixes ThinkFlowLab#814
Reproduce
Both under-counts were reproduced by running the code at
f20cfa37, not by reading it.skippedfiled underotherand counted in the denominator. The issue's own case, run against the old module:The bucket list had no
skippedkey at all (success,failure,cancelled,other,unknown), so a run that measured nothing moved the rate in exactly the wrong direction. The same defect is visible in the checked-in baseline: the 2026-10-22 report printed720/825 = 87.3%withother: 49, and all 49 of those runs areconclusion: skipped.A capped fetch returned as a total.
allPageswas driven with a stubbedfetchthat answers 20 pages of 100 runs, all inside the day:So a busy day's listing came back as 2000 items with no flag, no marker and exit code 0 — the number looks complete precisely when it is not. The new report line for that repository reads:
What changed
.github/scripts/rsi-baseline.mjsallPagesnow returns{ items, truncated }and takes an injectablerequestso the cap is tested without the network.truncatedis true when the last allowed page (page 20 of 20) came back full — that is "2000 or more", the case that cannot be told apart from "exactly 2000". A page that comes back short returnstruncated: false.MAX_PAGES = 20is exported and used both by the loop and by the report line, so the marker cannot drift from the cap.CONCLUSION_BUCKETSgainsskipped, andsummarizeRunsroutes it to its own bucket instead ofother(timed_out,action_required,stalestill go toother, unchanged).rateskeeps its formulasuccess + failure + cancelled + other;skippedandunknownstay out. Comment states whycancelledis in andskippedis out.renderReportgains aSkippedcolumn (in the per-event rows, theallrow and the all-unknownrow), names the exclusion in the formula line, and prints the truncation bullet per repository under each table, only when that fetch was capped.maincarriestruncatedByRepointo the report and writes one line to stderr when a listing was capped. The exit code stays 0 on purpose: a truncated day is still a day measured, and the marker — not the exit code — is the signal..github/scripts/rsi-baseline.test.mjs— five new cases: the skipped bucket and denominator arithmetic (3 success + 2 skipped →skipped: 2, denominator 3,3/3 = 100.0%), a full 20-page sequence → truncated, 1999 items → not truncated, a short page stopping the walk at 3 requests, and a rendered report with theSkippedcolumn, the formula wording and exactly two truncation markers for the capped repository and none for the short one.docs/rsi-baseline.md— theSkippedcolumn and the denominator rule, "a capped listing is a floor, not a total", and the test list.docs/reports/2026-10-22-rsi-baseline.md— regenerated with the new bucketing. Overall720/776 = 92.8%(was720/825 = 87.3%), theotherrow39/43 = 90.7%(was39/92 = 42.4%), and a newSkippedcolumn carrying the 49.What I ran
Local, at this tip:
node --test .github/scripts/rsi-baseline.test.mjs→ 10/10 pass.node --test .github/scripts/*.test.mjs→ 276/276 pass (the fourds-bot-patchescases needgitonPATH; without it they fail withspawnSync git ENOENT, which is the box, not this diff — 271 before this branch, 276 with the five added here).node .github/scripts/testing-layers.mjs --check→325 test file(s) in 13 workflow(s), every test file and workflow classified.node .github/scripts/changelog.mjs check→7 fragment(s) in changelog.d/ are well formed(no fragment added: this changes a report tool and its docs, no user-visible behaviour).End to end against the live API, the acceptance command:
exit 0, and the diff against the checked-in report is exactly three things: the
Generatedtimestamp, the addedSkippedcolumn with its two rate changes, and the formula line. Everything else — 158 lines, the run links, the notes — is byte-identical, so the two under-counts are the only thing that moved.The 2026-10-22 report itself is the reproduction of the rate change: 49
skippedruns leave the denominator and the rate goes 87.3% → 92.8%.Red without the source change
Three cuts, each made alone on a copy of this tree and run against the new tests:
skippedback underother(KNOWN_CONCLUSIONSloses it) → 2 red:a skipped run is its own bucket and never moves the rate—skipped has its own bucket, not other / 0 !== 2; andthe report carries the skipped column …—the skipped run has its own cell.skippedin the denominator (+ buckets.skippedinrates) → 3 red:cancelled runs stay in the denominator, missing conclusions do not(an empty day becomesdenominator: NaN,successRate: NaNinstead of0/null),a skipped run …—only the runs that produced an outcome divide the rate / 5 !== 3, and the render case —skipped is out of the rate.allPagesbreaks on a short page and always returnstruncated: false) → 1 red:a capped listing says it was capped, a short page does not—a full last page means 2000 or more / false !== true.Restoring each cut returns 10/10.
Not run
npm run verifyand thecore/suites: nothing undercore/orplugins/changed, the whole diff is.github/scriptsplusdocs/.request, which runs the real loop and the real return-value contract, and the marker is asserted throughrenderReport.packagejob'sTests of the repo scriptsstep is what will run the 276 here.actionlint: no workflow file is touched.Risk
.github/**is T3: this needs a PASS at this tip.