@orkestrel/brief 0.0.4 → 0.0.6

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.
@@ -31,6 +31,15 @@ import { Subject } from '@orkestrel/reason';
31
31
  * nothing, so it is an assertion rather than a factory. Reserve it for programmer-error
32
32
  * contexts where invalidity is a bug.
33
33
  *
34
+ * Intake NARROWS, and transfers no ownership. What comes back is the caller's own object,
35
+ * so a member carried on an accessor can answer this guard one way and a later reader
36
+ * another. The division is deliberate: the borrowed-engine law governs values this package
37
+ * pulls across a seam it called, and a value handed in at the door stays the caller's.
38
+ * `snapshotBrief` is the ownership door, and `pinBrief`, `BriefManager`, `briefToMarkdown`,
39
+ * `briefToGoal`, and `briefToDispatch` take it. `briefToSubject`, `briefToContent`, and
40
+ * `briefToTrace` read the value they are handed instead, so a caller reaching one of those
41
+ * directly owns that reading. Pass `assertBrief` a value you already own.
42
+ *
34
43
  * @param data - The candidate brief data.
35
44
  * @returns The same value, now known to satisfy {@link Brief}.
36
45
  * @throws {@link BriefError} `INVALID` when `data` fails `isBrief`.
@@ -173,22 +182,31 @@ import { Subject } from '@orkestrel/reason';
173
182
  * is FIXED: readiness is this package's contract, not a caller setting.
174
183
  *
175
184
  * A borrowed engine is the caller's own code, not an attacker, and this package does not
176
- * treat it as one. The line is OWNERSHIP, and it produces four obligations worth stating
177
- * because none of them is enforced in code:
178
- *
179
- * - Every value a borrowed engine returns is OWNED AT ARRIVAL — copied where the value
180
- * permits it, sealed in place where it does not — and then read exactly once. What the
181
- * engine does with its own object afterwards cannot reach a `Briefing`.
185
+ * treat it as one. The line is OWNERSHIP, and it produces obligations worth stating because
186
+ * none of them is enforced in code:
187
+ *
188
+ * - Every value a borrowed engine returns is OWNED AT ARRIVAL — copied where a structured
189
+ * clone can carry it, captured into a frozen plain view where it cannot — and read once,
190
+ * where that copy or capture takes the reading. The captured view is what the `Briefing`
191
+ * replays, exactly as the clone arm always produced: a member the caller's prototype
192
+ * carries, outside the published contract, does not survive capture, and it never survived
193
+ * a structured clone either. What the engine does with its own object afterwards cannot
194
+ * reach a `Briefing`.
182
195
  * - Both returns are shape-checked with their packages' published guards — reasons' logical
183
196
  * result guard for the verdict, interprets' interpretation guard at both of the interpret
184
197
  * stage's doors. A malformed value at either door records `INTERPRET_FAILED` instead of
185
198
  * escaping `compile` as a raw throw, and a supplied interpretation whose snapshot copy
186
- * loses prototype-carried members is sealed live rather than refused.
199
+ * loses prototype-carried members is captured rather than refused.
187
200
  * - Neither engine is narrowed past its published contract. `Entity.value` is `unknown` and
188
201
  * `LogicalResult` is an interface a class instance satisfies, so a value JSON cannot
189
- * express is on-contract and is sealed rather than refused.
190
- * - `actions` and `domains` are read LIVE on every `compile`, not snapshotted at
191
- * construction. Mutating them between calls changes what the next call derives.
202
+ * express is on-contract: its uncloneable leaves keep their identity inside the captured
203
+ * view rather than being refused.
204
+ * - `actions` and `domains` are read as option slots ONCE, at construction, so replacing
205
+ * either property on the options object afterwards changes nothing. The map each slot
206
+ * names is dereferenced on every `compile`, and each lookup captures its mapping once
207
+ * through the own descriptor. Mutating a map between calls therefore changes what the next
208
+ * call derives, while a mapping that answers differently on a second read cannot change
209
+ * what one call already derived.
192
210
  *
