Repository navigation
Conversation
dm/tools/triage_report.py reads the open PRs and issues over GraphQL and merges each PR's head with main in git's object store (merge-tree). It prints a Markdown report by fixed rules: PRs already in main (a no-op merge, or a commit on main that names the PR), likely duplicates (the same game's title ID, or similar titles and changed files), conflicts with main and the commit since which they conflict, PRs without a linked issue, and issues with no reply and no label. .github/workflows/triage-report.yml runs it daily and on demand and puts the report in the job summary. It checks out main only and never runs a PR's code. It never closes, labels or comments. With the repository variable TRIAGE_REPORT_ISSUE set, a second job replaces that one issue's body with the report. The tests use a recorded API answer and a temporary repository, without network. docs/development.md lists the rules and their limits. Part of seedds#313.
seedds
added a commit
that referenced
this pull request
Nov 3, 2026
dm/tools/triage_report.py reads the open PRs and issues over GraphQL and
merges each PR's head with main in git's object store (merge-tree). It
prints a Markdown report by fixed rules: PRs that merge as a no-op, PRs
a commit on main names ("PR #N", or "(#N)" in its subject), likely
duplicates (the same game's title ID, or similar titles and changed
files), conflicts with main and the commit since which they conflict,
PRs without a linked issue, and issues with no reply and no label.
A commit that names a PR often takes only part of it or just mentions
it, so a named PR is listed on its own and stays in the other tables;
only a no-op merge leaves them. On today's PRs the four named ones all
still conflict.
.github/workflows/triage-report.yml runs it daily and on demand and puts
the report in the job summary. It checks out main only and never runs a
PR's code. It never closes, labels or comments. With the repository
variable TRIAGE_REPORT_ISSUE set, a second job replaces that one issue's
body with the report.
The tests use a recorded API answer and a temporary repository, without
network. docs/development.md lists the rules and their limits.
Part of #313.
Co-authored-by: v0lumehi <34629096+v0lumehi@users.noreply.github.com>
Owner
|
Landed as bd68816, with you as co-author. Thank you: the merge-tree approach and the title-ID duplicate rule work well here. One change on top. On today's PRs, every PR that a commit on
The tests cover both rules, and |
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.
What and why
Part of #313. This builds the item "A regular triage report on open PRs and issues".
182 pull requests and 113 issues are open today. For each PR, the first questions are the same. Is it in
mainalready? Does it conflict? Does another PR do the same? Which issue does it fix?dm/tools/triage_report.pyanswers them by fixed rules over the GitHub API and git. There is no model and no judgement. Anyone can run it and get the same rows..github/workflows/triage-report.ymlruns it every day at 05:17 UTC and on demand (workflow_dispatch). The report goes to the job summary. It never closes, labels or comments on anything. The maintainer decides what to close.The rules and their limits
main: merging the PR intomainleavesmain's tree unchanged. Or a commit onmainmade after the PR was opened names it as "PR #N" in its subject or body. The first rule has no false positive I know of. It misses a change that landed reworked. The second rule also matches a commit that names a PR it replaces or only takes part of. The row names the commit, so checking it takes one click. A PR in this section is left out of the others.dm/games/<title ID>/game.tsvfor the same game, or for a game whose profile is onmainalready. An update or DLC title ID counts as its base game (the low 13 bits are masked). Also PRs whose title words overlap by at least 30% and whose changed files overlap by at least 15% (Jaccard index). On today's PRs these thresholds find 3 groups. With a title overlap of 20% they find 9 groups. I did not check those 9 by hand, so I kept the stricter rule. Two PRs that fix one bug in different files are missed.main:git merge-treereports a conflict, and the row lists the conflicting files. "Since" is the first commit onmainafter the PR's merge base that the PR no longer merges cleanly with. A bisection over the first-parent commits that touch the PR's files finds it. That assumes a conflict stays once it appears. When it does not, the row says "unknown" (none today). The date is the commit's date onmain, not the day anyone noticed. A rebase moves it. GitHub'smergeablefield is not used, because GitHub computes it lazily and can answerUNKNOWNfor a long list. Longest conflict first.closingIssuesReferences). And the title and body name none as#Nor an issue URL after Fixes, Closes, Resolves, Part of, Refs, Related to, See or Issue. HTML comments, like the template's, are left out. Numbers of open PRs are left out. A number of a closed PR still counts as a link.Every table is sorted oldest or longest first and shows 25 rows.
--limit 0shows all.What the workflow can do
reportjob hascontents: read,issues: readandpull-requests: read. It uses onlyGITHUB_TOKEN.main. It fetches each open PR's head intorefs/triage/pull/<N>. Git merges trees in its object store. No file of a PR is checked out or run.Proposal: one issue that always holds the latest report
The workflow has a second job,
publish, and it is off by default. Set the repository variableTRIAGE_REPORT_ISSUEto an issue number, and after each run it replaces that issue's body with the report. It edits that one issue and never comments. It runs in its own job withissues: writeand no checkout. The report writes authors without@, so nobody is mentioned. One side effect: each PR and issue that the body links gets a "mentioned this" entry in its timeline. #313 leaves open where the report goes, so I left it off. The job summary works without it.The report today
I ran it against seedds/nxnative on 2026-10-31 at 03:00 UTC, read only, with
--limit 10. Headline numbers: 2 PRs already inmain, 9 groups of likely duplicates (15 PRs), 80 PRs that conflict withmain, 148 PRs without a linked issue, and 75 issues with no reply and no label. In this copy, PR and issue numbers are code, so that this PR adds no timeline entries to them. The real report links them.Report of 2026-10-31
2026-10-31 03:00 UTC, 182 open pull requests (6 drafts) and 113 open issues on seedds/nxnative, against
mainat74e31944. Fixed rules over the API and git, listed in docs/development.md. The report never closes, labels or comments.mainmainAlready in
main, or named by a commit thereMerging the PR into
mainchanges nothing, or a commit onmainmade after the PR was opened names it as "PR #N". A commit may name a PR it replaces or only takes part of: read it before closing. Oldest first.#16737c7eaa8(2026-10-29) names it#7562aae9f8c(2026-10-31) names itLikely duplicates
Open PRs that add a profile for the same game (by title ID), or for one
mainalready has. Also PRs whose title words overlap by at least 30% and whose changed files overlap by at least 15%. Oldest PR first.010049900F546000#193Super Mario 3D All-Stars: multi-program applicati… (stan69b, 2026-10-25),#734Port Super Mario 3D All-Stars' Super Mario 64 and… (joaquinsandoval2307, 2026-10-30)dm/games/settings.tsv,dm/ios/Sources/DmGamepad.m+3#258iOS: add optional swipe camera and touch-control … (harshulkuhar, 2026-10-26),#630Add an on-screen control editor to the iOS touch … (klave7, 2026-10-29)01008F6008C5E000, already inmain#269Pokémon Violet: profile, Bluetooth LE takeover, C… (jthrilly, 2026-10-26),#415Pokémon Violet: profile, Bluetooth stubs, Nintend… (peachtaozhutou, 2026-10-27)dm/games/0100F43008C44000/README.md,docs/agents/symptoms.md#376Restore the Metal HUD option in Mac app builds (thehobbit85, 2026-10-27),#692Mac: fix Metal HUD menu hide/show (thehobbit85, 2026-10-30)0100ACD0163D0000, already inmain#384Batman: Arkham Asylum and Batman: Arkham Knight: … (Bobby201098, 2026-10-27)dm/gfx/nvn/nvn_mtl.m,dm/host/Makefile+19#481Runtime events: controller, thermal, save and the… (v0lumehi, 2026-10-27),#489Status notices: controller, heat and background s… (v0lumehi, 2026-10-27)010019A01E2F2000#520Metroid Prime 4: Beyond (010019A01E2F2000, 1.1.0)… (lx7720, 2026-10-28),#579Metroid Prime 4: Beyond: bring-up from#512,#514… (BrentRosen, 2026-10-28)01002E7016C46000, already inmain#532Add Cult of the Lamb 1.0.0 (01002E7016C46000): ga… (petervillaroman, 2026-10-28)0100AE00096EA000, already inmain#716Add the Hyrule Warriors: Definitive Edition 1.0.1… (monoquark, 2026-10-30)Conflicts with
main"Since" is the first commit on
mainafter the PR's merge base that the PR no longer merges cleanly with. A rebase moves it. Longest first.#2954eac07bREADME.md,dm/games/README.md+9#2734e91a3d0dm/gfx/nvn/dmsh_chain.h,dm/gfx/nvn/nvn_mtl.m+10#104787523f2README.md,dm/host/front.h+4#171641799d5dm/host/Makefile,dm/host/hle_svc.c+3#160be5b1976dm/gfx/nvn/nvn_mtl.m,dm/gfx/tools/shader_split.py+6#193796d592aREADME.md,dm/games/README.md+40#1861fa52195README.md,dm/games/README.md+2#2363aa706a3.gitignore,AGENTS.md+6#231435a2310dm/host/hle_audren.c#102fb20bce7dm/host/front_mac.m,docs/development.md70 more pull requests not shown.
Pull requests without a linked issue
No issue linked on GitHub, and none named as "Fixes #N", "Part of #N", "Refs #N", "Issue #N" or similar in the title or body. Oldest first.
#29#102#104#160#171#173#176#179#186#189138 more pull requests not shown.
Issues with no reply and no label
No comment from anyone but the author or a bot, and no label. "Named by" lists open PRs that link the issue. Oldest first.
#10#116#144#206#219#224#573#250#350#353#383#41965 more issues not shown.
Checked
python3 -m unittest -v dm/tools/tests/test_triage_report.pypasses (13 tests). They use a recorded GraphQL answer for 9 real PRs and 5 real issues (dm/tools/tests/triage_report_api.json, bodies shortened) and a temporary git repository. They need no network and no token.dm/tools/tests/test_docs.pypasses. Thetool-testsjob picks the new test up by its name.python3 dm/tools/lint_python.py(ruff and pyright): no finding in the new files.workflow_dispatchneeds the file there too. So it first runs after a merge.Docs
docs/development.mdhas a new "Triage report" section under Continuous integration. It says what each table shows, its limits, and that the report never closes, labels or comments. The report links to it.