@farmslot/recipe-cli 0.2.0 → 0.4.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 (119) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +13 -9
  3. package/dist/harness/adapters.d.ts +27 -0
  4. package/dist/harness/adapters.d.ts.map +1 -0
  5. package/dist/harness/adapters.js +91 -0
  6. package/dist/harness/adapters.js.map +1 -0
  7. package/dist/harness/artifact-files.d.ts +11 -0
  8. package/dist/harness/artifact-files.d.ts.map +1 -0
  9. package/dist/harness/artifact-files.js +75 -0
  10. package/dist/harness/artifact-files.js.map +1 -0
  11. package/dist/harness/checkout-lock.d.ts +13 -0
  12. package/dist/harness/checkout-lock.d.ts.map +1 -0
  13. package/dist/harness/checkout-lock.js +211 -0
  14. package/dist/harness/checkout-lock.js.map +1 -0
  15. package/dist/harness/cli-color.d.ts +25 -0
  16. package/dist/harness/cli-color.d.ts.map +1 -0
  17. package/dist/harness/cli-color.js +101 -0
  18. package/dist/harness/cli-color.js.map +1 -0
  19. package/dist/harness/command-journal.d.ts +25 -0
  20. package/dist/harness/command-journal.d.ts.map +1 -0
  21. package/dist/harness/command-journal.js +322 -0
  22. package/dist/harness/command-journal.js.map +1 -0
  23. package/dist/harness/commands/last.d.ts +3 -0
  24. package/dist/harness/commands/last.d.ts.map +1 -0
  25. package/dist/harness/commands/last.js +59 -0
  26. package/dist/harness/commands/last.js.map +1 -0
  27. package/dist/harness/commands/launch.d.ts +2 -0
  28. package/dist/harness/commands/launch.d.ts.map +1 -0
  29. package/dist/harness/commands/launch.js +105 -0
  30. package/dist/harness/commands/launch.js.map +1 -0
  31. package/dist/harness/commands/reload.d.ts +2 -0
  32. package/dist/harness/commands/reload.d.ts.map +1 -0
  33. package/dist/harness/commands/reload.js +24 -0
  34. package/dist/harness/commands/reload.js.map +1 -0
  35. package/dist/harness/commands/stop.d.ts +9 -0
  36. package/dist/harness/commands/stop.d.ts.map +1 -0
  37. package/dist/harness/commands/stop.js +60 -0
  38. package/dist/harness/commands/stop.js.map +1 -0
  39. package/dist/harness/execution-provenance.d.ts +56 -0
  40. package/dist/harness/execution-provenance.d.ts.map +1 -0
  41. package/dist/harness/execution-provenance.js +308 -0
  42. package/dist/harness/execution-provenance.js.map +1 -0
  43. package/dist/harness/heal-bounds.d.ts +15 -0
  44. package/dist/harness/heal-bounds.d.ts.map +1 -0
  45. package/dist/harness/heal-bounds.js +194 -0
  46. package/dist/harness/heal-bounds.js.map +1 -0
  47. package/dist/harness/host.d.ts +45 -0
  48. package/dist/harness/host.d.ts.map +1 -0
  49. package/dist/harness/host.js +55 -0
  50. package/dist/harness/host.js.map +1 -0
  51. package/dist/harness/index.d.ts +29 -0
  52. package/dist/harness/index.d.ts.map +1 -0
  53. package/dist/harness/index.js +32 -0
  54. package/dist/harness/index.js.map +1 -0
  55. package/dist/harness/json-stream.d.ts +19 -0
  56. package/dist/harness/json-stream.d.ts.map +1 -0
  57. package/dist/harness/json-stream.js +59 -0
  58. package/dist/harness/json-stream.js.map +1 -0
  59. package/dist/harness/leaf-invoke.d.ts +8 -0
  60. package/dist/harness/leaf-invoke.d.ts.map +1 -0
  61. package/dist/harness/leaf-invoke.js +31 -0
  62. package/dist/harness/leaf-invoke.js.map +1 -0
  63. package/dist/harness/library-provenance.d.ts +3 -0
  64. package/dist/harness/library-provenance.d.ts.map +1 -0
  65. package/dist/harness/library-provenance.js +31 -0
  66. package/dist/harness/library-provenance.js.map +1 -0
  67. package/dist/harness/live-adapter-contract.d.ts +32 -0
  68. package/dist/harness/live-adapter-contract.d.ts.map +1 -0
  69. package/dist/harness/live-adapter-contract.js +425 -0
  70. package/dist/harness/live-adapter-contract.js.map +1 -0
  71. package/dist/harness/overlay.d.ts +17 -0
  72. package/dist/harness/overlay.d.ts.map +1 -0
  73. package/dist/harness/overlay.js +415 -0
  74. package/dist/harness/overlay.js.map +1 -0
  75. package/dist/harness/parse-args.d.ts +35 -0
  76. package/dist/harness/parse-args.d.ts.map +1 -0
  77. package/dist/harness/parse-args.js +249 -0
  78. package/dist/harness/parse-args.js.map +1 -0
  79. package/dist/harness/paths.d.ts +15 -0
  80. package/dist/harness/paths.d.ts.map +1 -0
  81. package/dist/harness/paths.js +29 -0
  82. package/dist/harness/paths.js.map +1 -0
  83. package/dist/harness/recording-target.d.ts +9 -0
  84. package/dist/harness/recording-target.d.ts.map +1 -0
  85. package/dist/harness/recording-target.js +39 -0
  86. package/dist/harness/recording-target.js.map +1 -0
  87. package/dist/harness/run-diagnostics.d.ts +139 -0
  88. package/dist/harness/run-diagnostics.d.ts.map +1 -0
  89. package/dist/harness/run-diagnostics.js +458 -0
  90. package/dist/harness/run-diagnostics.js.map +1 -0
  91. package/dist/harness/run-options.d.ts +4 -0
  92. package/dist/harness/run-options.d.ts.map +1 -0
  93. package/dist/harness/run-options.js +35 -0
  94. package/dist/harness/run-options.js.map +1 -0
  95. package/dist/harness/run-recording.d.ts +43 -0
  96. package/dist/harness/run-recording.d.ts.map +1 -0
  97. package/dist/harness/run-recording.js +517 -0
  98. package/dist/harness/run-recording.js.map +1 -0
  99. package/dist/harness/run-report.d.ts +19 -0
  100. package/dist/harness/run-report.d.ts.map +1 -0
  101. package/dist/harness/run-report.js +269 -0
  102. package/dist/harness/run-report.js.map +1 -0
  103. package/dist/harness/runtime-proof.d.ts +27 -0
  104. package/dist/harness/runtime-proof.d.ts.map +1 -0
  105. package/dist/harness/runtime-proof.js +144 -0
  106. package/dist/harness/runtime-proof.js.map +1 -0
  107. package/dist/harness/shared.d.ts +43 -0
  108. package/dist/harness/shared.d.ts.map +1 -0
  109. package/dist/harness/shared.js +414 -0
  110. package/dist/harness/shared.js.map +1 -0
  111. package/dist/harness/suggest.d.ts +3 -0
  112. package/dist/harness/suggest.d.ts.map +1 -0
  113. package/dist/harness/suggest.js +37 -0
  114. package/dist/harness/suggest.js.map +1 -0
  115. package/dist/harness/trust.d.ts +38 -0
  116. package/dist/harness/trust.d.ts.map +1 -0
  117. package/dist/harness/trust.js +89 -0
  118. package/dist/harness/trust.js.map +1 -0
  119. package/package.json +11 -2
