@orkestrel/rater 0.0.13 → 0.0.14
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 +13 -9
- package/dist/src/core/index.cjs +70 -32
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +100 -53
- package/dist/src/core/index.d.ts +100 -53
- package/dist/src/core/index.js +70 -32
- package/dist/src/core/index.js.map +1 -1
- package/package.json +15 -16
package/dist/src/core/index.js
CHANGED
|
@@ -8,7 +8,8 @@ import { Emitter } from "@orkestrel/emitter";
|
|
|
8
8
|
* @remarks
|
|
9
9
|
* `DEFINITION` — the `rate` input failed both the array-of-lines and rating
|
|
10
10
|
* definition validation. `MISMATCH` — a rated subject is not a record.
|
|
11
|
-
* `DESTROYED` — use of a destroyed entity.
|
|
11
|
+
* `DESTROYED` — use of a destroyed entity. `context` carries optional
|
|
12
|
+
* structured detail beside the message.
|
|
12
13
|
*
|
|
13
14
|
* @example
|
|
14
15
|
* ```ts
|
|
@@ -52,6 +53,10 @@ function isRaterError(value) {
|
|
|
52
53
|
/**
|
|
53
54
|
* Determines whether a value is a {@link Stage} literal.
|
|
54
55
|
*
|
|
56
|
+
* @remarks
|
|
57
|
+
* A scalar union has no open or exact axis, so this guard accepts one of the
|
|
58
|
+
* `Stage` literals and leaves nothing unchecked.
|
|
59
|
+
*
|
|
55
60
|
* @param value - The value to test
|
|
56
61
|
* @returns True if `value` is `'factor'`, `'group'`, or `'total'`; false otherwise
|
|
57
62
|
*
|
|
@@ -68,8 +73,11 @@ var isStage = literalOf("factor", "group", "total");
|
|
|
68
73
|
* Determines whether a value is an exact {@link LineDefinition} record.
|
|
69
74
|
*
|
|
70
75
|
* @remarks
|
|
71
|
-
*
|
|
72
|
-
*
|
|
76
|
+
* Every `LineDefinition` member is checked, including its quantitative
|
|
77
|
+
* definition. Total guard: adversarial input (cycles, hostile prototypes)
|
|
78
|
+
* returns `false`, never throws. The record shape is exact — this package owns
|
|
79
|
+
* the authored input record, so an extra key fails and nothing is left
|
|
80
|
+
* unchecked.
|
|
73
81
|
*
|
|
74
82
|
* @param value - The value to test
|
|
75
83
|
* @returns True if `value` is a `LineDefinition`; false otherwise
|
|
@@ -95,8 +103,11 @@ function isLineDefinition(value) {
|
|
|
95
103
|
* Determines whether a value is an exact {@link RatingDefinition} record.
|
|
96
104
|
*
|
|
97
105
|
* @remarks
|
|
98
|
-
*
|
|
99
|
-
*
|
|
106
|
+
* Every `RatingDefinition` member is checked, including each nested line
|
|
107
|
+
* definition. Total guard: adversarial input (cycles, hostile prototypes)
|
|
108
|
+
* returns `false`, never throws. The record shape is exact — this package owns
|
|
109
|
+
* the authored input record, so an extra key fails and nothing is left
|
|
110
|
+
* unchecked.
|
|
100
111
|
*
|
|
101
112
|
* @param value - The value to test
|
|
102
113
|
* @returns True if `value` is a `RatingDefinition`; false otherwise
|
|
@@ -121,10 +132,13 @@ function isRatingDefinition(value) {
|
|
|
121
132
|
* Determines whether a value is an open result-side {@link Evidence} object.
|
|
122
133
|
*
|
|
123
134
|
* @remarks
|
|
135
|
+
* Optional `field` is checked as a `FieldPath`, `label` as a string,
|
|
136
|
+
* `comparison` as a `Comparison`, and `met` as a boolean, each when defined.
|
|
124
137
|
* Unknown members, prototypes, and class instances are admitted. Arrays are
|
|
125
138
|
* refused. `expected` and `actual` are `unknown`, so this guard does not read or
|
|
126
|
-
* check them
|
|
127
|
-
*
|
|
139
|
+
* check them and a borrowed result is never narrowed on them; either member may
|
|
140
|
+
* also be absent because `objectOf` reads declared members rather than
|
|
141
|
+
* requiring or enumerating own keys.
|
|
128
142
|
*
|
|
129
143
|
* @param value - The value to test
|
|
130
144
|
* @returns True if every checked `Evidence` member conforms; false otherwise
|
|
@@ -153,8 +167,11 @@ function isEvidence(value) {
|
|
|
153
167
|
* Determines whether a value is an open {@link WorksheetFactor} result object.
|
|
154
168
|
*
|
|
155
169
|
* @remarks
|
|
156
|
-
*
|
|
157
|
-
*
|
|
170
|
+
* `id`, the optional authored text, `applied`, an optional plain-number
|
|
171
|
+
* `value`, and each `Evidence` entry are checked. Unknown members, prototypes,
|
|
172
|
+
* and class instances are admitted and left unchecked, because a borrowed
|
|
173
|
+
* result implementation may add them. Arrays are refused. Optional members may
|
|
174
|
+
* be absent or read as `undefined`.
|
|
158
175
|
*
|
|
159
176
|
* @param value - The value to test
|
|
160
177
|
* @returns True if every published worksheet-factor member conforms; false otherwise
|
|
@@ -184,8 +201,11 @@ function isWorksheetFactor(value) {
|
|
|
184
201
|
* Determines whether a value is an open {@link WorksheetGroup} result object.
|
|
185
202
|
*
|
|
186
203
|
* @remarks
|
|
187
|
-
*
|
|
188
|
-
*
|
|
204
|
+
* `id`, the optional authored text, `applied`, a plain-number `value`, and each
|
|
205
|
+
* `WorksheetFactor` entry are checked. Unknown members, prototypes, and class
|
|
206
|
+
* instances are admitted and left unchecked, because a borrowed result
|
|
207
|
+
* implementation may add them. Arrays are refused. Optional members may be
|
|
208
|
+
* absent or read as `undefined`.
|
|
189
209
|
*
|
|
190
210
|
* @param value - The value to test
|
|
191
211
|
* @returns True if every published worksheet-group member conforms; false otherwise
|
|
@@ -211,8 +231,11 @@ function isWorksheetGroup(value) {
|
|
|
211
231
|
* Determines whether a value is an open {@link Step} result object.
|
|
212
232
|
*
|
|
213
233
|
* @remarks
|
|
214
|
-
*
|
|
215
|
-
*
|
|
234
|
+
* `stage` is checked through `isStage`, `id`, `name`, and `expression` when
|
|
235
|
+
* defined, and `value` as a plain number. Unknown members, prototypes, and
|
|
236
|
+
* class instances are admitted and left unchecked, because a borrowed result
|
|
237
|
+
* implementation may add them. Arrays are refused. Optional members may be
|
|
238
|
+
* absent or read as `undefined`.
|
|
216
239
|
*
|
|
217
240
|
* @param value - The value to test
|
|
218
241
|
* @returns True if every published worksheet-step member conforms; false otherwise
|
|
@@ -241,8 +264,12 @@ function isStep(value) {
|
|
|
241
264
|
* Determines whether a value is an open {@link Worksheet} result object.
|
|
242
265
|
*
|
|
243
266
|
* @remarks
|
|
244
|
-
*
|
|
245
|
-
*
|
|
267
|
+
* Identity, `aggregation` through reason's `isAggregation`, an optional
|
|
268
|
+
* plain-number `precision`, a plain-number `value`, the nested groups and steps,
|
|
269
|
+
* `trace`, `errors`, and `success` are checked. Unknown members, prototypes, and
|
|
270
|
+
* class instances are admitted and left unchecked, because a borrowed result
|
|
271
|
+
* implementation may add them. Arrays are refused. Optional members may be
|
|
272
|
+
* absent or read as `undefined`.
|
|
246
273
|
*
|
|
247
274
|
* @param value - The value to test
|
|
248
275
|
* @returns True if every published worksheet member conforms; false otherwise
|
|
@@ -272,10 +299,14 @@ function isWorksheet(value) {
|
|
|
272
299
|
* Determines whether a value is an open {@link LineResult} object.
|
|
273
300
|
*
|
|
274
301
|
* @remarks
|
|
275
|
-
*
|
|
276
|
-
*
|
|
277
|
-
*
|
|
278
|
-
*
|
|
302
|
+
* Identity, an optional plain-number `amount`, and the nested `Worksheet` that
|
|
303
|
+
* carries the line's outcome are checked. Unknown members, prototypes, and
|
|
304
|
+
* class instances are admitted and left unchecked, because a borrowed result
|
|
305
|
+
* implementation may add them, and so is the relationship between `amount` and
|
|
306
|
+
* `worksheet.success`, which the published interface types independently.
|
|
307
|
+
* Arrays are refused. `amount` may be absent or read as `undefined`; when
|
|
308
|
+
* present it stays a plain JavaScript `number` without a finite or range
|
|
309
|
+
* refinement.
|
|
279
310
|
*
|
|
280
311
|
* @param value - The value to test
|
|
281
312
|
* @returns True if every published line-result member conforms; false otherwise
|
|
@@ -299,10 +330,13 @@ function isLineResult(value) {
|
|
|
299
330
|
* Determines whether a value is an open {@link RatingResult} object.
|
|
300
331
|
*
|
|
301
332
|
* @remarks
|
|
302
|
-
* Use this guard for a result returned by a borrowed `RaterInterface`.
|
|
303
|
-
*
|
|
304
|
-
*
|
|
305
|
-
*
|
|
333
|
+
* Use this guard for a result returned by a borrowed `RaterInterface`. Every
|
|
334
|
+
* nested `LineResult`, an optional plain-number `total`, and a boolean `success`
|
|
335
|
+
* are checked. Unknown members, prototypes, and class instances are admitted and
|
|
336
|
+
* left unchecked, and so are the relationships among totals, lines, and success,
|
|
337
|
+
* because the borrowed interface publishes only their member types. Arrays are
|
|
338
|
+
* refused. `total` may be absent or read as `undefined`; when present it stays a
|
|
339
|
+
* plain JavaScript `number` without a finite or range refinement.
|
|
306
340
|
*
|
|
307
341
|
* @param value - The value to test
|
|
308
342
|
* @returns True if every published rating-result member conforms; false otherwise
|
|
@@ -324,7 +358,9 @@ function isRatingResult(value) {
|
|
|
324
358
|
//#endregion
|
|
325
359
|
//#region src/core/helpers.ts
|
|
326
360
|
/**
|
|
327
|
-
* Builds a {@link LineDefinition}
|
|
361
|
+
* Builds a fresh {@link LineDefinition} from a line id, a display name, and the
|
|
362
|
+
* line's quantitative rating definition, with `overrides` merged over those
|
|
363
|
+
* defaults.
|
|
328
364
|
*
|
|
329
365
|
* @param id - The line id
|
|
330
366
|
* @param name - The display name
|
|
@@ -349,7 +385,8 @@ function buildLineDefinition(id, name, rate, overrides) {
|
|
|
349
385
|
};
|
|
350
386
|
}
|
|
351
387
|
/**
|
|
352
|
-
* Builds a {@link RatingDefinition}
|
|
388
|
+
* Builds a fresh {@link RatingDefinition} from a rating id, a display name, and
|
|
389
|
+
* the rating's ordered lines, with `overrides` merged over those defaults.
|
|
353
390
|
*
|
|
354
391
|
* @param id - The rating id
|
|
355
392
|
* @param name - The display name
|
|
@@ -635,12 +672,12 @@ function sumAmounts(lines) {
|
|
|
635
672
|
* reasoning engine and projects results into the rating domain vocabulary.
|
|
636
673
|
*
|
|
637
674
|
* @remarks
|
|
638
|
-
* When no `engine` is injected, `Rater` builds and
|
|
639
|
-
* quantitative-only engine (`bail: false`) — Rater performs
|
|
675
|
+
* When no `engine` is injected, `Rater` builds and owns its own
|
|
676
|
+
* quantitative-only engine (`bail: false`) — Rater performs no evaluation
|
|
640
677
|
* arithmetic of its own; it only orchestrates and projects. The
|
|
641
|
-
* array-of-lines `rate` overload is declared
|
|
642
|
-
* resolves to that form. `destroy()` destroys an
|
|
643
|
-
* emitter
|
|
678
|
+
* array-of-lines `rate` overload is declared first so a plain line list
|
|
679
|
+
* resolves to that form. `destroy()` destroys an owned engine, then the
|
|
680
|
+
* emitter last; an injected engine is never destroyed. Afterwards every
|
|
644
681
|
* other method throws {@link RaterError} `'DESTROYED'`.
|
|
645
682
|
*
|
|
646
683
|
* @example
|
|
@@ -735,12 +772,13 @@ var Rater = class {
|
|
|
735
772
|
//#endregion
|
|
736
773
|
//#region src/core/factories.ts
|
|
737
774
|
/**
|
|
738
|
-
* Creates a rating orchestrator
|
|
775
|
+
* Creates a rating orchestrator over the shared quantitative engine, seeded
|
|
776
|
+
* from {@link RaterOptions} and returning a {@link RaterInterface}.
|
|
739
777
|
*
|
|
740
778
|
* @param options - Optional total handler, labels, injected engine, and emitter hooks
|
|
741
779
|
* @returns A {@link RaterInterface}
|
|
742
780
|
*
|
|
743
|
-
* @example
|
|
781
|
+
* @example Create a rater
|
|
744
782
|
* ```ts
|
|
745
783
|
* import { createRater } from '@orkestrel/rater'
|
|
746
784
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["#emitter","#engine","#owned","#total","#labels","#ensureAlive","#normalize","#rateLine","#destroyed","#reasonQuantitative"],"sources":["../../../src/core/errors.ts","../../../src/core/validators.ts","../../../src/core/helpers.ts","../../../src/core/Rater.ts","../../../src/core/factories.ts"],"sourcesContent":["import type { RaterErrorCode } from './types.js'\n\n/**\n * Represents a coded programmer error thrown by the rating layer.\n *\n * @remarks\n * `DEFINITION` — the `rate` input failed both the array-of-lines and rating\n * definition validation. `MISMATCH` — a rated subject is not a record.\n * `DESTROYED` — use of a destroyed entity.\n *\n * @example\n * ```ts\n * import { RaterError } from '@orkestrel/rater'\n *\n * throw new RaterError('MISMATCH', 'Subject must be a record')\n * ```\n */\nexport class RaterError extends Error {\n\treadonly code: RaterErrorCode\n\treadonly context?: Readonly<Record<string, unknown>>\n\n\tconstructor(code: RaterErrorCode, message: string, context?: Readonly<Record<string, unknown>>) {\n\t\tsuper(message)\n\t\tthis.name = 'RaterError'\n\t\tthis.code = code\n\t\tif (context !== undefined) this.context = context\n\t}\n}\n\n/**\n * Narrows a caught value to a {@link RaterError}.\n *\n * @param value - The caught value to test\n * @returns True if `value` is a `RaterError`; false otherwise\n *\n * @example\n * ```ts\n * import { isRaterError, RaterError } from '@orkestrel/rater'\n *\n * try {\n * \tthrow new RaterError('DESTROYED', 'Rater has been destroyed')\n * } catch (error) {\n * \tif (isRaterError(error)) error.code // 'DESTROYED'\n * }\n * ```\n */\nexport function isRaterError(value: unknown): value is RaterError {\n\treturn value instanceof RaterError\n}\n","import type { Guard } from '@orkestrel/contract'\nimport type {\n\tEvidence,\n\tLineDefinition,\n\tLineResult,\n\tRatingDefinition,\n\tRatingResult,\n\tStage,\n\tStep,\n\tWorksheet,\n\tWorksheetFactor,\n\tWorksheetGroup,\n} from './types.js'\nimport {\n\tarrayOf,\n\tisBoolean,\n\tisJSONValue,\n\tisNumber,\n\tisString,\n\tliteralOf,\n\tobjectOf,\n\trecordOf,\n} from '@orkestrel/contract'\nimport {\n\tisAggregation,\n\tisComparison,\n\tisFieldPath,\n\tisQuantitativeDefinition,\n} from '@orkestrel/reason'\n\n/**\n * Determines whether a value is a {@link Stage} literal.\n *\n * @param value - The value to test\n * @returns True if `value` is `'factor'`, `'group'`, or `'total'`; false otherwise\n *\n * @example\n * ```ts\n * import { isStage } from '@orkestrel/rater'\n *\n * isStage('group') // true\n * isStage('step') // false\n * ```\n */\nexport const isStage: Guard<Stage> = literalOf('factor', 'group', 'total')\n\n/**\n * Determines whether a value is an exact {@link LineDefinition} record.\n *\n * @remarks\n * Total guard: adversarial input (cycles, hostile prototypes) returns `false`,\n * never throws. The record shape is EXACT — an extra key fails.\n *\n * @param value - The value to test\n * @returns True if `value` is a `LineDefinition`; false otherwise\n *\n * @example\n * ```ts\n * import { createQuantitativeDefinition } from '@orkestrel/reason'\n * import { isLineDefinition } from '@orkestrel/rater'\n *\n * isLineDefinition({ id: 'base', name: 'Base', rate: createQuantitativeDefinition('base', 'Base', []) }) // true\n * ```\n */\nexport function isLineDefinition(value: unknown): value is LineDefinition {\n\treturn recordOf(\n\t\t{\n\t\t\tid: isString,\n\t\t\tname: isString,\n\t\t\tdescription: isString,\n\t\t\trate: isQuantitativeDefinition,\n\t\t\tmetadata: isJSONValue,\n\t\t},\n\t\t['description', 'metadata'],\n\t)(value)\n}\n\n/**\n * Determines whether a value is an exact {@link RatingDefinition} record.\n *\n * @remarks\n * Total guard: adversarial input (cycles, hostile prototypes) returns `false`,\n * never throws. The record shape is EXACT — an extra key fails.\n *\n * @param value - The value to test\n * @returns True if `value` is a `RatingDefinition`; false otherwise\n *\n * @example\n * ```ts\n * import { isRatingDefinition } from '@orkestrel/rater'\n *\n * isRatingDefinition({ id: 'r1', name: 'Rating', lines: [] }) // true\n * ```\n */\nexport function isRatingDefinition(value: unknown): value is RatingDefinition {\n\treturn recordOf(\n\t\t{\n\t\t\tid: isString,\n\t\t\tname: isString,\n\t\t\tdescription: isString,\n\t\t\tlines: arrayOf(isLineDefinition),\n\t\t\tmetadata: isJSONValue,\n\t\t},\n\t\t['description', 'metadata'],\n\t)(value)\n}\n\n/**\n * Determines whether a value is an open result-side {@link Evidence} object.\n *\n * @remarks\n * Unknown members, prototypes, and class instances are admitted. Arrays are\n * refused. `expected` and `actual` are `unknown`, so this guard does not read or\n * check them; either member may also be absent because `objectOf` reads declared\n * members rather than requiring or enumerating own keys.\n *\n * @param value - The value to test\n * @returns True if every checked `Evidence` member conforms; false otherwise\n *\n * @example\n * ```ts\n * import { isEvidence } from '@orkestrel/rater'\n *\n * isEvidence({ field: 'age', comparison: 'above', expected: 18, actual: 25, met: true }) // true\n * ```\n */\nexport function isEvidence(value: unknown): value is Evidence {\n\treturn objectOf(\n\t\t{\n\t\t\tfield: isFieldPath,\n\t\t\tlabel: isString,\n\t\t\tcomparison: isComparison,\n\t\t\tmet: isBoolean,\n\t\t},\n\t\t['field', 'label', 'comparison', 'met'],\n\t)(value)\n}\n\n/**\n * Determines whether a value is an open {@link WorksheetFactor} result object.\n *\n * @remarks\n * Unknown members, prototypes, and class instances are admitted. Arrays are\n * refused. Optional members may be absent or read as `undefined`.\n *\n * @param value - The value to test\n * @returns True if every published worksheet-factor member conforms; false otherwise\n *\n * @example\n * ```ts\n * import { isWorksheetFactor } from '@orkestrel/rater'\n *\n * isWorksheetFactor({ id: 'base', applied: true, value: 100, evidence: [] }) // true\n * ```\n */\nexport function isWorksheetFactor(value: unknown): value is WorksheetFactor {\n\treturn objectOf(\n\t\t{\n\t\t\tid: isString,\n\t\t\tname: isString,\n\t\t\tdescription: isString,\n\t\t\tapplied: isBoolean,\n\t\t\tvalue: isNumber,\n\t\t\tevidence: arrayOf(isEvidence),\n\t\t},\n\t\t['name', 'description', 'value'],\n\t)(value)\n}\n\n/**\n * Determines whether a value is an open {@link WorksheetGroup} result object.\n *\n * @remarks\n * Unknown members, prototypes, and class instances are admitted. Arrays are\n * refused. Optional members may be absent or read as `undefined`.\n *\n * @param value - The value to test\n * @returns True if every published worksheet-group member conforms; false otherwise\n *\n * @example\n * ```ts\n * import { isWorksheetGroup } from '@orkestrel/rater'\n *\n * isWorksheetGroup({ id: 'charges', applied: true, value: 100, factors: [] }) // true\n * ```\n */\nexport function isWorksheetGroup(value: unknown): value is WorksheetGroup {\n\treturn objectOf(\n\t\t{\n\t\t\tid: isString,\n\t\t\tname: isString,\n\t\t\tdescription: isString,\n\t\t\tapplied: isBoolean,\n\t\t\tvalue: isNumber,\n\t\t\tfactors: arrayOf(isWorksheetFactor),\n\t\t},\n\t\t['name', 'description'],\n\t)(value)\n}\n\n/**\n * Determines whether a value is an open {@link Step} result object.\n *\n * @remarks\n * Unknown members, prototypes, and class instances are admitted. Arrays are\n * refused. Optional members may be absent or read as `undefined`.\n *\n * @param value - The value to test\n * @returns True if every published worksheet-step member conforms; false otherwise\n *\n * @example\n * ```ts\n * import { isStep } from '@orkestrel/rater'\n *\n * isStep({ stage: 'total', value: 100 }) // true\n * ```\n */\nexport function isStep(value: unknown): value is Step {\n\treturn objectOf(\n\t\t{\n\t\t\tstage: isStage,\n\t\t\tid: isString,\n\t\t\tname: isString,\n\t\t\tvalue: isNumber,\n\t\t\texpression: isString,\n\t\t},\n\t\t['id', 'name', 'expression'],\n\t)(value)\n}\n\n/**\n * Determines whether a value is an open {@link Worksheet} result object.\n *\n * @remarks\n * Unknown members, prototypes, and class instances are admitted. Arrays are\n * refused. Optional members may be absent or read as `undefined`.\n *\n * @param value - The value to test\n * @returns True if every published worksheet member conforms; false otherwise\n *\n * @example\n * ```ts\n * import { isWorksheet } from '@orkestrel/rater'\n *\n * isWorksheet({ id: 'quote', name: 'Quote', aggregation: 'sum', value: 0, groups: [], steps: [], trace: [], errors: [], success: true }) // true\n * ```\n */\nexport function isWorksheet(value: unknown): value is Worksheet {\n\treturn objectOf(\n\t\t{\n\t\t\tid: isString,\n\t\t\tname: isString,\n\t\t\taggregation: isAggregation,\n\t\t\tprecision: isNumber,\n\t\t\tvalue: isNumber,\n\t\t\tgroups: arrayOf(isWorksheetGroup),\n\t\t\tsteps: arrayOf(isStep),\n\t\t\ttrace: arrayOf(isString),\n\t\t\terrors: arrayOf(isString),\n\t\t\tsuccess: isBoolean,\n\t\t},\n\t\t['precision'],\n\t)(value)\n}\n\n/**\n * Determines whether a value is an open {@link LineResult} object.\n *\n * @remarks\n * Unknown members, prototypes, and class instances are admitted. Arrays are\n * refused. `amount` may be absent or read as `undefined`; when present it stays\n * a plain JavaScript `number` without a finite or range refinement. The line's\n * outcome lives on `worksheet`, so `worksheet.success` carries it.\n *\n * @param value - The value to test\n * @returns True if every published line-result member conforms; false otherwise\n *\n * @example\n * ```ts\n * import { isLineResult } from '@orkestrel/rater'\n *\n * isLineResult({ id: 'base', name: 'Base', worksheet: { id: 'base', name: 'Base', aggregation: 'sum', value: 0, groups: [], steps: [], trace: [], errors: [], success: false } }) // true\n * ```\n */\nexport function isLineResult(value: unknown): value is LineResult {\n\treturn objectOf(\n\t\t{\n\t\t\tid: isString,\n\t\t\tname: isString,\n\t\t\tamount: isNumber,\n\t\t\tworksheet: isWorksheet,\n\t\t},\n\t\t['amount'],\n\t)(value)\n}\n\n/**\n * Determines whether a value is an open {@link RatingResult} object.\n *\n * @remarks\n * Use this guard for a result returned by a borrowed `RaterInterface`. Unknown\n * members, prototypes, and class instances are admitted. Arrays are refused.\n * `total` may be absent or read as `undefined`; when present it stays a plain\n * JavaScript `number` without a finite or range refinement.\n *\n * @param value - The value to test\n * @returns True if every published rating-result member conforms; false otherwise\n *\n * @example\n * ```ts\n * import { isRatingResult } from '@orkestrel/rater'\n *\n * isRatingResult({ lines: [], success: true }) // true\n * ```\n */\nexport function isRatingResult(value: unknown): value is RatingResult {\n\treturn objectOf(\n\t\t{\n\t\t\tlines: arrayOf(isLineResult),\n\t\t\ttotal: isNumber,\n\t\t\tsuccess: isBoolean,\n\t\t},\n\t\t['total'],\n\t)(value)\n}\n","import type {\n\tCheck,\n\tCheckResult,\n\tFactor,\n\tFactorResult,\n\tGroupResult,\n\tQuantitativeDefinition,\n\tQuantitativeResult,\n} from '@orkestrel/reason'\nimport type {\n\tEvidence,\n\tLineDefinition,\n\tLineResult,\n\tRatingDefinition,\n\tStage,\n\tStep,\n\tWorksheet,\n\tWorksheetFactor,\n\tWorksheetGroup,\n} from './types.js'\nimport { formatField } from '@orkestrel/reason'\n\n/**\n * Builds a {@link LineDefinition}.\n *\n * @param id - The line id\n * @param name - The display name\n * @param rate - The line's quantitative rating definition\n * @param overrides - Optional {@link LineDefinition} fields merged over the defaults\n * @returns A fresh line definition\n *\n * @example\n * ```ts\n * import { createQuantitativeDefinition } from '@orkestrel/reason'\n * import { buildLineDefinition } from '@orkestrel/rater'\n *\n * buildLineDefinition('base', 'Base Amount', createQuantitativeDefinition('base', 'Base', []))\n * ```\n */\nexport function buildLineDefinition(\n\tid: string,\n\tname: string,\n\trate: QuantitativeDefinition,\n\toverrides?: Partial<Omit<LineDefinition, 'id' | 'name' | 'rate'>>,\n): LineDefinition {\n\treturn { id, name, rate, ...overrides }\n}\n\n/**\n * Builds a {@link RatingDefinition}.\n *\n * @param id - The rating id\n * @param name - The display name\n * @param lines - The rating's ordered lines\n * @param overrides - Optional {@link RatingDefinition} fields merged over the defaults\n * @returns A fresh rating definition\n *\n * @example\n * ```ts\n * import { buildLineDefinition, buildRatingDefinition } from '@orkestrel/rater'\n * import { createQuantitativeDefinition } from '@orkestrel/reason'\n *\n * buildRatingDefinition('r1', 'Rating', [\n * \tbuildLineDefinition('base', 'Base Amount', createQuantitativeDefinition('base', 'Base', [])),\n * ])\n * ```\n */\nexport function buildRatingDefinition(\n\tid: string,\n\tname: string,\n\tlines: readonly LineDefinition[],\n\toverrides?: Partial<Omit<RatingDefinition, 'id' | 'name' | 'lines'>>,\n): RatingDefinition {\n\treturn { id, name, lines, ...overrides }\n}\n\n/**\n * Builds an {@link Evidence} row from an evaluated {@link Check}.\n *\n * @param check - The authored check\n * @param actual - The resolved subject value\n * @param met - If `true`, the check was met; if `false`, it was not; absent when the check\n * was not yet evaluated\n * @param labels - Optional field-to-label overrides, keyed by dot-joined field\n * @returns A fresh evidence row\n *\n * @example\n * ```ts\n * import { createCheck } from '@orkestrel/reason'\n * import { buildEvidence } from '@orkestrel/rater'\n *\n * const entry = createCheck('age', 'above', 18)\n * buildEvidence(entry, 25, true) // { field: 'age', comparison: 'above', expected: 18, actual: 25, met: true }\n * ```\n */\nexport function buildEvidence(\n\tcheck: Check,\n\tactual: unknown,\n\tmet: boolean | undefined,\n\tlabels?: Readonly<Record<string, string>>,\n): Evidence {\n\tconst field = formatField(check.field)\n\treturn {\n\t\tfield: check.field,\n\t\t...(labels?.[field] === undefined ? {} : { label: labels[field] }),\n\t\tcomparison: check.operator,\n\t\texpected: check.value,\n\t\tactual,\n\t\t...(met === undefined ? {} : { met }),\n\t}\n}\n\n/**\n * Builds one evidence row per authored check of a quantitative factor, joined\n * to that check's evaluated result.\n *\n * @param checks - The factor's authored checks\n * @param results - The corresponding {@link CheckResult}s, in the same order\n * @param labels - Optional field-to-label overrides, keyed by dot-joined field\n * @returns A fresh list of evidence rows, one per authored check\n *\n * @example\n * ```ts\n * import { createCheck } from '@orkestrel/reason'\n * import { buildEvidenceRows } from '@orkestrel/rater'\n *\n * const checks = [createCheck('age', 'above', 18)]\n * buildEvidenceRows(checks, [{ field: 'age', met: true, actual: 25 }])\n * ```\n */\nexport function buildEvidenceRows(\n\tchecks: readonly Check[] | undefined,\n\tresults: readonly CheckResult[] | undefined,\n\tlabels?: Readonly<Record<string, string>>,\n): readonly Evidence[] {\n\treturn (checks ?? []).map((check, index) => {\n\t\tconst result = results?.[index]\n\t\treturn buildEvidence(check, result?.actual, result?.met, labels)\n\t})\n}\n\n/**\n * Joins one authored quantitative factor to its evaluated {@link FactorResult}.\n *\n * @param definition - The authored factor\n * @param results - The group's factor results\n * @param labels - Optional field-to-label overrides, keyed by dot-joined field\n * @returns A fresh worksheet factor\n *\n * @example\n * ```ts\n * import { createFieldFactor } from '@orkestrel/reason'\n * import { buildWorksheetFactor } from '@orkestrel/rater'\n *\n * const factor = createFieldFactor('seats', 'seats')\n * buildWorksheetFactor(factor, [{ id: 'seats', applied: true, value: 10 }])\n * ```\n */\nexport function buildWorksheetFactor(\n\tdefinition: Factor,\n\tresults: readonly FactorResult[],\n\tlabels?: Readonly<Record<string, string>>,\n): WorksheetFactor {\n\tconst result = results.find((entry) => entry.id === definition.id)\n\treturn {\n\t\tid: definition.id,\n\t\tname: definition.name,\n\t\t...(definition.description === undefined ? {} : { description: definition.description }),\n\t\tapplied: result?.applied ?? false,\n\t\t...(result?.value === undefined ? {} : { value: result.value }),\n\t\tevidence: buildEvidenceRows(definition.checks, result?.checks, labels),\n\t}\n}\n\n/**\n * Joins one authored quantitative group to its evaluated {@link GroupResult}.\n *\n * @param definition - The authored group\n * @param results - The definition's group results\n * @param labels - Optional field-to-label overrides, keyed by dot-joined field\n * @returns A fresh worksheet group\n *\n * @example\n * ```ts\n * import { createFactorGroup, createStaticFactor } from '@orkestrel/reason'\n * import { buildWorksheetGroup } from '@orkestrel/rater'\n *\n * const group = createFactorGroup('charge', 'sum', [createStaticFactor('base', 100)])\n * buildWorksheetGroup(group, [{ id: 'charge', applied: true, value: 100, factors: [] }])\n * ```\n */\nexport function buildWorksheetGroup(\n\tdefinition: QuantitativeDefinition['groups'][number],\n\tresults: readonly GroupResult[],\n\tlabels?: Readonly<Record<string, string>>,\n): WorksheetGroup {\n\tconst result = results.find((entry) => entry.id === definition.id)\n\treturn {\n\t\tid: definition.id,\n\t\tname: definition.name,\n\t\t...(definition.description === undefined ? {} : { description: definition.description }),\n\t\tapplied: result?.applied ?? false,\n\t\tvalue: result?.value ?? 0,\n\t\tfactors: definition.factors.map((factor) =>\n\t\t\tbuildWorksheetFactor(factor, result?.factors ?? [], labels),\n\t\t),\n\t}\n}\n\n/**\n * Builds one display-neutral {@link Step} row.\n *\n * @param stage - The step's stage\n * @param id - The stage's authored id, when it has one\n * @param name - The stage's authored name, when it has one\n * @param value - The stage's resolved value\n * @param expression - A display-neutral expression string\n * @returns A fresh step\n *\n * @example\n * ```ts\n * import { buildWorksheetStep } from '@orkestrel/rater'\n *\n * buildWorksheetStep('total', 'quote', 'Quote', 110, 'sum = 110')\n * // { stage: 'total', id: 'quote', name: 'Quote', value: 110, expression: 'sum = 110' }\n * ```\n */\nexport function buildWorksheetStep(\n\tstage: Stage,\n\tid: string | undefined,\n\tname: string | undefined,\n\tvalue: number,\n\texpression: string,\n): Step {\n\treturn {\n\t\tstage,\n\t\t...(id === undefined ? {} : { id }),\n\t\t...(name === undefined ? {} : { name }),\n\t\tvalue,\n\t\texpression,\n\t}\n}\n\n/**\n * Builds the ordered {@link Step} rows for a resolved {@link Worksheet}.\n *\n * @param definition - The authored quantitative definition\n * @param result - The evaluated quantitative result\n * @param groups - The definition's already-joined worksheet groups\n * @returns A fresh, ordered list of steps: applied factors, then groups, then the total\n *\n * @example\n * ```ts\n * import { createFactorGroup, createQuantitativeDefinition, createQuantitativeReasoner, createReason, createStaticFactor } from '@orkestrel/reason'\n * import { buildWorksheetGroup, buildWorksheetSteps } from '@orkestrel/rater'\n *\n * const definition = createQuantitativeDefinition('base', 'Base', [createFactorGroup('g', 'sum', [createStaticFactor('flat', 100)])])\n * const result = createReason({ reasoners: [createQuantitativeReasoner()] }).reason({}, definition)\n * if (result.reasoning === 'quantitative') {\n * \tbuildWorksheetSteps(definition, result, definition.groups.map((group) => buildWorksheetGroup(group, result.groups)))\n * }\n * ```\n */\nexport function buildWorksheetSteps(\n\tdefinition: QuantitativeDefinition,\n\tresult: QuantitativeResult,\n\tgroups: readonly WorksheetGroup[],\n): readonly Step[] {\n\tconst output: Step[] = []\n\tfor (const group of groups) {\n\t\tfor (const factor of group.factors) {\n\t\t\tif (factor.applied && factor.value !== undefined) {\n\t\t\t\toutput.push(\n\t\t\t\t\tbuildWorksheetStep(\n\t\t\t\t\t\t'factor',\n\t\t\t\t\t\tfactor.id,\n\t\t\t\t\t\tfactor.name,\n\t\t\t\t\t\tfactor.value,\n\t\t\t\t\t\t`${factor.id} = ${factor.value}`,\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t\toutput.push(\n\t\t\tbuildWorksheetStep(\n\t\t\t\t'group',\n\t\t\t\tgroup.id,\n\t\t\t\tgroup.name,\n\t\t\t\tgroup.value,\n\t\t\t\t`${group.id} = ${group.value}`,\n\t\t\t),\n\t\t)\n\t}\n\toutput.push(\n\t\tbuildWorksheetStep(\n\t\t\t'total',\n\t\t\tdefinition.id,\n\t\t\tdefinition.name,\n\t\t\tresult.value,\n\t\t\t`${definition.aggregation} = ${result.value}`,\n\t\t),\n\t)\n\treturn output\n}\n\n/**\n * Joins a {@link QuantitativeDefinition} and its {@link QuantitativeResult} into\n * a {@link Worksheet} — the rating audit trail.\n *\n * @param definition - The authored quantitative definition\n * @param result - The evaluated quantitative result\n * @param labels - Optional field-to-label overrides, keyed by dot-joined field\n * @returns A fresh worksheet\n *\n * @example\n * ```ts\n * import { createFactorGroup, createQuantitativeDefinition, createQuantitativeReasoner, createReason, createStaticFactor } from '@orkestrel/reason'\n * import { buildWorksheet } from '@orkestrel/rater'\n *\n * const definition = createQuantitativeDefinition('base', 'Base', [createFactorGroup('g', 'sum', [createStaticFactor('flat', 100)])])\n * const result = createReason({ reasoners: [createQuantitativeReasoner()] }).reason({}, definition)\n * if (result.reasoning === 'quantitative') buildWorksheet(definition, result) // the full audit trail\n * ```\n */\nexport function buildWorksheet(\n\tdefinition: QuantitativeDefinition,\n\tresult: QuantitativeResult,\n\tlabels?: Readonly<Record<string, string>>,\n): Worksheet {\n\tconst groups = definition.groups.map((group) => buildWorksheetGroup(group, result.groups, labels))\n\treturn {\n\t\tid: definition.id,\n\t\tname: definition.name,\n\t\taggregation: definition.aggregation,\n\t\t...(definition.precision === undefined ? {} : { precision: definition.precision }),\n\t\tvalue: result.value,\n\t\tgroups,\n\t\tsteps: buildWorksheetSteps(definition, result, groups),\n\t\ttrace: result.trace,\n\t\terrors: result.errors,\n\t\tsuccess: result.success,\n\t}\n}\n\n/**\n * Builds a rated {@link LineResult} from a line's evaluated\n * {@link QuantitativeResult}.\n *\n * @param definition - The authored line definition\n * @param result - The evaluated quantitative result\n * @param labels - Optional field-to-label overrides, keyed by dot-joined field\n * @returns A fresh line result\n *\n * @example\n * ```ts\n * import { createQuantitativeDefinition, createQuantitativeReasoner, createReason } from '@orkestrel/reason'\n * import { buildLineDefinition, buildLineResult } from '@orkestrel/rater'\n *\n * const line = buildLineDefinition('base', 'Base', createQuantitativeDefinition('base', 'Base', []))\n * const result = createReason({ reasoners: [createQuantitativeReasoner()] }).reason({}, line.rate)\n * if (result.reasoning === 'quantitative') buildLineResult(line, result) // amount present only on a successful worksheet\n * ```\n */\nexport function buildLineResult(\n\tdefinition: LineDefinition,\n\tresult: QuantitativeResult,\n\tlabels?: Readonly<Record<string, string>>,\n): LineResult {\n\treturn {\n\t\tid: definition.id,\n\t\tname: definition.name,\n\t\t...(result.success ? { amount: result.value } : {}),\n\t\tworksheet: buildWorksheet(definition.rate, result, labels),\n\t}\n}\n\n/**\n * Sums defined line amounts.\n *\n * @param lines - The rated lines\n * @returns The sum of every line's `amount`, or `undefined` when no line has one\n *\n * @example\n * ```ts\n * import { createFactorGroup, createQuantitativeDefinition, createQuantitativeReasoner, createReason, createStaticFactor } from '@orkestrel/reason'\n * import { buildLineDefinition, buildLineResult, sumAmounts } from '@orkestrel/rater'\n *\n * const rate = createQuantitativeDefinition('base', 'Base', [createFactorGroup('g', 'sum', [createStaticFactor('flat', 100)])])\n * const line = buildLineDefinition('base', 'Base', rate)\n * const result = createReason({ reasoners: [createQuantitativeReasoner()] }).reason({}, rate)\n * if (result.reasoning === 'quantitative') sumAmounts([buildLineResult(line, result)]) // 100\n * ```\n */\nexport function sumAmounts(lines: readonly LineResult[]): number | undefined {\n\tlet total = 0\n\tlet count = 0\n\tfor (const rated of lines) {\n\t\tif (rated.amount !== undefined) {\n\t\t\ttotal += rated.amount\n\t\t\tcount += 1\n\t\t}\n\t}\n\treturn count === 0 ? undefined : total\n}\n","import type { EmitterInterface } from '@orkestrel/emitter'\nimport type {\n\tQuantitativeDefinition,\n\tQuantitativeResult,\n\tReasonInterface,\n\tSubject,\n} from '@orkestrel/reason'\nimport type {\n\tLineDefinition,\n\tLineResult,\n\tRaterEventMap,\n\tRaterInterface,\n\tRaterOptions,\n\tRatingDefinition,\n\tRatingResult,\n\tTotalHandler,\n} from './types.js'\nimport { Emitter } from '@orkestrel/emitter'\nimport { arrayOf, isArray, isRecord } from '@orkestrel/contract'\nimport { buildErrorResult, createQuantitativeReasoner, createReason } from '@orkestrel/reason'\nimport { RaterError } from './errors.js'\nimport { buildLineResult, sumAmounts } from './helpers.js'\nimport { isLineDefinition, isRatingDefinition } from './validators.js'\n\n/**\n * Orchestrates rating — owns (or receives) the shared quantitative\n * reasoning engine and projects results into the rating domain vocabulary.\n *\n * @remarks\n * When no `engine` is injected, `Rater` builds and OWNS its own\n * quantitative-only engine (`bail: false`) — Rater performs NO evaluation\n * arithmetic of its own; it only orchestrates and projects. The\n * array-of-lines `rate` overload is declared FIRST so a plain line list\n * resolves to that form. `destroy()` destroys an OWNED engine, then the\n * emitter LAST; an INJECTED engine is never destroyed. Afterwards every\n * other method throws {@link RaterError} `'DESTROYED'`.\n *\n * @example\n * ```ts\n * import { Rater } from '@orkestrel/rater'\n *\n * const rater = new Rater()\n * rater.rate([], { id: 'subject-1' }) // { lines: [], success: true }\n * rater.destroy()\n * ```\n */\nexport class Rater implements RaterInterface {\n\treadonly #emitter: Emitter<RaterEventMap>\n\treadonly #engine: ReasonInterface\n\treadonly #owned: boolean\n\treadonly #total: TotalHandler | undefined\n\treadonly #labels: Readonly<Record<string, string>> | undefined\n\t#destroyed = false\n\n\tconstructor(options?: RaterOptions) {\n\t\tthis.#emitter = new Emitter<RaterEventMap>({\n\t\t\t...(options?.on === undefined ? {} : { on: options.on }),\n\t\t\t...(options?.error === undefined ? {} : { error: options.error }),\n\t\t})\n\t\tif (options?.engine === undefined) {\n\t\t\tthis.#engine = createReason({ reasoners: [createQuantitativeReasoner()], bail: false })\n\t\t\tthis.#owned = true\n\t\t} else {\n\t\t\tthis.#engine = options.engine\n\t\t\tthis.#owned = false\n\t\t}\n\t\tthis.#total = options?.total\n\t\tthis.#labels = options?.labels\n\t}\n\n\tget emitter(): EmitterInterface<RaterEventMap> {\n\t\treturn this.#emitter\n\t}\n\n\t// Array overload first so a plain line list resolves to that form.\n\trate(lines: readonly LineDefinition[], subject: Subject): RatingResult\n\trate(definition: RatingDefinition, subject: Subject): RatingResult\n\trate(input: readonly LineDefinition[] | RatingDefinition, subject: Subject): RatingResult {\n\t\tthis.#ensureAlive()\n\t\tconst lines = this.#normalize(input)\n\t\tif (!isRecord(subject)) throw new RaterError('MISMATCH', 'Subject must be a record')\n\t\tconst results = lines.map((line) => this.#rateLine(line, subject))\n\t\tconst total = (this.#total ?? sumAmounts)(results)\n\t\tconst success = results.every((entry) => entry.worksheet.success)\n\t\tconst result: RatingResult = {\n\t\t\tlines: results,\n\t\t\t...(total === undefined ? {} : { total }),\n\t\t\tsuccess,\n\t\t}\n\t\tthis.#emitter.emit('rate', subject, result)\n\t\treturn result\n\t}\n\n\tdestroy(): void {\n\t\tif (this.#destroyed) return\n\t\tthis.#destroyed = true\n\t\tif (this.#owned) this.#engine.destroy()\n\t\tthis.#emitter.destroy()\n\t}\n\n\t#normalize(input: readonly LineDefinition[] | RatingDefinition): readonly LineDefinition[] {\n\t\tif (arrayOf(isLineDefinition)(input)) return input\n\t\tif (isRatingDefinition(input)) return input.lines\n\t\tthrow new RaterError(\n\t\t\t'DEFINITION',\n\t\t\t'Rating input must be an array of line definitions or a rating definition',\n\t\t)\n\t}\n\n\t#rateLine(line: LineDefinition, subject: Subject): LineResult {\n\t\tconst result = this.#reasonQuantitative(subject, line.rate)\n\t\treturn buildLineResult(line, result, this.#labels)\n\t}\n\n\t// Narrows the engine's tagged ReasonResult union down to a QuantitativeResult\n\t// for a definition the engine is guaranteed (by dispatch-by-reasoning, given\n\t// only the quantitative reasoner is ever registered) to resolve as such — a\n\t// defensive, total fallback rather than an assertion. A nonconforming\n\t// injected engine result missing (or with a non-array) `errors` contributes\n\t// no errors from that side rather than throwing.\n\t#reasonQuantitative(subject: Subject, definition: QuantitativeDefinition): QuantitativeResult {\n\t\tconst result = this.#engine.reason(subject, definition)\n\t\tif (result.reasoning === 'quantitative') return result\n\t\tconst failure = buildErrorResult(\n\t\t\tdefinition,\n\t\t\t`Expected quantitative result, got ${result.reasoning}`,\n\t\t)\n\t\tconst errors = [...(isArray<string>(result.errors) ? result.errors : []), ...failure.errors]\n\t\tif (failure.reasoning === 'quantitative') return { ...failure, errors }\n\t\treturn {\n\t\t\treasoning: 'quantitative',\n\t\t\tvalue: 0,\n\t\t\tgroups: [],\n\t\t\tcount: 0,\n\t\t\tsuccess: false,\n\t\t\ttrace: [],\n\t\t\terrors,\n\t\t}\n\t}\n\n\t#ensureAlive(): void {\n\t\tif (this.#destroyed) throw new RaterError('DESTROYED', 'Rater has been destroyed')\n\t}\n}\n","import type { RaterInterface, RaterOptions } from './types.js'\nimport { Rater } from './Rater.js'\n\n/**\n * Creates a rating orchestrator.\n *\n * @param options - Optional total handler, labels, injected engine, and emitter hooks\n * @returns A {@link RaterInterface}\n *\n * @example\n * ```ts\n * import { createRater } from '@orkestrel/rater'\n *\n * const rater = createRater()\n * rater.destroy()\n * ```\n */\nexport function createRater(options?: RaterOptions): RaterInterface {\n\treturn new Rater(options)\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/core/errors.ts","../../../src/core/validators.ts","../../../src/core/helpers.ts","../../../src/core/Rater.ts","../../../src/core/factories.ts"],"sourcesContent":["import type { RaterErrorCode } from './types.js'\n\n/**\n * Represents a coded programmer error thrown by the rating layer.\n *\n * @remarks\n * `DEFINITION` — the `rate` input failed both the array-of-lines and rating\n * definition validation. `MISMATCH` — a rated subject is not a record.\n * `DESTROYED` — use of a destroyed entity. `context` carries optional\n * structured detail beside the message.\n *\n * @example\n * ```ts\n * import { RaterError } from '@orkestrel/rater'\n *\n * throw new RaterError('MISMATCH', 'Subject must be a record')\n * ```\n */\nexport class RaterError extends Error {\n\treadonly code: RaterErrorCode\n\treadonly context?: Readonly<Record<string, unknown>>\n\n\tconstructor(code: RaterErrorCode, message: string, context?: Readonly<Record<string, unknown>>) {\n\t\tsuper(message)\n\t\tthis.name = 'RaterError'\n\t\tthis.code = code\n\t\tif (context !== undefined) this.context = context\n\t}\n}\n\n/**\n * Narrows a caught value to a {@link RaterError}.\n *\n * @param value - The caught value to test\n * @returns True if `value` is a `RaterError`; false otherwise\n *\n * @example\n * ```ts\n * import { isRaterError, RaterError } from '@orkestrel/rater'\n *\n * try {\n * \tthrow new RaterError('DESTROYED', 'Rater has been destroyed')\n * } catch (error) {\n * \tif (isRaterError(error)) error.code // 'DESTROYED'\n * }\n * ```\n */\nexport function isRaterError(value: unknown): value is RaterError {\n\treturn value instanceof RaterError\n}\n","import type { Guard } from '@orkestrel/contract'\nimport type {\n\tEvidence,\n\tLineDefinition,\n\tLineResult,\n\tRatingDefinition,\n\tRatingResult,\n\tStage,\n\tStep,\n\tWorksheet,\n\tWorksheetFactor,\n\tWorksheetGroup,\n} from './types.js'\nimport {\n\tarrayOf,\n\tisBoolean,\n\tisJSONValue,\n\tisNumber,\n\tisString,\n\tliteralOf,\n\tobjectOf,\n\trecordOf,\n} from '@orkestrel/contract'\nimport {\n\tisAggregation,\n\tisComparison,\n\tisFieldPath,\n\tisQuantitativeDefinition,\n} from '@orkestrel/reason'\n\n/**\n * Determines whether a value is a {@link Stage} literal.\n *\n * @remarks\n * A scalar union has no open or exact axis, so this guard accepts one of the\n * `Stage` literals and leaves nothing unchecked.\n *\n * @param value - The value to test\n * @returns True if `value` is `'factor'`, `'group'`, or `'total'`; false otherwise\n *\n * @example\n * ```ts\n * import { isStage } from '@orkestrel/rater'\n *\n * isStage('group') // true\n * isStage('step') // false\n * ```\n */\nexport const isStage: Guard<Stage> = literalOf('factor', 'group', 'total')\n\n/**\n * Determines whether a value is an exact {@link LineDefinition} record.\n *\n * @remarks\n * Every `LineDefinition` member is checked, including its quantitative\n * definition. Total guard: adversarial input (cycles, hostile prototypes)\n * returns `false`, never throws. The record shape is exact — this package owns\n * the authored input record, so an extra key fails and nothing is left\n * unchecked.\n *\n * @param value - The value to test\n * @returns True if `value` is a `LineDefinition`; false otherwise\n *\n * @example\n * ```ts\n * import { createQuantitativeDefinition } from '@orkestrel/reason'\n * import { isLineDefinition } from '@orkestrel/rater'\n *\n * isLineDefinition({ id: 'base', name: 'Base', rate: createQuantitativeDefinition('base', 'Base', []) }) // true\n * ```\n */\nexport function isLineDefinition(value: unknown): value is LineDefinition {\n\treturn recordOf(\n\t\t{\n\t\t\tid: isString,\n\t\t\tname: isString,\n\t\t\tdescription: isString,\n\t\t\trate: isQuantitativeDefinition,\n\t\t\tmetadata: isJSONValue,\n\t\t},\n\t\t['description', 'metadata'],\n\t)(value)\n}\n\n/**\n * Determines whether a value is an exact {@link RatingDefinition} record.\n *\n * @remarks\n * Every `RatingDefinition` member is checked, including each nested line\n * definition. Total guard: adversarial input (cycles, hostile prototypes)\n * returns `false`, never throws. The record shape is exact — this package owns\n * the authored input record, so an extra key fails and nothing is left\n * unchecked.\n *\n * @param value - The value to test\n * @returns True if `value` is a `RatingDefinition`; false otherwise\n *\n * @example\n * ```ts\n * import { isRatingDefinition } from '@orkestrel/rater'\n *\n * isRatingDefinition({ id: 'r1', name: 'Rating', lines: [] }) // true\n * ```\n */\nexport function isRatingDefinition(value: unknown): value is RatingDefinition {\n\treturn recordOf(\n\t\t{\n\t\t\tid: isString,\n\t\t\tname: isString,\n\t\t\tdescription: isString,\n\t\t\tlines: arrayOf(isLineDefinition),\n\t\t\tmetadata: isJSONValue,\n\t\t},\n\t\t['description', 'metadata'],\n\t)(value)\n}\n\n/**\n * Determines whether a value is an open result-side {@link Evidence} object.\n *\n * @remarks\n * Optional `field` is checked as a `FieldPath`, `label` as a string,\n * `comparison` as a `Comparison`, and `met` as a boolean, each when defined.\n * Unknown members, prototypes, and class instances are admitted. Arrays are\n * refused. `expected` and `actual` are `unknown`, so this guard does not read or\n * check them and a borrowed result is never narrowed on them; either member may\n * also be absent because `objectOf` reads declared members rather than\n * requiring or enumerating own keys.\n *\n * @param value - The value to test\n * @returns True if every checked `Evidence` member conforms; false otherwise\n *\n * @example\n * ```ts\n * import { isEvidence } from '@orkestrel/rater'\n *\n * isEvidence({ field: 'age', comparison: 'above', expected: 18, actual: 25, met: true }) // true\n * ```\n */\nexport function isEvidence(value: unknown): value is Evidence {\n\treturn objectOf(\n\t\t{\n\t\t\tfield: isFieldPath,\n\t\t\tlabel: isString,\n\t\t\tcomparison: isComparison,\n\t\t\tmet: isBoolean,\n\t\t},\n\t\t['field', 'label', 'comparison', 'met'],\n\t)(value)\n}\n\n/**\n * Determines whether a value is an open {@link WorksheetFactor} result object.\n *\n * @remarks\n * `id`, the optional authored text, `applied`, an optional plain-number\n * `value`, and each `Evidence` entry are checked. Unknown members, prototypes,\n * and class instances are admitted and left unchecked, because a borrowed\n * result implementation may add them. Arrays are refused. Optional members may\n * be absent or read as `undefined`.\n *\n * @param value - The value to test\n * @returns True if every published worksheet-factor member conforms; false otherwise\n *\n * @example\n * ```ts\n * import { isWorksheetFactor } from '@orkestrel/rater'\n *\n * isWorksheetFactor({ id: 'base', applied: true, value: 100, evidence: [] }) // true\n * ```\n */\nexport function isWorksheetFactor(value: unknown): value is WorksheetFactor {\n\treturn objectOf(\n\t\t{\n\t\t\tid: isString,\n\t\t\tname: isString,\n\t\t\tdescription: isString,\n\t\t\tapplied: isBoolean,\n\t\t\tvalue: isNumber,\n\t\t\tevidence: arrayOf(isEvidence),\n\t\t},\n\t\t['name', 'description', 'value'],\n\t)(value)\n}\n\n/**\n * Determines whether a value is an open {@link WorksheetGroup} result object.\n *\n * @remarks\n * `id`, the optional authored text, `applied`, a plain-number `value`, and each\n * `WorksheetFactor` entry are checked. Unknown members, prototypes, and class\n * instances are admitted and left unchecked, because a borrowed result\n * implementation may add them. Arrays are refused. Optional members may be\n * absent or read as `undefined`.\n *\n * @param value - The value to test\n * @returns True if every published worksheet-group member conforms; false otherwise\n *\n * @example\n * ```ts\n * import { isWorksheetGroup } from '@orkestrel/rater'\n *\n * isWorksheetGroup({ id: 'charges', applied: true, value: 100, factors: [] }) // true\n * ```\n */\nexport function isWorksheetGroup(value: unknown): value is WorksheetGroup {\n\treturn objectOf(\n\t\t{\n\t\t\tid: isString,\n\t\t\tname: isString,\n\t\t\tdescription: isString,\n\t\t\tapplied: isBoolean,\n\t\t\tvalue: isNumber,\n\t\t\tfactors: arrayOf(isWorksheetFactor),\n\t\t},\n\t\t['name', 'description'],\n\t)(value)\n}\n\n/**\n * Determines whether a value is an open {@link Step} result object.\n *\n * @remarks\n * `stage` is checked through `isStage`, `id`, `name`, and `expression` when\n * defined, and `value` as a plain number. Unknown members, prototypes, and\n * class instances are admitted and left unchecked, because a borrowed result\n * implementation may add them. Arrays are refused. Optional members may be\n * absent or read as `undefined`.\n *\n * @param value - The value to test\n * @returns True if every published worksheet-step member conforms; false otherwise\n *\n * @example\n * ```ts\n * import { isStep } from '@orkestrel/rater'\n *\n * isStep({ stage: 'total', value: 100 }) // true\n * ```\n */\nexport function isStep(value: unknown): value is Step {\n\treturn objectOf(\n\t\t{\n\t\t\tstage: isStage,\n\t\t\tid: isString,\n\t\t\tname: isString,\n\t\t\tvalue: isNumber,\n\t\t\texpression: isString,\n\t\t},\n\t\t['id', 'name', 'expression'],\n\t)(value)\n}\n\n/**\n * Determines whether a value is an open {@link Worksheet} result object.\n *\n * @remarks\n * Identity, `aggregation` through reason's `isAggregation`, an optional\n * plain-number `precision`, a plain-number `value`, the nested groups and steps,\n * `trace`, `errors`, and `success` are checked. Unknown members, prototypes, and\n * class instances are admitted and left unchecked, because a borrowed result\n * implementation may add them. Arrays are refused. Optional members may be\n * absent or read as `undefined`.\n *\n * @param value - The value to test\n * @returns True if every published worksheet member conforms; false otherwise\n *\n * @example\n * ```ts\n * import { isWorksheet } from '@orkestrel/rater'\n *\n * isWorksheet({ id: 'quote', name: 'Quote', aggregation: 'sum', value: 0, groups: [], steps: [], trace: [], errors: [], success: true }) // true\n * ```\n */\nexport function isWorksheet(value: unknown): value is Worksheet {\n\treturn objectOf(\n\t\t{\n\t\t\tid: isString,\n\t\t\tname: isString,\n\t\t\taggregation: isAggregation,\n\t\t\tprecision: isNumber,\n\t\t\tvalue: isNumber,\n\t\t\tgroups: arrayOf(isWorksheetGroup),\n\t\t\tsteps: arrayOf(isStep),\n\t\t\ttrace: arrayOf(isString),\n\t\t\terrors: arrayOf(isString),\n\t\t\tsuccess: isBoolean,\n\t\t},\n\t\t['precision'],\n\t)(value)\n}\n\n/**\n * Determines whether a value is an open {@link LineResult} object.\n *\n * @remarks\n * Identity, an optional plain-number `amount`, and the nested `Worksheet` that\n * carries the line's outcome are checked. Unknown members, prototypes, and\n * class instances are admitted and left unchecked, because a borrowed result\n * implementation may add them, and so is the relationship between `amount` and\n * `worksheet.success`, which the published interface types independently.\n * Arrays are refused. `amount` may be absent or read as `undefined`; when\n * present it stays a plain JavaScript `number` without a finite or range\n * refinement.\n *\n * @param value - The value to test\n * @returns True if every published line-result member conforms; false otherwise\n *\n * @example\n * ```ts\n * import { isLineResult } from '@orkestrel/rater'\n *\n * isLineResult({ id: 'base', name: 'Base', worksheet: { id: 'base', name: 'Base', aggregation: 'sum', value: 0, groups: [], steps: [], trace: [], errors: [], success: false } }) // true\n * ```\n */\nexport function isLineResult(value: unknown): value is LineResult {\n\treturn objectOf(\n\t\t{\n\t\t\tid: isString,\n\t\t\tname: isString,\n\t\t\tamount: isNumber,\n\t\t\tworksheet: isWorksheet,\n\t\t},\n\t\t['amount'],\n\t)(value)\n}\n\n/**\n * Determines whether a value is an open {@link RatingResult} object.\n *\n * @remarks\n * Use this guard for a result returned by a borrowed `RaterInterface`. Every\n * nested `LineResult`, an optional plain-number `total`, and a boolean `success`\n * are checked. Unknown members, prototypes, and class instances are admitted and\n * left unchecked, and so are the relationships among totals, lines, and success,\n * because the borrowed interface publishes only their member types. Arrays are\n * refused. `total` may be absent or read as `undefined`; when present it stays a\n * plain JavaScript `number` without a finite or range refinement.\n *\n * @param value - The value to test\n * @returns True if every published rating-result member conforms; false otherwise\n *\n * @example\n * ```ts\n * import { isRatingResult } from '@orkestrel/rater'\n *\n * isRatingResult({ lines: [], success: true }) // true\n * ```\n */\nexport function isRatingResult(value: unknown): value is RatingResult {\n\treturn objectOf(\n\t\t{\n\t\t\tlines: arrayOf(isLineResult),\n\t\t\ttotal: isNumber,\n\t\t\tsuccess: isBoolean,\n\t\t},\n\t\t['total'],\n\t)(value)\n}\n","import type {\n\tCheck,\n\tCheckResult,\n\tFactor,\n\tFactorResult,\n\tGroupResult,\n\tQuantitativeDefinition,\n\tQuantitativeResult,\n} from '@orkestrel/reason'\nimport type {\n\tEvidence,\n\tLineDefinition,\n\tLineResult,\n\tRatingDefinition,\n\tStage,\n\tStep,\n\tWorksheet,\n\tWorksheetFactor,\n\tWorksheetGroup,\n} from './types.js'\nimport { formatField } from '@orkestrel/reason'\n\n/**\n * Builds a fresh {@link LineDefinition} from a line id, a display name, and the\n * line's quantitative rating definition, with `overrides` merged over those\n * defaults.\n *\n * @param id - The line id\n * @param name - The display name\n * @param rate - The line's quantitative rating definition\n * @param overrides - Optional {@link LineDefinition} fields merged over the defaults\n * @returns A fresh line definition\n *\n * @example\n * ```ts\n * import { createQuantitativeDefinition } from '@orkestrel/reason'\n * import { buildLineDefinition } from '@orkestrel/rater'\n *\n * buildLineDefinition('base', 'Base Amount', createQuantitativeDefinition('base', 'Base', []))\n * ```\n */\nexport function buildLineDefinition(\n\tid: string,\n\tname: string,\n\trate: QuantitativeDefinition,\n\toverrides?: Partial<Omit<LineDefinition, 'id' | 'name' | 'rate'>>,\n): LineDefinition {\n\treturn { id, name, rate, ...overrides }\n}\n\n/**\n * Builds a fresh {@link RatingDefinition} from a rating id, a display name, and\n * the rating's ordered lines, with `overrides` merged over those defaults.\n *\n * @param id - The rating id\n * @param name - The display name\n * @param lines - The rating's ordered lines\n * @param overrides - Optional {@link RatingDefinition} fields merged over the defaults\n * @returns A fresh rating definition\n *\n * @example\n * ```ts\n * import { buildLineDefinition, buildRatingDefinition } from '@orkestrel/rater'\n * import { createQuantitativeDefinition } from '@orkestrel/reason'\n *\n * buildRatingDefinition('r1', 'Rating', [\n * \tbuildLineDefinition('base', 'Base Amount', createQuantitativeDefinition('base', 'Base', [])),\n * ])\n * ```\n */\nexport function buildRatingDefinition(\n\tid: string,\n\tname: string,\n\tlines: readonly LineDefinition[],\n\toverrides?: Partial<Omit<RatingDefinition, 'id' | 'name' | 'lines'>>,\n): RatingDefinition {\n\treturn { id, name, lines, ...overrides }\n}\n\n/**\n * Builds an {@link Evidence} row from an evaluated {@link Check}.\n *\n * @param check - The authored check\n * @param actual - The resolved subject value\n * @param met - If `true`, the check was met; if `false`, it was not; absent when the check\n * was not yet evaluated\n * @param labels - Optional field-to-label overrides, keyed by dot-joined field\n * @returns A fresh evidence row\n *\n * @example\n * ```ts\n * import { createCheck } from '@orkestrel/reason'\n * import { buildEvidence } from '@orkestrel/rater'\n *\n * const entry = createCheck('age', 'above', 18)\n * buildEvidence(entry, 25, true) // { field: 'age', comparison: 'above', expected: 18, actual: 25, met: true }\n * ```\n */\nexport function buildEvidence(\n\tcheck: Check,\n\tactual: unknown,\n\tmet: boolean | undefined,\n\tlabels?: Readonly<Record<string, string>>,\n): Evidence {\n\tconst field = formatField(check.field)\n\treturn {\n\t\tfield: check.field,\n\t\t...(labels?.[field] === undefined ? {} : { label: labels[field] }),\n\t\tcomparison: check.operator,\n\t\texpected: check.value,\n\t\tactual,\n\t\t...(met === undefined ? {} : { met }),\n\t}\n}\n\n/**\n * Builds one evidence row per authored check of a quantitative factor, joined\n * to that check's evaluated result.\n *\n * @param checks - The factor's authored checks\n * @param results - The corresponding {@link CheckResult}s, in the same order\n * @param labels - Optional field-to-label overrides, keyed by dot-joined field\n * @returns A fresh list of evidence rows, one per authored check\n *\n * @example\n * ```ts\n * import { createCheck } from '@orkestrel/reason'\n * import { buildEvidenceRows } from '@orkestrel/rater'\n *\n * const checks = [createCheck('age', 'above', 18)]\n * buildEvidenceRows(checks, [{ field: 'age', met: true, actual: 25 }])\n * ```\n */\nexport function buildEvidenceRows(\n\tchecks: readonly Check[] | undefined,\n\tresults: readonly CheckResult[] | undefined,\n\tlabels?: Readonly<Record<string, string>>,\n): readonly Evidence[] {\n\treturn (checks ?? []).map((check, index) => {\n\t\tconst result = results?.[index]\n\t\treturn buildEvidence(check, result?.actual, result?.met, labels)\n\t})\n}\n\n/**\n * Joins one authored quantitative factor to its evaluated {@link FactorResult}.\n *\n * @param definition - The authored factor\n * @param results - The group's factor results\n * @param labels - Optional field-to-label overrides, keyed by dot-joined field\n * @returns A fresh worksheet factor\n *\n * @example\n * ```ts\n * import { createFieldFactor } from '@orkestrel/reason'\n * import { buildWorksheetFactor } from '@orkestrel/rater'\n *\n * const factor = createFieldFactor('seats', 'seats')\n * buildWorksheetFactor(factor, [{ id: 'seats', applied: true, value: 10 }])\n * ```\n */\nexport function buildWorksheetFactor(\n\tdefinition: Factor,\n\tresults: readonly FactorResult[],\n\tlabels?: Readonly<Record<string, string>>,\n): WorksheetFactor {\n\tconst result = results.find((entry) => entry.id === definition.id)\n\treturn {\n\t\tid: definition.id,\n\t\tname: definition.name,\n\t\t...(definition.description === undefined ? {} : { description: definition.description }),\n\t\tapplied: result?.applied ?? false,\n\t\t...(result?.value === undefined ? {} : { value: result.value }),\n\t\tevidence: buildEvidenceRows(definition.checks, result?.checks, labels),\n\t}\n}\n\n/**\n * Joins one authored quantitative group to its evaluated {@link GroupResult}.\n *\n * @param definition - The authored group\n * @param results - The definition's group results\n * @param labels - Optional field-to-label overrides, keyed by dot-joined field\n * @returns A fresh worksheet group\n *\n * @example\n * ```ts\n * import { createFactorGroup, createStaticFactor } from '@orkestrel/reason'\n * import { buildWorksheetGroup } from '@orkestrel/rater'\n *\n * const group = createFactorGroup('charge', 'sum', [createStaticFactor('base', 100)])\n * buildWorksheetGroup(group, [{ id: 'charge', applied: true, value: 100, factors: [] }])\n * ```\n */\nexport function buildWorksheetGroup(\n\tdefinition: QuantitativeDefinition['groups'][number],\n\tresults: readonly GroupResult[],\n\tlabels?: Readonly<Record<string, string>>,\n): WorksheetGroup {\n\tconst result = results.find((entry) => entry.id === definition.id)\n\treturn {\n\t\tid: definition.id,\n\t\tname: definition.name,\n\t\t...(definition.description === undefined ? {} : { description: definition.description }),\n\t\tapplied: result?.applied ?? false,\n\t\tvalue: result?.value ?? 0,\n\t\tfactors: definition.factors.map((factor) =>\n\t\t\tbuildWorksheetFactor(factor, result?.factors ?? [], labels),\n\t\t),\n\t}\n}\n\n/**\n * Builds one display-neutral {@link Step} row.\n *\n * @param stage - The step's stage\n * @param id - The stage's authored id, when it has one\n * @param name - The stage's authored name, when it has one\n * @param value - The stage's resolved value\n * @param expression - A display-neutral expression string\n * @returns A fresh step\n *\n * @example\n * ```ts\n * import { buildWorksheetStep } from '@orkestrel/rater'\n *\n * buildWorksheetStep('total', 'quote', 'Quote', 110, 'sum = 110')\n * // { stage: 'total', id: 'quote', name: 'Quote', value: 110, expression: 'sum = 110' }\n * ```\n */\nexport function buildWorksheetStep(\n\tstage: Stage,\n\tid: string | undefined,\n\tname: string | undefined,\n\tvalue: number,\n\texpression: string,\n): Step {\n\treturn {\n\t\tstage,\n\t\t...(id === undefined ? {} : { id }),\n\t\t...(name === undefined ? {} : { name }),\n\t\tvalue,\n\t\texpression,\n\t}\n}\n\n/**\n * Builds the ordered {@link Step} rows for a resolved {@link Worksheet}.\n *\n * @param definition - The authored quantitative definition\n * @param result - The evaluated quantitative result\n * @param groups - The definition's already-joined worksheet groups\n * @returns A fresh, ordered list of steps: applied factors, then groups, then the total\n *\n * @example\n * ```ts\n * import { createFactorGroup, createQuantitativeDefinition, createQuantitativeReasoner, createReason, createStaticFactor } from '@orkestrel/reason'\n * import { buildWorksheetGroup, buildWorksheetSteps } from '@orkestrel/rater'\n *\n * const definition = createQuantitativeDefinition('base', 'Base', [createFactorGroup('g', 'sum', [createStaticFactor('flat', 100)])])\n * const result = createReason({ reasoners: [createQuantitativeReasoner()] }).reason({}, definition)\n * if (result.reasoning === 'quantitative') {\n * \tbuildWorksheetSteps(definition, result, definition.groups.map((group) => buildWorksheetGroup(group, result.groups)))\n * }\n * ```\n */\nexport function buildWorksheetSteps(\n\tdefinition: QuantitativeDefinition,\n\tresult: QuantitativeResult,\n\tgroups: readonly WorksheetGroup[],\n): readonly Step[] {\n\tconst output: Step[] = []\n\tfor (const group of groups) {\n\t\tfor (const factor of group.factors) {\n\t\t\tif (factor.applied && factor.value !== undefined) {\n\t\t\t\toutput.push(\n\t\t\t\t\tbuildWorksheetStep(\n\t\t\t\t\t\t'factor',\n\t\t\t\t\t\tfactor.id,\n\t\t\t\t\t\tfactor.name,\n\t\t\t\t\t\tfactor.value,\n\t\t\t\t\t\t`${factor.id} = ${factor.value}`,\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t\toutput.push(\n\t\t\tbuildWorksheetStep(\n\t\t\t\t'group',\n\t\t\t\tgroup.id,\n\t\t\t\tgroup.name,\n\t\t\t\tgroup.value,\n\t\t\t\t`${group.id} = ${group.value}`,\n\t\t\t),\n\t\t)\n\t}\n\toutput.push(\n\t\tbuildWorksheetStep(\n\t\t\t'total',\n\t\t\tdefinition.id,\n\t\t\tdefinition.name,\n\t\t\tresult.value,\n\t\t\t`${definition.aggregation} = ${result.value}`,\n\t\t),\n\t)\n\treturn output\n}\n\n/**\n * Joins a {@link QuantitativeDefinition} and its {@link QuantitativeResult} into\n * a {@link Worksheet} — the rating audit trail.\n *\n * @param definition - The authored quantitative definition\n * @param result - The evaluated quantitative result\n * @param labels - Optional field-to-label overrides, keyed by dot-joined field\n * @returns A fresh worksheet\n *\n * @example\n * ```ts\n * import { createFactorGroup, createQuantitativeDefinition, createQuantitativeReasoner, createReason, createStaticFactor } from '@orkestrel/reason'\n * import { buildWorksheet } from '@orkestrel/rater'\n *\n * const definition = createQuantitativeDefinition('base', 'Base', [createFactorGroup('g', 'sum', [createStaticFactor('flat', 100)])])\n * const result = createReason({ reasoners: [createQuantitativeReasoner()] }).reason({}, definition)\n * if (result.reasoning === 'quantitative') buildWorksheet(definition, result) // the full audit trail\n * ```\n */\nexport function buildWorksheet(\n\tdefinition: QuantitativeDefinition,\n\tresult: QuantitativeResult,\n\tlabels?: Readonly<Record<string, string>>,\n): Worksheet {\n\tconst groups = definition.groups.map((group) => buildWorksheetGroup(group, result.groups, labels))\n\treturn {\n\t\tid: definition.id,\n\t\tname: definition.name,\n\t\taggregation: definition.aggregation,\n\t\t...(definition.precision === undefined ? {} : { precision: definition.precision }),\n\t\tvalue: result.value,\n\t\tgroups,\n\t\tsteps: buildWorksheetSteps(definition, result, groups),\n\t\ttrace: result.trace,\n\t\terrors: result.errors,\n\t\tsuccess: result.success,\n\t}\n}\n\n/**\n * Builds a rated {@link LineResult} from a line's evaluated\n * {@link QuantitativeResult}.\n *\n * @param definition - The authored line definition\n * @param result - The evaluated quantitative result\n * @param labels - Optional field-to-label overrides, keyed by dot-joined field\n * @returns A fresh line result\n *\n * @example\n * ```ts\n * import { createQuantitativeDefinition, createQuantitativeReasoner, createReason } from '@orkestrel/reason'\n * import { buildLineDefinition, buildLineResult } from '@orkestrel/rater'\n *\n * const line = buildLineDefinition('base', 'Base', createQuantitativeDefinition('base', 'Base', []))\n * const result = createReason({ reasoners: [createQuantitativeReasoner()] }).reason({}, line.rate)\n * if (result.reasoning === 'quantitative') buildLineResult(line, result) // amount present only on a successful worksheet\n * ```\n */\nexport function buildLineResult(\n\tdefinition: LineDefinition,\n\tresult: QuantitativeResult,\n\tlabels?: Readonly<Record<string, string>>,\n): LineResult {\n\treturn {\n\t\tid: definition.id,\n\t\tname: definition.name,\n\t\t...(result.success ? { amount: result.value } : {}),\n\t\tworksheet: buildWorksheet(definition.rate, result, labels),\n\t}\n}\n\n/**\n * Sums defined line amounts.\n *\n * @param lines - The rated lines\n * @returns The sum of every line's `amount`, or `undefined` when no line has one\n *\n * @example\n * ```ts\n * import { createFactorGroup, createQuantitativeDefinition, createQuantitativeReasoner, createReason, createStaticFactor } from '@orkestrel/reason'\n * import { buildLineDefinition, buildLineResult, sumAmounts } from '@orkestrel/rater'\n *\n * const rate = createQuantitativeDefinition('base', 'Base', [createFactorGroup('g', 'sum', [createStaticFactor('flat', 100)])])\n * const line = buildLineDefinition('base', 'Base', rate)\n * const result = createReason({ reasoners: [createQuantitativeReasoner()] }).reason({}, rate)\n * if (result.reasoning === 'quantitative') sumAmounts([buildLineResult(line, result)]) // 100\n * ```\n */\nexport function sumAmounts(lines: readonly LineResult[]): number | undefined {\n\tlet total = 0\n\tlet count = 0\n\tfor (const rated of lines) {\n\t\tif (rated.amount !== undefined) {\n\t\t\ttotal += rated.amount\n\t\t\tcount += 1\n\t\t}\n\t}\n\treturn count === 0 ? undefined : total\n}\n","import type { EmitterInterface } from '@orkestrel/emitter'\nimport type {\n\tQuantitativeDefinition,\n\tQuantitativeResult,\n\tReasonInterface,\n\tSubject,\n} from '@orkestrel/reason'\nimport type {\n\tLineDefinition,\n\tLineResult,\n\tRaterEventMap,\n\tRaterInterface,\n\tRaterOptions,\n\tRatingDefinition,\n\tRatingResult,\n\tTotalHandler,\n} from './types.js'\nimport { Emitter } from '@orkestrel/emitter'\nimport { arrayOf, isArray, isRecord } from '@orkestrel/contract'\nimport { buildErrorResult, createQuantitativeReasoner, createReason } from '@orkestrel/reason'\nimport { RaterError } from './errors.js'\nimport { buildLineResult, sumAmounts } from './helpers.js'\nimport { isLineDefinition, isRatingDefinition } from './validators.js'\n\n/**\n * Orchestrates rating — owns (or receives) the shared quantitative\n * reasoning engine and projects results into the rating domain vocabulary.\n *\n * @remarks\n * When no `engine` is injected, `Rater` builds and owns its own\n * quantitative-only engine (`bail: false`) — Rater performs no evaluation\n * arithmetic of its own; it only orchestrates and projects. The\n * array-of-lines `rate` overload is declared first so a plain line list\n * resolves to that form. `destroy()` destroys an owned engine, then the\n * emitter last; an injected engine is never destroyed. Afterwards every\n * other method throws {@link RaterError} `'DESTROYED'`.\n *\n * @example\n * ```ts\n * import { Rater } from '@orkestrel/rater'\n *\n * const rater = new Rater()\n * rater.rate([], { id: 'subject-1' }) // { lines: [], success: true }\n * rater.destroy()\n * ```\n */\nexport class Rater implements RaterInterface {\n\treadonly #emitter: Emitter<RaterEventMap>\n\treadonly #engine: ReasonInterface\n\treadonly #owned: boolean\n\treadonly #total: TotalHandler | undefined\n\treadonly #labels: Readonly<Record<string, string>> | undefined\n\t#destroyed = false\n\n\tconstructor(options?: RaterOptions) {\n\t\tthis.#emitter = new Emitter<RaterEventMap>({\n\t\t\t...(options?.on === undefined ? {} : { on: options.on }),\n\t\t\t...(options?.error === undefined ? {} : { error: options.error }),\n\t\t})\n\t\tif (options?.engine === undefined) {\n\t\t\tthis.#engine = createReason({ reasoners: [createQuantitativeReasoner()], bail: false })\n\t\t\tthis.#owned = true\n\t\t} else {\n\t\t\tthis.#engine = options.engine\n\t\t\tthis.#owned = false\n\t\t}\n\t\tthis.#total = options?.total\n\t\tthis.#labels = options?.labels\n\t}\n\n\tget emitter(): EmitterInterface<RaterEventMap> {\n\t\treturn this.#emitter\n\t}\n\n\t// Array overload first so a plain line list resolves to that form.\n\trate(lines: readonly LineDefinition[], subject: Subject): RatingResult\n\trate(definition: RatingDefinition, subject: Subject): RatingResult\n\trate(input: readonly LineDefinition[] | RatingDefinition, subject: Subject): RatingResult {\n\t\tthis.#ensureAlive()\n\t\tconst lines = this.#normalize(input)\n\t\tif (!isRecord(subject)) throw new RaterError('MISMATCH', 'Subject must be a record')\n\t\tconst results = lines.map((line) => this.#rateLine(line, subject))\n\t\tconst total = (this.#total ?? sumAmounts)(results)\n\t\tconst success = results.every((entry) => entry.worksheet.success)\n\t\tconst result: RatingResult = {\n\t\t\tlines: results,\n\t\t\t...(total === undefined ? {} : { total }),\n\t\t\tsuccess,\n\t\t}\n\t\tthis.#emitter.emit('rate', subject, result)\n\t\treturn result\n\t}\n\n\tdestroy(): void {\n\t\tif (this.#destroyed) return\n\t\tthis.#destroyed = true\n\t\tif (this.#owned) this.#engine.destroy()\n\t\tthis.#emitter.destroy()\n\t}\n\n\t#normalize(input: readonly LineDefinition[] | RatingDefinition): readonly LineDefinition[] {\n\t\tif (arrayOf(isLineDefinition)(input)) return input\n\t\tif (isRatingDefinition(input)) return input.lines\n\t\tthrow new RaterError(\n\t\t\t'DEFINITION',\n\t\t\t'Rating input must be an array of line definitions or a rating definition',\n\t\t)\n\t}\n\n\t#rateLine(line: LineDefinition, subject: Subject): LineResult {\n\t\tconst result = this.#reasonQuantitative(subject, line.rate)\n\t\treturn buildLineResult(line, result, this.#labels)\n\t}\n\n\t// Narrows the engine's tagged ReasonResult union down to a QuantitativeResult\n\t// for a definition the engine is guaranteed (by dispatch-by-reasoning, given\n\t// only the quantitative reasoner is ever registered) to resolve as such — a\n\t// defensive, total fallback rather than an assertion. A nonconforming\n\t// injected engine result missing (or with a non-array) `errors` contributes\n\t// no errors from that side rather than throwing.\n\t#reasonQuantitative(subject: Subject, definition: QuantitativeDefinition): QuantitativeResult {\n\t\tconst result = this.#engine.reason(subject, definition)\n\t\tif (result.reasoning === 'quantitative') return result\n\t\tconst failure = buildErrorResult(\n\t\t\tdefinition,\n\t\t\t`Expected quantitative result, got ${result.reasoning}`,\n\t\t)\n\t\tconst errors = [...(isArray<string>(result.errors) ? result.errors : []), ...failure.errors]\n\t\tif (failure.reasoning === 'quantitative') return { ...failure, errors }\n\t\treturn {\n\t\t\treasoning: 'quantitative',\n\t\t\tvalue: 0,\n\t\t\tgroups: [],\n\t\t\tcount: 0,\n\t\t\tsuccess: false,\n\t\t\ttrace: [],\n\t\t\terrors,\n\t\t}\n\t}\n\n\t#ensureAlive(): void {\n\t\tif (this.#destroyed) throw new RaterError('DESTROYED', 'Rater has been destroyed')\n\t}\n}\n","import type { RaterInterface, RaterOptions } from './types.js'\nimport { Rater } from './Rater.js'\n\n/**\n * Creates a rating orchestrator over the shared quantitative engine, seeded\n * from {@link RaterOptions} and returning a {@link RaterInterface}.\n *\n * @param options - Optional total handler, labels, injected engine, and emitter hooks\n * @returns A {@link RaterInterface}\n *\n * @example Create a rater\n * ```ts\n * import { createRater } from '@orkestrel/rater'\n *\n * const rater = createRater()\n * rater.destroy()\n * ```\n */\nexport function createRater(options?: RaterOptions): RaterInterface {\n\treturn new Rater(options)\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAkBA,IAAa,aAAb,cAAgC,MAAM;CACrC;CACA;CAEA,YAAY,MAAsB,SAAiB,SAA6C;EAC/F,MAAM,OAAO;EACb,KAAK,OAAO;EACZ,KAAK,OAAO;EACZ,IAAI,YAAY,KAAA,GAAW,KAAK,UAAU;CAC3C;AACD;;;;;;;;;;;;;;;;;;AAmBA,SAAgB,aAAa,OAAqC;CACjE,OAAO,iBAAiB;AACzB;;;;;;;;;;;;;;;;;;;;;ACDA,IAAa,UAAwB,UAAU,UAAU,SAAS,OAAO;;;;;;;;;;;;;;;;;;;;;;AAuBzE,SAAgB,iBAAiB,OAAyC;CACzE,OAAO,SACN;EACC,IAAI;EACJ,MAAM;EACN,aAAa;EACb,MAAM;EACN,UAAU;CACX,GACA,CAAC,eAAe,UAAU,CAC3B,CAAC,CAAC,KAAK;AACR;;;;;;;;;;;;;;;;;;;;;AAsBA,SAAgB,mBAAmB,OAA2C;CAC7E,OAAO,SACN;EACC,IAAI;EACJ,MAAM;EACN,aAAa;EACb,OAAO,QAAQ,gBAAgB;EAC/B,UAAU;CACX,GACA,CAAC,eAAe,UAAU,CAC3B,CAAC,CAAC,KAAK;AACR;;;;;;;;;;;;;;;;;;;;;;;AAwBA,SAAgB,WAAW,OAAmC;CAC7D,OAAO,SACN;EACC,OAAO;EACP,OAAO;EACP,YAAY;EACZ,KAAK;CACN,GACA;EAAC;EAAS;EAAS;EAAc;CAAK,CACvC,CAAC,CAAC,KAAK;AACR;;;;;;;;;;;;;;;;;;;;;AAsBA,SAAgB,kBAAkB,OAA0C;CAC3E,OAAO,SACN;EACC,IAAI;EACJ,MAAM;EACN,aAAa;EACb,SAAS;EACT,OAAO;EACP,UAAU,QAAQ,UAAU;CAC7B,GACA;EAAC;EAAQ;EAAe;CAAO,CAChC,CAAC,CAAC,KAAK;AACR;;;;;;;;;;;;;;;;;;;;;AAsBA,SAAgB,iBAAiB,OAAyC;CACzE,OAAO,SACN;EACC,IAAI;EACJ,MAAM;EACN,aAAa;EACb,SAAS;EACT,OAAO;EACP,SAAS,QAAQ,iBAAiB;CACnC,GACA,CAAC,QAAQ,aAAa,CACvB,CAAC,CAAC,KAAK;AACR;;;;;;;;;;;;;;;;;;;;;AAsBA,SAAgB,OAAO,OAA+B;CACrD,OAAO,SACN;EACC,OAAO;EACP,IAAI;EACJ,MAAM;EACN,OAAO;EACP,YAAY;CACb,GACA;EAAC;EAAM;EAAQ;CAAY,CAC5B,CAAC,CAAC,KAAK;AACR;;;;;;;;;;;;;;;;;;;;;;AAuBA,SAAgB,YAAY,OAAoC;CAC/D,OAAO,SACN;EACC,IAAI;EACJ,MAAM;EACN,aAAa;EACb,WAAW;EACX,OAAO;EACP,QAAQ,QAAQ,gBAAgB;EAChC,OAAO,QAAQ,MAAM;EACrB,OAAO,QAAQ,QAAQ;EACvB,QAAQ,QAAQ,QAAQ;EACxB,SAAS;CACV,GACA,CAAC,WAAW,CACb,CAAC,CAAC,KAAK;AACR;;;;;;;;;;;;;;;;;;;;;;;;AAyBA,SAAgB,aAAa,OAAqC;CACjE,OAAO,SACN;EACC,IAAI;EACJ,MAAM;EACN,QAAQ;EACR,WAAW;CACZ,GACA,CAAC,QAAQ,CACV,CAAC,CAAC,KAAK;AACR;;;;;;;;;;;;;;;;;;;;;;;AAwBA,SAAgB,eAAe,OAAuC;CACrE,OAAO,SACN;EACC,OAAO,QAAQ,YAAY;EAC3B,OAAO;EACP,SAAS;CACV,GACA,CAAC,OAAO,CACT,CAAC,CAAC,KAAK;AACR;;;;;;;;;;;;;;;;;;;;;;AC5TA,SAAgB,oBACf,IACA,MACA,MACA,WACiB;CACjB,OAAO;EAAE;EAAI;EAAM;EAAM,GAAG;CAAU;AACvC;;;;;;;;;;;;;;;;;;;;;AAsBA,SAAgB,sBACf,IACA,MACA,OACA,WACmB;CACnB,OAAO;EAAE;EAAI;EAAM;EAAO,GAAG;CAAU;AACxC;;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,cACf,OACA,QACA,KACA,QACW;CACX,MAAM,QAAQ,YAAY,MAAM,KAAK;CACrC,OAAO;EACN,OAAO,MAAM;EACb,GAAI,SAAS,WAAW,KAAA,IAAY,CAAC,IAAI,EAAE,OAAO,OAAO,OAAO;EAChE,YAAY,MAAM;EAClB,UAAU,MAAM;EAChB;EACA,GAAI,QAAQ,KAAA,IAAY,CAAC,IAAI,EAAE,IAAI;CACpC;AACD;;;;;;;;;;;;;;;;;;;AAoBA,SAAgB,kBACf,QACA,SACA,QACsB;CACtB,QAAQ,UAAU,CAAC,EAAA,CAAG,KAAK,OAAO,UAAU;EAC3C,MAAM,SAAS,UAAU;EACzB,OAAO,cAAc,OAAO,QAAQ,QAAQ,QAAQ,KAAK,MAAM;CAChE,CAAC;AACF;;;;;;;;;;;;;;;;;;AAmBA,SAAgB,qBACf,YACA,SACA,QACkB;CAClB,MAAM,SAAS,QAAQ,MAAM,UAAU,MAAM,OAAO,WAAW,EAAE;CACjE,OAAO;EACN,IAAI,WAAW;EACf,MAAM,WAAW;EACjB,GAAI,WAAW,gBAAgB,KAAA,IAAY,CAAC,IAAI,EAAE,aAAa,WAAW,YAAY;EACtF,SAAS,QAAQ,WAAW;EAC5B,GAAI,QAAQ,UAAU,KAAA,IAAY,CAAC,IAAI,EAAE,OAAO,OAAO,MAAM;EAC7D,UAAU,kBAAkB,WAAW,QAAQ,QAAQ,QAAQ,MAAM;CACtE;AACD;;;;;;;;;;;;;;;;;;AAmBA,SAAgB,oBACf,YACA,SACA,QACiB;CACjB,MAAM,SAAS,QAAQ,MAAM,UAAU,MAAM,OAAO,WAAW,EAAE;CACjE,OAAO;EACN,IAAI,WAAW;EACf,MAAM,WAAW;EACjB,GAAI,WAAW,gBAAgB,KAAA,IAAY,CAAC,IAAI,EAAE,aAAa,WAAW,YAAY;EACtF,SAAS,QAAQ,WAAW;EAC5B,OAAO,QAAQ,SAAS;EACxB,SAAS,WAAW,QAAQ,KAAK,WAChC,qBAAqB,QAAQ,QAAQ,WAAW,CAAC,GAAG,MAAM,CAC3D;CACD;AACD;;;;;;;;;;;;;;;;;;;AAoBA,SAAgB,mBACf,OACA,IACA,MACA,OACA,YACO;CACP,OAAO;EACN;EACA,GAAI,OAAO,KAAA,IAAY,CAAC,IAAI,EAAE,GAAG;EACjC,GAAI,SAAS,KAAA,IAAY,CAAC,IAAI,EAAE,KAAK;EACrC;EACA;CACD;AACD;;;;;;;;;;;;;;;;;;;;;AAsBA,SAAgB,oBACf,YACA,QACA,QACkB;CAClB,MAAM,SAAiB,CAAC;CACxB,KAAK,MAAM,SAAS,QAAQ;EAC3B,KAAK,MAAM,UAAU,MAAM,SAC1B,IAAI,OAAO,WAAW,OAAO,UAAU,KAAA,GACtC,OAAO,KACN,mBACC,UACA,OAAO,IACP,OAAO,MACP,OAAO,OACP,GAAG,OAAO,GAAG,KAAK,OAAO,OAC1B,CACD;EAGF,OAAO,KACN,mBACC,SACA,MAAM,IACN,MAAM,MACN,MAAM,OACN,GAAG,MAAM,GAAG,KAAK,MAAM,OACxB,CACD;CACD;CACA,OAAO,KACN,mBACC,SACA,WAAW,IACX,WAAW,MACX,OAAO,OACP,GAAG,WAAW,YAAY,KAAK,OAAO,OACvC,CACD;CACA,OAAO;AACR;;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,eACf,YACA,QACA,QACY;CACZ,MAAM,SAAS,WAAW,OAAO,KAAK,UAAU,oBAAoB,OAAO,OAAO,QAAQ,MAAM,CAAC;CACjG,OAAO;EACN,IAAI,WAAW;EACf,MAAM,WAAW;EACjB,aAAa,WAAW;EACxB,GAAI,WAAW,cAAc,KAAA,IAAY,CAAC,IAAI,EAAE,WAAW,WAAW,UAAU;EAChF,OAAO,OAAO;EACd;EACA,OAAO,oBAAoB,YAAY,QAAQ,MAAM;EACrD,OAAO,OAAO;EACd,QAAQ,OAAO;EACf,SAAS,OAAO;CACjB;AACD;;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,gBACf,YACA,QACA,QACa;CACb,OAAO;EACN,IAAI,WAAW;EACf,MAAM,WAAW;EACjB,GAAI,OAAO,UAAU,EAAE,QAAQ,OAAO,MAAM,IAAI,CAAC;EACjD,WAAW,eAAe,WAAW,MAAM,QAAQ,MAAM;CAC1D;AACD;;;;;;;;;;;;;;;;;;AAmBA,SAAgB,WAAW,OAAkD;CAC5E,IAAI,QAAQ;CACZ,IAAI,QAAQ;CACZ,KAAK,MAAM,SAAS,OACnB,IAAI,MAAM,WAAW,KAAA,GAAW;EAC/B,SAAS,MAAM;EACf,SAAS;CACV;CAED,OAAO,UAAU,IAAI,KAAA,IAAY;AAClC;;;;;;;;;;;;;;;;;;;;;;;;;ACxWA,IAAa,QAAb,MAA6C;CAC5C;CACA;CACA;CACA;CACA;CACA,aAAa;CAEb,YAAY,SAAwB;EACnC,KAAK,WAAW,IAAI,QAAuB;GAC1C,GAAI,SAAS,OAAO,KAAA,IAAY,CAAC,IAAI,EAAE,IAAI,QAAQ,GAAG;GACtD,GAAI,SAAS,UAAU,KAAA,IAAY,CAAC,IAAI,EAAE,OAAO,QAAQ,MAAM;EAChE,CAAC;EACD,IAAI,SAAS,WAAW,KAAA,GAAW;GAClC,KAAK,UAAU,aAAa;IAAE,WAAW,CAAC,2BAA2B,CAAC;IAAG,MAAM;GAAM,CAAC;GACtF,KAAK,SAAS;EACf,OAAO;GACN,KAAK,UAAU,QAAQ;GACvB,KAAK,SAAS;EACf;EACA,KAAK,SAAS,SAAS;EACvB,KAAK,UAAU,SAAS;CACzB;CAEA,IAAI,UAA2C;EAC9C,OAAO,KAAK;CACb;CAKA,KAAK,OAAqD,SAAgC;EACzF,KAAK,aAAa;EAClB,MAAM,QAAQ,KAAK,WAAW,KAAK;EACnC,IAAI,CAAC,SAAS,OAAO,GAAG,MAAM,IAAI,WAAW,YAAY,0BAA0B;EACnF,MAAM,UAAU,MAAM,KAAK,SAAS,KAAK,UAAU,MAAM,OAAO,CAAC;EACjE,MAAM,SAAS,KAAK,UAAU,WAAA,CAAY,OAAO;EACjD,MAAM,UAAU,QAAQ,OAAO,UAAU,MAAM,UAAU,OAAO;EAChE,MAAM,SAAuB;GAC5B,OAAO;GACP,GAAI,UAAU,KAAA,IAAY,CAAC,IAAI,EAAE,MAAM;GACvC;EACD;EACA,KAAK,SAAS,KAAK,QAAQ,SAAS,MAAM;EAC1C,OAAO;CACR;CAEA,UAAgB;EACf,IAAI,KAAK,YAAY;EACrB,KAAK,aAAa;EAClB,IAAI,KAAK,QAAQ,KAAK,QAAQ,QAAQ;EACtC,KAAK,SAAS,QAAQ;CACvB;CAEA,WAAW,OAAgF;EAC1F,IAAI,QAAQ,gBAAgB,CAAC,CAAC,KAAK,GAAG,OAAO;EAC7C,IAAI,mBAAmB,KAAK,GAAG,OAAO,MAAM;EAC5C,MAAM,IAAI,WACT,cACA,0EACD;CACD;CAEA,UAAU,MAAsB,SAA8B;EAE7D,OAAO,gBAAgB,MADR,KAAK,oBAAoB,SAAS,KAAK,IACzB,GAAQ,KAAK,OAAO;CAClD;CAQA,oBAAoB,SAAkB,YAAwD;EAC7F,MAAM,SAAS,KAAK,QAAQ,OAAO,SAAS,UAAU;EACtD,IAAI,OAAO,cAAc,gBAAgB,OAAO;EAChD,MAAM,UAAU,iBACf,YACA,qCAAqC,OAAO,WAC7C;EACA,MAAM,SAAS,CAAC,GAAI,QAAgB,OAAO,MAAM,IAAI,OAAO,SAAS,CAAC,GAAI,GAAG,QAAQ,MAAM;EAC3F,IAAI,QAAQ,cAAc,gBAAgB,OAAO;GAAE,GAAG;GAAS;EAAO;EACtE,OAAO;GACN,WAAW;GACX,OAAO;GACP,QAAQ,CAAC;GACT,OAAO;GACP,SAAS;GACT,OAAO,CAAC;GACR;EACD;CACD;CAEA,eAAqB;EACpB,IAAI,KAAK,YAAY,MAAM,IAAI,WAAW,aAAa,0BAA0B;CAClF;AACD;;;;;;;;;;;;;;;;;;AC7HA,SAAgB,YAAY,SAAwC;CACnE,OAAO,IAAI,MAAM,OAAO;AACzB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orkestrel/rater",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.14",
|
|
4
4
|
"description": "A typed quantitative rating layer: authored lines are rated against a subject to produce per-line amounts, worksheets, and a derived total. Part of the @orkestrel line.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"quantitative",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
|
|
47
47
|
"copy": "node -e \"const fs=require('node:fs'),p=require('node:path'),a=process.argv[1],b=process.argv[2];fs.mkdirSync(p.dirname(b),{recursive:true});fs.cpSync(a,b,{force:true});console.log('Copied: '+a+' to '+b)\"",
|
|
48
48
|
"scaffold": "scaffold",
|
|
49
|
-
"lint": "oxlint --config .oxlintrc.json --fix
|
|
49
|
+
"lint": "oxlint --config .oxlintrc.json --fix .",
|
|
50
50
|
"check": "tsc --noEmit --project tsconfig.json && npm run check:src",
|
|
51
51
|
"check:src": "npm run check:src:core",
|
|
52
52
|
"check:src:core": "tsc --noEmit -p configs/src/tsconfig.core.json",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"test:src:core": "vitest run --config vite.config.ts --no-cache --reporter=dot --project src:core",
|
|
59
59
|
"test:policy": "vitest run --config vite.config.ts --no-cache --reporter=dot --project policy",
|
|
60
60
|
"test:config": "vitest run --config vite.config.ts --no-cache --reporter=dot --project config",
|
|
61
|
-
"test:guides": "
|
|
61
|
+
"test:guides": "node --experimental-strip-types tests/guides.test.ts",
|
|
62
62
|
"build": "npm run clean && npm run build:src",
|
|
63
63
|
"build:src": "npm run build:src:core",
|
|
64
64
|
"build:src:core": "vite build --config configs/src/vite.core.config.ts && npm run copy dist/src/core/index.d.ts dist/src/core/index.d.cts",
|
|
@@ -70,22 +70,21 @@
|
|
|
70
70
|
"test:setup": "vitest run --config vite.config.ts --no-cache --reporter=dot --project setup"
|
|
71
71
|
},
|
|
72
72
|
"dependencies": {
|
|
73
|
-
"@orkestrel/contract": "^0.0.
|
|
74
|
-
"@orkestrel/emitter": "^0.0.
|
|
75
|
-
"@orkestrel/reason": "^0.0.
|
|
73
|
+
"@orkestrel/contract": "^0.0.17",
|
|
74
|
+
"@orkestrel/emitter": "^0.0.10",
|
|
75
|
+
"@orkestrel/reason": "^0.0.10"
|
|
76
76
|
},
|
|
77
77
|
"devDependencies": {
|
|
78
|
-
"@microsoft/api-extractor": "^7.59.
|
|
79
|
-
"@orkestrel/guide": "^0.0.
|
|
80
|
-
"@orkestrel/probe": "^0.0.
|
|
81
|
-
"@orkestrel/scaffold": "^0.0.
|
|
82
|
-
"@orkestrel/test": "^0.0.
|
|
83
|
-
"@types/node": "^26.
|
|
84
|
-
"oxfmt": "^0.
|
|
85
|
-
"oxlint": "^1.
|
|
78
|
+
"@microsoft/api-extractor": "^7.59.1",
|
|
79
|
+
"@orkestrel/guide": "^0.0.18",
|
|
80
|
+
"@orkestrel/probe": "^0.0.12",
|
|
81
|
+
"@orkestrel/scaffold": "^0.0.64",
|
|
82
|
+
"@orkestrel/test": "^0.0.14",
|
|
83
|
+
"@types/node": "^26.5.1",
|
|
84
|
+
"oxfmt": "^0.67.0",
|
|
85
|
+
"oxlint": "^1.82.0",
|
|
86
86
|
"typescript": "^6.0.3",
|
|
87
|
-
"vite": "^8.
|
|
88
|
-
"vite-plugin-dts": "^5.1.0",
|
|
87
|
+
"vite": "^8.3.0",
|
|
89
88
|
"vitest": "^4.1.11"
|
|
90
89
|
},
|
|
91
90
|
"engines": {
|