@fnndsc/brasa 0.23.2 → 0.25.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 (92) hide show
  1. package/dist/buildinfo.json +1 -1
  2. package/dist/builtins/fs/pull.args.d.ts +1 -1
  3. package/dist/builtins/fs/pull.args.js +5 -3
  4. package/dist/builtins/fs/pull.args.js.map +1 -1
  5. package/dist/builtins/fs/pull.js +2 -2
  6. package/dist/builtins/fs/touch.js +1 -1
  7. package/dist/builtins/fs/touch.js.map +1 -1
  8. package/dist/builtins/help.js +134 -10
  9. package/dist/builtins/help.js.map +1 -1
  10. package/dist/builtins/index.d.ts +6 -0
  11. package/dist/builtins/index.js +6 -0
  12. package/dist/builtins/index.js.map +1 -1
  13. package/dist/builtins/net/query.csv.js +14 -0
  14. package/dist/builtins/net/query.csv.js.map +1 -1
  15. package/dist/builtins/net/query.js +3 -0
  16. package/dist/builtins/net/query.js.map +1 -1
  17. package/dist/builtins/pluginExecute.js +28 -3
  18. package/dist/builtins/pluginExecute.js.map +1 -1
  19. package/dist/builtins/proc.js +32 -2
  20. package/dist/builtins/proc.js.map +1 -1
  21. package/dist/builtins/res/dicom.d.ts +35 -1
  22. package/dist/builtins/res/dicom.js +15 -2
  23. package/dist/builtins/res/dicom.js.map +1 -1
  24. package/dist/builtins/res/expect.d.ts +40 -0
  25. package/dist/builtins/res/expect.js +447 -0
  26. package/dist/builtins/res/expect.js.map +1 -0
  27. package/dist/builtins/res/gather.d.ts +10 -0
  28. package/dist/builtins/res/gather.js +224 -0
  29. package/dist/builtins/res/gather.js.map +1 -0
  30. package/dist/builtins/res/gather.store.d.ts +131 -0
  31. package/dist/builtins/res/gather.store.js +225 -0
  32. package/dist/builtins/res/gather.store.js.map +1 -0
  33. package/dist/builtins/res/pipeline.args.d.ts +5 -2
  34. package/dist/builtins/res/pipeline.args.js +8 -3
  35. package/dist/builtins/res/pipeline.args.js.map +1 -1
  36. package/dist/builtins/res/pipeline.js +23 -0
  37. package/dist/builtins/res/pipeline.js.map +1 -1
  38. package/dist/builtins/res/play.d.ts +70 -0
  39. package/dist/builtins/res/play.js +334 -0
  40. package/dist/builtins/res/play.js.map +1 -0
  41. package/dist/builtins/res/plugin.js +21 -6
  42. package/dist/builtins/res/plugin.js.map +1 -1
  43. package/dist/builtins/res/record.d.ts +49 -0
  44. package/dist/builtins/res/record.js +150 -0
  45. package/dist/builtins/res/record.js.map +1 -0
  46. package/dist/builtins/res/runWait.d.ts +49 -0
  47. package/dist/builtins/res/runWait.js +193 -0
  48. package/dist/builtins/res/runWait.js.map +1 -0
  49. package/dist/builtins/sys/motd.d.ts +41 -0
  50. package/dist/builtins/sys/motd.js +139 -0
  51. package/dist/builtins/sys/motd.js.map +1 -0
  52. package/dist/builtins/sys/weather.d.ts +132 -0
  53. package/dist/builtins/sys/weather.js +297 -0
  54. package/dist/builtins/sys/weather.js.map +1 -0
  55. package/dist/command-keys.js +4 -0
  56. package/dist/command-keys.js.map +1 -1
  57. package/dist/core/connect.d.ts +31 -1
  58. package/dist/core/connect.js +32 -1
  59. package/dist/core/connect.js.map +1 -1
  60. package/dist/core/dispatch.d.ts +0 -14
  61. package/dist/core/dispatch.js +85 -27
  62. package/dist/core/dispatch.js.map +1 -1
  63. package/dist/core/engine.d.ts +10 -0
  64. package/dist/core/engine.js +9 -0
  65. package/dist/core/engine.js.map +1 -1
  66. package/dist/core/expansion.d.ts +70 -0
  67. package/dist/core/expansion.js +289 -0
  68. package/dist/core/expansion.js.map +1 -0
  69. package/dist/core/promptContext.js +5 -1
  70. package/dist/core/promptContext.js.map +1 -1
  71. package/dist/lib/duration.d.ts +17 -0
  72. package/dist/lib/duration.js +25 -0
  73. package/dist/lib/duration.js.map +1 -0
  74. package/dist/lib/parser.d.ts +50 -0
  75. package/dist/lib/parser.js +119 -0
  76. package/dist/lib/parser.js.map +1 -1
  77. package/dist/logo/brain.d.ts +6 -27
  78. package/dist/logo/brain.js +5 -250
  79. package/dist/logo/brain.js.map +1 -1
  80. package/dist/session/answer.d.ts +141 -0
  81. package/dist/session/answer.js +163 -0
  82. package/dist/session/answer.js.map +1 -0
  83. package/dist/session/answerAdapters.d.ts +4 -0
  84. package/dist/session/answerAdapters.js +106 -0
  85. package/dist/session/answerAdapters.js.map +1 -0
  86. package/dist/session/recent.d.ts +68 -0
  87. package/dist/session/recent.js +99 -0
  88. package/dist/session/recent.js.map +1 -0
  89. package/dist/session/recorder.d.ts +61 -0
  90. package/dist/session/recorder.js +95 -0
  91. package/dist/session/recorder.js.map +1 -0
  92. package/package.json +5 -5
