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