Commit 5964124
* feat(automation): stamp status 'stranded' on the resume catch arm and pin the re-armed run's exactly-once (the #13937 services half)
The shape-4 ruling keeps resumeInternal's consumption order; the state it
leaves behind when a downstream node throws now carries the contract's name
(AutomationResult.status: 'stranded', #14384) on the one exit that journals a
consumed suspension. Stale "unruled" comments cite the ruling. The existing
verb (restoreConsumedSuspension) is the exit; its double-run pins are added,
including the cross-replica stale-journal case, which is RED at this commit
by design (the precedence fix follows in the next commit).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XpTx2tbq3pZRYAdoGt6E6Y
* fix(automation): restoreConsumedSuspension reads the durable terminal row before its per-process journal
A hot copy left on the replica that stranded a run could re-arm the run after
another replica restored, resumed and finished it — the next resume then
re-ran every node after the pause. The terminal row is the record; a row that
exists without a snapshot is the last word and the hot copy is dropped. The
two stale-journal pins added in the previous commit go red -> green here.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XpTx2tbq3pZRYAdoGt6E6Y
* test(automation): pin the operator exit on ObjectStoreSuspendedRunStore — pause-node provenance, over-budget drop, two-witness read
Eight pins over the production store class and the repo's fake ObjectQL
engine; all eight are RED at this commit by design (the durable-first read
of the previous commit re-arms at the node that threw, and a dropped
snapshot reads as the run having moved on). The changeset's "no difference"
claim is replaced with what is now known. The fix follows in the next commit.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XpTx2tbq3pZRYAdoGt6E6Y
* fix(automation): restoreConsumedSuspension reads its journal and the durable row as two witnesses; the stranded row records the pause node and any dropped snapshot
- The stranded run's terminal row carries the PAUSE node in node_id (it
carried the last step, the node that threw, which the object store read
back as the snapshot's node: a restore from the row re-armed the failed
node and the next resume skipped it).
- The object store records an over-budget snapshot drop IN the row, with the
pause it belonged to (RunRecord.consumedSuspensionDropped), instead of a
bare NULL that read as the run having moved on.
- The engine prefers its hot copy when it and the row describe the same
pause; between different pauses the newest strand wins, judged by whether
this process's own history write landed (ConsumedSuspension.persisted);
a snapshot-less, notice-less row discards the hot copy only when that
write did land.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XpTx2tbq3pZRYAdoGt6E6Y
* test(automation): count the successful re-run of the failed node in the two-pause ledgers
The two-witness pins expected the ledger without the tail re-run that a
restore + resume legitimately performs; the engine was right, the count was
not. Pause-node assertions were already green.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XpTx2tbq3pZRYAdoGt6E6Y
* test(automation): pin the object-store fake's update to the engine's dispatch predicate; record the new pinned double
check:engine-double-contract's own two prescriptions: open the fake's
update() with assertEngineUpdateDispatch(data, options), and let the pinned
ledger learn the file (--write). The store's own update calls pass the
predicate: the object-store file stays 8/8.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XpTx2tbq3pZRYAdoGt6E6Y
* docs(automation): declare the stranded-row carve-out on sys_automation_run's node_id and variables_json
The durable row's own declarations now agree with their writer: on the one
terminal-row class that carries a consumed suspension, node_id is the PAUSED
node (the Runs surface titles and highlights the row with it), and
variables_json is either the restorable snapshot or the store's drop notice,
which is not one. Same carve-out pattern node_type's description already
carried. The changeset names the visible Runs-surface change. Source-only.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XpTx2tbq3pZRYAdoGt6E6Y
---------
Co-authored-by: Claude <noreply@anthropic.com>
1 parent e9b8cbb commit 5964124
9 files changed
Lines changed: 1272 additions & 72 deletions
File tree
- .changeset
- packages/services/service-automation/src
- scripts
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
Lines changed: 20 additions & 14 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
14 | 14 | | |
15 | 15 | | |
16 | 16 | | |
17 | | - | |
18 | | - | |
19 | | - | |
20 | | - | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
21 | 24 | | |
22 | 25 | | |
23 | 26 | | |
| |||
554 | 557 | | |
555 | 558 | | |
556 | 559 | | |
557 | | - | |
558 | | - | |
| 560 | + | |
| 561 | + | |
559 | 562 | | |
560 | 563 | | |
561 | 564 | | |
562 | 565 | | |
563 | 566 | | |
564 | | - | |
565 | | - | |
566 | | - | |
567 | | - | |
| 567 | + | |
| 568 | + | |
| 569 | + | |
| 570 | + | |
| 571 | + | |
| 572 | + | |
568 | 573 | | |
569 | 574 | | |
570 | 575 | | |
| |||
574 | 579 | | |
575 | 580 | | |
576 | 581 | | |
577 | | - | |
578 | | - | |
579 | | - | |
580 | | - | |
| 582 | + | |
| 583 | + | |
| 584 | + | |
| 585 | + | |
| 586 | + | |
581 | 587 | | |
582 | 588 | | |
583 | 589 | | |
| |||
0 commit comments