Skip to content

Add a daily triage report on open pull requests and issues - #770

Closed
v0lumehi wants to merge 1 commit into
seedds:mainfrom
v0lumehi:triage-report
Closed

v0lumehi wants to merge 1 commit into
seedds:mainfrom
v0lumehi:triage-report

Conversation

@v0lumehi

Copy link
Copy Markdown
Contributor

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 main already? Does it conflict? Does another PR do the same? Which issue does it fix? dm/tools/triage_report.py answers 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.yml runs 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

  • Already in main: merging the PR into main leaves main's tree unchanged. Or a commit on main made 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.
  • Likely duplicates: PRs that add dm/games/<title ID>/game.tsv for the same game, or for a game whose profile is on main already. 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.
  • Conflicts with main: git merge-tree reports a conflict, and the row lists the conflicting files. "Since" is the first commit on main after 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 on main, not the day anyone noticed. A rebase moves it. GitHub's mergeable field is not used, because GitHub computes it lazily and can answer UNKNOWN for a long list. Longest conflict first.
  • Pull requests without a linked issue: GitHub links none (closingIssuesReferences). And the title and body name none as #N or 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.
  • Issues with no reply and no label: no comment from anyone but the author or a bot, and no label. "Named by" lists the open PRs that link the issue. An issue with more than 30 comments counts as answered, because the query reads 30.

Every table is sorted oldest or longest first and shows 25 rows. --limit 0 shows all.

What the workflow can do

  • The report job has contents: read, issues: read and pull-requests: read. It uses only GITHUB_TOKEN.
  • It checks out main. It fetches each open PR's head into refs/triage/pull/<N>. Git merges trees in its object store. No file of a PR is checked out or run.
  • The API part is about 6 GraphQL queries per run (50 PRs or 100 issues per page). My local run took 30 seconds.

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 variable TRIAGE_REPORT_ISSUE to 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 with issues: write and 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 in main, 9 groups of likely duplicates (15 PRs), 80 PRs that conflict with main, 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 main at 74e31944. Fixed rules over the API and git, listed in docs/development.md. The report never closes, labels or comments.

Pull requests already in main 2
Likely duplicates 9 groups, 15 pull requests
Pull requests that conflict with main 80
Pull requests without a linked issue 148
Issues with no reply and no label 75 (75 with no reply, 112 with no label)

Already in main, or named by a commit there

Merging the PR into main changes nothing, or a commit on main made 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.

PR Title Author Opened Why Issues
#167 Textures: upload CPU-written linear and unflushed sampled textures Jiiiin 2026-10-25 body of 37c7eaa8 (2026-10-29) names it -
#756 Fix shared Python lint failures in Unreal engine-region rewriting thehobbit85 2026-10-30 merges as a no-op, body of 2aae9f8c (2026-10-31) names it -

Likely duplicates

Open PRs that add a profile for the same game (by title ID), or for one main already has. Also PRs whose title words overlap by at least 30% and whose changed files overlap by at least 15%. Oldest PR first.

Same Pull requests
profile 010049900F546000 #193 Super Mario 3D All-Stars: multi-program applicati… (stan69b, 2026-10-25), #734 Port Super Mario 3D All-Stars' Super Mario 64 and… (joaquinsandoval2307, 2026-10-30)
dm/games/settings.tsv, dm/ios/Sources/DmGamepad.m +3 #258 iOS: add optional swipe camera and touch-control … (harshulkuhar, 2026-10-26), #630 Add an on-screen control editor to the iOS touch … (klave7, 2026-10-29)
profile 01008F6008C5E000, already in main #269 Pokémon Violet: profile, Bluetooth LE takeover, C… (jthrilly, 2026-10-26), #415 Pokémon Violet: profile, Bluetooth stubs, Nintend… (peachtaozhutou, 2026-10-27)
dm/games/0100F43008C44000/README.md, docs/agents/symptoms.md #376 Restore the Metal HUD option in Mac app builds (thehobbit85, 2026-10-27), #692 Mac: fix Metal HUD menu hide/show (thehobbit85, 2026-10-30)
profile 0100ACD0163D0000, already in main #384 Batman: Arkham Asylum and Batman: Arkham Knight: … (Bobby201098, 2026-10-27)
dm/gfx/nvn/nvn_mtl.m, dm/host/Makefile +19 #481 Runtime events: controller, thermal, save and the… (v0lumehi, 2026-10-27), #489 Status notices: controller, heat and background s… (v0lumehi, 2026-10-27)
profile 010019A01E2F2000 #520 Metroid Prime 4: Beyond (010019A01E2F2000, 1.1.0)… (lx7720, 2026-10-28), #579 Metroid Prime 4: Beyond: bring-up from #512, #514… (BrentRosen, 2026-10-28)
profile 01002E7016C46000, already in main #532 Add Cult of the Lamb 1.0.0 (01002E7016C46000): ga… (petervillaroman, 2026-10-28)
profile 0100AE00096EA000, already in main #716 Add the Hyrule Warriors: Definitive Edition 1.0.1… (monoquark, 2026-10-30)

Conflicts with main

"Since" is the first commit on main after the PR's merge base that the PR no longer merges cleanly with. A rebase moves it. Longest first.

