@sensigo/realm-cli 0.40.0 → 0.41.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.
Files changed (60) hide show
  1. package/dist/agent/providers/agent-utils.d.ts +37 -13
  2. package/dist/agent/providers/agent-utils.d.ts.map +1 -1
  3. package/dist/agent/providers/agent-utils.js +92 -17
  4. package/dist/agent/providers/agent-utils.js.map +1 -1
  5. package/dist/commands/agent.d.ts +6 -0
  6. package/dist/commands/agent.d.ts.map +1 -1
  7. package/dist/commands/agent.js +28 -4
  8. package/dist/commands/agent.js.map +1 -1
  9. package/dist/commands/drain.d.ts.map +1 -1
  10. package/dist/commands/drain.js +37 -3
  11. package/dist/commands/drain.js.map +1 -1
  12. package/dist/commands/inspect.d.ts.map +1 -1
  13. package/dist/commands/inspect.js +19 -2
  14. package/dist/commands/inspect.js.map +1 -1
  15. package/dist/commands/list.d.ts.map +1 -1
  16. package/dist/commands/list.js +59 -8
  17. package/dist/commands/list.js.map +1 -1
  18. package/dist/commands/listen.d.ts +13 -0
  19. package/dist/commands/listen.d.ts.map +1 -1
  20. package/dist/commands/listen.js +36 -4
  21. package/dist/commands/listen.js.map +1 -1
  22. package/dist/commands/register.d.ts +25 -0
  23. package/dist/commands/register.d.ts.map +1 -1
  24. package/dist/commands/register.js +88 -20
  25. package/dist/commands/register.js.map +1 -1
  26. package/dist/commands/respond.d.ts.map +1 -1
  27. package/dist/commands/respond.js +23 -1
  28. package/dist/commands/respond.js.map +1 -1
  29. package/dist/commands/run.d.ts +34 -0
  30. package/dist/commands/run.d.ts.map +1 -1
  31. package/dist/commands/run.js +225 -11
  32. package/dist/commands/run.js.map +1 -1
  33. package/dist/commands/test.d.ts.map +1 -1
  34. package/dist/commands/test.js +48 -8
  35. package/dist/commands/test.js.map +1 -1
  36. package/dist/commands/validate.d.ts +19 -0
  37. package/dist/commands/validate.d.ts.map +1 -1
  38. package/dist/commands/validate.js +354 -82
  39. package/dist/commands/validate.js.map +1 -1
  40. package/dist/commands/watch.d.ts +30 -0
  41. package/dist/commands/watch.d.ts.map +1 -1
  42. package/dist/commands/watch.js +155 -21
  43. package/dist/commands/watch.js.map +1 -1
  44. package/dist/commands/workflow-list.d.ts +16 -0
  45. package/dist/commands/workflow-list.d.ts.map +1 -0
  46. package/dist/commands/workflow-list.js +96 -0
  47. package/dist/commands/workflow-list.js.map +1 -0
  48. package/dist/commands-registry.d.ts.map +1 -1
  49. package/dist/commands-registry.js +2 -0
  50. package/dist/commands-registry.js.map +1 -1
  51. package/dist/extensions/load-project-extensions.d.ts.map +1 -1
  52. package/dist/extensions/load-project-extensions.js +9 -3
  53. package/dist/extensions/load-project-extensions.js.map +1 -1
  54. package/dist/index.js +22 -1
  55. package/dist/index.js.map +1 -1
  56. package/dist/lib/loader-warnings.d.ts +24 -3
  57. package/dist/lib/loader-warnings.d.ts.map +1 -1
  58. package/dist/lib/loader-warnings.js +66 -5
  59. package/dist/lib/loader-warnings.js.map +1 -1
  60. package/package.json +4 -4
@@ -9,9 +9,9 @@ import { Command } from 'commander';
9
9
  import { dirname, join, resolve } from 'node:path';
10
10
  import { readFileSync } from 'node:fs';
11
11
  import { load } from 'js-yaml';
12
- import { loadWorkflowFromStringWithDiagnostics, loadWorkflowFromFileWithDiagnostics, findTrustRoot, WorkflowError, shouldEnforceTimeout, DEFAULT_EXECUTION_TIMEOUT_SECONDS, resolveSeverity, assessStructuredOutputEligibility, renderIneligibleMessage, } from '@sensigo/realm';
12
+ import { loadWorkflowFromStringWithDiagnostics, loadWorkflowFromFileWithDiagnostics, findTrustRoot, WorkflowError, shouldEnforceTimeout, DEFAULT_EXECUTION_TIMEOUT_SECONDS, resolveSeverity, renderLoaderWarning, assessStructuredOutputEligibility, renderIneligibleMessage, JsonWorkflowStore, RUNTIME_ONLY_WORKFLOW_KEYS, VERSION, } from '@sensigo/realm';
13
13
  import { loadProjectExtensions, checkForOrphanedManifests, } from '../extensions/load-project-extensions.js';
14
- import { renderLoadFailure, printLoaderWarnings, rejectOnErrorSeverity, failsStrict, } from '../lib/loader-warnings.js';
14
+ import { renderLoadFailure, renderEscalationLine, printLoaderWarnings, rejectOnErrorSeverity, failsStrict, wrapSentinelWarnings, } from '../lib/loader-warnings.js';
15
15
  /**
16
16
  * Advisory (issue A3, never rejects): an auto step declaring `retry:` but no `timeout_seconds`
17
17
  * has EVERY attempt bounded by the generous DEFAULT_EXECUTION_TIMEOUT_SECONDS default — a hung
@@ -27,7 +27,8 @@ import { renderLoadFailure, printLoaderWarnings, rejectOnErrorSeverity, failsStr
27
27
  * fires). The message is worded to cover both axes without requiring the reader to already know
28
28
  * about the cap.
29
29
  */