@@ -0,0 +1,414 @@
1
+ // Shared helpers for the harness command modules: flag parsing, adapter
2
+ // resolution, leaf composition, and the teaching-error emitter.
3
+ //
4
+ // Composition seam (overridable for contract tests):
5
+ // <envPrefix>_SCRIPT_BIN_<STEM> — override a specific script by its basename.
6
+ // For node invocations (bin === process.execPath) the stem is derived from the
7
+ // script path in args[0], e.g. <envPrefix>_SCRIPT_BIN_OPEN_DEBUG_MJS.
8
+ import { spawn, spawnSync } from 'node:child_process';
9
+ import path from 'node:path';
10
+ import { StringDecoder } from 'node:string_decoder';
11
+ import { OperationOutputTail } from '@farmslot/recipe-runner/runtime/operation';
12
+ import { adapterForPlatform, detectAdapter, harnessAdapters } from './adapters.js';
13
+ import { trackCheckoutChild } from './checkout-lock.js';
14
+ import { colorHumanMessage } from './cli-color.js';
15
+ import { recordCommandOutput, recordCommandStage } from './command-journal.js';
16
+ import { harnessHost, hostEnvName } from './host.js';
17
+ import { leafStartFailureMessage, resolveLeafInvoke, shellLeafMissing } from './leaf-invoke.js';
18
+ // Stable public exit-code taxonomy.
19
+ export const EXIT = { ok: 0, runtime: 1, usage: 2, infra: 3, bounded: 4, validation: 5 };
20
+ export function writeInteractiveProgress(json, message, { stdoutIsTTY = Boolean(process.stdout.isTTY), stream = process.stderr, } = {}) {
21
+ if (json || !stdoutIsTTY)
22
+ return false;
23
+ stream.write(`${colorHumanMessage(message, { stream: stream })}\n`);
24
+ return true;
25
+ }
26
+ // Positionals + boolean/valued flags; camelCases --foo-bar to fooBar.
27
+ export function parseFlags(argv, booleans) {
28
+ const positional = [];
29
+ const options = {};
30
+ for (let i = 0; i < argv.length; i += 1) {
31
+ const arg = argv[i];
32
+ if (!arg.startsWith('--')) {
33
+ positional.push(arg);
34
+ continue;
35
+ }
36
+ const body = arg.slice(2);
37
+ const eq = body.indexOf('=');
38
+ const rawKey = eq === -1 ? body : body.slice(0, eq);
39
+ const inline = eq === -1 ? undefined : body.slice(eq + 1);
40
+ const key = rawKey.replace(/-([a-z])/gu, (_, c) => c.toUpperCase());
41
+ if (booleans.has(key)) {
42
+ options[key] = inline === undefined ? true : inline !== 'false';
43
+ continue;
44
+ }
45
+ if (inline !== undefined) {
46
+ options[key] = inline;
47
+ continue;
48
+ }
49
+ // Valued flag with a following token, unless the next token is itself a flag.
50
+ const next = argv[i + 1];
51
+ if (next === undefined || next.startsWith('--')) {
52
+ options[key] = true;
53
+ continue;
54
+ }
55
+ options[key] = next;
56
+ i += 1;
57
+ }
58
+ return { positional, options };
59
+ }
60
+ export function str(options, key) {
61
+ const value = options[key];
62
+ return typeof value === 'string' ? value : undefined;
63
+ }
64
+ export function flag(options, key) {
65
+ return options[key] === true;
66
+ }
67
+ export function targetOf(options) {
68
+ return path.resolve(str(options, 'target') ?? process.cwd());
69
+ }
70
+ // Explicit --adapter/--platform (a platform target selects its adapter), else
71
+ // an optional hint, else auto-detect from the target.
72
+ export function resolveFlagsAdapter(options, target, hint) {
73
+ const explicit = str(options, 'adapter') ?? adapterForPlatform(str(options, 'platform'));
74
+ if (explicit && harnessAdapters().has(explicit))
75
+ return explicit;
76
+ if (hint)
77
+ return hint;
78
+ return detectAdapter(target);
79
+ }
80
+ // The composition-seam override path for a script, if set — same stem derivation
81
+ // spawnScript uses. Lets a caller pre-check the SAME bin that will actually run
82
+ // (and lets contract tests simulate a missing leaf by pointing the seam at a
83
+ // nonexistent path). Returns undefined when no override is set (production).
84
+ export function scriptOverride(scriptPath) {
85
+ const stem = path
86
+ .basename(scriptPath)
87
+ .replace(/[^A-Za-z0-9]/gu, '_')
88
+ .toUpperCase();
89
+ return process.env[hostEnvName(`SCRIPT_BIN_${stem}`)];
90
+ }
91
+ // Compose an adapters/ script directly. Output is always captured (needed for
92
+ // heal classification) and, in human mode, forwarded to stderr. --json keeps
93
+ // stdout clean for the machine summary. `env` overlays extra vars onto the
94
+ // inherited environment for spawns that need a scoped variable (e.g. color mode).
95
+ export function spawnScript(script, args, cwd, json, env) {
96
+ // For node invocations (script === process.execPath) the seam stem is derived
97
+ // from args[0] so each spawned script has its own override key.
98
+ const isNodeScript = script === process.execPath && args.length > 0;
99
+ // Seam stem: for node invocations derive from args[0] so each script has its
100
+ // own override key; for shell and other leaves derive from the script basename.
101
+ const stem = isNodeScript
102
+ ? path
103
+ .basename(args[0])
104
+ .replace(/[^A-Za-z0-9]/gu, '_')
105
+ .toUpperCase()
106
+ : path
107
+ .basename(script)
108
+ .replace(/[^A-Za-z0-9]/gu, '_')
109
+ .toUpperCase();
110
+ const override = process.env[hostEnvName(`SCRIPT_BIN_${stem}`)];
111
+ const bin = override ?? script;
112
+ const directArgs = override !== undefined && isNodeScript ? args.slice(1) : args;
113
+ // Shell leaves (.sh) run through bash so file mode need not be executable.
114
+ // Bash exits 127 (not a Node spawn error) for a missing file, so pre-check.
115
+ if (shellLeafMissing(bin)) {
116
+ const message = leafStartFailureMessage(path.basename(bin), 'ENOENT');
117
+ process.stderr.write(`${message}\n`);
118
+ return { status: 1, output: message };
119
+ }
120
+ const { bin: invokeBin, args: spawnArgs } = resolveLeafInvoke(bin, directArgs);
121
+ recordCommandStage(path.basename(isNodeScript ? args[0] : script));
122
+ const result = spawnSync(invokeBin, spawnArgs, {
123
+ cwd,
124
+ encoding: 'utf8',
125
+ env: env ? { ...process.env, ...env } : process.env,
126
+ maxBuffer: 64 * 1024 * 1024,
127
+ });
128
+ if (result.error) {
129
+ // Spawn failure for non-shell leaves (ENOENT/EACCES) or when bash itself
130
+ // cannot start. Always emit so a leaf that cannot start is never silent.
131
+ // For node invocations the leaf name comes from args[0], not process.execPath.
132
+ const leaf = isNodeScript ? path.basename(args[0]) : path.basename(script);
133
+ const code = result.error.code ?? 'ESPAWN';
134
+ const message = leafStartFailureMessage(leaf, code);
135
+ process.stderr.write(`${message}\n`);
136
+ return { status: 1, output: message };
137
+ }
138
+ const output = `${result.stdout ?? ''}${result.stderr ?? ''}`;
139
+ recordCommandOutput(output);
140
+ if (!json && output)
141
+ process.stderr.write(output);
142
+ return { status: result.status ?? 1, output };
143
+ }
144
+ // Inherit-stdio variant for interactive/streaming leaves (e.g. `logs` tailing a
145
+ // live file with tail -F / a follow viewer). spawnScript CAPTURES output, so a
146
+ // never-exiting follow shows the user nothing; this hands the terminal to the
147
+ // child so its output streams live. No capture, no envelope — the command owns
148
+ // its own --json handling.
149
+ export function spawnInherit(script, args, cwd) {
150
+ // Honor the same <envPrefix>_SCRIPT_BIN_<STEM> override seam as spawnScript so
151
+ // contract tests can stub tail/log-tui with a recorder (a real `tail -F`
152
+ // follows forever and hangs the test). Stem/override logic mirrors spawnScript.
153
+ const isNodeScript = script === process.execPath && args.length > 0;
154
+ const stem = (isNodeScript ? path.basename(args[0]) : path.basename(script))
155
+ .replace(/[^A-Za-z0-9]/gu, '_')
156
+ .toUpperCase();
157
+ const override = process.env[hostEnvName(`SCRIPT_BIN_${stem}`)];
158
+ const bin = override ?? script;
159
+ const directArgs = override !== undefined && isNodeScript ? args.slice(1) : args;
160
+ const { bin: invokeBin, args: spawnArgs } = resolveLeafInvoke(bin, directArgs);
161
+ const result = spawnSync(invokeBin, spawnArgs, { cwd, stdio: 'inherit', env: process.env });
162
+ if (result.error) {
163
+ // Teach on spawn failure like spawnScript/spawnScriptStreaming do (errors
164
+ // always teach escape) — the override-seam path can point at a missing bin.
165
+ const leaf = isNodeScript ? path.basename(args[0]) : path.basename(script);
166
+ const code = result.error.code ?? 'ESPAWN';
167
+ process.stderr.write(`${leafStartFailureMessage(leaf, code, 'leaf')}\n`);
168
+ return 1;
169
+ }
170
+ // Interactive follow: Ctrl-C (SIGINT) / SIGTERM is a normal user stop → success;
171
+ // any other signal (crash) is a failure.
172
+ if (result.status !== null)
173
+ return result.status;
174
+ return result.signal === 'SIGINT' || result.signal === 'SIGTERM' ? 0 : 1;
175
+ }
176
+ // Streaming variant of spawnScript for long-running leaves (mobile prepare:
177
+ // native build + Metro + health-bridge poll, minutes long). spawnScript buffers
178
+ // via spawnSync and, in --json mode, suppresses output entirely — so those leaves
179
+ // run with zero feedback until exit. This tees the child's stdout+stderr to the
180
+ // parent's STDERR live (so the --json envelope on stdout stays clean) while still
181
+ // capturing the combined output for heal classification. Same seam, leaf-invoke
182
+ // resolution, missing-leaf pre-check, and spawn-error contract as spawnScript.
183
+ export function spawnScriptStreaming(script, args, cwd, options) {
184
+ const spawnOptions = options &&
185
+ ('env' in options ||
186
+ 'timeoutMs' in options ||
187
+ 'forward' in options ||
188
+ 'capture' in options ||
189
+ 'stdin' in options ||
190
+ 'stage' in options)
191
+ ? options
192
+ : { env: options };
193
+ const isNodeScript = script === process.execPath && args.length > 0;
194
+ const stem = isNodeScript
195
+ ? path
196
+ .basename(args[0])
197
+ .replace(/[^A-Za-z0-9]/gu, '_')
198
+ .toUpperCase()
199
+ : path
200
+ .basename(script)
201
+ .replace(/[^A-Za-z0-9]/gu, '_')
202
+ .toUpperCase();
203
+ const override = process.env[hostEnvName(`SCRIPT_BIN_${stem}`)];
204
+ const bin = override ?? script;
205
+ const directArgs = override !== undefined && isNodeScript ? args.slice(1) : args;
206
+ if (shellLeafMissing(bin)) {
207
+ const message = leafStartFailureMessage(path.basename(bin), 'ENOENT');
208
+ if (spawnOptions.forward !== 'none')
209
+ process.stderr.write(`${message}\n`);
210
+ return Promise.resolve({ status: 1, output: message });
211
+ }
212
+ const { bin: invokeBin, args: spawnArgs } = resolveLeafInvoke(bin, directArgs);
213
+ recordCommandStage(spawnOptions.stage ?? path.basename(isNodeScript ? args[0] : script));
214
+ return new Promise((resolve, reject) => {
215
+ const ownsProcessGroup = process.platform !== 'win32';
216
+ const child = spawn(invokeBin, spawnArgs, {
217
+ cwd,
218
+ env: spawnOptions.env ? { ...process.env, ...spawnOptions.env } : process.env,
219
+ stdio: [spawnOptions.stdin ?? 'ignore', 'pipe', 'pipe'],
220
+ detached: ownsProcessGroup,
221
+ });
222
+ let untrack;
223
+ try {
224
+ untrack = child.pid ? trackCheckoutChild(cwd, child.pid, ownsProcessGroup) : undefined;
225
+ }
226
+ catch (error) {
227
+ child.once('error', reject);
228
+ child.once('close', () => reject(error));
229
+ try {
230
+ if (ownsProcessGroup && child.pid)
231
+ process.kill(-child.pid, 'SIGKILL');
232
+ else
233
+ child.kill('SIGKILL');
234
+ }
235
+ catch (killError) {
236
+ if (killError.code !== 'ESRCH')
237
+ reject(killError);
238
+ }
239
+ return;
240
+ }
241
+ const captured = new OperationOutputTail();
242
+ let settled = false;
243
+ let didTimeout = false;
244
+ let escalation;
245
+ let forwardedParentSignal;
246
+ let parentSignalFallback;
247
+ const parentSignals = ['SIGINT', 'SIGTERM', 'SIGHUP', 'SIGQUIT'];
248
+ const removeParentSignalHandlers = () => {
249
+ for (const signal of parentSignals)
250
+ process.removeListener(signal, parentSignalHandlers[signal]);
251
+ };
252
+ const finish = (result) => {
253
+ if (settled)
254
+ return;
255
+ settled = true;
256
+ if (timer)
257
+ clearTimeout(timer);
258
+ if (escalation)
259
+ clearTimeout(escalation);
260
+ if (parentSignalFallback)
261
+ clearTimeout(parentSignalFallback);
262
+ removeParentSignalHandlers();
263
+ resolve(result);
264
+ };
265
+ const signalChildTree = (signal) => {
266
+ try {
267
+ if (ownsProcessGroup && child.pid)
268
+ process.kill(-child.pid, signal);
269
+ else
270
+ child.kill(signal);
271
+ }
272
+ catch {
273
+ // The owned child tree already exited.
274
+ }
275
+ };
276
+ const exitFromForwardedSignal = () => {
277
+ if (!forwardedParentSignal)
278
+ return;
279
+ const signal = forwardedParentSignal;
280
+ forwardedParentSignal = undefined;
281
+ if (parentSignalFallback)
282
+ clearTimeout(parentSignalFallback);
283
+ process.kill(process.pid, signal);
284
+ };
285
+ const parentSignalHandlers = Object.fromEntries(parentSignals.map((signal) => [
286
+ signal,
287
+ () => {
288
+ if (forwardedParentSignal)
289
+ return;
290
+ forwardedParentSignal = signal;
291
+ signalChildTree(signal);
292
+ removeParentSignalHandlers();
293
+ // Let a cooperative leaf finish its signal trap before this process exits.
294
+ // The bound prevents an uncooperative child tree from holding Ctrl+C open.
295
+ if (Number(spawnOptions.timeoutMs) > 0)
296
+ parentSignalFallback = setTimeout(() => {
297
+ signalChildTree('SIGKILL');
298
+ exitFromForwardedSignal();
299
+ }, 1000);
300
+ },
301
+ ]));
302
+ if (ownsProcessGroup) {
303
+ for (const signal of parentSignals)
304
+ process.once(signal, parentSignalHandlers[signal]);
305
+ }
306
+ const timeoutMs = spawnOptions.timeoutMs;
307
+ const timer = Number.isFinite(timeoutMs) && Number(timeoutMs) > 0
308
+ ? setTimeout(() => {
309
+ didTimeout = true;
310
+ const message = `leaf timed out after ${String(timeoutMs)}ms: ${path.basename(script)}`;
311
+ captured.append(`\n${message}\n`);
312
+ if (spawnOptions.forward !== 'none')
313
+ process.stderr.write(`${message}\n`);
314
+ signalChildTree('SIGTERM');
315
+ escalation = setTimeout(() => {
316
+ signalChildTree('SIGKILL');
317
+ finish({
318
+ status: 1,
319
+ output: captured.toString(),
320
+ timedOut: true,
321
+ timeoutMs: Number(timeoutMs),
322
+ });
323
+ }, 1000);
324
+ }, Number(timeoutMs))
325
+ : undefined;
326
+ // Route BOTH child streams to the parent's stderr, live: stdout is reserved
327
+ // for the harness --json envelope, so all human/leaf progress goes to stderr.
328
+ const decoders = [new StringDecoder('utf8'), new StringDecoder('utf8')];
329
+ const tee = (chunk, stdout = false) => {
330
+ if (spawnOptions.capture !== false)
331
+ captured.append(decoders[stdout ? 0 : 1].write(chunk));
332
+ recordCommandOutput(chunk);
333
+ if (spawnOptions.forward !== 'none') {
334
+ (stdout && spawnOptions.forward === 'original' ? process.stdout : process.stderr).write(chunk);
335
+ }
336
+ };
337
+ child.stdout?.on('data', (chunk) => tee(chunk, true));
338
+ child.stderr?.on('data', tee);
339
+ child.on('error', (error) => {
340
+ const leaf = isNodeScript ? path.basename(args[0]) : path.basename(script);
341
+ const code = error.code ?? 'ESPAWN';
342
+ const message = leafStartFailureMessage(leaf, code);
343
+ if (spawnOptions.forward !== 'none')
344
+ process.stderr.write(`${message}\n`);
345
+ finish({ status: 1, output: message, error });
346
+ });
347
+ child.on('exit', () => {
348
+ if (forwardedParentSignal) {
349
+ exitFromForwardedSignal();
350
+ return;
351
+ }
352
+ if (!didTimeout)
353
+ return;
354
+ signalChildTree('SIGKILL');
355
+ finish({
356
+ status: 1,
357
+ output: captured.toString(),
358
+ timedOut: true,
359
+ timeoutMs: Number(timeoutMs),
360
+ });
361
+ });
362
+ child.on('close', (status) => {
363
+ // A normal leaf exit may intentionally leave a dev server running.
364
+ // A signal/crash keeps group ownership until every member exits.
365
+ if (status !== null)
366
+ untrack?.();
367
+ if (spawnOptions.capture !== false)
368
+ captured.append(decoders.map((decoder) => decoder.end()).join(''));
369
+ if (didTimeout)
370
+ signalChildTree('SIGKILL');
371
+ finish({
372
+ status: didTimeout ? 1 : (status ?? 1),
373
+ output: captured.toString(),
374
+ ...(didTimeout ? { timedOut: true, timeoutMs: Number(timeoutMs) } : {}),
375
+ });
376
+ });
377
+ });
378
+ }
379
+ // Teaching-error emitter (exit 2, machine-readable in --json). `userAction` is
380
+ // REQUIRED: a teaching error without a reachable escape must not compile, so the
381
+ // escape is a typed parameter rather than free-form prose spliced into `message`.
382
+ export function usageOut(json, command, message, userAction) {
383
+ if (json) {
384
+ console.log(JSON.stringify({
385
+ schemaVersion: 1,
386
+ command,
387
+ status: 'fail',
388
+ exitCode: EXIT.usage,
389
+ error: { code: 'USAGE', message, userAction },
390
+ }, null, 2));
391
+ }
392
+ else {
393
+ console.error(`✗ ${harnessHost().name} ${command}: ${message}\n Next: ${userAction}`);
394
+ }
395
+ return EXIT.usage;
396
+ }
397
+ export function checkoutBusyOut(json, command, message, lockPath) {
398
+ const userAction = `wait for the current owner, or inspect ${lockPath} if its process has exited`;
399
+ if (json) {
400
+ console.log(JSON.stringify({
401
+ schemaVersion: 1,
402
+ command,
403
+ status: 'fail',
404
+ exitCode: EXIT.bounded,
405
+ recoverable: false,
406
+ error: { code: 'SANDBOX_BUSY', message, userAction },
407
+ }, null, 2));
408
+ }
409
+ else {
410
+ console.error(`✗ ${harnessHost().name} ${command}: ${message}\n Next: ${userAction}`);
411
+ }
412
+ return EXIT.bounded;
413
+ }
414
+ //# sourceMappingURL=shared.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/harness/shared.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ /** The candidate nearest `input` by edit distance, or undefined when none is close. */
2
+ export declare function closest(input: string, candidates: readonly string[]): string | undefined;
3
+ //# sourceMappingURL=suggest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"suggest.d.ts","sourceRoot":"","sources":["../../src/harness/suggest.ts"],"names":[],"mappings":"AAEA,uFAAuF;AACvF,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAYxF"}
@@ -0,0 +1,37 @@
1
+ // "Did you mean" suggestions for a mistyped command, option, value or action.
2
+ /** The candidate nearest `input` by edit distance, or undefined when none is close. */
3
+ export function closest(input, candidates) {
4
+ if (candidates.length === 0)
5
+ return undefined;
6
+ const ranked = candidates
7
+ .map((candidate) => ({ candidate, distance: levenshtein(input, candidate) }))
8
+ .sort((left, right) => left.distance - right.distance || left.candidate.localeCompare(right.candidate));
9
+ const best = ranked[0];
10
+ if (!best)
11
+ return undefined;
12
+ const threshold = Math.max(2, Math.floor(Math.max(input.length, best.candidate.length) / 3));
13
+ return best.distance <= threshold ? best.candidate : undefined;
14
+ }
15
+ // Optimal string alignment distance: an adjacent transposition costs one edit.
16
+ function levenshtein(left, right) {
17
+ let twoBack;
18
+ let prior = Array.from({ length: right.length + 1 }, (_, index) => index);
19
+ for (let leftIndex = 1; leftIndex <= left.length; leftIndex += 1) {
20
+ const current = [leftIndex];
21
+ for (let rightIndex = 1; rightIndex <= right.length; rightIndex += 1) {
22
+ const substitution = prior[rightIndex - 1] + (left[leftIndex - 1] === right[rightIndex - 1] ? 0 : 1);
23
+ current[rightIndex] = Math.min((current[rightIndex - 1] ?? 0) + 1, (prior[rightIndex] ?? 0) + 1, substitution);
24
+ if (twoBack &&
25
+ leftIndex > 1 &&
26
+ rightIndex > 1 &&
27
+ left[leftIndex - 1] === right[rightIndex - 2] &&
28
+ left[leftIndex - 2] === right[rightIndex - 1]) {
29
+ current[rightIndex] = Math.min(current[rightIndex] ?? 0, (twoBack[rightIndex - 2] ?? 0) + 1);
30
+ }
31
+ }
32
+ twoBack = prior;
33
+ prior = current;
34
+ }
35
+ return prior[right.length] ?? right.length;
36
+ }
37
+ //# sourceMappingURL=suggest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"suggest.js","sourceRoot":"","sources":["../../src/harness/suggest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import type { RecipeExecutionApproval, RecipeSourceProvenance } from '@farmslot/protocol';
2
+ /** Source provenance and plan approval from explicit flags; absent flags add nothing. */
3
+ export declare function explicitRecipeTrustOptions(values: {
4
+ sourceTrust?: string;
5
+ sourceKind?: string;
6
+ sourceName?: string;
7
+ sourceDigest?: string;
8
+ approvalDigest?: string;
9
+ }): {
10
+ source?: RecipeSourceProvenance;
11
+ approval?: RecipeExecutionApproval;
12
+ };
13
+ export type RecipeTrustFailure = {
14
+ code: string;
15
+ message: string;
16
+ userAction: string;
17
+ details?: {
18
+ recipeDigest?: string;
19
+ trust?: string;
20
+ blocked?: Array<{
21
+ nodeId: string;
22
+ action: string;
23
+ capabilities: string[];
24
+ source: string;
25
+ implementation?: {
26
+ kind?: string;
27
+ trust?: string;
28
+ digest?: string;
29
+ };
30
+ }>;
31
+ };
32
+ };
33
+ /**
34
+ * A `RECIPE_*` trust error as a command envelope, without the blocked nodes'
35
+ * payloads; undefined for any other error.
36
+ */
37
+ export declare function recipeTrustFailure(error: unknown): RecipeTrustFailure | undefined;
38
+ //# sourceMappingURL=trust.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trust.d.ts","sourceRoot":"","sources":["../../src/harness/trust.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,uBAAuB,EAEvB,sBAAsB,EAEvB,MAAM,oBAAoB,CAAC;AAE5B,yFAAyF;AACzF,wBAAgB,0BAA0B,CAAC,MAAM,EAAE;IACjD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,GAAG;IAAE,MAAM,CAAC,EAAE,sBAAsB,CAAC;IAAC,QAAQ,CAAC,EAAE,uBAAuB,CAAA;CAAE,CAe1E;AAGD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE;QACR,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,OAAO,CAAC,EAAE,KAAK,CAAC;YACd,MAAM,EAAE,MAAM,CAAC;YACf,MAAM,EAAE,MAAM,CAAC;YACf,YAAY,EAAE,MAAM,EAAE,CAAC;YACvB,MAAM,EAAE,MAAM,CAAC;YACf,cAAc,CAAC,EAAE;gBACf,IAAI,CAAC,EAAE,MAAM,CAAC;gBACd,KAAK,CAAC,EAAE,MAAM,CAAC;gBACf,MAAM,CAAC,EAAE,MAAM,CAAC;aACjB,CAAC;SACH,CAAC,CAAC;KACJ,CAAC;CACH,CAAC;AAEF;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,kBAAkB,GAAG,SAAS,CA2EjF"}
@@ -0,0 +1,89 @@
1
+ /** Source provenance and plan approval from explicit flags; absent flags add nothing. */
2
+ export function explicitRecipeTrustOptions(values) {
3
+ const { sourceTrust, sourceKind, sourceName, sourceDigest, approvalDigest } = values;
4
+ const source = sourceTrust || sourceKind || sourceName || sourceDigest
5
+ ? {
6
+ trust: (sourceTrust ?? 'unknown'),
7
+ kind: (sourceKind ?? 'recipe-file'),
8
+ ...(sourceName ? { name: sourceName } : {}),
9
+ ...(sourceDigest ? { digest: sourceDigest } : {}),
10
+ }
11
+ : undefined;
12
+ return {
13
+ ...(source ? { source } : {}),
14
+ ...(approvalDigest ? { approval: { planDigest: approvalDigest } } : {}),
15
+ };
16
+ }
17
+ /**
18
+ * A `RECIPE_*` trust error as a command envelope, without the blocked nodes'
19
+ * payloads; undefined for any other error.
20
+ */
21
+ export function recipeTrustFailure(error) {
22
+ if (!error || typeof error !== 'object')
23
+ return undefined;
24
+ const value = error;
25
+ if (typeof value.code !== 'string' ||
26
+ !value.code.startsWith('RECIPE_') ||
27
+ typeof value.message !== 'string' ||
28
+ typeof value.userAction !== 'string')
29
+ return undefined;
30
+ const failure = value.failure && typeof value.failure === 'object'
31
+ ? value.failure
32
+ : undefined;
33
+ const blocked = Array.isArray(failure?.blocked)
34
+ ? failure.blocked.flatMap((entry) => {
35
+ if (!entry || typeof entry !== 'object')
36
+ return [];
37
+ const node = entry;
38
+ if (typeof node.nodeId !== 'string' ||
39
+ typeof node.action !== 'string' ||
40
+ !Array.isArray(node.capabilities))
41
+ return [];
42
+ const origin = node.origin && typeof node.origin === 'object'
43
+ ? node.origin
44
+ : undefined;
45
+ const adapterOrigin = node.adapterOrigin && typeof node.adapterOrigin === 'object'
46
+ ? node.adapterOrigin
47
+ : undefined;
48
+ const implementation = adapterOrigin
49
+ ? {
50
+ ...(typeof adapterOrigin.kind === 'string' ? { kind: adapterOrigin.kind } : {}),
51
+ ...(typeof adapterOrigin.trust === 'string' ? { trust: adapterOrigin.trust } : {}),
52
+ ...(typeof adapterOrigin.digest === 'string' ? { digest: adapterOrigin.digest } : {}),
53
+ }
54
+ : undefined;
55
+ return [
56
+ {
57
+ nodeId: node.nodeId,
58
+ action: node.action,
59
+ capabilities: node.capabilities.filter((item) => typeof item === 'string'),
60
+ source: typeof origin?.kind === 'string' ? origin.kind : 'unknown',
61
+ ...(implementation && Object.keys(implementation).length > 0 ? { implementation } : {}),
62
+ },
63
+ ];
64
+ })
65
+ : undefined;
66
+ const recipeDigest = typeof failure?.recipeDigest === 'string' ? failure.recipeDigest : undefined;
67
+ const userAction = recipeDigest &&
68
+ (value.code === 'RECIPE_TRUST_REQUIRED' || value.code === 'RECIPE_APPROVAL_MISMATCH') &&
69
+ !value.userAction.includes('execution environment')
70
+ ? `${value.userAction}; rerun with the same project root, artifact directory, and execution environment`
71
+ : value.userAction;
72
+ return {
73
+ code: value.code,
74
+ message: value.message,
75
+ userAction,
76
+ ...(failure
77
+ ? {
78
+ details: {
79
+ // Farmslot reports the approved execution plan digest as
80
+ // recipeDigest in failures; approval input names it planDigest.
81
+ ...(recipeDigest ? { recipeDigest } : {}),
82
+ ...(typeof failure.trust === 'string' ? { trust: failure.trust } : {}),
83
+ ...(blocked?.length ? { blocked } : {}),
84
+ },
85
+ }
86
+ : {}),
87
+ };
88
+ }
89
+ //# sourceMappingURL=trust.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trust.js","sourceRoot":"","sources":["../../src/harness/trust.ts"],"names":[],"mappings":"AASA,yFAAyF;AACzF,MAAM,UAAU,0BAA0B,CAAC,MAM1C;IACC,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,cAAc,EAAE,GAAG,MAAM,CAAC;IACrF,MAAM,MAAM,GACV,WAAW,IAAI,UAAU,IAAI,UAAU,IAAI,YAAY;QACrD,CAAC,CAAC;YACE,KAAK,EAAE,CAAC,WAAW,IAAI,SAAS,CAAsB;YACtD,IAAI,EAAE,CAAC,UAAU,IAAI,aAAa,CAAqB;YACvD,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3C,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAClD;QACH,CAAC,CAAC,SAAS,CAAC;IAChB,OAAO;QACL,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7B,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,UAAU,EAAE,cAAc,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACxE,CAAC;AACJ,CAAC;AAwBD;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAc;IAC/C,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAC1D,MAAM,KAAK,GAAG,KAAgC,CAAC;IAC/C,IACE,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ;QAC9B,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;QACjC,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ;QACjC,OAAO,KAAK,CAAC,UAAU,KAAK,QAAQ;QAEpC,OAAO,SAAS,CAAC;IACnB,MAAM,OAAO,GACX,KAAK,CAAC,OAAO,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ;QAChD,CAAC,CAAE,KAAK,CAAC,OAAmC;QAC5C,CAAC,CAAC,SAAS,CAAC;IAChB,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC;QAC7C,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;YAChC,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;gBAAE,OAAO,EAAE,CAAC;YACnD,MAAM,IAAI,GAAG,KAAgC,CAAC;YAC9C,IACE,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ;gBAC/B,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ;gBAC/B,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC;gBAEjC,OAAO,EAAE,CAAC;YACZ,MAAM,MAAM,GACV,IAAI,CAAC,MAAM,IAAI,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ;gBAC5C,CAAC,CAAE,IAAI,CAAC,MAAkC;gBAC1C,CAAC,CAAC,SAAS,CAAC;YAChB,MAAM,aAAa,GACjB,IAAI,CAAC,aAAa,IAAI,OAAO,IAAI,CAAC,aAAa,KAAK,QAAQ;gBAC1D,CAAC,CAAE,IAAI,CAAC,aAAyC;gBACjD,CAAC,CAAC,SAAS,CAAC;YAChB,MAAM,cAAc,GAAG,aAAa;gBAClC,CAAC,CAAC;oBACE,GAAG,CAAC,OAAO,aAAa,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,aAAa,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC/E,GAAG,CAAC,OAAO,aAAa,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,aAAa,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBAClF,GAAG,CAAC,OAAO,aAAa,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,aAAa,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBACtF;gBACH,CAAC,CAAC,SAAS,CAAC;YACd,OAAO;gBACL;oBACE,MAAM,EAAE,IAAI,CAAC,MAAM;oBACnB,MAAM,EAAE,IAAI,CAAC,MAAM;oBACnB,YAAY,EAAE,IAAI,CAAC,YAAY,CAAC,MAAM,CACpC,CAAC,IAAI,EAAkB,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,CACnD;oBACD,MAAM,EAAE,OAAO,MAAM,EAAE,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;oBAClE,GAAG,CAAC,cAAc,IAAI,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBACxF;aACF,CAAC;QACJ,CAAC,CAAC;QACJ,CAAC,CAAC,SAAS,CAAC;IACd,MAAM,YAAY,GAAG,OAAO,OAAO,EAAE,YAAY,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC;IAClG,MAAM,UAAU,GACd,YAAY;QACZ,CAAC,KAAK,CAAC,IAAI,KAAK,uBAAuB,IAAI,KAAK,CAAC,IAAI,KAAK,0BAA0B,CAAC;QACrF,CAAC,KAAK,CAAC,UAAU,CAAC,QAAQ,CAAC,uBAAuB,CAAC;QACjD,CAAC,CAAC,GAAG,KAAK,CAAC,UAAU,mFAAmF;QACxG,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC;IACvB,OAAO;QACL,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,UAAU;QACV,GAAG,CAAC,OAAO;YACT,CAAC,CAAC;gBACE,OAAO,EAAE;oBACP,yDAAyD;oBACzD,gEAAgE;oBAChE,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBACzC,GAAG,CAAC,OAAO,OAAO,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBACtE,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBACxC;aACF;YACH,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;AACJ,CAAC"}