feat(tri): --as-of for the issue counts, and say when a read is a page rather than a total - #3032
Merged
Conversation
…e rather than a total `tri issues numbers` printed 486 open issues. That is not a fact about this repository; it is a fact about the moment it was asked. Read as of a date one month back the same query answers 140 -- a 3.5x move in 33 days, and nothing in the old output said which month it belonged to. `--as-of YYYY-MM-DD` fixes the population instead of the phrasing. It drops `--state open` (an issue open THEN may be closed NOW, and that filter removes exactly the rows that make the two readings differ), reads `--state all` with createdAt/closedAt, and keeps what was open at the end of that UTC day: open_at(created, closed, t) = created <= t && (closed empty || closed > t) The two boundaries point opposite ways and that is the whole rule: created AT the instant counts as existing, closed AT the instant counts as closed, so an issue opened and closed in the same second is not open. A row with no creation time is not counted rather than defaulted to open. The END of the day, not the start, because GitHub's own search reads a bare date in `created:<=2026-08-01` as covering that whole day. Two tools answering the same question must mean the same thing by the same date. Three independent routes agree on 140: GitHub search as two queries (43 + 97), a full walk of all 1482 issues computing open-at-T from timestamps, and this command. The first two were run by separate readers before the command existed. A malformed date is refused, not defaulted: `--as-of 2026-8-1` errors, because a date silently becoming "today" under a heading that says the reading is anchored is worse than no anchor at all. The shape check is `skillnum::is_iso_date`, the rule already mutation-proved for section 459, rather than a second copy of the same ten conjuncts. Separately, and one level down: `gh` returns at most --limit rows and says nothing about what it left behind, so a full page is a LOWER BOUND and only a short page is a total. Nothing here checked that. Measured 2026-09-03T16:35Z: 486 open against a default limit of 500 -- fourteen issues from every printed figure becoming a page, in silence. read_is_complete(returned, limit) = returned < limit The class was four call sites, not one: `numbers`, `dated`, `stale`, and `gates prs`, the last with a hardcoded 50 and no flag. Each was run at its own boundary -- --limit 486 prints LOWER BOUND, --limit 487 prints COMPLETE. Eight clauses mutated, eight killed. Skill sections 461 and 462. Refs #2994
Contributor
|
📓 NotebookLM Notebook linked to this PR
This notebook contains session context, decisions, and artifacts for this work. |
Contributor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
tri issues numbersprinted 486 open issues. That is not a fact about this repository; it is a fact about the moment it was asked. Read as of a date one month back, the same query answers 140 — a 3.5× move in 33 days, and nothing in the old output said which month it belonged to.--as-of YYYY-MM-DDfixes the population, not the phrasingIt drops
--state open— an issue open THEN may be closed NOW, and that filter removes exactly the rows that make the two readings differ — reads--state allwithcreatedAt/closedAt, and keeps:The two boundaries point opposite ways, and that is the whole rule: created AT the instant counts as existing, closed AT the instant counts as closed, so an issue opened and closed in the same second is not open. A row with no creation time is not counted rather than defaulted to open — guessing would put it in the population in silence, which is the failure this command exists to expose.
The END of the UTC day, not the start, because GitHub's own search reads a bare date in
created:<=2026-08-01as covering that whole day. Two tools answering the same question must mean the same thing by the same date, or the second reader gets a different number and blames the first.Three independent routes agree on 140: GitHub search as two queries (
created:<=T state:open→ 43, pluscreated:<=T closed:>T→ 97); a full walk of all 1482 issues computing open-at-T from timestamps; and this command. The first two were run by separate readers before the command existed.A malformed date is refused, not defaulted —
--as-of 2026-8-1errors out, because a date silently becoming "today" under a heading that says the reading is anchored is worse than no anchor at all. The shape check isskillnum::is_iso_date, the rule already mutation-proved for §459's recovered anchors, not a second copy of the same ten conjuncts.Without the flag the command now says so in its own first line: this reading is NOT anchored.
And one level down: a page presented as a total
ghreturns at most--limitrows and says nothing about what it left behind, so a full page is a lower bound and only a short page is a total. Nothing here checked that.Measured
2026-09-03T16:35Z: 486 open issues against a default--limitof 500. Fourteen issues from every figure this command prints becoming a page, in silence, with no line of output different.At exactly
limitrows there may or may not be more, and the honest answer is that this cannot tell — so it reports incomplete. Mutating<to<=kills a test whose fixture is the live boundary,(486, 500)and(500, 500).The class was four call sites, not one. Grepping
"--limit"acrosscli/tri/src/foundnumbers,dated,staleandgates prs— the last carrying a hardcoded 50 with no flag at all (10 open PRs at the time of measuring, so it does not bite yet, and when it does it will bite in silence). Each was then run at its own boundary:--limit 486--limit 487issues numbersissues datedissues stalegates prsThis is §457 one level down. There the population was a query and the figure went stale; here the tool does not know whether it saw all of the population. An anchor on an incomplete read is worse than none — it says this number can be taken again about a number that was never the whole thing.
cargo test -p tri— 501 passed, 0 failedRefs #2994