193
211
  * Whether the engine is correct, and whether it answers the same way twice, remain the
194
212
  * caller's own problem.
@@ -638,6 +656,32 @@ import { Subject } from '@orkestrel/reason';
638
656
  */
639
657
  export declare function briefToTrace(source: Brief): string;
640
658
 
659
+ /**
660
+ * Captures one stable, frozen view of a foreign contract value.
661
+ *
662
+ * @remarks
663
+ * Rebuilds the root and every reachable plain container from its own enumerable members.
664
+ * Unknown own members survive. Each published member absent from that copied own set is read
665
+ * once and materialized, which admits a class that supplies its contract through prototype
666
+ * accessors without leaving later reads attached to the live instance. Non-container leaves
667
+ * retain their identity, including functions that `structuredClone` cannot carry.
668
+ *
669
+ * @param source - The foreign value to capture.
670
+ * @param members - The published root member names to materialize when absent from its own set.
671
+ * @returns A deeply frozen plain view, or `source` itself when it is a primitive.
672
+ *
673
+ * @example
674
+ * ```ts
675
+ * import { captureValue } from '@orkestrel/brief'
676
+ *
677
+ * const leaf = () => 'ready'
678
+ * const owned = captureValue({ leaf }, ['leaf'])
679
+ * Reflect.get(owned, 'leaf') === leaf // true — an uncloneable leaf keeps its identity
680
+ * Object.isFrozen(owned) // true
681
+ * ```
682
+ */
683
+ export declare function captureValue(source: unknown, members: readonly string[]): unknown;
684
+
641
685
  /**
642
686
  * One external source — what it is called, where it lives, and why it is cited.
643
687
  *
@@ -1307,6 +1351,22 @@ import { Subject } from '@orkestrel/reason';
1307
1351
  value: StringShape;
1308
1352
  }, false>;
1309
1353
 
1354
+ /**
1355
+ * Every published `Interpretation` member name, frozen.
1356
+ *
1357
+ * @remarks
1358
+ * The capture list `BriefCompiler` hands `captureValue` at each interpret door — the borrowed
1359
+ * engine's return, and the caller's supplied interpretation. A class instance carries its
1360
+ * contract on the prototype, so the captured view materializes exactly the members named here,
1361
+ * and a name missing from the list is a member the view drops.
1362
+ *
1363
+ * The `satisfies` clause refuses a name `Interpretation` does not declare, and it holds the
1364
+ * element type at the listed names rather than widening it to `string`. That is what lets the
1365
+ * equality assertion beside the capture cases refuse a list that has fallen short of the
1366
+ * published shape.
1367
+ */
1368
+ export declare const INTERPRETATION_MEMBERS: readonly ("text" | "normalized" | "intent" | "entities" | "subject" | "definition" | "mappings" | "ambiguities" | "prompt" | "stages" | "failures" | "complete" | "confidence" | "digest")[];
1369
+
1310
1370
  /**
1311
1371
  * The `interpret` phase snapshot — raw text in, an `Interpretation` out.
1312
1372
  *
@@ -1572,6 +1632,15 @@ import { Subject } from '@orkestrel/reason';
1572
1632
  * all fail the same way — `undefined`, never a throw. Coerce a bare vocabulary value with
1573
1633
  * `parseEnum` from `@orkestrel/contract` against the exported tuple instead.
1574
1634
  *
1635
+ * The half of the intake pair that is OWNED BY CONSTRUCTION, which is what separates it from
1636
+ * `assertBrief`. The argument is text, so the graph the guard reads is one `JSON.parse` built
1637
+ * inside this call: it carries no caller identity, no accessor, and no alias back into anything
1638
+ * the caller still holds, and the parse-and-guard primitive this file imports from
1639
+ * `@orkestrel/contract` returns that same parsed graph rather than a second reading of it.
1640
+ * Every member `isBrief` checked therefore answers a later reader identically. The value is
1641
+ * fresh rather than frozen, so the caller owns it outright — reach for `snapshotBrief` when the
1642
+ * value came from code instead of from text.
1643
+ *
1575
1644
  * @param value - The JSON text to parse.
1576
1645
  * @returns The `Brief` when the parsed value satisfies `isBrief`, otherwise `undefined`.
1577
1646
  *
@@ -31,6 +31,15 @@ import { Subject } from '@orkestrel/reason';
31
31
  * nothing, so it is an assertion rather than a factory. Reserve it for programmer-error
32
32
  * contexts where invalidity is a bug.
33
33
  *
34
+ * Intake NARROWS, and transfers no ownership. What comes back is the caller's own object,
35
+ * so a member carried on an accessor can answer this guard one way and a later reader
36
+ * another. The division is deliberate: the borrowed-engine law governs values this package
37
+ * pulls across a seam it called, and a value handed in at the door stays the caller's.
38
+ * `snapshotBrief` is the ownership door, and `pinBrief`, `BriefManager`, `briefToMarkdown`,
39
+ * `briefToGoal`, and `briefToDispatch` take it. `briefToSubject`, `briefToContent`, and
40
+ * `briefToTrace` read the value they are handed instead, so a caller reaching one of those
41
+ * directly owns that reading. Pass `assertBrief` a value you already own.
42
+ *
34
43
  * @param data - The candidate brief data.
35
44
  * @returns The same value, now known to satisfy {@link Brief}.
36
45
  * @throws {@link BriefError} `INVALID` when `data` fails `isBrief`.
@@ -173,22 +182,31 @@ import { Subject } from '@orkestrel/reason';
173
182
  * is FIXED: readiness is this package's contract, not a caller setting.
174
183
  *
175
184
  * A borrowed engine is the caller's own code, not an attacker, and this package does not
176
- * treat it as one. The line is OWNERSHIP, and it produces four obligations worth stating
177
- * because none of them is enforced in code:
178
- *
179
- * - Every value a borrowed engine returns is OWNED AT ARRIVAL — copied where the value
180
- * permits it, sealed in place where it does not — and then read exactly once. What the
181
- * engine does with its own object afterwards cannot reach a `Briefing`.
185
+ * treat it as one. The line is OWNERSHIP, and it produces obligations worth stating because
186
+ * none of them is enforced in code:
187
+ *
188
+ * - Every value a borrowed engine returns is OWNED AT ARRIVAL — copied where a structured
189
+ * clone can carry it, captured into a frozen plain view where it cannot — and read once,
190
+ * where that copy or capture takes the reading. The captured view is what the `Briefing`
191
+ * replays, exactly as the clone arm always produced: a member the caller's prototype
192
+ * carries, outside the published contract, does not survive capture, and it never survived
193
+ * a structured clone either. What the engine does with its own object afterwards cannot
194
+ * reach a `Briefing`.
182
195
  * - Both returns are shape-checked with their packages' published guards — reasons' logical
183
196
  * result guard for the verdict, interprets' interpretation guard at both of the interpret
184
197
  * stage's doors. A malformed value at either door records `INTERPRET_FAILED` instead of
185
198
  * escaping `compile` as a raw throw, and a supplied interpretation whose snapshot copy
186
- * loses prototype-carried members is sealed live rather than refused.
199
+ * loses prototype-carried members is captured rather than refused.
187
200
  * - Neither engine is narrowed past its published contract. `Entity.value` is `unknown` and
188
201
  * `LogicalResult` is an interface a class instance satisfies, so a value JSON cannot
189
- * express is on-contract and is sealed rather than refused.
190
- * - `actions` and `domains` are read LIVE on every `compile`, not snapshotted at
191
- * construction. Mutating them between calls changes what the next call derives.
202
+ * express is on-contract: its uncloneable leaves keep their identity inside the captured
203
+ * view rather than being refused.
204
+ * - `actions` and `domains` are read as option slots ONCE, at construction, so replacing
205
+ * either property on the options object afterwards changes nothing. The map each slot
206
+ * names is dereferenced on every `compile`, and each lookup captures its mapping once
207
+ * through the own descriptor. Mutating a map between calls therefore changes what the next
208
+ * call derives, while a mapping that answers differently on a second read cannot change
209
+ * what one call already derived.
192
210
  *
193
211
  * Whether the engine is correct, and whether it answers the same way twice, remain the
194
212
  * caller's own problem.
@@ -638,6 +656,32 @@ import { Subject } from '@orkestrel/reason';
638
656
  */
