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