feat(workflows): add heartbeat config contract - #2229
Conversation
There was a problem hiding this comment.
Pull request overview
Adds the slice-1 “heartbeat” authoring and contract surface to @bastani/workflows: a validated heartbeatIntervalMinutes option with a default, plus a typed custom event payload/identity contract, with accompanying spec/docs/tests. This aligns with #1975 while explicitly deferring scheduler/delivery + terminal cleanup to later slices.
Changes:
- Added
heartbeatIntervalMinutesto workflow authoring with defaulting (15), explicit0disable semantics, and non-negative finite validation. - Declared the
workflows:workflow-heartbeatevent contract (payload + identity types/constants) for later scheduling/delivery slices. - Added an RFC/spec, user-facing docs updates, and unit contract tests covering defaults/validation/immutability and event shape.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| test/unit/workflow-heartbeat-contract.test.ts | Adds unit contract coverage for authoring default/validation/freeze behavior and the heartbeat event payload/identity shape. |
| specs/2026-08-06-workflow-heartbeats.md | Introduces the three-slice RFC/spec describing goals, payload amendment, slice boundaries, and follow-up work. |
| packages/workflows/src/shared/workflow-authoring-types.ts | Extends the authored workflow spec type with optional heartbeatIntervalMinutes. |
| packages/workflows/src/shared/authoring-contract-ui.ts | Extends the compiled WorkflowDefinition contract with resolved heartbeatIntervalMinutes: number. |
| packages/workflows/src/extension/lifecycle-notifications.ts | Declares the heartbeat custom type constant plus payload/identity interfaces alongside existing lifecycle notification contracts. |
| packages/workflows/src/authoring/workflow.ts | Implements defaulting + validation and stamps the resolved heartbeatIntervalMinutes onto the frozen workflow definition. |
| packages/workflows/README.md | Documents the new authoring parameter, units/defaults, and the fact that scheduling/delivery is not yet implemented in this slice. |
| packages/workflows/CHANGELOG.md | Adds an Unreleased entry documenting the new authoring option and event contract (and clarifying that scheduling/delivery is out of scope here). |
| packages/coding-agent/docs/workflows.md | Updates user-facing workflow docs with the new parameter, semantics, and an example, including “authoring-only” caveat for this slice. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Results from the Live heartbeat delivery evidence follows with the scheduler slice. |
|
Hi @morgan-coded, thanks for your patience, and sorry for the delay. We have been working through a larger refactor and the pi 0.84.1 dependency upgrade. Since your last update, the branch has fallen behind and now conflicts with current Please also address Greptile's public API finding by exporting the heartbeat runtime constant and event types from Please let us know if you have any questions. |
|
Merged the latest |
|
Thanks @morgan-coded! Is it cool if I take over the rest of the scope of the heartbeat functionality after this part you created we merge? I got an urgent request for it and wanted to make some changes as I go to the scope so didn't want to cause confusion. Thank you for getting it this far along. |
|
Of course — take it from here. The #2229 contract should drop straight in as a base, and feel free to reshape any of it as the scope evolves. Thanks for the heads-up. |
bbf0c33 to
849702c
Compare
Move DEFAULT_WORKFLOW_HEARTBEAT_INTERVAL_MINUTES next to the heartbeat custom type and event interfaces so slice 2 imports one contract module, and drop the heartbeat re-export from lifecycle-notifications, which owns an unrelated event. The contract test now imports the contract directly and pins the exported default against the literal 15. Co-authored-by: morgan-coded <256248948+morgan-coded@users.noreply.github.com> Assistant-model: Claude Opus 5
849702c to
9097e18
Compare
Stack for #1975
Merge bottom to top; each PR is based on the one below it.
Base of the stack is
main. #2377, #2379 and #2383 are linked as GitHub stack #2380. #2229 cannot join it because its head branch lives on a fork, so this table carries the full chain.Workflows have no authored heartbeat cadence or typed event contract for periodic parent alignment checks. This first slice adds
heartbeatIntervalMinuteswith a 15-minute default, explicit0disable behavior, finite non-negative validation, and a five-field event payload with identity keyed byrunIdplusscheduledAt— no goal field, per your amendment. Scheduling/delivery and terminal cleanup/recovery stay out of this slice and will follow separately; the three-slice design is recorded inspecs/2026-08-06-workflow-heartbeats.md.docs/workflows.mdand the workflows README carry the parameter, minute units, default,0semantics, and an example, each stating that a positive interval does not deliver heartbeats until the scheduler slice lands — say the word if you would rather hold the user-facing docs until then. Terminal evidence follows in a comment below. Part of #1975Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.Greptile Summary
This change adds workflow heartbeat authoring configuration, a public heartbeat event contract, and documentation for the resolved default and disable behavior. Public-package verification confirmed that omitted intervals resolve to 15 minutes, explicit zero is retained, invalid numeric values are rejected, and the required package-root exports are available.
Confidence Score: 5/5
Safe to merge; no blocking failure remains.
No accepted blocking findings remain. The public workflow package contract was exercised successfully for defaulting, explicit disable behavior, invalid-value rejection, and package-root exports.
What T-Rex did
Reviews (6): Last reviewed commit: "refactor(workflows): colocate heartbeat ..." | Re-trigger Greptile