639
657
  export declare function briefToTrace(source: Brief): string;
640
658
 
659
+ /**
660
+ * Captures one stable, frozen view of a foreign contract value.
661
+ *
662
+ * @remarks
663
+ * Rebuilds the root and every reachable plain container from its own enumerable members.
664
+ * Unknown own members survive. Each published member absent from that copied own set is read
665
+ * once and materialized, which admits a class that supplies its contract through prototype
666
+ * accessors without leaving later reads attached to the live instance. Non-container leaves
667
+ * retain their identity, including functions that `structuredClone` cannot carry.
668
+ *
669
+ * @param source - The foreign value to capture.
670
+ * @param members - The published root member names to materialize when absent from its own set.
671
+ * @returns A deeply frozen plain view, or `source` itself when it is a primitive.
672
+ *
673
+ * @example
674
+ * ```ts
675
+ * import { captureValue } from '@orkestrel/brief'
676
+ *
677
+ * const leaf = () => 'ready'
678
+ * const owned = captureValue({ leaf }, ['leaf'])
679
+ * Reflect.get(owned, 'leaf') === leaf // true — an uncloneable leaf keeps its identity
680
+ * Object.isFrozen(owned) // true
681
+ * ```
682
+ */
683
+ export declare function captureValue(source: unknown, members: readonly string[]): unknown;
684
+
641
685
  /**
642
686
  * One external source — what it is called, where it lives, and why it is cited.
643
687
  *
@@ -1307,6 +1351,22 @@ import { Subject } from '@orkestrel/reason';
1307
1351
  value: StringShape;
1308
1352
  }, false>;
1309
1353
 
1354
+ /**
1355
+ * Every published `Interpretation` member name, frozen.
1356
+ *
1357
+ * @remarks
1358
+ * The capture list `BriefCompiler` hands `captureValue` at each interpret door — the borrowed
1359
+ * engine's return, and the caller's supplied interpretation. A class instance carries its
1360
+ * contract on the prototype, so the captured view materializes exactly the members named here,
1361
+ * and a name missing from the list is a member the view drops.
1362
+ *
1363
+ * The `satisfies` clause refuses a name `Interpretation` does not declare, and it holds the
1364
+ * element type at the listed names rather than widening it to `string`. That is what lets the
1365
+ * equality assertion beside the capture cases refuse a list that has fallen short of the
1366
+ * published shape.
1367
+ */
1368
+ export declare const INTERPRETATION_MEMBERS: readonly ("text" | "normalized" | "intent" | "entities" | "subject" | "definition" | "mappings" | "ambiguities" | "prompt" | "stages" | "failures" | "complete" | "confidence" | "digest")[];
1369
+
1310
1370
  /**
1311
1371
  * The `interpret` phase snapshot — raw text in, an `Interpretation` out.
1312
1372
  *
@@ -1572,6 +1632,15 @@ import { Subject } from '@orkestrel/reason';
1572
1632
  * all fail the same way — `undefined`, never a throw. Coerce a bare vocabulary value with
1573
1633
  * `parseEnum` from `@orkestrel/contract` against the exported tuple instead.
1574
1634
  *
1635
+ * The half of the intake pair that is OWNED BY CONSTRUCTION, which is what separates it from
1636
+ * `assertBrief`. The argument is text, so the graph the guard reads is one `JSON.parse` built
1637
+ * inside this call: it carries no caller identity, no accessor, and no alias back into anything
1638
+ * the caller still holds, and the parse-and-guard primitive this file imports from
1639
+ * `@orkestrel/contract` returns that same parsed graph rather than a second reading of it.
1640
+ * Every member `isBrief` checked therefore answers a later reader identically. The value is
1641
+ * fresh rather than frozen, so the caller owns it outright — reach for `snapshotBrief` when the
1642
+ * value came from code instead of from text.
1643
+ *
1575
1644
  * @param value - The JSON text to parse.
1576
1645
  * @returns The `Brief` when the parsed value satisfies `isBrief`, otherwise `undefined`.
1577
1646
  *
@@ -44,6 +44,36 @@ var RISK_SEVERITIES = Object.freeze([
44
44
  "high"
45
45
  ]);
46
46
  /**
47
+ * Every published `Interpretation` member name, frozen.
48
+ *
49
+ * @remarks
50
+ * The capture list `BriefCompiler` hands `captureValue` at each interpret door — the borrowed
51
+ * engine's return, and the caller's supplied interpretation. A class instance carries its
52
+ * contract on the prototype, so the captured view materializes exactly the members named here,
53
+ * and a name missing from the list is a member the view drops.
54
+ *
55
+ * The `satisfies` clause refuses a name `Interpretation` does not declare, and it holds the
56
+ * element type at the listed names rather than widening it to `string`. That is what lets the
57
+ * equality assertion beside the capture cases refuse a list that has fallen short of the
58
+ * published shape.
59
+ */
60
+ var INTERPRETATION_MEMBERS = Object.freeze([
61
+ "text",
62
+ "normalized",
63
+ "intent",
64
+ "entities",
65
+ "subject",
66
+ "definition",
67
+ "mappings",
68
+ "ambiguities",
69
+ "prompt",
70
+ "stages",
71
+ "failures",
72
+ "complete",
73
+ "confidence",
74
+ "digest"
75
+ ]);
76
+ /**
47
77
  * `16` — the default turn cap `briefToGoal` renders.
48
78
  *
49
79
  * @remarks
@@ -369,6 +399,84 @@ var isBrief = recordOf({
369
399
  //#endregion
370
400
  //#region src/core/cloners.ts
371
401
  /**
402
+ * Captures one stable, frozen view of a foreign contract value.
403
+ *
404
+ * @remarks
405
+ * Rebuilds the root and every reachable plain container from its own enumerable members.
406
+ * Unknown own members survive. Each published member absent from that copied own set is read
407
+ * once and materialized, which admits a class that supplies its contract through prototype
408
+ * accessors without leaving later reads attached to the live instance. Non-container leaves
409
+ * retain their identity, including functions that `structuredClone` cannot carry.
410
+ *
411
+ * @param source - The foreign value to capture.
412
+ * @param members - The published root member names to materialize when absent from its own set.
413
+ * @returns A deeply frozen plain view, or `source` itself when it is a primitive.
414
+ *
415
+ * @example
416
+ * ```ts
417
+ * import { captureValue } from '@orkestrel/brief'
418
+ *
419
+ * const leaf = () => 'ready'
420
+ * const owned = captureValue({ leaf }, ['leaf'])
421
+ * Reflect.get(owned, 'leaf') === leaf // true — an uncloneable leaf keeps its identity
422
+ * Object.isFrozen(owned) // true
423
+ * ```
424
+ */
425
+ function captureValue(source, members) {
426
+ if (source === null || typeof source !== "object" && typeof source !== "function") return source;
427
+ const target = Array.isArray(source) ? [] : Object.create(null);
428
+ const seen = new WeakMap([[source, target]]);
429
+ const captured = [target];
430
+ const pending = [[
431
+ source,
432
+ target,
433
+ members
434
+ ]];
435
+ while (pending.length > 0) {
436
+ const frame = pending.pop();
437
+ if (frame === void 0) continue;
438
+ const [current, view, expected] = frame;
439
+ const entries = [];
440
+ const copied = /* @__PURE__ */ new Set();
441
+ for (const key of Reflect.ownKeys(current)) {
442
+ const descriptor = Reflect.getOwnPropertyDescriptor(current, key);
443
+ if (descriptor === void 0 || !descriptor.enumerable) continue;
444
+ copied.add(key);
445
+ entries.push([key, "value" in descriptor ? descriptor.value : Reflect.get(current, key)]);
446
+ }
447
+ for (const key of expected ?? []) if (!copied.has(key)) entries.push([key, Reflect.get(current, key)]);
448
+ for (const [key, value] of entries) {
449
+ let owned = value;
450
+ if (value !== null && typeof value === "object") {
451
+ const existing = seen.get(value);
452
+ if (existing !== void 0) owned = existing;
453
+ else {
454
+ const prototype = Reflect.getPrototypeOf(value);
455
+ if (Array.isArray(value) || prototype === null || prototype === Object.prototype) {
456
+ const branch = Array.isArray(value) ? [] : Object.create(null);
457
+ seen.set(value, branch);
458
+ captured.push(branch);
459
+ pending.push([
460
+ value,
461
+ branch,
462
+ void 0
463
+ ]);
464
+ owned = branch;
465
+ }
466
+ }
467
+ }
468
+ Reflect.defineProperty(view, key, {
469
+ value: owned,
470
+ enumerable: true,
471
+ configurable: false,
472
+ writable: false
473
+ });
474
+ }
475
+ }
476
+ for (const view of captured) Object.freeze(view);
477
+ return target;
478
+ }
479
+ /**
372
480
  * Return a deeply owned, deeply frozen copy of a brief, refusing anything off-contract.
373
481
  *
374
482
  * @remarks
@@ -1163,6 +1271,15 @@ function errorToMessage(error) {
1163
1271
  * nothing, so it is an assertion rather than a factory. Reserve it for programmer-error
1164
1272
  * contexts where invalidity is a bug.
1165
1273
  *
1274
+ * Intake NARROWS, and transfers no ownership. What comes back is the caller's own object,
1275
+ * so a member carried on an accessor can answer this guard one way and a later reader
1276
+ * another. The division is deliberate: the borrowed-engine law governs values this package
1277
+ * pulls across a seam it called, and a value handed in at the door stays the caller's.
1278
+ * `snapshotBrief` is the ownership door, and `pinBrief`, `BriefManager`, `briefToMarkdown`,
1279
+ * `briefToGoal`, and `briefToDispatch` take it. `briefToSubject`, `briefToContent`, and
1280
+ * `briefToTrace` read the value they are handed instead, so a caller reaching one of those
1281
+ * directly owns that reading. Pass `assertBrief` a value you already own.
1282
+ *
1166
1283
  * @param data - The candidate brief data.
1167
1284
  * @returns The same value, now known to satisfy {@link Brief}.
1168
1285
  * @throws {@link BriefError} `INVALID` when `data` fails `isBrief`.
@@ -1502,8 +1619,10 @@ function deriveStatement(text) {
1502
1619
  * ```
1503
1620
  */
