Skip to content

Commit bd193c6

Browse files
committed
docs(spec): cancelRun's true is not exclusive to the call that read it
The contract docblock said `true` is answered "only when a suspension was consumed by THIS call". The only implementation gives no such guarantee: the engine has no `cancelling` guard (only `resuming` / `restoring`), and `cancelRun` consumes through `forgetSuspendedRun(run, 'cancelled')`, whose store delete is by id and unconditional — nothing like `resume`'s advance claim. Two cancels of one run overlapping in time therefore both answer `true` and both record the terminal `cancelled` log. Say what the engine does: `true` means this call cancelled a suspended run (the `@returns` line, unchanged), NOT that it was the only one — a caller may not read sole authorship out of it, nor use it as an idempotency token for a once-only side effect. Prose only; the `@returns` line, the pin, the changeset and the result shape are untouched. Whether the engine should grow a cancel-side compare-and-set is the services half's call, not this contract's. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T6HeZvT9wdSJD1ZxJb5Eno
1 parent 60aaf36 commit bd193c6

1 file changed

Lines changed: 11 additions & 7 deletions

File tree

packages/spec/src/contracts/automation-service.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -688,13 +688,17 @@ export interface IAutomationService {
688688
*
689689
* Consumes the run's continuation and records a terminal `cancelled` run
690690
* log, so it stops surfacing as resumable; `reason` lands on that terminal
691-
* record's `error`. Answers `true` only when a suspension was consumed by
692-
* THIS call, and `false` when no suspended run exists under the id — it is
693-
* already terminal, or unknown — which callers treat as idempotent
694-
* success. ⚠️ A durable store the implementation could not READ also
695-
* answers `false`: the two are indistinguishable to the caller and the
696-
* run may still be parked, which is why an implementation reports that
697-
* path at `error` — nothing above it can tell the difference.
691+
* record's `error`. Answers `true` when it cancelled a suspended run, and
692+
* `false` when no suspended run exists under the id — it is already
693+
* terminal, or unknown — which callers treat as idempotent success. `true`
694+
* is NOT exclusive to this call — this contract carries no cancel-side
695+
* exclusivity guarantee, so two cancels of one run overlapping in time can
696+
* each answer `true` (and each record the terminal log): a caller may not
697+
* read `true` as sole authorship, nor use it as an idempotency token for a
698+
* once-only side effect. ⚠️ A durable store the implementation could not
699+
* READ also answers `false`: the two are indistinguishable to the caller
700+
* and the run may still be parked, which is why an implementation reports
701+
* that path at `error` — nothing above it can tell the difference.
698702
*
699703
* **The persistent face (the #13953 ruling, maintainer 2026-09-05):**
700704
* "listing and acting go through `sys_automation_run` (the persistent

0 commit comments

Comments
 (0)