@@ -0,0 +1,40 @@
1
+ import { CommandEnvelope } from '@fnndsc/cumin';
2
+ import { duration_parse } from '../../lib/duration.js';
3
+ export { duration_parse };
4
+ /** The model kind under which a checked claim travels to a surface. */
5
+ export declare const EXPECT_MODEL_KIND: string;
6
+ /** What a claim turned out to be. */
7
+ export interface ExpectVerdict {
8
+ /** What was asked about, as the operator wrote it. */
9
+ claim: string;
10
+ /** Whether the claim held. */
11
+ held: boolean;
12
+ /** The value asked for. */
13
+ wanted: string;
14
+ /** The value found; absent when the subject could not be read at all. */
15
+ got: string | null;
16
+ /** Why the subject could not answer, when it could not. */
17
+ refusal?: string;
18
+ /** How long the claim was waited on. */
19
+ waitedMs: number;
20
+ }
21
+ /**
22
+ * Compares what was found against what was wanted.
23
+ *
24
+ * @param got - The value the session answered.
25
+ * @param predicate - How to compare.
26
+ * @param wanted - The value the claim asked for.
27
+ * @returns Whether the claim holds, or a refusal when the comparison is not meaningful.
28
+ */
29
+ export declare function claim_holds(got: string, predicate: string, wanted: string): {
30
+ held: boolean;
31
+ } | {
32
+ refusal: string;
33
+ };
34
+ /**
35
+ * Builtin handler for the `expect` command.
36
+ *
37
+ * @param args - Parsed command arguments.
38
+ * @returns An ok envelope when the claim holds, an error envelope when it does not.
39
+ */
40
+ export declare function builtin_expect(args: string[]): Promise<CommandEnvelope>;
@@ -0,0 +1,447 @@
1
+ /**
2
+ * @file Builtin expect command: a claim the session can refuse.
3
+ *
4
+ * A workflow that only acts is a demonstration. `expect` is what makes one a
5
+ * TEST: it states a claim about the session — how many things are gathered,
6
+ * what a feed's status is, what a produced file's tags say — and refuses,
7
+ * non-zero, when the claim does not hold. Because it is a verb rather than a
8
+ * harness, a workflow asserts wherever it is played: in CI, at an operator's
9
+ * console, or in someone else's browser after they were handed the file.
10
+ *
11
+ * Time lives here and nowhere else. `--within` polls until the claim holds or
12
+ * the deadline passes, which is why no other verb needs a timeout and why the
13
+ * language has no sleep: a sleep asserts nothing and lies about how long the
14
+ * work actually took.
15
+ *
16
+ * @module
17
+ */
18
+ import chalk from 'chalk';
19
+ import path from 'path';
20
+ import { envelope_ok, envelope_error, procCache_get } from '@fnndsc/cumin';
21
+ import { jobs_statusBatch } from '@fnndsc/salsa';
22
+ import { commandArgs_process, path_resolve } from '../utils.js';
23
+ import { duration_parse } from '../../lib/duration.js';
24
+ export { duration_parse };
25
+ import { vfs } from '../../lib/vfs/vfs.js';
26
+ import { cohort_read } from './gather.store.js';
27
+ import { path_physical, tagsModel_read } from './dicom.js';
28
+ import { feedStatus_derive } from '../proc.helpers.js';
29
+ import { commandCancellation_enable, commandCancellation_signalGet } from '../../core/cancellation.js';
30
+ /** The model kind under which a checked claim travels to a surface. */
31
+ export const EXPECT_MODEL_KIND = 'expect.result';
32
+ /** How the two sides of a claim are compared. */
33
+ const PREDICATES = [
34
+ 'eq', 'ne', 'gt', 'gte', 'lt', 'lte', 'contains', 'notContains', 'matches',
35
+ ];
36
+ /** What a claim can be about. */
37
+ const SUBJECTS = ['gather', 'feed', 'run', 'path'];
38
+ /** Predicates that only mean anything about numbers. */
39
+ const NUMERIC_PREDICATES = new Set(['gt', 'gte', 'lt', 'lte']);
40
+ /** How often a waiting claim asks again. */
41
+ const RECHECK_MS = 2000;
42
+ /**
43
+ * Compares what was found against what was wanted.
44
+ *
45
+ * @param got - The value the session answered.
46
+ * @param predicate - How to compare.
47
+ * @param wanted - The value the claim asked for.
48
+ * @returns Whether the claim holds, or a refusal when the comparison is not meaningful.
49
+ */
50
+ export function claim_holds(got, predicate, wanted) {
51
+ if (NUMERIC_PREDICATES.has(predicate)) {
52
+ const left = Number(got);
53
+ const right = Number(wanted);
54
+ if (Number.isNaN(left) || Number.isNaN(right)) {
55
+ return { refusal: `${predicate} compares numbers, and "${Number.isNaN(left) ? got : wanted}" is not one` };
56
+ }
57
+ if (predicate === 'gt')
58
+ return { held: left > right };
59
+ if (predicate === 'gte')
60
+ return { held: left >= right };
61
+ if (predicate === 'lt')
62
+ return { held: left < right };
63
+ return { held: left <= right };
64
+ }
65
+ if (predicate === 'eq' || predicate === 'ne') {
66
+ // A count read back as text and a count written as a number are the same
67
+ // claim: 14 and "14" must not disagree because one came from a table.
68
+ const numeric = got.trim() !== '' && wanted.trim() !== ''
69
+ && !Number.isNaN(Number(got)) && !Number.isNaN(Number(wanted));
70
+ const same = numeric ? Number(got) === Number(wanted) : got === wanted;
71
+ return { held: predicate === 'eq' ? same : !same };
72
+ }
73
+ if (predicate === 'contains')
74
+ return { held: got.includes(wanted) };
75
+ if (predicate === 'notContains')
76
+ return { held: !got.includes(wanted) };
77
+ try {
78
+ return { held: new RegExp(wanted).test(got) };
79
+ }
80
+ catch {
81
+ return { refusal: `matches needs a regular expression, and "${wanted}" is not one` };
82
+ }
83
+ }
84
+ /**
85
+ * Reads how much of the cohort is home.
86
+ *
87
+ * A place gathered from the filesystem was never anywhere else, so it counts
88
+ * as home; a series counts once CUBE has said where it landed.
89
+ *
90
+ * @param state - The cohort.
91
+ * @returns How many members are in CUBE.
92
+ */
93
+ function cohortPulled_count(state) {
94
+ return state.series.filter((member) => {
95
+ if (member.kind !== 'series')
96
+ return true;
97
+ const landed = member.folderPath;
98
+ return typeof landed === 'string' && landed.length > 0;
99
+ }).length;
100
+ }
101
+ /**
102
+ * Answers a claim about the cohort.
103
+ *
104
+ * @param property - `size` or `pulled`.
105
+ * @returns What the cohort says.
106
+ */
107
+ async function gather_read(property) {
108
+ const state = await cohort_read();
109
+ if (property === 'size')
110
+ return { got: `${state.series.length}` };
111
+ if (property === 'pulled')
112
+ return { got: `${cohortPulled_count(state)}` };
113
+ if (property === 'name')
114
+ return { got: state.name ?? '' };
115
+ return { got: null, refusal: `gather has no property "${property}" — try size, pulled or name` };
116
+ }
117
+ /**
118
+ * Answers a claim about a feed.
119
+ *
120
+ * @param target - The feed id.
121
+ * @param property - `status` today.
122
+ * @returns What the feed says.
123
+ */
124
+ async function feed_read(target, property) {
125
+ const feedID = Number(target);
126
+ if (!Number.isInteger(feedID))
127
+ return { got: null, refusal: `"${target}" is not a feed id` };
128
+ if (property !== 'status')
129
+ return { got: null, refusal: `feed has no property "${property}" — try status` };
130
+ const feed = procCache_get().feed_get(feedID);
131
+ if (feed === undefined || feed === null) {
132
+ return { got: null, refusal: `feed ${feedID} is not in this session's index yet` };
133
+ }
134
+ return { got: feedStatus_derive(feed) };
135
+ }
136
+ /**
137
+ * Answers a claim about one run.
138
+ *
139
+ * @param target - The plugin instance id.
140
+ * @param property - `status` today.
141
+ * @returns What the run says.
142
+ */
143
+ async function run_read(target, property) {
144
+ const instanceID = Number(target);
145
+ if (!Number.isInteger(instanceID))
146
+ return { got: null, refusal: `"${target}" is not an instance id` };
147
+ if (property !== 'status')
148
+ return { got: null, refusal: `run has no property "${property}" — try status` };
149
+ const statuses = await jobs_statusBatch([instanceID]);
150
+ const status = statuses.get(instanceID);
151
+ if (status === undefined)
152
+ return { got: null, refusal: `instance ${instanceID} did not answer` };
153
+ return { got: status };
154
+ }
155
+ /** How far beneath a named folder a claim will look for what it was asked about. */
156
+ const DEEP_MAX = 4;
157
+ /**
158
+ * Walks a folder, gathering what it holds and the folders under it.
159
+ *
160
+ * A plugin's output is routinely NESTED — pfdicom writes under
161
+ * `share/incoming/<input tree>`, and a converter mirrors its input — so a
162
+ * claim about what a run produced, made at the node's own folder, would be
163
+ * false about a run that worked perfectly. The walk is bounded: a claim is
164
+ * a question about a result, not a crawl of the filesystem.
165
+ *
166
+ * @param root - Where to start.
167
+ * @param depth - How many levels below the root to visit.
168
+ * @returns Every item found, with the folder each was found in.
169
+ */
170
+ async function folder_walkDeep(root, depth) {
171
+ const found = [];
172
+ const queue = [{ path: root, level: 0 }];
173
+ while (queue.length > 0) {
174
+ const here = queue.shift();
175
+ const listed = await vfs.data_get(here.path);
176
+ if (!listed.ok)
177
+ continue;
178
+ for (const item of listed.value) {
179
+ found.push({ folder: here.path, item });
180
+ if (item.type === 'dir' && here.level < depth) {
181
+ queue.push({ path: `${here.path.replace(/\/$/, '')}/${item.name}`, level: here.level + 1 });
182
+ }
183
+ }
184
+ }
185
+ return found;
186
+ }
187
+ /**
188
+ * Turns a shell-style pattern into a matcher.
189
+ *
190
+ * @param pattern - A glob such as `*.nii*`.
191
+ * @returns A regular expression anchored to the whole name.
192
+ */
193
+ function glob_toRegExp(pattern) {
194
+ const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, '\\$&')
195
+ .replace(/\*/g, '.*')
196
+ .replace(/\?/g, '.');
197
+ return new RegExp(`^${escaped}$`);
198
+ }
199
+ /**
200
+ * Answers a claim about a path: whether it is there, what it holds, what its
201
+ * headers say.
202
+ *
203
+ * @param target - The path, as the operator wrote it.
204
+ * @param property - `exists`, `count`, or `tags`.
205
+ * @param tagName - The tag to read, when the property is `tags`.
206
+ * @param matching - A glob narrowing a count.
207
+ * @param deep - Look beneath the folder, not only in it.
208
+ * @returns What the path says.
209
+ */
210
+ async function path_read(target, property, tagName, matching, deep) {
211
+ const resolved = await path_resolve(target);
212
+ if (property === 'exists') {
213
+ const listed = await vfs.data_get(resolved);
214
+ if (listed.ok)
215
+ return { got: 'true' };
216
+ // A file is not a listing: its parent knows it.
217
+ const parent = await vfs.data_get(path.posix.dirname(resolved));
218
+ if (!parent.ok)
219
+ return { got: 'false' };
220
+ const leaf = path.posix.basename(resolved);
221
+ return { got: `${parent.value.some((item) => item.name === leaf)}` };
222
+ }
223
+ if (property === 'count') {
224
+ if (deep) {
225
+ const walked = await folder_walkDeep(resolved, DEEP_MAX);
226
+ const files = walked
227
+ .map((entry) => entry.item)
228
+ .filter((item) => item.type !== 'dir');
229
+ if (matching === undefined)
230
+ return { got: `${files.length}` };
231
+ const deepPattern = glob_toRegExp(matching);
232
+ return { got: `${files.filter((item) => deepPattern.test(item.name)).length}` };
233
+ }
234
+ const listed = await vfs.data_get(resolved);
235
+ if (!listed.ok)
236
+ return { got: null, refusal: `${resolved} cannot be listed` };
237
+ if (matching === undefined)
238
+ return { got: `${listed.value.length}` };
239
+ const pattern = glob_toRegExp(matching);
240
+ return { got: `${listed.value.filter((item) => pattern.test(item.name)).length}` };
241
+ }
242
+ if (property === 'tags') {
243
+ if (tagName === undefined)
244
+ return { got: null, refusal: 'expect path <p> tags <TagName> <predicate> <value>' };
245
+ const physical = await path_physical(resolved);
246
+ let model = await tagsModel_read(physical);
247
+ if (!model.ok) {
248
+ // A plugin's output is routinely nested, so a tag claim made at the
249
+ // node's own folder looks BENEATH it before giving up: the files a run
250
+ // produced are what the claim is about, wherever the plugin filed them.
251
+ const walked = await folder_walkDeep(resolved, DEEP_MAX);
252
+ const folders = [...new Set(walked
253
+ .filter((entry) => entry.item.type === 'dir')
254
+ .map((entry) => `${entry.folder.replace(/\/$/, '')}/${entry.item.name}`))];
255
+ for (const folder of folders) {
256
+ const beneath = await tagsModel_read(await path_physical(folder));
257
+ if (beneath.ok) {
258
+ model = beneath;
259
+ break;
260
+ }
261
+ }
262
+ }
263
+ if (!model.ok)
264
+ return { got: null, refusal: `${resolved} holds no readable DICOM, here or beneath it` };
265
+ const constant = model.value.constant.find((tag) => tag.name === tagName || tag.tag === tagName);
266
+ if (constant !== undefined)
267
+ return { got: constant.value };
268
+ // A tag that varies across the folder answers with every value it takes,
269
+ // so a claim about "the" value cannot pass by reading only the first file.
270
+ const varying = model.value.varying.find((tag) => tag.name === tagName || tag.tag === tagName);
271
+ if (varying !== undefined) {
272
+ const values = [...new Set(varying.values
273
+ .map((entry) => entry.value ?? '')
274
+ .filter((value) => value.length > 0))];
275
+ return { got: values.join(', ') };
276
+ }
277
+ return { got: '' };
278
+ }
279
+ return { got: null, refusal: `path has no property "${property}" — try exists, count or tags` };
280
+ }
281
+ /**
282
+ * Asks the session once.
283
+ *
284
+ * @param subject - What the claim is about.
285
+ * @param target - Which one, for the subjects that need naming.
286
+ * @param property - What about it.
287
+ * @param tagName - The tag, when the property is `tags`.
288
+ * @param matching - A glob, when the property is `count`.
289
+ * @param deep - Whether to look beneath the path as well as in it.
290
+ * @returns What the session answered.
291
+ */
292
+ async function subject_read(subject, target, property, tagName, matching, deep) {
293
+ if (subject === 'gather')
294
+ return await gather_read(property);
295
+ if (subject === 'feed')
296
+ return await feed_read(target ?? '', property);
297
+ if (subject === 'run')
298
+ return await run_read(target ?? '', property);
299
+ if (subject === 'path')
300
+ return await path_read(target ?? '', property, tagName, matching, deep);
301
+ return { got: null, refusal: `expect knows nothing about "${subject}" — try gather, feed, run or path` };
302
+ }
303
+ /**
304
+ * Sleeps between asks, unless the command is cancelled first.
305
+ *
306
+ * @param ms - How long to wait.
307
+ * @param signal - The foreground command's abort signal.
308
+ * @returns True when the sleep completed.
309
+ */
310
+ async function pause_take(ms, signal) {
311
+ if (signal?.aborted === true)
312
+ return false;
313
+ return await new Promise((resolve) => {
314
+ const onAbort = () => { clearTimeout(timer); resolve(false); };
315
+ const timer = setTimeout(() => {
316
+ signal?.removeEventListener('abort', onAbort);
317
+ resolve(true);
318
+ }, ms);
319
+ signal?.addEventListener('abort', onAbort, { once: true });
320
+ });
321
+ }
322
+ /**
323
+ * Renders a claim the way it was made, for the readout.
324
+ *
325
+ * @param parts - The claim's words.
326
+ * @returns One line.
327
+ */
328
+ function claim_render(parts) {
329
+ return parts.filter((part) => part.length > 0).join(' ');
330
+ }
331
+ /**
332
+ * Builtin handler for the `expect` command.
333
+ *
334
+ * @param args - Parsed command arguments.
335
+ * @returns An ok envelope when the claim holds, an error envelope when it does not.
336
+ */
337
+ export async function builtin_expect(args) {
338
+ // `--deep` carries no value: undeclared, the parser hands it the next
339
+ // operand — which is the COMPARISON — and the claim loses its predicate.
340
+ const parsed = commandArgs_process(args, { booleanLongOptions: ['deep'] });
341
+ const operands = parsed._;
342
+ const subject = operands[0];
343
+ if (subject === undefined) {
344
+ process.exitCode = 1;
345
+ return envelope_error('', undefined, `${chalk.red('Usage: expect <gather|feed|run|path> [<target>] <property> [<predicate> <value>] [--within <duration>]')}\n`);
346
+ }
347
+ // The subject is checked FIRST: read as a shape instead, an unknown
348
+ // subject refuses by complaining about whatever word happened to land
349
+ // where a comparison goes, which names the wrong fault.
350
+ if (!SUBJECTS.includes(subject)) {
351
+ process.exitCode = 1;
352
+ return envelope_error('', undefined, `${chalk.red(`expect knows nothing about "${subject}" — try ${SUBJECTS.join(', ')}.`)}\n`);
353
+ }
354
+ // `gather` is the one subject that names nothing: there is one cohort.
355
+ const named = subject !== 'gather';
356
+ const target = named ? operands[1] : undefined;
357
+ const property = named ? operands[2] : operands[1];
358
+ const rest = named ? operands.slice(3) : operands.slice(2);
359
+ const tagName = property === 'tags' ? rest.shift() : undefined;
360
+ if (property === undefined) {
361
+ process.exitCode = 1;
362
+ return envelope_error('', undefined, `${chalk.red(`expect ${subject}: say what about it — a property such as size, status, exists or count.`)}\n`);
363
+ }
364
+ // `expect path <p> exists` is the claim in full; everything else compares.
365
+ const predicate = rest[0] ?? (property === 'exists' ? 'eq' : '');
366
+ const wanted = rest[1] ?? (property === 'exists' ? 'true' : '');
367
+ if (predicate === '' || !PREDICATES.includes(predicate)) {
368
+ process.exitCode = 1;
369
+ return envelope_error('', undefined, `${chalk.red(`expect: "${predicate}" is not a comparison — use ${PREDICATES.join(', ')}.`)}\n`);
370
+ }
371
+ let deadlineMs = 0;
372
+ if (typeof parsed.within === 'string') {
373
+ const parsedWait = duration_parse(parsed.within);
374
+ if (parsedWait === null) {
375
+ process.exitCode = 1;
376
+ return envelope_error('', undefined, `${chalk.red(`expect: --within takes a duration such as 30s, 20m or 2h, not "${parsed.within}".`)}\n`);
377
+ }
378
+ deadlineMs = parsedWait;
379
+ }
380
+ // The claim is printed as it was MADE, narrowing included: a ✓ reading
381
+ // `count gt 0` for a claim that was about `*.nii*` says the wrong thing
382
+ // held, and a battery is read by people who were not there.
383
+ const narrowing = matching_get(parsed) === undefined ? '' : `--matching '${matching_get(parsed)}'`;
384
+ const claim = claim_render([
385
+ subject, target ?? '', property, tagName ?? '', narrowing,
386
+ parsed.deep === true ? '--deep' : '', predicate, wanted,
387
+ ]);
388
+ const started = Date.now();
389
+ if (deadlineMs > 0)
390
+ commandCancellation_enable();
391
+ const signal = deadlineMs > 0 ? commandCancellation_signalGet() : undefined;
392
+ let reading = { got: null };
393
+ let outcome = { held: false };
394
+ for (;;) {
395
+ reading = await subject_read(subject, target, property, tagName, matching_get(parsed), parsed.deep === true);
396
+ if (reading.got !== null) {
397
+ outcome = claim_holds(reading.got, predicate, wanted);
398
+ if ('refusal' in outcome)
399
+ break;
400
+ if (outcome.held)
401
+ break;
402
+ }
403
+ const elapsed = Date.now() - started;
404
+ if (elapsed >= deadlineMs)
405
+ break;
406
+ const slept = await pause_take(Math.min(RECHECK_MS, deadlineMs - elapsed), signal);
407
+ if (!slept)
408
+ break;
409
+ }
410
+ const waitedMs = Date.now() - started;
411
+ const held = 'held' in outcome && outcome.held && reading.got !== null;
412
+ const refusal = 'refusal' in outcome ? outcome.refusal : reading.refusal;
413
+ const verdict = {
414
+ claim,
415
+ held,
416
+ wanted,
417
+ got: reading.got,
418
+ ...(refusal !== undefined ? { refusal } : {}),
419
+ waitedMs,
420
+ };
421
+ const model = { kind: EXPECT_MODEL_KIND, data: verdict };
422
+ if (held) {
423
+ const took = deadlineMs > 0 ? chalk.gray(` (${Math.round(waitedMs / 1000)}s)`) : '';
424
+ return envelope_ok(`${chalk.green('✓')} ${claim}${took}\n`, model);
425
+ }
426
+ process.exitCode = 1;
427
+ const lines = [
428
+ chalk.red(`✗ ${claim}`),
429
+ ` wanted ${wanted}`,
430
+ ` got ${reading.got ?? '—'}`,
431
+ ];
432
+ if (refusal !== undefined)
433
+ lines.push(` because ${refusal}`);
434
+ if (deadlineMs > 0)
435
+ lines.push(chalk.gray(` waited ${Math.round(waitedMs / 1000)}s of ${Math.round(deadlineMs / 1000)}s`));
436
+ return envelope_error('', undefined, `${lines.join('\n')}\n`);
437
+ }
438
+ /**
439
+ * The glob narrowing a count, when one was given.
440
+ *
441
+ * @param parsed - The parsed arguments.
442
+ * @returns The pattern, or undefined.
443
+ */
444
+ function matching_get(parsed) {
445
+ return typeof parsed.matching === 'string' ? parsed.matching : undefined;
446
+ }
447
+ //# sourceMappingURL=expect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expect.js","sourceRoot":"","sources":["../../../src/builtins/res/expect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { CommandEnvelope } from '@fnndsc/cumin';
2
+ /** The model kind under which a cohort travels to a surface. */
3
+ export declare const GATHER_MODEL_KIND: string;
4
+ /**
5
+ * Builtin handler for the `gather` command.
6
+ *
7
+ * @param args - Parsed command arguments.
8
+ * @returns An envelope carrying the cohort, or a usage refusal.
9
+ */
10
+ export declare function builtin_gather(args: string[]): Promise<CommandEnvelope>;