Repository navigation
Commit d12e650
feat(spec): ExecutionStatus gains missed, a scheduled due time that passed while no kernel was ticking (#25363)
<!-- claude-projects-attribution: {"github_login":"os-bill"} -->
_Requested by **Bill** · [project
thread](https://claude.ai/code/project/chan_016iMXWSZDzqWRWvWzdNo8wg?thread=cmsg_016iMXWSZDzqWRWvWzdNo8wg6zwDuV2XvoDkqC7bXgqnpc)_
Fixes #25325
Clause-②: yes (widening)
Metadata-protocol: none
## What changes
- `packages/spec/src/automation/execution.zod.ts`: `ExecutionStatus`
gains `'missed'`, appended **last** (the file's own rule, as for
`refused`). The TSDoc says what it means: a scheduled flow's due time
that passed while no kernel was ticking, recorded once by the next
kernel that found it. It is terminal and is never started, resumed or
replayed. It is distinct from `cancelled` (nobody cancelled it) and from
`failed` (nothing ran). No new field.
- `execution.test.ts`: the order pin moves. The first eight members are
unchanged, the ninth is `refused`, the tenth is `missed`, and the length
is 10.
- `content/docs/references/automation/execution.mdx` and
`api/automation-api.mdx`: regenerated with `gen:docs` after
`check:generated` named exactly that artifact as stale. Nothing else
regenerated.
- One changeset, `.changeset/25325-execution-status-missed.md`, at
`patch` for `@objectstack/spec` and `@objectstack/plugin-approvals`
(`Metadata-protocol: none` takes `patch`).
## Declared services hunk (`domain:services`)
`packages/plugins/plugin-approvals/src/approval-service.ts`:
`RUN_STATUS_LIVENESS` (declared `as const satisfies` a Record keyed by
`ExecutionStatus` with `RunLiveness` values) gains `missed: 'terminal'`.
The services seat agreed to this line in advance in hand-off addendum
`6354069893` on #25235. Without it the new member does not compile. The
services PR cannot carry the line either, because `satisfies` refuses
the extra key until the member exists.
## TSDoc claims checked against the schema at this head
- `ExecutionLogSchema` has `startedAt` (required), `completedAt` and
`durationMs` (optional), and `refusalMessage` (optional). It has **no**
top-level `error` field: errors live only on each `steps[]` entry. So
the TSDoc says that on the `ExecutionLog`, `durationMs` and
`refusalMessage` are absent and `steps` is empty.
- The stored run row (`sys_automation_run`) spells the same instants
`started_at` / `finished_at`, and it has `duration_ms`, `error` and
`refusal_message` columns. The TSDoc names those three as absent on the
row. This is a correction to the card's wording, which listed `error` as
absent on both surfaces.
## Not touched
`AutomationResult.status`, `TriggerFlowResponseSchema.data.status`
(`contracts/automation-result-status.pin.test.ts` is unchanged) and
`JobExecutionStatus`. `ListRunsRequestSchema.status` and the REST
`?status=` filter (`parseEnumParam(..., ExecutionStatus.options)` in
`packages/runtime/src/domains/automation.ts`) widen by construction. The
`sys_automation_run.status` column options, `TERMINAL_RUN_STATUSES` and
the retention `onlyWhen` set widen in the services PR for #25235,
together with the producer. #25235 remains open.
## Sweep for totality sites
Outside `packages/spec`, every reader of `ExecutionStatus` in
`packages/**` is one of three things: a parameter type (`client`,
`service-automation` `engine.ts`), an `.options` read (`runtime`
`automation.ts`, and its `it.each(ExecutionStatus.options)` test), or
the one total map, `RUN_STATUS_LIVENESS`. No other Record keyed by
`ExecutionStatus` and no exhaustive switch exists beyond that map.
## Tests
At head `a6b929fa3`:
- `pnpm --filter @objectstack/spec build`: lock VERDICT command-exit 0.
- `pnpm --filter @objectstack/spec exec vitest run --maxWorkers=2
src/automation/execution.test.ts`: 1 file, 49/49 passed.
- `pnpm --filter '@objectstack/plugin-approvals^...' build`, then `pnpm
--filter @objectstack/plugin-approvals typecheck && pnpm --filter
@objectstack/plugin-approvals test && pnpm --filter @objectstack/spec
typecheck`: lock VERDICT command-exit 0, with plugin-approvals at 94
files and 1214/1214 tests passed (the totality test
`run-status-liveness.test.ts` included).
- Reverse verification. `node scripts/ablation-replace.mjs` deleted the
`missed: 'terminal'` line (anchor x1 -> x0) and the plugin-approvals
typecheck exited 2 with TS1360 (the map does not satisfy the Record type
whose key union now includes `"missed"`). That shows the check read the
rebuilt `.d.ts`. The line was then restored with `git checkout HEAD --`:
`git diff HEAD` is empty and the HEAD blob hash matches.
## Gates
`node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` derived 116 families. Each one ran with its
exit code captured before any pipe, and `--ran` reconciled the record:
`116 derived famil(ies) accounted for — 113 run, 3 NOT-MEASURED`, 0
unrun, `--ran` exit 0. The three NOT MEASURED families all exited 3
(PREREQUISITE NOT MET) because they need built output from packages
outside this diff's closure. CI measures them:
- `check:skill-examples` needs the client SDK `dist`.
- `check:i18n` needs the workspace CLI `dist`.
- `check:dual-build-cjs-loads` needs a whole-repo build.
`pnpm --filter @objectstack/spec check:generated` passes after the
`gen:docs` regeneration (`check:api-surface`, `check:authorable-surface`
and `check:docs` are among the 113 that ran green). The full farm is
CI's.
## Acceptance notes
- The member has no producer until the services PR for #25235 lands.
This is the same short producer-less window that `refused` had.
- Contract review of record is owed before the queue
(`needs:contract-review`, per the claim).
---
_Generated by [Claude
Code](https://claude.ai/code/session_01B2EeooonSXrANpkpgUSfFZ)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent fb63d39 commit d12e650
6 files changed
Lines changed: 48 additions & 6 deletions
File tree
- .changeset
- content/docs/references
- api
- automation
- packages
- plugins/plugin-approvals/src
- spec/src/automation
| 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 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
860 | 860 | | |
861 | 861 | | |
862 | 862 | | |
863 | | - | |
| 863 | + | |
864 | 864 | | |
865 | 865 | | |
866 | 866 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
104 | 104 | | |
105 | 105 | | |
106 | 106 | | |
107 | | - | |
| 107 | + | |
108 | 108 | | |
109 | 109 | | |
110 | 110 | | |
| |||
177 | 177 | | |
178 | 178 | | |
179 | 179 | | |
| 180 | + | |
180 | 181 | | |
181 | 182 | | |
182 | 183 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
529 | 529 | | |
530 | 530 | | |
531 | 531 | | |
| 532 | + | |
| 533 | + | |
| 534 | + | |
532 | 535 | | |
533 | 536 | | |
534 | 537 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
18 | 18 | | |
19 | 19 | | |
20 | 20 | | |
21 | | - | |
| 21 | + | |
22 | 22 | | |
23 | 23 | | |
24 | 24 | | |
25 | 25 | | |
26 | 26 | | |
27 | | - | |
28 | | - | |
29 | | - | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
30 | 31 | | |
31 | 32 | | |
32 | 33 | | |
| |||
35 | 36 | | |
36 | 37 | | |
37 | 38 | | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
38 | 42 | | |
39 | 43 | | |
40 | 44 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
36 | 36 | | |
37 | 37 | | |
38 | 38 | | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
39 | 54 | | |
40 | 55 | | |
41 | 56 | | |
| |||
0 commit comments