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