You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
patrol: H4/H14/blocking-index read comment-level Blocked-by lines when the body carries none — the #8941 gauge fix #10061
{
"issue": 10061,
"status": "done",
"branch": "claude/issue-10061-comment-level-blockedby",
"pr": "https://github.com/objectstack-ai/objectstack/pull/10075",
"premise_still_valid": true,
"summary": "H4, H14 (both directions) and buildBlockingIndex now read comment-level `Blocked-by:` lines. H4 judges both channels and either discharges the duty; buildBlockingIndex takes options.comments and UNIONs comment-borne refs with body ones (cross-repo/self-ref filtering unchanged, applied per-ref regardless of channel); H14's stale direction is judged against the full two-channel index. Fetches are gated by the exported needsBlockedByComments to body-clean pm:blocked / pm:blocking cards and share the existing commentCache, so a card costs one request across H2, H17 and this; total failure rethrows as transport via the shared h16DetailPassUnreadable, and a partial shortfall is stated by the summary line's third `read X of Y` pair. The two directions treat an incomplete index asymmetrically on purpose: stale (a claim about ABSENT evidence) is suspended when any gated fetch failed, while missing (a claim about evidence IN HAND) survives, since reading more sources can only add edges. DECLARED NARROWING: the seat-post read-closure cut-off (comments newer than the body's last edit) is NOT implemented -- REST carries no issue body-edit timestamp (GraphQL userContentEdits only; this file is REST-only by a standing operational note) and the one proxy in reach, updated_at, bumps when a comment is posted, so the cut-off would be false for every comment ever written and the fallback would read nothing while looking like it read. See open_questions.",
"tests": "All on final commit 7ab290652 (tree clean; gate union re-derived on that HEAD). `node scripts/pm/dispatch-gates.mjs` with NO args, exit 0 -- 'change set derived from git -- 1 path(s) vs merge base a8509eba8', 6 families, all run. Verdict lines, each printed by the gate itself (exit codes captured by redirecting BEFORE any pipe): `pnpm check:pm-half-states` -> 'check-half-states self-test: 469 cases pass.' (baseline 414 -> 469, +55); `pnpm check:partof-closing-keyword` -> 'check-partof-closing-keyword self-test: 28 cases pass.'; `pnpm check:cross-package-test-inputs` -> 'OK: 12 package(s) read outside themselves, all declared, and turbo.json hashes every declared glob.'; `pnpm check:nul-bytes` -> 'check-nul-bytes: OK (scanned 6367 text file(s) -- 6367 tracked, 0 untracked-not-ignored; skipped 5 binary; no raw ASCII control bytes).' plus a manual grep -naP control-byte scan of the edited file (no match). The two `node scripts/...` rows in the derived list invoke the same scripts as their pnpm twins. Live sweep `node scripts/pm/check-half-states.mjs` exits 3 = 'PREREQUISITE NOT MET -- the token in the environment is not a valid GitHub credential' (transport-blocked container, expected; exit 3 is the CLASSIFIED verdict, not the unclassified 2, so the sweep path still loads and classifies). REVERSE VERIFICATION -- no build step exists for this artifact: node executes the script source directly, nothing resolves through a package dist/, so there is no stale-artifact hazard on either leg; every leg was ablated from the COMMITTED state and restored with `git checkout <branch> -- <path>`, and the restore leg was re-verified (469 pass, zero ABLATION markers left, `git status` clean). Directions predicted in writing first, all three held: (A) index union reverted to body-only -> predicted red on union-dependent rows with the two 'reads STALE against a body-only index' pins staying green; observed exit 1, and a direct probe through the exported functions showed edges at #9465 = null with #9465 reporting the stale sentence -- the measured false stale reproduced; after restore, edges = [9709,9828] and the row is null/clean. (B) H4 ignores commentBodies -> predicted red on the H4 comment-channel rows only, 8 rows named in advance; observed '8 of 469 case(s) failed', exactly those 8. (C) stale suspension removed -> predicted exactly one row; observed '1 of 469 case(s) failed' -- 'H14-A: stale is SUSPENDED when the index is known incomplete'. Self-test additions cover body-line / comment-line / both (union) / neither / comments-unreadable, positive and negative per shape, the gathering-policy gate, and the #9465/#9968 measured false-stale shapes as regression pins built from the REAL comment bodies on #9709/#9828/#9969/#9652, each pinned in both directions.",
"labels_read_back": ["size/m", "skip-changeset"],
"open_questions": [
{
"question": "The card specifies the comment fallback reads comments NEWER than the body's last edit, per the seat-post read-closure rule. That rule's own justification is that both timestamps are platform-stamped hard readings -- but only one of them is. A comment's created_at is on every REST row; an issue's body-edit time is on no REST payload at all (issues carry created_at/updated_at only, body edit history lives behind GraphQL userContentEdits, the timeline endpoint does not record body edits), and this file is REST-only by a standing operational note. How should the cut-off be handled?",
"options": [
"A -- ship without the cut-off (what this PR does): read the gated candidate's first comment page in full, and document the omission plus its direction analysis at the predicates. Errs only toward MORE evidence, which can clear an H4 row or an H14 stale row but can never invent a card's silence. Residual cost is a genuinely obsolete comment edge, which requires the source card to still be open, still labelled and still body-clean -- a state in which that source card is itself mis-stated.",
"B -- implement the cut-off against issue.updated_at. Rejected: updated_at bumps when a comment is POSTED, so 'newer than the body's last edit' is false for every comment ever written; the fallback would read nothing while reporting that it read. An unfalsifiable check is worse than an absent one and is the shape this file exists to catch.",
"C -- add a GraphQL read for lastEditedAt / userContentEdits. Buys the exact cut-off, and costs the file's REST-only operational note (the loop's hot path stays on the core quota) plus a second transport to classify in the prerequisite prober -- a real surface expansion for a boundary whose only measured benefit is suppressing obsolete edges nobody has observed.",
"D -- narrow the gate instead: fetch only comments whose created_at is newer than the card's created_at. Vacuous (always true) -- listed only to record that it was considered and is not a cut-off."
],
"recommendation": "A, shipped and declared. It is the only option that is both mechanizable under the file's stated constraints and directionally safe: the deviation can only clear false findings, which is precisely the #9948 recalibration this card implements, and it cannot manufacture one. C is the honest upgrade path if the maintainer decides the obsolete-edge case is worth a second transport -- worth a follow-up card only if such an edge is ever actually measured, since filing it now would be speculative surface. B is unsafe and should be recorded as rejected so nobody re-proposes it."
}
],
"out_of_scope_findings": []
}
Activity
os-warren commentedon Aug 19, 2026
Claim: session
ae0d8bd1-5667-5f58-8ff8-fa22ec154325· branchclaude/issue-10061-comment-level-blockedby串行解除:PR #10041(H17)已合并,
check-half-states.mjs空闲(自测基线 414,commentCache 机制已在树上)。折叠检查:队列无同文件第二卡 → 单卡。模型档:路径无强制(--tier 口径),report-only 量具修复 → opus。Generated by Claude Code
feat(pm): H4/H14/blocking-index read comment-level Blocked-by lines (#…
os-warren commentedon Aug 19, 2026
{ "issue": 10061, "status": "done", "branch": "claude/issue-10061-comment-level-blockedby", "pr": "https://github.com/objectstack-ai/objectstack/pull/10075", "premise_still_valid": true, "summary": "H4, H14 (both directions) and buildBlockingIndex now read comment-level `Blocked-by:` lines. H4 judges both channels and either discharges the duty; buildBlockingIndex takes options.comments and UNIONs comment-borne refs with body ones (cross-repo/self-ref filtering unchanged, applied per-ref regardless of channel); H14's stale direction is judged against the full two-channel index. Fetches are gated by the exported needsBlockedByComments to body-clean pm:blocked / pm:blocking cards and share the existing commentCache, so a card costs one request across H2, H17 and this; total failure rethrows as transport via the shared h16DetailPassUnreadable, and a partial shortfall is stated by the summary line's third `read X of Y` pair. The two directions treat an incomplete index asymmetrically on purpose: stale (a claim about ABSENT evidence) is suspended when any gated fetch failed, while missing (a claim about evidence IN HAND) survives, since reading more sources can only add edges. DECLARED NARROWING: the seat-post read-closure cut-off (comments newer than the body's last edit) is NOT implemented -- REST carries no issue body-edit timestamp (GraphQL userContentEdits only; this file is REST-only by a standing operational note) and the one proxy in reach, updated_at, bumps when a comment is posted, so the cut-off would be false for every comment ever written and the fallback would read nothing while looking like it read. See open_questions.", "tests": "All on final commit 7ab290652 (tree clean; gate union re-derived on that HEAD). `node scripts/pm/dispatch-gates.mjs` with NO args, exit 0 -- 'change set derived from git -- 1 path(s) vs merge base a8509eba8', 6 families, all run. Verdict lines, each printed by the gate itself (exit codes captured by redirecting BEFORE any pipe): `pnpm check:pm-half-states` -> 'check-half-states self-test: 469 cases pass.' (baseline 414 -> 469, +55); `pnpm check:partof-closing-keyword` -> 'check-partof-closing-keyword self-test: 28 cases pass.'; `pnpm check:cross-package-test-inputs` -> 'OK: 12 package(s) read outside themselves, all declared, and turbo.json hashes every declared glob.'; `pnpm check:nul-bytes` -> 'check-nul-bytes: OK (scanned 6367 text file(s) -- 6367 tracked, 0 untracked-not-ignored; skipped 5 binary; no raw ASCII control bytes).' plus a manual grep -naP control-byte scan of the edited file (no match). The two `node scripts/...` rows in the derived list invoke the same scripts as their pnpm twins. Live sweep `node scripts/pm/check-half-states.mjs` exits 3 = 'PREREQUISITE NOT MET -- the token in the environment is not a valid GitHub credential' (transport-blocked container, expected; exit 3 is the CLASSIFIED verdict, not the unclassified 2, so the sweep path still loads and classifies). REVERSE VERIFICATION -- no build step exists for this artifact: node executes the script source directly, nothing resolves through a package dist/, so there is no stale-artifact hazard on either leg; every leg was ablated from the COMMITTED state and restored with `git checkout <branch> -- <path>`, and the restore leg was re-verified (469 pass, zero ABLATION markers left, `git status` clean). Directions predicted in writing first, all three held: (A) index union reverted to body-only -> predicted red on union-dependent rows with the two 'reads STALE against a body-only index' pins staying green; observed exit 1, and a direct probe through the exported functions showed edges at #9465 = null with #9465 reporting the stale sentence -- the measured false stale reproduced; after restore, edges = [9709,9828] and the row is null/clean. (B) H4 ignores commentBodies -> predicted red on the H4 comment-channel rows only, 8 rows named in advance; observed '8 of 469 case(s) failed', exactly those 8. (C) stale suspension removed -> predicted exactly one row; observed '1 of 469 case(s) failed' -- 'H14-A: stale is SUSPENDED when the index is known incomplete'. Self-test additions cover body-line / comment-line / both (union) / neither / comments-unreadable, positive and negative per shape, the gathering-policy gate, and the #9465/#9968 measured false-stale shapes as regression pins built from the REAL comment bodies on #9709/#9828/#9969/#9652, each pinned in both directions.", "labels_read_back": ["size/m", "skip-changeset"], "open_questions": [ { "question": "The card specifies the comment fallback reads comments NEWER than the body's last edit, per the seat-post read-closure rule. That rule's own justification is that both timestamps are platform-stamped hard readings -- but only one of them is. A comment's created_at is on every REST row; an issue's body-edit time is on no REST payload at all (issues carry created_at/updated_at only, body edit history lives behind GraphQL userContentEdits, the timeline endpoint does not record body edits), and this file is REST-only by a standing operational note. How should the cut-off be handled?", "options": [ "A -- ship without the cut-off (what this PR does): read the gated candidate's first comment page in full, and document the omission plus its direction analysis at the predicates. Errs only toward MORE evidence, which can clear an H4 row or an H14 stale row but can never invent a card's silence. Residual cost is a genuinely obsolete comment edge, which requires the source card to still be open, still labelled and still body-clean -- a state in which that source card is itself mis-stated.", "B -- implement the cut-off against issue.updated_at. Rejected: updated_at bumps when a comment is POSTED, so 'newer than the body's last edit' is false for every comment ever written; the fallback would read nothing while reporting that it read. An unfalsifiable check is worse than an absent one and is the shape this file exists to catch.", "C -- add a GraphQL read for lastEditedAt / userContentEdits. Buys the exact cut-off, and costs the file's REST-only operational note (the loop's hot path stays on the core quota) plus a second transport to classify in the prerequisite prober -- a real surface expansion for a boundary whose only measured benefit is suppressing obsolete edges nobody has observed.", "D -- narrow the gate instead: fetch only comments whose created_at is newer than the card's created_at. Vacuous (always true) -- listed only to record that it was considered and is not a cut-off." ], "recommendation": "A, shipped and declared. It is the only option that is both mechanizable under the file's stated constraints and directionally safe: the deviation can only clear false findings, which is precisely the #9948 recalibration this card implements, and it cannot manufacture one. C is the honest upgrade path if the maintainer decides the obsolete-edge case is worth a second transport -- worth a follow-up card only if such an edge is ever actually measured, since filing it now would be speculative surface. B is unsafe and should be recorded as rejected so nobody re-proposes it." } ], "out_of_scope_findings": [] }Generated by Claude Code
os-warren commentedon Aug 19, 2026
ACCEPT — PR #10075 复核通过,已 flip ready + auto-merge(显式 SQUASH)。
复核记录(session
ae0d8bd1-5667-5f58-8ff8-fa22ec154325):undefined未询 /null不可读 /string[]已读)各配诚实句 —— 未询不冒领「评论为空」,不可读照报但注明第二通道未判(check:react-declaration-parity 是唯一没接进任何 workflow 的源码审计门禁,且无 MANIFEST 时静默 skip 退出 0 —— 它现在永远不可能红 #4690);presence 测试与 extractor 刻意分离的论证成立(Blocked-by: TBD尽义务但不产边)✓。impersonate_userandset_user_rolestill 403 every platform admin — neither route is safely raw-mountable, and each blocks for a different reason #9968 两个实测假 stale 以真实评论体做回归钉,双向(body-only 红 / 双通道清)✓。read X of Y在短缺时明说 stale 方向已悬置,静默板与拒判板不可混 ✓。needsBlockedByComments导出钉住,共享 commentCache,H2/H17/本项一卡一取;pm:blocking 卡在 unscoped 才可见 ⇒ 第二遍采集的摆位正确 ✓。updated_at代理会让 cut-off 对一切评论恒假 = 不可证伪的检查,B 正确拒绝并记录在案);无 cut-off 的误差方向只清假告警、不能捏造沉默 —— 恰是 request: run the pm:blocking derivation pass — cache measured at 0% coherence with the Blocked-by index (1 stale / 5 missing, 2026-08-19 census) #9948 重校要的方向。C(GraphQL)留作「若实测到过时边」的升级路径,现在不立卡 ✓。落地后:#8941 的本仓机械半闭环 —— 26/40 张评论停线的 blocked 卡从此对巡逻与解锁索引可见;cloud 回填半继续走 #9913 协调线。
Generated by Claude Code
os-warren commentedon Aug 20, 2026
冻结锚点移交记录(skills 座,session
ae0d8bd1-5667-5f58-8ff8-fa22ec154325):PR #10075 的冻结前提原挂在 #10071(registry.ts eslint 栈溢出 flake 根因卡),该卡已被 os-zhuang 关为 duplicate → 正主卡 #10030。截至本轮 #10030 仍开、pm:queue/domain:devx、无关联 PR、devx 队列无在班 PM —— 冻结维持,谓词不变,只换锚:#10030 有修复/止血落地 ⇒ 本卡 PR #10075 更新分支收割 → #10082 解锁。⛔ 期间不重触发 #10075 的 CI(停手线已在 #10071 第 5 击宣布)。flake 台账最新一击(第 6 击,PR #10038,run 32324337564)已记录并随 #10038 的 branch-update 重触发后合并收场。Generated by Claude Code
os-warren commentedon Aug 20, 2026
解冻:冻结条件已达成,PR #10075 全绿
skills 座(session
ae0d8bd1-5667-5f58-8ff8-fa22ec154325)。锚已落地:#10030(registry.ts eslint 栈溢出根因卡)已于 2026-08-20 07:09Z 关闭,修复 PR #10124 已合 —— 根
lint脚本改在node --stack-size=4000下运行 eslint。附带一条值得记的证伪:根因不是生成内容体积,而是step17.rationale里一条手写的 970 段+字符串拼接(AST 深度 976,全仓第二深仅 71),故原卡三个方向里有两个本来就修不好;永久修法另立卡。本卡收割:07:17Z 对 PR #10075 做 update-branch 收下该修复(新头
ae8b21705,⛔ 未用空 commit、未 force)。CI 全绿,逐项读回:Lint & Repo Gates ✅ success(即此前 6 击的那个必需门,现已稳定)· TypeScript Type Check ✅ · Test Core 1/3、2/3、3/3 全 ✅ · Dogfood Regression Gate ✅ · Live half-state sweep ✅ · 其余门全绿。冻结解除,停手线随之作废(该停手线是我在 flake 第 5 击时宣布的,目的是不再烧 CI —— 现在烧的理由消失了)。终态:非治理面 → 已 ready,auto-merge SQUASH 待挂(本轮撞 GitHub GraphQL 限流,已排入下一枪补挂;落地以
merged_at为准)。合并后 #10082 按其解锁条件解冻。顺带记一笔:同期堵塞 merge queue 的 #10115(冷启动 transform 吃光计时窗口)其修复 PR #10120 已于 06:44Z 合并,队列恢复正常;我先前在 #10112 对队列红的归因有误,已在该卡公开更正撤回。
Generated by Claude Code
feat(pm): H4/H14/blocking-index read comment-level Blocked-by lines (o…