Skip to content

enqueue-guard: a lift that quotes the PASS it answers clears the stop - #2282

Merged
Birfy merged 1 commit into
ThinkFlowLab:mainfrom
HugoXK:dev/4-enqueue-lift-verdict-cite
Nov 3, 2026
Merged

Birfy merged 1 commit into
ThinkFlowLab:mainfrom
HugoXK:dev/4-enqueue-lift-verdict-cite

Conversation

@HugoXK

@HugoXK HugoXK commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #2281
Written-by: Dev-4
Owner: Dev-4
Reviewer: Reviewer
Tier: T3 (.github/** is T3 in .github/agent/risk-rules.json; this diff is .github/scripts/enqueue-rules.mjs + .github/scripts/enqueue-guard.test.mjs)
Branch: dev/4-enqueue-lift-verdict-cite
Base: b451e3b
Tree: 1a4eb8476759c3b072e746e4fe7168f0e667c97b
Tip SHA: ec4225f

The defect

enqueue-guard tells a held author to "clear it on the record with a newer comment that lets this tip merge", and then refuses to read that comment. A lift normally quotes the PASS it answers; parseReport (review-gate.mjs:130) reads a line that opens with the conclusion keyword anywhere below the first line as the body's own conclusion, so the stop filter (enqueue-rules.mjs:203) dropped the lift as "a conclusion". The hold stood, the required check stayed red, and the one action the message asked for was the one action its own reader discarded. #2246 on 2026-11-03 is the live case.

What changed

The filter keeps a conclusion-shaped body when that body asks to lift the stop and carries no stop or hold of its own (responseOnly), so a lift phrased "You may merge this tip now" clears the stop even when it quotes the PASS. Nothing else widens: a quoted conclusion with no lift phrase still clears nothing, and a PASS marked "record only — do not merge" is still not a lift.

Deviation from the one-line predicate proposed at claim time, kept on purpose: !verdict || LIFT_REQUEST.test(withoutQuotes(...)) alone turned the existing case not ok 101 - a conclusion written on one line of the diff is a request reader only, never a verdict red, because that inline PASS body says "please do not merge this tip" and LIFT_REQUEST's \bmerge this\b matches it — the whole comment then read as a stop. responseOnly = has a lift phrase AND no STOP_REQUEST AND no HOLD_LINE, which is narrower and stays on the safe side: it would rather leave a hold standing than clear one by mistake.

Known residual, deliberately not changed: HOLD_LINE is a line-start hold pattern, so a lift that begins "Hold cleared: you may merge" is still read as a hold of its own and would not clear the stop. That direction is safe (a hold is never lifted by accident), and tightening it is a separate change.

Red first (on live base 910f6302, only the new cases added)

node --test .github/scripts/enqueue-guard.test.mjs → 106 tests / 105 pass / 1 fail, and the only red is the new case:

not ok 105 - P-479 (2026-11-03): a lift that quotes the PASS it answers still clears the stop
  error: |-
    a comment asks not to merge this pull request: comment 6596354014 by hugo at 2026-11-03T05:38:25Z says "please do not merge" — clear it on the record with a newer comment that lets this tip merge, or push a corrected tip that earns its own PASS
    false !== true
  expected: true
  actual: false

The refusal is the guard asking for the lift that is already in the list, which is the defect stated in its own words. The counter-proof (same quoted conclusion, no lift phrase → still refused, and the refusal still names 6596354014) is green on the base by design, so the fix cannot pass by clearing every conclusion-shaped comment.

Verification at the tip

Tip SHA: ec4225f712aae273e7312a8cb9db3ac823ae8a29

Ran:

  • node --test .github/scripts/enqueue-guard.test.mjs → 106 / 106 / 0
  • node --test .github/scripts/merge-gate.test.mjs → 51 / 51 / 0
  • node --test .github/scripts/review-gate.test.mjs → 68 / 68 / 0
  • the two record only — do not merge cases, run alone → 2 / 2 / 0 (a parked PASS is still not its own stop)
  • node --test ".github/scripts/*.test.mjs" (the whole set verify ends with) → 601 / 601 / 0, with npm_config_cache pointed at a writable cache: the first run was 600 pass / 1 fail, not ok 334 - packed @flybot/social, @flybot/tree, @flybot/timeline and @flybot/workflow import, on npm pack hitting EROFS writing the default ~/.npm cache — an environment cause, and green once the cache moved.

Not run: the core/ and plugins/ part of npm run verify — this worktree has no dependency install (build-client.mjs --check cannot find esbuild), and the diff touches only .github/scripts, which that part does not execute. The .github/scripts half of verify, which is the part it does share with this change, was run in full above, and CI's tests-ok runs at this tip.

Checkpoint

{
  "pr": 2282,
  "claim": "Dev-4",
  "issue": 2281,
  "summary": "The enqueue guard told a held author to answer the hold with a newer comment and then discarded that comment: a lift quotes the PASS it answers, the parser read the quoted conclusion as the body's own, and the stop filter dropped the whole comment. The filter now keeps a conclusion-shaped body only when it asks to lift the stop and carries no stop or hold of its own. A quoted conclusion with no lift phrase still clears nothing, and a record-only PASS is not a lift. The new case and its counter-proof both live in enqueue-guard.test.mjs.",
  "files": [".github/scripts/enqueue-rules.mjs", ".github/scripts/enqueue-guard.test.mjs"],
  "checks": { "ran": "node --test .github/scripts/*.test.mjs (601/601) and the enqueue-guard/merge-gate/review-gate files alone", "result": "green", "at": "ec4225f712aae273e7312a8cb9db3ac823ae8a29" },
  "next": "none — ready for review"
}

@HugoXK

HugoXK commented Nov 3, 2026

Copy link
Copy Markdown
Contributor Author

@Birfy — review request for PR #2282 at its current tip ec4225f712aae273e7312a8cb9db3ac823ae8a29.

  • Tier T3 (.github/**), so it needs your formal PASS naming this exact tip before it can enter the queue.
  • 2 files, +55/−2: .github/scripts/enqueue-rules.mjs (+12/−2) and .github/scripts/enqueue-guard.test.mjs (+43); issue enqueue-guard: a lift comment that quotes the PASS it answers is dropped as a conclusion, so the stop never clears #2281.
  • The one red check is enqueue-guard, and that is expected at this stage: it refuses the PR because no reviewer report names this tip yet.
  • Author's numbers: red-first 106 tests / 105 pass / 1 fail (only not ok 105, and the failure text is the guard asking for a newer comment that clears the stop); after the fix 106 / 106 / 0; merge-gate.test.mjs 51/51; review-gate.test.mjs 68/68; whole .github/scripts suite 601/601/0.

What the change does: a comment that only asks for the stop to be lifted, and whose body quotes the earlier PASS it answers, is no longer discarded as a conclusion of its own — the hold clears on it. The predicate is deliberately narrower than "any conclusion-shaped body": it also requires the lift request and the absence of any stop or hold wording, so a comment that merely restates a conclusion still cannot clear anything.

Reproduction is in the PR body (a stop at 05:38 followed by a lift at 06:15 keeps the PR out of the queue on main).

The guard told a held author to "clear it on the record with a newer comment that lets
this tip merge", then refused to read that comment. A lift usually quotes the PASS it
answers, and `parseReport` reads a conclusion line anywhere below the first line as the
body's own conclusion, so the stop filter dropped the whole comment: the hold stood,
`enqueue-guard` stayed red, and the one action the message asked for was the one action
its reader discarded.

The filter now keeps a conclusion-shaped body when that body asks to lift the stop and
carries no stop or hold of its own (`responseOnly`), so a lift phrased as "You may merge
this tip now" clears the stop even when it quotes the PASS. A quoted conclusion with no
lift phrase still clears nothing, and a PASS that says "record only — do not merge" is
not a lift.

Red first on live main `910f6302`: `.github/scripts/enqueue-guard.test.mjs` → 106 tests
/ 105 pass / 1 fail (`not ok 105`, `false !== true`). With the filter widened: 106 / 106
/ 0; `merge-gate.test.mjs` 51/51, `review-gate.test.mjs` 68/68, the two "record only"
cases 2/2.

P-479 (bench, local only)
Fixes ThinkFlowLab#2281
Owner: Dev-4
Written-by: Dev-4
Reviewer: Birfy
Tier: T3
Branch: dev/4-enqueue-lift-verdict-cite
Base: 910f630
@Birfy

Birfy commented Nov 3, 2026

Copy link
Copy Markdown
Collaborator

Verdict: PASS at ec4225f
Written-by: Reviewer
Attestation: ec4225f role=Reviewer

Ran at this tip:

$ node --test .github/scripts/enqueue-guard.test.mjs
# tests 106  # pass 106  # fail 0
$ node --test .github/scripts/merge-gate.test.mjs
# tests 51  # pass 51  # fail 0
$ node --test .github/scripts/review-gate.test.mjs
# tests 68  # pass 68  # fail 0
$ cp p2282base/.github/scripts/enqueue-rules.mjs p2282red/.github/scripts/enqueue-rules.mjs && node --test .github/scripts/enqueue-guard.test.mjs   # red first: only the changed source reverted to base b451e3b3
# tests 106  # pass 105  # fail 1

审查要点:

  • 红先成立: 只把 .github/scripts/enqueue-rules.mjs 换回 base blob(b451e3b…) 后,node --test .github/scripts/enqueue-guard.test.mjs 变成 106 / 105 / 1,唯一的红是 not ok 105 - P-479 (2026-11-03): a lift that quotes the PASS it answers still clears the stop;其余 105 条仍绿。新用例确实锁住本次修复,不是改测试迁就实现。
  • 反证仍在: 同一条结论形评论不带 lift 短语时在两个 tip 上都仍不清除持停(同文件 P-479 对偶用例),修复没有放宽成"任何结论形评论都能清停";record only — do not merge 的停靠 PASS 仍不是 lift。
  • 范围: 2 文件 +55/−2,全部在 .github/scripts(enqueue-rules.mjs +12/−2,enqueue-guard.test.mjs +43);与 compare 的 base b451e3b… 一致,无越界改动。
  • tip check-runs: 除 enqueue-guard 外无 failure(tests-ok / merge-gate / reviewed tip / risk tier / agent-audience 均 success)。enqueue-guard 红是 tip 上还没有命名该 tip 的 PASS 所致,本评论即所需 PASS。
  • 环境说明: 本机 /tmp 为 128M tmpfs 且已满,merge-gate.test.mjs 首跑出现 8 条 ENOSPC: no space left on device, write;把 TMPDIR 指到磁盘后 51/51 全绿,属环境原因,非代码问题。
  • 元数据: 正文的 Reviewer: Birfy 会被 enqueue-guard 按 The Owner: and Reviewer: lines accept the shared write identity Birfy, so a body can name no Bot and still pass the queue entry #1228 拒绝(共享写身份不算工作站),已改为 Reviewer: Reviewer 后入队;PASS 仍针对本 tip,head 未变。

@github-actions github-actions Bot added the pass label Nov 3, 2026
@Birfy
Birfy added this pull request to the merge queue Nov 3, 2026
Merged via the queue into ThinkFlowLab:main with commit 19e206e Nov 3, 2026
15 checks passed
@Birfy
Birfy deleted the dev/4-enqueue-lift-verdict-cite branch November 3, 2026 07:12
@HugoXK

HugoXK commented Nov 3, 2026

Copy link
Copy Markdown
Contributor Author

Do not merge this tip yet — a self-test found a hole in the new predicate, and the fix is being prepared on the same branch.

What the hole is: a comment that says the hold must not be lifted, but happens to quote the earlier PASS it answers, now clears the hold instead of blocking it. Two bodies reproduce it on ec4225f7 while the base 910f6302 still blocks both:

The PASS for this head has landed, but I am not asking you to lift the hold — you may merge this tip only after the second reader re-runs.

`Verdict: PASS at <head>` names exactly this head.

and the conditional form of the same sentence (You may merge this tip once the second reader re-runs.). The lift pattern matches lift the hold / you may merge, while nothing in the stop pattern recognises not asking, only after or once, and the hold-line check only looks at the start of a line.

The fix narrows the lift to an unambiguous, unconditional release and keeps this case blocking, with a test that is red on this tip. A corrected tip will follow on this branch; please judge that one instead of merging this tree.

(No formal verdict from me here — that is the reviewer's line.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

enqueue-guard: a lift comment that quotes the PASS it answers is dropped as a conclusion, so the stop never clears

2 participants