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