@orkestrel/rater 0.0.8 → 0.0.10
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/dist/src/core/index.cjs +263 -52
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +138 -0
- package/dist/src/core/index.d.ts +138 -0
- package/dist/src/core/index.js +259 -55
- package/dist/src/core/index.js.map +1 -1
- package/package.json +13 -11
package/dist/src/core/index.cjs
CHANGED
|
@@ -118,9 +118,265 @@ function isRatingDefinition(value) {
|
|
|
118
118
|
metadata: _orkestrel_contract.isJSONValue
|
|
119
119
|
}, ["description", "metadata"])(value);
|
|
120
120
|
}
|
|
121
|
+
/**
|
|
122
|
+
* Determine whether a value is an open result-side {@link Evidence} object.
|
|
123
|
+
*
|
|
124
|
+
* @remarks
|
|
125
|
+
* Unknown members, prototypes, and class instances are admitted. Arrays are
|
|
126
|
+
* refused. `expected` and `actual` are `unknown`, so this guard does not read or
|
|
127
|
+
* check them; either member may also be absent because `objectOf` reads declared
|
|
128
|
+
* members rather than requiring or enumerating own keys.
|
|
129
|
+
*
|
|
130
|
+
* @param value - The value to test
|
|
131
|
+
* @returns `true` when every checked `Evidence` member conforms
|
|
132
|
+
*
|
|
133
|
+
* @example
|
|
134
|
+
* ```ts
|
|
135
|
+
* import { isEvidence } from '@orkestrel/rater'
|
|
136
|
+
*
|
|
137
|
+
* isEvidence({ field: 'age', comparison: 'above', expected: 18, actual: 25, met: true }) // true
|
|
138
|
+
* ```
|
|
139
|
+
*/
|
|
140
|
+
function isEvidence(value) {
|
|
141
|
+
return (0, _orkestrel_contract.objectOf)({
|
|
142
|
+
field: _orkestrel_reason.isFieldPath,
|
|
143
|
+
label: _orkestrel_contract.isString,
|
|
144
|
+
comparison: _orkestrel_reason.isComparison,
|
|
145
|
+
met: _orkestrel_contract.isBoolean
|
|
146
|
+
}, [
|
|
147
|
+
"field",
|
|
148
|
+
"label",
|
|
149
|
+
"comparison",
|
|
150
|
+
"met"
|
|
151
|
+
])(value);
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Determine whether a value is an open {@link WorksheetFactor} result object.
|
|
155
|
+
*
|
|
156
|
+
* @remarks
|
|
157
|
+
* Unknown members, prototypes, and class instances are admitted. Arrays are
|
|
158
|
+
* refused. Optional members may be absent or read as `undefined`.
|
|
159
|
+
*
|
|
160
|
+
* @param value - The value to test
|
|
161
|
+
* @returns `true` when every published worksheet-factor member conforms
|
|
162
|
+
*
|
|
163
|
+
* @example
|
|
164
|
+
* ```ts
|
|
165
|
+
* import { isWorksheetFactor } from '@orkestrel/rater'
|
|
166
|
+
*
|
|
167
|
+
* isWorksheetFactor({ id: 'base', applied: true, value: 100, evidence: [] }) // true
|
|
168
|
+
* ```
|
|
169
|
+
*/
|
|
170
|
+
function isWorksheetFactor(value) {
|
|
171
|
+
return (0, _orkestrel_contract.objectOf)({
|
|
172
|
+
id: _orkestrel_contract.isString,
|
|
173
|
+
name: _orkestrel_contract.isString,
|
|
174
|
+
description: _orkestrel_contract.isString,
|
|
175
|
+
applied: _orkestrel_contract.isBoolean,
|
|
176
|
+
value: _orkestrel_contract.isNumber,
|
|
177
|
+
evidence: (0, _orkestrel_contract.arrayOf)(isEvidence)
|
|
178
|
+
}, [
|
|
179
|
+
"name",
|
|
180
|
+
"description",
|
|
181
|
+
"value"
|
|
182
|
+
])(value);
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Determine whether a value is an open {@link WorksheetGroup} result object.
|
|
186
|
+
*
|
|
187
|
+
* @remarks
|
|
188
|
+
* Unknown members, prototypes, and class instances are admitted. Arrays are
|
|
189
|
+
* refused. Optional members may be absent or read as `undefined`.
|
|
190
|
+
*
|
|
191
|
+
* @param value - The value to test
|
|
192
|
+
* @returns `true` when every published worksheet-group member conforms
|
|
193
|
+
*
|
|
194
|
+
* @example
|
|
195
|
+
* ```ts
|
|
196
|
+
* import { isWorksheetGroup } from '@orkestrel/rater'
|
|
197
|
+
*
|
|
198
|
+
* isWorksheetGroup({ id: 'charges', applied: true, value: 100, factors: [] }) // true
|
|
199
|
+
* ```
|
|
200
|
+
*/
|
|
201
|
+
function isWorksheetGroup(value) {
|
|
202
|
+
return (0, _orkestrel_contract.objectOf)({
|
|
203
|
+
id: _orkestrel_contract.isString,
|
|
204
|
+
name: _orkestrel_contract.isString,
|
|
205
|
+
description: _orkestrel_contract.isString,
|
|
206
|
+
applied: _orkestrel_contract.isBoolean,
|
|
207
|
+
value: _orkestrel_contract.isNumber,
|
|
208
|
+
factors: (0, _orkestrel_contract.arrayOf)(isWorksheetFactor)
|
|
209
|
+
}, ["name", "description"])(value);
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Determine whether a value is an open {@link Step} result object.
|
|
213
|
+
*
|
|
214
|
+
* @remarks
|
|
215
|
+
* Unknown members, prototypes, and class instances are admitted. Arrays are
|
|
216
|
+
* refused. Optional members may be absent or read as `undefined`.
|
|
217
|
+
*
|
|
218
|
+
* @param value - The value to test
|
|
219
|
+
* @returns `true` when every published worksheet-step member conforms
|
|
220
|
+
*
|
|
221
|
+
* @example
|
|
222
|
+
* ```ts
|
|
223
|
+
* import { isStep } from '@orkestrel/rater'
|
|
224
|
+
*
|
|
225
|
+
* isStep({ stage: 'total', value: 100 }) // true
|
|
226
|
+
* ```
|
|
227
|
+
*/
|
|
228
|
+
function isStep(value) {
|
|
229
|
+
return (0, _orkestrel_contract.objectOf)({
|
|
230
|
+
stage: isStage,
|
|
231
|
+
id: _orkestrel_contract.isString,
|
|
232
|
+
name: _orkestrel_contract.isString,
|
|
233
|
+
value: _orkestrel_contract.isNumber,
|
|
234
|
+
expression: _orkestrel_contract.isString
|
|
235
|
+
}, [
|
|
236
|
+
"id",
|
|
237
|
+
"name",
|
|
238
|
+
"expression"
|
|
239
|
+
])(value);
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Determine whether a value is an open {@link Worksheet} result object.
|
|
243
|
+
*
|
|
244
|
+
* @remarks
|
|
245
|
+
* Unknown members, prototypes, and class instances are admitted. Arrays are
|
|
246
|
+
* refused. Optional members may be absent or read as `undefined`.
|
|
247
|
+
*
|
|
248
|
+
* @param value - The value to test
|
|
249
|
+
* @returns `true` when every published worksheet member conforms
|
|
250
|
+
*
|
|
251
|
+
* @example
|
|
252
|
+
* ```ts
|
|
253
|
+
* import { isWorksheet } from '@orkestrel/rater'
|
|
254
|
+
*
|
|
255
|
+
* isWorksheet({ id: 'quote', name: 'Quote', aggregation: 'sum', value: 0, groups: [], steps: [], trace: [], errors: [], success: true }) // true
|
|
256
|
+
* ```
|
|
257
|
+
*/
|
|
258
|
+
function isWorksheet(value) {
|
|
259
|
+
return (0, _orkestrel_contract.objectOf)({
|
|
260
|
+
id: _orkestrel_contract.isString,
|
|
261
|
+
name: _orkestrel_contract.isString,
|
|
262
|
+
aggregation: _orkestrel_reason.isAggregation,
|
|
263
|
+
precision: _orkestrel_contract.isNumber,
|
|
264
|
+
value: _orkestrel_contract.isNumber,
|
|
265
|
+
groups: (0, _orkestrel_contract.arrayOf)(isWorksheetGroup),
|
|
266
|
+
steps: (0, _orkestrel_contract.arrayOf)(isStep),
|
|
267
|
+
trace: (0, _orkestrel_contract.arrayOf)(_orkestrel_contract.isString),
|
|
268
|
+
errors: (0, _orkestrel_contract.arrayOf)(_orkestrel_contract.isString),
|
|
269
|
+
success: _orkestrel_contract.isBoolean
|
|
270
|
+
}, ["precision"])(value);
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Determine whether a value is an open {@link LineResult} object.
|
|
274
|
+
*
|
|
275
|
+
* @remarks
|
|
276
|
+
* Unknown members, prototypes, and class instances are admitted. Arrays are
|
|
277
|
+
* refused. `amount` may be absent or read as `undefined`; when present it stays
|
|
278
|
+
* a plain JavaScript `number` without a finite or range refinement.
|
|
279
|
+
*
|
|
280
|
+
* @param value - The value to test
|
|
281
|
+
* @returns `true` when every published line-result member conforms
|
|
282
|
+
*
|
|
283
|
+
* @example
|
|
284
|
+
* ```ts
|
|
285
|
+
* import { isLineResult } from '@orkestrel/rater'
|
|
286
|
+
*
|
|
287
|
+
* isLineResult({ id: 'base', name: 'Base', worksheet: { id: 'base', name: 'Base', aggregation: 'sum', value: 0, groups: [], steps: [], trace: [], errors: [], success: false }, success: false }) // true
|
|
288
|
+
* ```
|
|
289
|
+
*/
|
|
290
|
+
function isLineResult(value) {
|
|
291
|
+
return (0, _orkestrel_contract.objectOf)({
|
|
292
|
+
id: _orkestrel_contract.isString,
|
|
293
|
+
name: _orkestrel_contract.isString,
|
|
294
|
+
amount: _orkestrel_contract.isNumber,
|
|
295
|
+
worksheet: isWorksheet,
|
|
296
|
+
success: _orkestrel_contract.isBoolean
|
|
297
|
+
}, ["amount"])(value);
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Determine whether a value is an open {@link RatingResult} object.
|
|
301
|
+
*
|
|
302
|
+
* @remarks
|
|
303
|
+
* Use this guard for a result returned by a borrowed `RaterInterface`. Unknown
|
|
304
|
+
* members, prototypes, and class instances are admitted. Arrays are refused.
|
|
305
|
+
* `total` may be absent or read as `undefined`; when present it stays a plain
|
|
306
|
+
* JavaScript `number` without a finite or range refinement.
|
|
307
|
+
*
|
|
308
|
+
* @param value - The value to test
|
|
309
|
+
* @returns `true` when every published rating-result member conforms
|
|
310
|
+
*
|
|
311
|
+
* @example
|
|
312
|
+
* ```ts
|
|
313
|
+
* import { isRatingResult } from '@orkestrel/rater'
|
|
314
|
+
*
|
|
315
|
+
* isRatingResult({ lines: [], success: true }) // true
|
|
316
|
+
* ```
|
|
317
|
+
*/
|
|
318
|
+
function isRatingResult(value) {
|
|
319
|
+
return (0, _orkestrel_contract.objectOf)({
|
|
320
|
+
lines: (0, _orkestrel_contract.arrayOf)(isLineResult),
|
|
321
|
+
total: _orkestrel_contract.isNumber,
|
|
322
|
+
success: _orkestrel_contract.isBoolean
|
|
323
|
+
}, ["total"])(value);
|
|
324
|
+
}
|
|
121
325
|
//#endregion
|
|
122
326
|
//#region src/core/helpers.ts
|
|
123
327
|
/**
|
|
328
|
+
* Build a {@link LineDefinition}.
|
|
329
|
+
*
|
|
330
|
+
* @param id - The line id
|
|
331
|
+
* @param name - The display name
|
|
332
|
+
* @param rate - The line's quantitative rating definition
|
|
333
|
+
* @param overrides - Optional {@link LineDefinition} fields merged over the defaults
|
|
334
|
+
* @returns A fresh line definition
|
|
335
|
+
*
|
|
336
|
+
* @example
|
|
337
|
+
* ```ts
|
|
338
|
+
* import { quantitativeDefinition } from '@orkestrel/reason'
|
|
339
|
+
* import { lineDefinition } from '@orkestrel/rater'
|
|
340
|
+
*
|
|
341
|
+
* lineDefinition('base', 'Base Amount', quantitativeDefinition('base', 'Base', []))
|
|
342
|
+
* ```
|
|
343
|
+
*/
|
|
344
|
+
function lineDefinition(id, name, rate, overrides) {
|
|
345
|
+
return {
|
|
346
|
+
id,
|
|
347
|
+
name,
|
|
348
|
+
rate,
|
|
349
|
+
...overrides
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Build a {@link RatingDefinition}.
|
|
354
|
+
*
|
|
355
|
+
* @param id - The rating id
|
|
356
|
+
* @param name - The display name
|
|
357
|
+
* @param lines - The rating's ordered lines
|
|
358
|
+
* @param overrides - Optional {@link RatingDefinition} fields merged over the defaults
|
|
359
|
+
* @returns A fresh rating definition
|
|
360
|
+
*
|
|
361
|
+
* @example
|
|
362
|
+
* ```ts
|
|
363
|
+
* import { lineDefinition, ratingDefinition } from '@orkestrel/rater'
|
|
364
|
+
* import { quantitativeDefinition } from '@orkestrel/reason'
|
|
365
|
+
*
|
|
366
|
+
* ratingDefinition('r1', 'Rating', [
|
|
367
|
+
* lineDefinition('base', 'Base Amount', quantitativeDefinition('base', 'Base', [])),
|
|
368
|
+
* ])
|
|
369
|
+
* ```
|
|
370
|
+
*/
|
|
371
|
+
function ratingDefinition(id, name, lines, overrides) {
|
|
372
|
+
return {
|
|
373
|
+
id,
|
|
374
|
+
name,
|
|
375
|
+
lines,
|
|
376
|
+
...overrides
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
/**
|
|
124
380
|
* Build an {@link Evidence} row from an evaluated {@link Check}.
|
|
125
381
|
*
|
|
126
382
|
* @param check - The authored check
|
|
@@ -496,68 +752,23 @@ var Rater = class {
|
|
|
496
752
|
function createRater(options) {
|
|
497
753
|
return new Rater(options);
|
|
498
754
|
}
|
|
499
|
-
/**
|
|
500
|
-
* Build a {@link LineDefinition}.
|
|
501
|
-
*
|
|
502
|
-
* @param id - The line id
|
|
503
|
-
* @param name - The display name
|
|
504
|
-
* @param rate - The line's quantitative rating definition
|
|
505
|
-
* @param overrides - Optional {@link LineDefinition} fields merged over the defaults
|
|
506
|
-
* @returns A fresh line definition
|
|
507
|
-
*
|
|
508
|
-
* @example
|
|
509
|
-
* ```ts
|
|
510
|
-
* import { quantitativeDefinition } from '@orkestrel/reason'
|
|
511
|
-
* import { lineDefinition } from '@orkestrel/rater'
|
|
512
|
-
*
|
|
513
|
-
* lineDefinition('base', 'Base Amount', quantitativeDefinition('base', 'Base', []))
|
|
514
|
-
* ```
|
|
515
|
-
*/
|
|
516
|
-
function lineDefinition(id, name, rate, overrides) {
|
|
517
|
-
return {
|
|
518
|
-
id,
|
|
519
|
-
name,
|
|
520
|
-
rate,
|
|
521
|
-
...overrides
|
|
522
|
-
};
|
|
523
|
-
}
|
|
524
|
-
/**
|
|
525
|
-
* Build a {@link RatingDefinition}.
|
|
526
|
-
*
|
|
527
|
-
* @param id - The rating id
|
|
528
|
-
* @param name - The display name
|
|
529
|
-
* @param lines - The rating's ordered lines
|
|
530
|
-
* @param overrides - Optional {@link RatingDefinition} fields merged over the defaults
|
|
531
|
-
* @returns A fresh rating definition
|
|
532
|
-
*
|
|
533
|
-
* @example
|
|
534
|
-
* ```ts
|
|
535
|
-
* import { lineDefinition, ratingDefinition } from '@orkestrel/rater'
|
|
536
|
-
* import { quantitativeDefinition } from '@orkestrel/reason'
|
|
537
|
-
*
|
|
538
|
-
* ratingDefinition('r1', 'Rating', [
|
|
539
|
-
* lineDefinition('base', 'Base Amount', quantitativeDefinition('base', 'Base', [])),
|
|
540
|
-
* ])
|
|
541
|
-
* ```
|
|
542
|
-
*/
|
|
543
|
-
function ratingDefinition(id, name, lines, overrides) {
|
|
544
|
-
return {
|
|
545
|
-
id,
|
|
546
|
-
name,
|
|
547
|
-
lines,
|
|
548
|
-
...overrides
|
|
549
|
-
};
|
|
550
|
-
}
|
|
551
755
|
//#endregion
|
|
552
756
|
exports.Rater = Rater;
|
|
553
757
|
exports.RaterError = RaterError;
|
|
554
758
|
exports.checkEvidence = checkEvidence;
|
|
555
759
|
exports.createRater = createRater;
|
|
556
760
|
exports.evidenceCheck = evidenceCheck;
|
|
761
|
+
exports.isEvidence = isEvidence;
|
|
557
762
|
exports.isLineDefinition = isLineDefinition;
|
|
763
|
+
exports.isLineResult = isLineResult;
|
|
558
764
|
exports.isRaterError = isRaterError;
|
|
559
765
|
exports.isRatingDefinition = isRatingDefinition;
|
|
766
|
+
exports.isRatingResult = isRatingResult;
|
|
560
767
|
exports.isStage = isStage;
|
|
768
|
+
exports.isStep = isStep;
|
|
769
|
+
exports.isWorksheet = isWorksheet;
|
|
770
|
+
exports.isWorksheetFactor = isWorksheetFactor;
|
|
771
|
+
exports.isWorksheetGroup = isWorksheetGroup;
|
|
561
772
|
exports.lineDefinition = lineDefinition;
|
|
562
773
|
exports.ratedLine = ratedLine;
|
|
563
774
|
exports.ratingDefinition = ratingDefinition;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","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 * 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 * Narrow a caught value to a {@link RaterError}.\n *\n * @param value - The caught value to test\n * @returns `true` when `value` is a `RaterError`\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 { LineDefinition, RatingDefinition, Stage } from './types.js'\nimport { arrayOf, isJSONValue, isString, literalOf, recordOf } from '@orkestrel/contract'\nimport { isQuantitativeDefinition } from '@orkestrel/reason'\n\n/**\n * Determine whether a value is a {@link Stage} literal.\n *\n * @param value - The value to test\n * @returns `true` when `value` is `'factor'`, `'group'`, or `'total'`\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 * Determine whether a value is an exact {@link LineDefinition} record.\n *\n * @remarks\n * Total guard (AGENTS §14): adversarial input (cycles, hostile prototypes)\n * returns `false`, never throws. The record shape is EXACT — an extra key fails.\n *\n * @param value - The value to test\n * @returns `true` when `value` is a `LineDefinition`\n *\n * @example\n * ```ts\n * import { quantitativeDefinition } from '@orkestrel/reason'\n * import { isLineDefinition } from '@orkestrel/rater'\n *\n * isLineDefinition({ id: 'base', name: 'Base', rate: quantitativeDefinition('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 * Determine whether a value is an exact {@link RatingDefinition} record.\n *\n * @remarks\n * Total guard (AGENTS §14): adversarial input (cycles, hostile prototypes)\n * returns `false`, never throws. The record shape is EXACT — an extra key fails.\n *\n * @param value - The value to test\n * @returns `true` when `value` is a `RatingDefinition`\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","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\tStage,\n\tStep,\n\tWorksheet,\n\tWorksheetFactor,\n\tWorksheetGroup,\n} from './types.js'\nimport { formatField } from '@orkestrel/reason'\n\n/**\n * Build 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 - Whether the check was met (absent when 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 { check } from '@orkestrel/reason'\n * import { evidenceCheck } from '@orkestrel/rater'\n *\n * const entry = check('age', 'above', 18)\n * evidenceCheck(entry, 25, true) // { field: 'age', comparison: 'above', expected: 18, actual: 25, met: true }\n * ```\n */\nexport function evidenceCheck(\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 * Build evidence rows from a quantitative factor's authored checks and\n * evaluated check results.\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 { check } from '@orkestrel/reason'\n * import { checkEvidence } from '@orkestrel/rater'\n *\n * const checks = [check('age', 'above', 18)]\n * checkEvidence(checks, [{ field: 'age', met: true, actual: 25 }])\n * ```\n */\nexport function checkEvidence(\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 evidenceCheck(check, result?.actual, result?.met, labels)\n\t})\n}\n\n/**\n * Join 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 { fieldFactor } from '@orkestrel/reason'\n * import { worksheetFactor } from '@orkestrel/rater'\n *\n * const factor = fieldFactor('seats', 'seats')\n * worksheetFactor(factor, [{ id: 'seats', applied: true, value: 10 }])\n * ```\n */\nexport function worksheetFactor(\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: checkEvidence(definition.checks, result?.checks, labels),\n\t}\n}\n\n/**\n * Join 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 { factorGroup, staticFactor } from '@orkestrel/reason'\n * import { worksheetGroup } from '@orkestrel/rater'\n *\n * const group = factorGroup('charge', 'sum', [staticFactor('base', 100)])\n * worksheetGroup(group, [{ id: 'charge', applied: true, value: 100, factors: [] }])\n * ```\n */\nexport function worksheetGroup(\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\tworksheetFactor(factor, result?.factors ?? [], labels),\n\t\t),\n\t}\n}\n\n/**\n * Build 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 { worksheetStep } from '@orkestrel/rater'\n *\n * worksheetStep('total', 'quote', 'Quote', 110, 'sum = 110')\n * // { stage: 'total', id: 'quote', name: 'Quote', value: 110, expression: 'sum = 110' }\n * ```\n */\nexport function worksheetStep(\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 * Build 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 { createQuantitativeReasoner, createReason, factorGroup, quantitativeDefinition, staticFactor } from '@orkestrel/reason'\n * import { worksheetGroup, worksheetSteps } from '@orkestrel/rater'\n *\n * const definition = quantitativeDefinition('base', 'Base', [factorGroup('g', 'sum', [staticFactor('flat', 100)])])\n * const result = createReason({ reasoners: [createQuantitativeReasoner()] }).reason({}, definition)\n * if (result.reasoning === 'quantitative') {\n * \tworksheetSteps(definition, result, definition.groups.map((group) => worksheetGroup(group, result.groups)))\n * }\n * ```\n */\nexport function worksheetSteps(\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\tworksheetStep(\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\tworksheetStep('group', group.id, group.name, group.value, `${group.id} = ${group.value}`),\n\t\t)\n\t}\n\toutput.push(\n\t\tworksheetStep(\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 * Join 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 { createQuantitativeReasoner, createReason, factorGroup, quantitativeDefinition, staticFactor } from '@orkestrel/reason'\n * import { resultsWorksheet } from '@orkestrel/rater'\n *\n * const definition = quantitativeDefinition('base', 'Base', [factorGroup('g', 'sum', [staticFactor('flat', 100)])])\n * const result = createReason({ reasoners: [createQuantitativeReasoner()] }).reason({}, definition)\n * if (result.reasoning === 'quantitative') resultsWorksheet(definition, result) // the full audit trail\n * ```\n */\nexport function resultsWorksheet(\n\tdefinition: QuantitativeDefinition,\n\tresult: QuantitativeResult,\n\tlabels?: Readonly<Record<string, string>>,\n): Worksheet {\n\tconst groups = definition.groups.map((group) => worksheetGroup(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: worksheetSteps(definition, result, groups),\n\t\ttrace: result.trace,\n\t\terrors: result.errors,\n\t\tsuccess: result.success,\n\t}\n}\n\n/**\n * Build 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 { createQuantitativeReasoner, createReason, quantitativeDefinition } from '@orkestrel/reason'\n * import { lineDefinition, ratedLine } from '@orkestrel/rater'\n *\n * const line = lineDefinition('base', 'Base', quantitativeDefinition('base', 'Base', []))\n * const result = createReason({ reasoners: [createQuantitativeReasoner()] }).reason({}, line.rate)\n * if (result.reasoning === 'quantitative') ratedLine(line, result) // amount present only when success\n * ```\n */\nexport function ratedLine(\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: resultsWorksheet(definition.rate, result, labels),\n\t\tsuccess: result.success,\n\t}\n}\n\n/**\n * Sum 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 { createQuantitativeReasoner, createReason, factorGroup, quantitativeDefinition, staticFactor } from '@orkestrel/reason'\n * import { lineDefinition, ratedLine, sumAmounts } from '@orkestrel/rater'\n *\n * const rate = quantitativeDefinition('base', 'Base', [factorGroup('g', 'sum', [staticFactor('flat', 100)])])\n * const line = lineDefinition('base', 'Base', rate)\n * const result = createReason({ reasoners: [createQuantitativeReasoner()] }).reason({}, rate)\n * if (result.reasoning === 'quantitative') sumAmounts([ratedLine(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 } from '@orkestrel/contract'\nimport {\n\tbuildErrorResult,\n\tcreateQuantitativeReasoner,\n\tcreateReason,\n\tisSubject,\n} from '@orkestrel/reason'\nimport { RaterError } from './errors.js'\nimport { ratedLine, sumAmounts } from './helpers.js'\nimport { isLineDefinition, isRatingDefinition } from './validators.js'\n\n/**\n * The rating orchestrator — 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 (AGENTS §9.2). `destroy()`\n * destroys an OWNED engine, then the emitter LAST (AGENTS §13); an INJECTED\n * engine is never destroyed. Afterwards every other method throws\n * {@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 (AGENTS §9.2) 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 (!isSubject(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.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 ratedLine(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 { QuantitativeDefinition } from '@orkestrel/reason'\nimport type { LineDefinition, RatingDefinition, RaterInterface, RaterOptions } from './types.js'\nimport { Rater } from './Rater.js'\n\n/**\n * Create 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\n/**\n * Build 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 { quantitativeDefinition } from '@orkestrel/reason'\n * import { lineDefinition } from '@orkestrel/rater'\n *\n * lineDefinition('base', 'Base Amount', quantitativeDefinition('base', 'Base', []))\n * ```\n */\nexport function lineDefinition(\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 * Build 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 { lineDefinition, ratingDefinition } from '@orkestrel/rater'\n * import { quantitativeDefinition } from '@orkestrel/reason'\n *\n * ratingDefinition('r1', 'Rating', [\n * \tlineDefinition('base', 'Base Amount', quantitativeDefinition('base', 'Base', [])),\n * ])\n * ```\n */\nexport function ratingDefinition(\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"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","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 * 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 * Narrow a caught value to a {@link RaterError}.\n *\n * @param value - The caught value to test\n * @returns `true` when `value` is a `RaterError`\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 * Determine whether a value is a {@link Stage} literal.\n *\n * @param value - The value to test\n * @returns `true` when `value` is `'factor'`, `'group'`, or `'total'`\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 * Determine whether a value is an exact {@link LineDefinition} record.\n *\n * @remarks\n * Total guard (AGENTS §14): adversarial input (cycles, hostile prototypes)\n * returns `false`, never throws. The record shape is EXACT — an extra key fails.\n *\n * @param value - The value to test\n * @returns `true` when `value` is a `LineDefinition`\n *\n * @example\n * ```ts\n * import { quantitativeDefinition } from '@orkestrel/reason'\n * import { isLineDefinition } from '@orkestrel/rater'\n *\n * isLineDefinition({ id: 'base', name: 'Base', rate: quantitativeDefinition('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 * Determine whether a value is an exact {@link RatingDefinition} record.\n *\n * @remarks\n * Total guard (AGENTS §14): adversarial input (cycles, hostile prototypes)\n * returns `false`, never throws. The record shape is EXACT — an extra key fails.\n *\n * @param value - The value to test\n * @returns `true` when `value` is a `RatingDefinition`\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 * Determine 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` when every checked `Evidence` member conforms\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 * Determine 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` when every published worksheet-factor member conforms\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 * Determine 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` when every published worksheet-group member conforms\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 * Determine 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` when every published worksheet-step member conforms\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 * Determine 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` when every published worksheet member conforms\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 * Determine 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.\n *\n * @param value - The value to test\n * @returns `true` when every published line-result member conforms\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 }, 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\tsuccess: isBoolean,\n\t\t},\n\t\t['amount'],\n\t)(value)\n}\n\n/**\n * Determine 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` when every published rating-result member conforms\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 * Build 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 { quantitativeDefinition } from '@orkestrel/reason'\n * import { lineDefinition } from '@orkestrel/rater'\n *\n * lineDefinition('base', 'Base Amount', quantitativeDefinition('base', 'Base', []))\n * ```\n */\nexport function lineDefinition(\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 * Build 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 { lineDefinition, ratingDefinition } from '@orkestrel/rater'\n * import { quantitativeDefinition } from '@orkestrel/reason'\n *\n * ratingDefinition('r1', 'Rating', [\n * \tlineDefinition('base', 'Base Amount', quantitativeDefinition('base', 'Base', [])),\n * ])\n * ```\n */\nexport function ratingDefinition(\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 * Build 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 - Whether the check was met (absent when 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 { check } from '@orkestrel/reason'\n * import { evidenceCheck } from '@orkestrel/rater'\n *\n * const entry = check('age', 'above', 18)\n * evidenceCheck(entry, 25, true) // { field: 'age', comparison: 'above', expected: 18, actual: 25, met: true }\n * ```\n */\nexport function evidenceCheck(\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 * Build evidence rows from a quantitative factor's authored checks and\n * evaluated check results.\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 { check } from '@orkestrel/reason'\n * import { checkEvidence } from '@orkestrel/rater'\n *\n * const checks = [check('age', 'above', 18)]\n * checkEvidence(checks, [{ field: 'age', met: true, actual: 25 }])\n * ```\n */\nexport function checkEvidence(\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 evidenceCheck(check, result?.actual, result?.met, labels)\n\t})\n}\n\n/**\n * Join 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 { fieldFactor } from '@orkestrel/reason'\n * import { worksheetFactor } from '@orkestrel/rater'\n *\n * const factor = fieldFactor('seats', 'seats')\n * worksheetFactor(factor, [{ id: 'seats', applied: true, value: 10 }])\n * ```\n */\nexport function worksheetFactor(\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: checkEvidence(definition.checks, result?.checks, labels),\n\t}\n}\n\n/**\n * Join 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 { factorGroup, staticFactor } from '@orkestrel/reason'\n * import { worksheetGroup } from '@orkestrel/rater'\n *\n * const group = factorGroup('charge', 'sum', [staticFactor('base', 100)])\n * worksheetGroup(group, [{ id: 'charge', applied: true, value: 100, factors: [] }])\n * ```\n */\nexport function worksheetGroup(\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\tworksheetFactor(factor, result?.factors ?? [], labels),\n\t\t),\n\t}\n}\n\n/**\n * Build 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 { worksheetStep } from '@orkestrel/rater'\n *\n * worksheetStep('total', 'quote', 'Quote', 110, 'sum = 110')\n * // { stage: 'total', id: 'quote', name: 'Quote', value: 110, expression: 'sum = 110' }\n * ```\n */\nexport function worksheetStep(\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 * Build 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 { createQuantitativeReasoner, createReason, factorGroup, quantitativeDefinition, staticFactor } from '@orkestrel/reason'\n * import { worksheetGroup, worksheetSteps } from '@orkestrel/rater'\n *\n * const definition = quantitativeDefinition('base', 'Base', [factorGroup('g', 'sum', [staticFactor('flat', 100)])])\n * const result = createReason({ reasoners: [createQuantitativeReasoner()] }).reason({}, definition)\n * if (result.reasoning === 'quantitative') {\n * \tworksheetSteps(definition, result, definition.groups.map((group) => worksheetGroup(group, result.groups)))\n * }\n * ```\n */\nexport function worksheetSteps(\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\tworksheetStep(\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\tworksheetStep('group', group.id, group.name, group.value, `${group.id} = ${group.value}`),\n\t\t)\n\t}\n\toutput.push(\n\t\tworksheetStep(\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 * Join 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 { createQuantitativeReasoner, createReason, factorGroup, quantitativeDefinition, staticFactor } from '@orkestrel/reason'\n * import { resultsWorksheet } from '@orkestrel/rater'\n *\n * const definition = quantitativeDefinition('base', 'Base', [factorGroup('g', 'sum', [staticFactor('flat', 100)])])\n * const result = createReason({ reasoners: [createQuantitativeReasoner()] }).reason({}, definition)\n * if (result.reasoning === 'quantitative') resultsWorksheet(definition, result) // the full audit trail\n * ```\n */\nexport function resultsWorksheet(\n\tdefinition: QuantitativeDefinition,\n\tresult: QuantitativeResult,\n\tlabels?: Readonly<Record<string, string>>,\n): Worksheet {\n\tconst groups = definition.groups.map((group) => worksheetGroup(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: worksheetSteps(definition, result, groups),\n\t\ttrace: result.trace,\n\t\terrors: result.errors,\n\t\tsuccess: result.success,\n\t}\n}\n\n/**\n * Build 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 { createQuantitativeReasoner, createReason, quantitativeDefinition } from '@orkestrel/reason'\n * import { lineDefinition, ratedLine } from '@orkestrel/rater'\n *\n * const line = lineDefinition('base', 'Base', quantitativeDefinition('base', 'Base', []))\n * const result = createReason({ reasoners: [createQuantitativeReasoner()] }).reason({}, line.rate)\n * if (result.reasoning === 'quantitative') ratedLine(line, result) // amount present only when success\n * ```\n */\nexport function ratedLine(\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: resultsWorksheet(definition.rate, result, labels),\n\t\tsuccess: result.success,\n\t}\n}\n\n/**\n * Sum 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 { createQuantitativeReasoner, createReason, factorGroup, quantitativeDefinition, staticFactor } from '@orkestrel/reason'\n * import { lineDefinition, ratedLine, sumAmounts } from '@orkestrel/rater'\n *\n * const rate = quantitativeDefinition('base', 'Base', [factorGroup('g', 'sum', [staticFactor('flat', 100)])])\n * const line = lineDefinition('base', 'Base', rate)\n * const result = createReason({ reasoners: [createQuantitativeReasoner()] }).reason({}, rate)\n * if (result.reasoning === 'quantitative') sumAmounts([ratedLine(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 } from '@orkestrel/contract'\nimport {\n\tbuildErrorResult,\n\tcreateQuantitativeReasoner,\n\tcreateReason,\n\tisSubject,\n} from '@orkestrel/reason'\nimport { RaterError } from './errors.js'\nimport { ratedLine, sumAmounts } from './helpers.js'\nimport { isLineDefinition, isRatingDefinition } from './validators.js'\n\n/**\n * The rating orchestrator — 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 (AGENTS §9.2). `destroy()`\n * destroys an OWNED engine, then the emitter LAST (AGENTS §13); an INJECTED\n * engine is never destroyed. Afterwards every other method throws\n * {@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 (AGENTS §9.2) 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 (!isSubject(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.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 ratedLine(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 * Create 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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"}
|
|
@@ -82,6 +82,27 @@ export declare interface Evidence {
|
|
|
82
82
|
*/
|
|
83
83
|
export declare function evidenceCheck(check: Check, actual: unknown, met: boolean | undefined, labels?: Readonly<Record<string, string>>): Evidence;
|
|
84
84
|
|
|
85
|
+
/**
|
|
86
|
+
* Determine whether a value is an open result-side {@link Evidence} object.
|
|
87
|
+
*
|
|
88
|
+
* @remarks
|
|
89
|
+
* Unknown members, prototypes, and class instances are admitted. Arrays are
|
|
90
|
+
* refused. `expected` and `actual` are `unknown`, so this guard does not read or
|
|
91
|
+
* check them; either member may also be absent because `objectOf` reads declared
|
|
92
|
+
* members rather than requiring or enumerating own keys.
|
|
93
|
+
*
|
|
94
|
+
* @param value - The value to test
|
|
95
|
+
* @returns `true` when every checked `Evidence` member conforms
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* ```ts
|
|
99
|
+
* import { isEvidence } from '@orkestrel/rater'
|
|
100
|
+
*
|
|
101
|
+
* isEvidence({ field: 'age', comparison: 'above', expected: 18, actual: 25, met: true }) // true
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
104
|
+
export declare function isEvidence(value: unknown): value is Evidence;
|
|
105
|
+
|
|
85
106
|
/**
|
|
86
107
|
* Determine whether a value is an exact {@link LineDefinition} record.
|
|
87
108
|
*
|
|
@@ -102,6 +123,26 @@ export declare function evidenceCheck(check: Check, actual: unknown, met: boolea
|
|
|
102
123
|
*/
|
|
103
124
|
export declare function isLineDefinition(value: unknown): value is LineDefinition;
|
|
104
125
|
|
|
126
|
+
/**
|
|
127
|
+
* Determine whether a value is an open {@link LineResult} object.
|
|
128
|
+
*
|
|
129
|
+
* @remarks
|
|
130
|
+
* Unknown members, prototypes, and class instances are admitted. Arrays are
|
|
131
|
+
* refused. `amount` may be absent or read as `undefined`; when present it stays
|
|
132
|
+
* a plain JavaScript `number` without a finite or range refinement.
|
|
133
|
+
*
|
|
134
|
+
* @param value - The value to test
|
|
135
|
+
* @returns `true` when every published line-result member conforms
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```ts
|
|
139
|
+
* import { isLineResult } from '@orkestrel/rater'
|
|
140
|
+
*
|
|
141
|
+
* isLineResult({ id: 'base', name: 'Base', worksheet: { id: 'base', name: 'Base', aggregation: 'sum', value: 0, groups: [], steps: [], trace: [], errors: [], success: false }, success: false }) // true
|
|
142
|
+
* ```
|
|
143
|
+
*/
|
|
144
|
+
export declare function isLineResult(value: unknown): value is LineResult;
|
|
145
|
+
|
|
105
146
|
/**
|
|
106
147
|
* Narrow a caught value to a {@link RaterError}.
|
|
107
148
|
*
|
|
@@ -140,6 +181,27 @@ export declare function isRaterError(value: unknown): value is RaterError;
|
|
|
140
181
|
*/
|
|
141
182
|
export declare function isRatingDefinition(value: unknown): value is RatingDefinition;
|
|
142
183
|
|
|
184
|
+
/**
|
|
185
|
+
* Determine whether a value is an open {@link RatingResult} object.
|
|
186
|
+
*
|
|
187
|
+
* @remarks
|
|
188
|
+
* Use this guard for a result returned by a borrowed `RaterInterface`. Unknown
|
|
189
|
+
* members, prototypes, and class instances are admitted. Arrays are refused.
|
|
190
|
+
* `total` may be absent or read as `undefined`; when present it stays a plain
|
|
191
|
+
* JavaScript `number` without a finite or range refinement.
|
|
192
|
+
*
|
|
193
|
+
* @param value - The value to test
|
|
194
|
+
* @returns `true` when every published rating-result member conforms
|
|
195
|
+
*
|
|
196
|
+
* @example
|
|
197
|
+
* ```ts
|
|
198
|
+
* import { isRatingResult } from '@orkestrel/rater'
|
|
199
|
+
*
|
|
200
|
+
* isRatingResult({ lines: [], success: true }) // true
|
|
201
|
+
* ```
|
|
202
|
+
*/
|
|
203
|
+
export declare function isRatingResult(value: unknown): value is RatingResult;
|
|
204
|
+
|
|
143
205
|
/**
|
|
144
206
|
* Determine whether a value is a {@link Stage} literal.
|
|
145
207
|
*
|
|
@@ -156,6 +218,82 @@ export declare function isRatingDefinition(value: unknown): value is RatingDefin
|
|
|
156
218
|
*/
|
|
157
219
|
export declare const isStage: Guard<Stage>;
|
|
158
220
|
|
|
221
|
+
/**
|
|
222
|
+
* Determine whether a value is an open {@link Step} result object.
|
|
223
|
+
*
|
|
224
|
+
* @remarks
|
|
225
|
+
* Unknown members, prototypes, and class instances are admitted. Arrays are
|
|
226
|
+
* refused. Optional members may be absent or read as `undefined`.
|
|
227
|
+
*
|
|
228
|
+
* @param value - The value to test
|
|
229
|
+
* @returns `true` when every published worksheet-step member conforms
|
|
230
|
+
*
|
|
231
|
+
* @example
|
|
232
|
+
* ```ts
|
|
233
|
+
* import { isStep } from '@orkestrel/rater'
|
|
234
|
+
*
|
|
235
|
+
* isStep({ stage: 'total', value: 100 }) // true
|
|
236
|
+
* ```
|
|
237
|
+
*/
|
|
238
|
+
export declare function isStep(value: unknown): value is Step;
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Determine whether a value is an open {@link Worksheet} result object.
|
|
242
|
+
*
|
|
243
|
+
* @remarks
|
|
244
|
+
* Unknown members, prototypes, and class instances are admitted. Arrays are
|
|
245
|
+
* refused. Optional members may be absent or read as `undefined`.
|
|
246
|
+
*
|
|
247
|
+
* @param value - The value to test
|
|
248
|
+
* @returns `true` when every published worksheet member conforms
|
|
249
|
+
*
|
|
250
|
+
* @example
|
|
251
|
+
* ```ts
|
|
252
|
+
* import { isWorksheet } from '@orkestrel/rater'
|
|
253
|
+
*
|
|
254
|
+
* isWorksheet({ id: 'quote', name: 'Quote', aggregation: 'sum', value: 0, groups: [], steps: [], trace: [], errors: [], success: true }) // true
|
|
255
|
+
* ```
|
|
256
|
+
*/
|
|
257
|
+
export declare function isWorksheet(value: unknown): value is Worksheet;
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Determine whether a value is an open {@link WorksheetFactor} result object.
|
|
261
|
+
*
|
|
262
|
+
* @remarks
|
|
263
|
+
* Unknown members, prototypes, and class instances are admitted. Arrays are
|
|
264
|
+
* refused. Optional members may be absent or read as `undefined`.
|
|
265
|
+
*
|
|
266
|
+
* @param value - The value to test
|
|
267
|
+
* @returns `true` when every published worksheet-factor member conforms
|
|
268
|
+
*
|
|
269
|
+
* @example
|
|
270
|
+
* ```ts
|
|
271
|
+
* import { isWorksheetFactor } from '@orkestrel/rater'
|
|
272
|
+
*
|
|
273
|
+
* isWorksheetFactor({ id: 'base', applied: true, value: 100, evidence: [] }) // true
|
|
274
|
+
* ```
|
|
275
|
+
*/
|
|
276
|
+
export declare function isWorksheetFactor(value: unknown): value is WorksheetFactor;
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Determine whether a value is an open {@link WorksheetGroup} result object.
|
|
280
|
+
*
|
|
281
|
+
* @remarks
|
|
282
|
+
* Unknown members, prototypes, and class instances are admitted. Arrays are
|
|
283
|
+
* refused. Optional members may be absent or read as `undefined`.
|
|
284
|
+
*
|
|
285
|
+
* @param value - The value to test
|
|
286
|
+
* @returns `true` when every published worksheet-group member conforms
|
|
287
|
+
*
|
|
288
|
+
* @example
|
|
289
|
+
* ```ts
|
|
290
|
+
* import { isWorksheetGroup } from '@orkestrel/rater'
|
|
291
|
+
*
|
|
292
|
+
* isWorksheetGroup({ id: 'charges', applied: true, value: 100, factors: [] }) // true
|
|
293
|
+
* ```
|
|
294
|
+
*/
|
|
295
|
+
export declare function isWorksheetGroup(value: unknown): value is WorksheetGroup;
|
|
296
|
+
|
|
159
297
|
/**
|
|
160
298
|
* One rateable line — a quantitative definition joined to display metadata.
|
|
161
299
|
*
|