Skip to content

CL-6326: onTrigger non-fatal body-failure edge (onBodyFailure) - #68

Merged
TheGreatAxios merged 3 commits into
mainfrom
cl-6326-onbodyfailure
Aug 20, 2026
Merged

CL-6326: onTrigger non-fatal body-failure edge (onBodyFailure)#68
TheGreatAxios merged 3 commits into
mainfrom
cl-6326-onbodyfailure

Conversation

@TheGreatAxios

Copy link
Copy Markdown
Contributor

Summary

  • onTrigger gains an onBodyFailure?: "end" | "continue" policy field. Default "end" preserves today's terminal-is-final behavior byte-compatibly. "continue" lets a body run that ends failed leave a long-lived, event-driven section subscribed instead of ending the whole run, so one bad turn does not kill the entire conversation's run.
  • cancelled is scoped out of the policy on purpose (confirmed with the ledger owner): it always ends the section, since cancellation reflects a drain/operator decision, not a turn-level error.
  • The failed occurrence is never silent: the existing ChildCompleted{terminalStatus:"failed"} commit lands on the run's own durable audit log before the policy check runs either way — "continue" makes it non-fatal to the section, not unobservable. Verified in tests (CL-6322's spike flagged this as the NO-GO condition: a killed turn that emits no failure signal and hangs to timeout).
  • Two call sites updated in vendor/intx/workflow/src/runtime/run.ts: the steady-state drive loop and planOnTriggerResume's crash-recovery counterpart, both reading primitive.onBodyFailure live (mirroring how awaitSignal.onTimeout is read live rather than defaulted at construction).

Vendoring

This is a local delta on the current pin (59f5e7b9), not the pending re-pin in #59#59 is held for the packaging milestone. Upstream's 486a6b1b touched run.ts after this pin; the delta will need re-applying against the re-pinned tree once #59 lands (noted in docs/revendor-inventory.md and VENDORED.md).

  • VENDORED.md — extended the vendor/intx/workflow local-modifications prose (existing row, not a new one).
  • vendor/intx/workflow/VENDORED-FROM — delta line for this change.
  • scripts/checks/kill-dates.txt — recomputed tree hash; bun run scripts/checks/killdates.ts passes.
  • docs/revendor-inventory.md — new entry under "Open upstream gaps patched in the vendored tree".

Upstream report (to file against faremeter/interchange separately):

Title: onTrigger: non-fatal body-failure edge (terminal-is-final is too strict for a long-lived section)

runOnTrigger's steady-state drive loop and its crash-recovery counterpart in planOnTriggerResume treat a failed body occurrence identically to a cancelled one: both end the whole section run. For a long-lived, event-driven section (chat-style: one occurrence per inbound message), that means a single bad turn permanently ends the entire conversation's run, with no way to keep servicing later occurrences. We've vendored a BodyFailurePolicy ("end" | "continue") field, onTrigger.onBodyFailure, defaulting to "end" (current behavior, byte-compatible), where "continue" lets the section re-arm on its input park after a failed occurrence instead of throwing — cancellation is untouched and always still ends the section. Retire our vendored copy once this (or an equivalent surface) ships upstream on a published @intx/workflow version.

Test plan

  • bun test vendor/intx/workflow/src/runtime/run.test.ts — 4 tests, red/green verified by stashing the runtime delta and confirming 2 of the 4 fail against the unmodified vendored code, then pass with it applied.
  • bunx prettier --check on all touched files.
  • bun run scripts/checks/killdates.ts passes (recomputed hash matches).
  • New coverage, not a top-up: no test file previously existed for run.ts in this vendored package (per runlocal/run-local.ts:8's own note pointing at the intended runtime/run.test.ts location).

Refs CL-6326.

Red/green coverage for a failed body occurrence ending a long-lived
onTrigger section (CL-6326): default policy is unchanged, a
"continue" policy re-arms past a failed occurrence while a
cancelled one is always terminal-is-final, and crash-recovery honors
the same policy. Fails against the unmodified vendored runtime; the
next commit makes it pass.
A failed body occurrence and a cancelled one were both terminal-is-final,
so a single bad turn permanently ended a long-lived, event-driven
onTrigger section. Adds onBodyFailure?: "end" | "continue" (default
"end", byte-compatible with prior behavior); "continue" lets the
section re-arm on its input park after a failed occurrence instead of
throwing. Cancellation is unaffected and always ends the section --
it reflects a drain/operator decision, not a turn-level error. The
failed occurrence stays durably recorded on the run's own audit log
(the existing ChildCompleted commit) regardless of policy, so it is
never silent, only non-fatal to the section.
@TheGreatAxios
TheGreatAxios force-pushed the cl-6326-onbodyfailure branch from 540b635 to f5658ad Compare August 20, 2026 04:40
Extends the vendor/intx/workflow ledger entries for CL-6326: VENDORED.md's
local-modifications prose, the package's own VENDORED-FROM delta line, the
recomputed kill-dates.txt tree hash, and a docs/revendor-inventory.md entry
noting the delta re-applies once PR #59's re-pin lands (upstream's 486a6b1b
touched run.ts after this pin).
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.

1 participant