@orkestrel/brief 0.0.5 → 0.0.7

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.
@@ -4,7 +4,7 @@ let _orkestrel_interpret = require("@orkestrel/interpret");
4
4
  let _orkestrel_reason = require("@orkestrel/reason");
5
5
  let _orkestrel_emitter = require("@orkestrel/emitter");
6
6
  //#region src/core/constants.ts
7
- /** The twelve `TaskOperation` values, frozen. */
7
+ /** Lists the `TaskOperation` values, frozen. */
8
8
  var TASK_OPERATIONS = Object.freeze([
9
9
  "create",
10
10
  "refactor",
@@ -19,7 +19,7 @@ var TASK_OPERATIONS = Object.freeze([
19
19
  "document",
20
20
  "plan"
21
21
  ]);
22
- /** The eight `TaskDomain` values, frozen. */
22
+ /** Lists the `TaskDomain` values, frozen. */
23
23
  var TASK_DOMAINS = Object.freeze([
24
24
  "code",
25
25
  "writing",
@@ -30,7 +30,7 @@ var TASK_DOMAINS = Object.freeze([
30
30
  "ops",
31
31
  "other"
32
32
  ]);
33
- /** The five `OutputFormat` values, frozen. */
33
+ /** Lists the `OutputFormat` values, frozen. */
34
34
  var OUTPUT_FORMATS = Object.freeze([
35
35
  "markdown",
36
36
  "json",
@@ -38,35 +38,64 @@ var OUTPUT_FORMATS = Object.freeze([
38
38
  "diff",
39
39
  "prose"
40
40
  ]);
41
- /** The three `RiskSeverity` values, frozen. */
41
+ /** Lists the `RiskSeverity` values, frozen. */
42
42
  var RISK_SEVERITIES = Object.freeze([
43
43
  "low",
44
44
  "medium",
45
45
  "high"
46
46
  ]);
47
47
  /**
48
- * `16` the default turn cap `briefToGoal` renders.
48
+ * Lists every published `Interpretation` member name, frozen.
49
+ *
50
+ * @remarks
51
+ * The capture list `BriefCompiler` hands `captureValue` at each interpret door — the borrowed
52
+ * engine's return, and the caller's supplied interpretation. A class instance carries its
53
+ * contract on the prototype, so the captured view materializes exactly the members named here,
54
+ * and a name missing from the list is a member the view drops.
55
+ *
56
+ * The `satisfies` clause refuses a name `Interpretation` does not declare, and it holds the
57
+ * element type at the listed names rather than widening it to `string`. That is what lets the
58
+ * equality assertion beside the capture cases refuse a list that has fallen short of the
59
+ * published shape.
60
+ */
61
+ var INTERPRETATION_MEMBERS = Object.freeze([
62
+ "text",
63
+ "normalized",
64
+ "intent",
65
+ "entities",
66
+ "subject",
67
+ "definition",
68
+ "mappings",
69
+ "ambiguities",
70
+ "prompt",
71
+ "stages",
72
+ "failures",
73
+ "confidence",
74
+ "digest"
75
+ ]);
76
+ /**
77
+ * Holds `16` — the default turn cap `briefToGoal` renders.
49
78
  *
50
79
  * @remarks
51
80
  * Domain-qualified so the barrel stays collision-free as sibling modules add their own
52
81
  * turn defaults.
53
82
  */
54
83
  var DEFAULT_BRIEF_TURNS = 16;
55
- /** `'gate'` — the id of the `gateDefinition()` logical definition. */
84
+ /** Holds `'gate'` — the id of the `buildGateDefinition()` logical definition. */
56
85
  var GATE_ID = "gate";
57
86
  /**
58
- * Every line terminator a brief field refuses.
87
+ * Matches every line terminator a brief field refuses.
59
88
  *
60
89
  * @remarks
61
- * The four ECMAScript line terminators, not just `\n`: a renderer that splits on any of
62
- * them would let the other three forge a markdown row. CRLF leads the alternation so a
63
- * Windows exemplar splits as ONE break rather than two, which would insert a blank line the
64
- * caller never wrote. Kept unanchored and stateless — no `g` flag — so `test` never carries
90
+ * Every ECMAScript line terminator, not just `\n`: a renderer that splits on any of them
91
+ * would let the others forge a markdown row. CRLF leads the alternation so a Windows
92
+ * exemplar splits as ONE break rather than two, which would insert a blank line the caller
93
+ * never wrote. Kept unanchored and stateless — no `g` flag — so `test` never carries
65
94
  * `lastIndex` between calls.
66
95
  */
67
96
  var LINE_BREAK_PATTERN = /\r\n|[\n\r\u2028\u2029]/;
68
97
  /**
69
- * The positive form of {@link LINE_BREAK_PATTERN}, for the shape DSL.
98
+ * Holds the positive form of {@link LINE_BREAK_PATTERN}, for the shape DSL.
70
99
  *
71
100
  * @remarks
72
101
  * `stringShape`'s `pattern` must MATCH an accepted value, so the guard's refusal regex
@@ -75,7 +104,7 @@ var LINE_BREAK_PATTERN = /\r\n|[\n\r\u2028\u2029]/;
75
104
  */
76
105
  var SINGLE_LINE_PATTERN = /^[^\n\r\u2028\u2029]*$/;
77
106
  /**
78
- * A string of one or more spaces and nothing else.
107
+ * Matches a string of one or more spaces and nothing else.
79
108
  *
80
109
  * @remarks
81
110
  * The one exemplar side `exampleToLines` must NOT pad. CommonMark strips a fully-blank code
@@ -89,7 +118,7 @@ var BLANK_PATTERN = /^ +$/;
89
118
  //#endregion
90
119
  //#region src/core/errors.ts
91
120
  /**
92
- * The one error class this package throws.
121
+ * Represents the one error class this package throws.
93
122
  *
94
123
  * @remarks
95
124
  * Throws are reserved for caller misuse: `assertBrief`, `snapshotBrief`, and `pinBrief` on
@@ -119,10 +148,10 @@ var BriefError = class extends Error {
119
148
  }
120
149
  };
121
150
  /**
122
- * Narrow a caught value to a {@link BriefError}.
151
+ * Narrows a caught value to a {@link BriefError}.
123
152
  *
124
153
  * @param value - The caught value to inspect.
125
- * @returns `true` when `value` is a `BriefError`.
154
+ * @returns True if `value` is a `BriefError`; false otherwise.
126
155
  *
127
156
  * @example
128
157
  * ```ts
@@ -140,82 +169,82 @@ function isBriefError(value) {
140
169
  }
141
170
  //#endregion
142
171
  //#region src/core/shapers.ts
143
- /** A single-line string of any length, including empty. */
172
+ /** Describes a single-line string of any length, including empty. */
144
173
  var textShape = (0, _orkestrel_contract.stringShape)({ pattern: SINGLE_LINE_PATTERN });
145
- /** A non-empty single-line string — the shape mirror of `isLine`. */
174
+ /** Describes a non-empty single-line string — the shape mirror of `isLine`. */
146
175
  var lineShape = (0, _orkestrel_contract.stringShape)({
147
176
  min: 1,
148
177
  pattern: SINGLE_LINE_PATTERN
149
178
  });
150
- /** The `Task` shape — closed operation and domain vocabularies plus a non-empty statement. */
179
+ /** Describes the `Task` shape — closed operation and domain vocabularies plus a non-empty statement. */
151
180
  var taskShape = (0, _orkestrel_contract.objectShape)({
152
181
  operation: (0, _orkestrel_contract.literalShape)(TASK_OPERATIONS),
153
182
  domain: (0, _orkestrel_contract.literalShape)(TASK_DOMAINS),
154
183
  statement: lineShape
155
184
  }, { description: "What the brief asks for, in one imperative sentence." });
156
- /** The `Reference` shape — a path and the note that justifies listing it. */
185
+ /** Describes the `Reference` shape — a path and the note that justifies listing it. */
157
186
  var referenceShape = (0, _orkestrel_contract.objectShape)({
158
187
  path: lineShape,
159
188
  note: lineShape
160
189
  }, { description: "One referenced path and why it is listed." });
161
- /** The `Manifest` shape — four disjoint reference partitions. */
190
+ /** Describes the `Manifest` shape — disjoint reference partitions. */
162
191
  var manifestShape = (0, _orkestrel_contract.objectShape)({
163
192
  read: (0, _orkestrel_contract.arrayShape)(referenceShape),
164
193
  edit: (0, _orkestrel_contract.arrayShape)(referenceShape),
165
194
  locked: (0, _orkestrel_contract.arrayShape)(referenceShape),
166
195
  forbidden: (0, _orkestrel_contract.arrayShape)(referenceShape)
167
- }, { description: "The four disjoint file partitions of a brief." });
168
- /** The `Outcome` shape — a one-based rank, the result text, and whether it gates done. */
196
+ }, { description: "The disjoint file partitions of a brief." });
197
+ /** Describes the `Outcome` shape — a one-based rank, the result text, and whether it gates done. */
169
198
  var outcomeShape = (0, _orkestrel_contract.objectShape)({
170
199
  rank: (0, _orkestrel_contract.integerShape)({ min: 1 }),
171
200
  text: lineShape,
172
201
  required: (0, _orkestrel_contract.booleanShape)()
173
202
  }, { description: "One ranked outcome — a result, never a step." });
174
- /** The `Given` shape — one categorized context fact. */
203
+ /** Describes the `Given` shape — one categorized context fact. */
175
204
  var givenShape = (0, _orkestrel_contract.objectShape)({
176
205
  category: lineShape,
177
206
  name: lineShape,
178
207
  value: textShape
179
208
  }, { description: "One context fact handed to the executor." });
180
- /** The `Example` shape — one input to output exemplar. */
209
+ /** Describes the `Example` shape — one input to output exemplar. */
181
210
  var exampleShape = (0, _orkestrel_contract.objectShape)({
182
211
  input: (0, _orkestrel_contract.stringShape)({ min: 1 }),
183
212
  output: (0, _orkestrel_contract.stringShape)({ min: 1 }),
184
213
  note: (0, _orkestrel_contract.optionalShape)(lineShape)
185
214
  }, { description: "One input to output exemplar." });
186
- /** The `Citation` shape — a name, a locator, and why the source is cited. */
215
+ /** Describes the `Citation` shape — a name, a locator, and why the source is cited. */
187
216
  var citationShape = (0, _orkestrel_contract.objectShape)({
188
217
  name: lineShape,
189
218
  url: lineShape,
190
219
  note: lineShape
191
220
  }, { description: "One external source; list order is the trust order." });
192
- /** The `Gap` shape — an unknown, whether it blocks, and the candidates that would close it. */
221
+ /** Describes the `Gap` shape — an unknown, whether it blocks, and the candidates that would close it. */
193
222
  var gapShape = (0, _orkestrel_contract.objectShape)({
194
223
  field: lineShape,
195
224
  question: lineShape,
196
225
  blocking: (0, _orkestrel_contract.booleanShape)(),
197
226
  candidates: (0, _orkestrel_contract.optionalShape)((0, _orkestrel_contract.arrayShape)(lineShape))
198
227
  }, { description: "One unresolved decision; blocking means the gate fails closed." });
199
- /** The `Risk` shape — a closed severity, the risk, and its mitigation. */
228
+ /** Describes the `Risk` shape — a closed severity, the risk, and its mitigation. */
200
229
  var riskShape = (0, _orkestrel_contract.objectShape)({
201
230
  severity: (0, _orkestrel_contract.literalShape)(RISK_SEVERITIES),
202
231
  text: lineShape,
203
232
  mitigation: lineShape
204
233
  }, { description: "One pre-empted risk and the mitigation that answers it." });
205
- /** The `Output` shape — a closed format plus its optional refinements. */
234
+ /** Describes the `Output` shape — a closed format plus its optional refinements. */
206
235
  var outputShape = (0, _orkestrel_contract.objectShape)({
207
236
  format: (0, _orkestrel_contract.literalShape)(OUTPUT_FORMATS),
208
237
  sections: (0, _orkestrel_contract.optionalShape)((0, _orkestrel_contract.arrayShape)(lineShape)),
209
238
  include: (0, _orkestrel_contract.optionalShape)((0, _orkestrel_contract.arrayShape)(lineShape)),
210
239
  exclude: (0, _orkestrel_contract.optionalShape)((0, _orkestrel_contract.arrayShape)(lineShape))
211
240
  }, { description: "The closed shape of the deliverable." });
212
- /** The `Proof` shape — the claim and the command that settles it. */
241
+ /** Describes the `Proof` shape — the claim and the command that settles it. */
213
242
  var proofShape = (0, _orkestrel_contract.objectShape)({
214
243
  text: lineShape,
215
244
  command: lineShape
216
245
  }, { description: "One mechanical, transcript-provable check." });
217
246
  /**
218
- * The whole `Brief` shape, section shapes composed.
247
+ * Describes the whole `Brief` shape, section shapes composed.
219
248
  *
220
249
  * @remarks
221
250
  * `trace` and `hash` are optional because `pinBrief` fills them; an unpinned draft is
@@ -242,40 +271,82 @@ var briefShape = (0, _orkestrel_contract.objectShape)({
242
271
  //#endregion
243
272
  //#region src/core/validators.ts
244
273
  /**
245
- * `true` when the value is a string holding no line terminator, empty included.
274
+ * Checks whether the value is a string holding no line terminator, empty included.
246
275
  *
247
276
  * @remarks
248
277
  * `briefToMarkdown` renders each brief field as ONE markdown row, so a field carrying a
249
278
  * line break would forge a heading or an extra manifest row — which is how a rendered
250
279
  * prompt and `briefToDispatch`'s path sets could disagree about the same brief.
280
+ *
281
+ * @param value - The value to inspect.
282
+ * @returns True if `value` is a string holding no line terminator, empty included; false
283
+ * otherwise.
251
284
  */
252
285
  var isText = (value) => (0, _orkestrel_contract.isString)(value) && !LINE_BREAK_PATTERN.test(value);
253
- /** `true` when the value is a non-empty string holding no line terminator. */
286
+ /**
287
+ * Checks whether the value is a non-empty string holding no line terminator.
288
+ *
289
+ * @param value - The value to inspect.
290
+ * @returns True if `value` is a non-empty string holding no line terminator; false otherwise.
291
+ */
254
292
  var isLine = (0, _orkestrel_contract.andOf)(_orkestrel_contract.isNonEmptyString, isText);
255
- /** `true` when the value is one of the twelve `TaskOperation` literals. */
293
+ /**
294
+ * Checks whether the value is one of the `TaskOperation` literals.
295
+ *
296
+ * @param value - The value to inspect.
297
+ * @returns True if `value` is one of the `TaskOperation` literals; false otherwise.
298
+ */
256
299
  var isTaskOperation = (0, _orkestrel_contract.literalOf)(TASK_OPERATIONS);
257
- /** `true` when the value is one of the eight `TaskDomain` literals. */
300
+ /**
301
+ * Checks whether the value is one of the `TaskDomain` literals.
302
+ *
303
+ * @param value - The value to inspect.
304
+ * @returns True if `value` is one of the `TaskDomain` literals; false otherwise.
305
+ */
258
306
  var isTaskDomain = (0, _orkestrel_contract.literalOf)(TASK_DOMAINS);
259
- /** `true` when the value is one of the five `OutputFormat` literals. */
307
+ /**
308
+ * Checks whether the value is one of the `OutputFormat` literals.
309
+ *
310
+ * @param value - The value to inspect.
311
+ * @returns True if `value` is one of the `OutputFormat` literals; false otherwise.
312
+ */
260
313
  var isOutputFormat = (0, _orkestrel_contract.literalOf)(OUTPUT_FORMATS);
261
- /** `true` when the value is one of the three `RiskSeverity` literals. */
314
+ /**
315
+ * Checks whether the value is one of the `RiskSeverity` literals.
316
+ *
317
+ * @param value - The value to inspect.
318
+ * @returns True if `value` is one of the `RiskSeverity` literals; false otherwise.
319
+ */
262
320
  var isRiskSeverity = (0, _orkestrel_contract.literalOf)(RISK_SEVERITIES);
263
- /** `true` when the value is a well-formed `Task` — both vocabularies closed, statement one line. */
321
+ /**
322
+ * Checks whether the value is a well-formed `Task` — both vocabularies closed, statement one line.
323
+ *
324
+ * @param value - The value to inspect.
325
+ * @returns True if `value` is a well-formed `Task`; false otherwise.
326
+ */
264
327
  var isTask = (0, _orkestrel_contract.recordOf)({
265
328
  operation: isTaskOperation,
266
329
  domain: isTaskDomain,
267
330
  statement: isLine
268
331
  });
269
- /** `true` when the value is a well-formed `Reference` — both members required, both single-line. */
332
+ /**
333
+ * Checks whether the value is a well-formed `Reference` — both members required, both single-line.
334
+ *
335
+ * @param value - The value to inspect.
336
+ * @returns True if `value` is a well-formed `Reference`; false otherwise.
337
+ */
270
338
  var isReference = (0, _orkestrel_contract.recordOf)({
271
339
  path: isLine,
272
340
  note: isLine
273
341
  });
274
342
  /**
275
- * `true` when the value is a well-formed `Manifest`.
343
+ * Checks whether the value is a well-formed `Manifest`.
276
344
  *
277
345
  * @remarks
278
346
  * Partition presence only — disjointness is `validateBrief`'s semantic pass.
347
+ *
348
+ * @param value - The value to inspect.
349
+ * @returns True if `value` is a well-formed `Manifest`; false otherwise.
279
350
  */
280
351
  var isManifest = (0, _orkestrel_contract.recordOf)({
281
352
  read: (0, _orkestrel_contract.arrayOf)(isReference),
@@ -283,50 +354,83 @@ var isManifest = (0, _orkestrel_contract.recordOf)({
283
354
  locked: (0, _orkestrel_contract.arrayOf)(isReference),
284
355
  forbidden: (0, _orkestrel_contract.arrayOf)(isReference)
285
356
  });
286
- /** `true` when the value is a well-formed `Outcome` — `rank` a positive integer. */
357
+ /**
358
+ * Checks whether the value is a well-formed `Outcome` — `rank` a positive integer.
359
+ *
360
+ * @param value - The value to inspect.
361
+ * @returns True if `value` is a well-formed `Outcome`; false otherwise.
362
+ */
287
363
  var isOutcome = (0, _orkestrel_contract.recordOf)({
288
364
  rank: (0, _orkestrel_contract.andOf)(_orkestrel_contract.isInteger, (0, _orkestrel_contract.boundsOf)(1)),
289
365
  text: isLine,
290
366
  required: _orkestrel_contract.isBoolean
291
367
  });
292
- /** `true` when the value is a well-formed `Given` — `value` may be empty but stays one line. */
368
+ /**
369
+ * Checks whether the value is a well-formed `Given` — its `value` may be empty but stays one line.
370
+ *
371
+ * @param value - The value to inspect.
372
+ * @returns True if `value` is a well-formed `Given`; false otherwise.
373
+ */
293
374
  var isGiven = (0, _orkestrel_contract.recordOf)({
294
375
  category: isLine,
295
376
  name: isLine,
296
377
  value: isText
297
378
  });
298
379
  /**
299
- * `true` when the value is a well-formed `Example`.
380
+ * Checks whether the value is a well-formed `Example`.
300
381
  *
301
382
  * @remarks
302
383
  * An exemplar's two sides are the ONLY members a brief lets span lines, because they
303
384
  * carry code. `briefToMarkdown` fences them rather than rendering them as a row.
385
+ *
386
+ * @param value - The value to inspect.
387
+ * @returns True if `value` is a well-formed `Example`; false otherwise.
304
388
  */
305
389
  var isExample = (0, _orkestrel_contract.recordOf)({
306
390
  input: _orkestrel_contract.isNonEmptyString,
307
391
  output: _orkestrel_contract.isNonEmptyString,
308
392
  note: isLine
309
393
  }, ["note"]);
310
- /** `true` when the value is a well-formed `Citation` — all three members single-line. */
394
+ /**
395
+ * Checks whether the value is a well-formed `Citation` — every member single-line.
396
+ *
397
+ * @param value - The value to inspect.
398
+ * @returns True if `value` is a well-formed `Citation`; false otherwise.
399
+ */
311
400
  var isCitation = (0, _orkestrel_contract.recordOf)({
312
401
  name: isLine,
313
402
  url: isLine,
314
403
  note: isLine
315
404
  });
316
- /** `true` when the value is a well-formed `Gap`. */
405
+ /**
406
+ * Checks whether the value is a well-formed `Gap`.
407
+ *
408
+ * @param value - The value to inspect.
409
+ * @returns True if `value` is a well-formed `Gap`; false otherwise.
410
+ */
317
411
  var isGap = (0, _orkestrel_contract.recordOf)({
318
412
  field: isLine,
319
413
  question: isLine,
320
414
  blocking: _orkestrel_contract.isBoolean,
321
415
  candidates: (0, _orkestrel_contract.arrayOf)(isLine)
322
416
  }, ["candidates"]);
323
- /** `true` when the value is a well-formed `Risk` — `severity` on the closed vocabulary. */
417
+ /**
418
+ * Checks whether the value is a well-formed `Risk` — `severity` on the closed vocabulary.
419
+ *
420
+ * @param value - The value to inspect.
421
+ * @returns True if `value` is a well-formed `Risk`; false otherwise.
422
+ */
324
423
  var isRisk = (0, _orkestrel_contract.recordOf)({
325
424
  severity: isRiskSeverity,
326
425
  text: isLine,
327
426
  mitigation: isLine
328
427
  });
329
- /** `true` when the value is a well-formed `Output` — `format` on the closed vocabulary. */
428
+ /**
429
+ * Checks whether the value is a well-formed `Output` — `format` on the closed vocabulary.
430
+ *
431
+ * @param value - The value to inspect.
432
+ * @returns True if `value` is a well-formed `Output`; false otherwise.
433
+ */
330
434
  var isOutput = (0, _orkestrel_contract.recordOf)({
331
435
  format: isOutputFormat,
332
436
  sections: (0, _orkestrel_contract.arrayOf)(isLine),
@@ -337,17 +441,25 @@ var isOutput = (0, _orkestrel_contract.recordOf)({
337
441
  "include",
338
442
  "exclude"
339
443
  ]);
340
- /** `true` when the value is a well-formed `Proof`. */
444
+ /**
445
+ * Checks whether the value is a well-formed `Proof`.
446
+ *
447
+ * @param value - The value to inspect.
448
+ * @returns True if `value` is a well-formed `Proof`; false otherwise.
449
+ */
341
450
  var isProof = (0, _orkestrel_contract.recordOf)({
342
451
  text: isLine,
343
452
  command: isLine
344
453
  });
345
454
  /**
346
- * `true` when the value satisfies the whole exact-record `Brief` contract.
455
+ * Checks whether the value satisfies the whole exact-record `Brief` contract.
347
456
  *
348
457
  * @remarks
349
458
  * Every section must be present; an extra key fails. `trace` and `hash` are the only
350
459
  * optional members, because `pinBrief` rather than the author fills them.
460
+ *
461
+ * @param value - The value to inspect.
462
+ * @returns True if `value` satisfies the whole exact-record `Brief` contract; false otherwise.
351
463
  */
352
464
  var isBrief = (0, _orkestrel_contract.recordOf)({
353
465
  task: isTask,
@@ -448,7 +560,7 @@ function captureValue(source, members) {
448
560
  return target;
449
561
  }
450
562
  /**
451
- * Return a deeply owned, deeply frozen copy of a brief, refusing anything off-contract.
563
+ * Returns a deeply owned, deeply frozen copy of a brief, refusing anything off-contract.
452
564
  *
453
565
  * @remarks
454
566
  * The one reading boundary this package has, used by the pin, the registry, and every
@@ -472,10 +584,10 @@ function captureValue(source, members) {
472
584
  *
473
585
  * @example
474
586
  * ```ts
475
- * import { brief, outcome, snapshotBrief, task } from '@orkestrel/brief'
587
+ * import { buildBrief, buildOutcome, buildTask, snapshotBrief } from '@orkestrel/brief'
476
588
  *
477
- * const outcomes = [outcome(1, 'shipped')]
478
- * const owned = snapshotBrief(brief(task('plan', 'ops', 'Plan the release.'), { outcomes }))
589
+ * const outcomes = [buildOutcome(1, 'shipped')]
590
+ * const owned = snapshotBrief(buildBrief(buildTask('plan', 'ops', 'Plan the release.'), { outcomes }))
479
591
  * owned.outcomes === outcomes // false — the alias is broken
480
592
  * Object.isFrozen(owned.outcomes) // true
481
593
  * ```
@@ -488,7 +600,7 @@ function snapshotBrief(source) {
488
600
  //#endregion
489
601
  //#region src/core/helpers.ts
490
602
  /**
491
- * Build a `Task`.
603
+ * Assembles a `Task` from an operation, a domain, and a statement.
492
604
  *
493
605
  * @param operation - What the brief asks for, from the closed operation vocabulary.
494
606
  * @param domain - The subject matter, from the closed domain vocabulary.
@@ -497,12 +609,12 @@ function snapshotBrief(source) {
497
609
  *
498
610
  * @example
499
611
  * ```ts
500
- * import { task } from '@orkestrel/brief'
612
+ * import { buildTask } from '@orkestrel/brief'
501
613
  *
502
- * task('refactor', 'code', 'Refactor useForm to native browser form APIs.')
614
+ * buildTask('refactor', 'code', 'Refactor useForm to native browser form APIs.')
503
615
  * ```
504
616
  */
505
- function task(operation, domain, statement) {
617
+ function buildTask(operation, domain, statement) {
506
618
  return {
507
619
  operation,
508
620
  domain,
@@ -510,7 +622,7 @@ function task(operation, domain, statement) {
510
622
  };
511
623
  }
512
624
  /**
513
- * Build a `Reference`.
625
+ * Assembles a `Reference` from a path and the note that justifies listing it.
514
626
  *
515
627
  * @param path - The referenced path or glob.
516
628
  * @param note - Why the path is listed.
@@ -518,31 +630,31 @@ function task(operation, domain, statement) {
518
630
  *
519
631
  * @example
520
632
  * ```ts
521
- * import { reference } from '@orkestrel/brief'
633
+ * import { buildReference } from '@orkestrel/brief'
522
634
  *
523
- * reference('AGENTS.md', 'project law') // { path: 'AGENTS.md', note: 'project law' }
635
+ * buildReference('AGENTS.md', 'project law') // { path: 'AGENTS.md', note: 'project law' }
524
636
  * ```
525
637
  */
526
- function reference(path, note) {
638
+ function buildReference(path, note) {
527
639
  return {
528
640
  path,
529
641
  note
530
642
  };
531
643
  }
532
644
  /**
533
- * Build a `Manifest`, defaulting every absent partition to an empty list.
645
+ * Assembles a `Manifest`, defaulting every absent partition to an empty list.
534
646
  *
535
647
  * @param partitions - The partitions to fill; a partial literal is enough.
536
- * @returns A fresh `Manifest` with all four partitions present.
648
+ * @returns A fresh `Manifest` with every partition present.
537
649
  *
538
650
  * @example
539
651
  * ```ts
540
- * import { manifest, reference } from '@orkestrel/brief'
652
+ * import { buildManifest, buildReference } from '@orkestrel/brief'
541
653
  *
542
- * manifest({ edit: [reference('src/core/helpers.ts', 'implementation')] })
654
+ * buildManifest({ edit: [buildReference('src/core/helpers.ts', 'implementation')] })
543
655
  * ```
544
656
  */
545
- function manifest(partitions) {
657
+ function buildManifest(partitions) {
546
658
  return {
547
659
  read: partitions?.read ?? [],
548
660
  edit: partitions?.edit ?? [],
@@ -551,22 +663,23 @@ function manifest(partitions) {
551
663
  };
552
664
  }
553
665
  /**
554
- * Build an `Outcome`.
666
+ * Assembles an `Outcome` from a rank and its result text.
555
667
  *
556
668
  * @param rank - The one-based rank; lower ranks matter more.
557
669
  * @param text - The result, never a step.
558
- * @param required - Whether the outcome gates "done"; defaults to `true`.
670
+ * @param required - If `true`, the outcome gates "done"; if `false`, it is desirable but not
671
+ * blocking. Default: `true`.
559
672
  * @returns A fresh `Outcome`.
560
673
  *
561
674
  * @example
562
675
  * ```ts
563
- * import { outcome } from '@orkestrel/brief'
676
+ * import { buildOutcome } from '@orkestrel/brief'
564
677
  *
565
- * outcome(1, 'useForm uses native FormData with no behavior change') // required: true
566
- * outcome(2, 'the diff stays under 200 lines', false)
678
+ * buildOutcome(1, 'useForm uses native FormData with no behavior change') // required: true
679
+ * buildOutcome(2, 'the diff stays under 200 lines', false)
567
680
  * ```
568
681
  */
569
- function outcome(rank, text, required = true) {
682
+ function buildOutcome(rank, text, required = true) {
570
683
  return {
571
684
  rank,
572
685
  text,
@@ -574,7 +687,7 @@ function outcome(rank, text, required = true) {
574
687
  };
575
688
  }
576
689
  /**
577
- * Build a `Given`.
690
+ * Assembles a `Given` from a category, a name, and a value.
578
691
  *
579
692
  * @param category - The kind of fact — a convention, a version, a constraint.
580
693
  * @param name - The fact's name.
@@ -583,12 +696,12 @@ function outcome(rank, text, required = true) {
583
696
  *
584
697
  * @example
585
698
  * ```ts
586
- * import { given } from '@orkestrel/brief'
699
+ * import { buildGiven } from '@orkestrel/brief'
587
700
  *
588
- * given('convention', 'indentation', 'tabs')
701
+ * buildGiven('convention', 'indentation', 'tabs')
589
702
  * ```
590
703
  */
591
- function given(category, name, value) {
704
+ function buildGiven(category, name, value) {
592
705
  return {
593
706
  category,
594
707
  name,
@@ -596,32 +709,32 @@ function given(category, name, value) {
596
709
  };
597
710
  }
598
711
  /**
599
- * Build an `Example`.
712
+ * Assembles an `Example` from an exemplar input and its expected output.
600
713
  *
601
714
  * @param input - The exemplar input.
602
- * @param result - The expected output for that input.
715
+ * @param output - The expected output for that input.
603
716
  * @param note - Optional detail; the key is OMITTED when absent.
604
717
  * @returns A fresh `Example`.
605
718
  *
606
719
  * @example
607
720
  * ```ts
608
- * import { example } from '@orkestrel/brief'
721
+ * import { buildExample } from '@orkestrel/brief'
609
722
  *
610
- * example('<input required>', 'validity read from el.validity')
723
+ * buildExample('<input required>', 'validity read from el.validity')
611
724
  * ```
612
725
  */
613
- function example(input, result, note) {
726
+ function buildExample(input, output, note) {
614
727
  return note === void 0 ? {
615
728
  input,
616
- output: result
729
+ output
617
730
  } : {
618
731
  input,
619
- output: result,
732
+ output,
620
733
  note
621
734
  };
622
735
  }
623
736
  /**
624
- * Build a `Citation`.
737
+ * Assembles a `Citation` from a name, a URL, and the note that justifies citing it.
625
738
  *
626
739
  * @param name - The source's display name.
627
740
  * @param url - Where the source lives.
@@ -630,16 +743,16 @@ function example(input, result, note) {
630
743
  *
631
744
  * @example
632
745
  * ```ts
633
- * import { citation } from '@orkestrel/brief'
746
+ * import { buildCitation } from '@orkestrel/brief'
634
747
  *
635
- * citation(
748
+ * buildCitation(
636
749
  * 'MDN Constraint Validation',
637
750
  * 'https://developer.mozilla.org/',
638
751
  * 'the native validity behavior being adopted',
639
752
  * )
640
753
  * ```
641
754
  */
642
- function citation(name, url, note) {
755
+ function buildCitation(name, url, note) {
643
756
  return {
644
757
  name,
645
758
  url,
@@ -647,23 +760,23 @@ function citation(name, url, note) {
647
760
  };
648
761
  }
649
762
  /**
650
- * Build a `Gap`.
763
+ * Assembles a `Gap` from the section it belongs to and the question that would close it.
651
764
  *
652
765
  * @param field - The brief section the unknown belongs to.
653
766
  * @param question - The question that would close it.
654
- * @param overrides - Optional `blocking` (defaults `false`) and `candidates`; an absent
655
- * `candidates` key is OMITTED entirely.
767
+ * @param overrides - Optional `blocking` and `candidates`; an absent `candidates` key is
768
+ * OMITTED entirely. Default: `blocking: false`.
656
769
  * @returns A fresh `Gap`.
657
770
  *
658
771
  * @example
659
772
  * ```ts
660
- * import { gap } from '@orkestrel/brief'
773
+ * import { buildGap } from '@orkestrel/brief'
661
774
  *
662
- * gap('rules', 'Should validation message wording change?') // blocking: false
663
- * gap('output', 'Diff or full files?', { blocking: true, candidates: ['diff', 'code'] })
775
+ * buildGap('rules', 'Does validation message wording need to change?') // blocking: false
776
+ * buildGap('output', 'Diff or full files?', { blocking: true, candidates: ['diff', 'code'] })
664
777
  * ```
665
778
  */
666
- function gap(field, question, overrides) {
779
+ function buildGap(field, question, overrides) {
667
780
  const blocking = overrides?.blocking ?? false;
668
781
  return overrides?.candidates === void 0 ? {
669
782
  field,
@@ -677,7 +790,7 @@ function gap(field, question, overrides) {
677
790
  };
678
791
  }
679
792
  /**
680
- * Build a `Risk`.
793
+ * Assembles a `Risk` from a severity, what could go wrong, and the mitigation that answers it.
681
794
  *
682
795
  * @param severity - The closed severity.
683
796
  * @param text - What could go wrong.
@@ -686,12 +799,12 @@ function gap(field, question, overrides) {
686
799
  *
687
800
  * @example
688
801
  * ```ts
689
- * import { risk } from '@orkestrel/brief'
802
+ * import { buildRisk } from '@orkestrel/brief'
690
803
  *
691
- * risk('medium', 'native validation differs subtly', 'assert message and state in tests')
804
+ * buildRisk('medium', 'native validation differs subtly', 'assert message and state in tests')
692
805
  * ```
693
806
  */
694
- function risk(severity, text, mitigation) {
807
+ function buildRisk(severity, text, mitigation) {
695
808
  return {
696
809
  severity,
697
810
  text,
@@ -699,7 +812,7 @@ function risk(severity, text, mitigation) {
699
812
  };
700
813
  }
701
814
  /**
702
- * Build an `Output`.
815
+ * Assembles an `Output` from a format plus its optional refinements.
703
816
  *
704
817
  * @param format - The closed deliverable format.
705
818
  * @param overrides - Optional `sections` / `include` / `exclude`; absent keys are OMITTED.
@@ -707,13 +820,13 @@ function risk(severity, text, mitigation) {
707
820
  *
708
821
  * @example
709
822
  * ```ts
710
- * import { output } from '@orkestrel/brief'
823
+ * import { buildOutput } from '@orkestrel/brief'
711
824
  *
712
- * output('markdown') // { format: 'markdown' }
713
- * output('diff', { include: ['updated useForm.ts'] })
825
+ * buildOutput('markdown') // { format: 'markdown' }
826
+ * buildOutput('diff', { include: ['updated useForm.ts'] })
714
827
  * ```
715
828
  */
716
- function output(format, overrides) {
829
+ function buildOutput(format, overrides) {
717
830
  return {
718
831
  format,
719
832
  ...overrides?.sections === void 0 ? {} : { sections: overrides.sections },
@@ -722,7 +835,7 @@ function output(format, overrides) {
722
835
  };
723
836
  }
724
837
  /**
725
- * Build a `Proof`.
838
+ * Assembles a `Proof` from what the check settles and the command that settles it.
726
839
  *
727
840
  * @param text - What the check settles.
728
841
  * @param command - The command whose exit signal settles it.
@@ -730,41 +843,41 @@ function output(format, overrides) {
730
843
  *
731
844
  * @example
732
845
  * ```ts
733
- * import { proof } from '@orkestrel/brief'
846
+ * import { buildProof } from '@orkestrel/brief'
734
847
  *
735
- * proof('type-check and lint pass', 'npm run check')
848
+ * buildProof('type-check and lint pass', 'npm run check')
736
849
  * ```
737
850
  */
738
- function proof(text, command) {
851
+ function buildProof(text, command) {
739
852
  return {
740
853
  text,
741
854
  command
742
855
  };
743
856
  }
744
857
  /**
745
- * Build a `Brief` from a `Task` plus section overrides.
858
+ * Assembles a `Brief` from a `Task` plus section overrides.
746
859
  *
747
860
  * @param subject - The task the brief is about.
748
- * @param overrides - Any sections to fill; every absent collection defaults to `[]`,
749
- * `output` defaults to `output('markdown')`, and `trace` / `hash` stay OMITTED so
750
- * `pinBrief` can fill them.
861
+ * @param overrides - Any sections to fill; `trace` / `hash` stay OMITTED so `pinBrief` can
862
+ * fill them. Default: `[]` for every absent collection and `buildOutput('markdown')` for
863
+ * `output`.
751
864
  * @returns A fresh, unpinned `Brief`.
752
865
  *
753
866
  * @example
754
867
  * ```ts
755
- * import { brief, outcome, proof, task } from '@orkestrel/brief'
868
+ * import { buildBrief, buildOutcome, buildProof, buildTask } from '@orkestrel/brief'
756
869
  *
757
- * brief(task('audit', 'code', 'Audit the barrel for undocumented exports.'), {
758
- * outcomes: [outcome(1, 'every export appears in the guide')],
759
- * proofs: [proof('parity passes', 'npm run test:guides')],
870
+ * buildBrief(buildTask('audit', 'code', 'Audit the barrel for undocumented exports.'), {
871
+ * outcomes: [buildOutcome(1, 'every export appears in the guide')],
872
+ * proofs: [buildProof('parity passes', 'npm run test:guides')],
760
873
  * })
761
874
  * ```
762
875
  */
763
- function brief(subject, overrides) {
876
+ function buildBrief(subject, overrides) {
764
877
  return {
765
878
  task: subject,
766
879
  authority: overrides?.authority ?? [],
767
- manifest: overrides?.manifest ?? manifest(),
880
+ manifest: overrides?.manifest ?? buildManifest(),
768
881
  outcomes: overrides?.outcomes ?? [],
769
882
  rules: overrides?.rules ?? [],
770
883
  invariants: overrides?.invariants ?? [],
@@ -774,17 +887,17 @@ function brief(subject, overrides) {
774
887
  citations: overrides?.citations ?? [],
775
888
  gaps: overrides?.gaps ?? [],
776
889
  risks: overrides?.risks ?? [],
777
- output: overrides?.output ?? output("markdown"),
890
+ output: overrides?.output ?? buildOutput("markdown"),
778
891
  proofs: overrides?.proofs ?? []
779
892
  };
780
893
  }
781
894
  /**
782
- * Build the fail-closed readiness gate as a reasons `LogicalDefinition`.
895
+ * Assembles the fail-closed readiness gate as a reasons `LogicalDefinition`.
783
896
  *
784
897
  * @remarks
785
- * Six readiness rules each derive one named fact from `briefToSubject`'s measures, and a
786
- * final `ready` rule conjoins all six. Forward chaining reports the LAST rule's
787
- * conclusion, so `LogicalResult.conclusion` is exactly `ready`.
898
+ * Each readiness rule derives one named fact from `briefToSubject`'s measures, and a final
899
+ * `ready` rule conjoins them all. Forward chaining reports the LAST rule's conclusion, so
900
+ * `LogicalResult.conclusion` is exactly `ready`.
788
901
  *
789
902
  * The gate takes NO parameters, and that is deliberate rather than unfinished. The
790
903
  * reasoner overlays every derived fact into one flat namespace, so a caller rule named
@@ -798,50 +911,50 @@ function brief(subject, overrides) {
798
911
  *
799
912
  * @example
800
913
  * ```ts
801
- * import { briefToSubject, gateDefinition } from '@orkestrel/brief'
914
+ * import { briefToSubject, buildGateDefinition } from '@orkestrel/brief'
802
915
  * import { createLogicalReasoner, createReason } from '@orkestrel/reason'
803
916
  *
804
917
  * const reason = createReason({ reasoners: [createLogicalReasoner()] })
805
- * const verdict = reason.reason(briefToSubject(pinned), gateDefinition())
918
+ * const verdict = reason.reason(briefToSubject(pinned), buildGateDefinition())
806
919
  * reason.destroy()
807
920
  * ```
808
921
  */
809
- function gateDefinition() {
922
+ function buildGateDefinition() {
810
923
  const readiness = [
811
- (0, _orkestrel_reason.rule)("specified", [(0, _orkestrel_reason.atom)("blocking", "equals", 0)], (0, _orkestrel_reason.atom)("specified", "equals", true)),
812
- (0, _orkestrel_reason.rule)("aimed", [(0, _orkestrel_reason.compound)("and", [(0, _orkestrel_reason.atom)("outcomes", "above", 0), (0, _orkestrel_reason.atom)("required", "above", 0)])], (0, _orkestrel_reason.atom)("aimed", "equals", true)),
813
- (0, _orkestrel_reason.rule)("proven", [(0, _orkestrel_reason.atom)("proofs", "above", 0)], (0, _orkestrel_reason.atom)("proven", "equals", true)),
814
- (0, _orkestrel_reason.rule)("disjoint", [(0, _orkestrel_reason.atom)("overlaps", "equals", 0)], (0, _orkestrel_reason.atom)("disjoint", "equals", true)),
815
- (0, _orkestrel_reason.rule)("granted", [(0, _orkestrel_reason.atom)("ungranted", "equals", 0)], (0, _orkestrel_reason.atom)("granted", "equals", true)),
816
- (0, _orkestrel_reason.rule)("single", [(0, _orkestrel_reason.atom)("sentences", "equals", 1)], (0, _orkestrel_reason.atom)("single", "equals", true))
924
+ (0, _orkestrel_reason.createRule)("specified", [(0, _orkestrel_reason.createAtom)("blocking", "equals", 0)], (0, _orkestrel_reason.createAtom)("specified", "equals", true)),
925
+ (0, _orkestrel_reason.createRule)("aimed", [(0, _orkestrel_reason.createCompound)("and", [(0, _orkestrel_reason.createAtom)("outcomes", "above", 0), (0, _orkestrel_reason.createAtom)("required", "above", 0)])], (0, _orkestrel_reason.createAtom)("aimed", "equals", true)),
926
+ (0, _orkestrel_reason.createRule)("proven", [(0, _orkestrel_reason.createAtom)("proofs", "above", 0)], (0, _orkestrel_reason.createAtom)("proven", "equals", true)),
927
+ (0, _orkestrel_reason.createRule)("disjoint", [(0, _orkestrel_reason.createAtom)("overlaps", "equals", 0)], (0, _orkestrel_reason.createAtom)("disjoint", "equals", true)),
928
+ (0, _orkestrel_reason.createRule)("granted", [(0, _orkestrel_reason.createAtom)("ungranted", "equals", 0)], (0, _orkestrel_reason.createAtom)("granted", "equals", true)),
929
+ (0, _orkestrel_reason.createRule)("single", [(0, _orkestrel_reason.createAtom)("sentences", "equals", 1)], (0, _orkestrel_reason.createAtom)("single", "equals", true))
817
930
  ];
818
- return (0, _orkestrel_reason.logicalDefinition)(GATE_ID, "Brief readiness", [...readiness, (0, _orkestrel_reason.rule)("ready", [(0, _orkestrel_reason.compound)("and", readiness.map((entry) => (0, _orkestrel_reason.atom)(entry.id, "equals", true)))], (0, _orkestrel_reason.atom)("ready", "equals", true))]);
931
+ return (0, _orkestrel_reason.createLogicalDefinition)(GATE_ID, "Brief readiness", [...readiness, (0, _orkestrel_reason.createRule)("ready", [(0, _orkestrel_reason.createCompound)("and", readiness.map((entry) => (0, _orkestrel_reason.createAtom)(entry.id, "equals", true)))], (0, _orkestrel_reason.createAtom)("ready", "equals", true))]);
819
932
  }
820
933
  /**
821
- * The readiness rules a brief fails, computed directly from its own measures.
934
+ * Lists the readiness rules a brief fails, computed directly from its own measures.
822
935
  *
823
936
  * @remarks
824
- * The gate's decision, in code. `gateDefinition()` states the same six rules as data for a
937
+ * The gate's decision, in code. `buildGateDefinition()` states the same rules as data for a
825
938
  * reasoner to narrate, and a narration is not a decision: `BriefCompilerOptions.reason` lets a
826
939
  * caller supply the engine, and an engine that answers "met" to everything would otherwise
827
940
  * emit a brief with no proofs. `compile` refuses on THIS and keeps the verdict for its
828
941
  * trace, so a supplied engine can add detail and never remove a refusal.
829
942
  *
830
- * The two must agree. `tests/src/core/helpers.test.ts` drives both over one value set, which
831
- * is what stops the data and the code from drifting apart.
943
+ * The data and the code must agree. `tests/src/core/helpers.test.ts` drives both over one
944
+ * value set, which is what stops them from drifting apart.
832
945
  *
833
946
  * @param source - The brief to measure.
834
947
  * @returns The unmet rule ids, in gate order; empty when the brief is ready.
835
948
  *
836
949
  * @example
837
950
  * ```ts
838
- * import { brief, findUnmetRules, outcome, proof, task } from '@orkestrel/brief'
951
+ * import { buildBrief, buildOutcome, buildProof, buildTask, findUnmetRules } from '@orkestrel/brief'
839
952
  *
840
- * findUnmetRules(brief(task('plan', 'ops', 'Plan the release.'))) // ['aimed', 'proven']
953
+ * findUnmetRules(buildBrief(buildTask('plan', 'ops', 'Plan the release.'))) // ['aimed', 'proven']
841
954
  * findUnmetRules(
842
- * brief(task('plan', 'ops', 'Plan the release.'), {
843
- * outcomes: [outcome(1, 'shipped')],
844
- * proofs: [proof('x', 'npm test')],
955
+ * buildBrief(buildTask('plan', 'ops', 'Plan the release.'), {
956
+ * outcomes: [buildOutcome(1, 'shipped')],
957
+ * proofs: [buildProof('x', 'npm test')],
845
958
  * }),
846
959
  * ) // []
847
960
  * ```
@@ -857,7 +970,7 @@ function findUnmetRules(source) {
857
970
  return unready;
858
971
  }
859
972
  /**
860
- * Count the sentences a statement holds.
973
+ * Counts the sentences a statement holds.
861
974
  *
862
975
  * @remarks
863
976
  * A terminator run (`.`, `!`, `?`) followed by whitespace or the end of the text closes one
@@ -895,17 +1008,17 @@ function countSentences(statement) {
895
1008
  return /[.!?]$/u.test(text) ? matches.length : matches.length + 1;
896
1009
  }
897
1010
  /**
898
- * The gaps that block emission.
1011
+ * Lists the gaps that block emission.
899
1012
  *
900
1013
  * @param source - The brief to inspect.
901
1014
  * @returns Every gap carrying `blocking: true`, in declaration order.
902
1015
  *
903
1016
  * @example
904
1017
  * ```ts
905
- * import { brief, findBlockingGaps, gap, task } from '@orkestrel/brief'
1018
+ * import { buildBrief, buildGap, buildTask, findBlockingGaps } from '@orkestrel/brief'
906
1019
  *
907
- * const draft = brief(task('plan', 'ops', 'Plan the release.'), {
908
- * gaps: [gap('output', 'Diff or files?', { blocking: true })],
1020
+ * const draft = buildBrief(buildTask('plan', 'ops', 'Plan the release.'), {
1021
+ * gaps: [buildGap('output', 'Diff or files?', { blocking: true })],
909
1022
  * })
910
1023
  * findBlockingGaps(draft).length // 1
911
1024
  * ```
@@ -914,18 +1027,18 @@ function findBlockingGaps(source) {
914
1027
  return source.gaps.filter((entry) => entry.blocking);
915
1028
  }
916
1029
  /**
917
- * The authority paths the manifest never grants access to.
1030
+ * Lists the authority paths the manifest never grants access to.
918
1031
  *
919
1032
  * @remarks
920
1033
  * An authority the executor cannot open is an instruction it cannot follow, so every ranked
921
- * path must appear in `read`, `edit`, or `locked`. Those three are the grants: `locked` is a
1034
+ * path must appear in `read`, `edit`, or `locked`. Those are the grants: `locked` is a
922
1035
  * grant, because read-only is exactly what obeying a file requires.
923
1036
  *
924
- * This subsumes the narrower question of an authority sitting in `forbidden`. The four
925
- * partitions are disjoint — `findManifestOverlaps` and the `disjoint` rule enforce it — so a
926
- * forbidden path is in none of the three grants and is reported here. An authority named in
927
- * NO partition at all is reported for the same reason, and that is the case a forbidden-only
928
- * check misses entirely: the brief simply never says the executor may open what it must obey.
1037
+ * This subsumes the narrower question of an authority sitting in `forbidden`. The partitions
1038
+ * are disjoint — `findManifestOverlaps` and the `disjoint` rule enforce it — so a forbidden
1039
+ * path is in none of the grants and is reported here. An authority named in NO partition at
1040
+ * all is reported for the same reason, and that is the case a forbidden-only check misses
1041
+ * entirely: the brief simply never says the executor may open what it must obey.
929
1042
  *
930
1043
  * Paths are compared as EXACT strings, matching `findManifestOverlaps`. A glob is never
931
1044
  * expanded, so `read: 'guides/**'` does not grant `authority: 'guides/brief.md'`. State a
@@ -936,11 +1049,17 @@ function findBlockingGaps(source) {
936
1049
  *
937
1050
  * @example
938
1051
  * ```ts
939
- * import { brief, findUngrantedAuthority, manifest, reference, task } from '@orkestrel/brief'
940
- *
941
- * const draft = brief(task('debug', 'code', 'Fix the leak.'), {
942
- * authority: [reference('AGENTS.md', 'project law')],
943
- * manifest: manifest(),
1052
+ * import {
1053
+ * buildBrief,
1054
+ * buildManifest,
1055
+ * buildReference,
1056
+ * buildTask,
1057
+ * findUngrantedAuthority,
1058
+ * } from '@orkestrel/brief'
1059
+ *
1060
+ * const draft = buildBrief(buildTask('debug', 'code', 'Fix the leak.'), {
1061
+ * authority: [buildReference('AGENTS.md', 'project law')],
1062
+ * manifest: buildManifest(),
944
1063
  * })
945
1064
  * findUngrantedAuthority(draft) // ['AGENTS.md'] — ranked, but no partition opens it
946
1065
  * ```
@@ -956,10 +1075,10 @@ function findUngrantedAuthority(source) {
956
1075
  return ungranted;
957
1076
  }
958
1077
  /**
959
- * The paths appearing in more than one manifest partition.
1078
+ * Lists the paths appearing in more than one manifest partition.
960
1079
  *
961
1080
  * @remarks
962
- * Duplicates WITHIN one partition are not an overlap; the four partitions must be
1081
+ * Duplicates WITHIN one partition are not an overlap; the partitions must be
963
1082
  * mutually disjoint, which is what `validateBrief` errors on.
964
1083
  *
965
1084
  * Paths are compared as EXACT strings. A glob is never expanded, so `edit: 'app/file.ts'`
@@ -971,12 +1090,18 @@ function findUngrantedAuthority(source) {
971
1090
  *
972
1091
  * @example
973
1092
  * ```ts
974
- * import { brief, findManifestOverlaps, manifest, reference, task } from '@orkestrel/brief'
975
- *
976
- * const draft = brief(task('debug', 'code', 'Fix the leak.'), {
977
- * manifest: manifest({
978
- * edit: [reference('src/core/BriefCompiler.ts', 'the leaking pipeline')],
979
- * locked: [reference('src/core/BriefCompiler.ts', 'the published contract')],
1093
+ * import {
1094
+ * buildBrief,
1095
+ * buildManifest,
1096
+ * buildReference,
1097
+ * buildTask,
1098
+ * findManifestOverlaps,
1099
+ * } from '@orkestrel/brief'
1100
+ *
1101
+ * const draft = buildBrief(buildTask('debug', 'code', 'Fix the leak.'), {
1102
+ * manifest: buildManifest({
1103
+ * edit: [buildReference('src/core/BriefCompiler.ts', 'the leaking pipeline')],
1104
+ * locked: [buildReference('src/core/BriefCompiler.ts', 'the published contract')],
980
1105
  * }),
981
1106
  * })
982
1107
  * findManifestOverlaps(draft) // ['src/core/BriefCompiler.ts']
@@ -996,7 +1121,7 @@ function findManifestOverlaps(source) {
996
1121
  return overlaps;
997
1122
  }
998
1123
  /**
999
- * The open gaps with no assumption to stand on.
1124
+ * Lists the open gaps with no assumption to stand on.
1000
1125
  *
1001
1126
  * @remarks
1002
1127
  * The discipline is exactly one recorded assumption per open gap, so the open gaps past
@@ -1008,10 +1133,10 @@ function findManifestOverlaps(source) {
1008
1133
  *
1009
1134
  * @example
1010
1135
  * ```ts
1011
- * import { brief, findUnpairedGaps, gap, task } from '@orkestrel/brief'
1136
+ * import { buildBrief, buildGap, buildTask, findUnpairedGaps } from '@orkestrel/brief'
1012
1137
  *
1013
- * const draft = brief(task('plan', 'ops', 'Plan the release.'), {
1014
- * gaps: [gap('rules', 'Keep the wording?'), gap('output', 'Diff or files?')],
1138
+ * const draft = buildBrief(buildTask('plan', 'ops', 'Plan the release.'), {
1139
+ * gaps: [buildGap('rules', 'Keep the wording?'), buildGap('output', 'Diff or files?')],
1015
1140
  * assumptions: ['Wording is preserved.'],
1016
1141
  * })
1017
1142
  * findUnpairedGaps(draft).length // 1
@@ -1021,16 +1146,16 @@ function findUnpairedGaps(source) {
1021
1146
  return source.gaps.filter((entry) => !entry.blocking).slice(source.assumptions.length);
1022
1147
  }
1023
1148
  /**
1024
- * Project a brief into the reasons `Subject` of readiness measures the gate reads.
1149
+ * Projects a brief into the reasons `Subject` of readiness measures the gate reads.
1025
1150
  *
1026
1151
  * @param source - The brief to measure.
1027
- * @returns A flat record of counts plus the task's two vocabulary values.
1152
+ * @returns A flat record of counts plus the task's vocabulary values.
1028
1153
  *
1029
1154
  * @example
1030
1155
  * ```ts
1031
- * import { brief, briefToSubject, proof, task } from '@orkestrel/brief'
1156
+ * import { briefToSubject, buildBrief, buildProof, buildTask } from '@orkestrel/brief'
1032
1157
  *
1033
- * briefToSubject(brief(task('test', 'code', 'Cover the gate.'), { proofs: [proof('x', 'y')] }))
1158
+ * briefToSubject(buildBrief(buildTask('test', 'code', 'Cover the gate.'), { proofs: [buildProof('x', 'y')] }))
1034
1159
  * // { operation: 'test', domain: 'code', sentences: 1, proofs: 1, … }
1035
1160
  * ```
1036
1161
  */
@@ -1057,7 +1182,7 @@ function briefToSubject(source) {
1057
1182
  };
1058
1183
  }
1059
1184
  /**
1060
- * The semantic pass over an already-shape-valid brief.
1185
+ * Runs the semantic pass over an already-shape-valid brief.
1061
1186
  *
1062
1187
  * @remarks
1063
1188
  * ERRORS are the structural violations no assumption can paper over: a manifest
@@ -1071,11 +1196,11 @@ function briefToSubject(source) {
1071
1196
  *
1072
1197
  * @example
1073
1198
  * ```ts
1074
- * import { brief, proof, task, validateBrief } from '@orkestrel/brief'
1199
+ * import { buildBrief, buildProof, buildTask, validateBrief } from '@orkestrel/brief'
1075
1200
  *
1076
- * validateBrief(brief(task('plan', 'ops', 'Plan the release.'))) // valid: false — no proofs
1201
+ * validateBrief(buildBrief(buildTask('plan', 'ops', 'Plan the release.'))) // valid: false — no proofs
1077
1202
  * validateBrief(
1078
- * brief(task('plan', 'ops', 'Plan the release.'), { proofs: [proof('ok', 'npm test')] }),
1203
+ * buildBrief(buildTask('plan', 'ops', 'Plan the release.'), { proofs: [buildProof('ok', 'npm test')] }),
1079
1204
  * ) // valid: true
1080
1205
  * ```
1081
1206
  */
@@ -1103,7 +1228,7 @@ function validateBrief(source) {
1103
1228
  };
1104
1229
  }
1105
1230
  /**
1106
- * The canonical structural digest of a brief's content.
1231
+ * Computes the canonical structural digest of a brief's content.
1107
1232
  *
1108
1233
  * @remarks
1109
1234
  * `trace` and `hash` are stripped before digesting, so the value is the identity of what
@@ -1115,9 +1240,9 @@ function validateBrief(source) {
1115
1240
  *
1116
1241
  * @example
1117
1242
  * ```ts
1118
- * import { brief, briefToHash, pinBrief, task } from '@orkestrel/brief'
1243
+ * import { briefToHash, buildBrief, buildTask, pinBrief } from '@orkestrel/brief'
1119
1244
  *
1120
- * const draft = brief(task('plan', 'ops', 'Plan the release.'))
1245
+ * const draft = buildBrief(buildTask('plan', 'ops', 'Plan the release.'))
1121
1246
  * briefToHash(draft) === briefToHash(pinBrief(draft)) // true — pinning does not move it
1122
1247
  * ```
1123
1248
  */
@@ -1125,7 +1250,7 @@ function briefToHash(source) {
1125
1250
  return (0, _orkestrel_interpret.digestValue)(briefToContent(source));
1126
1251
  }
1127
1252
  /**
1128
- * The canonical text of exactly what a brief's hash describes.
1253
+ * Renders the canonical text of exactly what a brief's hash describes.
1129
1254
  *
1130
1255
  * @remarks
1131
1256
  * `trace` and `hash` are stripped, then interprets `canonicalize` renders the rest in a
@@ -1137,9 +1262,9 @@ function briefToHash(source) {
1137
1262
  *
1138
1263
  * @example
1139
1264
  * ```ts
1140
- * import { brief, briefToContent, pinBrief, task } from '@orkestrel/brief'
1265
+ * import { briefToContent, buildBrief, buildTask, pinBrief } from '@orkestrel/brief'
1141
1266
  *
1142
- * const draft = brief(task('plan', 'ops', 'Plan the release.'))
1267
+ * const draft = buildBrief(buildTask('plan', 'ops', 'Plan the release.'))
1143
1268
  * briefToContent(draft) === briefToContent(pinBrief(draft)) // true — pinning adds no content
1144
1269
  * ```
1145
1270
  */
@@ -1148,7 +1273,7 @@ function briefToContent(source) {
1148
1273
  return (0, _orkestrel_interpret.canonicalize)(content);
1149
1274
  }
1150
1275
  /**
1151
- * Freeze a value and everything reachable from it.
1276
+ * Freezes a value and everything reachable from it.
1152
1277
  *
1153
1278
  * @remarks
1154
1279
  * `Object.freeze` is SHALLOW, so freezing a record leaves every nested array and object
@@ -1162,7 +1287,7 @@ function briefToContent(source) {
1162
1287
  * Reaches PLAIN objects and arrays, which is the whole of a `Brief` — it is JSON-serializable
1163
1288
  * by contract. A `Map`, `Set`, or typed array is frozen as an object and its CONTENTS are left
1164
1289
  * writable, and `Object.isFrozen` reports `true` for it either way. Nothing this package
1165
- * produces contains one; a caller freezing their own value should know the limit.
1290
+ * produces contains one; the limit lands on a caller freezing their own value.
1166
1291
  *
1167
1292
  * @param value - The value to freeze in place; returned for convenience.
1168
1293
  * @returns The same value, now deeply frozen.
@@ -1179,7 +1304,7 @@ function freezeDeep(value) {
1179
1304
  return freezeBranch(value, /* @__PURE__ */ new WeakSet());
1180
1305
  }
1181
1306
  /**
1182
- * Freeze one branch of a value graph, skipping what the visited set already holds.
1307
+ * Freezes one branch of a value graph, skipping what the visited set already holds.
1183
1308
  *
1184
1309
  * @param value - The branch to freeze.
1185
1310
  * @param seen - The objects already frozen on this walk; what makes a cycle terminate.
@@ -1201,7 +1326,7 @@ function freezeBranch(value, seen) {
1201
1326
  return value;
1202
1327
  }
1203
1328
  /**
1204
- * Render a value thrown by a stage into a message.
1329
+ * Renders a value thrown by a stage into a message.
1205
1330
  *
1206
1331
  * @remarks
1207
1332
  * TOTAL: it never throws, for any input. That is load-bearing rather than tidy, because this
@@ -1210,7 +1335,7 @@ function freezeBranch(value, seen) {
1210
1335
  * falsifies the package's central promise that a failing stage yields an incomplete
1211
1336
  * `Briefing` rather than an exception.
1212
1337
  *
1213
- * Three real inputs used to throw: an `Error` subclass whose `message` getter throws, a value
1338
+ * Real inputs used to throw: an `Error` subclass whose `message` getter throws, a value
1214
1339
  * whose string conversion throws, and a null-prototype object, which has no inherited
1215
1340
  * conversion for String() to reach. Each is wrapped, and an unreadable value degrades to its
1216
1341
  * type rather than propagating.
@@ -1234,10 +1359,10 @@ function errorToMessage(error) {
1234
1359
  return `an unreadable ${typeof error} was thrown`;
1235
1360
  }
1236
1361
  /**
1237
- * Narrow unknown data to a `Brief`, throwing when it is off-contract.
1362
+ * Narrows unknown data to a `Brief`, throwing when it is off-contract.
1238
1363
  *
1239
1364
  * @remarks
1240
- * The throwing half of the intake pair: this returns its argument by IDENTITY once the
1365
+ * The throwing half of the intake pair: this returns its argument by IDENTITY after the
1241
1366
  * guard passes, while `parseBrief` returns `undefined` for bad input. It constructs
1242
1367
  * nothing, so it is an assertion rather than a factory. Reserve it for programmer-error
1243
1368
  * contexts where invalidity is a bug.
@@ -1251,24 +1376,24 @@ function errorToMessage(error) {
1251
1376
  * `briefToTrace` read the value they are handed instead, so a caller reaching one of those
1252
1377
  * directly owns that reading. Pass `assertBrief` a value you already own.
1253
1378
  *
1254
- * @param data - The candidate brief data.
1379
+ * @param value - The candidate brief value.
1255
1380
  * @returns The same value, now known to satisfy {@link Brief}.
1256
- * @throws {@link BriefError} `INVALID` when `data` fails `isBrief`.
1381
+ * @throws {@link BriefError} `INVALID` when `value` fails `isBrief`.
1257
1382
  *
1258
1383
  * @example
1259
1384
  * ```ts
1260
- * import { assertBrief, brief, proof, task } from '@orkestrel/brief'
1385
+ * import { assertBrief, buildBrief, buildProof, buildTask } from '@orkestrel/brief'
1261
1386
  *
1262
- * assertBrief(brief(task('plan', 'ops', 'Plan the release.'), { proofs: [proof('x', 'y')] }))
1387
+ * assertBrief(buildBrief(buildTask('plan', 'ops', 'Plan the release.'), { proofs: [buildProof('x', 'y')] }))
1263
1388
  * assertBrief({ task: { operation: 'plan', domain: 'ops', statement: 'x.' } }) // throws INVALID
1264
1389
  * ```
1265
1390
  */
1266
- function assertBrief(data) {
1267
- if (!isBrief(data)) throw new BriefError("INVALID", "Brief failed the exact-record contract", { field: "brief" });
1268
- return data;
1391
+ function assertBrief(value) {
1392
+ if (!isBrief(value)) throw new BriefError("INVALID", "Brief failed the exact-record contract", { field: "brief" });
1393
+ return value;
1269
1394
  }
1270
1395
  /**
1271
- * Return a fresh brief with `trace` and `hash` derived from its own content.
1396
+ * Returns a fresh brief with `trace` and `hash` derived from its own content.
1272
1397
  *
1273
1398
  * @remarks
1274
1399
  * Deterministic: no clock, no randomness, no run-specific data. Any existing `trace` /
@@ -1284,9 +1409,9 @@ function assertBrief(data) {
1284
1409
  *
1285
1410
  * @example
1286
1411
  * ```ts
1287
- * import { brief, pinBrief, task } from '@orkestrel/brief'
1412
+ * import { buildBrief, buildTask, pinBrief } from '@orkestrel/brief'
1288
1413
  *
1289
- * const pinned = pinBrief(brief(task('document', 'writing', 'Write the brief guide.')))
1414
+ * const pinned = pinBrief(buildBrief(buildTask('document', 'writing', 'Write the brief guide.')))
1290
1415
  * pinned.hash // an 8-hex-digit structural digest
1291
1416
  * pinned.trace // 'document/writing · outcomes:0 · gaps:0/0 · proofs:0'
1292
1417
  * ```
@@ -1301,7 +1426,7 @@ function pinBrief(source) {
1301
1426
  });
1302
1427
  }
1303
1428
  /**
1304
- * The one-line census `pinBrief` stamps onto a brief.
1429
+ * Renders the one-line census `pinBrief` stamps onto a brief.
1305
1430
  *
1306
1431
  * @remarks
1307
1432
  * Extracted so it has ONE implementation. `pinBrief` derives it and `BriefManager` re-derives
@@ -1314,9 +1439,9 @@ function pinBrief(source) {
1314
1439
  *
1315
1440
  * @example
1316
1441
  * ```ts
1317
- * import { brief, briefToTrace, task } from '@orkestrel/brief'
1442
+ * import { briefToTrace, buildBrief, buildTask } from '@orkestrel/brief'
1318
1443
  *
1319
- * briefToTrace(brief(task('document', 'writing', 'Write the guide.')))
1444
+ * briefToTrace(buildBrief(buildTask('document', 'writing', 'Write the guide.')))
1320
1445
  * // 'document/writing · outcomes:0 · gaps:0/0 · proofs:0'
1321
1446
  * ```
1322
1447
  */
@@ -1329,7 +1454,7 @@ function briefToTrace(source) {
1329
1454
  ].join(" · ");
1330
1455
  }
1331
1456
  /**
1332
- * Render one exemplar as markdown lines.
1457
+ * Renders one exemplar as markdown lines.
1333
1458
  *
1334
1459
  * @remarks
1335
1460
  * An `Example`'s two sides are the only brief members permitted to span lines, so a
@@ -1341,9 +1466,9 @@ function briefToTrace(source) {
1341
1466
  *
1342
1467
  * @example
1343
1468
  * ```ts
1344
- * import { example, exampleToLines } from '@orkestrel/brief'
1469
+ * import { buildExample, exampleToLines } from '@orkestrel/brief'
1345
1470
  *
1346
- * exampleToLines(example('<input required>', 'el.validity')) // ['- ` <input required> ` → ` el.validity `']
1471
+ * exampleToLines(buildExample('<input required>', 'el.validity')) // ['- ` <input required> ` → ` el.validity `']
1347
1472
  * ```
1348
1473
  */
1349
1474
  function exampleToLines(entry) {
@@ -1374,20 +1499,20 @@ function exampleToLines(entry) {
1374
1499
  ];
1375
1500
  }
1376
1501
  /**
1377
- * Project a brief into the copy-ready agent prompt.
1502
+ * Projects a brief into the copy-ready agent prompt.
1378
1503
  *
1379
1504
  * @remarks
1380
1505
  * Paths are REFERENCED, never inlined — the executor retrieves them. An empty section is
1381
1506
  * omitted entirely, so the rendering carries no filler an executor must read past.
1382
1507
  *
1383
- * @param source - The brief to render.
1508
+ * @param input - The brief to render.
1384
1509
  * @returns The markdown prompt.
1385
1510
  *
1386
1511
  * @example
1387
1512
  * ```ts
1388
- * import { brief, briefToMarkdown, task } from '@orkestrel/brief'
1513
+ * import { briefToMarkdown, buildBrief, buildTask } from '@orkestrel/brief'
1389
1514
  *
1390
- * briefToMarkdown(brief(task('review', 'code', 'Review the gate rules.')))
1515
+ * briefToMarkdown(buildBrief(buildTask('review', 'code', 'Review the gate rules.')))
1391
1516
  * // '# Brief: Review the gate rules.\n\nreview · code\n\n## Output\n\n- format: markdown\n'
1392
1517
  * ```
1393
1518
  */
@@ -1481,21 +1606,21 @@ function briefToMarkdown(input) {
1481
1606
  return lines.join("\n");
1482
1607
  }
1483
1608
  /**
1484
- * Project a brief into a `/goal` completion condition.
1609
+ * Projects a brief into a `/goal` completion condition.
1485
1610
  *
1486
1611
  * @remarks
1487
1612
  * The proofs' commands VERBATIM plus a turn cap — the goal never adds a condition the
1488
1613
  * brief does not carry.
1489
1614
  *
1490
- * @param source - The brief to render.
1491
- * @param turns - The turn cap; defaults to `DEFAULT_BRIEF_TURNS`.
1615
+ * @param input - The brief to render.
1616
+ * @param turns - The turn cap. Default: `DEFAULT_BRIEF_TURNS`.
1492
1617
  * @returns The one-line completion condition.
1493
1618
  *
1494
1619
  * @example
1495
1620
  * ```ts
1496
- * import { brief, briefToGoal, proof, task } from '@orkestrel/brief'
1621
+ * import { briefToGoal, buildBrief, buildProof, buildTask } from '@orkestrel/brief'
1497
1622
  *
1498
- * briefToGoal(brief(task('test', 'code', 'Cover the gate.'), { proofs: [proof('x', 'npm test')] }))
1623
+ * briefToGoal(buildBrief(buildTask('test', 'code', 'Cover the gate.'), { proofs: [buildProof('x', 'npm test')] }))
1499
1624
  * // 'Done when every proof passes: npm test exits 0. Cap: 16 turns.'
1500
1625
  * ```
1501
1626
  */
@@ -1504,27 +1629,33 @@ function briefToGoal(input, turns = 16) {
1504
1629
  return `Done when every proof passes: ${source.proofs.length === 0 ? "no proofs recorded" : source.proofs.map((entry) => `${entry.command} exits 0`).join("; ")}. Cap: ${String(turns)} turns.`;
1505
1630
  }
1506
1631
  /**
1507
- * Project a brief into a subagent `Dispatch`.
1632
+ * Projects a brief into a subagent `Dispatch`.
1508
1633
  *
1509
1634
  * @remarks
1510
1635
  * `edit` is exactly `manifest.edit`, so two dispatches whose `edit` sets do not intersect
1511
1636
  * can run concurrently under the same brief without conflict.
1512
1637
  *
1513
1638
  * `authority` is exactly `brief.authority` in rank order, and it is a SEPARATE axis from the
1514
- * four permission sets rather than a fifth partition — a ranked path normally also appears in
1639
+ * permission sets rather than a further partition — a ranked path normally also appears in
1515
1640
  * `read` or `locked`, because the executor has to open what it obeys. It is projected as
1516
1641
  * paths so a machine consumer never has to parse `prompt`, which is written for a model.
1517
1642
  *
1518
- * @param source - The brief to project.
1519
- * @returns The dispatch — the rendered prompt, the ranked authority, and the four path sets.
1643
+ * @param input - The brief to project.
1644
+ * @returns The dispatch — the rendered prompt, the ranked authority, and the path sets.
1520
1645
  *
1521
1646
  * @example
1522
1647
  * ```ts
1523
- * import { brief, briefToDispatch, manifest, reference, task } from '@orkestrel/brief'
1524
- *
1525
- * const draft = brief(task('migrate', 'code', 'Migrate the stores.'), {
1526
- * authority: [reference('AGENTS.md', 'project law')],
1527
- * manifest: manifest({ edit: [reference('src/core/stores/**', 'the legacy stores')] }),
1648
+ * import {
1649
+ * briefToDispatch,
1650
+ * buildBrief,
1651
+ * buildManifest,
1652
+ * buildReference,
1653
+ * buildTask,
1654
+ * } from '@orkestrel/brief'
1655
+ *
1656
+ * const draft = buildBrief(buildTask('migrate', 'code', 'Migrate the stores.'), {
1657
+ * authority: [buildReference('AGENTS.md', 'project law')],
1658
+ * manifest: buildManifest({ edit: [buildReference('src/core/stores/**', 'the legacy stores')] }),
1528
1659
  * })
1529
1660
  * briefToDispatch(draft).edit // ['src/core/stores/**']
1530
1661
  * briefToDispatch(draft).authority // ['AGENTS.md']
@@ -1542,36 +1673,39 @@ function briefToDispatch(input) {
1542
1673
  };
1543
1674
  }
1544
1675
  /**
1545
- * Derive one imperative statement from free text.
1676
+ * Derives one imperative statement from free text.
1546
1677
  *
1547
1678
  * @remarks
1548
1679
  * Whitespace collapses, the first character uppercases, and a terminator is appended
1549
1680
  * when the text carries none. Nothing else is invented.
1550
1681
  *
1551
1682
  * @param text - The raw request text.
1552
- * @returns The statement, or `''` for empty or whitespace-only text.
1683
+ * @returns The statement, or `undefined` for empty or whitespace-only text.
1553
1684
  *
1554
1685
  * @example
1555
1686
  * ```ts
1556
1687
  * import { deriveStatement } from '@orkestrel/brief'
1557
1688
  *
1558
1689
  * deriveStatement(' clean up useForm ') // 'Clean up useForm.'
1559
- * deriveStatement('') // ''
1690
+ * deriveStatement('') // undefined
1560
1691
  * ```
1561
1692
  */
1562
1693
  function deriveStatement(text) {
1563
1694
  const collapsed = (0, _orkestrel_interpret.collapseWhitespace)(text);
1564
- if (collapsed.length === 0) return "";
1695
+ if (collapsed.length === 0) return void 0;
1565
1696
  const capitalized = collapsed.charAt(0).toUpperCase() + collapsed.slice(1);
1566
1697
  return /[.!?]$/u.test(capitalized) ? capitalized : `${capitalized}.`;
1567
1698
  }
1568
1699
  /**
1569
- * Derive a `Task` from an interprets `Intent` through the caller's vocabularies.
1700
+ * Derives a `Task` from an interprets `Intent` through the caller's vocabularies.
1570
1701
  *
1571
1702
  * @remarks
1572
1703
  * The vocabularies are the CALLER's policy: this maps and never guesses. An action or
1573
1704
  * domain the caller did not map — or mapped to an off-vocabulary value — yields
1574
- * `undefined` rather than an invented task. Inherited keys never resolve.
1705
+ * `undefined` rather than an invented task. Inherited keys never resolve. `Intent.action`
1706
+ * and `Intent.domain` are optional, because `classifyIntent` leaves an unmatched axis
1707
+ * absent, and an absent axis is unmapped by definition: it yields `undefined` before
1708
+ * either vocabulary is read.
1575
1709
  *
1576
1710
  * @param intent - The classified intent from an interpret pipeline.
1577
1711
  * @param text - The text the statement derives from.
@@ -1590,16 +1724,17 @@ function deriveStatement(text) {
1590
1724
  * ```
1591
1725
  */
1592
1726
  function deriveTask(intent, text, actions, domains) {
1727
+ if (intent.action === void 0 || intent.domain === void 0) return void 0;
1593
1728
  const operationDescriptor = Object.getOwnPropertyDescriptor(actions, intent.action);
1594
1729
  const domainDescriptor = Object.getOwnPropertyDescriptor(domains, intent.domain);
1595
1730
  const operation = operationDescriptor === void 0 ? void 0 : "value" in operationDescriptor ? operationDescriptor.value : operationDescriptor.get === void 0 ? void 0 : Reflect.apply(operationDescriptor.get, actions, []);
1596
1731
  const domain = domainDescriptor === void 0 ? void 0 : "value" in domainDescriptor ? domainDescriptor.value : domainDescriptor.get === void 0 ? void 0 : Reflect.apply(domainDescriptor.get, domains, []);
1597
1732
  if (!isTaskOperation(operation) || !isTaskDomain(domain)) return void 0;
1598
1733
  const statement = deriveStatement(text);
1599
- return statement.length === 0 ? void 0 : task(operation, domain, statement);
1734
+ return statement === void 0 ? void 0 : buildTask(operation, domain, statement);
1600
1735
  }
1601
1736
  /**
1602
- * Derive `Given[]` from an interprets `Entity[]`.
1737
+ * Derives `Given[]` from an interprets `Entity[]`.
1603
1738
  *
1604
1739
  * @remarks
1605
1740
  * Every extracted entity becomes one `extracted` fact. A nameless entity is dropped; an
@@ -1618,10 +1753,10 @@ function deriveTask(intent, text, actions, domains) {
1618
1753
  * ```
1619
1754
  */
1620
1755
  function deriveGivens(entities) {
1621
- return entities.filter((entity) => entity.name.length > 0).map((entity) => given("extracted", entity.name, typeof entity.value === "string" ? entity.value : typeof entity.value === "object" && entity.value !== null ? (0, _orkestrel_interpret.canonicalize)(entity.value) : String(entity.value)));
1756
+ return entities.filter((entity) => entity.name.length > 0).map((entity) => buildGiven("extracted", entity.name, typeof entity.value === "string" ? entity.value : typeof entity.value === "object" && entity.value !== null ? (0, _orkestrel_interpret.canonicalize)(entity.value) : String(entity.value)));
1622
1757
  }
1623
1758
  /**
1624
- * Derive `Gap[]` from an interprets `Ambiguity[]`.
1759
+ * Derives `Gap[]` from an interprets `Ambiguity[]`.
1625
1760
  *
1626
1761
  * @remarks
1627
1762
  * A REQUIRED ambiguity becomes a BLOCKING gap — the gate must fail closed on it. The
@@ -1642,7 +1777,7 @@ function deriveGivens(entities) {
1642
1777
  function deriveGaps(ambiguities) {
1643
1778
  return ambiguities.map((ambiguity) => {
1644
1779
  const candidates = ambiguity.candidates.filter((candidate) => candidate.length > 0);
1645
- return gap((0, _orkestrel_reason.formatField)(ambiguity.field), ambiguity.question, {
1780
+ return buildGap((0, _orkestrel_reason.formatField)(ambiguity.field), ambiguity.question, {
1646
1781
  blocking: ambiguity.required,
1647
1782
  ...candidates.length === 0 ? {} : { candidates }
1648
1783
  });
@@ -1651,7 +1786,7 @@ function deriveGaps(ambiguities) {
1651
1786
  //#endregion
1652
1787
  //#region src/core/parsers.ts
1653
1788
  /**
1654
- * Parse a JSON string into a `Brief`.
1789
+ * Parses a JSON string into a `Brief`.
1655
1790
  *
1656
1791
  * @remarks
1657
1792
  * The parse-then-trust boundary for a stored brief, a tool argument, or an agent's
@@ -1685,7 +1820,7 @@ function parseBrief(value) {
1685
1820
  //#endregion
1686
1821
  //#region src/core/BriefManager.ts
1687
1822
  /**
1688
- * The self-owning, versioned and content-hashed brief registry.
1823
+ * Implements the self-owning, versioned and content-hashed brief registry.
1689
1824
  *
1690
1825
  * @remarks
1691
1826
  * Record ids are MINTED from each brief's own content hash unless the caller names one,
@@ -1695,10 +1830,10 @@ function parseBrief(value) {
1695
1830
  *
1696
1831
  * @example
1697
1832
  * ```ts
1698
- * import { BriefManager, brief, task } from '@orkestrel/brief'
1833
+ * import { BriefManager, buildBrief, buildTask } from '@orkestrel/brief'
1699
1834
  *
1700
1835
  * const briefs = new BriefManager()
1701
- * const record = briefs.add(brief(task('document', 'writing', 'Write the brief guide.')))
1836
+ * const record = briefs.add(buildBrief(buildTask('document', 'writing', 'Write the brief guide.')))
1702
1837
  * record.id === record.hash // true
1703
1838
  * briefs.destroy()
1704
1839
  * ```
@@ -1725,7 +1860,7 @@ var BriefManager = class {
1725
1860
  get emitter() {
1726
1861
  return this.#emitter;
1727
1862
  }
1728
- get size() {
1863
+ get count() {
1729
1864
  return this.#records.size;
1730
1865
  }
1731
1866
  has(id) {
@@ -1740,9 +1875,9 @@ var BriefManager = class {
1740
1875
  this.#refuseDestroyed();
1741
1876
  return [...this.#records.values()];
1742
1877
  }
1743
- add(source, options) {
1878
+ add(brief, options) {
1744
1879
  this.#refuseDestroyed();
1745
- const record = this.#stage(source, this.#records, options);
1880
+ const record = this.#stage(brief, this.#records, options);
1746
1881
  this.#commit(record);
1747
1882
  return record;
1748
1883
  }
@@ -1809,7 +1944,7 @@ var BriefManager = class {
1809
1944
  //#endregion
1810
1945
  //#region src/core/BriefCompiler.ts
1811
1946
  /**
1812
- * The compilation orchestrator — the four-stage `[interpret, draft, gate, pin]` pipeline.
1947
+ * Implements the compilation orchestrator — the `[interpret, draft, gate, pin]` pipeline.
1813
1948
  *
1814
1949
  * @remarks
1815
1950
  * `compile` is genuinely SYNCHRONOUS and never throws for a brief it cannot emit: a
@@ -1819,13 +1954,13 @@ var BriefManager = class {
1819
1954
  *
1820
1955
  * @example
1821
1956
  * ```ts
1822
- * import { BriefCompiler, proof, task } from '@orkestrel/brief'
1957
+ * import { BriefCompiler, buildProof, buildTask } from '@orkestrel/brief'
1823
1958
  *
1824
1959
  * const compiler = new BriefCompiler()
1825
1960
  * const briefing = compiler.compile({
1826
- * task: task('audit', 'code', 'Audit the barrel for undocumented exports.'),
1961
+ * task: buildTask('audit', 'code', 'Audit the barrel for undocumented exports.'),
1827
1962
  * outcomes: [{ rank: 1, text: 'every export appears in the guide', required: true }],
1828
- * proofs: [proof('parity passes', 'npm run test:guides')],
1963
+ * proofs: [buildProof('parity passes', 'npm run test:guides')],
1829
1964
  * })
1830
1965
  * briefing.brief !== undefined // true — the presence of the brief IS the completeness test
1831
1966
  * compiler.destroy()
@@ -1976,9 +2111,9 @@ var BriefCompiler = class {
1976
2111
  this.#emitter.emit("compile", briefing);
1977
2112
  return briefing;
1978
2113
  }
1979
- gate(source) {
2114
+ gate(brief) {
1980
2115
  this.#refuseDestroyed();
1981
- const ruled = (0, _orkestrel_contract.attempt)(() => this.#own(this.#reason.reason(briefToSubject(source), gateDefinition()), [
2116
+ const ruled = (0, _orkestrel_contract.attempt)(() => this.#own(this.#reason.reason(briefToSubject(brief), buildGateDefinition()), [
1982
2117
  "reasoning",
1983
2118
  "conclusion",
1984
2119
  "rules",
@@ -2014,25 +2149,9 @@ var BriefCompiler = class {
2014
2149
  return cloned.success ? freezeDeep(cloned.value) : captureValue(value, members);
2015
2150
  }
2016
2151
  #read(input, raw, stages, failures) {
2017
- const members = [
2018
- "text",
2019
- "normalized",
2020
- "intent",
2021
- "entities",
2022
- "subject",
2023
- "definition",
2024
- "mappings",
2025
- "ambiguities",
2026
- "prompt",
2027
- "stages",
2028
- "failures",
2029
- "complete",
2030
- "confidence",
2031
- "digest"
2032
- ];
2033
2152
  const text = input.text;
2034
2153
  if (text !== void 0) {
2035
- const read = (0, _orkestrel_contract.attempt)(() => this.#own(this.#interpret.interpret(text), members));
2154
+ const read = (0, _orkestrel_contract.attempt)(() => this.#own(this.#interpret.interpret(text), INTERPRETATION_MEMBERS));
2036
2155
  if (read.success && (0, _orkestrel_interpret.isInterpretation)(read.value)) {
2037
2156
  stages.push(Object.freeze({
2038
2157
  stage: "interpret",
@@ -2057,7 +2176,7 @@ var BriefCompiler = class {
2057
2176
  const supplied = input.interpretation;
2058
2177
  if (supplied === void 0 || (0, _orkestrel_interpret.isInterpretation)(supplied)) return supplied;
2059
2178
  const live = raw.interpretation;
2060
- const captured = (0, _orkestrel_contract.attempt)(() => captureValue(live, members));
2179
+ const captured = (0, _orkestrel_contract.attempt)(() => captureValue(live, INTERPRETATION_MEMBERS));
2061
2180
  if (captured.success && (0, _orkestrel_interpret.isInterpretation)(captured.value)) return captured.value;
2062
2181
  const message = "The supplied interpretation does not satisfy the published shape";
2063
2182
  stages.push(Object.freeze({
@@ -2083,7 +2202,7 @@ var BriefCompiler = class {
2083
2202
  message: `Gate refused: ${unready.join(", ")}`
2084
2203
  };
2085
2204
  if (verdict === void 0) return void 0;
2086
- const refused = verdict.rules.filter((entry) => !entry.conclusion).map((entry) => entry.id).join(", ");
2205
+ const refused = verdict.rules.filter((entry) => !entry.applied).map((entry) => entry.id).join(", ");
2087
2206
  if (refused.length === 0) return {
2088
2207
  stage: "gate",
2089
2208
  code: "BLOCKED",
@@ -2098,7 +2217,7 @@ var BriefCompiler = class {
2098
2217
  #unresolved(interpretation, failures) {
2099
2218
  if (interpretation !== void 0) return [];
2100
2219
  if (!failures.some((entry) => entry.stage === "interpret")) return [];
2101
- return [gap("gaps", "The interpret stage failed, so the request is unread and its unknowns are unknown", { blocking: true })];
2220
+ return [buildGap("gaps", "The interpret stage failed, so the request is unread and its unknowns are unknown", { blocking: true })];
2102
2221
  }
2103
2222
  #draft(input, interpretation, unresolved) {
2104
2223
  const derived = interpretation === void 0 ? void 0 : deriveTask(interpretation.intent, interpretation.text, this.#actions, this.#domains);
@@ -2107,9 +2226,9 @@ var BriefCompiler = class {
2107
2226
  stage: "draft",
2108
2227
  field: "task"
2109
2228
  });
2110
- return snapshotBrief(brief(subject, {
2229
+ return snapshotBrief(buildBrief(subject, {
2111
2230
  authority: input.authority ?? [],
2112
- manifest: input.manifest ?? manifest(),
2231
+ manifest: input.manifest ?? buildManifest(),
2113
2232
  outcomes: input.outcomes ?? [],
2114
2233
  rules: input.rules ?? [],
2115
2234
  invariants: input.invariants ?? [],
@@ -2123,7 +2242,7 @@ var BriefCompiler = class {
2123
2242
  ...input.gaps ?? []
2124
2243
  ],
2125
2244
  risks: input.risks ?? [],
2126
- output: input.output ?? output("markdown"),
2245
+ output: input.output ?? buildOutput("markdown"),
2127
2246
  proofs: input.proofs ?? []
2128
2247
  }));
2129
2248
  }
@@ -2151,7 +2270,7 @@ var BriefCompiler = class {
2151
2270
  //#endregion
2152
2271
  //#region src/core/factories.ts
2153
2272
  /**
2154
- * Create a compilation orchestrator.
2273
+ * Creates a compilation orchestrator.
2155
2274
  *
2156
2275
  * @remarks
2157
2276
  * With no engines supplied the compiler wires its own: a default `createInterpret()`
@@ -2159,7 +2278,8 @@ var BriefCompiler = class {
2159
2278
  * `createReason` carrying one `LogicalReasoner` for the gate. Pass your own to share
2160
2279
  * instances or observe their emitters — the compiler destroys ONLY what it created.
2161
2280
  *
2162
- * @param options - Engines to borrow, the two intent vocabularies, and emitter hooks.
2281
+ * @param options - Engines to borrow, the `actions` and `domains` intent vocabularies, and
2282
+ * emitter hooks.
2163
2283
  * @returns A working {@link BriefCompilerInterface}.
2164
2284
  *
2165
2285
  * @example
@@ -2174,7 +2294,7 @@ function createBriefCompiler(options) {
2174
2294
  return new BriefCompiler(options);
2175
2295
  }
2176
2296
  /**
2177
- * Create a brief registry.
2297
+ * Creates a brief registry.
2178
2298
  *
2179
2299
  * @param options - An optional seed collection plus emitter hooks.
2180
2300
  * @returns A working {@link BriefManagerInterface}.
@@ -2184,7 +2304,7 @@ function createBriefCompiler(options) {
2184
2304
  * import { createBriefManager } from '@orkestrel/brief'
2185
2305
  *
2186
2306
  * const briefs = createBriefManager()
2187
- * briefs.size // 0
2307
+ * briefs.count // 0
2188
2308
  * briefs.destroy()
2189
2309
  * ```
2190
2310
  */
@@ -2192,7 +2312,7 @@ function createBriefManager(options) {
2192
2312
  return new BriefManager(options);
2193
2313
  }
2194
2314
  /**
2195
- * Compile `briefShape` into a guard, parser, JSON Schema, and seeded generator bundle.
2315
+ * Compiles `briefShape` into a guard, parser, JSON Schema, and seeded generator bundle.
2196
2316
  *
2197
2317
  * @remarks
2198
2318
  * The schema is what a tool boundary needs — hand it to `schemaToParameters` — and
@@ -2222,6 +2342,7 @@ exports.BriefError = BriefError;
2222
2342
  exports.BriefManager = BriefManager;
2223
2343
  exports.DEFAULT_BRIEF_TURNS = DEFAULT_BRIEF_TURNS;
2224
2344
  exports.GATE_ID = GATE_ID;
2345
+ exports.INTERPRETATION_MEMBERS = INTERPRETATION_MEMBERS;
2225
2346
  exports.LINE_BREAK_PATTERN = LINE_BREAK_PATTERN;
2226
2347
  exports.OUTPUT_FORMATS = OUTPUT_FORMATS;
2227
2348
  exports.RISK_SEVERITIES = RISK_SEVERITIES;
@@ -2229,7 +2350,6 @@ exports.SINGLE_LINE_PATTERN = SINGLE_LINE_PATTERN;
2229
2350
  exports.TASK_DOMAINS = TASK_DOMAINS;
2230
2351
  exports.TASK_OPERATIONS = TASK_OPERATIONS;
2231
2352
  exports.assertBrief = assertBrief;
2232
- exports.brief = brief;
2233
2353
  exports.briefShape = briefShape;
2234
2354
  exports.briefToContent = briefToContent;
2235
2355
  exports.briefToDispatch = briefToDispatch;
@@ -2238,8 +2358,20 @@ exports.briefToHash = briefToHash;
2238
2358
  exports.briefToMarkdown = briefToMarkdown;
2239
2359
  exports.briefToSubject = briefToSubject;
2240
2360
  exports.briefToTrace = briefToTrace;
2361
+ exports.buildBrief = buildBrief;
2362
+ exports.buildCitation = buildCitation;
2363
+ exports.buildExample = buildExample;
2364
+ exports.buildGap = buildGap;
2365
+ exports.buildGateDefinition = buildGateDefinition;
2366
+ exports.buildGiven = buildGiven;
2367
+ exports.buildManifest = buildManifest;
2368
+ exports.buildOutcome = buildOutcome;
2369
+ exports.buildOutput = buildOutput;
2370
+ exports.buildProof = buildProof;
2371
+ exports.buildReference = buildReference;
2372
+ exports.buildRisk = buildRisk;
2373
+ exports.buildTask = buildTask;
2241
2374
  exports.captureValue = captureValue;
2242
- exports.citation = citation;
2243
2375
  exports.citationShape = citationShape;
2244
2376
  exports.countSentences = countSentences;
2245
2377
  exports.createBriefCompiler = createBriefCompiler;
@@ -2250,7 +2382,6 @@ exports.deriveGivens = deriveGivens;
2250
2382
  exports.deriveStatement = deriveStatement;
2251
2383
  exports.deriveTask = deriveTask;
2252
2384
  exports.errorToMessage = errorToMessage;
2253
- exports.example = example;
2254
2385
  exports.exampleShape = exampleShape;
2255
2386
  exports.exampleToLines = exampleToLines;
2256
2387
  exports.findBlockingGaps = findBlockingGaps;
@@ -2260,10 +2391,7 @@ exports.findUnmetRules = findUnmetRules;
2260
2391
  exports.findUnpairedGaps = findUnpairedGaps;
2261
2392
  exports.freezeBranch = freezeBranch;
2262
2393
  exports.freezeDeep = freezeDeep;
2263
- exports.gap = gap;
2264
2394
  exports.gapShape = gapShape;
2265
- exports.gateDefinition = gateDefinition;
2266
- exports.given = given;
2267
2395
  exports.givenShape = givenShape;
2268
2396
  exports.isBrief = isBrief;
2269
2397
  exports.isBriefError = isBriefError;
@@ -2285,22 +2413,15 @@ exports.isTaskDomain = isTaskDomain;
2285
2413
  exports.isTaskOperation = isTaskOperation;
2286
2414
  exports.isText = isText;
2287
2415
  exports.lineShape = lineShape;
2288
- exports.manifest = manifest;
2289
2416
  exports.manifestShape = manifestShape;
2290
- exports.outcome = outcome;
2291
2417
  exports.outcomeShape = outcomeShape;
2292
- exports.output = output;
2293
2418
  exports.outputShape = outputShape;
2294
2419
  exports.parseBrief = parseBrief;
2295
2420
  exports.pinBrief = pinBrief;
2296
- exports.proof = proof;
2297
2421
  exports.proofShape = proofShape;
2298
- exports.reference = reference;
2299
2422
  exports.referenceShape = referenceShape;
2300
- exports.risk = risk;
2301
2423
  exports.riskShape = riskShape;
2302
2424
  exports.snapshotBrief = snapshotBrief;
2303
- exports.task = task;
2304
2425
  exports.taskShape = taskShape;
2305
2426
  exports.textShape = textShape;
2306
2427
  exports.validateBrief = validateBrief;