PR Title Author Since Conflicting files
#29 Rhythm Heaven Groove: A16 legacy support, touch pad and ambient bars Roylam23 2026-10-21 54eac07b README.md, dm/games/README.md +9
#273 Mac host: unrolled-switch jump tables, multi-output transform feedbac… aznikline 2026-10-24 4e91a3d0 dm/gfx/nvn/dmsh_chain.h, dm/gfx/nvn/nvn_mtl.m +10
#104 Mac: native AppKit app bundle, preferences, and controller mapping jamessturges 2026-10-25 787523f2 README.md, dm/host/front.h +4
#171 Add native SM and CSRNG IPC transport b4f8abbb24dbf56a7d0280f296e16eeb 2026-10-25 641799d5 dm/host/Makefile, dm/host/hle_svc.c +3
#160 Xenoblade Chronicles 2 (0100F3400332C000, JP 3.0.0, SDK 3.5) on the M… lx7720 2026-10-25 be5b1976 dm/gfx/nvn/nvn_mtl.m, dm/gfx/tools/shader_split.py +6
#193 Super Mario 3D All-Stars: multi-program applications, nn::jit served … stan69b 2026-10-26 796d592a README.md, dm/games/README.md +40
#186 Add NINJA GAIDEN Sigma profile (0100E2F014F46000) Nishikori-Yui 2026-10-26 1fa52195 README.md, dm/games/README.md +2
#236 Bring up 30XX: SDK in subsdk modules, GL 4.5 / ES probe, GLSL 1.20, s… razzamatazm 2026-10-26 3aa706a3 .gitignore, AGENTS.md +6
#231 audren: drive a concurrent secondary renderer widestorm 2026-10-26 435a2310 dm/host/hle_audren.c
#102 Mac: add optional Xbox letter-based controller mapping SilverFT 2026-10-26 fb20bce7 dm/host/front_mac.m, docs/development.md

70 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.

PR Title Author Opened
#29 Rhythm Heaven Groove: A16 legacy support, touch pad and ambient bars Roylam23 2026-10-21
#102 Mac: add optional Xbox letter-based controller mapping SilverFT 2026-10-24
#104 Mac: native AppKit app bundle, preferences, and controller mapping jamessturges 2026-10-24
#160 Xenoblade Chronicles 2 (0100F3400332C000, JP 3.0.0, SDK 3.5) on the M… lx7720 2026-10-25
#171 Add native SM and CSRNG IPC transport b4f8abbb24dbf56a7d0280f296e16eeb 2026-10-25
#173 SHIN MEGAMI TENSEI V (010063B012DC6000, 1.0.0): game profile, version… Xanawer 2026-10-25
#176 Trails in the Sky 1st Chapter (01001E9023920000, update 1.0.6.1): gam… leoli-dev 2026-10-25
#179 Add physical keyboard support on iOS Jansen611 2026-10-25
#186 Add NINJA GAIDEN Sigma profile (0100E2F014F46000) Nishikori-Yui 2026-10-25
#189 Intel Mac: build the shader translator for x86_64 and document the pi… Gdange 2026-10-25

138 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.

Issue Title Author Opened Named by
#10 大佬能否支持双人成行双手柄适配? gdzhujun 2026-10-19 -
#116 Request: Assassin's Creed IV: Black Flag stephenschloesser 2026-10-24 -
#144 Pull request for sonic superstars Kamario876 2026-10-24 -
#206 Super Mario 3D All-Stars (010049900F546000, SDK 9.5): null deref at m… EzaiMod 2026-10-25 -
#219 Compatibility report: Sifu (01007B5017A12000, v393216) runs on M3 Mac… jamiecollinson 2026-10-25 -
#224 Pokémon: Let's Go, Pikachu! boots and plays on iPhone: patches and fi… s7ymwkptc4-a11y 2026-10-25 #573
#250 Shader split fails on Next Level Games archives in Mario Strikers: Ba… CarlosSouza 2026-10-26 -
#350 Build game with atmosphere mods? LovecraftianGodsKiller 2026-10-26 -
#353 Final Fantasy Resonance black "background" screen jackymyc 2026-10-27 -
#383 Edge case: nx_extract crashes with "The LinkedList is empty" instead … varyform 2026-10-27 #419

65 more issues not shown.

Checked

  • Tests: python3 -m unittest -v dm/tools/tests/test_triage_report.py passes (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.py passes. The tool-tests job picks the new test up by its name.
  • python3 dm/tools/lint_python.py (ruff and pyright): no finding in the new files.
  • A real run against seedds/nxnative with my token, read only. The numbers above come from it.
  • Not checked: the workflow on GitHub. A schedule runs only on the default branch, and workflow_dispatch needs the file there too. So it first runs after a merge.

Docs

  • docs/development.md has 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.
  • No game files, keys or data extracted from a game in the change or the attachments

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.
@github-actions github-actions Bot added tools Tools and scripts (dm/tools, scripts) docs Documentation ci Continuous integration and repository settings (.github) labels Nov 3, 2026
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>
@seedds

seedds commented Nov 3, 2026

Copy link
Copy Markdown
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 main named was one that commit took only part of, or just mentioned (#167, #662, #791). Dropping them from the other tables hid that they still conflict. Also, main usually names a PR as (#N) at the end of the subject, which the rule missed (#765). So now:

  • Merges as a no-op is its own section. Only these PRs are left out of the other tables.
  • Named by a commit on main is a separate section, with a "Merges" column. It matches "PR #N" anywhere and (#N) in a subject, and these PRs stay in the conflict, duplicate and no-linked-issue tables.

The tests cover both rules, and docs/development.md describes them. A local run over 263 open PRs took 81 s. The workflow runs on its schedule from now on. TRIAGE_REPORT_ISSUE is not set, so the report stays in the job summary for now.

@seedds seedds closed this Nov 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci Continuous integration and repository settings (.github) docs Documentation tools Tools and scripts (dm/tools, scripts)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants