II.
Page JSON
Structured · livepage:docs-harness-features-backlog-gaps-tools-capabilities-gap-tools-030
GAP-TOOLS-030: Effect Cancellation json
Inspect the normalized record payload exactly as the atlas UI reads it.
{
"id": "page:docs-harness-features-backlog-gaps-tools-capabilities-gap-tools-030",
"_kind": "Page",
"_file": "wiki/docs/harness-features-backlog/gaps/tools-capabilities/gap-tools-030.md",
"_cluster": "wiki",
"attributes": {
"nodeKind": "Page",
"sourcePath": "docs/harness-features-backlog/gaps/tools-capabilities/GAP-TOOLS-030.md",
"sourceKind": "repo-docs",
"title": "GAP-TOOLS-030: Effect Cancellation",
"displayName": "GAP-TOOLS-030: Effect Cancellation",
"slug": "docs/harness-features-backlog/gaps/tools-capabilities/gap-tools-030",
"articlePath": "wiki/docs/harness-features-backlog/gaps/tools-capabilities/GAP-TOOLS-030.md",
"article": "\n# GAP-TOOLS-030: Effect Cancellation\n\n| Field | Value |\n|-------|-------|\n| Category | tools-capabilities |\n| Priority | High |\n| Effort | M |\n| Status | Missing |\n\n## Description\nCancel or stop a running effect mid-execution. CC's `TaskStopTool` can cancel\nbackground tasks. Babysitter has no cancellation mechanism -- once an effect is\ndispatched, it runs to completion or timeout.\n\n## Current State\nEffects are dispatched via `ctx.task()` and executed by the harness operator.\n`BABYSITTER_TIMEOUT` (default 2min) and `BABYSITTER_NODE_TASK_TIMEOUT` (15min) are\nthe only guards. The `invokeHarness()` function spawns a child process with a timeout\nbut the operator cannot cancel individual effects. If a harness hangs, the entire run\nblocks until timeout.\n\nNo journal event for cancellation. No `EFFECT_CANCELLED` type.\n\n## Target State\n- New `EFFECT_CANCELLED` journal event type\n- `task:cancel <runId> <effectId>` CLI command\n- Cancel signal propagated to running harness process (SIGTERM then SIGKILL)\n- Effect result marked as `status: 'cancelled'` with cancellation reason\n- Process code receives cancellation as a thrown error that can be caught:\n ```javascript\n try {\n await ctx.task(longRunningTask, args);\n } catch (e) {\n if (e instanceof EffectCancelledError) {\n // handle graceful cancellation\n }\n }\n ```\n- Embedded SDK dashboard shows cancel button for running effects\n- Timeout-based auto-cancellation configurable per task\n\n## Dependencies\nNone (core cancellation is standalone).\n\n**Optional enhancement**: [GAP-SUBOBS-004](../subagent-observability/GAP-SUBOBS-004.md) -- health monitoring can trigger auto-cancel (future integration, not a prerequisite)\n\n## Key Files\n| Component | Path |\n|-----------|------|\n| Harness invoker | `packages/sdk/src/harness/invoker.ts` |\n| Runtime exceptions | `packages/sdk/src/runtime/` (EffectRequestedError etc.) |\n| Storage events | `packages/sdk/src/storage/` (event types) |\n| Task CLI | `packages/sdk/src/cli/` (task:post) |\n\n## Recommendation\nPhase 2. High priority for production use -- runaway effects are a real operational\nissue. Start with CLI cancellation, then add embedded SDK dashboard button.\n",
"documents": []
},
"outgoingEdges": [],
"incomingEdges": [
{
"from": "page:docs-harness-features-backlog",
"to": "page:docs-harness-features-backlog-gaps-tools-capabilities-gap-tools-030",
"kind": "contains_page"
}
]
}