@orkestrel/toolbox 0.0.12 → 0.0.13

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.
@@ -9,29 +9,33 @@ import { createTool } from "@orkestrel/tool";
9
9
  import { createForm, isFormError, isFormValues, parseForm } from "@orkestrel/form";
10
10
  //#region src/core/constants.ts
11
11
  /**
12
- * Holds the name {@link import('./factories.js').createAgentTool} advertises by default — the key a
13
- * model calls and the `ToolManagerInterface` (`@orkestrel/tool`) registers under.
12
+ * Holds the name {@link import('./factories.js').createAgentTool} advertises by default, `'agent'`
13
+ * — the key a model calls and the `ToolManagerInterface` (`@orkestrel/tool`) registers under.
14
14
  */
15
15
  var AGENT_TOOL_NAME = "agent";
16
16
  /**
17
17
  * Holds the maximum nesting depth a delegation chain (agent tool → sub-agent → agent tool → …) may
18
- * reach — the bound {@link import('./factories.js').createAgentTool}'s depth/cycle guard
18
+ * reach, `8` — the bound {@link import('./factories.js').createAgentTool}'s depth/cycle guard
19
19
  * enforces.
20
20
  *
21
21
  * @remarks
22
- * Deliberately a SEPARATE constant from {@link MAX_WORKFLOW_CHAIN} (rather than the two guards
23
- * sharing one reference): the two guards bound DIFFERENT chains (workflow nesting vs. agent
22
+ * Deliberately a separate constant from {@link MAX_WORKFLOW_CHAIN} (rather than the guards
23
+ * sharing one reference): they bound different chains (workflow nesting against agent
24
24
  * delegation) that happen to share a value today, and keeping this bound decoupled means a
25
25
  * future change to one never silently shifts the other. Same numeric value by convention, not
26
26
  * by shared reference.
27
27
  */
28
28
  var AGENT_TOOL_DEPTH = 8;
29
29
  /**
30
- * Holds the lean {@link import('@orkestrel/tool').ToolInterface.summary} {@link import('./factories.js').createAgentTool}
31
- * advertises in place of {@link AGENT_TOOL_DESCRIPTION} — a `ToolManagerInterface.definitions()`
32
- * (`@orkestrel/tool`) advertises `summary ?? description`, so this one-sentence text stands in
33
- * for the full teaching description; the full text stays retrievable through
34
- * {@link import('./factories.js').createDescribeTool}.
30
+ * Holds the lean {@link import('@orkestrel/tool').ToolInterface.summary}
31
+ * {@link import('./factories.js').createAgentTool} advertises in place of
32
+ * {@link AGENT_TOOL_DESCRIPTION} — one sentence offering sub-agent delegation and pointing at
33
+ * `describe` for the optional overrides.
34
+ *
35
+ * @remarks
36
+ * A `ToolManagerInterface.definitions()` call (`@orkestrel/tool`) advertises
37
+ * `summary ?? description`, so this one-sentence text stands in for the full teaching description;
38
+ * the full text stays retrievable through {@link import('./factories.js').createDescribeTool}.
35
39
  */
36
40
  var AGENT_TOOL_SUMMARY = "Delegate a task to a sub-agent and return its result; each call runs one sub-agent turn to completion. Call describe('agent') for the optional provider/tools/system overrides.";
37
41
  /**
@@ -51,7 +55,7 @@ var AGENT_TOOL_DESCRIPTION = [
51
55
  JSON.stringify({ task: "Summarize the attached notes in three bullet points." })
52
56
  ].join("\n");
53
57
  /**
54
- * Holds the maximum nesting depth a workflow → agent → workflow chain may reach — the bound
58
+ * Holds the maximum nesting depth a workflow → agent → workflow chain may reach, `8` — the bound
55
59
  * {@link import('./factories.js').createAgentFunction} and
56
60
  * {@link import('./factories.js').createWorkflowTool}'s depth/cycle guards enforce.
57
61
  *
@@ -62,40 +66,40 @@ var AGENT_TOOL_DESCRIPTION = [
62
66
  */
63
67
  var MAX_WORKFLOW_CHAIN = 8;
64
68
  /**
65
- * Holds the name {@link import('./factories.js').createWorkflowTool} advertises by default — the key a
66
- * model calls and the `ToolManagerInterface` (`@orkestrel/tool`) registers under, and the name
67
- * {@link import('./factories.js').createAgentFunction} binds the depth/cycle-aware workflow tool
68
- * under onto a wrapped agent's `context.tools`.
69
+ * Holds the name {@link import('./factories.js').createWorkflowTool} advertises by default,
70
+ * `'workflow'` — the key a model calls and the `ToolManagerInterface` (`@orkestrel/tool`) registers
71
+ * under, and the name {@link import('./factories.js').createAgentFunction} binds the
72
+ * depth/cycle-aware workflow tool under onto a wrapped agent's `context.tools`.
69
73
  *
70
74
  * @remarks
71
75
  * The propagation seam's well-known key: when
72
76
  * `createAgentFunction`'s `runner` option is supplied, it adds a `createWorkflowTool`-built tool
73
- * under this name to the agent's `context.tools`, so it can author + run a NESTED workflow
77
+ * under this name to the agent's `context.tools`, so it can author and run a nested workflow
74
78
  * (bounded by {@link MAX_WORKFLOW_CHAIN}).
75
79
  */
76
80
  var WORKFLOW_TOOL_NAME = "workflow";
77
81
  /**
78
- * Holds a complete FLAT authoring example — the PRIMARY way a small model authors a workflow through
79
- * {@link import('./factories.js').createWorkflowTool}: `{ name, steps: [{ name }] }`.
82
+ * Holds a complete flat authoring example — the primary way a small model authors a workflow
83
+ * through {@link import('./factories.js').createWorkflowTool}: `{ name, steps: [{ name }] }`.
80
84
  *
81
85
  * @remarks
82
86
  * Each step becomes a one-task phase, in
83
- * order; a step's `name` is a REGISTERED behavior name (not a label) — the registry key its
87
+ * order; a step's `name` is a registered behavior name (not a label) — the registry key its
84
88
  * task's `behavior` resolves against. The tool expands this
85
89
  * ({@link import('./helpers.js').expandSteps}) into a valid `WorkflowDefinition`
86
- * (`@orkestrel/workflow`). It is embedded VERBATIM in {@link WORKFLOW_TOOL_DESCRIPTION}.
90
+ * (`@orkestrel/workflow`). It is embedded verbatim in {@link WORKFLOW_TOOL_DESCRIPTION}.
87
91
  */
88
92
  var WORKFLOW_TOOL_FLAT_EXAMPLE = Object.freeze({
89
93
  name: "release",
90
94
  steps: Object.freeze([Object.freeze({ name: "compile" }), Object.freeze({ name: "publish" })])
91
95
  });
92
96
  /**
93
- * Holds a minimal NESTED authoring example — the ADVANCED escape-hatch form a model may use instead of
94
- * the flat shape: a full `WorkflowDefinition` (`@orkestrel/workflow`).
97
+ * Holds a minimal nested authoring example — the advanced escape-hatch form a model can use instead
98
+ * of the flat shape: a full `WorkflowDefinition` (`@orkestrel/workflow`).
95
99
  *
96
100
  * @remarks
97
- * The full four-level form, documented in
98
- * {@link WORKFLOW_TOOL_DESCRIPTION} as the advanced alternative. It is embedded VERBATIM.
101
+ * The full nested form, documented in
102
+ * {@link WORKFLOW_TOOL_DESCRIPTION} as the advanced alternative. It is embedded verbatim.
99
103
  */
100
104
  var WORKFLOW_TOOL_NESTED_EXAMPLE = Object.freeze({
101
105
  id: "release",
@@ -111,11 +115,15 @@ var WORKFLOW_TOOL_NESTED_EXAMPLE = Object.freeze({
111
115
  })])
112
116
  });
113
117
  /**
114
- * Holds the lean {@link import('@orkestrel/tool').ToolInterface.summary} {@link import('./factories.js').createWorkflowTool}
115
- * advertises in place of {@link WORKFLOW_TOOL_DESCRIPTION} — a `ToolManagerInterface.definitions()`
116
- * (`@orkestrel/tool`) advertises `summary ?? description`, so this one-sentence text stands in
117
- * for the full teaching description; the full text stays retrievable through
118
- * {@link import('./factories.js').createDescribeTool}.
118
+ * Holds the lean {@link import('@orkestrel/tool').ToolInterface.summary}
119
+ * {@link import('./factories.js').createWorkflowTool} advertises in place of
120
+ * {@link WORKFLOW_TOOL_DESCRIPTION} — one sentence offering multi-phase authoring and pointing at
121
+ * `describe` for the authoring schema and its examples.
122
+ *
123
+ * @remarks
124
+ * A `ToolManagerInterface.definitions()` call (`@orkestrel/tool`) advertises
125
+ * `summary ?? description`, so this one-sentence text stands in for the full teaching description;
126
+ * the full text stays retrievable through {@link import('./factories.js').createDescribeTool}.
119
127
  */
120
128
  var WORKFLOW_TOOL_SUMMARY = "Author and run a multi-phase workflow in one call — phases run in sequence, tasks within a phase run concurrently. Call describe('workflow') for the full authoring schema and examples.";
121
129
  /**
@@ -138,13 +146,14 @@ var WORKFLOW_TOOL_DESCRIPTION = [
138
146
  "In the nested form you may omit any \"id\"/\"name\" and they are filled in positionally; a provided one is kept."
139
147
  ].join("\n");
140
148
  /**
141
- * Holds the name {@link import('./factories.js').createWorkspaceTool} advertises by default — the key a
142
- * model calls and the `ToolManagerInterface` (`@orkestrel/tool`) registers under.
149
+ * Holds the name {@link import('./factories.js').createWorkspaceTool} advertises by default,
150
+ * `'workspace'` — the key a model calls and the `ToolManagerInterface` (`@orkestrel/tool`)
151
+ * registers under.
143
152
  */
144
153
  var WORKSPACE_TOOL_NAME = "workspace";
145
154
  /**
146
- * Holds a valid {@link import('./types.js').WorkspaceOperation} object — the canonical example embedded
147
- * VERBATIM in {@link WORKSPACE_TOOL_DESCRIPTION}.
155
+ * Holds a valid {@link import('./types.js').WorkspaceOperation} object — the canonical example
156
+ * embedded verbatim in {@link WORKSPACE_TOOL_DESCRIPTION}.
148
157
  *
149
158
  * @remarks
150
159
  * A `'write'` op (the most common authoring
@@ -157,11 +166,15 @@ var WORKSPACE_TOOL_EXAMPLE = Object.freeze({
157
166
  content: "hello"
158
167
  });
159
168
  /**
160
- * Holds the lean {@link import('@orkestrel/tool').ToolInterface.summary} {@link import('./factories.js').createWorkspaceTool}
161
- * advertises in place of {@link WORKSPACE_TOOL_DESCRIPTION} — a `ToolManagerInterface.definitions()`
162
- * (`@orkestrel/tool`) advertises `summary ?? description`, so this one-sentence text stands in
163
- * for the full teaching description; the full text stays retrievable through
164
- * {@link import('./factories.js').createDescribeTool}.
169
+ * Holds the lean {@link import('@orkestrel/tool').ToolInterface.summary}
170
+ * {@link import('./factories.js').createWorkspaceTool} advertises in place of
171
+ * {@link WORKSPACE_TOOL_DESCRIPTION} — one sentence offering the `operation`-keyed file editing and
172
+ * pointing at `describe` for the operation list and its fields.
173
+ *
174
+ * @remarks
175
+ * A `ToolManagerInterface.definitions()` call (`@orkestrel/tool`) advertises
176
+ * `summary ?? description`, so this one-sentence text stands in for the full teaching description;
177
+ * the full text stays retrievable through {@link import('./factories.js').createDescribeTool}.
165
178
  */
166
179
  var WORKSPACE_TOOL_SUMMARY = "Read and edit files in a workspace — one operation per call (read, write, list, search, replace, splice, move, remove, plus workspace switching), chosen by the 'operation' field. Call describe('workspace') for the full operation list and fields.";
