Repository navigation
pin-watch: census our own orgs, so a repo we publish is not invisible until someone pins it - #1193
Conversation
|
#1193 ready for review at e7d1a0e (2 commits: tool+workflow+docs, then the one pin it found). It overlaps open #1181 in the same two files by design — #1181 makes the bump step work at all, this one makes the coverage complete. I will rebase whichever lands second; the only real decision between them is the workflow's run-annotation line, where this PR's |
|
CI green at |
|
Preparing review... |
e7d1a0e to
43428e0
Compare
|
Preparing review... |
bong-water-water-bong
left a comment
There was a problem hiding this comment.
VERDICT: READY at 43428e06.
Re-derived here:
- The tool's own gate, live, at this head:
python3 tools/pin_watch.py --check --orgs 1bit-MONSTER,bong-water-water-bongprints exactly# Model pins: 1 of 148 moved (2026-11-05)— 148 pins (147 + the one this PR adds), 192 files — with no "published but not pinned" row, and exits 1 on the unsloth re-quant alone. That is the body's "after" line, reproduced. - Every value in the new pin entry is the Hub's, fetched independently of the tool: the repo's main is
64f092fe4fddba1030d4ef1531d3e33dd09d584a; the tree at that commit gives the threechat_template.jinjaat 2237 B / blob02a1c3bce33f…and the threetokenizer_config.jsonat 459 B / blob53aca4fc5079…; the downloaded templates hash tob6835114b7303ddd…(all three identical); the threetokenizer_config.jsonreally have nochat_templatekey, sonullis the recorded truth. - The census, derived outside the tool (
/models?author=…&full=truefor both orgs, joined againstmodels/pins.jsonat this head): 160 public repos across the two orgs, 86 not in the table, and none of those 86 ships a.gguf/.q4nx/chat_template.jinja/tokenizer_config.json— so over the real orgs the census reports nothing at this head. No false positive, which is the failure mode that would make a daily run permanently noisy. --self-test: 45oklines, 0 failures.tools/copyright.py --checkrc 0.
Nits:
report()computeschecked = total - len(notes), andnotesnow also carries census notes, so one unreadable org makes the first line say147 of 148 checked, 1 not checked(measured withreport([], ["our-org: could not be listed (429)"], 148, True, [])) when all 148 pins may have been read fine. Conservative direction, but the sentence is about the wrong set. The exit code is unaffected (notes and len(notes) == len(doc["pins"])).- The org listing is one call with
limit=1000and no pagination, so an org past 1000 repos would truncate silently and report a clean census. Today it is 69 + 91. - A "published, not pinned" row exits 1 but opens no PR and only annotates the run with
::warning::, so the nightly is green apart from the annotation — unlike census-watch, nothing files an issue. Fine if that is the design; it is the one case in this tool a person will miss.
…loses #1193) The NPU driver keeps one client and frees the partition about 2 s after that client exits. A request made in that window is refused with `npu runtime: device error (code 102): No such device`, which is a WAIT, not a verdict. Measured on the c28 board (5 Nov 2026, stick /data/logs/20261105T234218-9e768484): the check ran straight after its own NPU rows released the device and 8 of 25 rows reded on that window alone - chat, chat-npu, chat-npu-followup, chat-npu-stream, chat-npu-ladder, chat-npu-queue, chat-npu-queue-plain and bench, all on a healthy appliance. Now: a reply carrying code 102 is retried with a 1 s back-off, up to NPU_WAIT seconds (default 10), in both the body arm and the status arm; the footer adds one `info npu-wait` line with the seconds spent, so a run that only passed because the wait worked does not read as a clean run; and a 102 that outlives the window is handed back with the backend's own words, unchanged. Also fixes the self-test: --self-test used to append `RESULT: FAIL (this check died before its footer)` to a green run, because the EXIT trap cannot tell a self-test from a death. Proof: ~/wt/release-rc/rowproof-rc-102wait.sh - 22 cases in bash and the image's busybox ash, on this file's own bytes, with the appliance's real 102 body out of the c28 take log: waits 1 s then answers; stops at the window and returns the refusal unchanged; a clean reply still costs exactly one request.
|
Prep for the second landing: #1181 and #1193 conflict in The conflicts (two hunks, one file). Rebased either way, The defect only the union has. #1193 is the census half; #1181 is the Branch
I am not touching either PR's head: both are READY at the reviewed SHA. If #1193 lands first I rebase this onto |
… until someone pins it --check iterates over pins, so a repo that was never pinned is watched by nobody: the template audit of 2026-11-05 had to be done by hand for exactly that reason. --orgs A,B adds one listing per org (full=true carries the siblings) and reports every repo that ships a model artifact or a chat template and is not in the table, under 'Published, not pinned', in the report's first line and as a run annotation. Measured on the committed pins (19:3x): of 167 repos in the two orgs, 92 are not in models/pins.json — 89 of them hold only .1bp packs (the 1BP lane's format, not this table's business) and 2 are private (this file is public, docs/model-pins.md), so exactly one is reported: bong-water-water-bong/ZR1-1.5B-Strix. --pin now selects the files this table exists for (.gguf, .q4nx, chat_template.jinja, tokenizer_config.json) rather than .gguf alone: a container or LoRA repo has no .gguf, so it could not be pinned at all before this. --self-test 45/45, including: a published repo that ships a template is reported and an .1bp-only repo is not, a private repo stays out, an already-pinned repo is not reported twice, an org that cannot be listed is a note rather than a clean day, and --pin on a container repo pins the model plus both template files.
…ublished repo the census found) 6 files at 64f092fe: three chat_template.jinja (root and both checkpoints, all b6835114b7303ddd78919a82e4d9f7d8c26ed0d7dfc36beeb12d524f6144eab1 — the same digest the audit measured and the ZR1 GGUF arms carry) and three tokenizer_config.json that carry no chat_template key (459 B each, so null is the honest value, not a missing read). Nothing else in the file moved.
…ut-unpinned repo is not "did not move" `--json` is what the workflow's PR step reads, and its docstring calls it "the sweep". #1181 added it when a sweep was only pins; #1193 added `--orgs`, which finds repos by a different route (we publish them and nobody pinned them). Applied together, `--check --orgs --json` wrote `date, pins, changes, notes`: the census rows survived only in the Markdown report, and the artifact the PR step consumes described half of what the run looked at — the F1/#1157 failure mode, an artifact whose prose is wider than its contents. Measured before, on the union tree: a sweep with `1 of 148 moved, 1 published but not pinned` wrote a JSON with `changes: [unsloth/Qwen3.8-Flash-Next-GGUF]` and no census key at all, and `--pr-body our-org/unpinned --from sweep.json` answered "did not move" — the one word that would send a reader looking at the wrong thing, and (with `|| true` removed by #1181) the shape of failure that opens an empty-bodied PR. Now: the JSON carries `published_not_pinned` and both `--pr-body` paths (`--from`, and the in-memory one after a `--check --orgs`) refuse a census row in one wording — "published but not pinned … needs `--pin`, not a bump PR". A sweep written before this commit has no such key and can still only say "did not move"; that is why the writer is fixed in the same change. `--self-test` 51 -> 56: the sweep runs with both flags and exits 1; the JSON holds both halves; a census row is refused in those words; and a pin that *did* move still prints its body from the same file (so the fix cannot have been "refuse everything"). `tests/workflow_shell_test.py` still passes. This commit belongs to whichever of #1181/#1193 lands *second*: it is the only change that is about the two of them meeting. Rebased onto current main either way the union tree is identical.
43428e0 to
50371ee
Compare
|
#1193 ready for review at 50371ee — rebased onto What the rebase did. #1181 landed first, so this branch is now The new commit ( So the JSON gains Re-derived at this head, just now:
Lane state: |
|
Two lines in this PR's own files state exit codes the tool does not return — measured on your head 1. That is 2. The exit paragraph says "1 a pin moved (or So the real branches are: 0 nothing moved / the requested output printed; 1 a pin moved (a 3. Suggested wording (yours to take or leave, ~6 lines): - repo. A repo that did not move is a usage error (3), not a body.
+ repo. A repo that did not move exits 1 with that message: no body exists for it.
-Exit codes: 0 nothing moved, 1 a pin moved (or --check found nothing readable), 2 usage,
-3 --self-test failed, 4 --bump needs a human (the repo or a tracked file is gone upstream).
+Exit codes: 0 nothing moved (or the requested output was printed), 1 a pin moved or the requested
+--pr-body repo did not move, 2 usage or --check could read no pin at all, 3 --self-test failed,
+4 --bump needs a human (the repo or a tracked file is gone upstream).and in If you would rather not carry it, say so and I will open it as its own PR against |
|
Known-answer probe on real Hub data, because the census has so far only ever printed an empty result in production (nothing new was published today) and a feature that has only been tested against its own fixture is a feature I cannot vouch for. Method, no writes to the tree: copy
And the before/after on the same sweep file, which is what the union commit in this PR is for: Same input, same exit code — different sentence, and the first one sends a reader to the wrong question. (Also worth noting for #1181's side of it: the production run 42139845712 that merged it opened #1215 for the unsloth re-quant, so the bump step that never parsed now works; that PR is the owner's to take.) |
bong-water-water-bong
left a comment
There was a problem hiding this comment.
VERDICT: READY at 50371ee7 (re-verdict: #1181's merged content is now in this branch, so the file is the two changes together).
What I re-derived at this head rather than assuming a clean rebase:
--self-test: 56oklines, no failures (45 at the head I verdicted; the 11 new ones are #1181's: the--jsonsweep,--from, exit 4 for a vanished file, the 401/403 note).- The tool's own gate, live, with a token:
--check --orgs 1bit-MONSTER,bong-water-water-bong-># Model pins: 1 of 148 moved (2026-11-05), no "published but not pinned" row, the 1 moved being unsloth's re-quant. Same answer as before the rebase. - The census half is intact and unmoved:
SHIPPED/shipped()/census()are the same code,models/pins.jsonis byte-identical (7e4f1829…) to the head I verdicted,docs/model-pins.mdkeeps its "The repos we publish" section, and the workflow runs both halves in one step (--check --orgs … --out pin-report.md --json pin-report.json) with thenot checked|not pinnedannotation still on line 71 — i.e. the two PRs' overlapping hunk resolved as one call rather than one of them dropped.
The three nits from my first verdict are unchanged and still non-blocking: the first line's checked = total - len(notes) subtracts census notes from the pin count (an unreadable org reports 147 of 148 checked when the pins were fine), the org listing is one limit=1000 call with no pagination, and a "published, not pinned" hit only annotates the run. #1181's rewrite already fixed the one that mattered for the merge gate (the bump step's shell and exit-code path).
PR Reviewer Guide 🔍Here are some key observations to aid the review process:
|
`--pr-body` for a repo that did not move ends in `sys.exit("… did not move …")`, i.e. a string, so
Python exits **1** — the header called it "a usage error (3)", and 3 is `--self-test` failing. The
header's exit paragraph also folded "--check found nothing readable" into 1 where the tool returns 2
(`main()` ends with `return 2` when every pin lands in `notes`, and the self-test asserts it), while
docs/model-pins.md said "There are three outcomes" and stopped at 2, leaving 3 and 4 — both of which
CI and the workflow branch on — undocumented.
Measured on main `1dfe2708` before the change, against the reviewer's own repro:
$ printf '{"changes":[],"notes":[],"pins":1,"published_not_pinned":[]}' > sweep.json
$ python3 tools/pin_watch.py --pr-body fake/moved --from sweep.json # -> 1
$ python3 tools/pin_watch.py # -> 2
The docs table was {0,1,2} against a header listing {0,1,2,3,4}, so the pair disagreed on the same
five codes; now both list all five, with 0 widened to "or the requested output was printed", 1 to
"or the requested --pr-body repo did not move", 2 to "usage or no pin could be read at all".
The check that keeps them together: `--self-test` now compares the header's list with the table's rows
(it fails on main's pair, verified against `git show origin/main:…`), and runs the tool in a
subprocess so the did-not-move code is asserted at the **process** level (1), not through the test's
own `SystemExit` mapping — which is why the old assertions could not have caught it. Self-test
**56 -> 60**, `tests/workflow_shell_test.py` all checks passed.
Reported by lane pi-docs in #1193's review thread; that PR merged with this loose end (it is #1181's
line, on files #1193 last owned). Reported, not filed: no issue number.
Co-authored-by: bong-water-water-bong <bong-water-water-bong@1bit.gg>
…ported, not a bump PR (#1321) `--check` called a pin "moved" when the repo's `main` moved *or* a tracked file's bytes did, so a vendor editing its README minted a bump PR. Measured on today's pins (`1 of 148 moved`): unsloth/Qwen3.8-Flash-Next-GGUF d9620119 -> 084c631a commits: "Update README.md" x3 (2026-11-07) 40 new .gguf upstream, none of them tracked by the pin all five pinned files: same lfs.oid and `unsloth/Qwen3.8-Flash-Next-GGUF` had already produced #1215 and #1257 that way. A daily PR a human has to approve is a queue item; approving pin PRs reflexively is how a `TEMPLATE CHANGED` row gets waved through, which is the one thing this watch exists for. The pin already records the **bytes** of every file (`lfs.oid` + size) independently of the commit, so a HEAD-only move changes nothing we hold. Such a repo is now `head_only`: - reported in its own section, **Head moved, no tracked file changed**, with the commit titles and the new untracked `.gguf`/`.q4nx` files — so "they re-quantised" and "they only edited the README" both stay visible; - counted in the first line apart from the moves: `0 of 148 moved, 1 head moved without a file change`; - carried in the JSON (`head_moved_no_file_change`, and `head_only: true` on the row); - exits **0** and opens **no PR**; - `--pr-body` refuses it in one wording, like the census rows: *"moved its HEAD but no file we track changed, so there is nothing to adopt and no bump PR to open"*. Measured before/after on the real pins, same minute: main: # Model pins: 1 of 148 moved -> exit 1, the workflow opens a PR branch: # Model pins: 0 of 148 moved, 1 head moved without a file change -> exit 0, bump step skipped A byte change is still a real bump, and a `404` is still a finding — both asserted in the same self-test run as the head-only case, so the fix cannot be "ignore head moves". Self-test **60 -> 75** (`ok`, 0 FAIL), `tests/workflow_shell_test.py` all pass (the new section is a `## H` heading, not `## \`repo\``, so the workflow's `moved=` count cannot pick it up), `copyright.py --check` clean. docs/model-pins.md: the exit-1 row says **bytes**, and "The daily check" explains the split with the measurement above. Follow-up to #1193/#1181 (the watch they built) — reported, not filed. Co-authored-by: bong-water-water-bong <bong-water-water-bong@1bit.gg>
Root cause
tools/pin_watch.py --checkiterates over pins. A repo that was never pinned is therefore watched by nobody — including a repo we publish ourselves. That is why the 2026-11-05 template audit had to be done by hand (~/tmplsec/AUDIT-1.md), and it means a model published tomorrow would sit in our orgs with no daily check of its bytes or its chat template, which is the whole subject of this lane.Measured on the committed pins (19:3x AST), 167 repos in the two orgs, 92 not in
models/pins.json:.1bppacks (the 1BP lane's format)ZAYA1-8B-QLoRA,ZAYA1-8B-Q4NX)models/pins.jsonis public, anddocs/model-pins.mdsays a private model is tracked in the lane that owns itbong-water-water-bong/ZR1-1.5B-Strixchat_template.jinja(root + two checkpoints), measuredb6835114…The change
--check --orgs A,B: one listing per org (full=truecarries the siblings, so this is 2 API calls, not 167), reporting every unpinned repo that ships a.gguf/.q4nx/chat_template.jinja/tokenizer_config.jsonunder Published, not pinned — counted in the report's first line and annotated on the run, since such a repo changes no pin and would otherwise open no PR and fail nothing.--pinselects those files, not.ggufalone: a container or LoRA repo has no.gguf, so before this it could not be pinned at all.models/pins.json: that one repo pinned (64f092fe, 6 files). The threechat_template.jinjaareb6835114b7303ddd…, the digest the audit measured and the ZR1 GGUF arms carry; the threetokenizer_config.jsonhave nochat_templatekey (459 B each), sonullis the recorded truth, not a failed read.--orgs 1bit-MONSTER,bong-water-water-bong, so the coverage maintains itself instead of decaying into another by-hand audit.Verification
--self-testgained the cases that would have made this silent: a published repo that ships a template is reported, an.1bp-only repo is not, a private repo stays out, an already-pinned repo is not reported twice, an org that cannot be listed is a note rather than a clean day, and--pinon a container repo pins the model plus both template files.tools/copyright.py --checkrc 0.Notes
--bumpexit code,--json/--fromand the 401 note; this PR adds the census. The workflow hunk is adjacent — the run annotation here coversnot checked|not pinned, so when the two meet, pin-watch: the bump step's shell parses (it never did), and an unread upstream fails it instead of passing as a clean day #1181'snot checkedline should be dropped in favour of this one. I will rebase whichever lands second.401, see pin-watch: the bump step's shell parses (it never did), and an unread upstream fails it instead of passing as a clean day #1181) are not double-reported.