30
- function findRetryWithoutExplicitTimeout(definition) {
30
+ /** @internal Exported for testing only. */
31
+ export function findRetryWithoutExplicitTimeout(definition) {
31
32
  const warnings = [];
32
33
  for (const [stepName, step] of Object.entries(definition.steps)) {
33
34
  if (shouldEnforceTimeout(step) &&
@@ -38,7 +39,7 @@ function findRetryWithoutExplicitTimeout(definition) {
38
39
  severity: resolveSeverity('RETRY_NO_TIMEOUT'),
39
40
  scope: 'step',
40
41
  step: stepName,
41
- message: `⚠ Step '${stepName}': declares 'retry' but no 'timeout_seconds' — each attempt is ` +
42
+ message: `Step '${stepName}': declares 'retry' but no 'timeout_seconds' — each attempt is ` +
42
43
  `bounded by the default execution timeout (${DEFAULT_EXECUTION_TIMEOUT_SECONDS}s), and ` +
43
44
  `(absent an explicit 'retry.total_timeout_seconds') the step's overall retry budget ` +
44
45
  `defaults to that same per-attempt bound compounded across every attempt plus backoffs. ` +
@@ -49,15 +50,6 @@ function findRetryWithoutExplicitTimeout(definition) {
49
50
  }
50
51
  return warnings;
51
52
  }
52
- /** Wraps loadProjectExtensions' sentinel-credential warnings as LoaderWarning (issue #169). */
53
- function wrapSentinelWarnings(sentinelWarnings) {
54
- return (sentinelWarnings ?? []).map((message) => ({
55
- code: 'EXTENSION_SENTINEL',
56
- severity: resolveSeverity('EXTENSION_SENTINEL'),
57
- scope: 'workflow',
58
- message: `⚠ ${message}`,
59
- }));
60
- }
61
53
  /**
62
54
  * The single success-path printer BOTH validation branches (extension-free and file-based)
63
55
  * share: prints every accumulated warning, then the summary line. Under `--strict`, a non-empty
@@ -67,9 +59,10 @@ function wrapSentinelWarnings(sentinelWarnings) {
67
59
  */
68
60
  function printValidationOutcome(definition, warnings, strict) {
69
61
  printLoaderWarnings(warnings);
70
- const base = `Valid: ${definition.id} v${definition.version} (${Object.keys(definition.steps).length} steps)`;
62
+ const stepCount = Object.keys(definition.steps).length;
63
+ const base = `Valid: ${definition.id} v${definition.version} (${stepCount} ${stepCount === 1 ? 'step' : 'steps'})`;
71
64
  if (strict && failsStrict(warnings)) {
72
- console.log(`${base} — ${warnings.length} warning(s); failing due to --strict`);
65
+ console.log(`${base} — ${warnings.length} ${warnings.length === 1 ? 'warning' : 'warnings'}; failing due to --strict`);
73
66
  return true;
74
67
  }
75
68
  console.log(base);
@@ -90,16 +83,34 @@ function findReasoningLikeTopLevelProperty(schema) {
90
83
  return Object.keys(properties).find((name) => REASONING_LIKE_PROPERTY.test(name));
91
84
  }
92
85
  /**
93
- * issue #236 (Deliverable 7) — the adoption-without-default-ON nudge. Prints, per
94
- * `execution: 'agent'` step with an effective schema, the migration DELTA on its OWN INFO
95
- * channel: structurally NOT a LoaderWarning (plain `console.log`, never routed through
96
- * `printLoaderWarnings`/the warnings accumulator/`--strict` that stays a hard zero-diff rail on
97
- * `loader-warnings.ts`, since ANY new WarningCode there would auto-fail `validate --strict`).
98
- * Opted-in steps ALSO print here (their own caveats) the same channel, per design [Rv3]. Never
99
- * printed for an ineligible-and-opted-in step: the LOADER already rejected that combination at
100
- * load time, so this function structurally never observes it.
86
+ * issue #236 (Deliverable 7) — the adoption nudge, on validate's own INFO channel. Structurally
87
+ * NOT a LoaderWarning (plain `console.log`, never routed through `printLoaderWarnings`/the
88
+ * warnings accumulator/`--strict` that stays a hard zero-diff rail on `loader-warnings.ts`,
89
+ * since ANY new WarningCode there would auto-fail `validate --strict`).
90
+ *
91
+ * issue #422 reshaped the FORM, not the purpose. It used to print one line per caveat per step,
92
+ * which on a green validate of a file that never mentions structured_output meant fourteen lines
93
+ * (examples/06) or nine (examples/02) of advice nobody asked for. The field's converged answer for
94
+ * adoption discovery on a clean run is one aggregate line plus a named detail command plus a
95
+ * durable silencer — npm fund, cargo's future-incompat report, npm audit; no surveyed tool prints
96
+ * per-item adoption advice on a green run, and npm's RFC 0017 explicitly rejected demoting the
97
+ * class behind a flag instead. So: a summary by default, the full per-step detail behind
98
+ * `--explain`, and `REALM_NO_NUDGE=1` to silence.
99
+ *
100
+ * THE POLICY THAT DECIDES WHICH STEPS ARE LOUD (rustc's attach-to-the-diagnostic rule, made
101
+ * written policy here): advice about config the author DECLARED is a diagnostic and always prints;
102
+ * advice about config they COULD adopt is one line. So an opted-in step's caveats print
103
+ * unconditionally — `--explain` does not gate them and `REALM_NO_NUDGE` does not silence them —
104
+ * while a not-opted-in step's detail is exactly what moves behind the flag.
105
+ *
106
+ * Never printed for an ineligible-and-opted-in step: the LOADER already rejected that combination
107
+ * at load time, so this function structurally never observes it.
101
108
  */
102
- function printStructuredOutputNudge(definition) {
109
+ function printStructuredOutputNudge(definition, opts) {
110
+ // Not-opted-in steps whose detail either renders (--explain) or feeds the summary counts.
111
+ const ready = []; // eligible | eligible_with_caveats
112
+ const withCaveats = []; // the subset of `ready` carrying >=1 caveat
113
+ const oneAway = []; // ineligible
103
114
  for (const [stepName, step] of Object.entries(definition.steps)) {
104
115
  if (step.execution !== 'agent')
105
116
  continue;
@@ -113,35 +124,121 @@ function printStructuredOutputNudge(definition) {
113
124
  ...(step.tools !== undefined ? { tools: step.tools } : {}),
114
125
  });
115
126
  const reasoningProp = findReasoningLikeTopLevelProperty(effectiveSchema);
127
+ // An opted-in step's advice is about DECLARED config: a diagnostic, printed here and now
128
+ // whatever the flags say. It is also EXCLUDED from the summary's census entirely — its
129
+ // surface is this branch, never the aggregate line.
130
+ if (optedIn) {
131
+ if (verdict.verdict !== 'eligible_with_caveats')
132
+ continue;
133
+ for (const caveat of verdict.caveats) {
134
+ console.log(`ℹ Step '${stepName}': structured_output caveat — ${caveat.remediation}`);
135
+ }
136
+ printReasoningAnnotation(stepName, reasoningProp);
137
+ continue;
138
+ }
116
139
  if (verdict.verdict === 'ineligible') {
117
- // Opted-in + ineligible is unreachable (the loader already rejected it) — this is always
118
- // the "here's what you're one step short of" migration nudge for a NOT-opted-in step.
119
- console.log(`ℹ Step '${stepName}': structured_output: strict — one line short: ` +
120
- `${renderIneligibleMessage(verdict.reasons)}`);
140
+ oneAway.push(stepName);
141
+ if (opts.explain) {
142
+ console.log(`ℹ Step '${stepName}': structured_output: strict — one line short: ` +
143
+ `${renderIneligibleMessage(verdict.reasons)}`);
144
+ }
121
145
  continue;
122
146
  }
147
+ ready.push(stepName);
123
148
  if (verdict.verdict === 'eligible_with_caveats') {
124
- const prefix = optedIn
125
- ? `ℹ Step '${stepName}': structured_output caveat`
126
- : `ℹ Step '${stepName}': eligible for structured_output: strict, with caveat`;
127
- for (const caveat of verdict.caveats) {
128
- console.log(`${prefix} ${caveat.remediation}`);
129
- }
130
- if (reasoningProp !== undefined) {
131
- console.log(`ℹ Step '${stepName}': the optional '${reasoningProp}' property looks like a ` +
132
- `reasoning field — see the optional_emission caveat above (position matters: with ` +
133
- `default thinking there is no regression; on non-thinking configurations prefer ` +
134
- `'required' + first property order — see docs/reference/yaml-schema.md).`);
149
+ // `eligible_with_caveats` with zero caveats is unconstructible — the assessor mints that
150
+ // verdict only when it has at least one — so the verdict IS the caveated subset.
151
+ withCaveats.push(stepName);
152
+ if (opts.explain) {
153
+ for (const caveat of verdict.caveats) {
154
+ console.log(`ℹ Step '${stepName}': eligible for structured_output: strict, with caveat — ` +
155
+ `${caveat.remediation}`);
156
+ }
157
+ printReasoningAnnotation(stepName, reasoningProp);
135
158
  }
136
159
  continue;
137
160
  }
138
161
  // eligible, zero caveats — NEVER printed bare (census: this is a rare, fully-required
139
162
  // schema). Always paired with the concrete next step.
140
- if (!optedIn) {
163
+ if (opts.explain) {
141
164
  console.log(`ℹ Step '${stepName}': eligible for structured_output: strict — add ` +
142
165
  `'structured_output: strict' to opt in.`);
143
166
  }
144
167
  }
168
+ // `--explain` REPLACES the summary with the detail above — an explicit ask for detail should
169
+ // not also get the pointer telling you how to ask for it.
170
+ if (opts.explain)
171
+ return;
172
+ // Read at call time, never captured at module scope (the #285 class). An explicit `--explain`
173
+ // beats a standing preference, which is why this check sits below the return above.
174
+ if (process.env['REALM_NO_NUDGE'] === '1')
175
+ return;
176
+ const line = renderNudgeSummary(ready.length, withCaveats.length, oneAway.length);
177
+ if (line !== undefined)
178
+ console.log(line);
179
+ }
180
+ /** The reasoning-position annotation, printed beside a caveat list wherever one renders. */
181
+ function printReasoningAnnotation(stepName, reasoningProp) {
182
+ if (reasoningProp === undefined)
183
+ return;
184
+ console.log(`ℹ Step '${stepName}': the optional '${reasoningProp}' property looks like a ` +
185
+ `reasoning field — see the optional_emission caveat above (position matters: with ` +
186
+ `default thinking there is no regression; on non-thinking configurations prefer ` +
187
+ `'required' + first property order — see docs/reference/yaml-schema.md).`);
188
+ }
189
+ /**
190
+ * The one graded summary line (issue #422), or `undefined` when there is nothing to say.
191
+ *
192
+ * The tail teaches BOTH escape routes in the one line it gets — the detail command (npm's
193
+ * "Run `npm fund` for details", cargo's named report command) fused with the silencer (git's
194
+ * squelch-teaching advice hints). A reader who wants more and a reader who wants less are both
195
+ * served without a second line.
196
+ *
197
+ * Each clause pluralizes on its OWN count, and a zero-valued clause is omitted rather than
198
+ * rendered as a zero. The caveats parenthetical and the one-change-away clause are independent:
199
+ * gating the second on the first would silently drop it for a file whose ready steps are all
200
+ * caveat-free.
201
+ */
202
+ function renderNudgeSummary(ready, withCaveats, oneAway) {
203
+ if (ready === 0 && oneAway === 0)
204
+ return undefined;
205
+ const steps = (n) => (n === 1 ? 'step' : 'steps');
206
+ const tail = ` — run 'realm workflow validate --explain' for detail (REALM_NO_NUDGE=1 to silence).`;
207
+ if (ready === 0) {
208
+ return `ℹ ${oneAway} ${steps(oneAway)} one change away from structured_output: strict${tail}`;
209
+ }
210
+ let line = `ℹ ${ready} ${steps(ready)} ready for structured_output: strict`;
211
+ if (withCaveats > 0)
212
+ line += ` (${withCaveats} with caveats)`;
213
+ if (oneAway > 0)
214
+ line += `, ${oneAway} ${steps(oneAway)} one change away`;
215
+ return line + tail;
216
+ }
217
+ /**
218
+ * The ONE place a load failure is rendered on this command (issue #445).
219
+ *
220
+ * WorkflowError means the workflow is invalid: print the warnings it carried (#424), render the
221
+ * message, exit 1. Anything else is an internal bug and is RETHROWN — the #123 doctrine, pinned
222
+ * by validate-internal-error.test.ts's "genuine-bug-still-loud" cell: a real crash must never be
223
+ * relabelled `Invalid:`, because that tells an author their file is wrong when realm is.
224
+ *
225
+ * The extensions arm used to render ANY error as `Invalid:`, so it violated that doctrine in two
226
+ * directions at once — an internal bug was swallowed, and a user's broken extension module was
227
+ * blamed on their workflow. Both arms route here now, and extension loading has its own catch
228
+ * with its own sentence, so the two populations stay separate.
229
+ *
230
+ * SCOPE, deliberate: watch/register/test/agent keep their own catches (#425's recorded
231
+ * exclusion). If a second surface ever adopts this, move it to lib/loader-warnings.ts — one
232
+ * caller does not earn a shared home.
233
+ */
234
+ function exitOnLoadFailure(err) {
235
+ if (err instanceof WorkflowError) {
236
+ if (err.warnings !== undefined)
237
+ printLoaderWarnings(err.warnings);
238
+ console.error(renderLoadFailure(err));
239
+ process.exit(1);
240
+ }
241
+ throw err;
145
242
  }
146
243
  /**
147
244
  * The issue #170 boundary-reject, LIVE since the flip: a workflow carrying an unrecognised
@@ -153,7 +250,15 @@ function rejectIfPolicyEscalates(warnings) {
153
250
  if (!rejectOnErrorSeverity(warnings))
154
251
  return false;
155
252
  printLoaderWarnings(warnings);
156
- console.error(`Invalid: ${warnings.length} warning(s) present, and at least one is escalated to an error by policy.`);
253
+ // issue #425: name WHICH warnings escalated. "at least one is escalated" left an author with
254
+ // three warnings above and no way to tell which of them was the refusal — the counts are the
255
+ // aggregate this line adds, so it is the line that has to say.
256
+ //
257
+ // register and watch print the same line since issue #451 (watch adds its timestamp and a
258
+ // `— refusing to register.` tail, because it does not exit); it lives in lib/loader-warnings.ts
259
+ // for that reason. On all three surfaces printLoaderWarnings' `— REFUSED below` substitution
260
+ // already marks each refused warning one line above.
261
+ console.error(renderEscalationLine(warnings));
157
262
  return true;
158
263
  }
159
264
  /** Pre-scan: does the YAML carry a top-level `extensions` key? (Parse errors → false; the
@@ -170,16 +275,121 @@ function hasTopLevelExtensions(content) {
170
275
  return false;
171
276
  }
172
277
  }
278
+ /**
279
+ * `validate --registered <id>` — audit the STORED copy of a workflow (issue #427).
280
+ *
281
+ * The mechanism is kubectl's server-side dry-run shape: strip the keys the loader stamps, feed
282
+ * the rest back through the REAL loader, report what it says. Zero rules are duplicated here, so
283
+ * this surface cannot drift from what `register` would accept tomorrow.
284
+ *
285
+ * What it audits is the INSTALLED loader — the same limitation kubectl documents. The
286
+ * pre-upgrade journey is therefore: upgrade the CLI first, THEN audit. That is safe precisely
287
+ * because grandfathering holds for the copies it applies to: a CURRENT-SCHEMA registered copy
288
+ * keeps running under the rules it was registered with, so upgrading the CLI to look does not
289
+ * change what your runs do. A legacy (schema_version-less or older) copy is a different case
290
+ * entirely — see the legacy arm below: it is not grandfathered, it is already unreachable.
291
+ */
292
+ async function validateRegistered(id, strict) {
293
+ const store = new JsonWorkflowStore();
294
+ let stored;
295
+ try {
296
+ stored = await store.get(id);
297
+ }
298
+ catch (err) {
299
+ if (err instanceof WorkflowError && err.code === 'STATE_WORKFLOW_NOT_FOUND') {
300
+ console.error(`Error: ${err.message}`);
301
+ console.error('Registered workflows: realm workflow list');
302
+ process.exit(1);
303
+ }
304
+ if (err instanceof WorkflowError && err.code === 'STATE_LEGACY_FORMAT') {
305
+ // ONE clause only. There is no schema_version to name — nothing parsed far enough to read
306
+ // one — and the grandfathering sentence would be FALSE for this cohort: every runtime
307
+ // consumer resolves through this same get() gate (start_run, execute_step, append_trace,
308
+ // get_workflow_protocol, submit_human_response, replay), so a legacy entry cannot run at
309
+ // all. It is not grandfathered; it is unreachable.
310
+ console.log(`Auditing the registered copy of '${id}' with realm ${VERSION}'s loader.`);
311
+ // The store's own message carries the remedy; the loader would say `Missing required
312
+ // field: 'steps'` here, which is true of the shape and useless about the cause.
313
+ console.error(renderLoadFailure(err));
314
+ process.exit(1);
315
+ }
316
+ if (!(err instanceof WorkflowError)) {
317
+ // get()'s try wraps ONLY the read — JSON.parse sits outside it, so a corrupt stored file
318
+ // arrives here as a bare SyntaxError with no code (executed).
319
+ console.error(`Error: the registered copy of '${id}' is not parseable JSON: ${err instanceof Error ? err.message : String(err)}`);
320
+ console.error('Registered workflows: realm workflow list');
321
+ process.exit(1);
322
+ }
323
+ throw err; // #123: an unexpected WorkflowError is a bug, and bugs stay loud.
324
+ }
325
+ console.log(`Auditing the registered copy of '${id}' (schema_version ${String(stored.schema_version)}) ` +
326
+ `with realm ${VERSION}'s loader.`);
327
+ console.log('Registered copies stay grandfathered at runtime — this reports what re-registration today would say.');
328
+ const clone = { ...stored };
329
+ for (const key of RUNTIME_ONLY_WORKFLOW_KEYS)
330
+ delete clone[key];
331
+ const declaresProfile = Object.values(stored.steps ?? {}).some((step) => step.agent_profile !== undefined);
332
+ if (clone['extensions'] !== undefined || declaresProfile) {
333
+ console.log('Extensions/profiles declared — module resolution, config_schema checks, and agent-profile ' +
334
+ 'file resolution need the source tree and are not audited here; structural rules only.');
335
+ }
336
+ // MUST delete: the from-string loader hard-throws on an `extensions` key (allowExtensions:
337
+ // false) with "Register this workflow from its YAML file" — maximally misleading here, where
338
+ // the workflow IS registered and the operator asked about the stored copy. The honesty line
339
+ // above is what carries the real limitation.
340
+ delete clone['extensions'];
341
+ let definition;
342
+ let loaderWarnings;
343
+ try {
344
+ ({ definition, warnings: loaderWarnings } = loadWorkflowFromStringWithDiagnostics(JSON.stringify(clone)));
345
+ }
346
+ catch (err) {
347
+ exitOnLoadFailure(err);
348
+ }
349
+ // The extension-free arm's tail, minus the orphan-manifest check (there is no source tree to
350
+ // have one) and minus the adoption nudge (a stored copy is not where you edit; `--explain` is
351
+ // therefore inert in this mode, deliberately — no machinery for it).
352
+ const accumulated = [...loaderWarnings, ...findRetryWithoutExplicitTimeout(definition)];
353
+ if (rejectIfPolicyEscalates(accumulated)) {
354
+ process.exit(1);
355
+ }
356
+ const strictFailed = printValidationOutcome(definition, accumulated, strict);
357
+ if (strictFailed) {
358
+ process.exit(1);
359
+ }
360
+ }
173
361
  export const validateCommand = new Command('validate')
174
- .argument('<path>', 'Path to workflow directory or workflow.yaml file')
362
+ .argument('[path]', 'Path to workflow directory or workflow.yaml file')
363
+ .option('--registered <id>', 'Audit the STORED copy of a registered workflow instead of a file (issue #427)')
175
364
  .option('--extensions-module <path>', "Extensions module that REPLACES the workflow's declared 'extensions' modules (repair/override)")
176
365
  .option('--strict', 'Exit non-zero if any loader warning is present (unknown keys, retry-without-timeout, sentinel credentials — issue #169)')
366
+ .option('--explain', 'Print the full per-step structured_output adoption detail instead of the one-line summary the default run prints (issue #422)')
177
367
  .description('Validate a workflow YAML file')
178
368
  .action(async (inputPath, opts) => {
369
+ const strict = opts.strict === true;
370
+ const explain = opts.explain === true;
371
+ // Exactly-one, checked FIRST and load-bearing: commander parses a `[path]` positional and
372
+ // a `--registered <id>` option happily together and enforces nothing between them
373
+ // (executed — both arrive). The flag is `--registered <id>` rather than an auto-detecting
374
+ // positional deliberately: nothing can reliably tell an id from a path, and guessing wrong
375
+ // means auditing something the operator did not name.
376
+ if (inputPath === undefined && opts.registered === undefined) {
377
+ console.error('Error: provide a workflow path, or --registered <id> to audit a stored definition.');
378
+ process.exit(1);
379
+ return;
380
+ }
381
+ if (inputPath !== undefined && opts.registered !== undefined) {
382
+ console.error('Error: --registered audits the stored copy — it cannot be combined with a path.');
383
+ process.exit(1);
384
+ return;
385
+ }
386
+ if (opts.registered !== undefined) {
387
+ await validateRegistered(opts.registered, strict);
388
+ return;
389
+ }
179
390
  const filePath = inputPath.endsWith('.yaml') || inputPath.endsWith('.yml')
180
391
  ? inputPath
181
392
  : join(inputPath, 'workflow.yaml');
182
- const strict = opts.strict === true;
183
393
  let content;
184
394
  try {
185
395
  content = readFileSync(filePath, 'utf8');
@@ -196,68 +406,130 @@ export const validateCommand = new Command('validate')
196
406
  // source_dir/trust_root, so resolve the same trust root the file-based path would
197
407
  // (findTrustRoot walks package.json/.git from the workflow dir) and run the guard
198
408
  // structural-first — after the workflow parses, before the `Valid:` print. It throws
199
- // WorkflowError, which the catch below renders as `Invalid:` + exit(1). resolve()
409
+ // WorkflowError, which exitOnLoadFailure renders as `Invalid:` + exit(1) — this arm's
410
+ // guard call is DIRECT, which is why it keeps that sentence while an extensions-declaring
411
+ // load surfaces the same guard as `Error loading extensions:` (issue #445). resolve()
200
412
  // before dirname so a relative `workflow.yaml` doesn't collapse the walk to '.'.
413
+ let definition;
414
+ let loaderWarnings;
415
+ try {
416
+ ({ definition, warnings: loaderWarnings } =
417
+ loadWorkflowFromStringWithDiagnostics(content));
418
+ }
419
+ catch (err) {
420
+ exitOnLoadFailure(err);
421
+ }
422
+ // Its own try (issue #463): each try owns one failure population — the #445 doctrine. A
423
+ // load failure above has nothing to print but itself; the guard below fails AFTER the
424
+ // workflow parsed, with its warnings in hand.
201
425
  try {
202
- const { definition, warnings: loaderWarnings } = loadWorkflowFromStringWithDiagnostics(content);
203
426
  const workflowDir = dirname(resolve(filePath));
204
427
  checkForOrphanedManifests(workflowDir, findTrustRoot(workflowDir));
205
- const accumulated = [...loaderWarnings, ...findRetryWithoutExplicitTimeout(definition)];
206
- if (rejectIfPolicyEscalates(accumulated)) {
207
- process.exit(1);
208
- }
209
- const strictFailed = printValidationOutcome(definition, accumulated, strict);
210
- // issue #236: the nudge's own INFO channel — never affects the exit code below.
211
- printStructuredOutputNudge(definition);
212
- if (strictFailed) {
213
- process.exit(1);
214
- }
215
428
  }
216
429
  catch (err) {
217
- if (err instanceof WorkflowError) {
218
- console.error(renderLoadFailure(err.message));
219
- process.exit(1);
430
+ // The workflow's own warnings before the refusal — the same set the success path counts,
431
+ // so nothing the author would otherwise see only on the NEXT run is withheld. Plain
432
+ // render: the escalation gate has not run, so printLoaderWarnings' `— REFUSED below`
433
+ // would name the wrong cause (test.ts's render comment, #450's reasoning). Unconditional:
434
+ // on the #123 non-WorkflowError rethrow population the warnings print before the loud
435
+ // crash — true statements either way. exitOnLoadFailure cannot print them twice: the
436
+ // orphan WorkflowError is minted bare in the CLI (load-project-extensions.ts), and the
437
+ // core `warnings` slot is set only by attachLoaderWarnings inside the core loader, which
438
+ // this throw never transits — which is exactly why this arm swallowed them until now.
439
+ for (const w of [...loaderWarnings, ...findRetryWithoutExplicitTimeout(definition)]) {
440
+ console.warn(renderLoaderWarning(w));
220
441
  }
221
- throw err;
442
+ exitOnLoadFailure(err);
443
+ }
444
+ // Reporting, deliberately OUTSIDE the try (issue #445): these lines only run once the
445
+ // load succeeded, and their own `process.exit` calls have no business passing through a
446
+ // catch that exists to classify LOAD failures. Production-neutral — the exits still exit.
447
+ const accumulated = [...loaderWarnings, ...findRetryWithoutExplicitTimeout(definition)];
448
+ if (rejectIfPolicyEscalates(accumulated)) {
449
+ process.exit(1);
450
+ }
451
+ const strictFailed = printValidationOutcome(definition, accumulated, strict);
452
+ // issue #236: the nudge's own INFO channel — never affects the exit code below.
453
+ printStructuredOutputNudge(definition, { explain });
454
+ if (strictFailed) {
455
+ process.exit(1);
222
456
  }
223
457
  return;
224
458
  }
225
459
  // Extensions declared (or an override supplied): file-based two-pass validation.
460
+ //
461
+ // THREE tries, not one (issue #445). The old single catch spanned five concerns and
462
+ // rendered every one of them `Invalid: …` — including a user's unresolvable extension
463
+ // module, and including internal bugs. Each try now owns one failure population, and the
464
+ // reporting tail sits outside all of them.
465
+ let definition;
466
+ let pass1Warnings;
226
467
  try {
227
468
  // Pass 1: structural validation + extension resolution metadata (source_dir/trust_root).
228
469
  // The universal, registry-independent structural load — its warnings are what we count.
229
- const { definition, warnings: pass1Warnings } = loadWorkflowFromFileWithDiagnostics(filePath);
230
- const { registry, manifest, sentinelWarnings } = await loadProjectExtensions(definition, {
470
+ ({ definition, warnings: pass1Warnings } = loadWorkflowFromFileWithDiagnostics(filePath));
471
+ }
472
+ catch (err) {
473
+ exitOnLoadFailure(err);
474
+ }
475
+ let registry;
476
+ let manifest;
477
+ let sentinelWarnings;
478
+ try {
479
+ ({ registry, manifest, sentinelWarnings } = await loadProjectExtensions(definition, {
231
480
  ...(opts.extensionsModule !== undefined ? { overrideModule: opts.extensionsModule } : {}),
232
481
  secretMode: 'sentinel',
233
- });
482
+ }));
483
+ }
484
+ catch (err) {
485
+ // issue #445 — a DIFFERENT population, and it gets its own sentence. Everything
486
+ // loadProjectExtensions throws is extension or deployment territory: an unresolvable
487
+ // module path, a failed import, a module whose default export is the wrong shape, a
488
+ // malformed `realm.yaml`, and the #123 orphaned-manifest refusal. None of those makes
489
+ // the WORKFLOW invalid, and calling them `Invalid:` sent an author to the wrong file.
490
+ // The sentence is `realm run`'s, verbatim (run.ts) — the sibling surface renders this
491
+ // identical failure class exactly so.
492
+ //
493
+ // issue #463 — the workflow's own warnings first: pass-1's plus the retry advisory, the
494
+ // same set the success path counts minus the sentinel wraps, which come from the load that
495
+ // just failed — there is nothing to wrap. Plain render (test.ts's render comment, #450's
496
+ // reasoning): the escalation gate has not run, so printLoaderWarnings' `— REFUSED below`
497
+ // would name the wrong cause.
498
+ for (const w of [...pass1Warnings, ...findRetryWithoutExplicitTimeout(definition)]) {
499
+ console.warn(renderLoaderWarning(w));
500
+ }
501
+ console.error(`Error loading extensions: ${err instanceof Error ? err.message : String(err)}`);
502
+ process.exit(1);
503
+ }
504
+ try {
234
505
  // Pass 2: step config validated against each resolved adapter's config_schema. Same
235
506
  // content as pass 1, registry only adds config_schema checks — its warnings are proven
236
507
  // identical to pass 1's, so they are deliberately discarded here (not collected) to avoid
237
508
  // double-counting the same unknown key twice.
238
509
  loadWorkflowFromFileWithDiagnostics(filePath, registry);
239
- const accumulated = [
240
- ...pass1Warnings,
241
- ...findRetryWithoutExplicitTimeout(definition),
242
- ...wrapSentinelWarnings(sentinelWarnings),
243
- ];
244
- if (rejectIfPolicyEscalates(accumulated)) {
245
- process.exit(1);
246
- }
247
- const strictFailed = printValidationOutcome(definition, accumulated, strict);
248
- // issue #236: the nudge's own INFO channel — never affects the exit code below.
249
- printStructuredOutputNudge(definition);
250
- if (manifest.modules.length > 0) {
251
- console.log(`Extensions: ${manifest.modules.map((m) => m.declared).join(', ')} ` +
252
- `(adapters: ${manifest.adapters.length}, handlers: ${manifest.handlers.length}, ` +
253
- `processors: ${manifest.processors.length})`);
254
- }
255
- if (strictFailed) {
256
- process.exit(1);
257
- }
258
510
  }
259
511
  catch (err) {
260
- console.error(renderLoadFailure(err instanceof Error ? err.message : String(err)));
512
+ exitOnLoadFailure(err);
513
+ }
514
+ const accumulated = [
515
+ ...pass1Warnings,
516
+ ...findRetryWithoutExplicitTimeout(definition),
517
+ ...wrapSentinelWarnings(sentinelWarnings),
518
+ ];
519
+ if (rejectIfPolicyEscalates(accumulated)) {
520
+ process.exit(1);
521
+ }
522
+ const strictFailed = printValidationOutcome(definition, accumulated, strict);
523
+ if (manifest.modules.length > 0) {
524
+ console.log(`Extensions: ${manifest.modules.map((m) => m.declared).join(', ')} ` +
525
+ `(adapters: ${manifest.adapters.length}, handlers: ${manifest.handlers.length}, ` +
526
+ `processors: ${manifest.processors.length})`);
527
+ }
528
+ // issue #236: the nudge's own INFO channel — never affects the exit code below.
529
+ // issue #422: genuinely end-of-report, BELOW the Extensions block — the summary is a
530
+ // pointer at what you could do next, not part of what was just validated.
531
+ printStructuredOutputNudge(definition, { explain });
532
+ if (strictFailed) {
261
533
  process.exit(1);
262
534
  }
263
535
  });
@@ -1 +1 @@
1
- {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,EAAE;AACF,yFAAyF;AACzF,qFAAqF;AACrF,uFAAuF;AACvF,wFAAwF;AACxF,4EAA4E;AAC5E,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC/B,OAAO,EACL,qCAAqC,EACrC,mCAAmC,EACnC,aAAa,EACb,aAAa,EACb,oBAAoB,EACpB,iCAAiC,EACjC,eAAe,EACf,iCAAiC,EACjC,uBAAuB,GAExB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,qBAAqB,EACrB,yBAAyB,GAC1B,MAAM,0CAA0C,CAAC;AAClD,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,WAAW,GACZ,MAAM,2BAA2B,CAAC;AAEnC;;;;;;;;;;;;;;GAcG;AACH,SAAS,+BAA+B,CAAC,UAA8B;IACrE,MAAM,QAAQ,GAAoB,EAAE,CAAC;IACrC,KAAK,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QAChE,IACE,oBAAoB,CAAC,IAAI,CAAC;YAC1B,IAAI,CAAC,KAAK,KAAK,SAAS;YACxB,IAAI,CAAC,eAAe,KAAK,SAAS,EAClC,CAAC;YACD,QAAQ,CAAC,IAAI,CAAC;gBACZ,IAAI,EAAE,kBAAkB;gBACxB,QAAQ,EAAE,eAAe,CAAC,kBAAkB,CAAC;gBAC7C,KAAK,EAAE,MAAM;gBACb,IAAI,EAAE,QAAQ;gBACd,OAAO,EACL,YAAY,QAAQ,iEAAiE;oBACrF,6CAA6C,iCAAiC,UAAU;oBACxF,qFAAqF;oBACrF,yFAAyF;oBACzF,wFAAwF;oBACxF,0EAA0E;aAC7E,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,+FAA+F;AAC/F,SAAS,oBAAoB,CAAC,gBAAsC;IAClE,OAAO,CAAC,gBAAgB,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAChD,IAAI,EAAE,oBAA6B;QACnC,QAAQ,EAAE,eAAe,CAAC,oBAAoB,CAAC;QAC/C,KAAK,EAAE,UAAmB;QAC1B,OAAO,EAAE,MAAM,OAAO,EAAE;KACzB,CAAC,CAAC,CAAC;AACN,CAAC;AAED;;;;;;GAMG;AACH,SAAS,sBAAsB,CAC7B,UAA8B,EAC9B,QAAyB,EACzB,MAAe;IAEf,mBAAmB,CAAC,QAAQ,CAAC,CAAC;IAC9B,MAAM,IAAI,GAAG,UAAU,UAAU,CAAC,EAAE,KAAK,UAAU,CAAC,OAAO,KAAK,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,MAAM,SAAS,CAAC;IAC9G,IAAI,MAAM,IAAI,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC;QACpC,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,MAAM,QAAQ,CAAC,MAAM,sCAAsC,CAAC,CAAC;QAChF,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAClB,IAAI,UAAU,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,KAAK,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC;IAC7C,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;4EAC4E;AAC5E,MAAM,uBAAuB,GAAG,wCAAwC,CAAC;AAEzE,SAAS,iCAAiC,CAAC,MAAe;IACxD,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IACpE,MAAM,UAAU,GAAI,MAAkC,CAAC,YAAY,CAAC,CAAC;IACrE,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IAC5E,OAAO,MAAM,CAAC,IAAI,CAAC,UAAqC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CACtE,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC,CACnC,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,SAAS,0BAA0B,CAAC,UAA8B;IAChE,KAAK,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QAChE,IAAI,IAAI,CAAC,SAAS,KAAK,OAAO;YAAE,SAAS;QACzC,MAAM,eAAe,GAAG,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,YAAY,CAAC;QAChE,IAAI,eAAe,KAAK,SAAS;YAAE,SAAS,CAAC,2CAA2C;QAExF,MAAM,OAAO,GAAG,IAAI,CAAC,iBAAiB,KAAK,QAAQ,CAAC;QACpD,MAAM,OAAO,GAAG,iCAAiC,CAAC;YAChD,GAAG,CAAC,IAAI,CAAC,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAClF,GAAG,CAAC,IAAI,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/E,GAAG,CAAC,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC3D,CAAC,CAAC;QACH,MAAM,aAAa,GAAG,iCAAiC,CAAC,eAAe,CAAC,CAAC;QAEzE,IAAI,OAAO,CAAC,OAAO,KAAK,YAAY,EAAE,CAAC;YACrC,yFAAyF;YACzF,sFAAsF;YACtF,OAAO,CAAC,GAAG,CACT,WAAW,QAAQ,iDAAiD;gBAClE,GAAG,uBAAuB,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAChD,CAAC;YACF,SAAS;QACX,CAAC;QAED,IAAI,OAAO,CAAC,OAAO,KAAK,uBAAuB,EAAE,CAAC;YAChD,MAAM,MAAM,GAAG,OAAO;gBACpB,CAAC,CAAC,WAAW,QAAQ,6BAA6B;gBAClD,CAAC,CAAC,WAAW,QAAQ,wDAAwD,CAAC;YAChF,KAAK,MAAM,MAAM,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;gBACrC,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,MAAM,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;YACnD,CAAC;YACD,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;gBAChC,OAAO,CAAC,GAAG,CACT,WAAW,QAAQ,oBAAoB,aAAa,0BAA0B;oBAC5E,mFAAmF;oBACnF,iFAAiF;oBACjF,yEAAyE,CAC5E,CAAC;YACJ,CAAC;YACD,SAAS;QACX,CAAC;QAED,sFAAsF;QACtF,sDAAsD;QACtD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,CAAC,GAAG,CACT,WAAW,QAAQ,kDAAkD;gBACnE,wCAAwC,CAC3C,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAS,uBAAuB,CAAC,QAAyB;IACxD,IAAI,CAAC,qBAAqB,CAAC,QAAQ,CAAC;QAAE,OAAO,KAAK,CAAC;IACnD,mBAAmB,CAAC,QAAQ,CAAC,CAAC;IAC9B,OAAO,CAAC,KAAK,CACX,YAAY,QAAQ,CAAC,MAAM,2EAA2E,CACvG,CAAC;IACF,OAAO,IAAI,CAAC;AACd,CAAC;AAED;uEACuE;AACvE,SAAS,qBAAqB,CAAC,OAAe;IAC5C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;QAC1B,OAAO,CACL,OAAO,GAAG,KAAK,QAAQ;YACvB,GAAG,KAAK,IAAI;YACZ,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;YACnB,YAAY,IAAK,GAA+B,CACjD,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,OAAO,CAAC,UAAU,CAAC;KACnD,QAAQ,CAAC,QAAQ,EAAE,kDAAkD,CAAC;KACtE,MAAM,CACL,4BAA4B,EAC5B,gGAAgG,CACjG;KACA,MAAM,CACL,UAAU,EACV,yHAAyH,CAC1H;KACA,WAAW,CAAC,+BAA+B,CAAC;KAC5C,MAAM,CAAC,KAAK,EAAE,SAAiB,EAAE,IAAqD,EAAE,EAAE;IACzF,MAAM,QAAQ,GACZ,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC;QACvD,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,IAAI,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;IACvC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC;IAEpC,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC3C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,OAAO,CAAC,KAAK,CAAC,UAAU,OAAO,EAAE,CAAC,CAAC;QACnC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAChB,OAAO;IACT,CAAC;IAED,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,gBAAgB,KAAK,SAAS,EAAE,CAAC;QAC3E,gFAAgF;QAChF,4EAA4E;QAC5E,kFAAkF;QAClF,kFAAkF;QAClF,qFAAqF;QACrF,kFAAkF;QAClF,iFAAiF;QACjF,IAAI,CAAC;YACH,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,cAAc,EAAE,GAC5C,qCAAqC,CAAC,OAAO,CAAC,CAAC;YACjD,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;YAC/C,yBAAyB,CAAC,WAAW,EAAE,aAAa,CAAC,WAAW,CAAC,CAAC,CAAC;YAEnE,MAAM,WAAW,GAAG,CAAC,GAAG,cAAc,EAAE,GAAG,+BAA+B,CAAC,UAAU,CAAC,CAAC,CAAC;YACxF,IAAI,uBAAuB,CAAC,WAAW,CAAC,EAAE,CAAC;gBACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,MAAM,YAAY,GAAG,sBAAsB,CAAC,UAAU,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;YAC7E,gFAAgF;YAChF,0BAA0B,CAAC,UAAU,CAAC,CAAC;YACvC,IAAI,YAAY,EAAE,CAAC;gBACjB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,aAAa,EAAE,CAAC;gBACjC,OAAO,CAAC,KAAK,CAAC,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;gBAC9C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;QACD,OAAO;IACT,CAAC;IAED,iFAAiF;IACjF,IAAI,CAAC;QACH,yFAAyF;QACzF,wFAAwF;QACxF,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,GAAG,mCAAmC,CAAC,QAAQ,CAAC,CAAC;QAC9F,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,gBAAgB,EAAE,GAAG,MAAM,qBAAqB,CAAC,UAAU,EAAE;YACvF,GAAG,CAAC,IAAI,CAAC,gBAAgB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACzF,UAAU,EAAE,UAAU;SACvB,CAAC,CAAC;QACH,oFAAoF;QACpF,uFAAuF;QACvF,0FAA0F;QAC1F,8CAA8C;QAC9C,mCAAmC,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAExD,MAAM,WAAW,GAAG;YAClB,GAAG,aAAa;YAChB,GAAG,+BAA+B,CAAC,UAAU,CAAC;YAC9C,GAAG,oBAAoB,CAAC,gBAAgB,CAAC;SAC1C,CAAC;QACF,IAAI,uBAAuB,CAAC,WAAW,CAAC,EAAE,CAAC;YACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,MAAM,YAAY,GAAG,sBAAsB,CAAC,UAAU,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;QAC7E,gFAAgF;QAChF,0BAA0B,CAAC,UAAU,CAAC,CAAC;QACvC,IAAI,QAAQ,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChC,OAAO,CAAC,GAAG,CACT,eAAe,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;gBAClE,cAAc,QAAQ,CAAC,QAAQ,CAAC,MAAM,eAAe,QAAQ,CAAC,QAAQ,CAAC,MAAM,IAAI;gBACjF,eAAe,QAAQ,CAAC,UAAU,CAAC,MAAM,GAAG,CAC/C,CAAC;QACJ,CAAC;QACD,IAAI,YAAY,EAAE,CAAC;YACjB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,iBAAiB,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACnF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,24 @@
1
1
  import { Command } from 'commander';
2
2
  import type { WorkflowRegistrar } from '@sensigo/realm';
3
+ /**
4
+ * A trailing-edge coalescer: every `trigger()` (re)arms one timer, so a burst of calls inside the
5
+ * window produces exactly one `fn()` at the end of it (issue #449).
6
+ *
7
+ * WHAT ACTUALLY BURSTS, precisely — the YAML watcher is not the reason. On this platform the
8
+ * basename filter already reduces an atomic save to ONE passing event. The burst is the
9
+ * profiles watcher, which has no filter: creating a file there emits `rename` + `change`, two
10
+ * events, probe-proven. Cross-platform event shapes vary besides, so one instance is shared by
11
+ * both watchers rather than reasoned about per-watcher.
12
+ *
13
+ * `cancel()` exists because an abort must not leave a pending timer: it would fire after the
14
+ * watch resolved, re-registering into a store whose owner has moved on. Idempotent.
15
+ *
16
+ * @internal Exported for testing only.
17
+ */
18
+ export declare function makeCoalescedTrigger(fn: () => void, delayMs: number): {
19
+ trigger(): void;
20
+ cancel(): void;
21
+ };
3
22
  /**
4
23
  * Watches a workflow YAML file and re-registers it into the given store on every change.
5
24
  * Also watches the profiles directory alongside the YAML — any file change there triggers
@@ -7,6 +26,17 @@ import type { WorkflowRegistrar } from '@sensigo/realm';
7
26
  * Performs an initial registration before entering the watch loop.
8
27
  * Resolves when the watcher is closed (e.g. when the AbortSignal fires).
9
28
  *
29
+ * Three mechanics worth knowing (issue #449):
30
+ * - The YAML watch is on the file's DIRECTORY, filtered by basename — a file watch dies with the
31
+ * inode an atomic save renames away.
32
+ * - Both watchers are persistent, so they hold the process open; Ctrl+C is what stops it.
33
+ * - Each save's event burst is coalesced into one re-registration on a 100ms trailing edge.
34
+ *
35
+ * RESTART REQUIRED for three things, all read once at startup and never re-read: the extension
36
+ * modules (ESM cache, note below), a `profiles/` directory created after the watch began, and a
37
+ * `profiles_dir:` value edited mid-watch — an edit to that key keeps watching the OLD directory
38
+ * until you restart. No late-mount machinery; watch-before-create is a separate feature.
39
+ *
10
40
  * @param filePath Path to the workflow YAML file.
11
41
  * @param store The workflow registrar to register into — injected, never instantiated here.
12
42
  * @param signal Optional AbortSignal; when aborted the watcher stops and the promise resolves.