167
180
  /**
@@ -197,8 +210,9 @@ var WORKSPACE_TOOL_DESCRIPTION = [
197
210
  JSON.stringify(WORKSPACE_TOOL_EXAMPLE)
198
211
  ].join("\n");
199
212
  /**
200
- * Holds the name {@link import('./factories.js').createDescribeTool} advertises by default — the key a
201
- * model calls and the `ToolManagerInterface` (`@orkestrel/tool`) registers under.
213
+ * Holds the name {@link import('./factories.js').createDescribeTool} advertises by default,
214
+ * `'describe'` — the key a model calls and the `ToolManagerInterface` (`@orkestrel/tool`) registers
215
+ * under.
202
216
  *
203
217
  * @remarks
204
218
  * Pairs with the lean {@link AGENT_TOOL_SUMMARY} / {@link WORKFLOW_TOOL_SUMMARY} /
@@ -214,7 +228,8 @@ var DESCRIBE_TOOL_NAME = "describe";
214
228
  */
215
229
  var DESCRIBE_TOOL_SUMMARY = "Return the full description of a named registered tool.";
216
230
  /**
217
- * Holds the DESCRIPTION {@link import('./factories.js').createDescribeTool} advertises.
231
+ * Holds the description {@link import('./factories.js').createDescribeTool} advertises — the
232
+ * registered tool `name` it requires, and the full description of that tool it returns.
218
233
  *
219
234
  * @remarks
220
235
  * Deliberately short — unlike the workflow / workspace / agent tools, this one has no authoring
@@ -222,19 +237,27 @@ var DESCRIBE_TOOL_SUMMARY = "Return the full description of a named registered t
222
237
  */
223
238
  var DESCRIBE_TOOL_DESCRIPTION = "Return the full description of a registered tool by its name. Required: name - the registered tool name (see another tool listing for available names).";
224
239
  /**
225
- * Holds the name {@link import('./factories.js').createPromptTool} advertises by default — the key a
226
- * model calls and the `ToolManagerInterface` (`@orkestrel/tool`) registers under.
240
+ * Holds the name {@link import('./factories.js').createPromptTool} advertises by default, `'ask'` —
241
+ * the key a model calls and the `ToolManagerInterface` (`@orkestrel/tool`) registers under.
227
242
  */
228
243
  var PROMPT_TOOL_NAME = "ask";
229
244
  /**
230
- * Holds the lean {@link import('@orkestrel/tool').ToolInterface.summary} {@link import('./factories.js').createPromptTool}
231
- * advertises in place of {@link PROMPT_TOOL_DESCRIPTION} — a `ToolManagerInterface.definitions()`
232
- * (`@orkestrel/tool`) advertises `summary ?? description`, so this one-sentence text stands in
233
- * for the full teaching description; the full text stays retrievable through
234
- * {@link import('./factories.js').createDescribeTool}.
245
+ * Holds the lean {@link import('@orkestrel/tool').ToolInterface.summary}
246
+ * {@link import('./factories.js').createPromptTool} advertises in place of
247
+ * {@link PROMPT_TOOL_DESCRIPTION} — one sentence offering the blocking multi-field ask and pointing
248
+ * at `describe` for the schema.
249
+ *
250
+ * @remarks
251
+ * A `ToolManagerInterface.definitions()` call (`@orkestrel/tool`) advertises
252
+ * `summary ?? description`, so this one-sentence text stands in for the full teaching description;
253
+ * the full text stays retrievable through {@link import('./factories.js').createDescribeTool}.
235
254
  */
236
255
  var PROMPT_TOOL_SUMMARY = "Ask another terminal a multi-field form and BLOCK until it answers; the call resolves with the values record. Call describe('ask') for the schema.";
237
- /** Holds the full form protocol {@link import('./factories.js').createPromptTool} advertises. */
256
+ /**
257
+ * Holds the form protocol {@link import('./factories.js').createPromptTool} advertises — the
258
+ * required `to` and `schema`, how a field declares its control and its rules, and a worked
259
+ * example.
260
+ */
238
261
  var PROMPT_TOOL_DESCRIPTION = [
239
262
  "Ask another terminal a multi-field form and block until it answers. This call does not return until the addressed terminal answers, or the form expires.",
240
263
  "",
@@ -260,19 +283,27 @@ var PROMPT_TOOL_DESCRIPTION = [
260
283
  })
261
284
  ].join("\n");
262
285
  /**
263
- * Holds the name {@link import('./factories.js').createAnswerTool} advertises by default — the key a
264
- * model calls and the `ToolManagerInterface` (`@orkestrel/tool`) registers under.
286
+ * Holds the name {@link import('./factories.js').createAnswerTool} advertises by default,
287
+ * `'answer'` — the key a model calls and the `ToolManagerInterface` (`@orkestrel/tool`) registers
288
+ * under.
265
289
  */
266
290
  var ANSWER_TOOL_NAME = "answer";
267
291
  /**
268
- * Holds the lean {@link import('@orkestrel/tool').ToolInterface.summary} {@link import('./factories.js').createAnswerTool}
269
- * advertises in place of {@link ANSWER_TOOL_DESCRIPTION} — a `ToolManagerInterface.definitions()`
270
- * (`@orkestrel/tool`) advertises `summary ?? description`, so this one-sentence text stands in
271
- * for the full teaching description; the full text stays retrievable through
272
- * {@link import('./factories.js').createDescribeTool}.
292
+ * Holds the lean {@link import('@orkestrel/tool').ToolInterface.summary}
293
+ * {@link import('./factories.js').createAnswerTool} advertises in place of
294
+ * {@link ANSWER_TOOL_DESCRIPTION} — one sentence offering the pending listing and the answer call,
295
+ * and pointing at `describe` for the fields each takes.
296
+ *
297
+ * @remarks
298
+ * A `ToolManagerInterface.definitions()` call (`@orkestrel/tool`) advertises
299
+ * `summary ?? description`, so this one-sentence text stands in for the full teaching description;
300
+ * the full text stays retrievable through {@link import('./factories.js').createDescribeTool}.
273
301
  */
274
302
  var ANSWER_TOOL_SUMMARY = "List forms addressed to this terminal, or answer one by id with a values record. Call describe('answer') for the required fields.";
275
- /** Holds the pending/answer protocol {@link import('./factories.js').createAnswerTool} advertises. */
303
+ /**
304
+ * Holds the protocol {@link import('./factories.js').createAnswerTool} advertises — the `pending`
305
+ * and `answer` operations and the `values` record an answer supplies, each with a worked example.
306
+ */
276
307
  var ANSWER_TOOL_DESCRIPTION = [
277
308
  "List the forms addressed to this terminal, or answer one of them by id. Every call is ONE operation, chosen by the \"operation\" field.",
278
309
  "",
@@ -292,24 +323,31 @@ var ANSWER_TOOL_DESCRIPTION = [
292
323
  })
293
324
  ].join("\n");
294
325
  /**
295
- * Holds the name {@link import('./factories.js').createDatabaseTool} advertises by default — the key
296
- * a model calls and the `ToolManagerInterface` (`@orkestrel/tool`) registers under.
326
+ * Holds the name {@link import('./factories.js').createDatabaseTool} advertises by default,
327
+ * `'database'` — the key a model calls and the `ToolManagerInterface` (`@orkestrel/tool`) registers
328
+ * under.
297
329
  */
298
330
  var DATABASE_TOOL_NAME = "database";
299
331
  /**
300
332
  * Holds the lean {@link import('@orkestrel/tool').ToolInterface.summary}
301
333
  * {@link import('./factories.js').createDatabaseTool} advertises in place of
302
- * {@link DATABASE_TOOL_DESCRIPTION}.
334
+ * {@link DATABASE_TOOL_DESCRIPTION} — one sentence offering the `operation`-keyed database call and
335
+ * pointing at `describe` for the operation list, the query form, and the column DSL.
336
+ *
337
+ * @remarks
338
+ * A `ToolManagerInterface.definitions()` call (`@orkestrel/tool`) advertises
339
+ * `summary ?? description`, so this one-sentence text stands in for the full teaching description;
340
+ * the full text stays retrievable through {@link import('./factories.js').createDescribeTool}.
303
341
  */
304
342
  var DATABASE_TOOL_SUMMARY = "Create and query a database — one operation per call (create, tables, get, records, count, aggregate, add, set, update, remove, destroy), chosen by the 'operation' field. Call describe('database') for the full operation list, the query form, and the column DSL.";
305
343
  /**
306
344
  * Holds the description {@link import('./factories.js').createDatabaseTool} advertises — a
307
- * multi-line guide that teaches a small model the operation list, the SERIALIZED query form, and
345
+ * multi-line guide that teaches a small model the operation list, the serialized query form, and
308
346
  * the {@link import('./types.js').TableSpec} column DSL.
309
347
  *
310
348
  * @remarks
311
- * The query form is deliberately SERIALIZED (never fluent) — every condition is a flat object
312
- * `{ column, operator, values, connector? }` where `values` is ALWAYS an array, even for a
349
+ * The query form is deliberately serialized (never fluent) — every condition is a flat object
350
+ * `{ column, operator, values, connector? }` where `values` is always an array, even for a
313
351
  * single-value operator (`{ column: 'age', operator: 'from', values: [18] }`), so a small model
314
352
  * never has to chain method calls or guess whether a value is scalar or a list.
315
353
  */
@@ -361,7 +399,10 @@ var DATABASE_TOOL_DESCRIPTION = [
361
399
  }] }
362
400
  })
363
401
  ].join("\n");
364
- /** Holds the default cap on rows a `records` call returns when the caller omits `query.limit` — the database tool's default row ceiling. */
402
+ /**
403
+ * Holds the default cap on rows a `records` call returns when the caller omits `query.limit`,
404
+ * `1000` — the database tool's default row ceiling.
405
+ */
365
406
  var DATABASE_TOOL_LIMIT = 1e3;
366
407
  /** Lists the runtime-frozen database-tool mutation names disabled by `DatabaseToolOptions.readonly`. */