1504
1621
  function deriveTask(intent, text, actions, domains) {
1505
- const operation = Object.hasOwn(actions, intent.action) ? actions[intent.action] : void 0;
1506
- const domain = Object.hasOwn(domains, intent.domain) ? domains[intent.domain] : void 0;
1622
+ const operationDescriptor = Object.getOwnPropertyDescriptor(actions, intent.action);
1623
+ const domainDescriptor = Object.getOwnPropertyDescriptor(domains, intent.domain);
1624
+ const operation = operationDescriptor === void 0 ? void 0 : "value" in operationDescriptor ? operationDescriptor.value : operationDescriptor.get === void 0 ? void 0 : Reflect.apply(operationDescriptor.get, actions, []);
1625
+ const domain = domainDescriptor === void 0 ? void 0 : "value" in domainDescriptor ? domainDescriptor.value : domainDescriptor.get === void 0 ? void 0 : Reflect.apply(domainDescriptor.get, domains, []);
1507
1626
  if (!isTaskOperation(operation) || !isTaskDomain(domain)) return void 0;
1508
1627
  const statement = deriveStatement(text);
1509
1628
  return statement.length === 0 ? void 0 : task(operation, domain, statement);
@@ -1569,6 +1688,15 @@ function deriveGaps(ambiguities) {
1569
1688
  * all fail the same way — `undefined`, never a throw. Coerce a bare vocabulary value with
1570
1689
  * `parseEnum` from `@orkestrel/contract` against the exported tuple instead.
1571
1690
  *
1691
+ * The half of the intake pair that is OWNED BY CONSTRUCTION, which is what separates it from
1692
+ * `assertBrief`. The argument is text, so the graph the guard reads is one `JSON.parse` built
1693
+ * inside this call: it carries no caller identity, no accessor, and no alias back into anything
1694
+ * the caller still holds, and the parse-and-guard primitive this file imports from
1695
+ * `@orkestrel/contract` returns that same parsed graph rather than a second reading of it.
1696
+ * Every member `isBrief` checked therefore answers a later reader identically. The value is
1697
+ * fresh rather than frozen, so the caller owns it outright — reach for `snapshotBrief` when the
1698
+ * value came from code instead of from text.
1699
+ *
1572
1700
  * @param value - The JSON text to parse.
1573
1701
  * @returns The `Brief` when the parsed value satisfies `isBrief`, otherwise `undefined`.
1574
1702
  *
@@ -1879,7 +2007,15 @@ var BriefCompiler = class {
1879
2007
  }
1880
2008
  gate(source) {
1881
2009
  this.#refuseDestroyed();
1882
- const ruled = attempt(() => this.#own(this.#reason.reason(briefToSubject(source), gateDefinition())));
2010
+ const ruled = attempt(() => this.#own(this.#reason.reason(briefToSubject(source), gateDefinition()), [
2011
+ "reasoning",
2012
+ "conclusion",
2013
+ "rules",
2014
+ "count",
2015
+ "success",
2016
+ "trace",
2017
+ "errors"
2018
+ ]));
1883
2019
  if (!ruled.success) throw new BriefError("GATE_FAILED", errorToMessage(ruled.error), {
1884
2020
  stage: "gate",
1885
2021
  field: "reason"
@@ -1902,14 +2038,14 @@ var BriefCompiler = class {
1902
2038
  #snapshot(input) {
1903
2039
  return freezeDeep(structuredClone(input));
1904
2040
  }
1905
- #own(value) {
2041
+ #own(value, members) {
1906
2042
  const cloned = attempt(() => structuredClone(value));
1907
- return freezeDeep(cloned.success ? cloned.value : value);
2043
+ return cloned.success ? freezeDeep(cloned.value) : captureValue(value, members);
1908
2044
  }
1909
2045
  #read(input, raw, stages, failures) {
1910
2046
  const text = input.text;
1911
2047
  if (text !== void 0) {
1912
- const read = attempt(() => this.#own(this.#interpret.interpret(text)));
2048
+ const read = attempt(() => this.#own(this.#interpret.interpret(text), INTERPRETATION_MEMBERS));
1913
2049
  if (read.success && isInterpretation(read.value)) {
1914
2050
  stages.push(Object.freeze({
1915
2051
  stage: "interpret",
@@ -1934,7 +2070,8 @@ var BriefCompiler = class {
1934
2070
  const supplied = input.interpretation;
1935
2071
  if (supplied === void 0 || isInterpretation(supplied)) return supplied;
1936
2072
  const live = raw.interpretation;
1937
- if (live !== void 0 && isInterpretation(live)) return freezeDeep(live);
2073
+ const captured = attempt(() => captureValue(live, INTERPRETATION_MEMBERS));
2074
+ if (captured.success && isInterpretation(captured.value)) return captured.value;
1938
2075
  const message = "The supplied interpretation does not satisfy the published shape";
1939
2076
  stages.push(Object.freeze({
1940
2077
  stage: "interpret",
@@ -1958,7 +2095,7 @@ var BriefCompiler = class {
1958
2095
  code: "BLOCKED",
1959
2096
  message: `Gate refused: ${unready.join(", ")}`
1960
2097
  };
1961
- if (!isLogicalResult(verdict)) return void 0;
2098
+ if (verdict === void 0) return void 0;
1962
2099
  const refused = verdict.rules.filter((entry) => !entry.conclusion).map((entry) => entry.id).join(", ");
1963
2100
  if (refused.length === 0) return {
1964
2101
  stage: "gate",
@@ -2092,6 +2229,6 @@ function createBriefContract() {
2092
2229
  return createContract(briefShape);
2093
2230
  }
2094
2231
  //#endregion
2095
- export { BLANK_PATTERN, BriefCompiler, BriefError, BriefManager, DEFAULT_BRIEF_TURNS, GATE_ID, LINE_BREAK_PATTERN, OUTPUT_FORMATS, RISK_SEVERITIES, SINGLE_LINE_PATTERN, TASK_DOMAINS, TASK_OPERATIONS, assertBrief, brief, briefShape, briefToContent, briefToDispatch, briefToGoal, briefToHash, briefToMarkdown, briefToSubject, briefToTrace, citation, citationShape, countSentences, createBriefCompiler, createBriefContract, createBriefManager, deriveGaps, deriveGivens, deriveStatement, deriveTask, errorToMessage, example, exampleShape, exampleToLines, findBlockingGaps, findManifestOverlaps, findUngrantedAuthority, findUnmetRules, findUnpairedGaps, freezeBranch, freezeDeep, gap, gapShape, gateDefinition, given, givenShape, isBrief, isBriefError, isCitation, isExample, isGap, isGiven, isLine, isManifest, isOutcome, isOutput, isOutputFormat, isProof, isReference, isRisk, isRiskSeverity, isTask, isTaskDomain, isTaskOperation, isText, lineShape, manifest, manifestShape, outcome, outcomeShape, output, outputShape, parseBrief, pinBrief, proof, proofShape, reference, referenceShape, risk, riskShape, snapshotBrief, task, taskShape, textShape, validateBrief };
2232
+ export { BLANK_PATTERN, BriefCompiler, BriefError, BriefManager, DEFAULT_BRIEF_TURNS, GATE_ID, INTERPRETATION_MEMBERS, LINE_BREAK_PATTERN, OUTPUT_FORMATS, RISK_SEVERITIES, SINGLE_LINE_PATTERN, TASK_DOMAINS, TASK_OPERATIONS, assertBrief, brief, briefShape, briefToContent, briefToDispatch, briefToGoal, briefToHash, briefToMarkdown, briefToSubject, briefToTrace, captureValue, citation, citationShape, countSentences, createBriefCompiler, createBriefContract, createBriefManager, deriveGaps, deriveGivens, deriveStatement, deriveTask, errorToMessage, example, exampleShape, exampleToLines, findBlockingGaps, findManifestOverlaps, findUngrantedAuthority, findUnmetRules, findUnpairedGaps, freezeBranch, freezeDeep, gap, gapShape, gateDefinition, given, givenShape, isBrief, isBriefError, isCitation, isExample, isGap, isGiven, isLine, isManifest, isOutcome, isOutput, isOutputFormat, isProof, isReference, isRisk, isRiskSeverity, isTask, isTaskDomain, isTaskOperation, isText, lineShape, manifest, manifestShape, outcome, outcomeShape, output, outputShape, parseBrief, pinBrief, proof, proofShape, reference, referenceShape, risk, riskShape, snapshotBrief, task, taskShape, textShape, validateBrief };
2096
2233
 
2097
2234
  //# sourceMappingURL=index.js.map