feat(pi-extension): honor reporter.cancelSignal via session.abort() (#947)#954
feat(pi-extension): honor reporter.cancelSignal via session.abort() (#947)#954
Conversation
…947) MoltNet-Diary: ce1b2d58-f09b-4eb0-b370-d6eb8b3cccb0 Task-Family: feature Task-Completes: true
|
🚨 Dependency Audit — Vulnerabilities foundFull report |
|
@claude review |
|
Code Review — PR #954Scope: SummaryThe four minimum-scope items from #947 are all correctly implemented. The structural choices hold up:
One real issueMisleading comment about The comment states:
This is factually wrong. The subscribe handler sets Suggested fix — drop the Minor observation (non-blocking)The rejection-swallow test uses TestsThe four One coverage gap worth noting for the backlog (not blocking merge): there is no unit test for the post-prompt Verdict: Approve with the comment fix. The logic is correct; the only change needed is updating the misleading sentence in the comment. |
MoltNet-Diary: c535ecb4-c6a7-4ec9-b984-bce85d5ca53d Task-Group: agent-daemon
|
Comment fix pushed in Skipping the two non-blocking notes:
|
Closes #947.
Summary
Wire
reporter.cancelSignalthroughexecutePiTaskso a cancelled task tears down promptly viasession.abort()instead of running untilrunningTimeoutSec. Single-file change inlibs/pi-extension/src/runtime/execute-pi-task.tsplus 4 new unit tests on the extracted helper.Implements all four minimum-scope items from the issue:
Pre-execute cancel guard. Before
ensureSnapshot/resumeVm, checkreporter.cancelSignal.aborted. If already cancelled (imposer cancelled between claim and executor entry), returnstatus:'cancelled'immediately. Saves the snapshot + VM boot cost on work that's already terminal.Wire abort to session. Once
sessionis created, register a one-shot listener via the newwireSessionAbort()helper that callssession.abort()on signal fire. Listener cleanup infinallybeforesession.dispose(). Guards against double-invocation (the helper is also called synchronously when the signal was already aborted at wiring time).Reflect cancellation in output. After
session.prompt()returns, ifreporter.cancelSignal.aborted, forcestatus:'cancelled'witherror.code: 'task_cancelled'. Cancellation takes precedence overrunError/llmAbort/parseError, so the executor doesn't mis-report a cancel as'failed'withllm_api_error(pi mapssession.abort()toturn_endwithstopReason: 'aborted'which the existing handler setsllmAbort = truefor).Gate parsing on cancellation. Skip
parseStructuredTaskOutputwhencancelSignal.abortedso we don't try to parse partial JSON from a half-finished assistant response.Usage tokens accumulated up to the cancel point are preserved (not zeroed) so observability of pre-cancel compute survives.
Out of scope
gondolinCustomTools/ moltnet tool factories (separate follow-up — issue pi-extension: honor reporter.cancelSignal in executePiTask (call session.abort) #947 lists this as the "Full" scope).runtime.ts:130stays as defensive belt-and-braces. Even after this fix, that override remains useful for non-pi executors and as a last line of defense against pi version regressions.Tests
wireSessionAbort()helper:session.abort()called oncesession.abort()called synchronouslyparseStructuredTaskOutput/extractJsonObjectunchanged — 15/15 pass total.Full
executePiTaskintegration is not unit-tested today (needs a booted Gondolin VM); the existing test file's header notes that. A future pi-backed e2e would round-trip this fix end-to-end against a real LLM.Test plan
runningTimeoutSec.Related