@sensigo/realm 0.27.0 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/engine/claim-liveness.d.ts +59 -11
- package/dist/engine/claim-liveness.d.ts.map +1 -1
- package/dist/engine/claim-liveness.js +83 -19
- package/dist/engine/claim-liveness.js.map +1 -1
- package/dist/engine/execution-loop.d.ts.map +1 -1
- package/dist/engine/execution-loop.js +141 -13
- package/dist/engine/execution-loop.js.map +1 -1
- package/dist/evidence/snapshot.d.ts +11 -1
- package/dist/evidence/snapshot.d.ts.map +1 -1
- package/dist/evidence/snapshot.js +1 -0
- package/dist/evidence/snapshot.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/types/run-record.d.ts +27 -5
- package/dist/types/run-record.d.ts.map +1 -1
- package/dist/types/workflow-definition.d.ts +52 -7
- package/dist/types/workflow-definition.d.ts.map +1 -1
- package/dist/types/workflow-definition.js +15 -0
- package/dist/types/workflow-definition.js.map +1 -1
- package/dist/workflow/diagnostics.d.ts +15 -6
- package/dist/workflow/diagnostics.d.ts.map +1 -1
- package/dist/workflow/diagnostics.js +16 -8
- package/dist/workflow/diagnostics.js.map +1 -1
- package/dist/workflow/yaml-loader.d.ts.map +1 -1
- package/dist/workflow/yaml-loader.js +108 -6
- package/dist/workflow/yaml-loader.js.map +1 -1
- package/package.json +1 -1
|
@@ -67,7 +67,44 @@ export interface RetryConfig {
|
|
|
67
67
|
base_delay_ms?: number;
|
|
68
68
|
/** Cap on the computed backoff delay. When set, no single delay exceeds this value. */
|
|
69
69
|
max_delay_ms?: number;
|
|
70
|
+
/**
|
|
71
|
+
* Opt in to retrying this step's own `STEP_TIMEOUT` in place, consuming a normal retry attempt
|
|
72
|
+
* (issue #140). Legal ONLY when the step also declares `idempotent: true` (E1 — hard error at
|
|
73
|
+
* load otherwise; the engine independently re-checks the same conjunct at dispatch time). A
|
|
74
|
+
* timeout-retry can run CONCURRENTLY with the still-in-flight original attempt (the aborted
|
|
75
|
+
* transport request may still be executing remotely) — `on_timeout: true` is the author's
|
|
76
|
+
* explicit attestation that any number of concurrent executions, including a PARTIAL PRIOR
|
|
77
|
+
* APPLICATION (a committed prefix left by that still-in-flight attempt), are harmless. This
|
|
78
|
+
* claims MORE than `idempotent`'s base (sequential re-apply) guarantee — declare both
|
|
79
|
+
* explicitly; the engine infers neither from the other. Absent/false ⇒ a timeout stays
|
|
80
|
+
* terminal (`retryable: false`), byte-identical to pre-#140 behavior.
|
|
81
|
+
*/
|
|
82
|
+
on_timeout?: boolean;
|
|
83
|
+
/**
|
|
84
|
+
* Total wall-clock budget, in seconds, across every attempt of this step (issue #140,
|
|
85
|
+
* Temporal-ScheduleToClose-style) — bounds `max_attempts × per-attempt-timeout` (plus the
|
|
86
|
+
* declared backoffs and any runtime rate-limit `retry_after` sleep) from growing unbounded.
|
|
87
|
+
* Standalone-legal: does NOT require `on_timeout`. **AMENDED default:** when absent, every
|
|
88
|
+
* retry-configured `execution: 'auto'` step is capped at the shared worst-case-schedule
|
|
89
|
+
* formula (`max_attempts × the step's own per-attempt timeout + the declared backoffs between
|
|
90
|
+
* attempts` — the same formula the claim horizon uses) — so the default cap always equals the
|
|
91
|
+
* step's own declared schedule and binds only when a runtime wait pushes an attempt's actual
|
|
92
|
+
* wall-clock MATERIALLY past that schedule (event-loop scheduling overhead is charged to the
|
|
93
|
+
* budget too — negligible at production scales; a step with no `retry:` block has no cap, as
|
|
94
|
+
* there is nothing to bound). When the cap is reached mid-schedule, the step settles as
|
|
95
|
+
* `STEP_RETRY_EXHAUSTED` with `exhausted_by: 'total_timeout'` instead of sleeping past it.
|
|
96
|
+
* Positive integer (E2) — same convention as `timeout_seconds`. Inert on a non-`execution:
|
|
97
|
+
* 'auto'` step (W5 warns) — the cap only bounds `auto` dispatch, which is the only dispatch
|
|
98
|
+
* ever wrapped in a timeout.
|
|
99
|
+
*/
|
|
100
|
+
total_timeout_seconds?: number;
|
|
70
101
|
}
|
|
102
|
+
/**
|
|
103
|
+
* Every key RetryConfig declares. Used by the YAML loader (issue #140) to warn when a `retry:`
|
|
104
|
+
* block declares a key that isn't recognized (misspelling, or a stale field) — same non-breaking
|
|
105
|
+
* posture as KNOWN_STEP_KEYS/KNOWN_WORKFLOW_KEYS (issue #144/#169).
|
|
106
|
+
*/
|
|
107
|
+
export declare const KNOWN_RETRY_KEYS: readonly ["max_attempts", "backoff", "base_delay_ms", "max_delay_ms", "on_timeout", "total_timeout_seconds"];
|
|
71
108
|
/**
|
|
72
109
|
* Controls when a step becomes eligible based on its dependencies' outcomes.
|
|
73
110
|
* Default: 'all_success'.
|
|
@@ -140,13 +177,21 @@ export interface StepDefinition {
|
|
|
140
177
|
*/
|
|
141
178
|
on_outcome?: FinalizerTrigger | FinalizerTrigger[];
|
|
142
179
|
/**
|
|
143
|
-
* Advisory hint (issue #101 Phase 2) that this step's handler is safe to re-execute
|
|
144
|
-
* READ-ONLY and WIDEN-ONLY: it does
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
180
|
+
* Advisory hint (issue #101 Phase 2) that this step's handler is safe to re-execute
|
|
181
|
+
* SEQUENTIALLY. It is READ-ONLY and WIDEN-ONLY: declared alone it does nothing to normal
|
|
182
|
+
* execution and never forces an outcome — it only *permits* two separate opt-in mechanisms,
|
|
183
|
+
* each gated by its OWN explicit declaration:
|
|
184
|
+
* 1. The bounded-time auto-reclaim allow-list (`realm run reclaim --all`). A concrete
|
|
185
|
+
* `claims[S].deadline` is still required, so this function is inert on a step in a
|
|
186
|
+
* workflow WITH finalizer steps (those write `deadline: null` → `claim_unknown_age` →
|
|
187
|
+
* never cron-reclaimable; use `realm run reclaim --step <id> --force` there instead).
|
|
188
|
+
* 2. Since issue #140, `retry.on_timeout: true` — required there (E1, hard error otherwise)
|
|
189
|
+
* before a timed-out attempt may be retried in place. A timeout-retry can run
|
|
190
|
+
* CONCURRENTLY with the still-in-flight original attempt, so `on_timeout` claims MORE than
|
|
191
|
+
* this hint's base sequential-reapply guarantee — declare both explicitly. Unlike function
|
|
192
|
+
* 1, this GATE function is live in every workflow, finalizer-bearing or not.
|
|
193
|
+
* Absent ⇒ false. Deliberately NOT `orphan_policy` (which would force a fail-seal); `idempotent`
|
|
194
|
+
* only ever *permits*, never forces, either mechanism.
|
|
150
195
|
*/
|
|
151
196
|
idempotent?: boolean;
|
|
152
197
|
uses_service?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflow-definition.d.ts","sourceRoot":"","sources":["../../src/types/workflow-definition.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEtD,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,WAAW,CAAC;AAErE;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG,UAAU,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;AAExE,MAAM,WAAW,cAAc;IAC7B,wDAAwD;IACxD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kEAAkE;IAClE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,gBAAgB,GAAG,iBAAiB,GAAG,gBAAgB,CAAC;AAE1F,MAAM,MAAM,YAAY,GAAG,kBAAkB,GAAG,gBAAgB,GAAG,gBAAgB,CAAC;AAEpF,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACxC,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,4EAA4E;IAC5E,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,kFAAkF;IAClF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,YAAY,CAAC;IACpB,UAAU,CAAC,EAAE,eAAe,CAAC;CAC9B;AAED,oDAAoD;AACpD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,+DAA+D;AAC/D,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACvC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,QAAQ,GAAG,aAAa,GAAG,OAAO,CAAC;IAC7C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uFAAuF;IACvF,YAAY,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"workflow-definition.d.ts","sourceRoot":"","sources":["../../src/types/workflow-definition.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every key RetryConfig declares. Used by the YAML loader (issue #140) to warn when a `retry:`
|
|
3
|
+
* block declares a key that isn't recognized (misspelling, or a stale field) — same non-breaking
|
|
4
|
+
* posture as KNOWN_STEP_KEYS/KNOWN_WORKFLOW_KEYS (issue #144/#169).
|
|
5
|
+
*/
|
|
6
|
+
export const KNOWN_RETRY_KEYS = [
|
|
7
|
+
'max_attempts',
|
|
8
|
+
'backoff',
|
|
9
|
+
'base_delay_ms',
|
|
10
|
+
'max_delay_ms',
|
|
11
|
+
'on_timeout',
|
|
12
|
+
'total_timeout_seconds',
|
|
13
|
+
];
|
|
14
|
+
const _retryKeysMissingCheck = true;
|
|
15
|
+
const _retryKeysExtraCheck = true;
|
|
1
16
|
/**
|
|
2
17
|
* Every key StepDefinition declares (it has no runtime-only fields — everything on a step is
|
|
3
18
|
* authored in YAML). Used by the YAML loader (issue #144) to warn when a step declares a key
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflow-definition.js","sourceRoot":"","sources":["../../src/types/workflow-definition.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"workflow-definition.js","sourceRoot":"","sources":["../../src/types/workflow-definition.ts"],"names":[],"mappings":"AAkHA;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,cAAc;IACd,SAAS;IACT,eAAe;IACf,cAAc;IACd,YAAY;IACZ,uBAAuB;CACf,CAAC;AAMX,MAAM,sBAAsB,GAE+C,IAAI,CAAC;AAChF,MAAM,oBAAoB,GAEyD,IAAI,CAAC;AA4OxF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,aAAa;IACb,WAAW;IACX,YAAY;IACZ,cAAc;IACd,MAAM;IACN,cAAc;IACd,eAAe;IACf,YAAY;IACZ,YAAY;IACZ,cAAc;IACd,gBAAgB;IAChB,WAAW;IACX,WAAW;IACX,SAAS;IACT,QAAQ;IACR,cAAc;IACd,eAAe;IACf,cAAc;IACd,uBAAuB;IACvB,eAAe;IACf,OAAO;IACP,iBAAiB;IACjB,OAAO;IACP,cAAc;IACd,QAAQ;IACR,SAAS;IACT,cAAc;IACd,MAAM;IACN,eAAe;IACf,OAAO;IACP,gBAAgB;IAChB,aAAa;IACb,cAAc;CACN,CAAC;AAQX,MAAM,qBAAqB,GAEiD,IAAI,CAAC;AACjF,MAAM,mBAAmB,GAE2D,IAAI,CAAC;AAoGzF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,IAAI;IACJ,MAAM;IACN,aAAa;IACb,SAAS;IACT,eAAe;IACf,UAAU;IACV,UAAU;IACV,aAAa;IACb,WAAW;IACX,OAAO;IACP,cAAc;IACd,YAAY;IACZ,kBAAkB;IAClB,iBAAiB;IACjB,SAAS;CACD,CAAC;AAEX;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG;IACxC,YAAY;IACZ,YAAY;IACZ,mBAAmB;IACnB,gBAAgB;IAChB,QAAQ;IACR,OAAO;IACP,OAAO;CACC,CAAC;AAYX,MAAM,yBAAyB,GAKvB,IAAI,CAAC;AACb,MAAM,uBAAuB,GAKrB,IAAI,CAAC;AACb,MAAM,yBAAyB,GAE4D,IAAI,CAAC"}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* emit. Deliberately excludes ORPHANED_MANIFEST — that condition already throws a WorkflowError
|
|
4
4
|
* (`Invalid:` + exit 1) at the CLI layer; it is a hard error, never a warning.
|
|
5
5
|
*/
|
|
6
|
-
export type WarningCode = 'UNKNOWN_WORKFLOW_KEY' | 'UNKNOWN_STEP_KEY' | 'UNKNOWN_CREATE_WORKFLOW_KEY' | 'IDEMPOTENT_INERT_IN_FINALIZER' | 'DUAL_SCHEMA_DECLARED' | 'RETRY_NO_TIMEOUT' | 'EXTENSION_SENTINEL';
|
|
6
|
+
export type WarningCode = 'UNKNOWN_WORKFLOW_KEY' | 'UNKNOWN_STEP_KEY' | 'UNKNOWN_CREATE_WORKFLOW_KEY' | 'IDEMPOTENT_INERT_IN_FINALIZER' | 'DUAL_SCHEMA_DECLARED' | 'RETRY_NO_TIMEOUT' | 'EXTENSION_SENTINEL' | 'UNKNOWN_RETRY_KEY' | 'ON_TIMEOUT_SINGLE_ATTEMPT' | 'TOTAL_TIMEOUT_BELOW_ATTEMPT' | 'TOTAL_TIMEOUT_NON_AUTO';
|
|
7
7
|
/**
|
|
8
8
|
* A single structured diagnostic. `message` is the full human-readable text (matching, for the
|
|
9
9
|
* three unknown-key codes, exactly what `renderLoaderWarning` would independently reconstruct
|
|
@@ -46,18 +46,27 @@ export declare function findUnknownKeys(obj: Record<string, unknown>, allowList:
|
|
|
46
46
|
code: WarningCode;
|
|
47
47
|
id?: string;
|
|
48
48
|
step?: string;
|
|
49
|
+
/**
|
|
50
|
+
* Overrides the "not a recognized ___ field" noun independently of `scope` — e.g.
|
|
51
|
+
* UNKNOWN_RETRY_KEY keeps `scope: 'step'` (the LoaderWarning's own scope union has no 'retry'
|
|
52
|
+
* value) but reads "not a recognized retry field", not "step field". Defaults to `scope`,
|
|
53
|
+
* byte-identical to pre-#140 behavior for every other unknown-key code.
|
|
54
|
+
*/
|
|
55
|
+
noun?: string;
|
|
49
56
|
}): LoaderWarning[];
|
|
50
57
|
/**
|
|
51
58
|
* The SINGLE source of the `⚠ ` line format — every printer (the core plain wrappers in
|
|
52
59
|
* yaml-loader.ts, and the CLI's `printLoaderWarnings` helper) renders through this, never by
|
|
53
60
|
* hand-rolling a `⚠ ` string itself.
|
|
54
61
|
*
|
|
55
|
-
* The
|
|
62
|
+
* The four unknown-key codes are templated fresh from the structured fields (so the
|
|
56
63
|
* `did_you_mean` suggestion is appended only when present) and always carry the `⚠ ` prefix —
|
|
57
|
-
* byte-identical to the pre-#169 console.warn text
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
64
|
+
* byte-identical to the pre-#169 console.warn text (UNKNOWN_RETRY_KEY, issue #140, follows the
|
|
65
|
+
* same rendering exactly, just with a 'retry' noun instead of 'step'/'workflow'). Every other code
|
|
66
|
+
* (IDEMPOTENT_INERT_IN_FINALIZER, DUAL_SCHEMA_DECLARED, RETRY_NO_TIMEOUT, EXTENSION_SENTINEL,
|
|
67
|
+
* ON_TIMEOUT_SINGLE_ATTEMPT, TOTAL_TIMEOUT_BELOW_ATTEMPT, TOTAL_TIMEOUT_NON_AUTO) returns
|
|
68
|
+
* `message` verbatim: these are free-text warnings whose exact current prefix (or lack of one) is
|
|
69
|
+
* preserved byte-for-byte by whatever constructed them, not re-derived here.
|
|
61
70
|
*/
|
|
62
71
|
export declare function renderLoaderWarning(w: LoaderWarning): string;
|
|
63
72
|
//# sourceMappingURL=diagnostics.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../../src/workflow/diagnostics.ts"],"names":[],"mappings":"AAQA;;;;GAIG;AACH,MAAM,MAAM,WAAW,GACnB,sBAAsB,GACtB,kBAAkB,GAClB,6BAA6B,GAC7B,+BAA+B,GAC/B,sBAAsB,GACtB,kBAAkB,GAClB,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../../src/workflow/diagnostics.ts"],"names":[],"mappings":"AAQA;;;;GAIG;AACH,MAAM,MAAM,WAAW,GACnB,sBAAsB,GACtB,kBAAkB,GAClB,6BAA6B,GAC7B,+BAA+B,GAC/B,sBAAsB,GACtB,kBAAkB,GAClB,oBAAoB,GAEpB,mBAAmB,GACnB,2BAA2B,GAC3B,6BAA6B,GAC7B,wBAAwB,CAAC;AAE7B;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,WAAW,CAAC;IAClB,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,UAAU,GAAG,MAAM,CAAC;IAC3B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAYhE,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,WAAW,EACjB,MAAM,GAAE,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAkB,GAC7D,MAAM,GAAG,OAAO,CAElB;AA8DD;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,SAAS,EAAE,SAAS,MAAM,EAAE,EAC5B,GAAG,EAAE;IACH,KAAK,EAAE,UAAU,GAAG,MAAM,CAAC;IAC3B,IAAI,EAAE,WAAW,CAAC;IAClB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,GACA,aAAa,EAAE,CAqBjB;AASD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,aAAa,GAAG,MAAM,CAK5D"}
|
|
@@ -20,6 +20,10 @@ export const DEFAULT_POLICY = {
|
|
|
20
20
|
DUAL_SCHEMA_DECLARED: 'warn',
|
|
21
21
|
RETRY_NO_TIMEOUT: 'warn',
|
|
22
22
|
EXTENSION_SENTINEL: 'warn',
|
|
23
|
+
UNKNOWN_RETRY_KEY: 'warn',
|
|
24
|
+
ON_TIMEOUT_SINGLE_ATTEMPT: 'warn',
|
|
25
|
+
TOTAL_TIMEOUT_BELOW_ATTEMPT: 'warn',
|
|
26
|
+
TOTAL_TIMEOUT_NON_AUTO: 'warn',
|
|
23
27
|
};
|
|
24
28
|
/**
|
|
25
29
|
* Pure lookup: resolves a warning code's severity against a policy table. `--strict` passes an
|
|
@@ -74,14 +78,14 @@ function closestKey(key, allowList) {
|
|
|
74
78
|
return best !== undefined && bestDistance <= threshold ? best : undefined;
|
|
75
79
|
}
|
|
76
80
|
/** Builds the templated "unknown key" message text (everything after the `⚠ ` prefix). */
|
|
77
|
-
function renderUnknownKeyMessage(
|
|
81
|
+
function renderUnknownKeyMessage(target, key, didYouMean, noun) {
|
|
78
82
|
// Punctuation deliberately differs by form, matching the design's own literal examples exactly:
|
|
79
83
|
// the no-suggestion form ends with a period (byte-identical to the pre-#169 text); the
|
|
80
84
|
// did_you_mean form's trailing '?)' is the sentence's natural end — no additional period.
|
|
81
85
|
if (didYouMean !== undefined) {
|
|
82
86
|
return `${target}: unknown key '${key}' — ignored (did you mean '${didYouMean}'?)`;
|
|
83
87
|
}
|
|
84
|
-
return `${target}: unknown key '${key}' — ignored (not a recognized ${
|
|
88
|
+
return `${target}: unknown key '${key}' — ignored (not a recognized ${noun} field).`;
|
|
85
89
|
}
|
|
86
90
|
/**
|
|
87
91
|
* Finds every own-key of `obj` not present in `allowList` and returns one LoaderWarning per
|
|
@@ -92,6 +96,7 @@ function renderUnknownKeyMessage(scope, target, key, didYouMean) {
|
|
|
92
96
|
export function findUnknownKeys(obj, allowList, ctx) {
|
|
93
97
|
const warnings = [];
|
|
94
98
|
const target = ctx.scope === 'workflow' ? `workflow '${ctx.id ?? '<unknown>'}'` : `step '${ctx.step}'`;
|
|
99
|
+
const noun = ctx.noun ?? ctx.scope;
|
|
95
100
|
for (const key of Object.keys(obj)) {
|
|
96
101
|
if (allowList.includes(key))
|
|
97
102
|
continue;
|
|
@@ -99,7 +104,7 @@ export function findUnknownKeys(obj, allowList, ctx) {
|
|
|
99
104
|
const warning = {
|
|
100
105
|
code: ctx.code,
|
|
101
106
|
severity: resolveSeverity(ctx.code),
|
|
102
|
-
message: renderUnknownKeyMessage(
|
|
107
|
+
message: renderUnknownKeyMessage(target, key, did_you_mean, noun),
|
|
103
108
|
scope: ctx.scope,
|
|
104
109
|
key,
|
|
105
110
|
};
|
|
@@ -117,18 +122,21 @@ const UNKNOWN_KEY_CODES = new Set([
|
|
|
117
122
|
'UNKNOWN_WORKFLOW_KEY',
|
|
118
123
|
'UNKNOWN_STEP_KEY',
|
|
119
124
|
'UNKNOWN_CREATE_WORKFLOW_KEY',
|
|
125
|
+
'UNKNOWN_RETRY_KEY',
|
|
120
126
|
]);
|
|
121
127
|
/**
|
|
122
128
|
* The SINGLE source of the `⚠ ` line format — every printer (the core plain wrappers in
|
|
123
129
|
* yaml-loader.ts, and the CLI's `printLoaderWarnings` helper) renders through this, never by
|
|
124
130
|
* hand-rolling a `⚠ ` string itself.
|
|
125
131
|
*
|
|
126
|
-
* The
|
|
132
|
+
* The four unknown-key codes are templated fresh from the structured fields (so the
|
|
127
133
|
* `did_you_mean` suggestion is appended only when present) and always carry the `⚠ ` prefix —
|
|
128
|
-
* byte-identical to the pre-#169 console.warn text
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
*
|
|
134
|
+
* byte-identical to the pre-#169 console.warn text (UNKNOWN_RETRY_KEY, issue #140, follows the
|
|
135
|
+
* same rendering exactly, just with a 'retry' noun instead of 'step'/'workflow'). Every other code
|
|
136
|
+
* (IDEMPOTENT_INERT_IN_FINALIZER, DUAL_SCHEMA_DECLARED, RETRY_NO_TIMEOUT, EXTENSION_SENTINEL,
|
|
137
|
+
* ON_TIMEOUT_SINGLE_ATTEMPT, TOTAL_TIMEOUT_BELOW_ATTEMPT, TOTAL_TIMEOUT_NON_AUTO) returns
|
|
138
|
+
* `message` verbatim: these are free-text warnings whose exact current prefix (or lack of one) is
|
|
139
|
+
* preserved byte-for-byte by whatever constructed them, not re-derived here.
|
|
132
140
|
*/
|
|
133
141
|
export function renderLoaderWarning(w) {
|
|
134
142
|
if (UNKNOWN_KEY_CODES.has(w.code)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diagnostics.js","sourceRoot":"","sources":["../../src/workflow/diagnostics.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,EAAE;AACF,4FAA4F;AAC5F,8FAA8F;AAC9F,gGAAgG;AAChG,gGAAgG;AAChG,+FAA+F;
|
|
1
|
+
{"version":3,"file":"diagnostics.js","sourceRoot":"","sources":["../../src/workflow/diagnostics.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"yaml-loader.d.ts","sourceRoot":"","sources":["../../src/workflow/yaml-loader.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,kBAAkB,EAGnB,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"yaml-loader.d.ts","sourceRoot":"","sources":["../../src/workflow/yaml-loader.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,kBAAkB,EAGnB,MAAM,iCAAiC,CAAC;AAOzC,OAAO,EAIL,KAAK,aAAa,EACnB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AA8FnE,iFAAiF;AACjF,eAAO,MAAM,+BAA+B,IAAI,CAAC;AAuEjD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAUjD;AA4JD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,iBAAiB,GAC3B,kBAAkB,CAIpB;AAED;;;;GAIG;AACH,wBAAgB,mCAAmC,CACjD,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,iBAAiB,GAC3B;IAAE,UAAU,EAAE,kBAAkB,CAAC;IAAC,QAAQ,EAAE,aAAa,EAAE,CAAA;CAAE,CAE/D;AAED;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,iBAAiB,GAC3B,kBAAkB,CAMpB;AAED;;;GAGG;AACH,wBAAgB,qCAAqC,CACnD,OAAO,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,iBAAiB,GAC3B;IAAE,UAAU,EAAE,kBAAkB,CAAC;IAAC,QAAQ,EAAE,aAAa,EAAE,CAAA;CAAE,CAE/D"}
|
|
@@ -4,12 +4,13 @@ import { dirname, resolve, join, isAbsolute } from 'node:path';
|
|
|
4
4
|
import { createHash } from 'node:crypto';
|
|
5
5
|
import { load } from 'js-yaml';
|
|
6
6
|
import { Ajv } from 'ajv';
|
|
7
|
-
import { KNOWN_STEP_KEYS, KNOWN_WORKFLOW_KEYS } from '../types/workflow-definition.js';
|
|
7
|
+
import { KNOWN_STEP_KEYS, KNOWN_WORKFLOW_KEYS, KNOWN_RETRY_KEYS, } from '../types/workflow-definition.js';
|
|
8
8
|
import { WorkflowError } from '../types/workflow-error.js';
|
|
9
9
|
import { findUnknownKeys, renderLoaderWarning, resolveSeverity, } from './diagnostics.js';
|
|
10
10
|
import { resolveTemplates } from './template-resolver.js';
|
|
11
11
|
import { normalizeTriggerFilter, validateTriggerStructure } from './trigger-schema.js';
|
|
12
12
|
import { splitComparison, isPathShaped } from '../engine/comparison-expr.js';
|
|
13
|
+
import { DEFAULT_EXECUTION_TIMEOUT_SECONDS } from '../engine/claim-liveness.js';
|
|
13
14
|
/**
|
|
14
15
|
* Validate one condition leaf at load time using the shared quote-aware splitter (the SAME split
|
|
15
16
|
* used at runtime). Rejects compound `and`/`or`, multiple operators, and non-path LHS. For `when`,
|
|
@@ -622,17 +623,31 @@ function parseWorkflowString(content, registry, opts) {
|
|
|
622
623
|
errors.push(`Step '${stepName}': 'idempotent' is only valid on execution: auto steps`);
|
|
623
624
|
}
|
|
624
625
|
// WARN (do not reject): an idempotent auto step in a finalizer-bearing workflow gets
|
|
625
|
-
// `deadline: null` (issue #101), so the
|
|
626
|
-
// select it. The author should know it stays per-step-manual-reclaim-only.
|
|
626
|
+
// `deadline: null` (issue #101), so the RECLAIM function is inert — `realm run reclaim --all`
|
|
627
|
+
// can never select it. The author should know it stays per-step-manual-reclaim-only.
|
|
628
|
+
//
|
|
629
|
+
// Issue #140 C5 (variant-aware reword): `idempotent` now has a SECOND function — gating
|
|
630
|
+
// `retry.on_timeout` — and that GATE function is live in every workflow, finalizer-bearing or
|
|
631
|
+
// not (shouldEnforceTimeout has no finalizer conjunct). A single unconditional message would
|
|
632
|
+
// either keep a falsehood (claiming idempotent is wholly inert when on_timeout is ALSO
|
|
633
|
+
// declared) or gratuitously mention a gate the author never declared (idempotent-alone case)
|
|
634
|
+
// — so the message is keyed on `step.retry?.on_timeout`, pinned by both-variant loader tests.
|
|
627
635
|
if (step['idempotent'] === true && step['execution'] === 'auto' && hasFinalizerStep) {
|
|
636
|
+
const stepRetry = typeof step['retry'] === 'object' && step['retry'] !== null
|
|
637
|
+
? step['retry']
|
|
638
|
+
: undefined;
|
|
639
|
+
const onTimeoutDeclared = stepRetry?.['on_timeout'] === true;
|
|
628
640
|
warnings.push({
|
|
629
641
|
code: 'IDEMPOTENT_INERT_IN_FINALIZER',
|
|
630
642
|
severity: resolveSeverity('IDEMPOTENT_INERT_IN_FINALIZER'),
|
|
631
643
|
scope: 'step',
|
|
632
644
|
step: stepName,
|
|
633
|
-
message: `Step '${stepName}': 'idempotent: true'
|
|
634
|
-
`carries no deadline, so 'realm run reclaim --all' can never select
|
|
635
|
-
`'realm run reclaim --step ${stepName} --force'
|
|
645
|
+
message: `Step '${stepName}': 'idempotent: true' cannot enable auto-reclaim in a finalizer-bearing ` +
|
|
646
|
+
`workflow (its claim carries no deadline, so 'realm run reclaim --all' can never select ` +
|
|
647
|
+
`it). Recover it with 'realm run reclaim <run-id> --step ${stepName} --force'.` +
|
|
648
|
+
(onTimeoutDeclared
|
|
649
|
+
? ` Its 'retry.on_timeout' gate role is unaffected — timeout retries remain active.`
|
|
650
|
+
: ''),
|
|
636
651
|
});
|
|
637
652
|
}
|
|
638
653
|
// output_schema is only valid on execution: agent steps.
|
|
@@ -684,6 +699,15 @@ function parseWorkflowString(content, registry, opts) {
|
|
|
684
699
|
}
|
|
685
700
|
else {
|
|
686
701
|
const retry = step['retry'];
|
|
702
|
+
// WARN (do not reject) on an unknown retry-block key — same non-breaking posture as the
|
|
703
|
+
// step/workflow-level checks (issue #140). Noun overridden to 'retry' (not 'step') since
|
|
704
|
+
// this is a nested block, not the step itself.
|
|
705
|
+
warnings.push(...findUnknownKeys(retry, KNOWN_RETRY_KEYS, {
|
|
706
|
+
scope: 'step',
|
|
707
|
+
code: 'UNKNOWN_RETRY_KEY',
|
|
708
|
+
step: stepName,
|
|
709
|
+
noun: 'retry',
|
|
710
|
+
}));
|
|
687
711
|
if ('backoff' in retry &&
|
|
688
712
|
retry['backoff'] !== 'fixed' &&
|
|
689
713
|
retry['backoff'] !== 'linear' &&
|
|
@@ -702,6 +726,84 @@ function parseWorkflowString(content, registry, opts) {
|
|
|
702
726
|
(typeof retry['max_delay_ms'] !== 'number' || retry['max_delay_ms'] < 0)) {
|
|
703
727
|
errors.push(`Step '${stepName}': 'retry.max_delay_ms' must be a non-negative number`);
|
|
704
728
|
}
|
|
729
|
+
// --- issue #140: on_timeout / total_timeout_seconds --------------------------------
|
|
730
|
+
// E3: on_timeout must be a boolean (kills the 'on_timeout: "true"' silent-inert case).
|
|
731
|
+
if ('on_timeout' in retry && typeof retry['on_timeout'] !== 'boolean') {
|
|
732
|
+
errors.push(`Step '${stepName}': 'retry.on_timeout' must be a boolean`);
|
|
733
|
+
}
|
|
734
|
+
// E2: total_timeout_seconds must be a positive integer — same convention as
|
|
735
|
+
// timeout_seconds (0 is rejected here at load; a hand-built definition bypassing the
|
|
736
|
+
// loader may still set 0 and have the engine's resolveCapMs honor it as a present cap).
|
|
737
|
+
if ('total_timeout_seconds' in retry &&
|
|
738
|
+
(!Number.isInteger(retry['total_timeout_seconds']) ||
|
|
739
|
+
retry['total_timeout_seconds'] <= 0)) {
|
|
740
|
+
errors.push(`Step '${stepName}': 'retry.total_timeout_seconds' must be a positive integer`);
|
|
741
|
+
}
|
|
742
|
+
// E1: on_timeout: true requires idempotent: true — declared, never inferred. Strict
|
|
743
|
+
// `=== true` on both loci, provably matching the engine's own conjunct.
|
|
744
|
+
if (retry['on_timeout'] === true && step['idempotent'] !== true) {
|
|
745
|
+
errors.push(`Step '${stepName}': 'retry.on_timeout: true' requires 'idempotent: true' declared ` +
|
|
746
|
+
`on the step — a timeout-retry can run concurrently with the still-in-flight ` +
|
|
747
|
+
`original attempt, so the step must explicitly attest that any partial prior ` +
|
|
748
|
+
`application is harmless to re-apply. Declare 'idempotent: true' or remove ` +
|
|
749
|
+
`'on_timeout'.`);
|
|
750
|
+
}
|
|
751
|
+
// W5 (CAP-ONLY advisory — the on_timeout half of this is already an E1 hard error, so
|
|
752
|
+
// it never reaches here as a warning): the total-time cap only bounds `execution: 'auto'`
|
|
753
|
+
// dispatch — inert on any other step type that legally declares `retry:` today.
|
|
754
|
+
if (step['execution'] !== 'auto' && retry['total_timeout_seconds'] !== undefined) {
|
|
755
|
+
warnings.push({
|
|
756
|
+
code: 'TOTAL_TIMEOUT_NON_AUTO',
|
|
757
|
+
severity: resolveSeverity('TOTAL_TIMEOUT_NON_AUTO'),
|
|
758
|
+
scope: 'step',
|
|
759
|
+
step: stepName,
|
|
760
|
+
message: `Step '${stepName}': 'retry.total_timeout_seconds' is inert on execution: ` +
|
|
761
|
+
`'${String(step['execution'])}' steps — the cap only bounds 'execution: auto' ` +
|
|
762
|
+
`dispatch, which is the only dispatch ever wrapped in a timeout.`,
|
|
763
|
+
});
|
|
764
|
+
}
|
|
765
|
+
// W1: on_timeout with an effective max_attempts of 1 (explicit OR absent, since the
|
|
766
|
+
// loader admits an absent max_attempts and the engine then defaults it to 1) — there is
|
|
767
|
+
// no second attempt for the opt-in to retry into.
|
|
768
|
+
const effectiveMaxAttempts = typeof retry['max_attempts'] === 'number' ? retry['max_attempts'] : 1;
|
|
769
|
+
if (retry['on_timeout'] === true && effectiveMaxAttempts === 1) {
|
|
770
|
+
warnings.push({
|
|
771
|
+
code: 'ON_TIMEOUT_SINGLE_ATTEMPT',
|
|
772
|
+
severity: resolveSeverity('ON_TIMEOUT_SINGLE_ATTEMPT'),
|
|
773
|
+
scope: 'step',
|
|
774
|
+
step: stepName,
|
|
775
|
+
message: `Step '${stepName}': 'retry.on_timeout: true' has no effect with an effective ` +
|
|
776
|
+
`'max_attempts' of 1 — there is no second attempt to retry into.`,
|
|
777
|
+
});
|
|
778
|
+
}
|
|
779
|
+
// W2: the cap can never cover even a single full-length attempt — (a) an EXPLICIT cap
|
|
780
|
+
// below an EXPLICIT timeout_seconds, or (b) on_timeout: true with a cap at-or-below the
|
|
781
|
+
// effective per-attempt timeout (retry-defeating: the opt-in can never yield a viable
|
|
782
|
+
// second attempt). Both conditions require an EXPLICIT total_timeout_seconds — the
|
|
783
|
+
// AMENDED default cap (the worst-case schedule) is, by construction, never below a
|
|
784
|
+
// single attempt for max_attempts ≥ 2, so this never fires on the bare 3600s-default
|
|
785
|
+
// population.
|
|
786
|
+
const explicitCapSeconds = typeof retry['total_timeout_seconds'] === 'number'
|
|
787
|
+
? retry['total_timeout_seconds']
|
|
788
|
+
: undefined;
|
|
789
|
+
if (explicitCapSeconds !== undefined) {
|
|
790
|
+
const explicitTimeoutSeconds = typeof step['timeout_seconds'] === 'number' ? step['timeout_seconds'] : undefined;
|
|
791
|
+
const effectivePerAttemptSeconds = explicitTimeoutSeconds ?? DEFAULT_EXECUTION_TIMEOUT_SECONDS;
|
|
792
|
+
const belowExplicitAttempt = explicitTimeoutSeconds !== undefined && explicitCapSeconds < explicitTimeoutSeconds;
|
|
793
|
+
const capTooTightForRetry = retry['on_timeout'] === true && explicitCapSeconds <= effectivePerAttemptSeconds;
|
|
794
|
+
if (belowExplicitAttempt || capTooTightForRetry) {
|
|
795
|
+
warnings.push({
|
|
796
|
+
code: 'TOTAL_TIMEOUT_BELOW_ATTEMPT',
|
|
797
|
+
severity: resolveSeverity('TOTAL_TIMEOUT_BELOW_ATTEMPT'),
|
|
798
|
+
scope: 'step',
|
|
799
|
+
step: stepName,
|
|
800
|
+
message: `Step '${stepName}': 'retry.total_timeout_seconds: ${explicitCapSeconds}' is at ` +
|
|
801
|
+
`or below its own effective per-attempt timeout (${effectivePerAttemptSeconds}s) ` +
|
|
802
|
+
`— the cap can never cover a single full-length attempt, so a retry can never ` +
|
|
803
|
+
`occur before the cap fires.`,
|
|
804
|
+
});
|
|
805
|
+
}
|
|
806
|
+
}
|
|
705
807
|
}
|
|
706
808
|
}
|
|
707
809
|
if ('service_method' in step && !VALID_SERVICE_METHODS.has(step['service_method'])) {
|