@orkestrel/scaffold 0.0.67 → 0.0.68

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.
Files changed (74) hide show
  1. package/dist/bin/main.js +67 -44
  2. package/dist/bin/main.js.map +1 -1
  3. package/dist/host/agents/templates/brief.md +9 -0
  4. package/dist/host/claude/agents/orkestrel.md +4 -4
  5. package/dist/host/claude/rules/names.md +15 -0
  6. package/dist/host/claude/rules/tests.md +33 -4
  7. package/dist/host/claude/rules/workspace.md +14 -2
  8. package/dist/host/dotfiles/prettierignore +3 -0
  9. package/dist/host/guides/README.md +65 -0
  10. package/dist/host/guides/abort.md +169 -0
  11. package/dist/host/guides/agent.md +1509 -0
  12. package/dist/host/guides/brief.md +1266 -0
  13. package/dist/host/guides/browser.md +2200 -0
  14. package/dist/host/guides/budget.md +196 -0
  15. package/dist/host/guides/codec.md +519 -0
  16. package/dist/host/guides/console.md +785 -0
  17. package/dist/host/guides/contract.md +1193 -0
  18. package/dist/host/guides/csv.md +541 -0
  19. package/dist/host/guides/database.md +2518 -0
  20. package/dist/host/guides/emitter.md +233 -0
  21. package/dist/host/guides/form.md +1791 -0
  22. package/dist/host/guides/html.md +717 -0
  23. package/dist/host/guides/indexeddb.md +505 -0
  24. package/dist/host/guides/interpret.md +1029 -0
  25. package/dist/host/guides/lsp.md +515 -0
  26. package/dist/host/guides/markdown.md +964 -0
  27. package/dist/host/guides/mcp.md +5554 -0
  28. package/dist/host/guides/middleware.md +927 -0
  29. package/dist/host/guides/msg.md +440 -0
  30. package/dist/host/guides/ndjson.md +120 -0
  31. package/dist/host/guides/ollama.md +380 -0
  32. package/dist/host/guides/pool.md +280 -0
  33. package/dist/host/guides/probe.md +1210 -0
  34. package/dist/host/guides/process.md +1620 -0
  35. package/dist/host/guides/program.md +1110 -0
  36. package/dist/host/guides/qualifier.md +854 -0
  37. package/dist/host/guides/queue.md +370 -0
  38. package/dist/host/guides/rater.md +330 -0
  39. package/dist/host/guides/reason.md +1122 -0
  40. package/dist/host/guides/relation.md +373 -0
  41. package/dist/host/guides/router.md +753 -0
  42. package/dist/host/guides/scaffold.md +192 -31
  43. package/dist/host/guides/sea.md +383 -0
  44. package/dist/host/guides/server.md +752 -0
  45. package/dist/host/guides/sqlite.md +330 -0
  46. package/dist/host/guides/sse.md +187 -0
  47. package/dist/host/guides/supervisor.md +4890 -0
  48. package/dist/host/guides/table.md +1556 -0
  49. package/dist/host/guides/template.md +280 -0
  50. package/dist/host/guides/terminal.md +1145 -0
  51. package/dist/host/guides/test.md +2969 -0
  52. package/dist/host/guides/timeout.md +252 -0
  53. package/dist/host/guides/tool.md +311 -0
  54. package/dist/host/guides/toolbox.md +1038 -0
  55. package/dist/host/guides/websocket.md +282 -0
  56. package/dist/host/guides/worker.md +615 -0
  57. package/dist/host/guides/workflow.md +1507 -0
  58. package/dist/host/guides/workspace.md +595 -0
  59. package/dist/host/manifest.json +1218 -10
  60. package/dist/host/tests/policy.test.ts +279 -2
  61. package/dist/host/tests/setupPolicy.ts +437 -6
  62. package/dist/src/core/index.cjs +38 -16
  63. package/dist/src/core/index.cjs.map +1 -1
  64. package/dist/src/core/index.d.cts +33 -9
  65. package/dist/src/core/index.d.ts +33 -9
  66. package/dist/src/core/index.js +37 -17
  67. package/dist/src/core/index.js.map +1 -1
  68. package/dist/src/server/index.cjs +1750 -1567
  69. package/dist/src/server/index.cjs.map +1 -1
  70. package/dist/src/server/index.d.cts +106 -24
  71. package/dist/src/server/index.d.ts +106 -24
  72. package/dist/src/server/index.js +1751 -1570
  73. package/dist/src/server/index.js.map +1 -1
  74. package/package.json +3 -3
