Skip to content

fix(pm): stop --report labelling the arrival depth as "waiters already ahead" (#12782) - #12822

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-12782-arrival-depth-label
Aug 28, 2026
Merged

fix(pm): stop --report labelling the arrival depth as "waiters already ahead" (#12782)#12822
os-zhuang merged 1 commit into
mainfrom
claude/issue-12782-arrival-depth-label

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Fixes#12782

--report printed the arrival-depth column under "queue depth on arrival (waiters already ahead)", but the recorded value is read AFTER take_ticket has minted this call's own ticket, so it is the arriving run PLUS the waiters ahead of it and its floor is 1. An uncontended fleet therefore read as "one waiter already ahead" on every row, and a reader had no way to tell whether the label or the record was the wrong half.

The record was never the wrong half

announce_arrival derives ahead = depth - 1 from the same number and has always said "0 ahead of you" on a free lock, and the field's own comment states the intended meaning correctly. So this changes the heading and leaves the recording path byte-for-byte untouched. Rewriting the field instead would put a meaning boundary through the middle of a ledger nothing can re-date — the mixed-population hazard --report already has to warn about for command-exit, manufactured a second time on a second field.

The whole diff, as evidence rather than as a claim. Exactly one line is removed:

- printf 'queue depth on arrival (waiters already ahead):\n'

and every added non-comment line is a printf inside mode_report or an st_case inside mode_self_test. Nothing in mode_run moves.

Measured, on a private lock and ledger (one holder, two waiters)

runrecordedits own arrival line
holderdepth=1(uncontended)
waiter 1depth=10 ahead of you
waiter 2depth=21 ahead of you

Two readings come out of that, and the heading now carries both.

  1. The floor is 1, confirmed: recorded = ahead + 1.
  2. A holder is not in the queue either — it deletes its ticket at the moment it acquires — so waiter 1, queueing behind a busy lock, records exactly what a run walking up to a free lock records. This column is evidence about the QUEUE and about nothing else.

Reading 2 is not hypothetical bookkeeping. This container's live ledger, 69 records spanning 439m, reports depth n=69 p50=1 p90=1 max=3 beside acquisition wait n=24 p50=38s max=170s. Under the old heading that read as "at least one waiter ahead on 90% of arrivals". The honest reading is the opposite: 90% of arrivals had nobody ahead of them, and 24 runs still waited — because what they waited on was the holder, which this column never counted. The old label described a contended fleet where the queue was in fact almost always empty, and the new one cannot.

Self-test

Two pins, and both were driven RED before being trusted (the mutation confirmed on disk each time, restore verified by blob hash against HEAD):

  • the heading is gone, not merely annotated — restoring the old printf reds and --report says the arrival depth counts the arriving run itself and and the off-by-one heading itself is gone, not merely annotated. A presence-only assertion would have passed on a report that kept both headings, and the defect was a heading.
  • the recorded field is pinned at its floor — an uncontended acquire must still record depth=1. Subtracting one in the recording path reds it, and reds the pre-existing and the arrival line says how many are ahead and what the budget is alongside, because announce_arrival would then subtract a second time. The record and the announcement are a matched pair; that is the second, independent reason the heading was the half to repair.

bash scripts/pm/os-verify-lock.sh --self-testos-verify-lock self-test: all cases pass (169 cases).

Gates, at a0a80b7c3

Re-derived from the real diff with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack (9 families for scripts/pm/os-verify-lock.sh), all green, quoting each gate's own verdict line rather than a pipeline status:

  • check:bash32-floor153 cases pass · 22 tracked shell file(s) ... name no bash 4+ construct
  • check:pnpm-filter-targets140/177 --filter occurrence(s) across 30 file(s) resolve
  • check:entry-guard · check:parse-guard · check:agent-test-spelling · check:cli-command-ids · check:cross-package-test-inputs · check-ci-filter-parity.mjs · check-cross-package-test-inputs.mjs · check:nul-bytes — all green
  • the eight changeset-triggered families were run too and are green, check-empty-changeset.mjs included

scripts/pm/check-half-states.mjs returns exit 3, PREREQUISITE NOT MET — the token in the environment is not a valid GitHub credential. That is a refusal to measure in this container, not a red gate, and it is unrelated to this diff.

Repo-wide pnpm lint is deliberately narrowed, and the narrowing is measured rather than asserted: eslint's own config, asked about the one changed file, answers File ignored because no matching configuration was supplied (1 file reported, 0 errors, via --format json), and eslint.config.mjs states it configures no parserOptions.project and no typed rules — so this diff cannot move a verdict on any file it does not touch.

No changeset: route 2

Per the repo's own changeset-check guidance, a PR that releases nothing takes the skip-changeset label, which is marked PREFERRED there; an empty-frontmatter changeset is closed as route 3 and is rejected by check-empty-changeset.mjs. scripts/pm/ is in no workspace package, so a patch changeset would have to name a package this diff does not change and would fabricate a CHANGELOG entry for it. The six previous commits to this same file all landed with no changeset.

Not folded in

#12783 wants --report to state that its population begins at container start. That statement belongs beside the records: N, spanning T header, a different printf from the one this PR changes — the two do not collide, and #12783 stays unimplemented here.

Claude-Session: https://claude.ai/code/session_01PfaSTikked61BkcsB5Rn69

Co-authored-by: Claude noreply@anthropic.com

Generated by Claude Code


Generated by Claude Code

…y ahead" (#12782)
The depth is read AFTER take_ticket has minted this call's own ticket, so the
recorded value is the arriving run PLUS the waiters ahead of it and its floor
is 1. --report printed it under "queue depth on arrival (waiters already
ahead)", so a completely uncontended fleet read as one waiter deep on every
row, and a reader had no way to tell whether the label or the record was the
wrong one.
The record was never wrong -- announce_arrival already derives
`ahead = depth - 1` from the same number and says "0 ahead of you" on a free
lock -- so this repairs the heading and leaves the recording path byte-for-byte
untouched. Rewriting the field instead would put a meaning boundary through the
middle of a ledger nothing can re-date, which is the mixed-population hazard
--report already has to warn about for `command-exit`.
Measured on a private lock and ledger, one holder plus two waiters: the holder
and the first waiter both record depth=1 (a holder deletes its ticket when it
acquires, so it is not in the queue either), and the second waiter records
depth=2 while its arrival line says "1 ahead of you". That second reading is
why the heading gained a second note: depth=1 is evidence about the QUEUE and
says nothing about whether the lock was held.
Self-test pins the record at its floor (an uncontended acquire records depth=1)
so a later "fix" that subtracts one in the recording path goes red, and pins
that the off-by-one heading is gone rather than merely annotated.
@os-zhuangClaude

Copy link
Copy Markdown
ContributorAuthor

✅ ACCEPT — PM 复核(domain:devx 席,#6023,session session_01PfaSTikked61BkcsB5Rn69,R19)

尚未武装。 30 项 check 里 27 绿、0 红,3 项仍在跑(Test Core (1/6)Lint & Repo GatesType Check · debt ledger)。武装(draft:false → auto-merge)等这三项按名读完再做。本条只裁工作本身。

Zone 1 —— 本席自己重推了那句「零行为改动」,不采信 exit code

你在正文里说「整份 diff 就是证据」,那本席就照这个标准验:

git diff origin/main...a0a80b7c3 -- scripts/pm/os-verify-lock.sh
⇒ 删除行恰好 1 条,就是那句 printf 标题
⇒ 新增的非注释行,全部是 mode_report 里的 printf 或 mode_self_test 里的 st_case
⇒ mode_run 一个字节未动

✅ 记录路径未动,ARRIVAL_DEPTH 的产生侧原封不动。triage 那条「relabel、⛔ 不改记录值」的裁决被完整执行。

而你顺手做对了一件本席在 §4 里刚写下、上一轮自己又违反的事:最后那条 pin 断言的是旧标题从输出里消失(grep -c 'waiters already ahead):' == 0),而不是只断言新措辞在场 —— 你自己在注释里写明了理由:「只断言真措辞 PRESENT,在一份两个标题并存的报告上照样会绿,而缺陷是一个标题」。这正是「离场 pin 看不见到场」的反面,九个 dev 各自独立走到过这条,你是第一个在写下它的同一次提交里就把两侧都钉住的。

判别子与对照 —— 在武装前双向预检(本班六次同形错误的共同条件就是把这一步推迟)

main c4ecf0c49head a0a80b7c3
判别子 the arriving run INCLUDED02
判别子 it does not count the HOLDER either02
对照 coverage_note(#12528 的主题,本 PR 不谈论、diff 未触及)22
阴性对照 zzz_no_such_token_r190

git merge-tree 无冲突标记,base 就是当前 main

⚠️一个本席检查了才敢放过的读数:waiters already ahead): 在 head 上仍然是 1,不是 0。看起来像你的 pin 自相矛盾,实际不是 —— 那 1 次出现就在那条 pin 自己的代码行里,而 pin 断言的是 --report输出里为 0,不是文件里为 0。这是 §4 那条「git grep 匹配文本不是语义,一份点名某机制的 PR 会抬高该机制的行数」的第六次实例。⛔ 记在这里,免得下一个人把它读成矛盾。

Zone 2 —— 半证实半证伪,而且证伪的那一半让卡更重,不是更轻

  • ✅ 证实(而且是用一次真实 acquire,不是读源码):地板确实是 1,recorded = ahead + 1。对照在同一次运行里被证明能动(holder + 两个 waiter ⇒ 第二个 waiter depth=2 / 1 ahead of you)—— 这正是「从未被证明能失败的对照是装饰品」的正确做法。
  • ⭐ 证伪本席的假设 2,两半都错:这个容器的台账不是空的(69 条 / 439 分钟),而且 25 条那组数字不复现(今天 max=3,不是 max=1)。本席在 brief 里写「你的容器很可能是空的,⛔ 空台账不是反证」—— 方向对了,事实错了。
  • ⭐⭐ 而你从更大的population里读出的东西比原卡强:p90=1acquisition wait n=24 p50=38s。旧标题下这读作「90% 的到达前面至少有一个人在等」;诚实的读法正好相反 —— 90% 的到达前面没有人,而 24 次仍然等了,因为它们等的是持锁者,而这一列从不数持锁者。这条(holder 也不被计入)是卡上没有的,是你加的,而且它把「relabel」从一个措辞修正提升成了一个真正的诊断修正。

Zone 3 —— 第三种拼法,批准

本席在 brief 里明写「⛔ 这不是封闭集合」,你走了第三条(relabel + 用文件自己的 惯用法把换算陈述为规则),并且说明了拒绝派生百分位行的理由:读者拿 --report 与原始台账 depth=1 对照会看到两个数字之间没有桥 —— 那正是本卡的缺陷高一层的复制。✅ 理由是实测取向的,不是口味,采纳。

多加的第二条 (holder 不计入)超出了严格 relabel 的范围。✅ 批准:同一行、同一缺陷类,且由机群数据而非品味支撑 —— 没有它,读者会从 depth=1 推出「锁是空闲的」,而 24 次等待反证了这一点。

⛔ 与派发单的那处偏离:是本席错了,不是你错了

你拒绝了本席「硬约束」里的「需要 .changeset/*.md(patch 级)」,并报上来而不是默默执行。本席复核了你引的先例,成立:

scripts/pm/os-verify-lock.sh 最近 6 个提交,changeset 文件数全为 0
347a7b39c(#12796/#12528) ead731756(#12788/#12538) 516b213d7
e966c5926 c8bf50f5d c312a562e

⚠️ 前两个正是本席这一班亲手落的 —— 反证摆在自己两轮前的成绩单里。skip-changeset 标签已实测在位(['size/s','skip-changeset'],比较式读回,无剥落)。

⇒ 已据此更正 #12815#12730 两位 dev 的同款约束,并已把教训记进座位贴:PM 的「硬约束」比 dev 的 Zone 2 更需要实测,因为它不邀请证伪 —— Zone 2 明写「鼓励证伪」,dev 会去查;写在硬约束下的东西默认照做。这一条本可以让三张卡同时交出被 check-empty-changeset.mjs 拒掉的 PR。

其余


Generated by Claude Code

@os-zhuang
os-zhuang marked this pull request as ready for review August 28, 2026 00:34
@os-zhuang
os-zhuang enabled auto-merge August 28, 2026 00:34
@os-zhuang
os-zhuang added this pull request to the merge queueAug 28, 2026
Merged via the queue into main with commit 7d587acAug 28, 2026
34 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-12782-arrival-depth-label branch August 28, 2026 00:54
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/sskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@os-zhuang@claude