@lucern/confidence 0.1.0-alpha.2
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 +34 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +1833 -0
- package/dist/index.js.map +1 -0
- package/dist/v1/index.d.ts +17 -0
- package/dist/v1/index.js +1833 -0
- package/dist/v1/index.js.map +1 -0
- package/dist/v1/interfaces.d.ts +28 -0
- package/dist/v1/interfaces.js +3 -0
- package/dist/v1/interfaces.js.map +1 -0
- package/dist/v1/operations/approximation.d.ts +8 -0
- package/dist/v1/operations/approximation.js +219 -0
- package/dist/v1/operations/approximation.js.map +1 -0
- package/dist/v1/operations/bridge/index.d.ts +12 -0
- package/dist/v1/operations/bridge/index.js +89 -0
- package/dist/v1/operations/bridge/index.js.map +1 -0
- package/dist/v1/operations/canonical.d.ts +7 -0
- package/dist/v1/operations/canonical.js +199 -0
- package/dist/v1/operations/canonical.js.map +1 -0
- package/dist/v1/operations/contracts/epistemicContract.d.ts +51 -0
- package/dist/v1/operations/contracts/epistemicContract.js +320 -0
- package/dist/v1/operations/contracts/epistemicContract.js.map +1 -0
- package/dist/v1/operations/contradiction/detectTupleContradiction.d.ts +13 -0
- package/dist/v1/operations/contradiction/detectTupleContradiction.js +40 -0
- package/dist/v1/operations/contradiction/detectTupleContradiction.js.map +1 -0
- package/dist/v1/operations/contradiction/index.d.ts +2 -0
- package/dist/v1/operations/contradiction/index.js +40 -0
- package/dist/v1/operations/contradiction/index.js.map +1 -0
- package/dist/v1/operations/dynamics/cascade.d.ts +6 -0
- package/dist/v1/operations/dynamics/cascade.js +56 -0
- package/dist/v1/operations/dynamics/cascade.js.map +1 -0
- package/dist/v1/operations/dynamics/decay.d.ts +25 -0
- package/dist/v1/operations/dynamics/decay.js +271 -0
- package/dist/v1/operations/dynamics/decay.js.map +1 -0
- package/dist/v1/operations/dynamics/defeat.d.ts +6 -0
- package/dist/v1/operations/dynamics/defeat.js +134 -0
- package/dist/v1/operations/dynamics/defeat.js.map +1 -0
- package/dist/v1/operations/dynamics/propagation.d.ts +58 -0
- package/dist/v1/operations/dynamics/propagation.js +399 -0
- package/dist/v1/operations/dynamics/propagation.js.map +1 -0
- package/dist/v1/operations/dynamics/revision.d.ts +24 -0
- package/dist/v1/operations/dynamics/revision.js +111 -0
- package/dist/v1/operations/dynamics/revision.js.map +1 -0
- package/dist/v1/operations/index.d.ts +2 -0
- package/dist/v1/operations/index.js +66 -0
- package/dist/v1/operations/index.js.map +1 -0
- package/dist/v1/operations/lucern.d.ts +14 -0
- package/dist/v1/operations/lucern.js +1280 -0
- package/dist/v1/operations/lucern.js.map +1 -0
- package/dist/v1/operations/operatorTaxonomy.d.ts +366 -0
- package/dist/v1/operations/operatorTaxonomy.js +508 -0
- package/dist/v1/operations/operatorTaxonomy.js.map +1 -0
- package/dist/v1/operations/scoring.d.ts +28 -0
- package/dist/v1/operations/scoring.js +107 -0
- package/dist/v1/operations/scoring.js.map +1 -0
- package/dist/v1/operations/subjectiveLogic/index.d.ts +26 -0
- package/dist/v1/operations/subjectiveLogic/index.js +285 -0
- package/dist/v1/operations/subjectiveLogic/index.js.map +1 -0
- package/dist/v1/operations/temporalDecay.d.ts +24 -0
- package/dist/v1/operations/temporalDecay.js +66 -0
- package/dist/v1/operations/temporalDecay.js.map +1 -0
- package/dist/v1/types.d.ts +208 -0
- package/dist/v1/types.js +3 -0
- package/dist/v1/types.js.map +1 -0
- package/package.json +46 -0
|
@@ -0,0 +1,1280 @@
|
|
|
1
|
+
// src/v1/operations/subjectiveLogic/index.ts
|
|
2
|
+
function opinion(belief, disbelief, uncertainty, baseRate = 0.5) {
|
|
3
|
+
const b = Math.max(0, Math.min(1, belief));
|
|
4
|
+
const d = Math.max(0, Math.min(1, disbelief));
|
|
5
|
+
const u = Math.max(0, Math.min(1, uncertainty));
|
|
6
|
+
const a = Math.max(0, Math.min(1, baseRate));
|
|
7
|
+
const sum = b + d + u;
|
|
8
|
+
if (sum === 0) {
|
|
9
|
+
return { b: 0, d: 0, u: 1, a };
|
|
10
|
+
}
|
|
11
|
+
return {
|
|
12
|
+
b: b / sum,
|
|
13
|
+
d: d / sum,
|
|
14
|
+
u: u / sum,
|
|
15
|
+
a
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function vacuous(baseRate = 0.5) {
|
|
19
|
+
return { b: 0, d: 0, u: 1, a: baseRate };
|
|
20
|
+
}
|
|
21
|
+
function project(o) {
|
|
22
|
+
return o.b + o.a * o.u;
|
|
23
|
+
}
|
|
24
|
+
function confidenceLevel(o) {
|
|
25
|
+
const projected = project(o);
|
|
26
|
+
if (o.u > 0.5) {
|
|
27
|
+
return "low";
|
|
28
|
+
}
|
|
29
|
+
if (projected >= 0.8 && o.u < 0.2) {
|
|
30
|
+
return "high";
|
|
31
|
+
}
|
|
32
|
+
if (projected >= 0.6) {
|
|
33
|
+
return "medium";
|
|
34
|
+
}
|
|
35
|
+
return "low";
|
|
36
|
+
}
|
|
37
|
+
function cumulativeFusion(left, right) {
|
|
38
|
+
if (left.u === 0 && right.u === 0) {
|
|
39
|
+
return opinion(
|
|
40
|
+
(left.b + right.b) / 2,
|
|
41
|
+
(left.d + right.d) / 2,
|
|
42
|
+
0,
|
|
43
|
+
(left.a + right.a) / 2
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
const k = left.u + right.u - left.u * right.u;
|
|
47
|
+
if (k === 0) {
|
|
48
|
+
return vacuous((left.a + right.a) / 2);
|
|
49
|
+
}
|
|
50
|
+
return opinion(
|
|
51
|
+
(left.b * right.u + right.b * left.u) / k,
|
|
52
|
+
(left.d * right.u + right.d * left.u) / k,
|
|
53
|
+
left.u * right.u / k,
|
|
54
|
+
(left.a + right.a) / 2
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
function trustDiscount(sourceOpinion, trust) {
|
|
58
|
+
const weight = Math.max(0, Math.min(1, Math.abs(trust)));
|
|
59
|
+
return opinion(
|
|
60
|
+
weight * sourceOpinion.b,
|
|
61
|
+
weight * sourceOpinion.d,
|
|
62
|
+
1 - weight * (sourceOpinion.b + sourceOpinion.d),
|
|
63
|
+
sourceOpinion.a
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
var EPSILON = 1e-9;
|
|
67
|
+
function childBaseRateFallback(ifTrue, ifFalse, fallbackBaseRate) {
|
|
68
|
+
if (fallbackBaseRate !== void 0) {
|
|
69
|
+
return Math.max(0, Math.min(1, fallbackBaseRate));
|
|
70
|
+
}
|
|
71
|
+
if (Math.abs(ifTrue.a - ifFalse.a) <= EPSILON) {
|
|
72
|
+
return ifTrue.a;
|
|
73
|
+
}
|
|
74
|
+
return (ifTrue.a + ifFalse.a) / 2;
|
|
75
|
+
}
|
|
76
|
+
function computeConditionalDeductionBaseRate(opinionA, ifTrue, ifFalse, fallbackBaseRate) {
|
|
77
|
+
const denominator = 1 - opinionA.a * ifTrue.u - (1 - opinionA.a) * ifFalse.u;
|
|
78
|
+
if (ifTrue.u + ifFalse.u < 2 - EPSILON && Math.abs(denominator) > EPSILON) {
|
|
79
|
+
const baseRate = (opinionA.a * ifTrue.b + (1 - opinionA.a) * ifFalse.b) / denominator;
|
|
80
|
+
if (baseRate >= -EPSILON && baseRate <= 1 + EPSILON) {
|
|
81
|
+
return Math.max(0, Math.min(1, baseRate));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return fallbackBaseRate;
|
|
85
|
+
}
|
|
86
|
+
function safeCorrectionTerm(numerator, denominator) {
|
|
87
|
+
if (Math.abs(denominator) <= EPSILON) {
|
|
88
|
+
return void 0;
|
|
89
|
+
}
|
|
90
|
+
const value = numerator / denominator;
|
|
91
|
+
if (!Number.isFinite(value)) {
|
|
92
|
+
return void 0;
|
|
93
|
+
}
|
|
94
|
+
return Math.max(0, value);
|
|
95
|
+
}
|
|
96
|
+
function conditionalDeduction(opinionA, ifTrue, ifFalse, fallbackBaseRate) {
|
|
97
|
+
const fallbackChildBaseRate = childBaseRateFallback(
|
|
98
|
+
ifTrue,
|
|
99
|
+
ifFalse,
|
|
100
|
+
fallbackBaseRate
|
|
101
|
+
);
|
|
102
|
+
const childBaseRate = computeConditionalDeductionBaseRate(
|
|
103
|
+
opinionA,
|
|
104
|
+
ifTrue,
|
|
105
|
+
ifFalse,
|
|
106
|
+
fallbackChildBaseRate
|
|
107
|
+
);
|
|
108
|
+
const projectedAntecedent = project(opinionA);
|
|
109
|
+
const projectedAntecedentComplement = 1 - projectedAntecedent;
|
|
110
|
+
const intermediateBelief = opinionA.b * ifTrue.b + opinionA.d * ifFalse.b + opinionA.u * (ifTrue.b * opinionA.a + ifFalse.b * (1 - opinionA.a));
|
|
111
|
+
const intermediateDisbelief = opinionA.b * ifTrue.d + opinionA.d * ifFalse.d + opinionA.u * (ifTrue.d * opinionA.a + ifFalse.d * (1 - opinionA.a));
|
|
112
|
+
const intermediateUncertainty = opinionA.b * ifTrue.u + opinionA.d * ifFalse.u + opinionA.u * (ifTrue.u * opinionA.a + ifFalse.u * (1 - opinionA.a));
|
|
113
|
+
const projectedVacuousDeduction = ifTrue.b * opinionA.a + ifFalse.b * (1 - opinionA.a) + childBaseRate * (ifTrue.u * opinionA.a + ifFalse.u * (1 - opinionA.a));
|
|
114
|
+
const projectedConditionalA = ifTrue.b + childBaseRate * (1 - ifTrue.b - ifTrue.d);
|
|
115
|
+
let correction = 0;
|
|
116
|
+
if (ifTrue.b > ifFalse.b && ifTrue.d > ifFalse.d || ifTrue.b <= ifFalse.b && ifTrue.d <= ifFalse.d) {
|
|
117
|
+
correction = 0;
|
|
118
|
+
} else if (ifTrue.b > ifFalse.b && ifTrue.d <= ifFalse.d) {
|
|
119
|
+
const beliefGap = ifTrue.b - ifFalse.b;
|
|
120
|
+
const disbeliefGap = ifFalse.d - ifTrue.d;
|
|
121
|
+
if (projectedVacuousDeduction <= projectedConditionalA && projectedAntecedent <= opinionA.a) {
|
|
122
|
+
correction = safeCorrectionTerm(
|
|
123
|
+
opinionA.a * opinionA.u * (intermediateBelief - ifTrue.b),
|
|
124
|
+
projectedAntecedent * childBaseRate
|
|
125
|
+
) ?? 0;
|
|
126
|
+
} else if (projectedVacuousDeduction <= projectedConditionalA && projectedAntecedent > opinionA.a) {
|
|
127
|
+
correction = safeCorrectionTerm(
|
|
128
|
+
opinionA.a * opinionA.u * (intermediateDisbelief - ifTrue.d) * beliefGap,
|
|
129
|
+
projectedAntecedentComplement * childBaseRate * disbeliefGap
|
|
130
|
+
) ?? 0;
|
|
131
|
+
} else if (projectedVacuousDeduction > projectedConditionalA && projectedAntecedent <= opinionA.a) {
|
|
132
|
+
correction = safeCorrectionTerm(
|
|
133
|
+
(1 - opinionA.a) * opinionA.u * (intermediateBelief - ifTrue.b) * disbeliefGap,
|
|
134
|
+
projectedAntecedent * (1 - childBaseRate) * beliefGap
|
|
135
|
+
) ?? 0;
|
|
136
|
+
} else {
|
|
137
|
+
correction = safeCorrectionTerm(
|
|
138
|
+
(1 - opinionA.a) * opinionA.u * (intermediateDisbelief - ifTrue.d),
|
|
139
|
+
projectedAntecedentComplement * (1 - childBaseRate)
|
|
140
|
+
) ?? 0;
|
|
141
|
+
}
|
|
142
|
+
} else {
|
|
143
|
+
const beliefGap = ifFalse.b - ifTrue.b;
|
|
144
|
+
const disbeliefGap = ifTrue.d - ifFalse.d;
|
|
145
|
+
if (projectedVacuousDeduction <= projectedConditionalA && projectedAntecedent <= opinionA.a) {
|
|
146
|
+
correction = safeCorrectionTerm(
|
|
147
|
+
(1 - opinionA.a) * opinionA.u * (intermediateDisbelief - ifTrue.d) * beliefGap,
|
|
148
|
+
projectedAntecedent * childBaseRate * disbeliefGap
|
|
149
|
+
) ?? 0;
|
|
150
|
+
} else if (projectedVacuousDeduction <= projectedConditionalA && projectedAntecedent > opinionA.a) {
|
|
151
|
+
correction = safeCorrectionTerm(
|
|
152
|
+
(1 - opinionA.a) * opinionA.u * (intermediateBelief - ifTrue.b),
|
|
153
|
+
projectedAntecedentComplement * childBaseRate
|
|
154
|
+
) ?? 0;
|
|
155
|
+
} else if (projectedVacuousDeduction > projectedConditionalA && projectedAntecedent <= opinionA.a) {
|
|
156
|
+
correction = safeCorrectionTerm(
|
|
157
|
+
opinionA.a * opinionA.u * (intermediateDisbelief - ifTrue.d),
|
|
158
|
+
projectedAntecedent * (1 - childBaseRate)
|
|
159
|
+
) ?? 0;
|
|
160
|
+
} else {
|
|
161
|
+
correction = safeCorrectionTerm(
|
|
162
|
+
opinionA.a * opinionA.u * (intermediateBelief - ifTrue.b) * disbeliefGap,
|
|
163
|
+
projectedAntecedentComplement * (1 - childBaseRate) * beliefGap
|
|
164
|
+
) ?? 0;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return opinion(
|
|
168
|
+
intermediateBelief - childBaseRate * correction,
|
|
169
|
+
intermediateDisbelief - (1 - childBaseRate) * correction,
|
|
170
|
+
intermediateUncertainty + correction,
|
|
171
|
+
childBaseRate
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
function negate(o) {
|
|
175
|
+
return { b: o.d, d: o.b, u: o.u, a: 1 - o.a };
|
|
176
|
+
}
|
|
177
|
+
function constraintFusion(left, right, mode = "pressure") {
|
|
178
|
+
if (mode === "redistribute") {
|
|
179
|
+
const leftProjected = project(left);
|
|
180
|
+
const rightProjected = project(right);
|
|
181
|
+
const total = leftProjected + rightProjected;
|
|
182
|
+
if (total <= 1) {
|
|
183
|
+
return { o1: left, o2: right };
|
|
184
|
+
}
|
|
185
|
+
const scale = 1 / total;
|
|
186
|
+
return {
|
|
187
|
+
o1: opinion(
|
|
188
|
+
left.b * scale,
|
|
189
|
+
left.d + left.b * (1 - scale),
|
|
190
|
+
left.u,
|
|
191
|
+
left.a
|
|
192
|
+
),
|
|
193
|
+
o2: opinion(
|
|
194
|
+
right.b * scale,
|
|
195
|
+
right.d + right.b * (1 - scale),
|
|
196
|
+
right.u,
|
|
197
|
+
right.a
|
|
198
|
+
)
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
const pressureLeft = right.b * 0.5;
|
|
202
|
+
const pressureRight = left.b * 0.5;
|
|
203
|
+
return {
|
|
204
|
+
o1: opinion(
|
|
205
|
+
left.b - pressureLeft * 0.3,
|
|
206
|
+
left.d + pressureLeft * 0.3,
|
|
207
|
+
left.u,
|
|
208
|
+
left.a
|
|
209
|
+
),
|
|
210
|
+
o2: opinion(
|
|
211
|
+
right.b - pressureRight * 0.3,
|
|
212
|
+
right.d + pressureRight * 0.3,
|
|
213
|
+
right.u,
|
|
214
|
+
right.a
|
|
215
|
+
)
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
function evidenceBalance(o) {
|
|
219
|
+
const total = o.b + o.d;
|
|
220
|
+
if (total === 0) {
|
|
221
|
+
return 0;
|
|
222
|
+
}
|
|
223
|
+
return (o.b - o.d) / total;
|
|
224
|
+
}
|
|
225
|
+
function areTensioned(left, right) {
|
|
226
|
+
return project(left) > 0.5 && project(right) > 0.5 && (left.d > 0.2 || right.d > 0.2);
|
|
227
|
+
}
|
|
228
|
+
function informationGain(o) {
|
|
229
|
+
if (o.u === 0) {
|
|
230
|
+
return 0;
|
|
231
|
+
}
|
|
232
|
+
if (o.u === 1) {
|
|
233
|
+
return 1;
|
|
234
|
+
}
|
|
235
|
+
return o.u * (1 - Math.abs(o.b - o.d));
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// src/v1/operations/scoring.ts
|
|
239
|
+
function finiteNumber(value) {
|
|
240
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
241
|
+
}
|
|
242
|
+
function clamp01(value) {
|
|
243
|
+
return Math.max(0, Math.min(1, value));
|
|
244
|
+
}
|
|
245
|
+
function confidenceFromOpinion(opinion2) {
|
|
246
|
+
return clamp01(opinion2.b + opinion2.a * opinion2.u);
|
|
247
|
+
}
|
|
248
|
+
function toStoredOpinionFields(opinion2) {
|
|
249
|
+
return {
|
|
250
|
+
belief: opinion2.b,
|
|
251
|
+
disbelief: opinion2.d,
|
|
252
|
+
uncertainty: opinion2.u,
|
|
253
|
+
baseRate: opinion2.a
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
function readOpinionFromRecord(source, fallback = {}) {
|
|
257
|
+
const record = source && typeof source === "object" ? source : {};
|
|
258
|
+
return {
|
|
259
|
+
b: finiteNumber(record.b) ?? finiteNumber(record.belief) ?? finiteNumber(record.slBelief) ?? finiteNumber(record.opinion_b) ?? fallback.b ?? 0,
|
|
260
|
+
d: finiteNumber(record.d) ?? finiteNumber(record.disbelief) ?? finiteNumber(record.slDisbelief) ?? finiteNumber(record.opinion_d) ?? fallback.d ?? 0,
|
|
261
|
+
u: finiteNumber(record.u) ?? finiteNumber(record.uncertainty) ?? finiteNumber(record.slUncertainty) ?? finiteNumber(record.opinion_u) ?? fallback.u ?? 1,
|
|
262
|
+
a: finiteNumber(record.a) ?? finiteNumber(record.baseRate) ?? finiteNumber(record.slBaseRate) ?? finiteNumber(record.opinion_a) ?? fallback.a ?? 0.5
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
function opinionFromScalar(value, mode, options) {
|
|
266
|
+
const clampedValue = clamp01(value);
|
|
267
|
+
const baseRate = clamp01(options?.baseRate ?? 0.5);
|
|
268
|
+
switch (mode) {
|
|
269
|
+
case "base_rate":
|
|
270
|
+
return {
|
|
271
|
+
b: 0,
|
|
272
|
+
d: 0,
|
|
273
|
+
u: 1,
|
|
274
|
+
a: clampedValue
|
|
275
|
+
};
|
|
276
|
+
case "dogmatic":
|
|
277
|
+
return {
|
|
278
|
+
b: clampedValue,
|
|
279
|
+
d: 1 - clampedValue,
|
|
280
|
+
u: 0,
|
|
281
|
+
a: baseRate
|
|
282
|
+
};
|
|
283
|
+
case "projected_with_u": {
|
|
284
|
+
const uncertainty = options?.uncertainty;
|
|
285
|
+
if (uncertainty === void 0) {
|
|
286
|
+
throw new Error(
|
|
287
|
+
'opinionFromScalar(value, "projected_with_u") requires options.uncertainty.'
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
const clampedUncertainty = clamp01(uncertainty);
|
|
291
|
+
const evidenceWeight = 1 - clampedUncertainty;
|
|
292
|
+
return {
|
|
293
|
+
b: clampedValue * evidenceWeight,
|
|
294
|
+
d: (1 - clampedValue) * evidenceWeight,
|
|
295
|
+
u: clampedUncertainty,
|
|
296
|
+
a: baseRate
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
throw new Error(`Unsupported opinionFromScalar mode: ${mode}`);
|
|
301
|
+
}
|
|
302
|
+
function toDogmaticOpinion(confidence, baseRate = 0.5) {
|
|
303
|
+
return opinionFromScalar(confidence, "dogmatic", { baseRate });
|
|
304
|
+
}
|
|
305
|
+
function hasProjectedOpinionChanged(current, next, tolerance = 0.01) {
|
|
306
|
+
return Math.abs(confidenceFromOpinion(next) - confidenceFromOpinion(current)) >= tolerance;
|
|
307
|
+
}
|
|
308
|
+
function toEpochMs(value) {
|
|
309
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
310
|
+
return value;
|
|
311
|
+
}
|
|
312
|
+
if (value instanceof Date) {
|
|
313
|
+
const epochMs = value.getTime();
|
|
314
|
+
return Number.isFinite(epochMs) ? epochMs : void 0;
|
|
315
|
+
}
|
|
316
|
+
return void 0;
|
|
317
|
+
}
|
|
318
|
+
function normalizeHalfLifeMs(halfLifeMs) {
|
|
319
|
+
if (halfLifeMs === void 0 || !Number.isFinite(halfLifeMs)) {
|
|
320
|
+
return 0;
|
|
321
|
+
}
|
|
322
|
+
return Math.max(0, halfLifeMs);
|
|
323
|
+
}
|
|
324
|
+
function temporalDecay(sourceOpinion, now, decayParams) {
|
|
325
|
+
const halfLifeMs = normalizeHalfLifeMs(decayParams.halfLifeMs);
|
|
326
|
+
if (halfLifeMs === 0) {
|
|
327
|
+
return { ...sourceOpinion };
|
|
328
|
+
}
|
|
329
|
+
const nowMs = toEpochMs(now);
|
|
330
|
+
const referenceTimeMs = toEpochMs(decayParams.referenceTime);
|
|
331
|
+
if (nowMs === void 0 || referenceTimeMs === void 0) {
|
|
332
|
+
return { ...sourceOpinion };
|
|
333
|
+
}
|
|
334
|
+
const ageMs = Math.max(0, nowMs - referenceTimeMs);
|
|
335
|
+
if (ageMs === 0) {
|
|
336
|
+
return { ...sourceOpinion };
|
|
337
|
+
}
|
|
338
|
+
const retainedEvidenceWeight = Math.pow(0.5, ageMs / halfLifeMs);
|
|
339
|
+
return trustDiscount(sourceOpinion, retainedEvidenceWeight);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// src/v1/operations/contradiction/detectTupleContradiction.ts
|
|
343
|
+
var DEFAULT_TUPLE_CONTRADICTION_BELIEF_THRESHOLD = 0.7;
|
|
344
|
+
var DEFAULT_TUPLE_CONTRADICTION_DISBELIEF_THRESHOLD = 0.7;
|
|
345
|
+
function normalizeTupleContradictionPolicy(policy = {}) {
|
|
346
|
+
return {
|
|
347
|
+
beliefThreshold: clamp01(
|
|
348
|
+
policy.beliefThreshold ?? DEFAULT_TUPLE_CONTRADICTION_BELIEF_THRESHOLD
|
|
349
|
+
),
|
|
350
|
+
disbeliefThreshold: clamp01(
|
|
351
|
+
policy.disbeliefThreshold ?? DEFAULT_TUPLE_CONTRADICTION_DISBELIEF_THRESHOLD
|
|
352
|
+
)
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
function detectTupleContradiction(opinion2, tauB = DEFAULT_TUPLE_CONTRADICTION_BELIEF_THRESHOLD, tauD = DEFAULT_TUPLE_CONTRADICTION_DISBELIEF_THRESHOLD) {
|
|
356
|
+
return opinion2.b > tauB && opinion2.d > tauD;
|
|
357
|
+
}
|
|
358
|
+
function evaluateTupleContradictionTransition(args) {
|
|
359
|
+
const policy = normalizeTupleContradictionPolicy(args.policy);
|
|
360
|
+
const tupleContradicted = detectTupleContradiction(
|
|
361
|
+
args.opinion,
|
|
362
|
+
policy.beliefThreshold,
|
|
363
|
+
policy.disbeliefThreshold
|
|
364
|
+
);
|
|
365
|
+
const previousTupleContradicted = Boolean(args.previousTupleContradicted);
|
|
366
|
+
return {
|
|
367
|
+
tupleContradicted,
|
|
368
|
+
crossedIntoTupleContradiction: !previousTupleContradicted && tupleContradicted,
|
|
369
|
+
crossedOutOfTupleContradiction: previousTupleContradicted && !tupleContradicted,
|
|
370
|
+
policy
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// src/v1/operations/dynamics/cascade.ts
|
|
375
|
+
function dampedDependencyOpinion(dependencyOpinion, beliefOpinion, mode = "continuous", threshold = 0.3) {
|
|
376
|
+
const dependencyProjection = project(dependencyOpinion);
|
|
377
|
+
if (mode === "threshold") {
|
|
378
|
+
if (dependencyProjection < threshold) {
|
|
379
|
+
return opinion(
|
|
380
|
+
0,
|
|
381
|
+
beliefOpinion.d + beliefOpinion.b * 0.5,
|
|
382
|
+
0.5,
|
|
383
|
+
beliefOpinion.a
|
|
384
|
+
);
|
|
385
|
+
}
|
|
386
|
+
return beliefOpinion;
|
|
387
|
+
}
|
|
388
|
+
const dampingFactor = Math.pow(dependencyProjection, 0.5);
|
|
389
|
+
return opinion(
|
|
390
|
+
beliefOpinion.b * dampingFactor,
|
|
391
|
+
beliefOpinion.d + beliefOpinion.b * (1 - dampingFactor) * 0.3,
|
|
392
|
+
beliefOpinion.u + beliefOpinion.b * (1 - dampingFactor) * 0.7,
|
|
393
|
+
beliefOpinion.a
|
|
394
|
+
);
|
|
395
|
+
}
|
|
396
|
+
function dampedDependencyCascade(dependencyOpinion, beliefOpinion, mode = "continuous") {
|
|
397
|
+
return {
|
|
398
|
+
opinion: dampedDependencyOpinion(dependencyOpinion, beliefOpinion, mode),
|
|
399
|
+
operator: "dependency_cascade",
|
|
400
|
+
rationale: `Damped dependency cascade (${mode}): prerequisite at ${project(
|
|
401
|
+
dependencyOpinion
|
|
402
|
+
).toFixed(2)}`
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// src/v1/operations/dynamics/defeat.ts
|
|
407
|
+
function applyNegativeSupport(source, target, weight, metadata = {}) {
|
|
408
|
+
if (metadata.constraint === "xor") {
|
|
409
|
+
const result = constraintFusion(
|
|
410
|
+
source,
|
|
411
|
+
target,
|
|
412
|
+
metadata.normalization ?? "pressure"
|
|
413
|
+
);
|
|
414
|
+
return {
|
|
415
|
+
opinion: result.o2,
|
|
416
|
+
operator: "constraint_fusion",
|
|
417
|
+
rationale: `XOR constraint: source belief at ${project(source).toFixed(
|
|
418
|
+
2
|
|
419
|
+
)} pressures target`
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
const discounted = trustDiscount(negate(source), Math.abs(weight));
|
|
423
|
+
return {
|
|
424
|
+
opinion: cumulativeFusion(target, discounted),
|
|
425
|
+
operator: "cumulative_fusion",
|
|
426
|
+
rationale: `Contradicting evidence (weight=${weight.toFixed(
|
|
427
|
+
2
|
|
428
|
+
)}) from source at ${project(source).toFixed(2)}`
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
function applyNegativeEvidence(source, target, weight) {
|
|
432
|
+
const discounted = trustDiscount(negate(source), Math.abs(weight));
|
|
433
|
+
return {
|
|
434
|
+
opinion: cumulativeFusion(target, discounted),
|
|
435
|
+
operator: "cumulative_fusion",
|
|
436
|
+
rationale: `Contradicting evidence (weight=${weight.toFixed(2)})`
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// src/v1/operations/dynamics/propagation.ts
|
|
441
|
+
var EDGE_PROPAGATION_RULES = {
|
|
442
|
+
supports: {
|
|
443
|
+
direction: "outgoing",
|
|
444
|
+
handler: (source, target, weight, metadata) => {
|
|
445
|
+
if (weight < 0) {
|
|
446
|
+
return applyNegativeSupport(source, target, weight, metadata);
|
|
447
|
+
}
|
|
448
|
+
const discounted = trustDiscount(source, weight);
|
|
449
|
+
return {
|
|
450
|
+
opinion: cumulativeFusion(target, discounted),
|
|
451
|
+
operator: "cumulative_fusion",
|
|
452
|
+
rationale: `Supporting evidence (weight=${weight.toFixed(
|
|
453
|
+
2
|
|
454
|
+
)}) from source at ${project(source).toFixed(2)}`
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
},
|
|
458
|
+
informs: {
|
|
459
|
+
direction: "outgoing",
|
|
460
|
+
handler: (source, target, weight) => {
|
|
461
|
+
if (weight < 0) {
|
|
462
|
+
return applyNegativeEvidence(source, target, weight);
|
|
463
|
+
}
|
|
464
|
+
const discounted = trustDiscount(source, Math.abs(weight));
|
|
465
|
+
return {
|
|
466
|
+
opinion: cumulativeFusion(target, discounted),
|
|
467
|
+
operator: "cumulative_fusion",
|
|
468
|
+
rationale: `Supporting evidence (weight=${weight.toFixed(2)})`
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
},
|
|
472
|
+
depends_on: {
|
|
473
|
+
direction: "incoming",
|
|
474
|
+
handler: (source, target, _weight, metadata) => {
|
|
475
|
+
if (metadata.conditionalA && metadata.conditionalNotA) {
|
|
476
|
+
return {
|
|
477
|
+
opinion: conditionalDeduction(
|
|
478
|
+
source,
|
|
479
|
+
metadata.conditionalA,
|
|
480
|
+
metadata.conditionalNotA,
|
|
481
|
+
target.a
|
|
482
|
+
),
|
|
483
|
+
operator: "conditional_deduction",
|
|
484
|
+
rationale: `Conditional deduction: prerequisite at ${project(
|
|
485
|
+
source
|
|
486
|
+
).toFixed(2)}`
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
return dampedDependencyCascade(
|
|
490
|
+
source,
|
|
491
|
+
target,
|
|
492
|
+
metadata.propagation ?? "continuous"
|
|
493
|
+
);
|
|
494
|
+
}
|
|
495
|
+
},
|
|
496
|
+
derived_from: {
|
|
497
|
+
direction: "incoming",
|
|
498
|
+
handler: (_source, target) => ({
|
|
499
|
+
opinion: target,
|
|
500
|
+
operator: "trust_discount",
|
|
501
|
+
rationale: "Provenance edge \u2014 no confidence propagation"
|
|
502
|
+
})
|
|
503
|
+
},
|
|
504
|
+
contains: {
|
|
505
|
+
direction: "outgoing",
|
|
506
|
+
handler: (_source, target) => ({
|
|
507
|
+
opinion: target,
|
|
508
|
+
operator: "trust_discount",
|
|
509
|
+
rationale: "Containment edge \u2014 no confidence propagation"
|
|
510
|
+
})
|
|
511
|
+
},
|
|
512
|
+
tests: {
|
|
513
|
+
direction: "outgoing",
|
|
514
|
+
handler: (_source, target) => ({
|
|
515
|
+
opinion: target,
|
|
516
|
+
operator: "trust_discount",
|
|
517
|
+
rationale: "Testing edge \u2014 no confidence propagation"
|
|
518
|
+
})
|
|
519
|
+
}
|
|
520
|
+
};
|
|
521
|
+
var PROPAGATION_TRAVERSAL_SPECS = Object.entries(EDGE_PROPAGATION_RULES).map(([edgeType, rule]) => ({
|
|
522
|
+
edgeType,
|
|
523
|
+
direction: rule.direction
|
|
524
|
+
}));
|
|
525
|
+
function isPropagationEdgeType(edgeType) {
|
|
526
|
+
return edgeType in EDGE_PROPAGATION_RULES;
|
|
527
|
+
}
|
|
528
|
+
function getPropagationTraversalSpecs() {
|
|
529
|
+
return PROPAGATION_TRAVERSAL_SPECS;
|
|
530
|
+
}
|
|
531
|
+
function propagateThroughEdge(sourceOpinion, targetOpinion, edgeType, weight = 1, metadata = {}) {
|
|
532
|
+
const handler = isPropagationEdgeType(edgeType) ? EDGE_PROPAGATION_RULES[edgeType].handler : void 0;
|
|
533
|
+
if (!handler) {
|
|
534
|
+
return {
|
|
535
|
+
opinion: targetOpinion,
|
|
536
|
+
operator: "manual_assessment",
|
|
537
|
+
rationale: `Unknown edge type: ${edgeType} \u2014 no propagation`
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
return handler(sourceOpinion, targetOpinion, weight, metadata);
|
|
541
|
+
}
|
|
542
|
+
function propagateAllEdges(currentOpinion, incomingEdges) {
|
|
543
|
+
let result = currentOpinion;
|
|
544
|
+
const rationales = [];
|
|
545
|
+
for (const edgeType of ["depends_on", "informs", "supports"]) {
|
|
546
|
+
for (const incoming of incomingEdges.filter((edge) => edge.edgeType === edgeType)) {
|
|
547
|
+
const propagated = propagateThroughEdge(
|
|
548
|
+
incoming.sourceOpinion,
|
|
549
|
+
result,
|
|
550
|
+
incoming.edgeType,
|
|
551
|
+
incoming.weight,
|
|
552
|
+
incoming.metadata
|
|
553
|
+
);
|
|
554
|
+
result = propagated.opinion;
|
|
555
|
+
rationales.push(propagated.rationale);
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
return {
|
|
559
|
+
opinion: result,
|
|
560
|
+
operator: "cumulative_fusion",
|
|
561
|
+
rationale: rationales.join("; ")
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
// src/v1/operations/bridge/index.ts
|
|
566
|
+
var DEFAULT_NON_INFORMATIVE_WEIGHT = 2;
|
|
567
|
+
function clamp012(value) {
|
|
568
|
+
return Math.max(0, Math.min(1, value));
|
|
569
|
+
}
|
|
570
|
+
function clampNonNegative(value) {
|
|
571
|
+
return Number.isFinite(value) ? Math.max(0, value) : 0;
|
|
572
|
+
}
|
|
573
|
+
function normalizeNonInformativeWeight(weight) {
|
|
574
|
+
if (weight === void 0) {
|
|
575
|
+
return DEFAULT_NON_INFORMATIVE_WEIGHT;
|
|
576
|
+
}
|
|
577
|
+
return Number.isFinite(weight) ? Math.max(0, weight) : DEFAULT_NON_INFORMATIVE_WEIGHT;
|
|
578
|
+
}
|
|
579
|
+
function normalizeBaseRateVector(baseRate, size) {
|
|
580
|
+
if (size === 0) {
|
|
581
|
+
return [];
|
|
582
|
+
}
|
|
583
|
+
const fallback = Array.from({ length: size }, () => 1 / size);
|
|
584
|
+
if (!baseRate) {
|
|
585
|
+
return fallback;
|
|
586
|
+
}
|
|
587
|
+
if (baseRate.length !== size) {
|
|
588
|
+
throw new Error(
|
|
589
|
+
`Base-rate vector length ${baseRate.length} must match evidence vector length ${size}.`
|
|
590
|
+
);
|
|
591
|
+
}
|
|
592
|
+
const normalized = baseRate.map((value) => clampNonNegative(value));
|
|
593
|
+
const total = normalized.reduce((sum, value) => sum + value, 0);
|
|
594
|
+
if (total === 0) {
|
|
595
|
+
return fallback;
|
|
596
|
+
}
|
|
597
|
+
return normalized.map((value) => value / total);
|
|
598
|
+
}
|
|
599
|
+
function opinionFromDirichlet(alpha, nonInformativeWeight = DEFAULT_NON_INFORMATIVE_WEIGHT, baseRate) {
|
|
600
|
+
const evidence = alpha.map((value) => clampNonNegative(value));
|
|
601
|
+
const safeWeight = normalizeNonInformativeWeight(nonInformativeWeight);
|
|
602
|
+
const normalizedBaseRate = normalizeBaseRateVector(baseRate, evidence.length);
|
|
603
|
+
const totalEvidence = evidence.reduce((sum, value) => sum + value, 0);
|
|
604
|
+
const denominator = totalEvidence + safeWeight;
|
|
605
|
+
if (denominator === 0) {
|
|
606
|
+
return {
|
|
607
|
+
b: evidence.map(() => 0),
|
|
608
|
+
u: 1,
|
|
609
|
+
a: normalizedBaseRate
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
return {
|
|
613
|
+
b: evidence.map((value) => value / denominator),
|
|
614
|
+
u: safeWeight / denominator,
|
|
615
|
+
a: normalizedBaseRate
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
function opinionFromBeta(alpha, beta, nonInformativeWeight = DEFAULT_NON_INFORMATIVE_WEIGHT, baseRate = 0.5) {
|
|
619
|
+
const dirichlet = opinionFromDirichlet(
|
|
620
|
+
[alpha, beta],
|
|
621
|
+
nonInformativeWeight,
|
|
622
|
+
[clamp012(baseRate), 1 - clamp012(baseRate)]
|
|
623
|
+
);
|
|
624
|
+
return {
|
|
625
|
+
b: dirichlet.b[0] ?? 0,
|
|
626
|
+
d: dirichlet.b[1] ?? 0,
|
|
627
|
+
u: dirichlet.u,
|
|
628
|
+
a: dirichlet.a[0] ?? clamp012(baseRate)
|
|
629
|
+
};
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
// src/v1/operations/dynamics/revision.ts
|
|
633
|
+
function clamp013(value) {
|
|
634
|
+
return Math.max(0, Math.min(1, value));
|
|
635
|
+
}
|
|
636
|
+
function toEvidence(probability, weight) {
|
|
637
|
+
const safeProbability = clamp013(probability);
|
|
638
|
+
const safeWeight = Number.isFinite(weight) ? Math.max(0, weight) : 0;
|
|
639
|
+
return {
|
|
640
|
+
alpha: safeProbability * safeWeight,
|
|
641
|
+
beta: (1 - safeProbability) * safeWeight
|
|
642
|
+
};
|
|
643
|
+
}
|
|
644
|
+
function bayesianUpdate(priorConfidence, priorWeight, newAssessment, newWeight, options) {
|
|
645
|
+
return reviseConfidence({
|
|
646
|
+
priorConfidence,
|
|
647
|
+
priorWeight,
|
|
648
|
+
newAssessment,
|
|
649
|
+
newWeight,
|
|
650
|
+
baseRate: options?.baseRate,
|
|
651
|
+
nonInformativeWeight: options?.nonInformativeWeight
|
|
652
|
+
});
|
|
653
|
+
}
|
|
654
|
+
function reviseConfidence(args) {
|
|
655
|
+
return project(reviseConfidenceOpinion(args));
|
|
656
|
+
}
|
|
657
|
+
function reviseConfidenceOpinion(args) {
|
|
658
|
+
const priorEvidence = toEvidence(args.priorConfidence, args.priorWeight);
|
|
659
|
+
const newEvidence = toEvidence(args.newAssessment, args.newWeight ?? 1);
|
|
660
|
+
return opinionFromBeta(
|
|
661
|
+
priorEvidence.alpha + newEvidence.alpha,
|
|
662
|
+
priorEvidence.beta + newEvidence.beta,
|
|
663
|
+
args.nonInformativeWeight ?? DEFAULT_NON_INFORMATIVE_WEIGHT,
|
|
664
|
+
args.baseRate ?? 0.5
|
|
665
|
+
);
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
// src/v1/operations/dynamics/decay.ts
|
|
669
|
+
var DECAY_TIERS = {
|
|
670
|
+
FRESH: {
|
|
671
|
+
maxAgeDays: 30,
|
|
672
|
+
weight: 1,
|
|
673
|
+
label: "fresh",
|
|
674
|
+
action: "Full confidence \u2014 recently validated",
|
|
675
|
+
rescoreInDays: 30
|
|
676
|
+
},
|
|
677
|
+
AGING: {
|
|
678
|
+
maxAgeDays: 90,
|
|
679
|
+
weight: 0.8,
|
|
680
|
+
label: "aging",
|
|
681
|
+
action: "Evidence refresh recommended",
|
|
682
|
+
rescoreInDays: 14
|
|
683
|
+
},
|
|
684
|
+
STALE: {
|
|
685
|
+
maxAgeDays: 180,
|
|
686
|
+
weight: 0.5,
|
|
687
|
+
label: "stale",
|
|
688
|
+
action: "Evidence update required before trusting",
|
|
689
|
+
rescoreInDays: 7
|
|
690
|
+
},
|
|
691
|
+
EXPIRED: {
|
|
692
|
+
maxAgeDays: Number.POSITIVE_INFINITY,
|
|
693
|
+
weight: 0.2,
|
|
694
|
+
label: "expired",
|
|
695
|
+
action: "Full re-evaluation needed",
|
|
696
|
+
rescoreInDays: 0
|
|
697
|
+
}
|
|
698
|
+
};
|
|
699
|
+
var DEADLINE_URGENCY = {
|
|
700
|
+
DISTANT: {
|
|
701
|
+
minDaysToDeadline: 365,
|
|
702
|
+
urgencyMultiplier: 1,
|
|
703
|
+
label: "distant",
|
|
704
|
+
rescoreIntervalDays: 90,
|
|
705
|
+
action: "Quarterly confidence check"
|
|
706
|
+
},
|
|
707
|
+
APPROACHING: {
|
|
708
|
+
minDaysToDeadline: 180,
|
|
709
|
+
urgencyMultiplier: 0.9,
|
|
710
|
+
label: "approaching",
|
|
711
|
+
rescoreIntervalDays: 30,
|
|
712
|
+
action: "Monthly confidence check \u2014 conditions may be shifting"
|
|
713
|
+
},
|
|
714
|
+
NEAR: {
|
|
715
|
+
minDaysToDeadline: 90,
|
|
716
|
+
urgencyMultiplier: 0.75,
|
|
717
|
+
label: "near",
|
|
718
|
+
rescoreIntervalDays: 14,
|
|
719
|
+
action: "Biweekly rescore \u2014 deadline within 3 months"
|
|
720
|
+
},
|
|
721
|
+
IMMINENT: {
|
|
722
|
+
minDaysToDeadline: 30,
|
|
723
|
+
urgencyMultiplier: 0.6,
|
|
724
|
+
label: "imminent",
|
|
725
|
+
rescoreIntervalDays: 7,
|
|
726
|
+
action: "Weekly rescore \u2014 deadline within 1 month"
|
|
727
|
+
},
|
|
728
|
+
CRITICAL: {
|
|
729
|
+
minDaysToDeadline: 7,
|
|
730
|
+
urgencyMultiplier: 0.4,
|
|
731
|
+
label: "critical",
|
|
732
|
+
rescoreIntervalDays: 1,
|
|
733
|
+
action: "Daily rescore \u2014 deadline THIS WEEK"
|
|
734
|
+
},
|
|
735
|
+
OVERDUE: {
|
|
736
|
+
minDaysToDeadline: Number.NEGATIVE_INFINITY,
|
|
737
|
+
urgencyMultiplier: 0.2,
|
|
738
|
+
label: "overdue",
|
|
739
|
+
rescoreIntervalDays: 0,
|
|
740
|
+
action: "OVERDUE \u2014 must validate or archive immediately"
|
|
741
|
+
}
|
|
742
|
+
};
|
|
743
|
+
function normalizeBeliefConfidence(confidence) {
|
|
744
|
+
if (typeof confidence !== "number" || !Number.isFinite(confidence)) {
|
|
745
|
+
return null;
|
|
746
|
+
}
|
|
747
|
+
if (confidence >= 0 && confidence <= 1) {
|
|
748
|
+
return confidence;
|
|
749
|
+
}
|
|
750
|
+
if (confidence > 1 && confidence <= 100) {
|
|
751
|
+
return confidence / 100;
|
|
752
|
+
}
|
|
753
|
+
return null;
|
|
754
|
+
}
|
|
755
|
+
function hasResolvedPredictionOutcome(predictionMeta) {
|
|
756
|
+
if (!predictionMeta || typeof predictionMeta !== "object") {
|
|
757
|
+
return false;
|
|
758
|
+
}
|
|
759
|
+
const outcome = predictionMeta.outcome;
|
|
760
|
+
return outcome === "confirmed" || outcome === "disconfirmed" || outcome === "partial" || outcome === "expired";
|
|
761
|
+
}
|
|
762
|
+
function resolveLifecycleBucket(args) {
|
|
763
|
+
if (normalizeBeliefConfidence(args.confidence) === 0 || normalizeBeliefConfidence(args.confidence) === 1 || hasResolvedPredictionOutcome(args.predictionMeta)) {
|
|
764
|
+
return "fact";
|
|
765
|
+
}
|
|
766
|
+
if (args.beliefStatus === "assumption" || args.beliefStatus === "hypothesis" || args.beliefStatus === "belief" || args.beliefStatus === "fact") {
|
|
767
|
+
if (normalizeBeliefConfidence(args.confidence) !== null && (args.beliefStatus === "assumption" || args.beliefStatus === "hypothesis")) {
|
|
768
|
+
return "belief";
|
|
769
|
+
}
|
|
770
|
+
return args.beliefStatus;
|
|
771
|
+
}
|
|
772
|
+
return "assumption";
|
|
773
|
+
}
|
|
774
|
+
function lifecycleMultiplier(status) {
|
|
775
|
+
if (status === "assumption") {
|
|
776
|
+
return 0.65;
|
|
777
|
+
}
|
|
778
|
+
if (status === "hypothesis") {
|
|
779
|
+
return 0.8;
|
|
780
|
+
}
|
|
781
|
+
return 1;
|
|
782
|
+
}
|
|
783
|
+
function computeBaseDecay(lastScoredAt) {
|
|
784
|
+
const ageDays = (Date.now() - lastScoredAt) / (1e3 * 60 * 60 * 24);
|
|
785
|
+
let tier = DECAY_TIERS.EXPIRED;
|
|
786
|
+
if (ageDays <= DECAY_TIERS.FRESH.maxAgeDays) {
|
|
787
|
+
tier = DECAY_TIERS.FRESH;
|
|
788
|
+
} else if (ageDays <= DECAY_TIERS.AGING.maxAgeDays) {
|
|
789
|
+
tier = DECAY_TIERS.AGING;
|
|
790
|
+
} else if (ageDays <= DECAY_TIERS.STALE.maxAgeDays) {
|
|
791
|
+
tier = DECAY_TIERS.STALE;
|
|
792
|
+
}
|
|
793
|
+
return { ageDays, tier, weight: tier.weight };
|
|
794
|
+
}
|
|
795
|
+
function computeDeadlineUrgency(expectedBy) {
|
|
796
|
+
if (!expectedBy) {
|
|
797
|
+
return null;
|
|
798
|
+
}
|
|
799
|
+
const daysToDeadline = (expectedBy - Date.now()) / (1e3 * 60 * 60 * 24);
|
|
800
|
+
let urgencyTier = DEADLINE_URGENCY.DISTANT;
|
|
801
|
+
if (daysToDeadline < 0) {
|
|
802
|
+
urgencyTier = DEADLINE_URGENCY.OVERDUE;
|
|
803
|
+
} else if (daysToDeadline <= 7) {
|
|
804
|
+
urgencyTier = DEADLINE_URGENCY.CRITICAL;
|
|
805
|
+
} else if (daysToDeadline <= 30) {
|
|
806
|
+
urgencyTier = DEADLINE_URGENCY.IMMINENT;
|
|
807
|
+
} else if (daysToDeadline <= 90) {
|
|
808
|
+
urgencyTier = DEADLINE_URGENCY.NEAR;
|
|
809
|
+
} else if (daysToDeadline <= 180) {
|
|
810
|
+
urgencyTier = DEADLINE_URGENCY.APPROACHING;
|
|
811
|
+
}
|
|
812
|
+
return {
|
|
813
|
+
daysToDeadline: Math.round(daysToDeadline),
|
|
814
|
+
urgencyTier,
|
|
815
|
+
urgencyMultiplier: urgencyTier.urgencyMultiplier,
|
|
816
|
+
isOverdue: daysToDeadline < 0
|
|
817
|
+
};
|
|
818
|
+
}
|
|
819
|
+
function computeEffectiveDecay(lastScoredAt, expectedBy, beliefStatus) {
|
|
820
|
+
const base = computeBaseDecay(lastScoredAt);
|
|
821
|
+
const urgency = computeDeadlineUrgency(expectedBy);
|
|
822
|
+
const effectiveWeight = (urgency ? base.weight * urgency.urgencyMultiplier : base.weight) * lifecycleMultiplier(beliefStatus);
|
|
823
|
+
const urgencyRescoreDays = urgency?.urgencyTier.rescoreIntervalDays ?? Number.POSITIVE_INFINITY;
|
|
824
|
+
const rescoreInDays = Math.min(base.tier.rescoreInDays, urgencyRescoreDays);
|
|
825
|
+
const rescoreByDate = lastScoredAt + rescoreInDays * 24 * 60 * 60 * 1e3;
|
|
826
|
+
let action = base.tier.action;
|
|
827
|
+
if (urgency && urgency.urgencyTier.label !== "distant") {
|
|
828
|
+
action = `${urgency.urgencyTier.action}. ${base.tier.action}`;
|
|
829
|
+
}
|
|
830
|
+
return {
|
|
831
|
+
ageDays: base.ageDays,
|
|
832
|
+
baseTier: base.tier,
|
|
833
|
+
baseWeight: base.weight,
|
|
834
|
+
urgency,
|
|
835
|
+
effectiveWeight: Math.max(0, Math.min(1, effectiveWeight)),
|
|
836
|
+
rescoreByDate,
|
|
837
|
+
rescoreInDays,
|
|
838
|
+
action
|
|
839
|
+
};
|
|
840
|
+
}
|
|
841
|
+
function getRescoringSchedule(opts) {
|
|
842
|
+
const lifecycleStatus = resolveLifecycleBucket({
|
|
843
|
+
beliefStatus: opts.beliefStatus,
|
|
844
|
+
confidence: opts.confidence,
|
|
845
|
+
predictionMeta: opts.predictionMeta
|
|
846
|
+
});
|
|
847
|
+
const decayState = computeEffectiveDecay(
|
|
848
|
+
opts.lastScoredAt,
|
|
849
|
+
opts.expectedBy,
|
|
850
|
+
lifecycleStatus
|
|
851
|
+
);
|
|
852
|
+
const daysUntilRescore = (decayState.rescoreByDate - Date.now()) / (1e3 * 60 * 60 * 24);
|
|
853
|
+
const isOverdue = daysUntilRescore < 0;
|
|
854
|
+
let priority;
|
|
855
|
+
let reason;
|
|
856
|
+
if (isOverdue && lifecycleStatus === "assumption") {
|
|
857
|
+
priority = "critical";
|
|
858
|
+
reason = `Untested assumption is stale (${Math.round(decayState.ageDays)}d) \u2014 validate or supersede`;
|
|
859
|
+
} else if (isOverdue && lifecycleStatus === "hypothesis" || lifecycleStatus === "hypothesis" && daysUntilRescore < 7) {
|
|
860
|
+
priority = "high";
|
|
861
|
+
reason = `Hypothesis aging without validation (${Math.round(decayState.ageDays)}d) \u2014 run/finish sprint testing`;
|
|
862
|
+
} else if (decayState.urgency?.isOverdue) {
|
|
863
|
+
priority = "critical";
|
|
864
|
+
reason = `Prediction deadline passed ${Math.abs(decayState.urgency.daysToDeadline)}d ago \u2014 validate or archive`;
|
|
865
|
+
} else if (isOverdue && decayState.baseTier.label === "expired") {
|
|
866
|
+
priority = "critical";
|
|
867
|
+
reason = `Not scored in ${Math.round(decayState.ageDays)}d \u2014 confidence severely degraded`;
|
|
868
|
+
} else if (isOverdue && decayState.baseTier.label === "stale") {
|
|
869
|
+
priority = "high";
|
|
870
|
+
reason = `Stale (${Math.round(decayState.ageDays)}d since scoring) \u2014 evidence update required`;
|
|
871
|
+
} else if (decayState.urgency && decayState.urgency.urgencyTier.label === "critical") {
|
|
872
|
+
priority = "critical";
|
|
873
|
+
reason = `Deadline in ${decayState.urgency.daysToDeadline}d \u2014 needs immediate rescoring`;
|
|
874
|
+
} else if (decayState.urgency && decayState.urgency.urgencyTier.label === "imminent") {
|
|
875
|
+
priority = "high";
|
|
876
|
+
reason = `Deadline in ${decayState.urgency.daysToDeadline}d \u2014 weekly rescoring required`;
|
|
877
|
+
} else if (isOverdue) {
|
|
878
|
+
priority = "high";
|
|
879
|
+
reason = `Rescore overdue by ${Math.abs(Math.round(daysUntilRescore))}d`;
|
|
880
|
+
} else if (opts.temporalNature === "forecast" && daysUntilRescore < 7) {
|
|
881
|
+
priority = "medium";
|
|
882
|
+
reason = `Forecast belief \u2014 next rescore due in ${Math.round(daysUntilRescore)}d`;
|
|
883
|
+
} else if (daysUntilRescore < 14) {
|
|
884
|
+
priority = "medium";
|
|
885
|
+
reason = `Rescore due in ${Math.round(daysUntilRescore)}d`;
|
|
886
|
+
} else {
|
|
887
|
+
priority = "low";
|
|
888
|
+
reason = `On schedule \u2014 next rescore in ${Math.round(daysUntilRescore)}d`;
|
|
889
|
+
}
|
|
890
|
+
if ((opts.confidence ?? 0) >= 0.8 && decayState.baseTier.label !== "fresh" && priority === "medium") {
|
|
891
|
+
priority = "high";
|
|
892
|
+
reason = `High-confidence belief (${((opts.confidence ?? 0) * 100).toFixed(0)}%) aging without rescore \u2014 ${reason}`;
|
|
893
|
+
}
|
|
894
|
+
return {
|
|
895
|
+
nextRescoreBy: decayState.rescoreByDate,
|
|
896
|
+
daysUntilRescore: Math.round(daysUntilRescore),
|
|
897
|
+
isOverdue,
|
|
898
|
+
priority,
|
|
899
|
+
reason,
|
|
900
|
+
decay: decayState
|
|
901
|
+
};
|
|
902
|
+
}
|
|
903
|
+
function decay(current, daysSinceLastUpdate, halfLifeDays = 90) {
|
|
904
|
+
if (daysSinceLastUpdate <= 0) {
|
|
905
|
+
return current;
|
|
906
|
+
}
|
|
907
|
+
const decayFactor = Math.pow(0.5, daysSinceLastUpdate / halfLifeDays);
|
|
908
|
+
const certainty = current.b + current.d;
|
|
909
|
+
const lostCertainty = certainty - certainty * decayFactor;
|
|
910
|
+
return opinion(
|
|
911
|
+
current.b * decayFactor,
|
|
912
|
+
current.d * decayFactor,
|
|
913
|
+
current.u + lostCertainty,
|
|
914
|
+
current.a
|
|
915
|
+
);
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
// src/v1/operations/contracts/epistemicContract.ts
|
|
919
|
+
var BUILT_IN_METRIC_CHECKER = "metric_checker";
|
|
920
|
+
var BUILT_IN_REFERENCE_CHECK_COUNTER = "reference_check_counter";
|
|
921
|
+
var BUILT_IN_MARKET_INDEX_COMPARATOR = "market_index_comparator";
|
|
922
|
+
function clampConfidence(value) {
|
|
923
|
+
return Math.max(0, Math.min(1, value));
|
|
924
|
+
}
|
|
925
|
+
function generateContractId() {
|
|
926
|
+
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
927
|
+
return crypto.randomUUID();
|
|
928
|
+
}
|
|
929
|
+
return `contract-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
|
|
930
|
+
}
|
|
931
|
+
function deriveContractStatus(result, currentStatus) {
|
|
932
|
+
if (currentStatus === "archived") {
|
|
933
|
+
return currentStatus;
|
|
934
|
+
}
|
|
935
|
+
switch (result) {
|
|
936
|
+
case "confirmed":
|
|
937
|
+
return "satisfied";
|
|
938
|
+
case "disconfirmed":
|
|
939
|
+
return "violated";
|
|
940
|
+
case "expired":
|
|
941
|
+
return "expired";
|
|
942
|
+
default:
|
|
943
|
+
return currentStatus === "satisfied" || currentStatus === "violated" || currentStatus === "expired" ? "active" : currentStatus;
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
function deriveVerificationTrigger(result) {
|
|
947
|
+
switch (result) {
|
|
948
|
+
case "confirmed":
|
|
949
|
+
return "verification_confirmed";
|
|
950
|
+
case "disconfirmed":
|
|
951
|
+
return "verification_disconfirmed";
|
|
952
|
+
case "expired":
|
|
953
|
+
return "verification_expired";
|
|
954
|
+
case "partial":
|
|
955
|
+
return "verification_partial";
|
|
956
|
+
default:
|
|
957
|
+
return null;
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
function deriveContractModulationPlan(args) {
|
|
961
|
+
const trigger = deriveVerificationTrigger(args.result);
|
|
962
|
+
if (!trigger) {
|
|
963
|
+
return null;
|
|
964
|
+
}
|
|
965
|
+
if (args.result === "confirmed") {
|
|
966
|
+
const rawNext = args.currentConfidence + args.modulation.onConfirmed.delta;
|
|
967
|
+
const confidenceAfter = clampConfidence(
|
|
968
|
+
Math.min(
|
|
969
|
+
args.modulation.onConfirmed.ceiling ?? Number.POSITIVE_INFINITY,
|
|
970
|
+
rawNext
|
|
971
|
+
)
|
|
972
|
+
);
|
|
973
|
+
return {
|
|
974
|
+
trigger,
|
|
975
|
+
confidenceBefore: args.currentConfidence,
|
|
976
|
+
confidenceAfter,
|
|
977
|
+
confidenceDelta: confidenceAfter - args.currentConfidence
|
|
978
|
+
};
|
|
979
|
+
}
|
|
980
|
+
if (args.result === "disconfirmed") {
|
|
981
|
+
const rawNext = args.currentConfidence + args.modulation.onDisconfirmed.delta;
|
|
982
|
+
const confidenceAfter = clampConfidence(
|
|
983
|
+
Math.max(args.modulation.onDisconfirmed.floor ?? 0, rawNext)
|
|
984
|
+
);
|
|
985
|
+
return {
|
|
986
|
+
trigger,
|
|
987
|
+
confidenceBefore: args.currentConfidence,
|
|
988
|
+
confidenceAfter,
|
|
989
|
+
confidenceDelta: confidenceAfter - args.currentConfidence
|
|
990
|
+
};
|
|
991
|
+
}
|
|
992
|
+
if (args.result === "expired" && args.modulation.onExpired) {
|
|
993
|
+
const confidenceAfter = clampConfidence(
|
|
994
|
+
args.currentConfidence + args.modulation.onExpired.delta
|
|
995
|
+
);
|
|
996
|
+
return {
|
|
997
|
+
trigger,
|
|
998
|
+
confidenceBefore: args.currentConfidence,
|
|
999
|
+
confidenceAfter,
|
|
1000
|
+
confidenceDelta: confidenceAfter - args.currentConfidence
|
|
1001
|
+
};
|
|
1002
|
+
}
|
|
1003
|
+
if (args.result === "partial" && args.modulation.onPartial) {
|
|
1004
|
+
if ((args.resultConfidence ?? 0) < args.modulation.onPartial.threshold) {
|
|
1005
|
+
return null;
|
|
1006
|
+
}
|
|
1007
|
+
const confidenceAfter = clampConfidence(
|
|
1008
|
+
args.currentConfidence + args.modulation.onPartial.delta
|
|
1009
|
+
);
|
|
1010
|
+
return {
|
|
1011
|
+
trigger,
|
|
1012
|
+
confidenceBefore: args.currentConfidence,
|
|
1013
|
+
confidenceAfter,
|
|
1014
|
+
confidenceDelta: confidenceAfter - args.currentConfidence
|
|
1015
|
+
};
|
|
1016
|
+
}
|
|
1017
|
+
return null;
|
|
1018
|
+
}
|
|
1019
|
+
function createInheritedContractRecord(contract, args) {
|
|
1020
|
+
return {
|
|
1021
|
+
beliefNodeId: args.beliefNodeId,
|
|
1022
|
+
contractId: generateContractId(),
|
|
1023
|
+
title: contract.title,
|
|
1024
|
+
description: contract.description,
|
|
1025
|
+
conditionType: contract.conditionType,
|
|
1026
|
+
direction: contract.direction,
|
|
1027
|
+
condition: contract.condition,
|
|
1028
|
+
deadline: contract.deadline,
|
|
1029
|
+
compositeOf: contract.compositeOf,
|
|
1030
|
+
compositeOperator: contract.compositeOperator,
|
|
1031
|
+
modulation: contract.modulation,
|
|
1032
|
+
evaluationSchedule: contract.evaluationSchedule,
|
|
1033
|
+
periodicIntervalMs: contract.periodicIntervalMs,
|
|
1034
|
+
status: "active",
|
|
1035
|
+
lineageSource: "inherited",
|
|
1036
|
+
inheritedFromContractId: contract.contractId,
|
|
1037
|
+
inheritedFromBeliefNodeId: contract.beliefNodeId,
|
|
1038
|
+
inheritedAt: args.now,
|
|
1039
|
+
topicId: args.topicId,
|
|
1040
|
+
createdAt: args.now,
|
|
1041
|
+
createdBy: args.createdBy,
|
|
1042
|
+
updatedAt: args.now
|
|
1043
|
+
};
|
|
1044
|
+
}
|
|
1045
|
+
function normalizeEvidentialAction(value) {
|
|
1046
|
+
return value === "modulate_confidence" || value === "flag_review" || value === "archive" ? value : void 0;
|
|
1047
|
+
}
|
|
1048
|
+
function parseComparisonOperator(value, evaluatorName) {
|
|
1049
|
+
if (value === "gte" || value === "lte" || value === "eq" || value === "gt" || value === "lt") {
|
|
1050
|
+
return value;
|
|
1051
|
+
}
|
|
1052
|
+
throw new Error(
|
|
1053
|
+
`${evaluatorName} requires operator to be one of gte, lte, eq, gt, or lt.`
|
|
1054
|
+
);
|
|
1055
|
+
}
|
|
1056
|
+
function parseNumericThreshold(value, evaluatorName) {
|
|
1057
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
1058
|
+
return value;
|
|
1059
|
+
}
|
|
1060
|
+
throw new Error(`${evaluatorName} requires a finite numeric threshold.`);
|
|
1061
|
+
}
|
|
1062
|
+
function pickFiniteNumber(config, keys) {
|
|
1063
|
+
for (const key of keys) {
|
|
1064
|
+
const value = config[key];
|
|
1065
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
1066
|
+
return value;
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
return void 0;
|
|
1070
|
+
}
|
|
1071
|
+
function getEvaluatorInputRecord(inputData, nestedKey) {
|
|
1072
|
+
if (!inputData || typeof inputData !== "object") {
|
|
1073
|
+
return {};
|
|
1074
|
+
}
|
|
1075
|
+
const root = inputData;
|
|
1076
|
+
const nested = root[nestedKey];
|
|
1077
|
+
if (nested && typeof nested === "object") {
|
|
1078
|
+
return nested;
|
|
1079
|
+
}
|
|
1080
|
+
return root;
|
|
1081
|
+
}
|
|
1082
|
+
function parseEvidentialEvaluatorConfig(value) {
|
|
1083
|
+
if (!value || typeof value !== "object") {
|
|
1084
|
+
throw new Error(
|
|
1085
|
+
"Evidential contracts require condition.evaluatorConfig with metric/operator/threshold."
|
|
1086
|
+
);
|
|
1087
|
+
}
|
|
1088
|
+
const config = value;
|
|
1089
|
+
const metric = config.metric;
|
|
1090
|
+
const operator = config.operator;
|
|
1091
|
+
const threshold = config.threshold;
|
|
1092
|
+
if (metric !== "evidence_count" && metric !== "contradiction_status" && metric !== "edge_freshness" && metric !== "dependent_count") {
|
|
1093
|
+
throw new Error(`Unsupported evidential metric: ${String(metric)}`);
|
|
1094
|
+
}
|
|
1095
|
+
if (operator !== "gte" && operator !== "lte" && operator !== "eq" && operator !== "gt" && operator !== "lt") {
|
|
1096
|
+
throw new Error(`Unsupported evidential operator: ${String(operator)}`);
|
|
1097
|
+
}
|
|
1098
|
+
if (typeof threshold !== "number" || !Number.isFinite(threshold)) {
|
|
1099
|
+
throw new Error("Evidential contracts require a numeric threshold.");
|
|
1100
|
+
}
|
|
1101
|
+
const actionParams = config.actionParams && typeof config.actionParams === "object" && config.actionParams !== null ? config.actionParams : void 0;
|
|
1102
|
+
return {
|
|
1103
|
+
metric,
|
|
1104
|
+
operator,
|
|
1105
|
+
threshold,
|
|
1106
|
+
action: normalizeEvidentialAction(config.action),
|
|
1107
|
+
actionParams: actionParams && (typeof actionParams.targetConfidence === "number" || typeof actionParams.rationale === "string") ? {
|
|
1108
|
+
targetConfidence: typeof actionParams.targetConfidence === "number" ? actionParams.targetConfidence : void 0,
|
|
1109
|
+
rationale: typeof actionParams.rationale === "string" ? actionParams.rationale : void 0
|
|
1110
|
+
} : void 0
|
|
1111
|
+
};
|
|
1112
|
+
}
|
|
1113
|
+
function compareMetricValue(operator, left, right) {
|
|
1114
|
+
switch (operator) {
|
|
1115
|
+
case "gte":
|
|
1116
|
+
return left >= right;
|
|
1117
|
+
case "lte":
|
|
1118
|
+
return left <= right;
|
|
1119
|
+
case "eq":
|
|
1120
|
+
return left === right;
|
|
1121
|
+
case "gt":
|
|
1122
|
+
return left > right;
|
|
1123
|
+
case "lt":
|
|
1124
|
+
return left < right;
|
|
1125
|
+
default:
|
|
1126
|
+
return false;
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
function resolveComparisonResult(direction, comparisonSatisfied) {
|
|
1130
|
+
return direction === "falsifies" ? comparisonSatisfied ? "disconfirmed" : "confirmed" : comparisonSatisfied ? "confirmed" : "disconfirmed";
|
|
1131
|
+
}
|
|
1132
|
+
function buildComparisonRationale(args) {
|
|
1133
|
+
const renderedObserved = args.observedValue === null ? "no data" : `${args.observedValue}${args.unit ? ` ${args.unit}` : ""}`;
|
|
1134
|
+
const renderedThreshold = `${args.threshold}${args.unit ? ` ${args.unit}` : ""}`;
|
|
1135
|
+
const clause = `${args.label} observed ${renderedObserved} against ${args.operator} ${renderedThreshold}`;
|
|
1136
|
+
if (args.observedValue === null) {
|
|
1137
|
+
return `${clause}; evaluator returned ${args.result} because no current data was available.`;
|
|
1138
|
+
}
|
|
1139
|
+
return `${clause}; comparison ${args.comparisonSatisfied ? "passed" : "failed"}, resulting in ${args.result}.`;
|
|
1140
|
+
}
|
|
1141
|
+
function buildEvidentialRationale(args) {
|
|
1142
|
+
const observed = args.snapshot.value === null ? "no data" : String(args.snapshot.value);
|
|
1143
|
+
const clause = `${args.snapshot.metric} observed ${observed} against ${args.config.operator} ${args.config.threshold}`;
|
|
1144
|
+
if (args.snapshot.value === null) {
|
|
1145
|
+
return `${clause}; evidential evaluator treated the comparison as unmet, resulting in ${args.result}.`;
|
|
1146
|
+
}
|
|
1147
|
+
return `${clause}; comparison ${args.comparisonSatisfied ? "passed" : "failed"}, resulting in ${args.result}.`;
|
|
1148
|
+
}
|
|
1149
|
+
function parseMetricCheckerConfig(value) {
|
|
1150
|
+
if (!value || typeof value !== "object") {
|
|
1151
|
+
throw new Error(
|
|
1152
|
+
"metric_checker requires condition.evaluatorConfig with observedValue/operator/threshold."
|
|
1153
|
+
);
|
|
1154
|
+
}
|
|
1155
|
+
const config = value;
|
|
1156
|
+
return {
|
|
1157
|
+
metric: typeof config.metric === "string" && config.metric.length > 0 ? config.metric : void 0,
|
|
1158
|
+
operator: parseComparisonOperator(config.operator, BUILT_IN_METRIC_CHECKER),
|
|
1159
|
+
threshold: parseNumericThreshold(config.threshold, BUILT_IN_METRIC_CHECKER),
|
|
1160
|
+
observedValue: pickFiniteNumber(config, ["observedValue", "value"]),
|
|
1161
|
+
currentValue: pickFiniteNumber(config, ["currentValue"]),
|
|
1162
|
+
metricValue: pickFiniteNumber(config, ["metricValue"]),
|
|
1163
|
+
unit: typeof config.unit === "string" && config.unit.length > 0 ? config.unit : void 0
|
|
1164
|
+
};
|
|
1165
|
+
}
|
|
1166
|
+
function parseReferenceCheckCounterConfig(value) {
|
|
1167
|
+
if (!value || typeof value !== "object") {
|
|
1168
|
+
throw new Error(
|
|
1169
|
+
"reference_check_counter requires condition.evaluatorConfig with tag/operator/threshold."
|
|
1170
|
+
);
|
|
1171
|
+
}
|
|
1172
|
+
const config = value;
|
|
1173
|
+
if (typeof config.tag !== "string" || config.tag.trim().length === 0) {
|
|
1174
|
+
throw new Error("reference_check_counter requires a non-empty tag.");
|
|
1175
|
+
}
|
|
1176
|
+
return {
|
|
1177
|
+
tag: config.tag.trim(),
|
|
1178
|
+
operator: parseComparisonOperator(
|
|
1179
|
+
config.operator,
|
|
1180
|
+
BUILT_IN_REFERENCE_CHECK_COUNTER
|
|
1181
|
+
),
|
|
1182
|
+
threshold: parseNumericThreshold(
|
|
1183
|
+
config.threshold,
|
|
1184
|
+
BUILT_IN_REFERENCE_CHECK_COUNTER
|
|
1185
|
+
),
|
|
1186
|
+
caseSensitive: config.caseSensitive === true
|
|
1187
|
+
};
|
|
1188
|
+
}
|
|
1189
|
+
function parseTemporalDeadlineConfig(value) {
|
|
1190
|
+
if (!value || typeof value !== "object") {
|
|
1191
|
+
return {};
|
|
1192
|
+
}
|
|
1193
|
+
const config = value;
|
|
1194
|
+
return {
|
|
1195
|
+
label: typeof config.label === "string" && config.label.length > 0 ? config.label : void 0,
|
|
1196
|
+
completed: config.completed === true,
|
|
1197
|
+
completedAt: pickFiniteNumber(config, ["completedAt"]),
|
|
1198
|
+
observedAt: pickFiniteNumber(config, ["observedAt"]),
|
|
1199
|
+
satisfiedAt: pickFiniteNumber(config, ["satisfiedAt"]),
|
|
1200
|
+
achievedAt: pickFiniteNumber(config, ["achievedAt"])
|
|
1201
|
+
};
|
|
1202
|
+
}
|
|
1203
|
+
function parseMarketIndexComparatorConfig(value) {
|
|
1204
|
+
if (!value || typeof value !== "object") {
|
|
1205
|
+
throw new Error(
|
|
1206
|
+
"market_index_comparator requires condition.evaluatorConfig with subjectValue/benchmarkValue/operator/threshold."
|
|
1207
|
+
);
|
|
1208
|
+
}
|
|
1209
|
+
const config = value;
|
|
1210
|
+
return {
|
|
1211
|
+
subject: typeof config.subject === "string" && config.subject.length > 0 ? config.subject : void 0,
|
|
1212
|
+
subjectValue: pickFiniteNumber(config, ["subjectValue", "leftValue"]),
|
|
1213
|
+
primaryValue: pickFiniteNumber(config, ["primaryValue"]),
|
|
1214
|
+
benchmark: typeof config.benchmark === "string" && config.benchmark.length > 0 ? config.benchmark : void 0,
|
|
1215
|
+
benchmarkValue: pickFiniteNumber(config, ["benchmarkValue", "rightValue"]),
|
|
1216
|
+
comparisonValue: pickFiniteNumber(config, ["comparisonValue"]),
|
|
1217
|
+
operator: parseComparisonOperator(
|
|
1218
|
+
config.operator,
|
|
1219
|
+
BUILT_IN_MARKET_INDEX_COMPARATOR
|
|
1220
|
+
),
|
|
1221
|
+
threshold: parseNumericThreshold(
|
|
1222
|
+
config.threshold,
|
|
1223
|
+
BUILT_IN_MARKET_INDEX_COMPARATOR
|
|
1224
|
+
)
|
|
1225
|
+
};
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
// src/v1/operations/lucern.ts
|
|
1229
|
+
var LUCERN_SPECIFIC_OPERATOR_NAMES = [
|
|
1230
|
+
"clamp01",
|
|
1231
|
+
"toStoredOpinionFields",
|
|
1232
|
+
"readOpinionFromRecord",
|
|
1233
|
+
"opinionFromScalar",
|
|
1234
|
+
"temporalDecay",
|
|
1235
|
+
"toDogmaticOpinion",
|
|
1236
|
+
"hasProjectedOpinionChanged",
|
|
1237
|
+
"normalizeTupleContradictionPolicy",
|
|
1238
|
+
"detectTupleContradiction",
|
|
1239
|
+
"evaluateTupleContradictionTransition",
|
|
1240
|
+
"confidenceLevel",
|
|
1241
|
+
"constraintFusion",
|
|
1242
|
+
"evidenceBalance",
|
|
1243
|
+
"areTensioned",
|
|
1244
|
+
"informationGain",
|
|
1245
|
+
"isPropagationEdgeType",
|
|
1246
|
+
"getPropagationTraversalSpecs",
|
|
1247
|
+
"propagateThroughEdge",
|
|
1248
|
+
"propagateAllEdges",
|
|
1249
|
+
"bayesianUpdate",
|
|
1250
|
+
"reviseConfidence",
|
|
1251
|
+
"computeBaseDecay",
|
|
1252
|
+
"computeDeadlineUrgency",
|
|
1253
|
+
"computeEffectiveDecay",
|
|
1254
|
+
"getRescoringSchedule",
|
|
1255
|
+
"decay",
|
|
1256
|
+
"applyNegativeSupport",
|
|
1257
|
+
"applyNegativeEvidence",
|
|
1258
|
+
"deriveContractStatus",
|
|
1259
|
+
"deriveVerificationTrigger",
|
|
1260
|
+
"deriveContractModulationPlan",
|
|
1261
|
+
"createInheritedContractRecord",
|
|
1262
|
+
"normalizeEvidentialAction",
|
|
1263
|
+
"parseComparisonOperator",
|
|
1264
|
+
"parseNumericThreshold",
|
|
1265
|
+
"pickFiniteNumber",
|
|
1266
|
+
"getEvaluatorInputRecord",
|
|
1267
|
+
"parseEvidentialEvaluatorConfig",
|
|
1268
|
+
"compareMetricValue",
|
|
1269
|
+
"resolveComparisonResult",
|
|
1270
|
+
"buildComparisonRationale",
|
|
1271
|
+
"buildEvidentialRationale",
|
|
1272
|
+
"parseMetricCheckerConfig",
|
|
1273
|
+
"parseReferenceCheckCounterConfig",
|
|
1274
|
+
"parseTemporalDeadlineConfig",
|
|
1275
|
+
"parseMarketIndexComparatorConfig"
|
|
1276
|
+
];
|
|
1277
|
+
|
|
1278
|
+
export { LUCERN_SPECIFIC_OPERATOR_NAMES, applyNegativeEvidence, applyNegativeSupport, areTensioned, bayesianUpdate, buildComparisonRationale, buildEvidentialRationale, clamp01, compareMetricValue, computeBaseDecay, computeDeadlineUrgency, computeEffectiveDecay, confidenceLevel, constraintFusion, createInheritedContractRecord, decay, deriveContractModulationPlan, deriveContractStatus, deriveVerificationTrigger, detectTupleContradiction, evaluateTupleContradictionTransition, evidenceBalance, getEvaluatorInputRecord, getPropagationTraversalSpecs, getRescoringSchedule, hasProjectedOpinionChanged, informationGain, isPropagationEdgeType, normalizeEvidentialAction, normalizeTupleContradictionPolicy, opinionFromScalar, parseComparisonOperator, parseEvidentialEvaluatorConfig, parseMarketIndexComparatorConfig, parseMetricCheckerConfig, parseNumericThreshold, parseReferenceCheckCounterConfig, parseTemporalDeadlineConfig, pickFiniteNumber, propagateAllEdges, propagateThroughEdge, readOpinionFromRecord, resolveComparisonResult, reviseConfidence, temporalDecay, toDogmaticOpinion, toStoredOpinionFields };
|
|
1279
|
+
//# sourceMappingURL=lucern.js.map
|
|
1280
|
+
//# sourceMappingURL=lucern.js.map
|