367
408
  var DATABASE_TOOL_MUTATIONS = Object.freeze([
@@ -373,21 +414,30 @@ var DATABASE_TOOL_MUTATIONS = Object.freeze([
373
414
  "destroy"
374
415
  ]);
375
416
  /**
376
- * Holds the name `createRelationTool` advertises by default — the key a model calls and the
377
- * `ToolManagerInterface` (`@orkestrel/tool`) registers under.
417
+ * Holds the name {@link import('./factories.js').createRelationTool} advertises by default,
418
+ * `'relation'` — the key a model calls and the `ToolManagerInterface` (`@orkestrel/tool`) registers
419
+ * under.
378
420
  */
379
421
  var RELATION_TOOL_NAME = "relation";
380
422
  /**
381
- * Holds the lean {@link import('@orkestrel/tool').ToolInterface.summary} the relation tool advertises
382
- * in place of {@link RELATION_TOOL_DESCRIPTION}.
423
+ * Holds the lean {@link import('@orkestrel/tool').ToolInterface.summary}
424
+ * {@link import('./factories.js').createRelationTool} advertises in place of
425
+ * {@link RELATION_TOOL_DESCRIPTION} — one sentence offering the `operation`-keyed relationship
426
+ * traversal and pointing at `describe` for the include-path syntax.
427
+ *
428
+ * @remarks
429
+ * A `ToolManagerInterface.definitions()` call (`@orkestrel/tool`) advertises
430
+ * `summary ?? description`, so this one-sentence text stands in for the full teaching description;
431
+ * the full text stays retrievable through {@link import('./factories.js').createDescribeTool}.
383
432
  */
384
433
  var RELATION_TOOL_SUMMARY = "Traverse and edit relationships between database rows — one operation per call (load, find, link, unlink, links), chosen by the 'operation' field. Call describe('relation') for the include-path syntax.";
385
434
  /**
386
- * Holds the DESCRIPTION the relation tool advertises — a multi-line guide that teaches a small model
387
- * the operation list and the flat dot-path `include` syntax.
435
+ * Holds the description {@link import('./factories.js').createRelationTool} advertises — a
436
+ * multi-line guide that teaches a small model the operation list and the flat dot-path `include`
437
+ * syntax.
388
438
  *
389
439
  * @remarks
390
- * An include path is a FLAT dot-separated string (`'contacts.account'`), never a nested object —
440
+ * An include path is a flat dot-separated string (`'contacts.account'`), never a nested object —
391
441
  * the same small-model ergonomic lever the other tools in this package use for flat args.
392
442
  */
393
443
  var RELATION_TOOL_DESCRIPTION = [
@@ -409,24 +459,38 @@ var RELATION_TOOL_DESCRIPTION = [
409
459
  include: ["contacts.account"]
410
460
  })
411
461
  ].join("\n");
412
- /** Holds the default cap on rows a `find` / `links` call returns when the caller omits `limit` — the relation tool's default row ceiling. */
462
+ /**
463
+ * Holds the default cap on rows a `find` or `links` call returns when the caller omits `limit`,
464
+ * `1000` — the relation tool's default row ceiling.
465
+ */
413
466
  var RELATION_TOOL_LIMIT = 1e3;
414
- /** Holds the default cap on how many `include` path segments deep a `load` / `find` call may traverse — the relation tool's default include-depth ceiling. */
467
+ /**
468
+ * Holds the default cap on how many `include` path segments deep a `load` or `find` call may
469
+ * traverse, `3` — the relation tool's default include-depth ceiling.
470
+ */
415
471
  var RELATION_TOOL_DEPTH = 3;
416
472
  /**
417
- * Holds the name {@link import('./factories.js').createInferTool} advertises by default — the key a
418
- * model calls and the `ToolManagerInterface` (`@orkestrel/tool`) registers under.
473
+ * Holds the name {@link import('./factories.js').createInferTool} advertises by default, `'infer'`
474
+ * — the key a model calls and the `ToolManagerInterface` (`@orkestrel/tool`) registers under.
419
475
  */
420
476
  var INFER_TOOL_NAME = "infer";
421
477
  /**
422
- * Holds the lean {@link import('@orkestrel/tool').ToolInterface.summary} {@link import('./factories.js').createInferTool}
423
- * advertises in place of {@link INFER_TOOL_DESCRIPTION} — a `ToolManagerInterface.definitions()`
424
- * (`@orkestrel/tool`) advertises `summary ?? description`, so this one-sentence text stands in
425
- * for the full teaching description; the full text stays retrievable through
426
- * {@link import('./factories.js').createDescribeTool}.
478
+ * Holds the lean {@link import('@orkestrel/tool').ToolInterface.summary}
479
+ * {@link import('./factories.js').createInferTool} advertises in place of
480
+ * {@link INFER_TOOL_DESCRIPTION} — one sentence offering schema inference from example values and
481
+ * pointing at `describe` for the fields it takes.
482
+ *
483
+ * @remarks
484
+ * A `ToolManagerInterface.definitions()` call (`@orkestrel/tool`) advertises
485
+ * `summary ?? description`, so this one-sentence text stands in for the full teaching description;
486
+ * the full text stays retrievable through {@link import('./factories.js').createDescribeTool}.
427
487
  */
428
488
  var INFER_TOOL_SUMMARY = "Infer a JSON Schema (as advertised tool parameters) from one or more example values. Call describe('infer') for the required fields.";
429
- /** Holds the schema-inference protocol {@link import('./factories.js').createInferTool} advertises. */
489
+ /**
490
+ * Holds the schema-inference protocol {@link import('./factories.js').createInferTool} advertises —
491
+ * the required `samples`, the optional `format`, `enum`, and `candidates` arguments, and a worked
492
+ * example of the bare return and of the `candidates`-wrapped return.
493
+ */
430
494
  var INFER_TOOL_DESCRIPTION = [
431
495
  "Infer a JSON Schema from example values, returned in the same shape a tool advertises its parameters.",
432
496
  "",
@@ -551,7 +615,7 @@ var ToolboxError = class extends Error {
551
615
  }
552
616
  };
553
617
  /**
554
- * Narrows an unknown caught value to an {@link ToolboxError}.
618
+ * Narrows an unknown caught value to a {@link ToolboxError}.
555
619
  *
556
620
  * @param value - The value to test (typically a `catch` binding)
557
621
  * @returns True if `value` is an {@link ToolboxError}; false otherwise
@@ -628,7 +692,7 @@ function isColumnPrimitive(value) {
628
692
  return value === "string" || value === "integer" || value === "number" || value === "boolean";
629
693
  }
630
694
  /**
631
- * Narrows an unknown value to a {@link DatabaseDefinition} — a non-empty `id` + `driver`, a
695
+ * Narrows an unknown value to a {@link DatabaseDefinition} — a non-empty `id` and `driver`, a
632
696
  * `tables` record whose every value is `{ columns: record of valid ColumnSpec }`, plus optional
633
697
  * `primary`, `indexes`, and finite `version` schema configuration. The boundary guard a
634
698
  * {@link import('./types.js').DefinitionStoreInterface} applies to an untrusted persisted blob
@@ -729,8 +793,8 @@ var describeToolShape = objectShape({ name: stringShape({
729
793
  description: "The registered name of the tool whose full description to return."
730
794
  }) });
731
795
  /**
732
- * Describes the shape of a {@link import('./types.js').TaskDraft} — identical to a strict task shape
733
- * EXCEPT `id` and `name` are OPTIONAL.
796
+ * Describes the shape of a {@link import('./types.js').TaskDraft} — identical to a strict task
797
+ * shape except that `id` and `name` are optional.
734
798
  */
735
799
  var taskDraftShape = objectShape({
736
800
  id: optionalShape(stringShape({
@@ -757,8 +821,8 @@ var taskDraftShape = objectShape({
757
821
  }))
758
822
  });
759
823
  /**
760
- * Describes the shape of a PHASE in a draft workflow — identical to a strict phase shape EXCEPT `id` and
761
- * `name` are OPTIONAL, and its tasks are {@link taskDraftShape}s.
824
+ * Describes the shape of a phase in a draft workflow — identical to a strict phase shape except
825
+ * that `id` and `name` are optional and each task takes {@link taskDraftShape}.
762
826
  */
763
827
  var phaseDraftShape = objectShape({
764
828
  id: optionalShape(stringShape({
@@ -778,17 +842,17 @@ var phaseDraftShape = objectShape({
778
842
  bail: optionalShape(literalShape([true, false], { description: "Per-phase failure-policy override; omitted inherits the workflow bail." }))
779
843
  });
780
844
  /**
781
- * Describes the shape of a DRAFT workflow — identical to a strict workflow shape EXCEPT `id` and `name`
782
- * are OPTIONAL at all three levels (workflow / phase / task), so a small model can omit the six
783
- * identity strings and let the tool synthesize them positionally.
845
+ * Describes the shape of a draft workflow — identical to a strict workflow shape except that `id`
846
+ * and `name` are optional at the workflow, phase, and task levels, so a small model can omit every
847
+ * identity string and let the tool synthesize them positionally.
784
848
  *
785
849
  * @remarks
786
850
  * The lenient counterpart {@link import('./factories.js').createWorkflowDraftContract} compiles.
787
851
  * `behavior` stays optional like the strict form; omission is the deliberate JSON `null` no-op. A
788
852
  * provided `id` / `name` still has `minLength: 1` (so
789
- * an explicitly-empty `id: ''` is REJECTED, not auto-filled). After
853
+ * an explicitly-empty `id: ''` is rejected, not auto-filled). After
790
854
  * {@link import('./helpers.js').completeDraft} fills the missing ids/names, the result is
791
- * validated against the STRICT `createWorkflowContract` (`@orkestrel/workflow`) gate before
855
+ * validated against the strict `createWorkflowContract` (`@orkestrel/workflow`) gate before
792
856
  * running.
793
857
  */
794
858
  var workflowDraftShape = objectShape({
@@ -805,10 +869,11 @@ var workflowDraftShape = objectShape({
805
869
  bail: optionalShape(literalShape([true, false], { description: "Failure policy: false (default) continues gracefully, true halts on the first failure." }))
806
870
  });
807
871
  /**
808
- * Describes the shape of ONE flat step — `{ name }` — the building block of {@link workflowStepsShape}.
872
+ * Describes the shape of one flat step — `{ name }` — the building block of
873
+ * {@link workflowStepsShape}.
809
874
  *
810
875
  * @remarks
811
- * `name` is the REGISTERED behavior name the step runs (it becomes the task's `behavior`). The tool
876
+ * `name` is the registered behavior name the step runs (it becomes the task's `behavior`). The tool
812
877
  * expands each step into a one-task phase, in order ({@link import('./helpers.js').expandSteps}).
813
878
  */
814
879
  var stepShape = objectShape({ name: stringShape({
@@ -816,16 +881,17 @@ var stepShape = objectShape({ name: stringShape({
816
881
  description: "The registered behavior name this step runs (becomes the task behavior)."
817
882
  }) });
818
883
  /**
819
- * Describes the FLAT authoring shape {@link import('./factories.js').createWorkflowTool} advertises as its
820
- * `parameters` — the simplest surface a small model can fill: `{ name?, steps: [{ name }] }`.
884
+ * Describes the flat authoring shape {@link import('./factories.js').createWorkflowTool} advertises
885
+ * as its `parameters` — the simplest surface a small model can fill:
886
+ * `{ name?, steps: [{ name }] }`.
821
887
  *
822
888
  * @remarks
823
889
  * A deliberately-reduced surface: a flat ordered list of steps, each a `{ name }`. The tool
824
- * EXPANDS it ({@link import('./helpers.js').expandSteps}) into a full
890
+ * expands it ({@link import('./helpers.js').expandSteps}) into a full
825
891
  * {@link import('./types.js').WorkflowDefinition} — one one-task phase per step, in order —
826
- * then validates against the STRICT `createWorkflowContract` (`@orkestrel/workflow`) gate. The
827
- * full nested form is STILL accepted by the tool (it branches on the args' shape) and is
828
- * documented as the advanced escape-hatch in the tool's description — but THIS is what
892
+ * then validates against the strict `createWorkflowContract` (`@orkestrel/workflow`) gate. The
893
+ * full nested form is still accepted by the tool (it branches on the args' shape) and is
894
+ * documented as the advanced escape-hatch in the tool's description — but this is what
829
895
  * `parameters` advertises.
830
896
  */
831
897
  var workflowStepsShape = objectShape({
@@ -839,17 +905,17 @@ var workflowStepsShape = objectShape({
839
905
  * Describes the shape of a {@link import('./types.js').WorkspaceOperation} — a descriptive tagged union
840
906
  * over the workspace edit, read, and navigation operations, discriminated by the `operation`
841
907
  * literal (never a bare `kind`). Each variant leads with its `operation`
842
- * discriminant then its FLAT fields, every field through `stringShape` / `optionalShape` /
908
+ * discriminant then its flat fields, every field through `stringShape` / `optionalShape` /
843
909
  * `integerShape({ min: 1 })` / `booleanShape`, each carrying a strong field-level `description`.
844
910
  *
845
911
  * @remarks
846
- * The union compiles to an `anyOf` JSON Schema + a `unionOf` guard + a first-match parser
912
+ * The union compiles to an `anyOf` JSON Schema, a `unionOf` guard, and a first-match parser
847
913
  * automatically ({@link import('./factories.js').createWorkspaceTool} types the result to the
848
- * hand-written {@link import('./types.js').WorkspaceOperation}). `limit` and the four `'splice'`
849
- * caret components are POSITIVE integers (`integerShape({ min: 1 })`); `regex` / `sensitive`
850
- * are `optionalShape(booleanShape(...))`. The two REGISTRY arms — `workspaces` (list the
914
+ * hand-written {@link import('./types.js').WorkspaceOperation}). `limit` and the `'splice'`
915
+ * caret components are positive integers (`integerShape({ min: 1 })`); `regex` / `sensitive`
916
+ * are `optionalShape(booleanShape(...))`. The registry arms — `workspaces` (list the
851
917
  * workspaces the model can move between) and `switch` (re-point the active one by `id`) — let a
852
- * model DISCOVER then CHOOSE which workspace the edit / read arms target.
918
+ * model discover then choose which workspace the edit / read arms target.
853
919
  */
854
920
  var workspaceToolShape = unionShape(objectShape({
855
921
  operation: literalShape(["read"], { description: "Read a whole text file's text by path." }),
@@ -933,13 +999,23 @@ var columnSpecShape = unionShape(columnPrimitiveShape, objectShape({
933
999
  }));
934
1000
  /** Describes a {@link import('./types.js').TableSpec} — table name to `{ columns }`, each column a {@link columnSpecShape}. */
935
1001
  var tableSpecShape = recordShape(objectShape({ columns: recordShape(columnSpecShape, { description: "Column name to its primitive or its { primitive, optional } spec." }) }), { description: "Table name to its column layout." });
936
- /** Describes one key value for the database tool and the relation tool — a string or number; the array form (multiple keys, positional) resolves FIRST, so an array argument is read as many keys rather than one. */
1002
+ /**
1003
+ * Describes one key value for the database tool and the relation tool — a string or number; the
1004
+ * array form (multiple keys, positional) resolves first, so an array argument is read as many keys
1005
+ * rather than one.
1006
+ */
937
1007
  var keyShape = unionShape(arrayShape(unionShape(stringShape(), numberShape()), { description: "Multiple row keys, positional — a miss at an index is undefined there." }), stringShape({ description: "One row key." }), numberShape({ description: "One row key." }));
938
- /** Describes a loose row — a flat object of column name to JSON value; the array form (multiple rows) resolves FIRST, so an array argument is read as many rows rather than one. */
1008
+ /** Describes a loose row — a flat object of column name to JSON value. */
939
1009
  var rowShape = recordShape(jsonShape(), { description: "A row as a flat object of column name to value." });
940
- /** Describes one or many loose rows — the array form resolves FIRST, so an array argument is read as many rows rather than one. */
1010
+ /**
1011
+ * Describes one or many loose rows — the array form resolves first, so an array argument is read as
1012
+ * many rows rather than one.
1013
+ */
941
1014
  var rowsShape = unionShape(arrayShape(rowShape, { description: "Multiple rows." }), rowShape);
942
- /** Describes one SERIALIZED WHERE condition — `values` is ALWAYS an array, even for a single-value operator. */
1015
+ /**
1016
+ * Describes one serialized where condition — `values` is always an array, even for a single-value
1017
+ * operator.
1018
+ */
943
1019
  var conditionShape = objectShape({
944
1020
  column: stringShape({ description: "The column this condition applies to." }),
945
1021
  operator: literalShape([
@@ -962,12 +1038,12 @@ var conditionShape = objectShape({
962
1038
  values: arrayShape(jsonShape(), { description: "The operand values the operator needs (always an array, even for one value)." }),
963
1039
  connector: optionalShape(literalShape(["and", "or"], { description: "Joins this condition to the next; omit on the last condition." }))
964
1040
  });
965
- /** Describes one sort term. */
1041
+ /** Describes one sort term — a `column` to sort by and the `direction` to sort it in. */
966
1042
  var orderShape = objectShape({
967
1043
  column: stringShape({ description: "The column to sort by." }),
968
1044
  direction: literalShape(["ascending", "descending"], { description: "The sort direction." })
969
1045
  });
970
- /** Describes the SERIALIZED query form — conditions, order, and pagination. */
1046
+ /** Describes the serialized query form — conditions, order, and pagination. */
971
1047
  var queryShape = objectShape({
972
1048
  conditions: optionalShape(arrayShape(conditionShape, { description: "The WHERE conditions, folded left to right." })),
973
1049
  order: optionalShape(arrayShape(orderShape, { description: "The sort terms, applied in order." })),
@@ -982,9 +1058,8 @@ var queryShape = objectShape({
982
1058
  });
983
1059
  /**
984
1060
  * Describes the shape of {@link import('./factories.js').createDatabaseTool}'s call arguments —
985
- * discriminated by `operation` into the 11 database operations (`'create'` / `'tables'` /
986
- * `'get'` / `'records'` / `'count'` / `'aggregate'` / `'add'` / `'set'` / `'update'` /
987
- * `'remove'` / `'destroy'`).
1061
+ * discriminated by `operation` into the database operations `'create'`, `'tables'`, `'get'`,
1062
+ * `'records'`, `'count'`, `'aggregate'`, `'add'`, `'set'`, `'update'`, `'remove'`, and `'destroy'`.
988
1063
  *
989
1064
  * @remarks
990
1065
  * Every arm carries `id` (the database id). `'create'` carries `tables` (the
@@ -992,7 +1067,7 @@ var queryShape = objectShape({
992
1067
  * {@link import('./compilers.js').expandTables}); `'get'` / `'update'` / `'remove'` carry `key`
993
1068
  * (one key or an array of keys, positional); `'add'` / `'set'` carry `row` (one row or an array of
994
1069
  * rows); `'update'` also carries `changes` (a loose partial row); `'records'` / `'count'` /
995
- * `'aggregate'` carry an optional `query` (the SERIALIZED form — `values` is ALWAYS an array,
1070
+ * `'aggregate'` carry an optional `query` (the serialized form — `values` is always an array,
996
1071
  * even for a single-value operator, so a caller never chains method calls or guesses arity).
997
1072
  */
998
1073
  var databaseToolShape = unionShape(objectShape({
@@ -1136,8 +1211,8 @@ var managerShape = optionalShape(stringShape({
1136
1211
  }));
1137
1212
  /**
1138
1213
  * Describes the shape of {@link import('./factories.js').createRelationTool}'s call arguments —
1139
- * discriminated by `operation` into the 5 relation operations (`'load'` / `'find'` / `'link'` /
1140
- * `'unlink'` / `'links'`).
1214
+ * discriminated by `operation` into the relation operations `'load'`, `'find'`, `'link'`,
1215
+ * `'unlink'`, and `'links'`.
1141
1216
  *
1142
1217
  * @remarks
1143
1218
  * `'load'` fetches one or more rows (positional key/array) with `include` attached. `'find'`
@@ -1222,8 +1297,8 @@ var relationToolShape = unionShape(objectShape({
1222
1297
  * `samples` requires at least one element (`min: 1`) — an empty array parses to `undefined`,
1223
1298
  * surfaced by the handler as a typed `TOOL` {@link import('./errors.js').ToolboxError}. When
1224
1299
  * `candidates` is present (any array, including empty), the handler compiles a contract from the
1225
- * freshly inferred schema and checks each candidate against it with a STRICT guard (`.is`, no
1226
- * coercion) — the opposite of {@link import('./factories.js').createEndpointTool}'s NORMALIZING
1300
+ * freshly inferred schema and checks each candidate against it with a strict guard (`.is`, no
1301
+ * coercion) — the opposite of {@link import('./factories.js').createEndpointTool}'s normalizing
1227
1302
  * `.parse` enforcement.
1228
1303
  */
1229
1304
  var inferToolShape = objectShape({
@@ -1241,8 +1316,8 @@ var inferToolShape = objectShape({
1241
1316
  * Returns the ancestry identifier of a workflow in a run chain — `workflow:<id>`.
1242
1317
  *
1243
1318
  * @remarks
1244
- * Namespacing keeps a workflow id and a {@link tagAgent} agent name in ONE set without
1245
- * collision, so re-entering a workflow OR an agent already in the chain is a single `includes`
1319
+ * Namespacing keeps a workflow id and a {@link tagAgent} agent name in one set without
1320
+ * collision, so re-entering a workflow or an agent already in the chain is a single `includes`
1246
1321
  * check.
1247
1322
  *
1248
1323
  * @param id - The workflow definition's `id`
@@ -1297,12 +1372,12 @@ function deriveWorkflowDepth(lineage) {
1297
1372
  return Math.max(0, workflows - 1);
1298
1373
  }
1299
1374
  /**
1300
- * Builds the plain success summary {@link import('./factories.js').createWorkflowTool} returns on
1301
- * a completed run — the universal tool-handler contract: return a plain value on success,
1302
- * appearing identically over BOTH the agent loop and MCP.
1375
+ * Builds the plain success summary {@link import('./factories.js').createWorkflowTool} returns on a
1376
+ * completed run — the universal tool-handler contract: return a plain value on success, appearing
1377
+ * identically over both the agent loop and MCP.
1303
1378
  *
1304
1379
  * @remarks
1305
- * The summary is LEAN: the workflow's terminal `status`, settled-task count, and exact optional
1380
+ * The summary is lean: the workflow's terminal `status`, settled-task count, and exact optional
1306
1381
  * native persistence outcome. It carries no synthetic `id` / `name`: a tool handler has no call
1307
1382
  * id; the `ToolManagerInterface` (`@orkestrel/tool`) supplies the canonical envelope's identity.
1308
1383
  *
@@ -1318,21 +1393,21 @@ function summarizeWorkflow(result) {
1318
1393
  };
1319
1394
  }
1320
1395
  /**
1321
- * Completes a {@link WorkflowDraft} into a strict {@link WorkflowDefinition} — synthesizes any
1322
- * MISSING `id` deterministically + positionally, and defaults any MISSING `name` to its
1323
- * (now-resolved) `id`.
1396
+ * Completes a {@link WorkflowDraft} into a strict {@link WorkflowDefinition} — synthesizes a
1397
+ * missing `id` deterministically and positionally, and defaults a missing `name` to its resolved
1398
+ * `id`.
1324
1399
  *
1325
1400
  * @remarks
1326
1401
  * The positional id scheme is stable and human-legible: the workflow is `wf`, phase `i` is
1327
1402
  * `phase-<i>`, and task `j` of that phase is `<phaseId>-task-<j>` (so a provided phase id flows
1328
- * into its tasks' synthesized ids). A PROVIDED `id` / `name` at any level is kept VERBATIM —
1403
+ * into its tasks' synthesized ids). A provided `id` / `name` at any level is kept verbatim —
1329
1404
  * synthesis touches only the omitted ones. A missing `name` defaults to the resolved `id` (never
1330
- * the other way round), so the result always has both. `behavior`, `description`, the per-phase
1405
+ * the other way round), so the result always carries an `id` and a `name`. `behavior`, `description`, the per-phase
1331
1406
  * `concurrency` / `bail`, the per-task `retries` / `timeout`, and the workflow `bail` carry over
1332
1407
  * unchanged. The result is a complete {@link WorkflowDefinition}; the caller still validates it
1333
- * against the STRICT contract.
1408
+ * against the strict contract.
1334
1409
  *
1335
- * @param draft - The draft workflow (id/name optional at all three levels)
1410
+ * @param draft - The draft workflow (`id` and `name` optional at the workflow, phase, and task levels)
1336
1411
  * @returns A complete {@link WorkflowDefinition} with every id/name filled
1337
1412
  */
1338
1413
  function completeDraft(draft) {
@@ -1387,18 +1462,18 @@ function completeTaskDraft(task, phaseId, index) {
1387
1462
  }
1388
1463
  /**
1389
1464
  * Expands a flat {@link WorkflowSteps} blob into a strict {@link WorkflowDefinition} — each step
1390
- * becomes a one-task phase, IN ORDER.
1465
+ * becomes a one-task phase, in order.
1391
1466
  *
1392
1467
  * @remarks
1393
- * The expansion of the tool's ADVERTISED surface: the deliberately-reduced flat form. Each
1468
+ * The expansion of the tool's advertised surface: the deliberately-reduced flat form. Each
1394
1469
  * {@link import('./types.js').WorkflowStep} maps to a phase holding exactly one task: the step's
1395
1470
  * `name` becomes the task's `behavior` (the behavior-registry key). Ids/names are auto-filled
1396
1471
  * positionally — it builds an ids-omitted {@link WorkflowDraft} and delegates to
1397
- * {@link completeDraft}, so the two lenient surfaces share ONE synthesis path (step `i` → phase
1472
+ * {@link completeDraft}, so the lenient surfaces share one synthesis path (step `i` → phase
1398
1473
  * `phase-<i>`, its task `phase-<i>-task-0`). The optional `name` becomes both the workflow's
1399
1474
  * deterministic id and its name, so named flat workflows retain distinct persistence keys;
1400
1475
  * omission keeps the shared draft fallback `wf`. The result is a complete definition the caller
1401
- * validates against the STRICT contract before running.
1476
+ * validates against the strict contract before running.
1402
1477
  *
1403
1478
  * @param flat - The flat steps blob (`{ name?, steps: [{ name }] }`)
1404
1479
  * @returns A complete {@link WorkflowDefinition} (one one-task phase per step)
@@ -1458,15 +1533,15 @@ function inferRelationCode(error) {
1458
1533
  return isRelationError(error) ? error.code : void 0;
1459
1534
  }
1460
1535
  /**
1461
- * Expands the relation tool's FLAT dot-path `include` list into a live `@orkestrel/relation`
1536
+ * Expands the relation tool's flat dot-path `include` list into a live `@orkestrel/relation`
1462
1537
  * {@link Include} tree — the pure leaf {@link import('./factories.js').createRelationTool} calls
1463
1538
  * before a `'load'` / `'find'` call.
1464
1539
  *
1465
1540
  * @remarks
1466
1541
  * Each path splits on `'.'` into a chain of relation names, deep-merged into one nested
1467
- * `Include` object with a leaf `true`. A longer path SUBSUMES a shorter sibling's bare `true` —
1542
+ * `Include` object with a leaf `true`. A longer path subsumes a shorter sibling's bare `true` —
1468
1543
  * `'contacts'` followed by `'contacts.account'` yields `{ contacts: { account: true } }`, never
1469
- * overwriting the deeper chain. An EMPTY segment (`''`, from a leading/trailing/doubled `.`) or a
1544
+ * overwriting the deeper chain. An empty segment (`''`, from a leading/trailing/doubled `.`) or a
1470
1545
  * path whose segment count exceeds `depth` throws a typed `TOOL` {@link ToolboxError}.
1471
1546
  *
1472
1547
  * @param paths - The flat dot-path `include` list (or `undefined` — yields `{}`)
@@ -1535,7 +1610,7 @@ function expandInclude(paths, depth) {
1535
1610
  *
1536
1611
  * @remarks
1537
1612
  * An explicit `name` must match a key of `managers` (a miss throws a typed `TOOL`
1538
- * {@link ToolboxError} naming the registered managers). An OMITTED `name` resolves to the sole
1613
+ * {@link ToolboxError} naming the registered managers). An omitted `name` resolves to the sole
1539
1614
  * registered manager when exactly one is registered, else throws the same typed error.
1540
1615
  *
1541
1616
  * @param managers - The tool's registered `RelationManagerInterface` map
@@ -1577,11 +1652,11 @@ function resolveRelationModel(manager, name) {
1577
1652
  }
1578
1653
  /**
1579
1654
  * Returns the canonical live `@orkestrel/database` {@link QueryInput} for the database tool's
1580
- * parsed SERIALIZED query — each condition's OMITTED `connector` defaults to `'and'`.
1655
+ * parsed serialized query — each condition's omitted `connector` defaults to `'and'`.
1581
1656
  *
1582
1657
  * @remarks
1583
1658
  * The wire form ({@link import('./shapers.js').databaseToolShape}) lets a caller drop `connector`
1584
- * on the last condition (it has nothing to join FORWARD to); the compiled `Condition` a live
1659
+ * on the last condition (it has nothing to join forward to); the compiled `Condition` a live
1585
1660
  * `@orkestrel/database` table call accepts always carries one, so this fills the gap. `order` /
1586
1661
  * `limit` / `offset` pass through unchanged. Pure and total.
1587
1662
  *
@@ -1627,14 +1702,14 @@ function resolveLimit(requested, cap) {
1627
1702
  return Math.max(0, Math.min(requested ?? cap, cap));
1628
1703
  }
1629
1704
  /**
1630
- * Clamps a `'records'` call's query to a row cap, and builds the PROBE query the caller reads
1631
- * with — the pure leaf {@link import('./factories.js').createDatabaseTool}'s `'records'` operation
1632
- * uses to detect truncation without a separate `count` round trip.
1705
+ * Clamps a `'records'` call's query to a row cap, and builds the probe query the caller reads with
1706
+ * — the pure leaf {@link import('./factories.js').createDatabaseTool}'s `'records'` operation uses
1707
+ * to detect truncation without a separate `count` round trip.
1633
1708
  *
1634
1709
  * @remarks
1635
1710
  * {@link resolveLimit} picks the effective limit, so a caller can never exceed the configured cap
1636
1711
  * by supplying a larger `query.limit`, and can never drive it below `0`. The returned probe query
1637
- * requests ONE MORE row than the effective limit (`limit: effective + 1`) — if storage returns
1712
+ * requests one more row than the effective limit (`limit: effective + 1`) — if storage returns
1638
1713
  * that many, the caller knows the true result was truncated (`rows.length > effective`) and slices
1639
1714
  * back down to `effective` before returning.
1640
1715
  *
@@ -1650,7 +1725,7 @@ function resolveLimit(requested, cap) {
1650
1725
  *
1651
1726
  * @param query - The live query to clamp (or `undefined`)
1652
1727
  * @param cap - The row-count ceiling
1653
- * @returns The PROBE query (`limit` bumped by one) and the effective `limit`
1728
+ * @returns The probe query (`limit` bumped by one) and the effective `limit`
1654
1729
  */
1655
1730
  function clampQuery(query, cap) {
1656
1731
  const limit = resolveLimit(query?.limit, cap);
@@ -1712,7 +1787,7 @@ function compileColumnPrimitive(primitive) {
1712
1787
  //#region src/core/stores/MemoryDefinitionStore.ts
1713
1788
  /**
1714
1789
  * Represents the in-memory {@link DefinitionStoreInterface} — a process-lifetime `Map` of
1715
- * {@link DatabaseDefinition}s keyed by database id, the DEFAULT store
1790
+ * {@link DatabaseDefinition}s keyed by database id, the default store
1716
1791
  * {@link import('../factories.js').createMemoryDefinitionStore} builds. It implements the same
1717
1792
  * {@link DefinitionStoreInterface} contract as
1718
1793
  * {@link import('./DatabaseDefinitionStore.js').DatabaseDefinitionStore}: this store copies on
@@ -1721,19 +1796,19 @@ function compileColumnPrimitive(primitive) {
1721
1796
  *
1722
1797
  * @remarks
1723
1798
  * A plain `Map<string, DatabaseDefinition>` (the definition is already pure,
1724
- * self-contained CONFIG-only JSON, so no encoding is needed for the memory tier). Values are
1725
- * structured-cloned on both write and read, keeping caller mutation outside the store. There is NO
1726
- * idle-TTL and NO eviction: a persisted definition lives until an explicit `delete`. A durable
1727
- * backend (JSON / SQLite / IndexedDB) swaps in through the SAME interface without touching a
1799
+ * self-contained config-only JSON, so no encoding is needed for the memory tier). Values are
1800
+ * structured-cloned on both write and read, keeping caller mutation outside the store. There is no
1801
+ * idle-TTL and no eviction: a persisted definition lives until an explicit `delete`. A durable
1802
+ * backend (JSON / SQLite / IndexedDB) swaps in through the same interface without touching a
1728
1803
  * consumer — its driver-pluggable twin is
1729
1804
  * {@link import('./DatabaseDefinitionStore.js').DatabaseDefinitionStore} (the definition as one
1730
1805
  * opaque JSON column).
1731
1806
  *
1732
1807
  * - **`get` resolves the persisted definition for an id**, or `undefined` if none is stored.
1733
- * - **`set` inserts / replaces under the definition's OWN `id`** (no separate id param).
1808
+ * - **`set` inserts / replaces under the definition's own `id`** (no separate id param).
1734
1809
  * - **`delete` drops a definition by id**; an absent id is a no-op (no throw).
1735
1810
  *
1736
- * The public surface is EXACTLY `get` / `set` / `delete` — no extra members (the method
1811
+ * The public surface is exactly `get` / `set` / `delete` — no extra members (the method
1737
1812
  * bijection with {@link DefinitionStoreInterface}).
1738
1813
  *
1739
1814
  * @example
@@ -1759,10 +1834,10 @@ var MemoryDefinitionStore = class {
1759
1834
  return Promise.resolve(definition === void 0 ? void 0 : structuredClone(definition));
1760
1835
  }
1761
1836
  /**
1762
- * Inserts or replaces a definition under its OWN `id`, copied into the backing `Map`.
1837
+ * Inserts or replaces a definition under its own `id`, copied into the backing `Map`.
1763
1838
  *
1764
1839
  * @param definition - The config to persist; its own `id` is the key (no separate id param)
1765
- * @returns A promise settling once the definition is stored
1840
+ * @returns A promise settling after the definition is stored
1766
1841
  */
1767
1842
  set(definition) {
1768
1843
  this.#definitions.set(definition.id, structuredClone(definition));
@@ -1772,7 +1847,7 @@ var MemoryDefinitionStore = class {
1772
1847
  * Drops the definition stored under `id`.
1773
1848
  *
1774
1849
  * @param id - The database id to drop; an absent id is a no-op, never a throw
1775
- * @returns A promise settling once no definition is stored under `id`
1850
+ * @returns A promise settling after no definition is stored under `id`
1776
1851
  */
1777
1852
  delete(id) {
1778
1853
  this.#definitions.delete(id);
@@ -1783,25 +1858,25 @@ var MemoryDefinitionStore = class {
1783
1858
  //#region src/core/stores/DatabaseDefinitionStore.ts
1784
1859
  /**
1785
1860
  * Represents a {@link DefinitionStoreInterface} backed by one table of the `@orkestrel/database` layer — a
1786
- * database's durable CONFIG state IS a row, so persistence reduces to keyed point-access
1861
+ * database's durable config state is a row, so persistence reduces to keyed point-access
1787
1862
  * (`get` / `set` / `delete`) over a {@link TableInterface}, the driver-pluggable twin of the
1788
1863
  * plain-`Map` {@link import('./MemoryDefinitionStore.js').MemoryDefinitionStore}.
1789
1864
  *
1790
1865
  * @remarks
1791
1866
  * The store is driver-agnostic: it holds a single {@link TableInterface} whose backend (memory,
1792
1867
  * JSON, SQLite, IndexedDB) is chosen by whoever builds it (the factories), so a JSON / SQLite /
1793
- * IndexedDB backend swaps in WITHOUT touching a consumer — the same seam as
1868
+ * IndexedDB backend swaps in without touching a consumer — the same seam as
1794
1869
  * {@link import('./MemoryDefinitionStore.js').MemoryDefinitionStore}. The driver defaults to
1795
1870
  * memory ({@link import('../factories.js').createDatabaseDefinitionStore} passes
1796
- * `createMemoryDriver()`), so it ALSO works in memory out of the box; you opt into the durable
1871
+ * `createMemoryDriver()`), so it also works in memory out of the box; you opt into the durable
1797
1872
  * plumbing by passing a JSON / SQLite / IndexedDB driver.
1798
1873
  *
1799
- * The {@link DatabaseDefinition} is stored as ONE OPAQUE JSON COLUMN — the table is a row of
1800
- * `{ id; definition }` ({@link DatabaseDefinitionRow}). The definition is already a COMPLETE,
1801
- * self-contained, pure-JSON CONFIG payload (never a live handle), so storing it whole is lossless
1802
- * AND keeps the row type flat (`definition` reads back as `unknown`).
1874
+ * The {@link DatabaseDefinition} is stored as one opaque JSON column — the table is a row of
1875
+ * `{ id; definition }` ({@link DatabaseDefinitionRow}). The definition is already a complete,
1876
+ * self-contained, pure-JSON config payload (never a live handle), so storing it whole is lossless
1877
+ * and keeps the row type flat (`definition` reads back as `unknown`).
1803
1878
  *
1804
- * - **`set(definition)` upserts under the definition's OWN `id`** (no separate id param) — it
1879
+ * - **`set(definition)` upserts under the definition's own `id`** (no separate id param) — it
1805
1880
  * writes the row `{ id: definition.id, definition }`.
1806
1881
  * - **`get(id)` resolves the stored definition for an id**, narrowing the opaque JSON column back
1807
1882
  * to a {@link DatabaseDefinition} ({@link import('../validators.js').isDatabaseDefinition} — the
@@ -1809,7 +1884,7 @@ var MemoryDefinitionStore = class {
1809
1884
  * or the stored blob is malformed.
1810
1885
  * - **`delete(id)` drops a definition by id**; an absent id is a no-op (no throw).
1811
1886
  *
1812
- * The public surface is EXACTLY `get` / `set` / `delete` — no extra members (the method
1887
+ * The public surface is exactly `get` / `set` / `delete` — no extra members (the method
1813
1888
  * bijection with {@link DefinitionStoreInterface}).
1814
1889
  *
1815
1890
  * @example
@@ -1847,10 +1922,10 @@ var DatabaseDefinitionStore = class {
1847
1922
  return isDatabaseDefinition(row.definition) ? row.definition : void 0;
1848
1923
  }
1849
1924
  /**
1850
- * Inserts or replaces a definition under its OWN `id` — the written row is `{ id, definition }`.
1925
+ * Inserts or replaces a definition under its own `id` — the written row is `{ id, definition }`.
1851
1926
  *
1852
1927
  * @param definition - The config to persist; its own `id` is the row key (no separate id param)
1853
- * @returns A promise settling once the row is written
1928
+ * @returns A promise settling after the row is written
1854
1929
  */
1855
1930
  async set(definition) {
1856
1931
  await this.#table.set({
@@ -1862,7 +1937,7 @@ var DatabaseDefinitionStore = class {
1862
1937
  * Drops the definition stored under `id`.
1863
1938
  *
1864
1939
  * @param id - The database id to drop; an absent id is a no-op, never a throw
1865
- * @returns A promise settling once no row is stored under `id`
1940
+ * @returns A promise settling after no row is stored under `id`
1866
1941
  */
1867
1942
  async delete(id) {
1868
1943
  await this.#table.remove(id);
@@ -1871,7 +1946,8 @@ var DatabaseDefinitionStore = class {
1871
1946
  //#endregion
1872
1947
  //#region src/core/databases/DatabaseResolver.ts
1873
1948
  /**
1874
- * Resolves database definitions into cached live handles for database tools.
1949
+ * Resolves a database definition into a cached live handle for a database tool, over the tool's
1950
+ * live handles, its stored definitions, its driver registry, and an optional key generator.
1875
1951
  *
1876
1952
  * @example
1877
1953
  * ```ts
@@ -1938,7 +2014,8 @@ var DatabaseResolver = class {
1938
2014
  this.#handles.delete(id);
1939
2015
  }
1940
2016
  /**
1941
- * Resolves a cached or stored database by id.
2017
+ * Resolves a live database by id — the cached handle when one exists, otherwise a database
2018
+ * constructed from its stored definition.
1942
2019
  *
1943
2020
  * @param id - Database definition id
1944
2021
  * @returns The cached or newly constructed live database
@@ -1973,8 +2050,8 @@ var DatabaseResolver = class {
1973
2050
  //#endregion
1974
2051
  //#region src/core/factories.ts
1975
2052
  /**
1976
- * Wraps a registered tool as a {@link WorkflowFunction} (`@orkestrel/workflow`) — the OPT-IN
1977
- * adapter that lets a `function`-form task run a `@orkestrel/tool` tool BY NAME.
2053
+ * Wraps a registered tool as a {@link WorkflowFunction} (`@orkestrel/workflow`) — the opt-in
2054
+ * adapter that lets a `function`-form task run a `@orkestrel/tool` tool by name.
1978
2055
  *
1979
2056
  * @remarks
1980
2057
  * Composes into a caller's `WorkflowOptions.functions` registry like any other behavior
@@ -2148,7 +2225,9 @@ function createWorkflowFunctions(runner, options) {
2148
2225
  return Object.freeze(composed);
2149
2226
  }
2150
2227
  /**
2151
- * Compiles the lenient workflow draft contract used by {@link createWorkflowTool}.
2228
+ * Compiles the lenient workflow draft contract {@link createWorkflowTool} parses an authored tree
2229
+ * with — a `ContractInterface` over a {@link WorkflowDraft}, whose `id` and `name` are optional at
2230
+ * the workflow, phase, and task levels.
2152
2231
  *
2153
2232
  * @returns The compiled {@link import('./types.js').WorkflowDraft} contract
2154
2233
  */
@@ -2156,34 +2235,33 @@ function createWorkflowDraftContract() {
2156
2235
  return createContract(workflowDraftShape);
2157
2236
  }
2158
2237
  /**
2159
- * Wraps a {@link WorkflowDefinition} as an LLM-callable tool — it ADVERTISES the SIMPLE flat
2160
- * authoring shape (`{ name?, steps: [{ name }] }`) as its `parameters` so even a small model can
2161
- * author a complete tree, and its handler EXPANDS / COMPLETES the authored blob, validates it
2162
- * against the STRICT contract, and runs it through `runner`, forwarding the caller's optional
2163
- * named functions and native checkpoint store.
2238
+ * Wraps a {@link WorkflowDefinition} as an LLM-callable tool — it advertises the flat authoring
2239
+ * shape (`{ name?, steps: [{ name }] }`) as its `parameters`, and its handler completes the
2240
+ * authored blob, validates it against the strict contract, and runs it through `runner`, forwarding
2241
+ * the caller's optional named functions and native checkpoint store.
2164
2242
  *
2165
2243
  * @remarks
2166
2244
  * A plain `ToolManagerInterface`-compatible tool (`@orkestrel/tool`), reproducing
2167
2245
  * Toolbox's flat / draft / full authoring contract, strict soundness gate, and lineage guard.
2168
- * It is ALSO the propagation carrier
2246
+ * It is also the propagation carrier
2169
2247
  * {@link createAgentFunction} binds onto a wrapped agent's `context.tools`: because a tool
2170
2248
  * handler receives only the model-supplied `args`, the immutable lineage is closed over at bind
2171
2249
  * time. The authored target is appended and its zero-based depth derived from workflow tags.
2172
2250
  *
2173
- * **Widened authoring surface (additive — the canonical contract + runner stay STRICT and
2174
- * unchanged).** A 2B model reliably CALLS the tool but cannot reliably emit the full four-level
2175
- * nested {@link WorkflowDefinition} (six required `id`/`name` strings, an all-or-nothing tree).
2176
- * So the tool ACCEPTS three authoring forms and converges them on the SAME strict
2251
+ * **Widened authoring surface (additive — the canonical contract and runner stay strict and
2252
+ * unchanged).** A 2B model reliably calls the tool but cannot reliably emit the full nested
2253
+ * {@link WorkflowDefinition}, whose every `id` and `name` is required across an all-or-nothing
2254
+ * tree. So the tool accepts the authoring forms that follow and converges them on the same strict
2177
2255
  * `createWorkflowContract` gate before running (soundness preserved):
2178
- * - the FLAT shape `{ name?, steps: [{ name }] }` — the ADVERTISED `parameters` (the simplest
2256
+ * - the flat shape `{ name?, steps: [{ name }] }` — the advertised `parameters` (the simplest
2179
2257
  * form, {@link import('./helpers.js').expandSteps}'d into one one-task phase per step);
2180
- * - a nested DRAFT with any `id`/`name` OMITTED — {@link createWorkflowDraftContract}-parsed then
2258
+ * - a nested draft with any `id`/`name` omitted — {@link createWorkflowDraftContract}-parsed then
2181
2259
  * {@link import('./helpers.js').completeDraft}'d (missing ids synthesized positionally);
2182
2260
  * - the full nested {@link WorkflowDefinition} — the advanced escape-hatch, accepted as the draft
2183
2261
  * super-set.
2184
2262
  *
2185
2263
  * The universal tool-handler contract: returns the plain run summary
2186
- * (`{ status, count, durable?, fault? }`) on success, THROWS a typed `ToolboxError` on Toolbox
2264
+ * (`{ status, count, durable?, fault? }`) on success, throws a typed `ToolboxError` on Toolbox
2187
2265
  * boundary failures — malformed authored args (`TOOL`), or an over-deep / cyclic nested run
2188
2266
  * (`DEPTH`) — and preserves genuine runner `WorkflowError`s. The `ToolManagerInterface` isolates every throw into the canonical tool result's
2189
2267
  * top-level `error`, so nothing escapes the run. `options.lineage` is the propagation carrier
@@ -2197,6 +2275,34 @@ function createWorkflowDraftContract() {
2197
2275
  * @returns A `ToolInterface` (named {@link import('./constants.js').WORKFLOW_TOOL_NAME}) whose
2198
2276
  * `parameters` advertise the flat authoring schema
2199
2277
  *
2278
+ * @example Authoring and running a workflow through the tool with a real ToolManager
2279
+ * ```ts
2280
+ * import { createWorkflowTool } from '@orkestrel/toolbox'
2281
+ * import { createToolManager } from '@orkestrel/tool'
2282
+ * import { createWorkflowRunner } from '@orkestrel/workflow'
2283
+ * import type { WorkflowDefinition } from '@orkestrel/workflow'
2284
+ *
2285
+ * const definition: WorkflowDefinition = { id: 'release', name: 'Release', phases: [] }
2286
+ * const runner = createWorkflowRunner()
2287
+ * const functions = {
2288
+ * compile: () => 'compiled',
2289
+ * publish: () => 'published',
2290
+ * }
2291
+ * const tool = createWorkflowTool(definition, runner, { functions })
2292
+ *
2293
+ * const tools = createToolManager()
2294
+ * tools.add(tool)
2295
+ *
2296
+ * // A small model authors the simple flat shape — no ids/names required.
2297
+ * const result = await tools.execute({
2298
+ * id: 'call-1',
2299
+ * name: 'workflow',
2300
+ * arguments: { name: 'release', steps: [{ name: 'compile' }, { name: 'publish' }] },
2301
+ * })
2302
+ * if (!result.success) throw new Error(result.error)
2303
+ * result.value // { status: 'completed', count: 2 } — the single-level envelope; no nested { id, name, value }
2304
+ * ```
2305
+ *
2200
2306
  * @example
2201
2307
  * ```ts
2202
2308
  * import { createWorkflowTool } from '@src/core'
@@ -2265,42 +2371,35 @@ function createWorkflowTool(definition, runner, options) {
2265
2371
  });
2266
2372
  }
2267
2373
  /**
2268
- * Builds an LLM-callable workspace-editing tool — it ADVERTISES the `operation`-discriminated
2269
- * union ({@link import('./shapers.js').workspaceToolShape}) as its `parameters`, and its
2270
- * handler PARSES the model-supplied args against that contract and DISPATCHES the matched
2271
- * operation against the manager's ACTIVE workspace (the registry ops drive the manager itself),
2272
- * returning the plain result. A malformed operation throws this package's `ToolboxError`; a
2273
- * genuine workspace-domain failure propagates `@orkestrel/workspace`'s typed `WorkspaceError`.
2274
- * EITHER drives a caller-supplied {@link WorkspaceToolOptions.manager} directly, OR
2275
- * constructs a fresh `WorkspaceManagerInterface` (`@orkestrel/workspace`) over
2276
- * {@link import('./types.js').WorkspaceToolOptions.store} (through `@orkestrel/workspace`'s
2277
- * `createWorkspaceManager`); neither given constructs a manager backed by
2278
- * `@orkestrel/workspace`'s in-memory store default.
2374
+ * Builds an LLM-callable workspace-editing tool — it advertises the `operation`-discriminated union
2375
+ * ({@link import('./shapers.js').workspaceToolShape}) as its `parameters`, and its handler parses
2376
+ * the model-supplied args against that contract and dispatches the matched operation against the
2377
+ * manager's active workspace, returning the plain result.
2279
2378
  *
2280
2379
  * @remarks
2281
- * MANAGER-DRIVEN: every edit / read op (read / list / has / search / replace / write / splice /
2380
+ * Manager-driven: every edit / read op (read / list / has / search / replace / write / splice /
2282
2381
  * prepend / append / move / remove) targets `manager.active`, so the model edits whichever
2283
2382
  * workspace is active and a host can re-point it (`WorkspaceManagerInterface.switch`) between
2284
- * turns. Two REGISTRY ops make the model self-sufficient: `workspaces` LISTS the registered
2383
+ * turns. The registry ops make the model self-sufficient: `workspaces` lists the registered
2285
2384
  * workspaces (each `{ id, files, active }`) so it can discover an id, and `switch` re-points the
2286
2385
  * active workspace by id (lenient — an unknown id is a no-op reporting `switched: false`, never a
2287
2386
  * throw).
2288
2387
  *
2289
- * NO-ACTIVE RULE (the ergonomic seam): a WRITING op (write / splice / prepend / append / move /
2290
- * remove / replace) run when `manager.active` is `undefined` AUTO-CREATES + activates a default
2291
- * workspace (`manager.add()`) so the model can start writing; a pure-READ op (read / list /
2292
- * has / search) against no active workspace returns the EMPTY result (`undefined` / `[]` /
2388
+ * No-active rule (the ergonomic seam): a writing op (write / splice / prepend / append / move /
2389
+ * remove / replace) run when `manager.active` is `undefined` auto-creates and activates a default
2390
+ * workspace (`manager.add()`) so the model can start writing; a pure-read op (read / list /
2391
+ * has / search) against no active workspace returns the empty result (`undefined` / `[]` /
2293
2392
  * `false`), never creating one and never throwing.
2294
2393
  *
2295
2394
  * The handler conforms to the universal tool-handler contract: it `contract.parse`s
2296
- * the args, THROWS a `TOOL` `ToolboxError` when no operation arm matched (a malformed / unknown
2297
- * operation), else `switch`es on `op.operation` and RETURNS the plain result — letting a
2395
+ * the args, throws a `TOOL` `ToolboxError` when no operation arm matched (a malformed / unknown
2396
+ * operation), else `switch`es on `op.operation` and returns the plain result — letting a
2298
2397
  * `WorkspaceError` raised by the live workspace (`MISSING` / `MODALITY` / `PATTERN` / `RANGE`)
2299
- * PROPAGATE uncaught. The range edit is the FLAT `'splice'` op: its four flat caret integers are
2398
+ * propagate uncaught. The range edit is the flat `'splice'` op: its flat caret integers are
2300
2399
  * reassembled into a `Range` (`@orkestrel/workspace`) by `rangeOf` and fed to the workspace's
2301
2400
  * ranged `write`.
2302
2401
  *
2303
- * @param options - `manager` (drive directly) OR `store` (build a manager over it); neither ⇒
2402
+ * @param options - `manager` (drive directly) or `store` (build a manager over it); neither ⇒
2304
2403
  * an in-memory-backed manager (see {@link import('./types.js').WorkspaceToolOptions})
2305
2404
  * @returns A `ToolInterface` (named {@link import('./constants.js').WORKSPACE_TOOL_NAME} by default)
2306
2405
  *
@@ -2418,8 +2517,8 @@ function createWorkspaceTool(options) {
2418
2517
  });
2419
2518
  }
2420
2519
  /**
2421
- * Builds an LLM-callable sub-agent delegation tool — resolves a live, seeded `AgentInterface`
2422
- * from `registry` and runs it to completion for ONE delegated `task`.
2520
+ * Builds an LLM-callable sub-agent delegation tool — it resolves a live, seeded `AgentInterface`
2521
+ * from `registry` and runs it to completion for one delegated `task`.
2423
2522
  *
2424
2523
  * @remarks
2425
2524
  * The universal tool-handler contract: validates the call args against
@@ -2427,10 +2526,10 @@ function createWorkspaceTool(options) {
2427
2526
  * sub-agent's conversation as a single `user` message; `provider` / `tools` / `system` fall
2428
2527
  * back to the tool's own {@link import('./types.js').AgentToolOptions} defaults), rehydrates the sub-agent through
2429
2528
  * `registry.build`, runs it with `agent.generate()`, and returns the settled
2430
- * `AgentResult.content` string (the sub-agent's final text). A missing / unresolvable `provider`, or a malformed call, THROWS a typed `TOOL`
2529
+ * `AgentResult.content` string (the sub-agent's final text). A missing / unresolvable `provider`, or a malformed call, throws a typed `TOOL`
2431
2530
  * {@link import('./errors.js').ToolboxError}; a delegation that would exceed
2432
2531
  * {@link import('./constants.js').AGENT_TOOL_DEPTH}, or re-enter an already-delegated agent (a
2433
- * cycle), THROWS a typed `DEPTH` {@link import('./errors.js').ToolboxError} — both isolated
2532
+ * cycle), throws a typed `DEPTH` {@link import('./errors.js').ToolboxError}, each isolated
2434
2533
  * by the `ToolManagerInterface` into the canonical tool result's top-level `error`.
2435
2534
  *
2436
2535
  * `AgentInterface` (`@orkestrel/agent`) exposes no teardown method — a bound sub-agent's
@@ -2502,9 +2601,8 @@ function createAgentTool(registry, options) {
2502
2601
  });
2503
2602
  }
2504
2603
  /**
2505
- * Builds an LLM-callable tool that returns the FULL `description` of another registered tool by
2506
- * name — the counterpart to the lean `summary` the other tools in this package advertise
2507
- * (`AGENT_TOOL_SUMMARY` / `WORKFLOW_TOOL_SUMMARY` / `WORKSPACE_TOOL_SUMMARY`).
2604
+ * Builds an LLM-callable tool that returns the full `description` of another registered tool by
2605
+ * name — the counterpart to the lean `summary` the other tools in this package advertise.
2508
2606
  *
2509
2607
  * @remarks
2510
2608
  * `ToolManagerInterface.definitions()` (`@orkestrel/tool`) advertises `tool.summary ??
@@ -2515,8 +2613,8 @@ function createAgentTool(registry, options) {
2515
2613
  * tool has no `description` of its own, then a placeholder when it has neither).
2516
2614
  *
2517
2615
  * The universal tool-handler contract: validates the call args against
2518
- * {@link import('./shapers.js').describeToolShape}, RETURNS the plain description string on
2519
- * success, THROWS a typed `TOOL` {@link import('./errors.js').ToolboxError} on a malformed call
2616
+ * {@link import('./shapers.js').describeToolShape}, returns the plain description string on
2617
+ * success, throws a typed `TOOL` {@link import('./errors.js').ToolboxError} on a malformed call
2520
2618
  * or an unknown tool name.
2521
2619
  *
2522
2620
  * @param tools - The `ToolManagerInterface` (`@orkestrel/tool`) whose registered tools this
@@ -2553,20 +2651,23 @@ function createDescribeTool(tools) {
2553
2651
  });
2554
2652
  }
2555
2653
  /**
2556
- * Builds an LLM-callable form tool — the ASK side of the terminal seam. Asks
2557
- * a multi-field form and BLOCKS until it answers, returning the resolved values record.
2654
+ * Builds an LLM-callable form tool — the ask side of the terminal seam. It asks a multi-field form
2655
+ * and blocks until the addressed terminal answers, returning the resolved values record.
2558
2656
  *
2559
2657
  * @remarks
2560
2658
  * The universal tool-handler contract: validates the call args against
2561
2659
  * {@link import('./shapers.js').promptToolShape}, parses the call's schema through
2562
2660
  * `@orkestrel/form`, constructs the live form, and passes it to `TerminalManagerInterface.ask`.
2563
- * `from` is FIXED at construction
2661
+ * `from` is fixed at construction
2564
2662
  * ({@link import('./types.js').PromptToolOptions.from}) — never read from the model-supplied
2565
- * args — so a model cannot spoof which terminal is asking. A form CYCLE rejects with
2663
+ * args — so a model cannot spoof which terminal is asking. A form cycle rejects with
2566
2664
  * `TerminalError('DEADLOCK')`, re-surfaced as a typed `DEADLOCK`
2567
2665
  * {@link import('./errors.js').ToolboxError}; an expired form re-surfaces as `EXPIRE`; an
2568
2666
  * unknown `to` (or any other `TerminalError`) re-surfaces as `TOOL`, naming the unknown terminal
2569
- * and how many brokers the manager holds (`manager.count`).
2667
+ * and how many brokers the manager holds (`manager.count`). A schema `parseForm` refuses — an
2668
+ * unknown control, a duplicate field name, a `'select'` or `'checkbox'` field without usable
2669
+ * `choices` — throws a typed `TOOL` error up front, so a malformed schema never parks as a form
2670
+ * nobody can answer.
2570
2671
  *
2571
2672
  * @param options - The live manager, the fixed `from` identity, and advertised overrides (see
2572
2673
  * {@link import('./types.js').PromptToolOptions})
@@ -2624,9 +2725,8 @@ function createPromptTool(options) {
2624
2725
  });
2625
2726
  }
2626
2727
  /**
2627
- * Builds an LLM-callable answer tool — the ANSWER side of the terminal seam. Lists the forms
2628
- * addressed to {@link import('./types.js').AnswerToolOptions.to}, or answers one of
2629
- * them by id.
2728
+ * Builds an LLM-callable answer tool — the answer side of the terminal seam. It lists the forms
2729
+ * addressed to {@link import('./types.js').AnswerToolOptions.to}, or answers one of them by id.
2630
2730
  *
2631
2731
  * @remarks
2632
2732
  * The universal tool-handler contract: validates the call args against
@@ -2636,10 +2736,10 @@ function createPromptTool(options) {
2636
2736
  * and applies it through
2637
2737
  * `TerminalManagerInterface.answer` — a rejected / unknown / unresolvable outcome
2638
2738
  * (`TerminalAnswerResult.error`) re-surfaces as a typed `ANSWER` `ToolboxError`; success returns
2639
- * `{ answered: id }`. `to` is FIXED at construction
2739
+ * `{ answered: id }`. `to` is fixed at construction
2640
2740
  * ({@link import('./types.js').AnswerToolOptions.to}) — never read from the model-supplied args —
2641
2741
  * so a model cannot spoof which terminal it is answering for. Concurrent answerers racing on one
2642
- * endpoint are FIRST-WRITE-WINS — a late answer to an already-settled form returns a typed
2742
+ * endpoint are first-write-wins — a late answer to an already-settled form returns a typed
2643
2743
  * `ANSWER` `ToolboxError` (surfaced as a 422 over HTTP).
2644
2744
  *
2645
2745
  * @param options - The live manager, the fixed `to` identity, and advertised overrides (see
@@ -2692,8 +2792,8 @@ function createAnswerTool(options) {
2692
2792
  }
2693
2793
  /**
2694
2794
  * Creates the in-memory {@link DefinitionStoreInterface} — a process-lifetime `Map` of database
2695
- * definitions, the DEFAULT store the database and relation tools persist their
2696
- * `DatabaseDefinition` configs through.
2795
+ * definitions, the default store the database and relation tools persist their `DatabaseDefinition`
2796
+ * configs through.
2697
2797
  *
2698
2798
  * @returns A {@link DefinitionStoreInterface}
2699
2799
  *
@@ -2740,7 +2840,7 @@ function createDatabaseDefinitionStore(driver = createMemoryDriver()) {
2740
2840
  * @remarks
2741
2841
  * The universal tool-handler contract: validates the call args against
2742
2842
  * {@link import('./shapers.js').databaseToolShape}, dispatches to the matching operation, and
2743
- * RETURNS a plain result on success. A database is resolved lazily and cached for the tool's
2843
+ * returns a plain result on success. A database is resolved lazily and cached for the tool's
2744
2844
  * lifetime — `'create'` mints one from `tables` ({@link import('./compilers.js').expandTables}) and
2745
2845
  * a registered `driver` key ({@link import('./types.js').DatabaseToolOptions.drivers}, default
2746
2846
  * `{ memory: () => createMemoryDriver() }`); any other operation addressing an uncached id falls
@@ -2765,7 +2865,7 @@ function createDatabaseDefinitionStore(driver = createMemoryDriver()) {
2765
2865
  * ({@link import('./helpers.js').inferDatabaseCode}); an `ToolboxError` thrown by this tool's own
2766
2866
  * guards passes through unwrapped.
2767
2867
  *
2768
- * A lazily re-minted database over the DEFAULT in-memory driver yields an EMPTY database — only
2868
+ * A lazily re-minted database over the default in-memory driver yields an empty database — only
2769
2869
  * the {@link import('./types.js').DatabaseDefinition} schema persists in `store`, never rows;
2770
2870
  * durable rows need a persistent driver factory registered in
2771
2871
  * {@link import('./types.js').DatabaseToolOptions.drivers}. `'destroy'` closes whatever handle is
@@ -2773,7 +2873,7 @@ function createDatabaseDefinitionStore(driver = createMemoryDriver()) {
2773
2873
  * {@link import('./types.js').DatabaseToolOptions.databases} handle — the embedder relinquishes
2774
2874
  * that handle's lifecycle to this tool for any id it wires in. This tool assumes the
2775
2875
  * single-writer, non-reentrant model `@orkestrel/database` itself assumes — concurrent calls
2776
- * against one id are NOT serialized by this tool. `'get'` is uncapped by
2876
+ * against one id are not serialized by this tool. `'get'` is uncapped by
2777
2877
  * {@link import('./types.js').DatabaseToolOptions.limit} (bounded only by the caller's `key` array
2778
2878
  * size), unlike `'records'` / `'find'` / `'links'`.
2779
2879
  *
@@ -2949,14 +3049,14 @@ function createDatabaseTool(options = {}) {
2949
3049
  * The universal tool-handler contract: validates the call args against
2950
3050
  * {@link import('./shapers.js').relationToolShape}, resolves the addressed
2951
3051
  * {@link import('@orkestrel/relation').RelationManagerInterface} — an explicit `manager` field
2952
- * must match a key of {@link import('./types.js').RelationToolOptions.managers}, an OMITTED one
2953
- * resolves to the SOLE registered manager, either miss throwing a typed `TOOL`
3052
+ * must match a key of {@link import('./types.js').RelationToolOptions.managers}, an omitted one
3053
+ * resolves to the sole registered manager, either miss throwing a typed `TOOL`
2954
3054
  * {@link import('./errors.js').ToolboxError}
2955
3055
  * ({@link import('./helpers.js').resolveRelationManager}) — then resolves `model` against it
2956
3056
  * ({@link import('./helpers.js').resolveRelationModel}, same typed-`TOOL`-on-miss shape), and
2957
- * dispatches to the matched operation, RETURNING a plain result on success.
3057
+ * dispatches to the matched operation, returning a plain result on success.
2958
3058
  *
2959
- * `'load'` / `'find'` expand the call's FLAT dot-path `include` list into a live
3059
+ * `'load'` / `'find'` expand the call's flat dot-path `include` list into a live
2960
3060
  * `@orkestrel/relation` `Include` tree through {@link import('./helpers.js').expandInclude}, capped
2961
3061
  * at {@link import('./types.js').RelationToolOptions.depth} (default
2962
3062
  * {@link import('./constants.js').RELATION_TOOL_DEPTH}) — a path exceeding the cap, or carrying an
@@ -2966,7 +3066,7 @@ function createDatabaseTool(options = {}) {
2966
3066
  * result to {@link import('./types.js').RelationToolOptions.limit} (default
2967
3067
  * {@link import('./constants.js').RELATION_TOOL_LIMIT}), taken through
2968
3068
  * {@link import('./helpers.js').resolveLimit} — `'find'` probes one row past the effective limit to
2969
- * report `truncated`; `'links'` (which has no upstream pagination) fetches the FULL linked-key
3069
+ * report `truncated`; `'links'` (which has no upstream pagination) fetches the full linked-key
2970
3070
  * list and slices/truncates it the same way. `'link'` / `'unlink'` write / remove one `through` junction
2971
3071
  * row.
2972
3072
  *
@@ -3066,44 +3166,44 @@ function createRelationTool(options) {
3066
3166
  });
3067
3167
  }
3068
3168
  /**
3069
- * Builds a standalone LLM-callable tool that infers a JSON Schema from example values — the
3070
- * utility half of the "existing API/DB → MCP tool" bridge (the other half,
3071
- * {@link createEndpointTool}, wraps one CONCRETE endpoint).
3169
+ * Builds a standalone LLM-callable tool that infers a JSON Schema from example values — the utility
3170
+ * half of the bridge from an existing API or database into an MCP tool (the other half,
3171
+ * {@link createEndpointTool}, wraps one concrete endpoint).
3072
3172
  *
3073
3173
  * @remarks
3074
3174
  * The universal tool-handler contract: validates the call args against
3075
3175
  * {@link import('./shapers.js').inferToolShape} (`samples` non-empty, `format` / `enum` optional
3076
3176
  * booleans, `candidates` an optional array), infers a schema through `@orkestrel/contract`'s
3077
3177
  * `samplesToSchema`, wraps a non-object root as `{ value: <schema> }` through `schemaToObject` (mirrors
3078
- * the tool-parameters convention every other `create*Tool` factory advertises), and RETURNS the
3178
+ * the tool-parameters convention every other `create*Tool` factory advertises), and returns the
3079
3179
  * resulting parameters record. An empty `samples` array fails `inferToolShape`'s `min: 1` bound —
3080
3180
  * `contract.parse` returns `undefined` and the handler throws a typed `TOOL`
3081
3181
  * {@link import('./errors.js').ToolboxError}.
3082
3182
  *
3083
- * When `candidates` is ABSENT, the return is the bare parameters record — unchanged from before
3084
- * this array existed. When `candidates` is PRESENT (any array, including empty), the handler
3085
- * compiles a SEPARATE per-call contract from the RAW inferred schema (through `@orkestrel/contract`'s
3086
- * `schemaToShape`, NOT the `schemaToObject`-wrapped parameters — a bare-value sample checks a
3183
+ * When `candidates` is absent, the return is the bare parameters record — unchanged from before
3184
+ * this array existed. When `candidates` is present (any array, including empty), the handler
3185
+ * compiles a separate per-call contract from the raw inferred schema (through `@orkestrel/contract`'s
3186
+ * `schemaToShape`, not the `schemaToObject`-wrapped parameters — a bare-value sample checks a
3087
3187
  * bare-value candidate) and returns `{ parameters, checks }`, one check per candidate at the same
3088
- * index. Every entry has a UNIFORM shape — `{ index, valid, coercible }`, with `faults` added ONLY
3089
- * when `valid` is `false`: `valid` is the STRICT guard verdict (`checker.is(candidate)`), the
3090
- * OPPOSITE of {@link createEndpointTool}'s enforcement, which coerces (`7` becomes `'7'` for a
3091
- * string slot) — here a conformance report answers "does this value conform AS-IS": `7` against a
3092
- * string slot is `valid: false`, full stop. `coercible` answers a SEPARATE question — "would the
3093
- * NORMALIZING parse accept this value", that is would {@link createEndpointTool}'s default enforcement
3188
+ * index. Every entry has a uniform shape — `{ index, valid, coercible }`, with `faults` added only
3189
+ * when `valid` is `false`: `valid` is the strict guard verdict (`checker.is(candidate)`), the
3190
+ * opposite of {@link createEndpointTool}'s enforcement, which coerces (`7` becomes `'7'` for a
3191
+ * string slot) — here a conformance report answers "does this value conform as-is": `7` against a
3192
+ * string slot is `valid: false`, full stop. `coercible` answers a separate question — "would the
3193
+ * normalizing parse accept this value", that is would {@link createEndpointTool}'s default enforcement
3094
3194
  * admit it (`checker.parse(candidate) !== undefined`) — computed for every candidate regardless of
3095
3195
  * `valid`; by the house parse/guard round-trip, a `valid: true` entry is
3096
- * ALWAYS also `coercible: true`. `@orkestrel/contract`'s `explain` mirrors the normalizing
3196
+ * always also `coercible: true`. `@orkestrel/contract`'s `explain` mirrors the normalizing
3097
3197
  * `parse`'s leniency, not `is`'s strictness — so a strictly-invalid but coercible candidate (`7`
3098
- * against a string slot) yields `{ valid: false, coercible: true, faults: [] }`: EMPTY faults, since
3198
+ * against a string slot) yields `{ valid: false, coercible: true, faults: [] }`: empty faults, because
3099
3199
  * the mismatch the normalizing parse would silently fix is not one `explain` reports. `faults`
3100
- * therefore only ever populates for a NON-coercible mismatch — a wrong type the parse can't coerce
3200
+ * therefore only ever populates for a non-coercible mismatch — a wrong type the parse can't coerce
3101
3201
  * (a boolean in a string slot), a missing required key, or an out-of-enum value — where
3102
3202
  * `coercible: false`. `checker.is` / `.parse` / `.explain` are all total over JSON-safe input — a
3103
- * JSON-safe hostile candidate (a `__proto__`-carrying object, deeply nested data) reaches all three
3104
- * and yields a bounded, non-throwing per-candidate verdict; a NON-JSON-safe candidate (for example a
3105
- * throwing-getter `Proxy`) never reaches the checker at all — it fails the OUTER `args` parse
3106
- * against {@link import('./shapers.js').inferToolShape} and rejects the WHOLE call with the same
3203
+ * JSON-safe hostile candidate (a `__proto__`-carrying object, deeply nested data) reaches each of them
3204
+ * and yields a bounded, non-throwing per-candidate verdict; a non-JSON-safe candidate (for example a
3205
+ * throwing-getter `Proxy`) never reaches the checker at all — it fails the outer `args` parse
3206
+ * against {@link import('./shapers.js').inferToolShape} and rejects the whole call with the same
3107
3207
  * `TOOL` {@link import('./errors.js').ToolboxError} a malformed `samples`/`format`/`enum` throws,
3108
3208
  * with no per-candidate verdict produced.
3109
3209
  *
@@ -3182,36 +3282,36 @@ function createInferTool(options) {
3182
3282
  });
3183
3283
  }
3184
3284
  /**
3185
- * Wraps one CONCRETE endpoint ({@link import('./types.js').EndpointDefinition}) as an LLM-callable
3186
- * `ToolInterface` — the endpoint half of the "existing API/DB → MCP tool" bridge (the other half,
3187
- * {@link createInferTool}, is a standalone inference utility).
3285
+ * Wraps one concrete endpoint ({@link import('./types.js').EndpointDefinition}) as an LLM-callable
3286
+ * `ToolInterface` — the endpoint half of the bridge from an existing API or database into an MCP
3287
+ * tool (the other half, {@link createInferTool}, is a standalone inference utility).
3188
3288
  *
3189
3289
  * @remarks
3190
- * `parameters` is inferred ONCE at construction from `definition.samples` through
3290
+ * `parameters` is inferred once at construction from `definition.samples` through
3191
3291
  * `@orkestrel/contract`'s `samplesToSchema` (tuned by {@link import('./types.js').EndpointToolOptions}'s
3192
3292
  * `format` / `enum`), wrapping a non-object root as `{ value: <schema> }` through `schemaToObject` —
3193
- * the SAME object-rooted schema is both the ADVERTISED `parameters` and, by default
3194
- * ({@link import('./types.js').EndpointToolOptions.validate} `true`), the ENFORCED contract:
3195
- * `@orkestrel/contract`'s `schemaToShape` compiles it ONCE (through `createContract`) into a
3293
+ * the same object-rooted schema is both the advertised `parameters` and, by default
3294
+ * ({@link import('./types.js').EndpointToolOptions.validate} `true`), the enforced contract:
3295
+ * `@orkestrel/contract`'s `schemaToShape` compiles it once (through `createContract`) into a
3196
3296
  * `ContractInterface` whose `.parse` runs on every call's `args` before `definition.execute` — a
3197
- * NORMALIZING parse, not a strict type check: a scalar is COERCED to its inferred type where the
3297
+ * normalizing parse, not a strict type check: a scalar is coerced to its inferred type where the
3198
3298
  * house parsers coerce (a number to/from a numeric string, a boolean from `'1'`/`'0'`/`'true'`/
3199
- * `'false'`/`1`/`0`), so `definition.execute` receives the COERCED value (for example `7` sent for a
3299
+ * `'false'`/`1`/`0`), so `definition.execute` receives the coerced value (for example `7` sent for a
3200
3300
  * string slot arrives as `'7'`), not the raw call value. A call whose `args` fails to parse into
3201
- * a record — a required key missing, or a value not coercible to its slot's type — THROWS a
3301
+ * a record — a required key missing, or a value not coercible to its slot's type — throws a
3202
3302
  * typed `TOOL` {@link import('./errors.js').ToolboxError} carrying the compiled contract's
3203
3303
  * structured `explain` faults, and `definition.execute` is never called. `format` annotations are
3204
- * NEVER asserted, and a key outside the closed inferred schema is SILENTLY DROPPED rather than
3304
+ * never asserted, and a key outside the closed inferred schema is silently dropped rather than
3205
3305
  * rejected (see {@link import('./types.js').EndpointToolOptions.validate}). With
3206
- * `validate: false`, the tool's `execute` PASSES THROUGH the model-supplied `args` to
3207
- * `definition.execute` WITHOUT re-validation — the raw-passthrough opt-out. Either way, the
3208
- * definition's return flows back as the tool call's plain result; a throw PROPAGATES uncaught,
3306
+ * `validate: false`, the tool's `execute` passes through the model-supplied `args` to
3307
+ * `definition.execute` without re-validation — the raw-passthrough opt-out. Either way, the
3308
+ * definition's return flows back as the tool call's plain result; a throw propagates uncaught,
3209
3309
  * isolated by the `ToolManagerInterface` (`@orkestrel/tool`) into the canonical error envelope
3210
3310
  * — never caught or re-wrapped here.
3211
3311
  *
3212
3312
  * @param definition - The endpoint's identity, non-empty samples, and local handler (see
3213
3313
  * {@link import('./types.js').EndpointDefinition})
3214
- * @param options - Construction-time inference tuning + the validate opt-out (see
3314
+ * @param options - Construction-time inference tuning and the validate opt-out (see
3215
3315
  * {@link import('./types.js').EndpointToolOptions})
3216
3316
  * @returns A `ToolInterface` named `definition.name`
3217
3317
  *