Repository navigation
Conversation
Bugbot is paused — on-demand spend limit reachedBugbot uses usage-based billing for this team and has hit its on-demand spend limit. A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue. |
|
Sentinel 已审核此变更,未发现已核验问题,但发现需要人工确认的风险。 另有 2 个需要人工确认的风险;黄色 advisory 不阻塞合并,建议开发 agent review advisory 评论并逐条确认。 开发 agent 查询详情: 调用 MCP 工具 由 Sentinel 审核 · 目标提交 67191f56d55b |
|
Sentinel 保留了 2 个尚未确认的审核候选。这些黄色条目不阻塞合并;红色 P0/P1 与其他独立硬门禁不受影响。 单一猜测、缺少变更行证据或纯 checklist 的候选会统一降为 P3。
需要完整证据时,可用行末 由 Sentinel 审核 · 目标提交 67191f56d55b |
forrestlinfeng
left a comment
There was a problem hiding this comment.
Code review — changes requested (simplify after #26)
The race is real and the recheck via isCurrentCandidate has no false-positive risk of its own. The fix is over-built, though.
Major — design/proportion: ~25 lines of compensation logic sit inside post() (lib/app/distill-session.js:30-54), which now POSTs, saves and compensates, with nested closures and a displaced variable set from inside the update callback. Most of it exists to restore drafts evicted by the 20-draft cap, which #26 removes — so this becomes dead code. Restoring a same-id predecessor assumes the Hub reuses a distill_id for a different candidate, which looks speculative. Per docs/architecture.md, pure list rules belong in lib/distill/, not lib/app/.
Suggested: land #26 first, then reduce this to "recheck → if not current, remove this candidate's draft", extracted as one pure helper.
Minor
withoutDraft(drafts, null, now)is used as a prune-expired call (:38,:44-45) — an odd use of remove-by-id, and a no-op after #26.return [...restore, ...kept](:51) puts restored drafts first, renumbering the list;publish/discard <n>act on list numbers, so a user can act on the wrong draft.- A correction landing after the second check still leaves the draft (acknowledged) — this narrows the window rather than closing it.
- The ~100 lines of tests mostly support the restore logic and would shrink with the simplification.
|
Sentinel 已审核此变更,未发现已核验问题,但发现需要人工确认的风险。 另有 1 个需要人工确认的风险;黄色 advisory 不阻塞合并,建议开发 agent review advisory 评论并逐条确认。 开发 agent 查询详情: 调用 MCP 工具 由 Sentinel 审核 · 目标提交 035418794ad5 |
|
Sentinel 保留了 1 个尚未确认的审核候选。这些黄色条目不阻塞合并;红色 P0/P1 与其他独立硬门禁不受影响。 单一猜测、缺少变更行证据或纯 checklist 的候选会统一降为 P3。
需要完整证据时,可用行末 由 Sentinel 审核 · 目标提交 035418794ad5 |
forrestlinfeng
left a comment
There was a problem hiding this comment.
Round 2 — one simplification before merge
#26 is merged now, so this can rebase onto main. Fixed since round 1: draft order is preserved (withDraft replaces in place, flatMap restores in place), and the withoutDraft(null) prune is gone. 37/37 touched tests pass.
Before merge
- Drop the same-id restore (
lib/app/distill-session.js:34-38,lib/distill.js:151-158). Restoringpreviousassumes the Hub reuses adistill_idfor a different candidate; nothing in lib or docs shows that, and it can bring back a draft an earlier correction should have removed (the bot flagged this too). The rule we need is just "after the recheck, if the candidate is no longer current, remove the draft stamped with this candidate". If there is Hub evidence for id reuse, please link it instead. - Normalise the draft list once.
distill-session.js:36anddistill.js:157callfind/some/flatMapwithout theArray.isArrayguard every other draft helper uses; a non-array drafts file throws inside the lock.
With (1), post() no longer needs previous assigned from inside the update callback or the outcome.draft mutation — please move the draft write + recheck into one helper so post() is back to a sequence of single-purpose calls. The ~105 lines of tests should shrink accordingly.
Nit: withDraft now keeps position on replacement, but test/distill.test.js has no unit assertion for it.
|
Sentinel 已审核此变更,未发现已核验问题,但发现需要人工确认的风险。 另有 2 个需要人工确认的风险;黄色 advisory 不阻塞合并,建议开发 agent review advisory 评论并逐条确认。 开发 agent 查询详情: 调用 MCP 工具 由 Sentinel 审核 · 目标提交 ebc68e1c7fc4 |
|
Sentinel 保留了 2 个尚未确认的审核候选。这些黄色条目不阻塞合并;红色 P0/P1 与其他独立硬门禁不受影响。 单一猜测、缺少变更行证据或纯 checklist 的候选会统一降为 P3。
需要完整证据时,可用行末 由 Sentinel 审核 · 目标提交 ebc68e1c7fc4 |
|
Sentinel 已审核此变更,未发现已核验问题,但发现需要人工确认的风险。 另有 1 个需要人工确认的风险;黄色 advisory 不阻塞合并,建议开发 agent review advisory 评论并逐条确认。 开发 agent 查询详情: 调用 MCP 工具 由 Sentinel 审核 · 目标提交 60a6b2b90871 |
|
Sentinel 保留了 1 个尚未确认的审核候选。这些黄色条目不阻塞合并;红色 P0/P1 与其他独立硬门禁不受影响。 单一猜测、缺少变更行证据或纯 checklist 的候选会统一降为 P3。
需要完整证据时,可用行末 由 Sentinel 审核 · 目标提交 60a6b2b90871 |
|
Sentinel 已审核此变更,并发现 1 个已核验问题。 另有 2 个需要人工确认的风险;黄色 advisory 不阻塞合并,建议开发 agent review advisory 评论并逐条确认。 开发 agent 查询详情: 调用 MCP 工具 由 Sentinel 审核 · 目标提交 5167732b8088 |
|
Sentinel 保留了 2 个尚未确认的审核候选。这些黄色条目不阻塞合并;红色 P0/P1 与其他独立硬门禁不受影响。 单一猜测、缺少变更行证据或纯 checklist 的候选会统一降为 P3。
需要完整证据时,可用行末 由 Sentinel 审核 · 目标提交 5167732b8088 |
| async function post(ports, { sessionId, candidate }, args, usage, signal) { | ||
| const body = distillBody({ platform: ports.identity.agent, sessionId: taskSessionId(ports.identity, sessionId), candidate, args, usage }); | ||
| const result = await ports.proxy.request('POST', '/conversation/distill', body, { timeoutMs: DISTILL_TIMEOUT_MS, signal }); | ||
| if (!isCurrentCandidate(await ports.candidates.read(), sessionId, candidate)) return { status: 'dropped' }; |
There was a problem hiding this comment.
候选失效会掩盖已成功的远端写入
🟠 严重程度:中(P2)
ports.proxy.request('POST', '/conversation/distill', ...) 已经完成后,新增检查会在解析响应前直接返回 {status: 'dropped'}。因此,即使 Proxy 返回可映射为 stored 的成功结果,调用方也会收到 dropped;而 distillText 又把它描述为 “nothing was sent”。远端 POST 实际已经发送并可能完成持久化,返回状态与已发生的副作用不一致。
Finding:finding_3bafd60f05ebb9f7133d1272
Bugbot is paused — on-demand spend limit reachedBugbot uses usage-based billing for this team and has hit its on-demand spend limit. A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue. |
|
Sentinel 已审核此变更,未发现已核验问题,但发现需要人工确认的风险。 另有 2 个需要人工确认的风险;黄色 advisory 不阻塞合并,建议开发 agent review advisory 评论并逐条确认。 开发 agent 查询详情: 调用 MCP 工具 由 Sentinel 审核 · 目标提交 58f0c14d6f7c |
|
Sentinel 保留了 2 个尚未确认的审核候选。这些黄色条目不阻塞合并;红色 P0/P1 与其他独立硬门禁不受影响。 单一猜测、缺少变更行证据或纯 checklist 的候选会统一降为 P3。
需要完整证据时,可用行末 由 Sentinel 审核 · 目标提交 58f0c14d6f7c |
|
Sentinel 已审核此变更,并发现 2 个已核验问题。 无法定位到 diff 的已核验问题
|
|
Sentinel 保留了 3 个尚未确认的审核候选。这些黄色条目不阻塞合并;红色 P0/P1 与其他独立硬门禁不受影响。 单一猜测、缺少变更行证据或纯 checklist 的候选会统一降为 P3。
需要完整证据时,可用行末 由 Sentinel 审核 · 目标提交 d00d39a91268 |
|
Sentinel 正在审核此变更,尚未形成最终结论。 Sentinel 审核中
开发 agent 查询详情: 调用 MCP 工具 由 Sentinel 审核 · 目标提交 d4952d908b77 |
|
Sentinel 正在审核此变更,尚未形成最终结论。 Sentinel 审核中
开发 agent 查询详情: 调用 MCP 工具 由 Sentinel 审核 · 目标提交 d6f4cd2007ae |
|
Sentinel 正在审核此变更,尚未形成最终结论。 Sentinel 审核中
开发 agent 查询详情: 调用 MCP 工具 由 Sentinel 审核 · 目标提交 32a5c7c659a7 |
Bugbot is paused — on-demand spend limit reachedBugbot uses usage-based billing for this team and has hit its on-demand spend limit. A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue. |
|
Sentinel 已审核此变更,并发现 1 个已核验问题。 无法定位到 diff 的已核验问题声明仍接受数字
|
|
Sentinel 正在审核此变更,尚未形成最终结论。 Sentinel 审核中
开发 agent 查询详情: 调用 MCP 工具 由 Sentinel 审核 · 目标提交 f070a4918f1c |
|
Sentinel 已审核此变更,未发现已核验问题,但发现需要人工确认的风险。 另有 2 个需要人工确认的风险;黄色 advisory 不阻塞合并,建议开发 agent review advisory 评论并逐条确认。 开发 agent 查询详情: 调用 MCP 工具 由 Sentinel 审核 · 目标提交 792e4cbac755 |
|
Sentinel 保留了 2 个尚未确认的审核候选。这些黄色条目不阻塞合并;红色 P0/P1 与其他独立硬门禁不受影响。 单一猜测、缺少变更行证据或纯 checklist 的候选会统一降为 P3。
需要完整证据时,可用行末 由 Sentinel 审核 · 目标提交 792e4cbac755 |
|
Sentinel 已审核此变更,未发现已核验问题,但发现需要人工确认的风险。 另有 9 个需要人工确认的风险;黄色 advisory 不阻塞合并,建议开发 agent review advisory 评论并逐条确认。 审核覆盖提示: 开发 agent 查询详情: 调用 MCP 工具 由 Sentinel 审核 · 目标提交 0d59f0263e63 |
|
Sentinel 保留了 9 个尚未确认的审核候选。这些黄色条目不阻塞合并;红色 P0/P1 与其他独立硬门禁不受影响。 单一猜测、缺少变更行证据或纯 checklist 的候选会统一降为 P3。
需要完整证据时,可用行末 由 Sentinel 审核 · 目标提交 0d59f0263e63 |
Summary
A correction can remove the candidate while /conversation/distill is in flight, after the existing pre-request check. Its late reply is currently saved as a valid draft.
Recheck after the response and after persistence. Local candidate provenance distinguishes a corrected draft from a same-id newer turn or another session. Restore live records displaced by the invalidated insertion without rolling back concurrent records or resurrecting a discarded same-id draft.
Evidence
Merge Danger
Door: two-way
Adds optional local sourceCandidate metadata; existing drafts remain readable. Engine assets and publication authorization are unchanged.
Blast Radius: persistence
Compensation protects final local state. It cannot undo a Proxy request already accepted or guarantee a draft is never briefly visible while a write and correction cross. Restoring unrelated displaced records can exceed the old capacity cap to prevent a second data loss.