Skip to content

feat(pi-extension): honor reporter.cancelSignal via session.abort() (#947)#954

Merged
getlarge merged 2 commits intomainfrom
fix/issue-947-pi-cancel
Apr 26, 2026
Merged

feat(pi-extension): honor reporter.cancelSignal via session.abort() (#947)#954
getlarge merged 2 commits intomainfrom
fix/issue-947-pi-cancel

Conversation

@legreffier
Copy link
Copy Markdown
Contributor

@legreffier legreffier Bot commented Apr 26, 2026

Closes #947.

Summary

Wire reporter.cancelSignal through executePiTask so a cancelled task tears down promptly via session.abort() instead of running until runningTimeoutSec. Single-file change in libs/pi-extension/src/runtime/execute-pi-task.ts plus 4 new unit tests on the extracted helper.

Implements all four minimum-scope items from the issue:

  1. Pre-execute cancel guard. Before ensureSnapshot / resumeVm, check reporter.cancelSignal.aborted. If already cancelled (imposer cancelled between claim and executor entry), return status:'cancelled' immediately. Saves the snapshot + VM boot cost on work that's already terminal.

  2. Wire abort to session. Once session is created, register a one-shot listener via the new wireSessionAbort() helper that calls session.abort() on signal fire. Listener cleanup in finally before session.dispose(). Guards against double-invocation (the helper is also called synchronously when the signal was already aborted at wiring time).

  3. Reflect cancellation in output. After session.prompt() returns, if reporter.cancelSignal.aborted, force status:'cancelled' with error.code: 'task_cancelled'. Cancellation takes precedence over runError / llmAbort / parseError, so the executor doesn't mis-report a cancel as 'failed' with llm_api_error (pi maps session.abort() to turn_end with stopReason: 'aborted' which the existing handler sets llmAbort = true for).

  4. Gate parsing on cancellation. Skip parseStructuredTaskOutput when cancelSignal.aborted so 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

  • Tool-level signal forwarding into 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 override at runtime.ts:130 stays 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

  • 4 new unit tests on the extracted wireSessionAbort() helper:
    • Fire after wiring → session.abort() called once
    • Fire before wiring (signal already aborted at call time) → session.abort() called synchronously
    • Double-invocation guard
    • Rejection swallow path (logged to stderr, doesn't escape the listener)
  • Existing 11 tests on parseStructuredTaskOutput / extractJsonObject unchanged — 15/15 pass total.
  • Full pi-extension test suite green (62/62).
  • Daemon e2e from feat(agent-daemon): new app + polling source + GET /tasks/schemas #944 still passes locally (4/4) — confirms the cancel contract integration didn't regress.

Full executePiTask integration 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

  • CI green (lint + typecheck + tests)
  • Daemon e2e in CI still passes (it doesn't touch pi but confirms the broader contract)
  • Manual verification once the daemon runs a real pi task: imposer-side cancel during a long curate_pack run should tear down the LLM session within seconds, not block until runningTimeoutSec.

Related

…947)

MoltNet-Diary: ce1b2d58-f09b-4eb0-b370-d6eb8b3cccb0
Task-Family: feature
Task-Completes: true
@github-actions
Copy link
Copy Markdown
Contributor

⚠️ CLI go.mod is behind internal Go module releases

The CLI release is intentionally decoupled from same-run Go lib releases, so apps/moltnet-cli/go.mod must already be bumped in a normal PR.

Detected drift:

  • moltnet-api-client: go.mod has v1.19.1, expected v1.21.0

Run these commands from apps/moltnet-cli:

GOWORK=off go get github.com/getlarge/themoltnet/libs/moltnet-api-client@v1.21.0
GOWORK=off go mod tidy

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 26, 2026

🚨 Dependency Audit — Vulnerabilities found

Full report
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ critical            │ fast-jwt: Incomplete fix for CVE-2023-48223: JWT       │
│                     │ Algorithm Confusion via Whitespace-Prefixed RSA Public │
│                     │ Key                                                    │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ fast-jwt                                               │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ <=6.1.0                                                │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=6.2.0                                                │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ apps__mcp-server>@getlarge/fastify-mcp>@fastify/       │
│                     │ jwt>fast-jwt                                           │
│                     │                                                        │
│                     │ libs__auth>fast-jwt                                    │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-mvf2-f6gm-w987      │
└─────────────────────┴────────────────────────────────────────────────────────┘
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ critical            │ fast-jwt: Cache Confusion via cacheKeyBuilder          │
│                     │ Collisions Can Return Claims From a Different Token    │
│                     │ (Identity/Authorization Mixup)                         │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ fast-jwt                                               │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ >=0.0.1 <6.2.0                                         │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=6.2.0                                                │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ apps__mcp-server>@getlarge/fastify-mcp>@fastify/       │
│                     │ jwt>fast-jwt                                           │
│                     │                                                        │
│                     │ libs__auth>fast-jwt                                    │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-rp9m-7r4c-75qg      │
└─────────────────────┴────────────────────────────────────────────────────────┘
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ critical            │ Arbitrary code execution in protobufjs                 │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ protobufjs                                             │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ <7.5.5                                                 │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=7.5.5                                                │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ apps__mcp-server>pino-opentelemetry-transport>otlp-    │
│                     │ logger>@opentelemetry/exporter-logs-otlp-grpc>@grpc/   │
│                     │ grpc-js>@grpc/proto-loader>protobufjs                  │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-xq3m-2v4x-88gg      │
└─────────────────────┴────────────────────────────────────────────────────────┘
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ critical            │ Arbitrary code execution in protobufjs                 │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ protobufjs                                             │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ >=8.0.0 <8.0.1                                         │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=8.0.1                                                │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ apps__agent-daemon>@opentelemetry/exporter-trace-otlp- │
│                     │ proto>@opentelemetry/otlp-transformer>protobufjs       │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-xq3m-2v4x-88gg      │
└─────────────────────┴────────────────────────────────────────────────────────┘
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ high                │ fast-jwt accepts unknown `crit` header extensions (RFC │
│                     │ 7515 violation)                                        │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ fast-jwt                                               │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ <=6.1.0                                                │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ <0.0.0                                                 │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ apps__mcp-server>@getlarge/fastify-mcp>@fastify/       │
│                     │ jwt>fast-jwt                                           │
│                     │                                                        │
│                     │ libs__auth>fast-jwt                                    │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-hm7r-c7qw-ghp6      │
└─────────────────────┴────────────────────────────────────────────────────────┘
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ high                │ Fastify has a Body Schema Validation Bypass via        │
│                     │ Leading Space in Content-Type Header                   │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ fastify                                                │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ >=5.3.2 <=5.8.4                                        │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=5.8.5                                                │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ apps__mcp-server>fastify                               │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-247c-9743-5963      │
└─────────────────────┴────────────────────────────────────────────────────────┘
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ moderate            │ Hono missing validation of cookie name on write path   │
│                     │ in setCookie()                                         │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ hono                                                   │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ <4.12.12                                               │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=4.12.12                                              │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ tools>@mariozechner/pi-ai>@google/                     │
│                     │ genai>@modelcontextprotocol/sdk>hono                   │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-26pp-8wgv-hjvm      │
└─────────────────────┴────────────────────────────────────────────────────────┘
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ moderate            │ Hono: Non-breaking space prefix bypass in cookie name  │
│                     │ handling in getCookie()                                │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ hono                                                   │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ <4.12.12                                               │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=4.12.12                                              │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ tools>@mariozechner/pi-ai>@google/                     │
│                     │ genai>@modelcontextprotocol/sdk>hono                   │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-r5rp-j6wh-rvv4      │
└─────────────────────┴────────────────────────────────────────────────────────┘
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ moderate            │ Hono: Path traversal in toSSG() allows writing files   │
│                     │ outside the output directory                           │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ hono                                                   │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ >=4.0.0 <=4.12.11                                      │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=4.12.12                                              │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ tools>@mariozechner/pi-ai>@google/                     │
│                     │ genai>@modelcontextprotocol/sdk>hono                   │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-xf4j-xp2r-rqqx      │
└─────────────────────┴────────────────────────────────────────────────────────┘
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ moderate            │ Hono: Middleware bypass via repeated slashes in        │
│                     │ serveStatic                                            │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ hono                                                   │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ <4.12.12                                               │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=4.12.12                                              │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ tools>@mariozechner/pi-ai>@google/                     │
│                     │ genai>@modelcontextprotocol/sdk>hono                   │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-wmmm-f939-6g9c      │
└─────────────────────┴────────────────────────────────────────────────────────┘
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ moderate            │ @hono/node-server: Middleware bypass via repeated      │
│                     │ slashes in serveStatic                                 │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ @hono/node-server                                      │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ <1.19.13                                               │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=1.19.13                                              │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ tools>@mariozechner/pi-ai>@google/                     │
│                     │ genai>@modelcontextprotocol/sdk>@hono/node-server      │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-92pp-h63x-v22m      │
└─────────────────────┴────────────────────────────────────────────────────────┘
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ moderate            │ fast-jwt has a ReDoS when using RegExp in allowed*     │
│                     │ leading to CPU exhaustion during token verification    │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ fast-jwt                                               │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ >=5.0.0 <=6.2.0                                        │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=6.2.1                                                │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ apps__mcp-server>@getlarge/fastify-mcp>@fastify/       │
│                     │ jwt>fast-jwt                                           │
│                     │                                                        │
│                     │ libs__auth>fast-jwt                                    │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-cjw9-ghj4-fwxf      │
└─────────────────────┴────────────────────────────────────────────────────────┘
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ moderate            │ fast-jwt: Stateful RegExp (/g or /y) causes            │
│                     │ non-deterministic allowed-claim validation (logical    │
│                     │ DoS)                                                   │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ fast-jwt                                               │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ <6.2.1                                                 │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=6.2.1                                                │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ apps__mcp-server>@getlarge/fastify-mcp>@fastify/       │
│                     │ jwt>fast-jwt                                           │
│                     │                                                        │
│                     │ libs__auth>fast-jwt                                    │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-3j8v-cgw4-2g6q      │
└─────────────────────┴────────────────────────────────────────────────────────┘
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ moderate            │ hono Improperly Handles JSX Attribute Names Allows     │
│                     │ HTML Injection in hono/jsx SSR                         │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ hono                                                   │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ <4.12.14                                               │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=4.12.14                                              │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ tools>@mariozechner/pi-ai>@google/                     │
│                     │ genai>@modelcontextprotocol/sdk>hono                   │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-458j-xx4x-4375      │
└─────────────────────┴────────────────────────────────────────────────────────┘
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ moderate            │ fast-xml-parser XMLBuilder: XML Comment and CDATA      │
│                     │ Injection via Unescaped Delimiters                     │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ fast-xml-parser                                        │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ <5.7.0                                                 │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=5.7.0                                                │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ tools>@mariozechner/pi-ai>@aws-sdk/client-bedrock-     │
│                     │ runtime>@aws-sdk/core>@aws-sdk/xml-builder>fast-xml-   │
│                     │ parser                                                 │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-gh4j-gqv2-49f6      │
└─────────────────────┴────────────────────────────────────────────────────────┘
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ moderate            │ uuid: Missing buffer bounds check in v3/v5/v6 when buf │
│                     │ is provided                                            │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ uuid                                                   │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ <14.0.0                                                │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=14.0.0                                               │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ apps__mcp-server>@getlarge/fastify-mcp>mqemitter-      │
│                     │ redis>hyperid>uuid                                     │
│                     │                                                        │
│                     │ tools>@mariozechner/pi-coding-agent>uuid               │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-w5hq-g745-h8pq      │
└─────────────────────┴────────────────────────────────────────────────────────┘
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ moderate            │ Hono has incorrect IP matching in ipRestriction() for  │
│                     │ IPv4-mapped IPv6 addresses                             │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ hono                                                   │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ <4.12.12                                               │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=4.12.12                                              │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ tools>@mariozechner/pi-ai>@google/                     │
│                     │ genai>@modelcontextprotocol/sdk>hono                   │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-xpcf-pg52-r92g      │
└─────────────────────┴────────────────────────────────────────────────────────┘
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ low                 │ Elliptic Uses a Cryptographic Primitive with a Risky   │
│                     │ Implementation                                         │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ elliptic                                               │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ <=6.6.1                                                │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ <0.0.0                                                 │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ libs__auth>get-jwks>jwk-to-pem>elliptic                │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-848j-6mx2-7j84      │
└─────────────────────┴────────────────────────────────────────────────────────┘
24 vulnerabilities found
Severity: 1 low | 14 moderate | 3 high | 6 critical

@getlarge
Copy link
Copy Markdown
Owner

@claude review

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 26, 2026

⚠️ Knip — Unused code or dependencies found

Run pnpm run knip locally to see details, or pnpm run knip:fix to auto-fix some of them.

Full report
�[93m�[4mUnused files�[24m�[39m (64)
apps/console/e2e/seed-diary-browser.ts                                                     
apps/landing/src/hooks/useFeedSSE.ts                                                       
apps/mcp-server/src/schemas/index.ts                                                       
apps/rest-api/src/migrate.ts                                                               
apps/rest-api/src/sse/public-feed-poller.ts                                                
apps/rest-api/src/sse/sse-writer.ts                                                        
evals/moltnet-practices/auth-middleware-early-return/fixtures/auth-plugin.ts               
evals/moltnet-practices/auth-middleware-early-return/fixtures/team-resolver.ts             
evals/moltnet-practices/e2e-raw-fetch-vs-api-client/fixtures/sdk.gen.ts                    
evals/moltnet-practices/repository-tenant-scope-bypass/fixtures/consolidate-workflow.ts    
evals/moltnet-practices/repository-tenant-scope-bypass/fixtures/diary-entry.repository.ts  
evals/moltnet-practices/rest-error-boundary/fixtures/pack-routes.ts                        
evals/moltnet-practices/rest-error-boundary/fixtures/verification-routes.ts                
evals/moltnet-practices/webhook-auth-status-code/fixtures/hooks.ts                         
examples/compile-context.ts                                                                
examples/diary-create.ts                                                                   
examples/diary-search.ts                                                                   
examples/register.ts                                                                       
examples/sign-entry.ts                                                                     
libs/api-client/__tests__/retry-fetch.test.ts                                              
libs/context-distill/__tests__/benchmarks/cluster.bench.ts                                 
libs/context-distill/__tests__/benchmarks/compile.bench.ts                                 
libs/context-distill/__tests__/cluster.test.ts                                             
libs/context-distill/__tests__/compile.test.ts                                             
libs/context-distill/__tests__/compress.test.ts                                            
libs/context-distill/__tests__/consolidate.test.ts                                         
libs/context-distill/__tests__/entry-relations.integration.test.ts                         
libs/context-distill/__tests__/mmr.test.ts                                                 
libs/context-distill/__tests__/provenance-dag.integration.test.ts                          
libs/context-distill/__tests__/selector.test.ts                                            
libs/context-pack-service/__tests__/context-pack.service.diff.test.ts                      
libs/context-pack-service/__tests__/context-pack.service.test.ts                           
libs/context-pack-service/__tests__/entry-fitter.test.ts                                   
libs/context-pack-service/__tests__/entry-loader.test.ts                                   
libs/context-pack-service/__tests__/pack-renderer.test.ts                                  
libs/embedding-service/__tests__/embedding-service.test.ts                                 
libs/sdk/__tests__/agent.test.ts                                                           
libs/sdk/__tests__/config.test.ts                                                          
libs/sdk/__tests__/connect.test.ts                                                         
libs/sdk/__tests__/credentials.test.ts                                                     
libs/sdk/__tests__/encrypt-vectors.test.ts                                                 
libs/sdk/__tests__/encrypt.test.ts                                                         
libs/sdk/__tests__/errors-formatting.test.ts                                               
libs/sdk/__tests__/errors.test.ts                                                          
libs/sdk/__tests__/register.test.ts                                                        
libs/sdk/__tests__/repair.test.ts                                                          
libs/sdk/__tests__/retry.test.ts                                                           
libs/sdk/__tests__/sign-bytes.test.ts                                                      
libs/sdk/__tests__/sign.test.ts                                                            
libs/sdk/__tests__/ssh.test.ts                                                             
libs/sdk/__tests__/token.test.ts                                                           
packages/github-agent/__tests__/bot-user.test.ts                                           
packages/github-agent/__tests__/credential-helper.test.ts                                  
packages/github-agent/__tests__/find-installation.integration.test.ts                      
packages/github-agent/__tests__/git-setup.test.ts                                          
packages/github-agent/__tests__/token.test.ts                                              
test-fixtures/generate-ssh-vectors.mjs                                                     
test-fixtures/generate-x25519-vectors.mjs                                                  
tools/db/backfill-content-hashes.ts                                                        
tools/db/backfill-diary-team-links.ts                                                      
tools/db/backfill-keto-subject-set.ts                                                      
tools/db/backfill-personal-teams.ts                                                        
tools/db/backfill-team-relations-plural.ts                                                 
tools/db/cleanup-legacy-diary-tuples.ts                                                    
�[93m�[4mUnused dependencies�[24m�[39m (38)
@moltnet/models                              apps/console/package.json:18:6             
@fastify/otel                                apps/mcp-server/package.json:31:6          
@opentelemetry/exporter-metrics-otlp-proto   apps/mcp-server/package.json:33:6          
@opentelemetry/exporter-trace-otlp-proto     apps/mcp-server/package.json:34:6          
@opentelemetry/instrumentation               apps/mcp-server/package.json:35:6          
@opentelemetry/instrumentation-dns           apps/mcp-server/package.json:36:6          
@opentelemetry/instrumentation-http          apps/mcp-server/package.json:37:6          
@opentelemetry/instrumentation-net           apps/mcp-server/package.json:38:6          
@opentelemetry/instrumentation-pino          apps/mcp-server/package.json:39:6          
@opentelemetry/instrumentation-pg            apps/mcp-server/package.json:40:6          
@opentelemetry/instrumentation-runtime-node  apps/mcp-server/package.json:41:6          
@opentelemetry/instrumentation-undici        apps/mcp-server/package.json:42:6          
@opentelemetry/resources                     apps/mcp-server/package.json:43:6          
@opentelemetry/sdk-metrics                   apps/mcp-server/package.json:44:6          
@opentelemetry/sdk-trace-base                apps/mcp-server/package.json:45:6          
@opentelemetry/sdk-trace-node                apps/mcp-server/package.json:46:6          
@opentelemetry/semantic-conventions          apps/mcp-server/package.json:47:6          
pino                                         apps/mcp-server/package.json:51:6          
pino-opentelemetry-transport                 apps/mcp-server/package.json:52:6          
thread-stream                                apps/mcp-server/package.json:53:6          
multiformats                                 apps/rest-api/package.json:36:6            
@huggingface/transformers                    apps/rest-api/package.json:38:6            
@opentelemetry/exporter-metrics-otlp-proto   apps/rest-api/package.json:48:6            
@opentelemetry/instrumentation               apps/rest-api/package.json:50:6            
@opentelemetry/resources                     apps/rest-api/package.json:58:6            
@opentelemetry/sdk-metrics                   apps/rest-api/package.json:59:6            
@opentelemetry/sdk-trace-base                apps/rest-api/package.json:60:6            
@opentelemetry/sdk-trace-node                apps/rest-api/package.json:61:6            
@opentelemetry/semantic-conventions          apps/rest-api/package.json:62:6            
pino-pretty                                  apps/rest-api/package.json:70:6            
thread-stream                                apps/rest-api/package.json:71:6            
@noble/hashes                                libs/context-pack-service/package.json:27:6
@sinclair/typebox                            libs/pi-extension/package.json:48:6        
@moltnet/auth                                tools/package.json:36:6                    
@moltnet/models                              tools/package.json:42:6                    
@moltnet/tasks                               tools/package.json:44:6                    
drizzle-orm                                  tools/package.json:50:6                    
fastq                                        tools/package.json:51:6                    
�[93m�[4mUnused devDependencies�[24m�[39m (11)
drizzle-orm                 apps/mcp-server/package.json:59:6      
pino-pretty                 apps/mcp-server/package.json:60:6      
@moltnet/crypto-service     libs/context-distill/package.json:24:6 
@moltnet/database           libs/context-distill/package.json:25:6 
@testcontainers/postgresql  libs/context-distill/package.json:26:6 
drizzle-orm                 libs/context-distill/package.json:27:6 
pg                          libs/context-distill/package.json:28:6 
@types/pg                   libs/context-distill/package.json:29:6 
testcontainers              libs/diary-service/package.json:37:6   
@moltnet/crypto-service     packages/github-agent/package.json:43:6
@types/figlet               tools/package.json:57:6                
�[93m�[4mReferenced optional peerDependencies�[24m�[39m (1)
ink  libs/design-system/package.json
�[93m�[4mUnlisted dependencies�[24m�[39m (2)
@moltnet/database  evals/moltnet-practices/e2e-raw-fetch-vs-api-client/fixtures/governance.e2e.test.ts:19:46
pg                 libs/diary-service/__tests__/diary-service.dbos.integration.test.ts:21:27                
�[93m�[4mUnlisted binaries�[24m�[39m (6)
python3                                             .github/workflows/ci.yml     
clawhub                                             .github/workflows/release.yml
go                                                  package.json                 
gofmt                                               package.json                 
packages/openclaw-skill/scripts/publish-clawhub.sh  package.json                 
packages/openclaw-skill/scripts/package.sh          package.json                 
�[93m�[4mUnused exports�[24m�[39m (73)
ENTRY_TYPE_OPTIONS                          apps/console/src/diaries/utils.ts:22:14                       
API_BASE_URL                                apps/landing/src/api.ts:16:14                                 
handleDiaryTags                   function  apps/mcp-server/src/diary-tools.ts:464:23                     
handleGrantCreate                 function  apps/mcp-server/src/grant-tools.ts:38:23                      
handleGrantRevoke                 function  apps/mcp-server/src/grant-tools.ts:70:23                      
handleGrantList                   function  apps/mcp-server/src/grant-tools.ts:102:23                     
handleMoltnetInfo                 function  apps/mcp-server/src/info-tools.ts:24:23                       
handlePacksUpdate                 function  apps/mcp-server/src/pack-tools.ts:287:23                      
handleRenderedPacksUpdate         function  apps/mcp-server/src/pack-tools.ts:314:23                      
handlePacksDiff                   function  apps/mcp-server/src/pack-tools.ts:413:23                      
handleSignMessage                 function  apps/mcp-server/src/prompts.ts:212:23                         
CustomPackEntrySelectionSchema              apps/mcp-server/src/schemas/pack-schemas.ts:102:14            
handleTeamsList                   function  apps/mcp-server/src/team-tools.ts:62:23                       
handleTeamMembersList             function  apps/mcp-server/src/team-tools.ts:84:23                       
handleTeamsCreate                 function  apps/mcp-server/src/team-tools.ts:109:23                      
handleTeamsJoin                   function  apps/mcp-server/src/team-tools.ts:132:23                      
handleTeamsDelete                 function  apps/mcp-server/src/team-tools.ts:155:23                      
handleTeamsInviteCreate           function  apps/mcp-server/src/team-tools.ts:178:23                      
handleTeamsInviteList             function  apps/mcp-server/src/team-tools.ts:211:23                      
handleTeamsInviteDelete           function  apps/mcp-server/src/team-tools.ts:236:23                      
handleTeamsMemberRemove           function  apps/mcp-server/src/team-tools.ts:264:23                      
ServerConfigSchema                          apps/rest-api/src/config.ts:26:14                             
DatabaseConfigSchema                        apps/rest-api/src/config.ts:38:14                             
WebhookConfigSchema                         apps/rest-api/src/config.ts:43:14                             
RecoveryConfigSchema                        apps/rest-api/src/config.ts:47:14                             
OryConfigSchema                             apps/rest-api/src/config.ts:51:14                             
ObservabilityConfigSchema                   apps/rest-api/src/config.ts:62:14                             
EmbeddingConfigSchema                       apps/rest-api/src/config.ts:98:14                             
SecurityConfigSchema                        apps/rest-api/src/config.ts:105:14                            
loadEmbeddingConfig               function  apps/rest-api/src/config.ts:264:17                            
loadPackGcConfig                  function  apps/rest-api/src/config.ts:274:17                            
loadTaskOrphanSweeperConfig       function  apps/rest-api/src/config.ts:284:17                            
acceptsProblemJson                          apps/rest-api/src/problems/index.ts:2:3                       
findProblemTypeByCode                       apps/rest-api/src/problems/index.ts:8:3                       
findProblemTypeByStatus                     apps/rest-api/src/problems/index.ts:9:3                       
getTypeUri                                  apps/rest-api/src/problems/index.ts:10:3                      
problemTypes                                apps/rest-api/src/problems/index.ts:12:3                      
DiaryTagCountSchema                         apps/rest-api/src/schemas/diary.ts:57:14                      
PublicAuthorSchema                          apps/rest-api/src/schemas/diary.ts:122:14                     
ContextPackEntrySchema                      apps/rest-api/src/schemas/packs.ts:8:14                       
TaskTypeDescriptorSchema                    apps/rest-api/src/schemas/tasks.ts:184:14                     
consolidateQueue                            apps/rest-api/src/workflows/context-distill-workflows.ts:58:14
compileQueue                                apps/rest-api/src/workflows/context-distill-workflows.ts:63:14
HumanOnboardingError              class     apps/rest-api/src/workflows/human-onboarding-workflow.ts:36:14
compileQueue                                apps/rest-api/src/workflows/index.ts:2:3                      
consolidateQueue                            apps/rest-api/src/workflows/index.ts:4:3                      
contextDistillWorkflows                     apps/rest-api/src/workflows/index.ts:7:3                      
diaryTransferWorkflow                       apps/rest-api/src/workflows/index.ts:14:3                     
TRANSFER_DECISION_EVENT                     apps/rest-api/src/workflows/index.ts:17:3                     
HumanOnboardingError                        apps/rest-api/src/workflows/index.ts:22:3                     
DEFAULT_WORKFLOW_TIMEOUT_MS                 apps/rest-api/src/workflows/index.ts:56:3                     
runWorkflow                                 apps/rest-api/src/workflows/index.ts:57:3                     
FOUNDING_ACCEPT_EVENT                       apps/rest-api/src/workflows/index.ts:61:3                     
TeamFoundingTimeoutError                    apps/rest-api/src/workflows/index.ts:67:3                     
teamFoundingWorkflow                        apps/rest-api/src/workflows/index.ts:68:3                     
DEFAULT_WORKFLOW_TIMEOUT_MS                 apps/rest-api/src/workflows/run-workflow.ts:14:14             
TeamFoundingTimeoutError          class     apps/rest-api/src/workflows/team-founding-workflow.ts:32:14   
DBOSWorkflowConflictError                   libs/database/src/dbos.ts:145:3                               
DEFAULT_DISPATCH_TIMEOUT_SECONDS            libs/database/src/workflows/task-workflows.ts:107:14          
DEFAULT_RUNNING_TIMEOUT_SECONDS             libs/database/src/workflows/task-workflows.ts:111:14          
MAX_PUBLIC_CONTENT_LENGTH                   libs/diary-service/src/diary-service.ts:52:14                 
RUBRIC_ASSET_PATH                           libs/pi-extension/src/moltnet/judge/assets.ts:15:14           
JUDGE_PROMPT_ASSET_PATH                     libs/pi-extension/src/moltnet/judge/assets.ts:16:14           
JUDGE_PROMPT_ASSET_PATH                     libs/pi-extension/src/moltnet/judge/fidelity.ts:13:3          
JUDGE_SYSTEM_PROMPT                         libs/pi-extension/src/moltnet/judge/fidelity.ts:14:3          
RUBRIC_ASSET_PATH                           libs/pi-extension/src/moltnet/judge/fidelity.ts:15:3          
makeClient                        function  packages/legreffier-cli/src/api.ts:77:17                      
formatPortIssues                  function  packages/legreffier-cli/src/phases/portValidate.ts:140:17     
gitMergeBase                      function  tools/src/tasksmith/gh-client.ts:151:23                       
gitShowFileAtRef                  function  tools/src/tasksmith/gh-client.ts:206:23                       
SEED_INSTRUCTION                            tools/src/tasksmith/task-extractor.ts:538:10                  
verifyTask                        function  tools/src/tasksmith/verify.ts:356:23                          
cleanupPrArtifacts                function  tools/src/tasksmith/verify.ts:480:23                          
�[93m�[4mUnused exported types�[24m�[39m (39)
MailRecord                 interface  apps/console/e2e/helpers/mailslurper.ts:3:18                      
MoltnetInfoInput           type       apps/mcp-server/src/schemas/info-schemas.ts:19:13                 
IssueVoucherInput          type       apps/mcp-server/src/schemas/vouch-schemas.ts:22:13                
ListVouchersInput          type       apps/mcp-server/src/schemas/vouch-schemas.ts:25:13                
TrustGraphInput            type       apps/mcp-server/src/schemas/vouch-schemas.ts:28:13                
CorsPluginOptions          interface  apps/rest-api/src/plugins/cors.ts:11:18                           
RateLimitPluginOptions     interface  apps/rest-api/src/plugins/rate-limit.ts:14:18                     
ProblemType                type       apps/rest-api/src/problems/index.ts:11:8                          
CreateTaskInput            type       apps/rest-api/src/services/task.service.ts:2:8                    
AuthContext                type       apps/rest-api/src/types.ts:14:3                                   
PermissionChecker          type       apps/rest-api/src/types.ts:15:3                                   
RelationshipReader         type       apps/rest-api/src/types.ts:16:3                                   
RelationshipWriter         type       apps/rest-api/src/types.ts:17:3                                   
CompileWorkflowInput       type       apps/rest-api/src/workflows/index.ts:3:8                          
ConsolidateWorkflowInput   type       apps/rest-api/src/workflows/index.ts:5:8                          
ContextDistillDeps         type       apps/rest-api/src/workflows/index.ts:6:8                          
DiaryTransferDeps          type       apps/rest-api/src/workflows/index.ts:12:8                         
DiaryTransferResult        type       apps/rest-api/src/workflows/index.ts:13:8                         
TransferDecision           type       apps/rest-api/src/workflows/index.ts:18:8                         
HumanOnboardingDeps        type       apps/rest-api/src/workflows/index.ts:21:8                         
HumanOnboardingResult      type       apps/rest-api/src/workflows/index.ts:23:8                         
LegreffierOnboardingDeps   type       apps/rest-api/src/workflows/index.ts:34:8                         
MaintenanceDeps            type       apps/rest-api/src/workflows/index.ts:43:8                         
RegistrationDeps           type       apps/rest-api/src/workflows/index.ts:48:8                         
RegistrationResult         type       apps/rest-api/src/workflows/index.ts:49:8                         
RunWorkflowOptions         type       apps/rest-api/src/workflows/index.ts:58:8                         
FoundingMember             type       apps/rest-api/src/workflows/index.ts:62:8                         
TeamFoundingDeps           type       apps/rest-api/src/workflows/index.ts:65:8                         
TeamFoundingResult         type       apps/rest-api/src/workflows/index.ts:66:8                         
SessionResolverLogger      interface  libs/auth/src/session-resolver.ts:24:18                           
CommandRegistrar           type       libs/pi-extension/src/commands/index.ts:5:3                       
SessionMeta                type       libs/pi-extension/src/commands/index.ts:7:3                       
PiJudgeRecipeVersions      interface  libs/pi-extension/src/moltnet/judge-recipe-cid.ts:47:18           
RateLimitRetryOptions      type       libs/sdk/src/retry.ts:5:15                                        
AgentAdapter               type       packages/legreffier-cli/src/adapters/index.ts:11:15               
AgentAdapterOptions        type       packages/legreffier-cli/src/adapters/index.ts:11:29               
ResolveInstallationStatus  type       packages/legreffier-cli/src/phases/portResolveInstallation.ts:6:13
VerifyInstallationStatus   type       packages/legreffier-cli/src/phases/portVerifyInstallation.ts:4:13 
InitPhase                  type       packages/legreffier-cli/src/state.ts:4:13                         
�[93m�[4mUnused exported enum members�[24m�[39m (1)
Impose  TaskPermission  libs/auth/src/keto-constants.ts:134:3
�[93m�[4mUnused catalog entries�[24m�[39m (4)
@anthropic-ai/claude-agent-sdk  default  pnpm-workspace.yaml:22:4 
@fastify/static                 default  pnpm-workspace.yaml:32:4 
@openai/codex-sdk               default  pnpm-workspace.yaml:46:4 
zod                             default  pnpm-workspace.yaml:124:3
�[33m�[4mConfiguration hints�[24m (7)�[39m
libs/sdk                   …p.config.ts  �[90mAdd �[97mentry�[90m and/or refine �[97mproject�[90m files in �[97mworkspaces["libs/sdk"]�[90m (15 unused fil…�[39m
. �[90m(root)�[39m                   …p.config.ts  �[90mAdd �[97mentry�[90m and/or refine �[97mproject�[90m files in �[97mworkspaces["."]�[90m (15 unused files)�[39m     
libs/context-distill       …p.config.ts  �[90mAdd �[97mentry�[90m and/or refine �[97mproject�[90m files in �[97mworkspaces["libs/context-distill"]�[90m (1…�[39m
tools                      …p.config.ts  �[90mAdd �[97mentry�[90m and/or refine �[97mproject�[90m files in �[97mworkspaces["tools"]�[90m (6 unused files)�[39m  
…s/context-pack-service    …p.config.ts  �[90mAdd �[97mentry�[90m and/or refine �[97mproject�[90m files in �[97mworkspaces["libs/context-pack-service�[90m…�[39m
packages/github-agent      …p.config.ts  �[90mAdd �[97mentry�[90m and/or refine �[97mproject�[90m files in �[97mworkspaces["packages/github-agent"]�[90m (…�[39m
apps/rest-api              …p.config.ts  �[90mAdd �[97mentry�[90m and/or refine �[97mproject�[90m files in �[97mworkspaces["apps/rest-api"]�[90m (3 unused…�[39m
 ELIFECYCLE  Command failed with exit code 1.

@claude
Copy link
Copy Markdown

claude Bot commented Apr 26, 2026

Code Review — PR #954

Scope: libs/pi-extension/src/runtime/execute-pi-task.ts + test file
CI: All checks passing (lint, typecheck, CodeQL, Semgrep) — Test and Build & Push (rest-api) still running at time of review.


Summary

The four minimum-scope items from #947 are all correctly implemented. The structural choices hold up:

  • The pre-execute guard returns before resumeVm, so no VM teardown is needed in that path.
  • cancelListener is declared outside the try block so finally can always reach it regardless of throw path.
  • The wireSessionAbort double-invocation guard is sound — direct calls to the returned listener don't remove it from the EventTarget, so abortInvoked is the right guard (not { once: true } alone).
  • removeEventListener in finally is a safe no-op when the signal was already aborted at wiring time (listener was never added via addEventListener in that path).
  • Token preservation on early cancel is correct — emptyUsage rather than the accumulated finalUsage in the pre-execute path (no tokens were spent), accumulated usage in the post-prompt path (tokens were spent).

One real issue

Misleading comment about llmAbort and stopReason: 'aborted' (execute-pi-task.ts, the new block around const cancelled = reporter.cancelSignal.aborted)

The comment states:

pi maps session.abort() to a turn_end with stopReason: 'aborted' which the subscribe handler above sets llmAbort = true for

This is factually wrong. The subscribe handler sets llmAbort only on stopReason === 'error'. stopReason: 'aborted' leaves llmAbort = false. The cancellation is detected solely via reporter.cancelSignal.aborted. The comment will mislead a future reader who tries to trace the llmAbort path through an abort-triggered cancel.

Suggested fix — drop the llmAbort clause from that sentence:

// Cancellation takes precedence over runError / parseError.
// pi maps `session.abort()` to a `turn_end` with `stopReason: 'aborted'`;
// the subscribe handler does NOT set `llmAbort` for that stop reason, so
// the cancelSignal check here is the sole mechanism that distinguishes a
// cancel-driven stop from a clean finish.

Minor observation (non-blocking)

The rejection-swallow test uses setTimeout(resolve, 10) as a microtask drain. The vi.fn().mockRejectedValue(...) rejection is caught immediately inside the listener's .catch(), so 10 ms is more than sufficient in practice. Flagging only because it's a timing-sensitive pattern — await Promise.resolve(); await Promise.resolve() would be more robust if this test ever becomes flaky under load.


Tests

The four wireSessionAbort tests cover the contract well (normal fire, pre-aborted signal, double-invocation guard, rejection swallow). The exported helper makes unit testing possible without a Gondolin VM — good call.

One coverage gap worth noting for the backlog (not blocking merge): there is no unit test for the post-prompt cancelled path inside executePiTask itself (the const cancelled = reporter.cancelSignal.aborted check after Promise.all(recordingPromise)). That integration requires a real session mock, which brings the "needs booted VM" complexity. Tracking it as a follow-up is the right call.


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
@legreffier
Copy link
Copy Markdown
Contributor Author

legreffier Bot commented Apr 26, 2026

Comment fix pushed in 0a4ac9cd. Verified: line 356 sets llmAbort = msg?.stopReason === 'error', so 'aborted' indeed leaves it false. The cancelSignal check is the sole detection path. Wording aligned with the suggested replacement.

Skipping the two non-blocking notes:

  • The setTimeout(resolve, 10) in the rejection-swallow test: works as-is, the synchronous rejection lands well within 10ms; not changing it preemptively.
  • Unit coverage for the post-prompt cancelled path inside executePiTask: agreed it's a real gap, but it requires the same VM-mock complexity that's already explicitly out of scope for this file's tests. Tracking as part of the future pi-backed e2e (no separate issue yet — would land alongside the run-the-daemon-for-real validation).

@getlarge getlarge merged commit 39c7db7 into main Apr 26, 2026
27 checks passed
@getlarge getlarge deleted the fix/issue-947-pi-cancel branch April 26, 2026 11:59
@github-actions github-actions Bot mentioned this pull request Apr 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

pi-extension: honor reporter.cancelSignal in executePiTask (call session.abort)

1 participant