@@ -0,0 +1,330 @@
1
+ # Rater
2
+
3
+ > A typed quantitative rating layer over `@orkestrel/reason`'s shared engine: authored
4
+ > lines, each a plain reason `QuantitativeDefinition` joined to display metadata, rated
5
+ > against one subject to produce a `LineResult` per line — an `amount` and its
6
+ > `Worksheet` audit trail — and one `RatingResult` carrying every line's outcome and a
7
+ > derived `total`.
8
+
9
+ A subject is a plain data record, and the caller decides which lines to rate for it:
10
+ `Rater` rates the lines it is handed, reports what each one resolved to, and performs no
11
+ evaluation arithmetic of its own. Rating never mutates its inputs, so every result is a
12
+ fresh object. A rater either receives an injected `ReasonInterface`, which it never
13
+ destroys, or builds and owns its own quantitative-only engine (`bail: false`) and
14
+ destroys that engine in `destroy()`. An injected engine must be able to dispatch a
15
+ quantitative definition: one it cannot dispatch surfaces the engine's own error, which
16
+ this package never wraps. Every `rate` call fires once through the rater's typed
17
+ `emitter`. Source: [`src/core`](../src/core). Surfaced through the `@src/core` barrel.
18
+
19
+ ## Surface
20
+
21
+ Create a rater, rate one subject against a list of lines (or a full rating
22
+ definition), read the derived total:
23
+
24
+ ```ts
25
+ import { buildLineDefinition, createRater } from '@orkestrel/rater'
26
+ import {
27
+ createFactorGroup,
28
+ createQuantitativeDefinition,
29
+ createStaticFactor,
30
+ } from '@orkestrel/reason'
31
+
32
+ const rater = createRater()
33
+
34
+ const base = buildLineDefinition(
35
+ 'base',
36
+ 'Base Amount',
37
+ createQuantitativeDefinition('base', 'Base', [
38
+ createFactorGroup('amount', 'sum', [createStaticFactor('flat', 100)]),
39
+ ]),
40
+ )
41
+
42
+ const result = rater.rate([base], { id: 'subject-1' })
43
+ result.lines[0]?.amount // 100
44
+ result.total // 100
45
+
46
+ rater.emitter.on('rate', (subject, rated) => rated.success)
47
+
48
+ rater.destroy()
49
+ ```
50
+
51
+ `rate` dispatches by input shape — the array-of-lines overload is declared first so a
52
+ plain line list resolves to that form; a `RatingDefinition` resolves the same way
53
+ through its own `lines`. Each overload rates exactly one subject — there is no batch
54
+ overload, and the subject must be a plain record or `rate` throws `RaterError`
55
+ `'MISMATCH'`; an input that is neither an array of lines nor a `RatingDefinition`
56
+ throws `RaterError` `'DEFINITION'`. A line that fails to resolve (a missing lookup
57
+ entry, a failed required factor) is a rating failure reported on its own `LineResult`
58
+ (`worksheet.success: false`, no `amount`, a populated `worksheet.errors`) — the caller decides
59
+ what to do with a failed line, and `Rater` reports exactly what each line resolved
60
+ to. `total` is derived from every line's `amount` by a `TotalHandler` (default
61
+ `sumAmounts`, overridable through `RaterOptions.total`). A `LineResult` carries an
62
+ `amount` only when its `worksheet.success` is `true`, and a `RatingResult`'s `success`
63
+ is `true` only when every line's `worksheet.success` is `true`.
64
+
65
+ ### Types
66
+
67
+ A `Shape` cell holds an interface's data members as bare names in braces, `?` marking an
68
+ optional member and `plus` introducing its call-signature members, and a type alias's own
69
+ type literal with a union's arms escaped as `\|`.
70
+
71
+ | Type | Kind | Shape | Summary |
72
+ | ------------------ | --------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
73
+ | `Stage` | type | `'factor' \| 'group' \| 'total'` | Names a worksheet derivation step stage. |
74
+ | `RaterErrorCode` | type | `'DEFINITION' \| 'MISMATCH' \| 'DESTROYED'` | Names a coded `RaterError` programmer-error code. |
75
+ | `TotalHandler` | type | `(lines: readonly LineResult[]) => number \| undefined` | Represents a pure total port over resolved lines. |
76
+ | `LineDefinition` | interface | `{ id, name, description?, rate, metadata? }` | Represents one rateable line — a quantitative definition joined to display metadata. |
77
+ | `RatingDefinition` | interface | `{ id, name, description?, lines, metadata? }` | Represents a pure authored rating — a named, ordered set of lines. |
78
+ | `Evidence` | interface | `{ field?, label?, comparison?, expected?, actual?, met? }` | Represents a checked-evidence row rendered into a display-neutral sentence. |
79
+ | `WorksheetFactor` | interface | `{ id, name?, description?, applied, value?, evidence }` | Represents a resolved quantitative factor, joined to its authored metadata. |
80
+ | `WorksheetGroup` | interface | `{ id, name?, description?, applied, value, factors }` | Represents a resolved quantitative group, joined to its authored metadata. |
81
+ | `Step` | interface | `{ stage, id?, name?, value, expression? }` | Represents a display-neutral worksheet derivation step. |
82
+ | `Worksheet` | interface | `{ id, name, aggregation, precision?, value, groups, steps, trace, errors, success }` | Represents a quantitative definition joined to its result — the rating audit trail. |
83
+ | `LineResult` | interface | `{ id, name, amount?, worksheet }` | Represents one line's rating outcome. |
84
+ | `RatingResult` | interface | `{ lines, total?, success }` | Represents a rated outcome across every line of one `rate` call. |
85
+ | `RaterEventMap` | type | `{ rate }` | Represents the push observation surface of a `RaterInterface`. |
86
+ | `RaterOptions` | interface | `{ on?, error?, engine?, total?, labels? }` | Configures `createRater` and the `Rater` constructor. |
87
+ | `RaterInterface` | interface | `{ emitter } plus rate, destroy` | Represents the rating orchestrator over the shared quantitative reasoning engine. |
88
+
89
+ `RaterInterface`'s `emitter` is a `readonly` data member and stays in this table's
90
+ `Shape` cell; the interface's call-signature members are documented under
91
+ [Methods](#methods).
92
+
93
+ ### Errors
94
+
95
+ Every `RaterError` carries a `code` — `'DEFINITION'`, `'MISMATCH'`, or `'DESTROYED'` —
96
+ and an optional `context` record of structured detail beside its message.
97
+
98
+ | API | Kind | Summary |
99
+ | -------------- | -------- | --------------------------------------------------------------- |
100
+ | `RaterError` | class | Represents a coded programmer error thrown by the rating layer. |
101
+ | `isRaterError` | function | Narrows a caught value to a `RaterError`. |
102
+
103
+ The `isRaterError` guard narrows a caught value, so a handler reads the `code` member
104
+ off it:
105
+
106
+ ```ts
107
+ import { isRaterError, RaterError } from '@orkestrel/rater'
108
+
109
+ try {
110
+ throw new RaterError('DESTROYED', 'Rater has been destroyed')
111
+ } catch (error) {
112
+ if (isRaterError(error)) error.code // 'DESTROYED'
113
+ }
114
+ ```
115
+
116
+ ### Validators
117
+
118
+ Total guards composed from `@orkestrel/contract` combinators — adversarial input
119
+ (junk, cycles, hostile prototypes) returns `false`, never throws. The guards take their
120
+ posture from who produces the value. Authored definitions supplied to this package use
121
+ exact `recordOf` guards because this package owns that input shape; extra keys fail.
122
+ Results returned by a borrowed `RaterInterface` use open `objectOf` guards because
123
+ another valid implementation may return class instances, inherited members,
124
+ or extra members. `isRatingResult` is the borrowed-engine boundary: it and its nested
125
+ result guards reject arrays and check every published typed member without narrowing
126
+ plain numbers, strings, or unknown values.
127
+
128
+ In a guard table a `Shape` cell holds the type the guard narrows to.
129
+
130
+ | API | Kind | Shape | Summary |
131
+ | -------------------- | -------- | ------------------ | ---------------------------------------------------------------------- |
132
+ | `isStage` | const | `Stage` | Determines whether a value is a `Stage` literal. |
133
+ | `isLineDefinition` | function | `LineDefinition` | Determines whether a value is an exact `LineDefinition` record. |
134
+ | `isRatingDefinition` | function | `RatingDefinition` | Determines whether a value is an exact `RatingDefinition` record. |
135
+ | `isEvidence` | function | `Evidence` | Determines whether a value is an open result-side `Evidence` object. |
136
+ | `isWorksheetFactor` | function | `WorksheetFactor` | Determines whether a value is an open `WorksheetFactor` result object. |
137
+ | `isWorksheetGroup` | function | `WorksheetGroup` | Determines whether a value is an open `WorksheetGroup` result object. |
138
+ | `isStep` | function | `Step` | Determines whether a value is an open `Step` result object. |
139
+ | `isWorksheet` | function | `Worksheet` | Determines whether a value is an open `Worksheet` result object. |
140
+ | `isLineResult` | function | `LineResult` | Determines whether a value is an open `LineResult` object. |
141
+ | `isRatingResult` | function | `RatingResult` | Determines whether a value is an open `RatingResult` object. |
142
+
143
+ Each guard answers `true` for a value of its own shape:
144
+
145
+ ```ts
146
+ import { isLineDefinition, isRatingDefinition, isStage } from '@orkestrel/rater'
147
+ import { createQuantitativeDefinition } from '@orkestrel/reason'
148
+
149
+ isStage('group') // true
150
+ isLineDefinition({
151
+ id: 'base',
152
+ name: 'Base Amount',
153
+ rate: createQuantitativeDefinition('base', 'Base', []),
154
+ }) // true
155
+ isRatingDefinition({ id: 'r1', name: 'Rating', lines: [] }) // true
156
+ ```
157
+
158
+ ### Helpers
159
+
160
+ Pure, exported utility functions — the definition builders, the evidence construction,
161
+ and the worksheet-joining behind `Rater`'s `rate` projection.
162
+
163
+ | API | Kind | Summary |
164
+ | ----------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
165
+ | `buildLineDefinition` | function | Builds a fresh `LineDefinition` from a line id, a display name, and the line's quantitative rating definition, with `overrides` merged over those defaults. |
166
+ | `buildRatingDefinition` | function | Builds a fresh `RatingDefinition` from a rating id, a display name, and the rating's ordered lines, with `overrides` merged over those defaults. |
167
+ | `buildEvidence` | function | Builds an `Evidence` row from an evaluated `Check`. |
168
+ | `buildEvidenceRows` | function | Builds one evidence row per authored check of a quantitative factor, joined to that check's evaluated result. |
169
+ | `buildWorksheetFactor` | function | Joins one authored quantitative factor to its evaluated `FactorResult`. |
170
+ | `buildWorksheetGroup` | function | Joins one authored quantitative group to its evaluated `GroupResult`. |
171
+ | `buildWorksheetStep` | function | Builds one display-neutral `Step` row. |
172
+ | `buildWorksheetSteps` | function | Builds the ordered `Step` rows for a resolved `Worksheet`. |
173
+ | `buildWorksheet` | function | Joins a `QuantitativeDefinition` and its `QuantitativeResult` into a `Worksheet` — the rating audit trail. |
174
+ | `buildLineResult` | function | Builds a rated `LineResult` from a line's evaluated `QuantitativeResult`. |
175
+ | `sumAmounts` | function | Sums defined line amounts. |
176
+
177
+ Each definition builder returns a fresh object and omits an absent optional key
178
+ entirely:
179
+
180
+ ```ts
181
+ import { buildLineDefinition, buildRatingDefinition } from '@orkestrel/rater'
182
+ import { createQuantitativeDefinition } from '@orkestrel/reason'
183
+
184
+ const base = buildLineDefinition(
185
+ 'base',
186
+ 'Base Amount',
187
+ createQuantitativeDefinition('base', 'Base', []),
188
+ )
189
+ buildRatingDefinition('r1', 'Rating', [base])
190
+ buildRatingDefinition('r1', 'Rating', [base], { description: 'A rating' }) // overrides merged over the defaults
191
+ ```
192
+
193
+ Evidence construction — a `Check` (and its evaluated result) rendered into a
194
+ display-neutral `Evidence` row; `labels` (keyed by dot-joined field) override the resolved
195
+ `label`:
196
+
197
+ ```ts
198
+ import { buildEvidence, buildEvidenceRows } from '@orkestrel/rater'
199
+ import { createCheck } from '@orkestrel/reason'
200
+
201
+ const evaluated = createCheck('age', 'above', 18)
202
+ buildEvidence(evaluated, 25, true) // { field: 'age', comparison: 'above', expected: 18, actual: 25, met: true }
203
+ buildEvidence(evaluated, 25, true, { age: 'Age' }) // labels override → adds { label: 'Age' }
204
+ buildEvidenceRows([evaluated], [{ field: 'age', met: true, actual: 25 }])
205
+ ```
206
+
207
+ Worksheet joining and line assembly — one authored quantitative definition and its
208
+ evaluated result, walked into the display-neutral `Worksheet` audit trail and then a
209
+ rated `LineResult`:
210
+
211
+ ```ts
212
+ import {
213
+ buildLineDefinition,
214
+ buildLineResult,
215
+ buildWorksheet,
216
+ buildWorksheetFactor,
217
+ buildWorksheetGroup,
218
+ buildWorksheetStep,
219
+ buildWorksheetSteps,
220
+ sumAmounts,
221
+ } from '@orkestrel/rater'
222
+ import {
223
+ createFactorGroup,
224
+ createFieldFactor,
225
+ createQuantitativeDefinition,
226
+ createQuantitativeReasoner,
227
+ createReason,
228
+ } from '@orkestrel/reason'
229
+
230
+ const definition = createQuantitativeDefinition('risk', 'Risk', [
231
+ createFactorGroup('drivers', 'sum', [createFieldFactor('age', 'age')]),
232
+ ])
233
+ const engine = createReason({ reasoners: [createQuantitativeReasoner()] })
234
+ const result = engine.reason({ age: 25 }, definition)
235
+
236
+ if (result.reasoning === 'quantitative') {
237
+ const group = definition.groups[0]
238
+ const groupResult = result.groups[0]
239
+ if (group !== undefined && groupResult !== undefined) {
240
+ const factor = group.factors[0]
241
+ if (factor !== undefined) buildWorksheetFactor(factor, groupResult.factors) // one factor joined to its result
242
+ buildWorksheetGroup(group, result.groups) // one group joined to its result
243
+ }
244
+ buildWorksheetStep('total', definition.id, definition.name, result.value, `sum = ${result.value}`)
245
+ buildWorksheetSteps(
246
+ definition,
247
+ result,
248
+ definition.groups.map((entry) => buildWorksheetGroup(entry, result.groups)),
249
+ ) // the full ordered step list: factors, groups, then the total
250
+ buildWorksheet(definition, result) // the whole worksheet — groups, steps, trace, errors, success
251
+
252
+ const line = buildLineDefinition('risk', 'Risk', definition)
253
+ buildLineResult(line, result) // the line's rated LineResult — amount present only on a successful worksheet
254
+ }
255
+
256
+ sumAmounts([]) // undefined — no line carries an amount
257
+ ```
258
+
259
+ ### Factories
260
+
261
+ | API | Kind | Summary |
262
+ | ------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------- |
263
+ | `createRater` | function | Creates a rating orchestrator over the shared quantitative engine, seeded from `RaterOptions` and returning a `RaterInterface`. |
264
+
265
+ `createRater` returns a live entity that owns an engine unless one is injected, so every
266
+ rater is destroyed when its work is done.
267
+
268
+ #### Create a rater
269
+
270
+ The demonstration builds a rater over its own engine and destroys that rater:
271
+
272
+ ```ts
273
+ import { createRater } from '@orkestrel/rater'
274
+
275
+ const rater = createRater()
276
+ rater.destroy()
277
+ ```
278
+
279
+ ### Classes
280
+
281
+ | API | Kind | Summary |
282
+ | ------- | ----- | ----------------------------------------------------------------------------------------------------------------------------------------- |
283
+ | `Rater` | class | Orchestrates rating — owns (or receives) the shared quantitative reasoning engine and projects results into the rating domain vocabulary. |
284
+
285
+ ## Methods
286
+
287
+ The public methods of `RaterInterface` — one table, keyed by its backticked name, every
288
+ call-signature member listed, and the `readonly` data member `emitter` left off it.
289
+ `Rater` exposes exactly its interface's methods, so this doubles as the per-instance
290
+ method surface.
291
+
292
+ #### `RaterInterface`
293
+
294
+ The array-of-lines overload of `rate` is declared first so a plain line list resolves
295
+ to that form; each overload rates exactly one subject. `destroy()` is idempotent — it
296
+ destroys an owned engine (never an injected one), then the emitter last. Afterwards
297
+ every other method throws `RaterError` `'DESTROYED'`.
298
+
299
+ | Method | Returns | Summary |
300
+ | --------- | -------------- | ---------------------------------------------------------------------------------------------------------- |
301
+ | `rate` | `RatingResult` | Rates an array of lines, or a `RatingDefinition`, against one subject over the shared quantitative engine. |
302
+ | `destroy` | `void` | Destroys an owned engine and then the emitter, and does nothing on a later call. |
303
+
304
+ The array-of-lines and rating-definition forms of `rate` each take one subject and
305
+ return equal results for the same lines:
306
+
307
+ ```ts
308
+ import { buildLineDefinition, createRater } from '@orkestrel/rater'
309
+ import { createQuantitativeDefinition } from '@orkestrel/reason'
310
+
311
+ const rater = createRater()
312
+ const base = buildLineDefinition(
313
+ 'base',
314
+ 'Base Amount',
315
+ createQuantitativeDefinition('base', 'Base', []),
316
+ )
317
+
318
+ rater.rate([base], { id: 'subject-1' }) // the array-of-lines overload
319
+ rater.rate({ id: 'r1', name: 'Rating', lines: [base] }, { id: 'subject-1' }) // the RatingDefinition overload
320
+
321
+ rater.destroy()
322
+ ```
323
+
324
+ ## Tests
325
+
326
+ - [`tests/guides.test.ts`](../tests/guides.test.ts) — the `## Surface` ↔ `src/core` bijection (value and type exports), the `RaterInterface` ↔ `Rater` method bijection, and the equality gate: every `Summary` cell against its declaration's description paragraph, the titled `Create a rater` fence against the `@example` block of that title (pinned so the titled pair cannot be retired silently), and the README pitch against this guide's tagline. It also runs the flagship fences and asserts the values their comments claim.
327
+ - [`tests/src/core/Rater.test.ts`](../tests/src/core/Rater.test.ts) — line selection (only the supplied lines are evaluated, exactly once each, and an omitted line never is), the result shape (`LineResult` carries an `amount` only on a successful worksheet; `RatingResult` carries a `total` only when one is defined), quantitative-only dispatch against an injected engine that also carries a logical reasoner, rating failures (a missing lookup key with no fallback, a failed required check), totals (a custom `TotalHandler`, an all-failed rating, an empty line list), immutability against frozen inputs, engine ownership and `destroy` (idempotence, `'DESTROYED'` afterwards, an injected engine surviving), the array-of-lines and rating-definition `rate` overloads agreeing, the `'DEFINITION'` and `'MISMATCH'` errors, the `rate` event firing once per call, `labels` threading into a resolved `Evidence.label`, the defensive fallback for a non-quantitative or malformed engine result, and the finite-arithmetic guarantees.
328
+ - [`tests/src/core/factories.test.ts`](../tests/src/core/factories.test.ts) — `createRater` returns a rater usable immediately, threads an injected engine, a total override, labels, and an `on.rate` hook together, and tears down an owned engine on `destroy` while leaving an injected one working.
329
+ - [`tests/src/core/helpers.test.ts`](../tests/src/core/helpers.test.ts) — evidence construction and label application, the factor and group joins with their defaults for an absent result, the step ordering (applied factors, then the group, then the total), the full worksheet join passing `trace`, `errors`, and `success` through, `buildLineResult` carrying an `amount` only on success, `sumAmounts` over defined, negative-zero, overflowing, `NaN`, and opposing-infinity amounts, the definition builders' override merge and optional-key omission, and the round trip from each builder back through its guard.
330
+ - [`tests/src/core/validators.test.ts`](../tests/src/core/validators.test.ts) — each guard against its accepted shapes, its wrong-typed and missing members, adversarial input (junk, cycles, hostile prototypes, revoked proxies) answered without throwing, the exact `recordOf` posture rejecting an extra key on an authored definition, and the open `objectOf` posture admitting unknown members, prototypes, and class instances on a borrowed result.