threepp
C++20 기반 크로스플랫폼 3D 라이브러리, 파이썬 바인딩 및 three.js 수준 API 제공
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗A dashboard of pull requests on Macaulay2/M2 — who wrote them, what they're labelled, and who the task force put on them. Two tabs:
JSAG — those are opened as drafts
by policy but are still meant to be reviewed. Other drafts are left out.Published daily to GitHub Pages. Run npm start any time to regenerate it locally.
requested_reviewersGitHub deletes a review request the moment that person submits a review. So "pending
requests" and "has reviewed" are disjoint sets, and neither remembers who did the assigning.
Counting requested_reviewers alone ranks the project's most active reviewer as idle.
This app therefore replays each PR's ReviewRequestedEvent / ReviewRequestRemovedEvent
timeline to recover who assigned whom, and sorts every (PR, reviewer) pair into one of three
origins:
| Origin | Meaning | Can it be pending? |
|---|---|---|
| mine | a task force selection: the assigner requested it, on or after the start date | yes |
| other | somebody else requested it — or the assigner did, before the task force began | yes |
| volunteer | nobody ever requested them; they reviewed anyway | no — nothing was ever asked |
The assigner has been requesting reviews as ordinary maintainer work for years, and the API
cannot tell that apart from the task force. Without TASK_FORCE_START the merged view claimed
8 PRs for an effort that had actually produced 2 — the other six were assignments from
April and May, months before the task force existed. Requests made before the cutoff are still
attributed truthfully (the tooltip names the requester and the date); they simply aren't the
task force's own output.
The PR table shows two visual states, because triage only asks one question: bold is a task force selection, grey is anyone else's (hover any name for who requested it). Bots are never bold whoever requested them — emphasis is for the humans carrying load.
The page is public, so it names the assigner throughout rather than addressing a "you" that most readers aren't.
The task force's own queue, and only that: one row per reviewer it has put on an open PR — exactly the pairs the PR table sets in bold. The columns are read off whose turn it is:
| Column | Meaning |
|---|---|
| awaiting first review | their move, and they have not reviewed since being picked |
| awaiting follow-up review | their move, and they have reviewed before: the author has answered since, or re-requested them |
| waiting on author | the author owes a reply to a review, so there is nothing to ask this reviewer yet |
Total is all three: a PR waiting on the author is still one the reviewer is assigned. The split is what matters for "who to ask next" — the last two used to be a single "reviewed, not approved" column, which ranked a reviewer the author owed three replies alongside one sitting on three answers.
The bar under Total splits the same way. The reviewer's two stages are one hue at two steps rather than two different colors: they are stages of one review, so the order should be visible in the color. The author's move steps out of the hue into a neutral grey, so the blue part of a bar is always what the reviewer could act on today. The numbers stay in the columns beside it, so the split never rests on color alone.
Only the first of those exists in GitHub's own view, and counting it alone — as this table used to — reports the task force's most engaged picks as carrying nothing: the moment they comment their request is deleted, while the PR still waits on their approval. Total is what the table sorts on — the load each reviewer carries — and the columns beside it sort too.
Requests the task force did not make are left out, and so are the people who only ever appear that way. A maintainer who comments on many PRs unasked would otherwise rank near the top of a table used to decide who to ask, on work nobody asked them for — as one did, at 11. Those reviews still show on the PR rows, in grey, and the merged tab still credits every approval whoever requested it. A pick who has answered everything keeps a row at zero: that is what free capacity looks like, and dropping it would hide the person most available to ask.
TASK_FORCE_START therefore moves rows here, as it does everywhere else.
The open tab leads with PRs opened since the start date that the assigner has not put anybody
on — the task force's own inbox, and the one queue that can be kept at zero. Dated from the
start deliberately: M2 has open PRs going back four years, and mixing that backlog in buries the
handful of new arrivals that actually need a decision this week. PRs labelled waiting for another PR are left out too: there is nothing to review until the other one lands.
data.json still carries the wider gap numbers, and the PR table can filter on them, but the
headline row stays on the number that implies an action. Those numbers split the open queue
three ways, and the middle group is the one worth naming:
| Meaning | |
|---|---|
pending | somebody is still to take a first look (pendingMine = at least one of them a task force pick) |
inProgress | no request outstanding, but a reviewer has commented or requested changes without approving |
noOneOnHook | nothing outstanding at all — the real queue of work to hand out (unassigned = not even a reviewer to nudge) |
inProgress used to be folded into noOneOnHook, for the same reason the workload table read
as zero: the review that removed the request is invisible to a request count. That put 13 of
M2's 21 supposedly untended PRs in a pile where somebody was already mid-review.
For each task force pick on an open PR, the build works out whose move it is, since when, and how
it got there. The rules are the ones assigned.sh uses, where they were worked out, so its
table matches a reviewer's row in the workload table:
The PR table's Waiting column shows the result, with the story in its tooltip ("picked 2026-07-06, ggsmith reviewed 2026-07-24, author responded 2026-07-24, last pushed 2026-07-28, no review since"). It replaces nothing: Updated is still there, but it moves with any activity at all — a ping, a label, a bot — so it is no guide to what is stalled.
This needs what the author did, which the main query does not fetch: comments, the last commit,
and every review round (latestReviews keeps one per person). So the build fetches it
separately, and only for open PRs with a task force pick — a fraction of the queue — batched by
number. Comments and reviews past the first 100 are not fetched; that can only make a wait read
shorter.
Both tabs carry timing stats, scoped to the task force's own requests. The open tab's are waits on a pick, first looks and follow-ups alike, measured as in whose turn it is. Three deliberate choices:
Two caveats the page states outright, rather than leaving a reader to infer:
Requires Node 18+ (for built-in fetch) and nothing else — no dependencies, no lockfile.
npm start # fetch, reconcile, render -> dist/
npm test # attribution logic
Open dist/index.html directly — it needs no server. The data is baked into the page, so it
never calls the API from the browser, and no token is ever exposed to one.
A token is required to build. Attribution needs the timeline, and the GraphQL API rejects
unauthenticated requests outright (403) — there is no anonymous fallback that gets this right.
The build uses GITHUB_TOKEN if set, otherwise gh auth token, so a local run with the
gh CLI authenticated needs no setup.
| Variable | Default | Meaning |
|---|---|---|
TASK_FORCE_OWNER | Macaulay2 | repo owner |
TASK_FORCE_REPO | M2 | repo name |
TASK_FORCE_ASSIGNER | d-torrance | whose requests count as task force selections |
TASK_FORCE_START | 2026-07-06 | requests before this date aren't task force selections |
TASK_FORCE_MONTHS | 3 | how far back the merged tab looks |
TASK_FORCE_ASSIGNER is deliberately independent of the token's identity: CI builds run as
github-actions[bot] but must still attribute to a real person.
.github/workflows/build.yml rebuilds daily (07:00 UTC) and on demand via Run workflow.
It publishes through upload-pages-artifact/deploy-pages rather than committing dist/,
so there's no daily junk commit. Set the repo's Settings → Pages → Source to
GitHub Actions.
GitHub's cron is best-effort and drifts under load; the page footer prints its real generation time and flags a snapshot older than two days.
| Path | |
|---|---|
build.js | fetch → reconcile → render |
src/query.js | GraphQL documents, pagination, the author-activity fetch, token resolution |
src/reconcile.js | timeline replay, origins, whose turn it is, workload, wait times |
src/render.js | HTML + CSS shell |
src/page.js | client-side sort/filter, inlined into the page |
test/ | attribution and timing tests over a synthetic fixture |