@lucern/confidence 1.0.36 → 1.0.38

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/index.js +0 -2
  2. package/dist/proof-attestation.json +1 -1
  3. package/dist/v1/codec.js +0 -2
  4. package/dist/v1/index.js +0 -2
  5. package/dist/v1/interfaces.js +0 -2
  6. package/dist/v1/operations/approximation.js +0 -2
  7. package/dist/v1/operations/bridge/index.js +0 -2
  8. package/dist/v1/operations/canonical.js +0 -2
  9. package/dist/v1/operations/contracts/epistemicContract.js +0 -2
  10. package/dist/v1/operations/contradiction/detectTupleContradiction.js +0 -2
  11. package/dist/v1/operations/contradiction/index.js +0 -2
  12. package/dist/v1/operations/dynamics/cascade.js +0 -2
  13. package/dist/v1/operations/dynamics/decay.js +0 -2
  14. package/dist/v1/operations/dynamics/defeat.js +0 -2
  15. package/dist/v1/operations/dynamics/propagation.js +0 -2
  16. package/dist/v1/operations/dynamics/revision.js +0 -2
  17. package/dist/v1/operations/index.js +0 -2
  18. package/dist/v1/operations/lucern.js +0 -2
  19. package/dist/v1/operations/operatorTaxonomy.js +0 -2
  20. package/dist/v1/operations/scoring.js +0 -2
  21. package/dist/v1/operations/subjectiveLogic/index.js +0 -2
  22. package/dist/v1/operations/temporalDecay.js +0 -2
  23. package/dist/v1/types.js +0 -2
  24. package/package.json +1 -1
  25. package/dist/index.js.map +0 -1
  26. package/dist/v1/codec.js.map +0 -1
  27. package/dist/v1/index.js.map +0 -1
  28. package/dist/v1/interfaces.js.map +0 -1
  29. package/dist/v1/operations/approximation.js.map +0 -1
  30. package/dist/v1/operations/bridge/index.js.map +0 -1
  31. package/dist/v1/operations/canonical.js.map +0 -1
  32. package/dist/v1/operations/contracts/epistemicContract.js.map +0 -1
  33. package/dist/v1/operations/contradiction/detectTupleContradiction.js.map +0 -1
  34. package/dist/v1/operations/contradiction/index.js.map +0 -1
  35. package/dist/v1/operations/dynamics/cascade.js.map +0 -1
  36. package/dist/v1/operations/dynamics/decay.js.map +0 -1
  37. package/dist/v1/operations/dynamics/defeat.js.map +0 -1
  38. package/dist/v1/operations/dynamics/propagation.js.map +0 -1
  39. package/dist/v1/operations/dynamics/revision.js.map +0 -1
  40. package/dist/v1/operations/index.js.map +0 -1
  41. package/dist/v1/operations/lucern.js.map +0 -1
  42. package/dist/v1/operations/operatorTaxonomy.js.map +0 -1
  43. package/dist/v1/operations/scoring.js.map +0 -1
  44. package/dist/v1/operations/subjectiveLogic/index.js.map +0 -1
  45. package/dist/v1/operations/temporalDecay.js.map +0 -1
  46. package/dist/v1/types.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../src/v1/operations/subjectiveLogic/index.ts","../../../src/v1/operations/scoring.ts","../../../src/v1/operations/canonical.ts"],"names":["opinion"],"mappings":"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","file":"canonical.js","sourcesContent":["import type { SLOpinion } from \"../../types\";\n\nexport function opinion(\n belief: number,\n disbelief: number,\n uncertainty: number,\n baseRate: number\n): SLOpinion {\n const b = Number.isFinite(belief) ? Math.max(0, belief) : 0;\n const d = Number.isFinite(disbelief) ? Math.max(0, disbelief) : 0;\n const u = Number.isFinite(uncertainty) ? Math.max(0, uncertainty) : 0;\n const a = Math.max(0, Math.min(1, baseRate));\n const sum = b + d + u;\n\n if (sum === 0) {\n return { b: 0, d: 0, u: 1, a } as SLOpinion;\n }\n\n return {\n b: b / sum,\n d: d / sum,\n u: u / sum,\n a,\n } as SLOpinion;\n}\n\nexport function mkOpinion(\n belief: number,\n disbelief: number,\n uncertainty: number,\n baseRate: number\n): SLOpinion {\n return opinion(belief, disbelief, uncertainty, baseRate);\n}\n\nexport function vacuous(baseRate: number): SLOpinion {\n return mkOpinion(0, 0, 1, baseRate);\n}\n\nexport function dogmatic(probability: number, baseRate: number): SLOpinion {\n const p = Math.max(0, Math.min(1, probability));\n return mkOpinion(p, 1 - p, 0, baseRate);\n}\n\nexport function project(o: SLOpinion): number {\n return o.b + o.a * o.u;\n}\n\nexport function confidenceLevel(o: SLOpinion): \"high\" | \"medium\" | \"low\" {\n const projected = project(o);\n if (o.u > 0.5) {\n return \"low\";\n }\n if (projected >= 0.8 && o.u < 0.2) {\n return \"high\";\n }\n if (projected >= 0.6) {\n return \"medium\";\n }\n return \"low\";\n}\n\nconst VACUOUS_IDENTITY_EPSILON = 1e-12;\n\n/**\n * Associative, vacuous-identity-preserving base rate for a fused opinion.\n *\n * The legacy `(left.a + right.a) / 2` arithmetic mean was the shared root of\n * RR.7 F1 (projected-confidence non-associativity) and F2 (a vacuous opinion of\n * a different base rate was not a fusion identity): averaging always pulled the\n * fused base rate toward the other operand even when that operand carried no\n * evidence. Subjective Logic requires every opinion over the same frame to share\n * one canonical base rate, so a correct fusion never *invents* a new base rate\n * from the operands' priors. We therefore:\n *\n * - return the informative operand's base rate when exactly one operand is\n * vacuous (the vacuous operand contributes no prior), making `vacuous(a)` a\n * true identity for any `a`; and\n * - require equal base rates otherwise (the canonical-frame contract). When\n * they coincide the result is that shared value — trivially associative.\n *\n * If two informative opinions carry genuinely different base rates they are not\n * opinions over the same frame and must be reconciled before fusion; we fall\n * back to the arithmetic mean ONLY in that ill-posed case to stay total, and the\n * property suite documents that this path is outside the order-independence\n * guarantee.\n */\nfunction fusedBaseRate(left: SLOpinion, right: SLOpinion): number {\n const leftVacuous = 1 - left.u <= VACUOUS_IDENTITY_EPSILON;\n const rightVacuous = 1 - right.u <= VACUOUS_IDENTITY_EPSILON;\n if (leftVacuous && !rightVacuous) {\n return right.a;\n }\n if (rightVacuous && !leftVacuous) {\n return left.a;\n }\n if (Math.abs(left.a - right.a) <= VACUOUS_IDENTITY_EPSILON) {\n return left.a;\n }\n return (left.a + right.a) / 2;\n}\n\nexport function cumulativeFusion(left: SLOpinion, right: SLOpinion): SLOpinion {\n const a = fusedBaseRate(left, right);\n\n // F2: a vacuous operand is the identity element of cumulative fusion. Return\n // the other operand verbatim (including its base rate) so fusion with the\n // vacuous opinion is a true no-op regardless of differing priors.\n if (1 - left.u <= VACUOUS_IDENTITY_EPSILON) {\n return opinion(right.b, right.d, right.u, a);\n }\n if (1 - right.u <= VACUOUS_IDENTITY_EPSILON) {\n return opinion(left.b, left.d, left.u, a);\n }\n\n // F4: dogmatic pair handled via the ε-limit of the cumulative rule rather than\n // the standalone `(b+d)/2` shortcut. As both uncertainties shrink at the same\n // rate, the cumulative formula's `(b_L·u_R + b_R·u_L)/k` term converges to the\n // arithmetic mean of the masses; deriving it from the same limit the interior\n // formula uses keeps mass-associativity intact (no special-case discontinuity).\n if (\n left.u <= VACUOUS_IDENTITY_EPSILON &&\n right.u <= VACUOUS_IDENTITY_EPSILON\n ) {\n return opinion((left.b + right.b) / 2, (left.d + right.d) / 2, 0, a);\n }\n\n const k = left.u + right.u - left.u * right.u;\n if (k === 0) {\n return vacuous(a);\n }\n\n return opinion(\n (left.b * right.u + right.b * left.u) / k,\n (left.d * right.u + right.d * left.u) / k,\n (left.u * right.u) / k,\n a\n );\n}\n\nexport function averagingFusion(left: SLOpinion, right: SLOpinion): SLOpinion {\n const a = fusedBaseRate(left, right);\n\n // F2: vacuous identity, mirroring cumulativeFusion.\n if (1 - left.u <= VACUOUS_IDENTITY_EPSILON) {\n return opinion(right.b, right.d, right.u, a);\n }\n if (1 - right.u <= VACUOUS_IDENTITY_EPSILON) {\n return opinion(left.b, left.d, left.u, a);\n }\n\n // F4: dogmatic pair via the ε-limit of the averaging rule.\n if (\n left.u <= VACUOUS_IDENTITY_EPSILON &&\n right.u <= VACUOUS_IDENTITY_EPSILON\n ) {\n return opinion((left.b + right.b) / 2, (left.d + right.d) / 2, 0, a);\n }\n\n const k = left.u + right.u;\n if (k === 0) {\n return vacuous(a);\n }\n\n return opinion(\n (left.b * right.u + right.b * left.u) / k,\n (left.d * right.u + right.d * left.u) / k,\n (2 * left.u * right.u) / k,\n a\n );\n}\n\nexport function trustDiscount(\n sourceOpinion: SLOpinion,\n trust: number\n): SLOpinion {\n const weight = Math.max(0, Math.min(1, Math.abs(trust)));\n return opinion(\n weight * sourceOpinion.b,\n weight * sourceOpinion.d,\n 1 - weight * (sourceOpinion.b + sourceOpinion.d),\n sourceOpinion.a\n );\n}\n\nconst EPSILON = 1e-9;\n\nfunction childBaseRateFallback(\n ifTrue: SLOpinion,\n ifFalse: SLOpinion,\n fallbackBaseRate: number | undefined\n): number {\n if (fallbackBaseRate !== undefined) {\n return Math.max(0, Math.min(1, fallbackBaseRate));\n }\n\n if (Math.abs(ifTrue.a - ifFalse.a) <= EPSILON) {\n return ifTrue.a;\n }\n\n return (ifTrue.a + ifFalse.a) / 2;\n}\n\nfunction computeConditionalDeductionBaseRate(\n opinionA: SLOpinion,\n ifTrue: SLOpinion,\n ifFalse: SLOpinion,\n fallbackBaseRate: number\n): number {\n const denominator = 1 - opinionA.a * ifTrue.u - (1 - opinionA.a) * ifFalse.u;\n\n if (ifTrue.u + ifFalse.u < 2 - EPSILON && Math.abs(denominator) > EPSILON) {\n const baseRate =\n (opinionA.a * ifTrue.b + (1 - opinionA.a) * ifFalse.b) / denominator;\n if (baseRate >= -EPSILON && baseRate <= 1 + EPSILON) {\n return Math.max(0, Math.min(1, baseRate));\n }\n }\n\n return fallbackBaseRate;\n}\n\nfunction safeCorrectionTerm(\n numerator: number,\n denominator: number\n): number | undefined {\n if (Math.abs(denominator) <= EPSILON) {\n return;\n }\n\n const value = numerator / denominator;\n if (!Number.isFinite(value)) {\n return;\n }\n\n return Math.max(0, value);\n}\n\ninterface ConditionalDeductionCorrectionContext {\n childBaseRate: number;\n ifFalse: SLOpinion;\n ifTrue: SLOpinion;\n intermediateBelief: number;\n intermediateDisbelief: number;\n opinionA: SLOpinion;\n projectedAntecedent: number;\n projectedAntecedentComplement: number;\n projectedConditionalA: number;\n projectedVacuousDeduction: number;\n}\n\nfunction correctionOrZero(numerator: number, denominator: number): number {\n return safeCorrectionTerm(numerator, denominator) ?? 0;\n}\n\nfunction hasNoConditionalDeductionCorrection(\n ifTrue: SLOpinion,\n ifFalse: SLOpinion\n): boolean {\n return (\n (ifTrue.b > ifFalse.b && ifTrue.d > ifFalse.d) ||\n (ifTrue.b <= ifFalse.b && ifTrue.d <= ifFalse.d)\n );\n}\n\nfunction usesLowerVacuousBranch(\n context: ConditionalDeductionCorrectionContext\n): boolean {\n return context.projectedVacuousDeduction <= context.projectedConditionalA;\n}\n\nfunction usesLowerAntecedentBranch(\n context: ConditionalDeductionCorrectionContext\n): boolean {\n return context.projectedAntecedent <= context.opinionA.a;\n}\n\nfunction computeTrueDominantDeductionCorrection(\n context: ConditionalDeductionCorrectionContext\n): number {\n const beliefGap = context.ifTrue.b - context.ifFalse.b;\n const disbeliefGap = context.ifFalse.d - context.ifTrue.d;\n const lowerVacuous = usesLowerVacuousBranch(context);\n const lowerAntecedent = usesLowerAntecedentBranch(context);\n\n if (lowerVacuous && lowerAntecedent) {\n return correctionOrZero(\n context.opinionA.a *\n context.opinionA.u *\n (context.intermediateBelief - context.ifTrue.b),\n context.projectedAntecedent * context.childBaseRate\n );\n }\n\n if (lowerVacuous) {\n return correctionOrZero(\n context.opinionA.a *\n context.opinionA.u *\n (context.intermediateDisbelief - context.ifTrue.d) *\n beliefGap,\n context.projectedAntecedentComplement *\n context.childBaseRate *\n disbeliefGap\n );\n }\n\n if (lowerAntecedent) {\n return correctionOrZero(\n (1 - context.opinionA.a) *\n context.opinionA.u *\n (context.intermediateBelief - context.ifTrue.b) *\n disbeliefGap,\n context.projectedAntecedent * (1 - context.childBaseRate) * beliefGap\n );\n }\n\n return correctionOrZero(\n (1 - context.opinionA.a) *\n context.opinionA.u *\n (context.intermediateDisbelief - context.ifTrue.d),\n context.projectedAntecedentComplement * (1 - context.childBaseRate)\n );\n}\n\nfunction computeFalseDominantDeductionCorrection(\n context: ConditionalDeductionCorrectionContext\n): number {\n const beliefGap = context.ifFalse.b - context.ifTrue.b;\n const disbeliefGap = context.ifTrue.d - context.ifFalse.d;\n const lowerVacuous = usesLowerVacuousBranch(context);\n const lowerAntecedent = usesLowerAntecedentBranch(context);\n\n if (lowerVacuous && lowerAntecedent) {\n return correctionOrZero(\n (1 - context.opinionA.a) *\n context.opinionA.u *\n (context.intermediateDisbelief - context.ifTrue.d) *\n beliefGap,\n context.projectedAntecedent * context.childBaseRate * disbeliefGap\n );\n }\n\n if (lowerVacuous) {\n return correctionOrZero(\n (1 - context.opinionA.a) *\n context.opinionA.u *\n (context.intermediateBelief - context.ifTrue.b),\n context.projectedAntecedentComplement * context.childBaseRate\n );\n }\n\n if (lowerAntecedent) {\n return correctionOrZero(\n context.opinionA.a *\n context.opinionA.u *\n (context.intermediateDisbelief - context.ifTrue.d),\n context.projectedAntecedent * (1 - context.childBaseRate)\n );\n }\n\n return correctionOrZero(\n context.opinionA.a *\n context.opinionA.u *\n (context.intermediateBelief - context.ifTrue.b) *\n disbeliefGap,\n context.projectedAntecedentComplement *\n (1 - context.childBaseRate) *\n beliefGap\n );\n}\n\nfunction computeConditionalDeductionCorrection(\n context: ConditionalDeductionCorrectionContext\n): number {\n if (hasNoConditionalDeductionCorrection(context.ifTrue, context.ifFalse)) {\n return 0;\n }\n\n if (\n context.ifTrue.b > context.ifFalse.b &&\n context.ifTrue.d <= context.ifFalse.d\n ) {\n return computeTrueDominantDeductionCorrection(context);\n }\n\n return computeFalseDominantDeductionCorrection(context);\n}\n\nexport function conditionalDeduction(\n opinionA: SLOpinion,\n ifTrue: SLOpinion,\n ifFalse: SLOpinion,\n fallbackBaseRate?: number\n): SLOpinion {\n const fallbackChildBaseRate = childBaseRateFallback(\n ifTrue,\n ifFalse,\n fallbackBaseRate\n );\n const childBaseRate = computeConditionalDeductionBaseRate(\n opinionA,\n ifTrue,\n ifFalse,\n fallbackChildBaseRate\n );\n const projectedAntecedent = project(opinionA);\n const projectedAntecedentComplement = 1 - projectedAntecedent;\n const intermediateBelief =\n opinionA.b * ifTrue.b +\n opinionA.d * ifFalse.b +\n opinionA.u * (ifTrue.b * opinionA.a + ifFalse.b * (1 - opinionA.a));\n const intermediateDisbelief =\n opinionA.b * ifTrue.d +\n opinionA.d * ifFalse.d +\n opinionA.u * (ifTrue.d * opinionA.a + ifFalse.d * (1 - opinionA.a));\n const intermediateUncertainty =\n opinionA.b * ifTrue.u +\n opinionA.d * ifFalse.u +\n opinionA.u * (ifTrue.u * opinionA.a + ifFalse.u * (1 - opinionA.a));\n const projectedVacuousDeduction =\n ifTrue.b * opinionA.a +\n ifFalse.b * (1 - opinionA.a) +\n childBaseRate * (ifTrue.u * opinionA.a + ifFalse.u * (1 - opinionA.a));\n const projectedConditionalA =\n ifTrue.b + childBaseRate * (1 - ifTrue.b - ifTrue.d);\n const correction = computeConditionalDeductionCorrection({\n childBaseRate,\n ifFalse,\n ifTrue,\n intermediateBelief,\n intermediateDisbelief,\n opinionA,\n projectedAntecedent,\n projectedAntecedentComplement,\n projectedConditionalA,\n projectedVacuousDeduction,\n });\n\n return opinion(\n intermediateBelief - childBaseRate * correction,\n intermediateDisbelief - (1 - childBaseRate) * correction,\n intermediateUncertainty + correction,\n childBaseRate\n );\n}\n\n/**\n * Abductive inference over a conditional.\n * Given an opinion on Y and conditionals P(Y|X), P(Y|~X), infer an opinion on X.\n */\nexport function conditionalAbduction(\n opinionY: SLOpinion,\n ifTrue: SLOpinion,\n ifFalse: SLOpinion,\n baseRateX: number\n): SLOpinion {\n const priorX = Math.max(0, Math.min(1, baseRateX));\n const probabilityY = project(opinionY);\n const probabilityGivenTrue = project(ifTrue);\n const probabilityGivenFalse = project(ifFalse);\n\n const posteriorIfYDenominator =\n probabilityGivenTrue * priorX + probabilityGivenFalse * (1 - priorX);\n const posteriorIfY =\n posteriorIfYDenominator === 0\n ? priorX\n : (probabilityGivenTrue * priorX) / posteriorIfYDenominator;\n\n const posteriorIfNotYDenominator =\n (1 - probabilityGivenTrue) * priorX +\n (1 - probabilityGivenFalse) * (1 - priorX);\n const posteriorIfNotY =\n posteriorIfNotYDenominator === 0\n ? priorX\n : ((1 - probabilityGivenTrue) * priorX) / posteriorIfNotYDenominator;\n\n const projectedX =\n probabilityY * posteriorIfY + (1 - probabilityY) * posteriorIfNotY;\n const uncertainty = Math.max(\n opinionY.u * 0.5,\n probabilityY * ifTrue.u + (1 - probabilityY) * ifFalse.u\n );\n\n return opinion(\n projectedX * (1 - uncertainty),\n (1 - projectedX) * (1 - uncertainty),\n uncertainty,\n priorX\n );\n}\n\nexport function negate(o: SLOpinion): SLOpinion {\n return mkOpinion(o.d, o.b, o.u, 1 - o.a);\n}\n\nexport function constraintFusion(\n left: SLOpinion,\n right: SLOpinion,\n mode: \"pressure\" | \"redistribute\" = \"pressure\"\n): { o1: SLOpinion; o2: SLOpinion } {\n if (mode === \"redistribute\") {\n const leftProjected = project(left);\n const rightProjected = project(right);\n const total = leftProjected + rightProjected;\n\n if (total <= 1) {\n return { o1: left, o2: right };\n }\n\n const scale = 1 / total;\n return {\n o1: opinion(\n left.b * scale,\n left.d + left.b * (1 - scale),\n left.u,\n left.a\n ),\n o2: opinion(\n right.b * scale,\n right.d + right.b * (1 - scale),\n right.u,\n right.a\n ),\n };\n }\n\n const pressureLeft = right.b * 0.5;\n const pressureRight = left.b * 0.5;\n\n return {\n o1: opinion(\n left.b - pressureLeft * 0.3,\n left.d + pressureLeft * 0.3,\n left.u,\n left.a\n ),\n o2: opinion(\n right.b - pressureRight * 0.3,\n right.d + pressureRight * 0.3,\n right.u,\n right.a\n ),\n };\n}\n\nexport function evidenceBalance(o: SLOpinion): number {\n const total = o.b + o.d;\n if (total === 0) {\n return 0;\n }\n return (o.b - o.d) / total;\n}\n\nexport function areTensioned(left: SLOpinion, right: SLOpinion): boolean {\n return (\n project(left) > 0.5 &&\n project(right) > 0.5 &&\n (left.d > 0.2 || right.d > 0.2)\n );\n}\n\nexport function informationGain(o: SLOpinion): number {\n if (o.u === 0) {\n return 0;\n }\n if (o.u === 1) {\n return 1;\n }\n return o.u * (1 - Math.abs(o.b - o.d));\n}\n","import type { Opinion, SLOpinion, StoredOpinionFields } from \"../types\";\nimport { dogmatic, mkOpinion, vacuous } from \"./subjectiveLogic\";\n\nfunction finiteNumber(value: unknown): number | undefined {\n return typeof value === \"number\" && Number.isFinite(value)\n ? value\n : undefined;\n}\n\nfunction requiredOpinionNumber(label: string, ...values: unknown[]): number {\n for (const value of values) {\n const numberValue = finiteNumber(value);\n if (numberValue !== undefined) {\n return numberValue;\n }\n }\n throw new Error(`Opinion record is missing required ${label}.`);\n}\n\nexport function clamp01(value: number): number {\n return Math.max(0, Math.min(1, value));\n}\n\nexport function confidenceFromOpinion(opinion: Opinion): number {\n return clamp01(opinion.b + opinion.a * opinion.u);\n}\n\nexport function confidenceFromSL(\n belief: number,\n _disbelief: number,\n uncertainty: number,\n baseRate: number\n): number {\n return confidenceFromOpinion({\n b: belief,\n d: _disbelief,\n u: uncertainty,\n a: baseRate,\n });\n}\n\nexport function toStoredOpinionFields(opinion: Opinion): StoredOpinionFields {\n return {\n belief: opinion.b,\n disbelief: opinion.d,\n uncertainty: opinion.u,\n baseRate: opinion.a,\n };\n}\n\nexport function readOpinionFromRecord(source: unknown): SLOpinion {\n const record =\n source && typeof source === \"object\"\n ? (source as Record<string, unknown>)\n : {};\n\n return mkOpinion(\n requiredOpinionNumber(\n \"belief\",\n record.b,\n record.belief,\n record.slBelief,\n record.opinion_b\n ),\n requiredOpinionNumber(\n \"disbelief\",\n record.d,\n record.disbelief,\n record.slDisbelief,\n record.opinion_d\n ),\n requiredOpinionNumber(\n \"uncertainty\",\n record.u,\n record.uncertainty,\n record.slUncertainty,\n record.opinion_u\n ),\n requiredOpinionNumber(\n \"baseRate\",\n record.a,\n record.baseRate,\n record.slBaseRate,\n record.opinion_a\n )\n );\n}\n\nexport type OpinionFromScalarMode =\n | \"base_rate\"\n | \"dogmatic\"\n | \"projected_with_u\";\n\nexport type OpinionFromScalarOptions =\n | { baseRate?: never; uncertainty?: never }\n | { baseRate: number; uncertainty?: never }\n | { baseRate: number; uncertainty: number };\n\nexport function opinionFromScalar(\n value: number,\n mode: \"base_rate\",\n options?: { baseRate?: never; uncertainty?: never }\n): SLOpinion;\nexport function opinionFromScalar(\n value: number,\n mode: \"dogmatic\",\n options: { baseRate: number; uncertainty?: never }\n): SLOpinion;\nexport function opinionFromScalar(\n value: number,\n mode: \"projected_with_u\",\n options: { baseRate: number; uncertainty: number }\n): SLOpinion;\nexport function opinionFromScalar(\n value: number,\n mode: OpinionFromScalarMode,\n options?: OpinionFromScalarOptions\n): SLOpinion {\n const clampedValue = clamp01(value);\n const baseRate =\n options?.baseRate === undefined ? undefined : clamp01(options.baseRate);\n\n switch (mode) {\n case \"base_rate\":\n return mkOpinion(0, 0, 1, clampedValue);\n case \"dogmatic\":\n if (baseRate === undefined) {\n throw new Error(\n 'opinionFromScalar(value, \"dogmatic\") requires options.baseRate.'\n );\n }\n return mkOpinion(clampedValue, 1 - clampedValue, 0, baseRate);\n case \"projected_with_u\": {\n if (baseRate === undefined) {\n throw new Error(\n 'opinionFromScalar(value, \"projected_with_u\") requires options.baseRate.'\n );\n }\n const uncertainty = options?.uncertainty;\n if (uncertainty === undefined) {\n throw new Error(\n 'opinionFromScalar(value, \"projected_with_u\") requires options.uncertainty.'\n );\n }\n const clampedUncertainty = clamp01(uncertainty);\n const evidenceWeight = 1 - clampedUncertainty;\n return mkOpinion(\n clampedValue * evidenceWeight,\n (1 - clampedValue) * evidenceWeight,\n clampedUncertainty,\n baseRate\n );\n }\n default:\n throw new Error(`Unsupported opinionFromScalar mode: ${mode}`);\n }\n}\n\n/**\n * @deprecated Use opinionFromScalar(value, \"dogmatic\", { baseRate }) instead.\n */\nexport function toDogmaticOpinion(\n confidence: number,\n baseRate: number\n): SLOpinion {\n return opinionFromScalar(confidence, \"dogmatic\", { baseRate });\n}\n\n/** Interpret p as a prior with no observed evidence. */\nexport function opinionFromBaseRate(probability: number): SLOpinion {\n return vacuous(clamp01(probability));\n}\n\n/** Interpret p as a certainty-equivalent projected probability. */\nexport function opinionFromDogmatic(\n probability: number,\n baseRate: number\n): SLOpinion {\n return dogmatic(clamp01(probability), clamp01(baseRate));\n}\n\nfunction representableProjectedUncertainty(\n probability: number,\n uncertainty: number,\n baseRate: number\n): number {\n const maxBeliefUncertainty =\n baseRate > 0 ? probability / baseRate : Number.POSITIVE_INFINITY;\n const maxDisbeliefUncertainty =\n baseRate < 1\n ? (1 - probability) / (1 - baseRate)\n : Number.POSITIVE_INFINITY;\n\n return clamp01(\n Math.min(uncertainty, maxBeliefUncertainty, maxDisbeliefUncertainty)\n );\n}\n\n/**\n * Interpret p as a projected probability with an explicit uncertainty bucket.\n * Uses the requested uncertainty when representable; otherwise lowers it so the\n * resulting opinion stays valid and projects back to p.\n */\nexport function opinionFromProjected(\n probability: number,\n uncertainty: number,\n baseRate: number\n): SLOpinion {\n const p = clamp01(probability);\n const a = clamp01(baseRate);\n const u = representableProjectedUncertainty(p, clamp01(uncertainty), a);\n return mkOpinion(\n Math.max(0, p - a * u),\n Math.max(0, 1 - p - (1 - a) * u),\n u,\n a\n );\n}\n\nexport function hasProjectedOpinionChanged(\n current: Opinion,\n next: Opinion,\n tolerance = 0.01\n): boolean {\n return (\n Math.abs(confidenceFromOpinion(next) - confidenceFromOpinion(current)) >=\n tolerance\n );\n}\n","// biome-ignore-all lint/performance/noBarrelFile: Public confidence canonical facade; splitting requires an export-map migration.\n\nexport const SL_CANONICAL_OPERATOR_NAMES = [\n \"mkOpinion\",\n \"opinion\",\n \"vacuous\",\n \"dogmatic\",\n \"project\",\n \"trustDiscount\",\n \"negate\",\n \"conditionalDeduction\",\n \"confidenceFromOpinion\",\n \"confidenceFromSL\",\n \"opinionFromBaseRate\",\n \"opinionFromDogmatic\",\n \"opinionFromProjected\",\n] as const;\n\nexport {\n confidenceFromOpinion,\n confidenceFromSL,\n opinionFromBaseRate,\n opinionFromDogmatic,\n opinionFromProjected,\n} from \"./scoring\";\nexport {\n conditionalDeduction,\n dogmatic,\n mkOpinion,\n negate,\n opinion,\n project,\n trustDiscount,\n vacuous,\n} from \"./subjectiveLogic\";\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../src/v1/operations/contracts/epistemicContract.ts"],"names":[],"mappings":"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","file":"epistemicContract.js","sourcesContent":["// biome-ignore-all lint/style/useFilenamingConvention: Published @lucern/confidence contract subpath; rename needs an export-map migration.\n\nimport type {\n ContractModulationPlan,\n EpistemicContractDirection,\n EpistemicContractEvaluationResult,\n EpistemicContractModulation,\n EpistemicContractRecord,\n EpistemicContractStatus,\n EvidentialAction,\n EvidentialEvaluatorConfig,\n EvidentialMetricSnapshot,\n EvidentialOperator,\n MarketIndexComparatorConfig,\n MetricCheckerEvaluatorConfig,\n ReferenceCheckCounterConfig,\n TemporalDeadlineEvaluatorConfig,\n VerificationConfidenceTrigger,\n} from \"../../types\";\n\nexport const BUILT_IN_EVIDENTIAL_EVALUATOR = \"evidential\";\nexport const BUILT_IN_EVIDENTIAL_ALIASES = new Set([\n BUILT_IN_EVIDENTIAL_EVALUATOR,\n \"built_in_evidential\",\n \"builtin_evidential\",\n]);\nexport const BUILT_IN_METRIC_CHECKER = \"metric_checker\";\nexport const BUILT_IN_REFERENCE_CHECK_COUNTER = \"reference_check_counter\";\nexport const BUILT_IN_TEMPORAL_DEADLINE = \"temporal_deadline\";\nexport const BUILT_IN_MARKET_INDEX_COMPARATOR = \"market_index_comparator\";\n\nfunction clampConfidence(value: number): number {\n return Math.max(0, Math.min(1, value));\n}\n\nfunction generateContractId(): string {\n if (\n typeof crypto !== \"undefined\" &&\n typeof crypto.randomUUID === \"function\"\n ) {\n return crypto.randomUUID();\n }\n return `contract-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === \"object\" && !Array.isArray(value);\n}\n\nexport function deriveContractStatus(\n result: EpistemicContractEvaluationResult,\n currentStatus: EpistemicContractStatus\n): EpistemicContractStatus {\n if (currentStatus === \"archived\") {\n return currentStatus;\n }\n\n switch (result) {\n case \"confirmed\":\n return \"satisfied\";\n case \"disconfirmed\":\n return \"violated\";\n case \"expired\":\n return \"expired\";\n default:\n if (\n currentStatus === \"satisfied\" ||\n currentStatus === \"violated\" ||\n currentStatus === \"expired\"\n ) {\n return \"active\";\n }\n return currentStatus;\n }\n}\n\nexport function deriveVerificationTrigger(\n result: EpistemicContractEvaluationResult\n): VerificationConfidenceTrigger | null {\n switch (result) {\n case \"confirmed\":\n return \"verification_confirmed\";\n case \"disconfirmed\":\n return \"verification_disconfirmed\";\n case \"expired\":\n return \"verification_expired\";\n case \"partial\":\n return \"verification_partial\";\n default:\n return null;\n }\n}\n\nexport function deriveContractModulationPlan(args: {\n currentConfidence: number;\n modulation: EpistemicContractModulation;\n result: EpistemicContractEvaluationResult;\n resultConfidence?: number;\n}): ContractModulationPlan | null {\n const trigger = deriveVerificationTrigger(args.result);\n if (!trigger) {\n return null;\n }\n\n if (args.result === \"confirmed\") {\n const rawNext = args.currentConfidence + args.modulation.onConfirmed.delta;\n const confidenceAfter = clampConfidence(\n Math.min(\n args.modulation.onConfirmed.ceiling ?? Number.POSITIVE_INFINITY,\n rawNext\n )\n );\n return {\n trigger,\n confidenceBefore: args.currentConfidence,\n confidenceAfter,\n confidenceDelta: confidenceAfter - args.currentConfidence,\n };\n }\n\n if (args.result === \"disconfirmed\") {\n const rawNext =\n args.currentConfidence + args.modulation.onDisconfirmed.delta;\n const confidenceAfter = clampConfidence(\n Math.max(args.modulation.onDisconfirmed.floor ?? 0, rawNext)\n );\n return {\n trigger,\n confidenceBefore: args.currentConfidence,\n confidenceAfter,\n confidenceDelta: confidenceAfter - args.currentConfidence,\n };\n }\n\n if (args.result === \"expired\" && args.modulation.onExpired) {\n const confidenceAfter = clampConfidence(\n args.currentConfidence + args.modulation.onExpired.delta\n );\n return {\n trigger,\n confidenceBefore: args.currentConfidence,\n confidenceAfter,\n confidenceDelta: confidenceAfter - args.currentConfidence,\n };\n }\n\n if (args.result === \"partial\" && args.modulation.onPartial) {\n if ((args.resultConfidence ?? 0) < args.modulation.onPartial.threshold) {\n return null;\n }\n const confidenceAfter = clampConfidence(\n args.currentConfidence + args.modulation.onPartial.delta\n );\n return {\n trigger,\n confidenceBefore: args.currentConfidence,\n confidenceAfter,\n confidenceDelta: confidenceAfter - args.currentConfidence,\n };\n }\n\n return null;\n}\n\nexport function createInheritedContractRecord<\n TBeliefId = string,\n TTopicId = string | undefined,\n>(\n contract: EpistemicContractRecord<unknown, unknown>,\n args: {\n beliefNodeId: TBeliefId;\n topicId?: TTopicId;\n createdBy: string;\n now: number;\n }\n): EpistemicContractRecord<TBeliefId, TTopicId> {\n return {\n beliefNodeId: args.beliefNodeId,\n contractId: generateContractId(),\n title: contract.title,\n description: contract.description,\n conditionType: contract.conditionType,\n direction: contract.direction,\n condition: contract.condition,\n deadline: contract.deadline,\n compositeOf: contract.compositeOf,\n compositeOperator: contract.compositeOperator,\n modulation: contract.modulation,\n evaluationSchedule: contract.evaluationSchedule,\n periodicIntervalMs: contract.periodicIntervalMs,\n status: \"active\",\n lineageSource: \"inherited\",\n inheritedFromContractId: contract.contractId,\n inheritedFromBeliefNodeId: contract.beliefNodeId as TBeliefId,\n inheritedAt: args.now,\n topicId: args.topicId,\n createdAt: args.now,\n createdBy: args.createdBy,\n updatedAt: args.now,\n };\n}\n\nexport function normalizeEvidentialAction(\n value: unknown\n): EvidentialAction | undefined {\n return value === \"append_sl_scoring\" ||\n value === \"flag_review\" ||\n value === \"archive\"\n ? value\n : undefined;\n}\n\nexport function parseComparisonOperator(\n value: unknown,\n evaluatorName: string\n): EvidentialOperator {\n if (\n value === \"gte\" ||\n value === \"lte\" ||\n value === \"eq\" ||\n value === \"gt\" ||\n value === \"lt\"\n ) {\n return value;\n }\n throw new Error(\n `${evaluatorName} requires operator to be one of gte, lte, eq, gt, or lt.`\n );\n}\n\nexport function parseNumericThreshold(\n value: unknown,\n evaluatorName: string\n): number {\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return value;\n }\n throw new Error(`${evaluatorName} requires a finite numeric threshold.`);\n}\n\nexport function pickFiniteNumber(\n config: Record<string, unknown>,\n keys: string[]\n): number | undefined {\n for (const key of keys) {\n const value = config[key];\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return value;\n }\n }\n return;\n}\n\nexport function getEvaluatorInputRecord(\n inputData: unknown,\n nestedKey: string\n): Record<string, unknown> {\n if (!isRecord(inputData)) {\n return {};\n }\n\n const nested = inputData[nestedKey];\n if (isRecord(nested)) {\n return nested;\n }\n return inputData;\n}\n\nexport function parseEvidentialEvaluatorConfig(\n value: unknown\n): EvidentialEvaluatorConfig {\n if (!isRecord(value)) {\n throw new Error(\n \"Evidential contracts require condition.evaluatorConfig with metric/operator/threshold.\"\n );\n }\n\n const config = value;\n const metric = config.metric;\n const operator = config.operator;\n const threshold = config.threshold;\n\n if (\n metric !== \"evidence_count\" &&\n metric !== \"contradiction_status\" &&\n metric !== \"edge_freshness\" &&\n metric !== \"dependent_count\"\n ) {\n throw new Error(`Unsupported evidential metric: ${String(metric)}`);\n }\n\n if (\n operator !== \"gte\" &&\n operator !== \"lte\" &&\n operator !== \"eq\" &&\n operator !== \"gt\" &&\n operator !== \"lt\"\n ) {\n throw new Error(`Unsupported evidential operator: ${String(operator)}`);\n }\n\n if (typeof threshold !== \"number\" || !Number.isFinite(threshold)) {\n throw new Error(\"Evidential contracts require a numeric threshold.\");\n }\n\n const actionParams = isRecord(config.actionParams)\n ? config.actionParams\n : undefined;\n\n return {\n metric,\n operator,\n threshold,\n action: normalizeEvidentialAction(config.action),\n actionParams:\n actionParams &&\n (typeof actionParams.targetConfidence === \"number\" ||\n typeof actionParams.rationale === \"string\")\n ? {\n targetConfidence:\n typeof actionParams.targetConfidence === \"number\"\n ? actionParams.targetConfidence\n : undefined,\n rationale:\n typeof actionParams.rationale === \"string\"\n ? actionParams.rationale\n : undefined,\n }\n : undefined,\n };\n}\n\nexport function compareMetricValue(\n operator: EvidentialOperator,\n left: number,\n right: number\n): boolean {\n switch (operator) {\n case \"gte\":\n return left >= right;\n case \"lte\":\n return left <= right;\n case \"eq\":\n return left === right;\n case \"gt\":\n return left > right;\n case \"lt\":\n return left < right;\n default:\n return false;\n }\n}\n\nexport function resolveComparisonResult(\n direction: EpistemicContractDirection,\n comparisonSatisfied: boolean\n): EpistemicContractEvaluationResult {\n if (direction === \"falsifies\") {\n return comparisonSatisfied ? \"disconfirmed\" : \"confirmed\";\n }\n\n return comparisonSatisfied ? \"confirmed\" : \"disconfirmed\";\n}\n\nexport function buildComparisonRationale(args: {\n label: string;\n observedValue: number | null;\n operator: EvidentialOperator;\n threshold: number;\n comparisonSatisfied: boolean;\n result: EpistemicContractEvaluationResult;\n unit?: string;\n}): string {\n const renderedObserved =\n args.observedValue === null\n ? \"no data\"\n : `${args.observedValue}${args.unit ? ` ${args.unit}` : \"\"}`;\n const renderedThreshold = `${args.threshold}${args.unit ? ` ${args.unit}` : \"\"}`;\n const clause = `${args.label} observed ${renderedObserved} against ${args.operator} ${renderedThreshold}`;\n\n if (args.observedValue === null) {\n return `${clause}; evaluator returned ${args.result} because no current data was available.`;\n }\n\n return `${clause}; comparison ${\n args.comparisonSatisfied ? \"passed\" : \"failed\"\n }, resulting in ${args.result}.`;\n}\n\nexport function buildEvidentialRationale(args: {\n config: EvidentialEvaluatorConfig;\n snapshot: EvidentialMetricSnapshot;\n comparisonSatisfied: boolean;\n result: EpistemicContractEvaluationResult;\n}): string {\n const observed =\n args.snapshot.value === null ? \"no data\" : String(args.snapshot.value);\n const clause = `${args.snapshot.metric} observed ${observed} against ${args.config.operator} ${args.config.threshold}`;\n\n if (args.snapshot.value === null) {\n return `${clause}; evidential evaluator treated the comparison as unmet, resulting in ${args.result}.`;\n }\n\n return `${clause}; comparison ${\n args.comparisonSatisfied ? \"passed\" : \"failed\"\n }, resulting in ${args.result}.`;\n}\n\nexport function parseMetricCheckerConfig(\n value: unknown\n): MetricCheckerEvaluatorConfig {\n if (!isRecord(value)) {\n throw new Error(\n \"metric_checker requires condition.evaluatorConfig with observedValue/operator/threshold.\"\n );\n }\n\n const config = value;\n return {\n metric:\n typeof config.metric === \"string\" && config.metric.length > 0\n ? config.metric\n : undefined,\n operator: parseComparisonOperator(config.operator, BUILT_IN_METRIC_CHECKER),\n threshold: parseNumericThreshold(config.threshold, BUILT_IN_METRIC_CHECKER),\n observedValue: pickFiniteNumber(config, [\"observedValue\", \"value\"]),\n currentValue: pickFiniteNumber(config, [\"currentValue\"]),\n metricValue: pickFiniteNumber(config, [\"metricValue\"]),\n unit:\n typeof config.unit === \"string\" && config.unit.length > 0\n ? config.unit\n : undefined,\n };\n}\n\nexport function parseReferenceCheckCounterConfig(\n value: unknown\n): ReferenceCheckCounterConfig {\n if (!isRecord(value)) {\n throw new Error(\n \"reference_check_counter requires condition.evaluatorConfig with tag/operator/threshold.\"\n );\n }\n\n const config = value;\n if (typeof config.tag !== \"string\" || config.tag.trim().length === 0) {\n throw new Error(\"reference_check_counter requires a non-empty tag.\");\n }\n\n return {\n tag: config.tag.trim(),\n operator: parseComparisonOperator(\n config.operator,\n BUILT_IN_REFERENCE_CHECK_COUNTER\n ),\n threshold: parseNumericThreshold(\n config.threshold,\n BUILT_IN_REFERENCE_CHECK_COUNTER\n ),\n caseSensitive: config.caseSensitive === true,\n };\n}\n\nexport function parseTemporalDeadlineConfig(\n value: unknown\n): TemporalDeadlineEvaluatorConfig {\n if (!isRecord(value)) {\n return {};\n }\n\n const config = value;\n return {\n label:\n typeof config.label === \"string\" && config.label.length > 0\n ? config.label\n : undefined,\n completed: config.completed === true,\n completedAt: pickFiniteNumber(config, [\"completedAt\"]),\n observedAt: pickFiniteNumber(config, [\"observedAt\"]),\n satisfiedAt: pickFiniteNumber(config, [\"satisfiedAt\"]),\n achievedAt: pickFiniteNumber(config, [\"achievedAt\"]),\n };\n}\n\nexport function parseMarketIndexComparatorConfig(\n value: unknown\n): MarketIndexComparatorConfig {\n if (!isRecord(value)) {\n throw new Error(\n \"market_index_comparator requires condition.evaluatorConfig with subjectValue/benchmarkValue/operator/threshold.\"\n );\n }\n\n const config = value;\n return {\n subject:\n typeof config.subject === \"string\" && config.subject.length > 0\n ? config.subject\n : undefined,\n subjectValue: pickFiniteNumber(config, [\"subjectValue\", \"leftValue\"]),\n primaryValue: pickFiniteNumber(config, [\"primaryValue\"]),\n benchmark:\n typeof config.benchmark === \"string\" && config.benchmark.length > 0\n ? config.benchmark\n : undefined,\n benchmarkValue: pickFiniteNumber(config, [\"benchmarkValue\", \"rightValue\"]),\n comparisonValue: pickFiniteNumber(config, [\"comparisonValue\"]),\n operator: parseComparisonOperator(\n config.operator,\n BUILT_IN_MARKET_INDEX_COMPARATOR\n ),\n threshold: parseNumericThreshold(\n config.threshold,\n BUILT_IN_MARKET_INDEX_COMPARATOR\n ),\n };\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../src/v1/operations/scoring.ts","../../../../src/v1/operations/contradiction/detectTupleContradiction.ts"],"names":[],"mappings":";AAmBO,SAAS,QAAQ,KAAA,EAAuB;AAC7C,EAAA,OAAO,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,CAAC,CAAA;AACvC;;;ACZO,IAAM,4CAAA,GAA+C;AACrD,IAAM,+CAAA,GAAkD;AAExD,SAAS,iCAAA,CACd,MAAA,GAA4C,EAAC,EACnB;AAC1B,EAAA,OAAO;AAAA,IACL,eAAA,EAAiB,OAAA;AAAA,MACf,OAAO,eAAA,IAAmB;AAAA,KAC5B;AAAA,IACA,kBAAA,EAAoB,OAAA;AAAA,MAClB,OAAO,kBAAA,IACL;AAAA;AACJ,GACF;AACF;AAEO,SAAS,wBAAA,CACd,OAAA,EACA,IAAA,GAAe,4CAAA,EACf,OAAe,+CAAA,EACN;AACT,EAAA,OAAO,OAAA,CAAQ,CAAA,GAAI,IAAA,IAAQ,OAAA,CAAQ,CAAA,GAAI,IAAA;AACzC;AAEO,SAAS,qCAAqC,IAAA,EAIpB;AAC/B,EAAA,MAAM,MAAA,GAAS,iCAAA,CAAkC,IAAA,CAAK,MAAM,CAAA;AAC5D,EAAA,MAAM,iBAAA,GAAoB,wBAAA;AAAA,IACxB,IAAA,CAAK,OAAA;AAAA,IACL,MAAA,CAAO,eAAA;AAAA,IACP,MAAA,CAAO;AAAA,GACT;AACA,EAAA,MAAM,yBAAA,GAA4B,OAAA,CAAQ,IAAA,CAAK,yBAAyB,CAAA;AAExE,EAAA,OAAO;AAAA,IACL,iBAAA;AAAA,IACA,6BAAA,EACE,CAAC,yBAAA,IAA6B,iBAAA;AAAA,IAChC,8BAAA,EACE,6BAA6B,CAAC,iBAAA;AAAA,IAChC;AAAA,GACF;AACF","file":"detectTupleContradiction.js","sourcesContent":["import type { Opinion, SLOpinion, StoredOpinionFields } from \"../types\";\nimport { dogmatic, mkOpinion, vacuous } from \"./subjectiveLogic\";\n\nfunction finiteNumber(value: unknown): number | undefined {\n return typeof value === \"number\" && Number.isFinite(value)\n ? value\n : undefined;\n}\n\nfunction requiredOpinionNumber(label: string, ...values: unknown[]): number {\n for (const value of values) {\n const numberValue = finiteNumber(value);\n if (numberValue !== undefined) {\n return numberValue;\n }\n }\n throw new Error(`Opinion record is missing required ${label}.`);\n}\n\nexport function clamp01(value: number): number {\n return Math.max(0, Math.min(1, value));\n}\n\nexport function confidenceFromOpinion(opinion: Opinion): number {\n return clamp01(opinion.b + opinion.a * opinion.u);\n}\n\nexport function confidenceFromSL(\n belief: number,\n _disbelief: number,\n uncertainty: number,\n baseRate: number\n): number {\n return confidenceFromOpinion({\n b: belief,\n d: _disbelief,\n u: uncertainty,\n a: baseRate,\n });\n}\n\nexport function toStoredOpinionFields(opinion: Opinion): StoredOpinionFields {\n return {\n belief: opinion.b,\n disbelief: opinion.d,\n uncertainty: opinion.u,\n baseRate: opinion.a,\n };\n}\n\nexport function readOpinionFromRecord(source: unknown): SLOpinion {\n const record =\n source && typeof source === \"object\"\n ? (source as Record<string, unknown>)\n : {};\n\n return mkOpinion(\n requiredOpinionNumber(\n \"belief\",\n record.b,\n record.belief,\n record.slBelief,\n record.opinion_b\n ),\n requiredOpinionNumber(\n \"disbelief\",\n record.d,\n record.disbelief,\n record.slDisbelief,\n record.opinion_d\n ),\n requiredOpinionNumber(\n \"uncertainty\",\n record.u,\n record.uncertainty,\n record.slUncertainty,\n record.opinion_u\n ),\n requiredOpinionNumber(\n \"baseRate\",\n record.a,\n record.baseRate,\n record.slBaseRate,\n record.opinion_a\n )\n );\n}\n\nexport type OpinionFromScalarMode =\n | \"base_rate\"\n | \"dogmatic\"\n | \"projected_with_u\";\n\nexport type OpinionFromScalarOptions =\n | { baseRate?: never; uncertainty?: never }\n | { baseRate: number; uncertainty?: never }\n | { baseRate: number; uncertainty: number };\n\nexport function opinionFromScalar(\n value: number,\n mode: \"base_rate\",\n options?: { baseRate?: never; uncertainty?: never }\n): SLOpinion;\nexport function opinionFromScalar(\n value: number,\n mode: \"dogmatic\",\n options: { baseRate: number; uncertainty?: never }\n): SLOpinion;\nexport function opinionFromScalar(\n value: number,\n mode: \"projected_with_u\",\n options: { baseRate: number; uncertainty: number }\n): SLOpinion;\nexport function opinionFromScalar(\n value: number,\n mode: OpinionFromScalarMode,\n options?: OpinionFromScalarOptions\n): SLOpinion {\n const clampedValue = clamp01(value);\n const baseRate =\n options?.baseRate === undefined ? undefined : clamp01(options.baseRate);\n\n switch (mode) {\n case \"base_rate\":\n return mkOpinion(0, 0, 1, clampedValue);\n case \"dogmatic\":\n if (baseRate === undefined) {\n throw new Error(\n 'opinionFromScalar(value, \"dogmatic\") requires options.baseRate.'\n );\n }\n return mkOpinion(clampedValue, 1 - clampedValue, 0, baseRate);\n case \"projected_with_u\": {\n if (baseRate === undefined) {\n throw new Error(\n 'opinionFromScalar(value, \"projected_with_u\") requires options.baseRate.'\n );\n }\n const uncertainty = options?.uncertainty;\n if (uncertainty === undefined) {\n throw new Error(\n 'opinionFromScalar(value, \"projected_with_u\") requires options.uncertainty.'\n );\n }\n const clampedUncertainty = clamp01(uncertainty);\n const evidenceWeight = 1 - clampedUncertainty;\n return mkOpinion(\n clampedValue * evidenceWeight,\n (1 - clampedValue) * evidenceWeight,\n clampedUncertainty,\n baseRate\n );\n }\n default:\n throw new Error(`Unsupported opinionFromScalar mode: ${mode}`);\n }\n}\n\n/**\n * @deprecated Use opinionFromScalar(value, \"dogmatic\", { baseRate }) instead.\n */\nexport function toDogmaticOpinion(\n confidence: number,\n baseRate: number\n): SLOpinion {\n return opinionFromScalar(confidence, \"dogmatic\", { baseRate });\n}\n\n/** Interpret p as a prior with no observed evidence. */\nexport function opinionFromBaseRate(probability: number): SLOpinion {\n return vacuous(clamp01(probability));\n}\n\n/** Interpret p as a certainty-equivalent projected probability. */\nexport function opinionFromDogmatic(\n probability: number,\n baseRate: number\n): SLOpinion {\n return dogmatic(clamp01(probability), clamp01(baseRate));\n}\n\nfunction representableProjectedUncertainty(\n probability: number,\n uncertainty: number,\n baseRate: number\n): number {\n const maxBeliefUncertainty =\n baseRate > 0 ? probability / baseRate : Number.POSITIVE_INFINITY;\n const maxDisbeliefUncertainty =\n baseRate < 1\n ? (1 - probability) / (1 - baseRate)\n : Number.POSITIVE_INFINITY;\n\n return clamp01(\n Math.min(uncertainty, maxBeliefUncertainty, maxDisbeliefUncertainty)\n );\n}\n\n/**\n * Interpret p as a projected probability with an explicit uncertainty bucket.\n * Uses the requested uncertainty when representable; otherwise lowers it so the\n * resulting opinion stays valid and projects back to p.\n */\nexport function opinionFromProjected(\n probability: number,\n uncertainty: number,\n baseRate: number\n): SLOpinion {\n const p = clamp01(probability);\n const a = clamp01(baseRate);\n const u = representableProjectedUncertainty(p, clamp01(uncertainty), a);\n return mkOpinion(\n Math.max(0, p - a * u),\n Math.max(0, 1 - p - (1 - a) * u),\n u,\n a\n );\n}\n\nexport function hasProjectedOpinionChanged(\n current: Opinion,\n next: Opinion,\n tolerance = 0.01\n): boolean {\n return (\n Math.abs(confidenceFromOpinion(next) - confidenceFromOpinion(current)) >=\n tolerance\n );\n}\n","// biome-ignore-all lint/style/useFilenamingConvention: Published @lucern/confidence contradiction subpath; rename needs an export-map migration.\n\nimport type {\n Opinion,\n TupleContradictionPolicy,\n TupleContradictionTransition,\n} from \"../../types\";\nimport { clamp01 } from \"../scoring\";\n\nexport const DEFAULT_TUPLE_CONTRADICTION_BELIEF_THRESHOLD = 0.7;\nexport const DEFAULT_TUPLE_CONTRADICTION_DISBELIEF_THRESHOLD = 0.7;\n\nexport function normalizeTupleContradictionPolicy(\n policy: Partial<TupleContradictionPolicy> = {}\n): TupleContradictionPolicy {\n return {\n beliefThreshold: clamp01(\n policy.beliefThreshold ?? DEFAULT_TUPLE_CONTRADICTION_BELIEF_THRESHOLD\n ),\n disbeliefThreshold: clamp01(\n policy.disbeliefThreshold ??\n DEFAULT_TUPLE_CONTRADICTION_DISBELIEF_THRESHOLD\n ),\n };\n}\n\nexport function detectTupleContradiction(\n opinion: Opinion,\n tauB: number = DEFAULT_TUPLE_CONTRADICTION_BELIEF_THRESHOLD,\n tauD: number = DEFAULT_TUPLE_CONTRADICTION_DISBELIEF_THRESHOLD\n): boolean {\n return opinion.b > tauB && opinion.d > tauD;\n}\n\nexport function evaluateTupleContradictionTransition(args: {\n previousTupleContradicted?: boolean;\n opinion: Opinion;\n policy?: Partial<TupleContradictionPolicy>;\n}): TupleContradictionTransition {\n const policy = normalizeTupleContradictionPolicy(args.policy);\n const tupleContradicted = detectTupleContradiction(\n args.opinion,\n policy.beliefThreshold,\n policy.disbeliefThreshold\n );\n const previousTupleContradicted = Boolean(args.previousTupleContradicted);\n\n return {\n tupleContradicted,\n crossedIntoTupleContradiction:\n !previousTupleContradicted && tupleContradicted,\n crossedOutOfTupleContradiction:\n previousTupleContradicted && !tupleContradicted,\n policy,\n };\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../src/v1/operations/scoring.ts","../../../../src/v1/operations/contradiction/detectTupleContradiction.ts"],"names":[],"mappings":";AAmBO,SAAS,QAAQ,KAAA,EAAuB;AAC7C,EAAA,OAAO,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,CAAC,CAAA;AACvC;;;ACZO,IAAM,4CAAA,GAA+C;AACrD,IAAM,+CAAA,GAAkD;AAExD,SAAS,iCAAA,CACd,MAAA,GAA4C,EAAC,EACnB;AAC1B,EAAA,OAAO;AAAA,IACL,eAAA,EAAiB,OAAA;AAAA,MACf,OAAO,eAAA,IAAmB;AAAA,KAC5B;AAAA,IACA,kBAAA,EAAoB,OAAA;AAAA,MAClB,OAAO,kBAAA,IACL;AAAA;AACJ,GACF;AACF;AAEO,SAAS,wBAAA,CACd,OAAA,EACA,IAAA,GAAe,4CAAA,EACf,OAAe,+CAAA,EACN;AACT,EAAA,OAAO,OAAA,CAAQ,CAAA,GAAI,IAAA,IAAQ,OAAA,CAAQ,CAAA,GAAI,IAAA;AACzC;AAEO,SAAS,qCAAqC,IAAA,EAIpB;AAC/B,EAAA,MAAM,MAAA,GAAS,iCAAA,CAAkC,IAAA,CAAK,MAAM,CAAA;AAC5D,EAAA,MAAM,iBAAA,GAAoB,wBAAA;AAAA,IACxB,IAAA,CAAK,OAAA;AAAA,IACL,MAAA,CAAO,eAAA;AAAA,IACP,MAAA,CAAO;AAAA,GACT;AACA,EAAA,MAAM,yBAAA,GAA4B,OAAA,CAAQ,IAAA,CAAK,yBAAyB,CAAA;AAExE,EAAA,OAAO;AAAA,IACL,iBAAA;AAAA,IACA,6BAAA,EACE,CAAC,yBAAA,IAA6B,iBAAA;AAAA,IAChC,8BAAA,EACE,6BAA6B,CAAC,iBAAA;AAAA,IAChC;AAAA,GACF;AACF","file":"index.js","sourcesContent":["import type { Opinion, SLOpinion, StoredOpinionFields } from \"../types\";\nimport { dogmatic, mkOpinion, vacuous } from \"./subjectiveLogic\";\n\nfunction finiteNumber(value: unknown): number | undefined {\n return typeof value === \"number\" && Number.isFinite(value)\n ? value\n : undefined;\n}\n\nfunction requiredOpinionNumber(label: string, ...values: unknown[]): number {\n for (const value of values) {\n const numberValue = finiteNumber(value);\n if (numberValue !== undefined) {\n return numberValue;\n }\n }\n throw new Error(`Opinion record is missing required ${label}.`);\n}\n\nexport function clamp01(value: number): number {\n return Math.max(0, Math.min(1, value));\n}\n\nexport function confidenceFromOpinion(opinion: Opinion): number {\n return clamp01(opinion.b + opinion.a * opinion.u);\n}\n\nexport function confidenceFromSL(\n belief: number,\n _disbelief: number,\n uncertainty: number,\n baseRate: number\n): number {\n return confidenceFromOpinion({\n b: belief,\n d: _disbelief,\n u: uncertainty,\n a: baseRate,\n });\n}\n\nexport function toStoredOpinionFields(opinion: Opinion): StoredOpinionFields {\n return {\n belief: opinion.b,\n disbelief: opinion.d,\n uncertainty: opinion.u,\n baseRate: opinion.a,\n };\n}\n\nexport function readOpinionFromRecord(source: unknown): SLOpinion {\n const record =\n source && typeof source === \"object\"\n ? (source as Record<string, unknown>)\n : {};\n\n return mkOpinion(\n requiredOpinionNumber(\n \"belief\",\n record.b,\n record.belief,\n record.slBelief,\n record.opinion_b\n ),\n requiredOpinionNumber(\n \"disbelief\",\n record.d,\n record.disbelief,\n record.slDisbelief,\n record.opinion_d\n ),\n requiredOpinionNumber(\n \"uncertainty\",\n record.u,\n record.uncertainty,\n record.slUncertainty,\n record.opinion_u\n ),\n requiredOpinionNumber(\n \"baseRate\",\n record.a,\n record.baseRate,\n record.slBaseRate,\n record.opinion_a\n )\n );\n}\n\nexport type OpinionFromScalarMode =\n | \"base_rate\"\n | \"dogmatic\"\n | \"projected_with_u\";\n\nexport type OpinionFromScalarOptions =\n | { baseRate?: never; uncertainty?: never }\n | { baseRate: number; uncertainty?: never }\n | { baseRate: number; uncertainty: number };\n\nexport function opinionFromScalar(\n value: number,\n mode: \"base_rate\",\n options?: { baseRate?: never; uncertainty?: never }\n): SLOpinion;\nexport function opinionFromScalar(\n value: number,\n mode: \"dogmatic\",\n options: { baseRate: number; uncertainty?: never }\n): SLOpinion;\nexport function opinionFromScalar(\n value: number,\n mode: \"projected_with_u\",\n options: { baseRate: number; uncertainty: number }\n): SLOpinion;\nexport function opinionFromScalar(\n value: number,\n mode: OpinionFromScalarMode,\n options?: OpinionFromScalarOptions\n): SLOpinion {\n const clampedValue = clamp01(value);\n const baseRate =\n options?.baseRate === undefined ? undefined : clamp01(options.baseRate);\n\n switch (mode) {\n case \"base_rate\":\n return mkOpinion(0, 0, 1, clampedValue);\n case \"dogmatic\":\n if (baseRate === undefined) {\n throw new Error(\n 'opinionFromScalar(value, \"dogmatic\") requires options.baseRate.'\n );\n }\n return mkOpinion(clampedValue, 1 - clampedValue, 0, baseRate);\n case \"projected_with_u\": {\n if (baseRate === undefined) {\n throw new Error(\n 'opinionFromScalar(value, \"projected_with_u\") requires options.baseRate.'\n );\n }\n const uncertainty = options?.uncertainty;\n if (uncertainty === undefined) {\n throw new Error(\n 'opinionFromScalar(value, \"projected_with_u\") requires options.uncertainty.'\n );\n }\n const clampedUncertainty = clamp01(uncertainty);\n const evidenceWeight = 1 - clampedUncertainty;\n return mkOpinion(\n clampedValue * evidenceWeight,\n (1 - clampedValue) * evidenceWeight,\n clampedUncertainty,\n baseRate\n );\n }\n default:\n throw new Error(`Unsupported opinionFromScalar mode: ${mode}`);\n }\n}\n\n/**\n * @deprecated Use opinionFromScalar(value, \"dogmatic\", { baseRate }) instead.\n */\nexport function toDogmaticOpinion(\n confidence: number,\n baseRate: number\n): SLOpinion {\n return opinionFromScalar(confidence, \"dogmatic\", { baseRate });\n}\n\n/** Interpret p as a prior with no observed evidence. */\nexport function opinionFromBaseRate(probability: number): SLOpinion {\n return vacuous(clamp01(probability));\n}\n\n/** Interpret p as a certainty-equivalent projected probability. */\nexport function opinionFromDogmatic(\n probability: number,\n baseRate: number\n): SLOpinion {\n return dogmatic(clamp01(probability), clamp01(baseRate));\n}\n\nfunction representableProjectedUncertainty(\n probability: number,\n uncertainty: number,\n baseRate: number\n): number {\n const maxBeliefUncertainty =\n baseRate > 0 ? probability / baseRate : Number.POSITIVE_INFINITY;\n const maxDisbeliefUncertainty =\n baseRate < 1\n ? (1 - probability) / (1 - baseRate)\n : Number.POSITIVE_INFINITY;\n\n return clamp01(\n Math.min(uncertainty, maxBeliefUncertainty, maxDisbeliefUncertainty)\n );\n}\n\n/**\n * Interpret p as a projected probability with an explicit uncertainty bucket.\n * Uses the requested uncertainty when representable; otherwise lowers it so the\n * resulting opinion stays valid and projects back to p.\n */\nexport function opinionFromProjected(\n probability: number,\n uncertainty: number,\n baseRate: number\n): SLOpinion {\n const p = clamp01(probability);\n const a = clamp01(baseRate);\n const u = representableProjectedUncertainty(p, clamp01(uncertainty), a);\n return mkOpinion(\n Math.max(0, p - a * u),\n Math.max(0, 1 - p - (1 - a) * u),\n u,\n a\n );\n}\n\nexport function hasProjectedOpinionChanged(\n current: Opinion,\n next: Opinion,\n tolerance = 0.01\n): boolean {\n return (\n Math.abs(confidenceFromOpinion(next) - confidenceFromOpinion(current)) >=\n tolerance\n );\n}\n","// biome-ignore-all lint/style/useFilenamingConvention: Published @lucern/confidence contradiction subpath; rename needs an export-map migration.\n\nimport type {\n Opinion,\n TupleContradictionPolicy,\n TupleContradictionTransition,\n} from \"../../types\";\nimport { clamp01 } from \"../scoring\";\n\nexport const DEFAULT_TUPLE_CONTRADICTION_BELIEF_THRESHOLD = 0.7;\nexport const DEFAULT_TUPLE_CONTRADICTION_DISBELIEF_THRESHOLD = 0.7;\n\nexport function normalizeTupleContradictionPolicy(\n policy: Partial<TupleContradictionPolicy> = {}\n): TupleContradictionPolicy {\n return {\n beliefThreshold: clamp01(\n policy.beliefThreshold ?? DEFAULT_TUPLE_CONTRADICTION_BELIEF_THRESHOLD\n ),\n disbeliefThreshold: clamp01(\n policy.disbeliefThreshold ??\n DEFAULT_TUPLE_CONTRADICTION_DISBELIEF_THRESHOLD\n ),\n };\n}\n\nexport function detectTupleContradiction(\n opinion: Opinion,\n tauB: number = DEFAULT_TUPLE_CONTRADICTION_BELIEF_THRESHOLD,\n tauD: number = DEFAULT_TUPLE_CONTRADICTION_DISBELIEF_THRESHOLD\n): boolean {\n return opinion.b > tauB && opinion.d > tauD;\n}\n\nexport function evaluateTupleContradictionTransition(args: {\n previousTupleContradicted?: boolean;\n opinion: Opinion;\n policy?: Partial<TupleContradictionPolicy>;\n}): TupleContradictionTransition {\n const policy = normalizeTupleContradictionPolicy(args.policy);\n const tupleContradicted = detectTupleContradiction(\n args.opinion,\n policy.beliefThreshold,\n policy.disbeliefThreshold\n );\n const previousTupleContradicted = Boolean(args.previousTupleContradicted);\n\n return {\n tupleContradicted,\n crossedIntoTupleContradiction:\n !previousTupleContradicted && tupleContradicted,\n crossedOutOfTupleContradiction:\n previousTupleContradicted && !tupleContradicted,\n policy,\n };\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../src/v1/operations/subjectiveLogic/index.ts","../../../../src/v1/operations/dynamics/cascade.ts"],"names":[],"mappings":"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","file":"cascade.js","sourcesContent":["import type { SLOpinion } from \"../../types\";\n\nexport function opinion(\n belief: number,\n disbelief: number,\n uncertainty: number,\n baseRate: number\n): SLOpinion {\n const b = Number.isFinite(belief) ? Math.max(0, belief) : 0;\n const d = Number.isFinite(disbelief) ? Math.max(0, disbelief) : 0;\n const u = Number.isFinite(uncertainty) ? Math.max(0, uncertainty) : 0;\n const a = Math.max(0, Math.min(1, baseRate));\n const sum = b + d + u;\n\n if (sum === 0) {\n return { b: 0, d: 0, u: 1, a } as SLOpinion;\n }\n\n return {\n b: b / sum,\n d: d / sum,\n u: u / sum,\n a,\n } as SLOpinion;\n}\n\nexport function mkOpinion(\n belief: number,\n disbelief: number,\n uncertainty: number,\n baseRate: number\n): SLOpinion {\n return opinion(belief, disbelief, uncertainty, baseRate);\n}\n\nexport function vacuous(baseRate: number): SLOpinion {\n return mkOpinion(0, 0, 1, baseRate);\n}\n\nexport function dogmatic(probability: number, baseRate: number): SLOpinion {\n const p = Math.max(0, Math.min(1, probability));\n return mkOpinion(p, 1 - p, 0, baseRate);\n}\n\nexport function project(o: SLOpinion): number {\n return o.b + o.a * o.u;\n}\n\nexport function confidenceLevel(o: SLOpinion): \"high\" | \"medium\" | \"low\" {\n const projected = project(o);\n if (o.u > 0.5) {\n return \"low\";\n }\n if (projected >= 0.8 && o.u < 0.2) {\n return \"high\";\n }\n if (projected >= 0.6) {\n return \"medium\";\n }\n return \"low\";\n}\n\nconst VACUOUS_IDENTITY_EPSILON = 1e-12;\n\n/**\n * Associative, vacuous-identity-preserving base rate for a fused opinion.\n *\n * The legacy `(left.a + right.a) / 2` arithmetic mean was the shared root of\n * RR.7 F1 (projected-confidence non-associativity) and F2 (a vacuous opinion of\n * a different base rate was not a fusion identity): averaging always pulled the\n * fused base rate toward the other operand even when that operand carried no\n * evidence. Subjective Logic requires every opinion over the same frame to share\n * one canonical base rate, so a correct fusion never *invents* a new base rate\n * from the operands' priors. We therefore:\n *\n * - return the informative operand's base rate when exactly one operand is\n * vacuous (the vacuous operand contributes no prior), making `vacuous(a)` a\n * true identity for any `a`; and\n * - require equal base rates otherwise (the canonical-frame contract). When\n * they coincide the result is that shared value — trivially associative.\n *\n * If two informative opinions carry genuinely different base rates they are not\n * opinions over the same frame and must be reconciled before fusion; we fall\n * back to the arithmetic mean ONLY in that ill-posed case to stay total, and the\n * property suite documents that this path is outside the order-independence\n * guarantee.\n */\nfunction fusedBaseRate(left: SLOpinion, right: SLOpinion): number {\n const leftVacuous = 1 - left.u <= VACUOUS_IDENTITY_EPSILON;\n const rightVacuous = 1 - right.u <= VACUOUS_IDENTITY_EPSILON;\n if (leftVacuous && !rightVacuous) {\n return right.a;\n }\n if (rightVacuous && !leftVacuous) {\n return left.a;\n }\n if (Math.abs(left.a - right.a) <= VACUOUS_IDENTITY_EPSILON) {\n return left.a;\n }\n return (left.a + right.a) / 2;\n}\n\nexport function cumulativeFusion(left: SLOpinion, right: SLOpinion): SLOpinion {\n const a = fusedBaseRate(left, right);\n\n // F2: a vacuous operand is the identity element of cumulative fusion. Return\n // the other operand verbatim (including its base rate) so fusion with the\n // vacuous opinion is a true no-op regardless of differing priors.\n if (1 - left.u <= VACUOUS_IDENTITY_EPSILON) {\n return opinion(right.b, right.d, right.u, a);\n }\n if (1 - right.u <= VACUOUS_IDENTITY_EPSILON) {\n return opinion(left.b, left.d, left.u, a);\n }\n\n // F4: dogmatic pair handled via the ε-limit of the cumulative rule rather than\n // the standalone `(b+d)/2` shortcut. As both uncertainties shrink at the same\n // rate, the cumulative formula's `(b_L·u_R + b_R·u_L)/k` term converges to the\n // arithmetic mean of the masses; deriving it from the same limit the interior\n // formula uses keeps mass-associativity intact (no special-case discontinuity).\n if (\n left.u <= VACUOUS_IDENTITY_EPSILON &&\n right.u <= VACUOUS_IDENTITY_EPSILON\n ) {\n return opinion((left.b + right.b) / 2, (left.d + right.d) / 2, 0, a);\n }\n\n const k = left.u + right.u - left.u * right.u;\n if (k === 0) {\n return vacuous(a);\n }\n\n return opinion(\n (left.b * right.u + right.b * left.u) / k,\n (left.d * right.u + right.d * left.u) / k,\n (left.u * right.u) / k,\n a\n );\n}\n\nexport function averagingFusion(left: SLOpinion, right: SLOpinion): SLOpinion {\n const a = fusedBaseRate(left, right);\n\n // F2: vacuous identity, mirroring cumulativeFusion.\n if (1 - left.u <= VACUOUS_IDENTITY_EPSILON) {\n return opinion(right.b, right.d, right.u, a);\n }\n if (1 - right.u <= VACUOUS_IDENTITY_EPSILON) {\n return opinion(left.b, left.d, left.u, a);\n }\n\n // F4: dogmatic pair via the ε-limit of the averaging rule.\n if (\n left.u <= VACUOUS_IDENTITY_EPSILON &&\n right.u <= VACUOUS_IDENTITY_EPSILON\n ) {\n return opinion((left.b + right.b) / 2, (left.d + right.d) / 2, 0, a);\n }\n\n const k = left.u + right.u;\n if (k === 0) {\n return vacuous(a);\n }\n\n return opinion(\n (left.b * right.u + right.b * left.u) / k,\n (left.d * right.u + right.d * left.u) / k,\n (2 * left.u * right.u) / k,\n a\n );\n}\n\nexport function trustDiscount(\n sourceOpinion: SLOpinion,\n trust: number\n): SLOpinion {\n const weight = Math.max(0, Math.min(1, Math.abs(trust)));\n return opinion(\n weight * sourceOpinion.b,\n weight * sourceOpinion.d,\n 1 - weight * (sourceOpinion.b + sourceOpinion.d),\n sourceOpinion.a\n );\n}\n\nconst EPSILON = 1e-9;\n\nfunction childBaseRateFallback(\n ifTrue: SLOpinion,\n ifFalse: SLOpinion,\n fallbackBaseRate: number | undefined\n): number {\n if (fallbackBaseRate !== undefined) {\n return Math.max(0, Math.min(1, fallbackBaseRate));\n }\n\n if (Math.abs(ifTrue.a - ifFalse.a) <= EPSILON) {\n return ifTrue.a;\n }\n\n return (ifTrue.a + ifFalse.a) / 2;\n}\n\nfunction computeConditionalDeductionBaseRate(\n opinionA: SLOpinion,\n ifTrue: SLOpinion,\n ifFalse: SLOpinion,\n fallbackBaseRate: number\n): number {\n const denominator = 1 - opinionA.a * ifTrue.u - (1 - opinionA.a) * ifFalse.u;\n\n if (ifTrue.u + ifFalse.u < 2 - EPSILON && Math.abs(denominator) > EPSILON) {\n const baseRate =\n (opinionA.a * ifTrue.b + (1 - opinionA.a) * ifFalse.b) / denominator;\n if (baseRate >= -EPSILON && baseRate <= 1 + EPSILON) {\n return Math.max(0, Math.min(1, baseRate));\n }\n }\n\n return fallbackBaseRate;\n}\n\nfunction safeCorrectionTerm(\n numerator: number,\n denominator: number\n): number | undefined {\n if (Math.abs(denominator) <= EPSILON) {\n return;\n }\n\n const value = numerator / denominator;\n if (!Number.isFinite(value)) {\n return;\n }\n\n return Math.max(0, value);\n}\n\ninterface ConditionalDeductionCorrectionContext {\n childBaseRate: number;\n ifFalse: SLOpinion;\n ifTrue: SLOpinion;\n intermediateBelief: number;\n intermediateDisbelief: number;\n opinionA: SLOpinion;\n projectedAntecedent: number;\n projectedAntecedentComplement: number;\n projectedConditionalA: number;\n projectedVacuousDeduction: number;\n}\n\nfunction correctionOrZero(numerator: number, denominator: number): number {\n return safeCorrectionTerm(numerator, denominator) ?? 0;\n}\n\nfunction hasNoConditionalDeductionCorrection(\n ifTrue: SLOpinion,\n ifFalse: SLOpinion\n): boolean {\n return (\n (ifTrue.b > ifFalse.b && ifTrue.d > ifFalse.d) ||\n (ifTrue.b <= ifFalse.b && ifTrue.d <= ifFalse.d)\n );\n}\n\nfunction usesLowerVacuousBranch(\n context: ConditionalDeductionCorrectionContext\n): boolean {\n return context.projectedVacuousDeduction <= context.projectedConditionalA;\n}\n\nfunction usesLowerAntecedentBranch(\n context: ConditionalDeductionCorrectionContext\n): boolean {\n return context.projectedAntecedent <= context.opinionA.a;\n}\n\nfunction computeTrueDominantDeductionCorrection(\n context: ConditionalDeductionCorrectionContext\n): number {\n const beliefGap = context.ifTrue.b - context.ifFalse.b;\n const disbeliefGap = context.ifFalse.d - context.ifTrue.d;\n const lowerVacuous = usesLowerVacuousBranch(context);\n const lowerAntecedent = usesLowerAntecedentBranch(context);\n\n if (lowerVacuous && lowerAntecedent) {\n return correctionOrZero(\n context.opinionA.a *\n context.opinionA.u *\n (context.intermediateBelief - context.ifTrue.b),\n context.projectedAntecedent * context.childBaseRate\n );\n }\n\n if (lowerVacuous) {\n return correctionOrZero(\n context.opinionA.a *\n context.opinionA.u *\n (context.intermediateDisbelief - context.ifTrue.d) *\n beliefGap,\n context.projectedAntecedentComplement *\n context.childBaseRate *\n disbeliefGap\n );\n }\n\n if (lowerAntecedent) {\n return correctionOrZero(\n (1 - context.opinionA.a) *\n context.opinionA.u *\n (context.intermediateBelief - context.ifTrue.b) *\n disbeliefGap,\n context.projectedAntecedent * (1 - context.childBaseRate) * beliefGap\n );\n }\n\n return correctionOrZero(\n (1 - context.opinionA.a) *\n context.opinionA.u *\n (context.intermediateDisbelief - context.ifTrue.d),\n context.projectedAntecedentComplement * (1 - context.childBaseRate)\n );\n}\n\nfunction computeFalseDominantDeductionCorrection(\n context: ConditionalDeductionCorrectionContext\n): number {\n const beliefGap = context.ifFalse.b - context.ifTrue.b;\n const disbeliefGap = context.ifTrue.d - context.ifFalse.d;\n const lowerVacuous = usesLowerVacuousBranch(context);\n const lowerAntecedent = usesLowerAntecedentBranch(context);\n\n if (lowerVacuous && lowerAntecedent) {\n return correctionOrZero(\n (1 - context.opinionA.a) *\n context.opinionA.u *\n (context.intermediateDisbelief - context.ifTrue.d) *\n beliefGap,\n context.projectedAntecedent * context.childBaseRate * disbeliefGap\n );\n }\n\n if (lowerVacuous) {\n return correctionOrZero(\n (1 - context.opinionA.a) *\n context.opinionA.u *\n (context.intermediateBelief - context.ifTrue.b),\n context.projectedAntecedentComplement * context.childBaseRate\n );\n }\n\n if (lowerAntecedent) {\n return correctionOrZero(\n context.opinionA.a *\n context.opinionA.u *\n (context.intermediateDisbelief - context.ifTrue.d),\n context.projectedAntecedent * (1 - context.childBaseRate)\n );\n }\n\n return correctionOrZero(\n context.opinionA.a *\n context.opinionA.u *\n (context.intermediateBelief - context.ifTrue.b) *\n disbeliefGap,\n context.projectedAntecedentComplement *\n (1 - context.childBaseRate) *\n beliefGap\n );\n}\n\nfunction computeConditionalDeductionCorrection(\n context: ConditionalDeductionCorrectionContext\n): number {\n if (hasNoConditionalDeductionCorrection(context.ifTrue, context.ifFalse)) {\n return 0;\n }\n\n if (\n context.ifTrue.b > context.ifFalse.b &&\n context.ifTrue.d <= context.ifFalse.d\n ) {\n return computeTrueDominantDeductionCorrection(context);\n }\n\n return computeFalseDominantDeductionCorrection(context);\n}\n\nexport function conditionalDeduction(\n opinionA: SLOpinion,\n ifTrue: SLOpinion,\n ifFalse: SLOpinion,\n fallbackBaseRate?: number\n): SLOpinion {\n const fallbackChildBaseRate = childBaseRateFallback(\n ifTrue,\n ifFalse,\n fallbackBaseRate\n );\n const childBaseRate = computeConditionalDeductionBaseRate(\n opinionA,\n ifTrue,\n ifFalse,\n fallbackChildBaseRate\n );\n const projectedAntecedent = project(opinionA);\n const projectedAntecedentComplement = 1 - projectedAntecedent;\n const intermediateBelief =\n opinionA.b * ifTrue.b +\n opinionA.d * ifFalse.b +\n opinionA.u * (ifTrue.b * opinionA.a + ifFalse.b * (1 - opinionA.a));\n const intermediateDisbelief =\n opinionA.b * ifTrue.d +\n opinionA.d * ifFalse.d +\n opinionA.u * (ifTrue.d * opinionA.a + ifFalse.d * (1 - opinionA.a));\n const intermediateUncertainty =\n opinionA.b * ifTrue.u +\n opinionA.d * ifFalse.u +\n opinionA.u * (ifTrue.u * opinionA.a + ifFalse.u * (1 - opinionA.a));\n const projectedVacuousDeduction =\n ifTrue.b * opinionA.a +\n ifFalse.b * (1 - opinionA.a) +\n childBaseRate * (ifTrue.u * opinionA.a + ifFalse.u * (1 - opinionA.a));\n const projectedConditionalA =\n ifTrue.b + childBaseRate * (1 - ifTrue.b - ifTrue.d);\n const correction = computeConditionalDeductionCorrection({\n childBaseRate,\n ifFalse,\n ifTrue,\n intermediateBelief,\n intermediateDisbelief,\n opinionA,\n projectedAntecedent,\n projectedAntecedentComplement,\n projectedConditionalA,\n projectedVacuousDeduction,\n });\n\n return opinion(\n intermediateBelief - childBaseRate * correction,\n intermediateDisbelief - (1 - childBaseRate) * correction,\n intermediateUncertainty + correction,\n childBaseRate\n );\n}\n\n/**\n * Abductive inference over a conditional.\n * Given an opinion on Y and conditionals P(Y|X), P(Y|~X), infer an opinion on X.\n */\nexport function conditionalAbduction(\n opinionY: SLOpinion,\n ifTrue: SLOpinion,\n ifFalse: SLOpinion,\n baseRateX: number\n): SLOpinion {\n const priorX = Math.max(0, Math.min(1, baseRateX));\n const probabilityY = project(opinionY);\n const probabilityGivenTrue = project(ifTrue);\n const probabilityGivenFalse = project(ifFalse);\n\n const posteriorIfYDenominator =\n probabilityGivenTrue * priorX + probabilityGivenFalse * (1 - priorX);\n const posteriorIfY =\n posteriorIfYDenominator === 0\n ? priorX\n : (probabilityGivenTrue * priorX) / posteriorIfYDenominator;\n\n const posteriorIfNotYDenominator =\n (1 - probabilityGivenTrue) * priorX +\n (1 - probabilityGivenFalse) * (1 - priorX);\n const posteriorIfNotY =\n posteriorIfNotYDenominator === 0\n ? priorX\n : ((1 - probabilityGivenTrue) * priorX) / posteriorIfNotYDenominator;\n\n const projectedX =\n probabilityY * posteriorIfY + (1 - probabilityY) * posteriorIfNotY;\n const uncertainty = Math.max(\n opinionY.u * 0.5,\n probabilityY * ifTrue.u + (1 - probabilityY) * ifFalse.u\n );\n\n return opinion(\n projectedX * (1 - uncertainty),\n (1 - projectedX) * (1 - uncertainty),\n uncertainty,\n priorX\n );\n}\n\nexport function negate(o: SLOpinion): SLOpinion {\n return mkOpinion(o.d, o.b, o.u, 1 - o.a);\n}\n\nexport function constraintFusion(\n left: SLOpinion,\n right: SLOpinion,\n mode: \"pressure\" | \"redistribute\" = \"pressure\"\n): { o1: SLOpinion; o2: SLOpinion } {\n if (mode === \"redistribute\") {\n const leftProjected = project(left);\n const rightProjected = project(right);\n const total = leftProjected + rightProjected;\n\n if (total <= 1) {\n return { o1: left, o2: right };\n }\n\n const scale = 1 / total;\n return {\n o1: opinion(\n left.b * scale,\n left.d + left.b * (1 - scale),\n left.u,\n left.a\n ),\n o2: opinion(\n right.b * scale,\n right.d + right.b * (1 - scale),\n right.u,\n right.a\n ),\n };\n }\n\n const pressureLeft = right.b * 0.5;\n const pressureRight = left.b * 0.5;\n\n return {\n o1: opinion(\n left.b - pressureLeft * 0.3,\n left.d + pressureLeft * 0.3,\n left.u,\n left.a\n ),\n o2: opinion(\n right.b - pressureRight * 0.3,\n right.d + pressureRight * 0.3,\n right.u,\n right.a\n ),\n };\n}\n\nexport function evidenceBalance(o: SLOpinion): number {\n const total = o.b + o.d;\n if (total === 0) {\n return 0;\n }\n return (o.b - o.d) / total;\n}\n\nexport function areTensioned(left: SLOpinion, right: SLOpinion): boolean {\n return (\n project(left) > 0.5 &&\n project(right) > 0.5 &&\n (left.d > 0.2 || right.d > 0.2)\n );\n}\n\nexport function informationGain(o: SLOpinion): number {\n if (o.u === 0) {\n return 0;\n }\n if (o.u === 1) {\n return 1;\n }\n return o.u * (1 - Math.abs(o.b - o.d));\n}\n","import type { Opinion, PropagationMode, PropagationResult } from \"../../types\";\nimport { mkOpinion, opinion, project } from \"../subjectiveLogic\";\n\nexport function dampedDependencyOpinion(\n dependencyOpinion: Opinion,\n beliefOpinion: Opinion,\n mode: PropagationMode = \"continuous\",\n threshold = 0.3\n): Opinion {\n const dependencyProjection = project(\n mkOpinion(\n dependencyOpinion.b,\n dependencyOpinion.d,\n dependencyOpinion.u,\n dependencyOpinion.a\n )\n );\n\n if (mode === \"threshold\") {\n if (dependencyProjection < threshold) {\n return opinion(\n 0,\n beliefOpinion.d + beliefOpinion.b * 0.5,\n 0.5,\n beliefOpinion.a\n );\n }\n return beliefOpinion;\n }\n\n const dampingFactor = dependencyProjection ** 0.5;\n return opinion(\n beliefOpinion.b * dampingFactor,\n beliefOpinion.d + beliefOpinion.b * (1 - dampingFactor) * 0.3,\n beliefOpinion.u + beliefOpinion.b * (1 - dampingFactor) * 0.7,\n beliefOpinion.a\n );\n}\n\nexport function dampedDependencyCascade(\n dependencyOpinion: Opinion,\n beliefOpinion: Opinion,\n mode: PropagationMode = \"continuous\"\n): PropagationResult {\n return {\n opinion: dampedDependencyOpinion(dependencyOpinion, beliefOpinion, mode),\n operator: \"dependency_cascade\",\n rationale: `Damped dependency cascade (${mode}): prerequisite at ${project(\n mkOpinion(\n dependencyOpinion.b,\n dependencyOpinion.d,\n dependencyOpinion.u,\n dependencyOpinion.a\n )\n ).toFixed(2)}`,\n };\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../src/v1/operations/subjectiveLogic/index.ts","../../../../src/v1/operations/dynamics/decay.ts"],"names":[],"mappings":"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","file":"decay.js","sourcesContent":["import type { SLOpinion } from \"../../types\";\n\nexport function opinion(\n belief: number,\n disbelief: number,\n uncertainty: number,\n baseRate: number\n): SLOpinion {\n const b = Number.isFinite(belief) ? Math.max(0, belief) : 0;\n const d = Number.isFinite(disbelief) ? Math.max(0, disbelief) : 0;\n const u = Number.isFinite(uncertainty) ? Math.max(0, uncertainty) : 0;\n const a = Math.max(0, Math.min(1, baseRate));\n const sum = b + d + u;\n\n if (sum === 0) {\n return { b: 0, d: 0, u: 1, a } as SLOpinion;\n }\n\n return {\n b: b / sum,\n d: d / sum,\n u: u / sum,\n a,\n } as SLOpinion;\n}\n\nexport function mkOpinion(\n belief: number,\n disbelief: number,\n uncertainty: number,\n baseRate: number\n): SLOpinion {\n return opinion(belief, disbelief, uncertainty, baseRate);\n}\n\nexport function vacuous(baseRate: number): SLOpinion {\n return mkOpinion(0, 0, 1, baseRate);\n}\n\nexport function dogmatic(probability: number, baseRate: number): SLOpinion {\n const p = Math.max(0, Math.min(1, probability));\n return mkOpinion(p, 1 - p, 0, baseRate);\n}\n\nexport function project(o: SLOpinion): number {\n return o.b + o.a * o.u;\n}\n\nexport function confidenceLevel(o: SLOpinion): \"high\" | \"medium\" | \"low\" {\n const projected = project(o);\n if (o.u > 0.5) {\n return \"low\";\n }\n if (projected >= 0.8 && o.u < 0.2) {\n return \"high\";\n }\n if (projected >= 0.6) {\n return \"medium\";\n }\n return \"low\";\n}\n\nconst VACUOUS_IDENTITY_EPSILON = 1e-12;\n\n/**\n * Associative, vacuous-identity-preserving base rate for a fused opinion.\n *\n * The legacy `(left.a + right.a) / 2` arithmetic mean was the shared root of\n * RR.7 F1 (projected-confidence non-associativity) and F2 (a vacuous opinion of\n * a different base rate was not a fusion identity): averaging always pulled the\n * fused base rate toward the other operand even when that operand carried no\n * evidence. Subjective Logic requires every opinion over the same frame to share\n * one canonical base rate, so a correct fusion never *invents* a new base rate\n * from the operands' priors. We therefore:\n *\n * - return the informative operand's base rate when exactly one operand is\n * vacuous (the vacuous operand contributes no prior), making `vacuous(a)` a\n * true identity for any `a`; and\n * - require equal base rates otherwise (the canonical-frame contract). When\n * they coincide the result is that shared value — trivially associative.\n *\n * If two informative opinions carry genuinely different base rates they are not\n * opinions over the same frame and must be reconciled before fusion; we fall\n * back to the arithmetic mean ONLY in that ill-posed case to stay total, and the\n * property suite documents that this path is outside the order-independence\n * guarantee.\n */\nfunction fusedBaseRate(left: SLOpinion, right: SLOpinion): number {\n const leftVacuous = 1 - left.u <= VACUOUS_IDENTITY_EPSILON;\n const rightVacuous = 1 - right.u <= VACUOUS_IDENTITY_EPSILON;\n if (leftVacuous && !rightVacuous) {\n return right.a;\n }\n if (rightVacuous && !leftVacuous) {\n return left.a;\n }\n if (Math.abs(left.a - right.a) <= VACUOUS_IDENTITY_EPSILON) {\n return left.a;\n }\n return (left.a + right.a) / 2;\n}\n\nexport function cumulativeFusion(left: SLOpinion, right: SLOpinion): SLOpinion {\n const a = fusedBaseRate(left, right);\n\n // F2: a vacuous operand is the identity element of cumulative fusion. Return\n // the other operand verbatim (including its base rate) so fusion with the\n // vacuous opinion is a true no-op regardless of differing priors.\n if (1 - left.u <= VACUOUS_IDENTITY_EPSILON) {\n return opinion(right.b, right.d, right.u, a);\n }\n if (1 - right.u <= VACUOUS_IDENTITY_EPSILON) {\n return opinion(left.b, left.d, left.u, a);\n }\n\n // F4: dogmatic pair handled via the ε-limit of the cumulative rule rather than\n // the standalone `(b+d)/2` shortcut. As both uncertainties shrink at the same\n // rate, the cumulative formula's `(b_L·u_R + b_R·u_L)/k` term converges to the\n // arithmetic mean of the masses; deriving it from the same limit the interior\n // formula uses keeps mass-associativity intact (no special-case discontinuity).\n if (\n left.u <= VACUOUS_IDENTITY_EPSILON &&\n right.u <= VACUOUS_IDENTITY_EPSILON\n ) {\n return opinion((left.b + right.b) / 2, (left.d + right.d) / 2, 0, a);\n }\n\n const k = left.u + right.u - left.u * right.u;\n if (k === 0) {\n return vacuous(a);\n }\n\n return opinion(\n (left.b * right.u + right.b * left.u) / k,\n (left.d * right.u + right.d * left.u) / k,\n (left.u * right.u) / k,\n a\n );\n}\n\nexport function averagingFusion(left: SLOpinion, right: SLOpinion): SLOpinion {\n const a = fusedBaseRate(left, right);\n\n // F2: vacuous identity, mirroring cumulativeFusion.\n if (1 - left.u <= VACUOUS_IDENTITY_EPSILON) {\n return opinion(right.b, right.d, right.u, a);\n }\n if (1 - right.u <= VACUOUS_IDENTITY_EPSILON) {\n return opinion(left.b, left.d, left.u, a);\n }\n\n // F4: dogmatic pair via the ε-limit of the averaging rule.\n if (\n left.u <= VACUOUS_IDENTITY_EPSILON &&\n right.u <= VACUOUS_IDENTITY_EPSILON\n ) {\n return opinion((left.b + right.b) / 2, (left.d + right.d) / 2, 0, a);\n }\n\n const k = left.u + right.u;\n if (k === 0) {\n return vacuous(a);\n }\n\n return opinion(\n (left.b * right.u + right.b * left.u) / k,\n (left.d * right.u + right.d * left.u) / k,\n (2 * left.u * right.u) / k,\n a\n );\n}\n\nexport function trustDiscount(\n sourceOpinion: SLOpinion,\n trust: number\n): SLOpinion {\n const weight = Math.max(0, Math.min(1, Math.abs(trust)));\n return opinion(\n weight * sourceOpinion.b,\n weight * sourceOpinion.d,\n 1 - weight * (sourceOpinion.b + sourceOpinion.d),\n sourceOpinion.a\n );\n}\n\nconst EPSILON = 1e-9;\n\nfunction childBaseRateFallback(\n ifTrue: SLOpinion,\n ifFalse: SLOpinion,\n fallbackBaseRate: number | undefined\n): number {\n if (fallbackBaseRate !== undefined) {\n return Math.max(0, Math.min(1, fallbackBaseRate));\n }\n\n if (Math.abs(ifTrue.a - ifFalse.a) <= EPSILON) {\n return ifTrue.a;\n }\n\n return (ifTrue.a + ifFalse.a) / 2;\n}\n\nfunction computeConditionalDeductionBaseRate(\n opinionA: SLOpinion,\n ifTrue: SLOpinion,\n ifFalse: SLOpinion,\n fallbackBaseRate: number\n): number {\n const denominator = 1 - opinionA.a * ifTrue.u - (1 - opinionA.a) * ifFalse.u;\n\n if (ifTrue.u + ifFalse.u < 2 - EPSILON && Math.abs(denominator) > EPSILON) {\n const baseRate =\n (opinionA.a * ifTrue.b + (1 - opinionA.a) * ifFalse.b) / denominator;\n if (baseRate >= -EPSILON && baseRate <= 1 + EPSILON) {\n return Math.max(0, Math.min(1, baseRate));\n }\n }\n\n return fallbackBaseRate;\n}\n\nfunction safeCorrectionTerm(\n numerator: number,\n denominator: number\n): number | undefined {\n if (Math.abs(denominator) <= EPSILON) {\n return;\n }\n\n const value = numerator / denominator;\n if (!Number.isFinite(value)) {\n return;\n }\n\n return Math.max(0, value);\n}\n\ninterface ConditionalDeductionCorrectionContext {\n childBaseRate: number;\n ifFalse: SLOpinion;\n ifTrue: SLOpinion;\n intermediateBelief: number;\n intermediateDisbelief: number;\n opinionA: SLOpinion;\n projectedAntecedent: number;\n projectedAntecedentComplement: number;\n projectedConditionalA: number;\n projectedVacuousDeduction: number;\n}\n\nfunction correctionOrZero(numerator: number, denominator: number): number {\n return safeCorrectionTerm(numerator, denominator) ?? 0;\n}\n\nfunction hasNoConditionalDeductionCorrection(\n ifTrue: SLOpinion,\n ifFalse: SLOpinion\n): boolean {\n return (\n (ifTrue.b > ifFalse.b && ifTrue.d > ifFalse.d) ||\n (ifTrue.b <= ifFalse.b && ifTrue.d <= ifFalse.d)\n );\n}\n\nfunction usesLowerVacuousBranch(\n context: ConditionalDeductionCorrectionContext\n): boolean {\n return context.projectedVacuousDeduction <= context.projectedConditionalA;\n}\n\nfunction usesLowerAntecedentBranch(\n context: ConditionalDeductionCorrectionContext\n): boolean {\n return context.projectedAntecedent <= context.opinionA.a;\n}\n\nfunction computeTrueDominantDeductionCorrection(\n context: ConditionalDeductionCorrectionContext\n): number {\n const beliefGap = context.ifTrue.b - context.ifFalse.b;\n const disbeliefGap = context.ifFalse.d - context.ifTrue.d;\n const lowerVacuous = usesLowerVacuousBranch(context);\n const lowerAntecedent = usesLowerAntecedentBranch(context);\n\n if (lowerVacuous && lowerAntecedent) {\n return correctionOrZero(\n context.opinionA.a *\n context.opinionA.u *\n (context.intermediateBelief - context.ifTrue.b),\n context.projectedAntecedent * context.childBaseRate\n );\n }\n\n if (lowerVacuous) {\n return correctionOrZero(\n context.opinionA.a *\n context.opinionA.u *\n (context.intermediateDisbelief - context.ifTrue.d) *\n beliefGap,\n context.projectedAntecedentComplement *\n context.childBaseRate *\n disbeliefGap\n );\n }\n\n if (lowerAntecedent) {\n return correctionOrZero(\n (1 - context.opinionA.a) *\n context.opinionA.u *\n (context.intermediateBelief - context.ifTrue.b) *\n disbeliefGap,\n context.projectedAntecedent * (1 - context.childBaseRate) * beliefGap\n );\n }\n\n return correctionOrZero(\n (1 - context.opinionA.a) *\n context.opinionA.u *\n (context.intermediateDisbelief - context.ifTrue.d),\n context.projectedAntecedentComplement * (1 - context.childBaseRate)\n );\n}\n\nfunction computeFalseDominantDeductionCorrection(\n context: ConditionalDeductionCorrectionContext\n): number {\n const beliefGap = context.ifFalse.b - context.ifTrue.b;\n const disbeliefGap = context.ifTrue.d - context.ifFalse.d;\n const lowerVacuous = usesLowerVacuousBranch(context);\n const lowerAntecedent = usesLowerAntecedentBranch(context);\n\n if (lowerVacuous && lowerAntecedent) {\n return correctionOrZero(\n (1 - context.opinionA.a) *\n context.opinionA.u *\n (context.intermediateDisbelief - context.ifTrue.d) *\n beliefGap,\n context.projectedAntecedent * context.childBaseRate * disbeliefGap\n );\n }\n\n if (lowerVacuous) {\n return correctionOrZero(\n (1 - context.opinionA.a) *\n context.opinionA.u *\n (context.intermediateBelief - context.ifTrue.b),\n context.projectedAntecedentComplement * context.childBaseRate\n );\n }\n\n if (lowerAntecedent) {\n return correctionOrZero(\n context.opinionA.a *\n context.opinionA.u *\n (context.intermediateDisbelief - context.ifTrue.d),\n context.projectedAntecedent * (1 - context.childBaseRate)\n );\n }\n\n return correctionOrZero(\n context.opinionA.a *\n context.opinionA.u *\n (context.intermediateBelief - context.ifTrue.b) *\n disbeliefGap,\n context.projectedAntecedentComplement *\n (1 - context.childBaseRate) *\n beliefGap\n );\n}\n\nfunction computeConditionalDeductionCorrection(\n context: ConditionalDeductionCorrectionContext\n): number {\n if (hasNoConditionalDeductionCorrection(context.ifTrue, context.ifFalse)) {\n return 0;\n }\n\n if (\n context.ifTrue.b > context.ifFalse.b &&\n context.ifTrue.d <= context.ifFalse.d\n ) {\n return computeTrueDominantDeductionCorrection(context);\n }\n\n return computeFalseDominantDeductionCorrection(context);\n}\n\nexport function conditionalDeduction(\n opinionA: SLOpinion,\n ifTrue: SLOpinion,\n ifFalse: SLOpinion,\n fallbackBaseRate?: number\n): SLOpinion {\n const fallbackChildBaseRate = childBaseRateFallback(\n ifTrue,\n ifFalse,\n fallbackBaseRate\n );\n const childBaseRate = computeConditionalDeductionBaseRate(\n opinionA,\n ifTrue,\n ifFalse,\n fallbackChildBaseRate\n );\n const projectedAntecedent = project(opinionA);\n const projectedAntecedentComplement = 1 - projectedAntecedent;\n const intermediateBelief =\n opinionA.b * ifTrue.b +\n opinionA.d * ifFalse.b +\n opinionA.u * (ifTrue.b * opinionA.a + ifFalse.b * (1 - opinionA.a));\n const intermediateDisbelief =\n opinionA.b * ifTrue.d +\n opinionA.d * ifFalse.d +\n opinionA.u * (ifTrue.d * opinionA.a + ifFalse.d * (1 - opinionA.a));\n const intermediateUncertainty =\n opinionA.b * ifTrue.u +\n opinionA.d * ifFalse.u +\n opinionA.u * (ifTrue.u * opinionA.a + ifFalse.u * (1 - opinionA.a));\n const projectedVacuousDeduction =\n ifTrue.b * opinionA.a +\n ifFalse.b * (1 - opinionA.a) +\n childBaseRate * (ifTrue.u * opinionA.a + ifFalse.u * (1 - opinionA.a));\n const projectedConditionalA =\n ifTrue.b + childBaseRate * (1 - ifTrue.b - ifTrue.d);\n const correction = computeConditionalDeductionCorrection({\n childBaseRate,\n ifFalse,\n ifTrue,\n intermediateBelief,\n intermediateDisbelief,\n opinionA,\n projectedAntecedent,\n projectedAntecedentComplement,\n projectedConditionalA,\n projectedVacuousDeduction,\n });\n\n return opinion(\n intermediateBelief - childBaseRate * correction,\n intermediateDisbelief - (1 - childBaseRate) * correction,\n intermediateUncertainty + correction,\n childBaseRate\n );\n}\n\n/**\n * Abductive inference over a conditional.\n * Given an opinion on Y and conditionals P(Y|X), P(Y|~X), infer an opinion on X.\n */\nexport function conditionalAbduction(\n opinionY: SLOpinion,\n ifTrue: SLOpinion,\n ifFalse: SLOpinion,\n baseRateX: number\n): SLOpinion {\n const priorX = Math.max(0, Math.min(1, baseRateX));\n const probabilityY = project(opinionY);\n const probabilityGivenTrue = project(ifTrue);\n const probabilityGivenFalse = project(ifFalse);\n\n const posteriorIfYDenominator =\n probabilityGivenTrue * priorX + probabilityGivenFalse * (1 - priorX);\n const posteriorIfY =\n posteriorIfYDenominator === 0\n ? priorX\n : (probabilityGivenTrue * priorX) / posteriorIfYDenominator;\n\n const posteriorIfNotYDenominator =\n (1 - probabilityGivenTrue) * priorX +\n (1 - probabilityGivenFalse) * (1 - priorX);\n const posteriorIfNotY =\n posteriorIfNotYDenominator === 0\n ? priorX\n : ((1 - probabilityGivenTrue) * priorX) / posteriorIfNotYDenominator;\n\n const projectedX =\n probabilityY * posteriorIfY + (1 - probabilityY) * posteriorIfNotY;\n const uncertainty = Math.max(\n opinionY.u * 0.5,\n probabilityY * ifTrue.u + (1 - probabilityY) * ifFalse.u\n );\n\n return opinion(\n projectedX * (1 - uncertainty),\n (1 - projectedX) * (1 - uncertainty),\n uncertainty,\n priorX\n );\n}\n\nexport function negate(o: SLOpinion): SLOpinion {\n return mkOpinion(o.d, o.b, o.u, 1 - o.a);\n}\n\nexport function constraintFusion(\n left: SLOpinion,\n right: SLOpinion,\n mode: \"pressure\" | \"redistribute\" = \"pressure\"\n): { o1: SLOpinion; o2: SLOpinion } {\n if (mode === \"redistribute\") {\n const leftProjected = project(left);\n const rightProjected = project(right);\n const total = leftProjected + rightProjected;\n\n if (total <= 1) {\n return { o1: left, o2: right };\n }\n\n const scale = 1 / total;\n return {\n o1: opinion(\n left.b * scale,\n left.d + left.b * (1 - scale),\n left.u,\n left.a\n ),\n o2: opinion(\n right.b * scale,\n right.d + right.b * (1 - scale),\n right.u,\n right.a\n ),\n };\n }\n\n const pressureLeft = right.b * 0.5;\n const pressureRight = left.b * 0.5;\n\n return {\n o1: opinion(\n left.b - pressureLeft * 0.3,\n left.d + pressureLeft * 0.3,\n left.u,\n left.a\n ),\n o2: opinion(\n right.b - pressureRight * 0.3,\n right.d + pressureRight * 0.3,\n right.u,\n right.a\n ),\n };\n}\n\nexport function evidenceBalance(o: SLOpinion): number {\n const total = o.b + o.d;\n if (total === 0) {\n return 0;\n }\n return (o.b - o.d) / total;\n}\n\nexport function areTensioned(left: SLOpinion, right: SLOpinion): boolean {\n return (\n project(left) > 0.5 &&\n project(right) > 0.5 &&\n (left.d > 0.2 || right.d > 0.2)\n );\n}\n\nexport function informationGain(o: SLOpinion): number {\n if (o.u === 0) {\n return 0;\n }\n if (o.u === 1) {\n return 1;\n }\n return o.u * (1 - Math.abs(o.b - o.d));\n}\n","import type {\n BeliefLifecycleBucket,\n DeadlineUrgency,\n DeadlineUrgencyTier,\n DecayTier,\n EffectiveDecay,\n Opinion,\n RescoringSchedule,\n} from \"../../types\";\nimport { opinion } from \"../subjectiveLogic\";\n\ntype RescoringPriorityReason = Pick<RescoringSchedule, \"priority\" | \"reason\">;\n\ninterface RescoringPriorityContext {\n confidence?: number;\n daysUntilRescore: number;\n decayState: EffectiveDecay;\n isOverdue: boolean;\n lifecycleStatus: BeliefLifecycleBucket;\n temporalNature?: \"factual\" | \"forecast\" | \"unknown\" | null;\n}\n\ntype RescoringRule = (\n context: RescoringPriorityContext\n) => RescoringPriorityReason | undefined;\n\nexport const DECAY_TIERS: Record<string, DecayTier> = {\n FRESH: {\n maxAgeDays: 30,\n weight: 1,\n label: \"fresh\",\n action: \"Full confidence — recently validated\",\n rescoreInDays: 30,\n },\n AGING: {\n maxAgeDays: 90,\n weight: 0.8,\n label: \"aging\",\n action: \"Evidence refresh recommended\",\n rescoreInDays: 14,\n },\n STALE: {\n maxAgeDays: 180,\n weight: 0.5,\n label: \"stale\",\n action: \"Evidence update required before trusting\",\n rescoreInDays: 7,\n },\n EXPIRED: {\n maxAgeDays: Number.POSITIVE_INFINITY,\n weight: 0.2,\n label: \"expired\",\n action: \"Full re-evaluation needed\",\n rescoreInDays: 0,\n },\n};\n\nexport const DEADLINE_URGENCY: Record<string, DeadlineUrgencyTier> = {\n DISTANT: {\n minDaysToDeadline: 365,\n urgencyMultiplier: 1,\n label: \"distant\",\n rescoreIntervalDays: 90,\n action: \"Quarterly confidence check\",\n },\n APPROACHING: {\n minDaysToDeadline: 180,\n urgencyMultiplier: 0.9,\n label: \"approaching\",\n rescoreIntervalDays: 30,\n action: \"Monthly confidence check — conditions may be shifting\",\n },\n NEAR: {\n minDaysToDeadline: 90,\n urgencyMultiplier: 0.75,\n label: \"near\",\n rescoreIntervalDays: 14,\n action: \"Biweekly rescore — deadline within 3 months\",\n },\n IMMINENT: {\n minDaysToDeadline: 30,\n urgencyMultiplier: 0.6,\n label: \"imminent\",\n rescoreIntervalDays: 7,\n action: \"Weekly rescore — deadline within 1 month\",\n },\n CRITICAL: {\n minDaysToDeadline: 7,\n urgencyMultiplier: 0.4,\n label: \"critical\",\n rescoreIntervalDays: 1,\n action: \"Daily rescore — deadline THIS WEEK\",\n },\n OVERDUE: {\n minDaysToDeadline: Number.NEGATIVE_INFINITY,\n urgencyMultiplier: 0.2,\n label: \"overdue\",\n rescoreIntervalDays: 0,\n action: \"OVERDUE — must validate or archive immediately\",\n },\n};\n\nfunction normalizeBeliefConfidence(confidence: unknown): number | null {\n if (typeof confidence !== \"number\" || !Number.isFinite(confidence)) {\n return null;\n }\n if (confidence >= 0 && confidence <= 1) {\n return confidence;\n }\n if (confidence > 1 && confidence <= 100) {\n return confidence / 100;\n }\n return null;\n}\n\nfunction hasResolvedPredictionOutcome(predictionMeta: unknown): boolean {\n if (!predictionMeta || typeof predictionMeta !== \"object\") {\n return false;\n }\n\n const outcome = (predictionMeta as { outcome?: unknown }).outcome;\n return (\n outcome === \"confirmed\" ||\n outcome === \"disconfirmed\" ||\n outcome === \"partial\" ||\n outcome === \"expired\"\n );\n}\n\nfunction resolveLifecycleBucket(args: {\n beliefStatus?: string | null;\n confidence?: unknown;\n predictionMeta?: unknown;\n}): BeliefLifecycleBucket {\n if (\n normalizeBeliefConfidence(args.confidence) === 0 ||\n normalizeBeliefConfidence(args.confidence) === 1 ||\n hasResolvedPredictionOutcome(args.predictionMeta)\n ) {\n return \"fact\";\n }\n\n if (\n args.beliefStatus === \"assumption\" ||\n args.beliefStatus === \"hypothesis\" ||\n args.beliefStatus === \"belief\" ||\n args.beliefStatus === \"fact\"\n ) {\n if (\n normalizeBeliefConfidence(args.confidence) !== null &&\n (args.beliefStatus === \"assumption\" || args.beliefStatus === \"hypothesis\")\n ) {\n return \"belief\";\n }\n return args.beliefStatus;\n }\n\n return \"assumption\";\n}\n\nfunction lifecycleMultiplier(\n status: BeliefLifecycleBucket | string | null | undefined\n) {\n if (status === \"assumption\") {\n return 0.65;\n }\n if (status === \"hypothesis\") {\n return 0.8;\n }\n return 1;\n}\n\nfunction resolveLifecycleRescore(\n context: RescoringPriorityContext\n): RescoringPriorityReason | undefined {\n if (context.isOverdue && context.lifecycleStatus === \"assumption\") {\n return {\n priority: \"critical\",\n reason: `Untested assumption is stale (${Math.round(context.decayState.ageDays)}d) — validate or supersede`,\n };\n }\n\n if (\n (context.isOverdue && context.lifecycleStatus === \"hypothesis\") ||\n (context.lifecycleStatus === \"hypothesis\" && context.daysUntilRescore < 7)\n ) {\n return {\n priority: \"high\",\n reason: `Hypothesis aging without validation (${Math.round(context.decayState.ageDays)}d) — run/finish sprint testing`,\n };\n }\n}\n\nfunction resolveDeadlineRescore(\n context: RescoringPriorityContext\n): RescoringPriorityReason | undefined {\n const urgency = context.decayState.urgency;\n if (urgency?.isOverdue) {\n return {\n priority: \"critical\",\n reason: `Prediction deadline passed ${Math.abs(urgency.daysToDeadline)}d ago — validate or archive`,\n };\n }\n\n if (urgency?.urgencyTier.label === \"critical\") {\n return {\n priority: \"critical\",\n reason: `Deadline in ${urgency.daysToDeadline}d — needs immediate rescoring`,\n };\n }\n\n if (urgency?.urgencyTier.label === \"imminent\") {\n return {\n priority: \"high\",\n reason: `Deadline in ${urgency.daysToDeadline}d — weekly rescoring required`,\n };\n }\n}\n\nfunction resolveStalenessRescore(\n context: RescoringPriorityContext\n): RescoringPriorityReason | undefined {\n if (context.isOverdue && context.decayState.baseTier.label === \"expired\") {\n return {\n priority: \"critical\",\n reason: `Not scored in ${Math.round(context.decayState.ageDays)}d — confidence severely degraded`,\n };\n }\n\n if (context.isOverdue && context.decayState.baseTier.label === \"stale\") {\n return {\n priority: \"high\",\n reason: `Stale (${Math.round(context.decayState.ageDays)}d since scoring) — evidence update required`,\n };\n }\n\n if (context.isOverdue) {\n return {\n priority: \"high\",\n reason: `Rescore overdue by ${Math.abs(Math.round(context.daysUntilRescore))}d`,\n };\n }\n}\n\nfunction resolveRoutineRescore(\n context: RescoringPriorityContext\n): RescoringPriorityReason {\n if (context.temporalNature === \"forecast\" && context.daysUntilRescore < 7) {\n return {\n priority: \"medium\",\n reason: `Forecast belief — next rescore due in ${Math.round(context.daysUntilRescore)}d`,\n };\n }\n\n if (context.daysUntilRescore < 14) {\n return {\n priority: \"medium\",\n reason: `Rescore due in ${Math.round(context.daysUntilRescore)}d`,\n };\n }\n\n return {\n priority: \"low\",\n reason: `On schedule — next rescore in ${Math.round(context.daysUntilRescore)}d`,\n };\n}\n\nfunction escalateHighConfidenceRescore(\n result: RescoringPriorityReason,\n context: RescoringPriorityContext\n): RescoringPriorityReason {\n if (\n (context.confidence ?? 0) >= 0.8 &&\n context.decayState.baseTier.label !== \"fresh\" &&\n result.priority === \"medium\"\n ) {\n return {\n priority: \"high\",\n reason: `High-confidence belief (${((context.confidence ?? 0) * 100).toFixed(0)}%) aging without rescore — ${result.reason}`,\n };\n }\n\n return result;\n}\n\nconst RESCORING_RULES: readonly RescoringRule[] = [\n resolveLifecycleRescore,\n resolveDeadlineRescore,\n resolveStalenessRescore,\n];\n\nfunction resolveRescoringPriority(\n context: RescoringPriorityContext\n): RescoringPriorityReason {\n for (const rule of RESCORING_RULES) {\n const result = rule(context);\n if (result) {\n return escalateHighConfidenceRescore(result, context);\n }\n }\n\n return escalateHighConfidenceRescore(resolveRoutineRescore(context), context);\n}\n\nexport function computeBaseDecay(lastScoredAt: number): {\n ageDays: number;\n tier: DecayTier;\n weight: number;\n} {\n const ageDays = (Date.now() - lastScoredAt) / (1000 * 60 * 60 * 24);\n let tier = DECAY_TIERS.EXPIRED;\n\n if (ageDays <= DECAY_TIERS.FRESH.maxAgeDays) {\n tier = DECAY_TIERS.FRESH;\n } else if (ageDays <= DECAY_TIERS.AGING.maxAgeDays) {\n tier = DECAY_TIERS.AGING;\n } else if (ageDays <= DECAY_TIERS.STALE.maxAgeDays) {\n tier = DECAY_TIERS.STALE;\n }\n\n return { ageDays, tier, weight: tier.weight };\n}\n\nexport function computeDeadlineUrgency(\n expectedBy: number | null | undefined\n): DeadlineUrgency {\n if (!expectedBy) {\n return null;\n }\n\n const daysToDeadline = (expectedBy - Date.now()) / (1000 * 60 * 60 * 24);\n let urgencyTier = DEADLINE_URGENCY.DISTANT;\n\n if (daysToDeadline < 0) {\n urgencyTier = DEADLINE_URGENCY.OVERDUE;\n } else if (daysToDeadline <= 7) {\n urgencyTier = DEADLINE_URGENCY.CRITICAL;\n } else if (daysToDeadline <= 30) {\n urgencyTier = DEADLINE_URGENCY.IMMINENT;\n } else if (daysToDeadline <= 90) {\n urgencyTier = DEADLINE_URGENCY.NEAR;\n } else if (daysToDeadline <= 180) {\n urgencyTier = DEADLINE_URGENCY.APPROACHING;\n }\n\n return {\n daysToDeadline: Math.round(daysToDeadline),\n urgencyTier,\n urgencyMultiplier: urgencyTier.urgencyMultiplier,\n isOverdue: daysToDeadline < 0,\n };\n}\n\nexport function computeEffectiveDecay(\n lastScoredAt: number,\n expectedBy?: number | null,\n beliefStatus?: BeliefLifecycleBucket | string | null\n): EffectiveDecay {\n const base = computeBaseDecay(lastScoredAt);\n const urgency = computeDeadlineUrgency(expectedBy);\n const effectiveWeight =\n (urgency ? base.weight * urgency.urgencyMultiplier : base.weight) *\n lifecycleMultiplier(beliefStatus);\n\n const urgencyRescoreDays =\n urgency?.urgencyTier.rescoreIntervalDays ?? Number.POSITIVE_INFINITY;\n const rescoreInDays = Math.min(base.tier.rescoreInDays, urgencyRescoreDays);\n const rescoreByDate = lastScoredAt + rescoreInDays * 24 * 60 * 60 * 1000;\n\n let action = base.tier.action;\n if (urgency && urgency.urgencyTier.label !== \"distant\") {\n action = `${urgency.urgencyTier.action}. ${base.tier.action}`;\n }\n\n return {\n ageDays: base.ageDays,\n baseTier: base.tier,\n baseWeight: base.weight,\n urgency,\n effectiveWeight: Math.max(0, Math.min(1, effectiveWeight)),\n rescoreByDate,\n rescoreInDays,\n action,\n };\n}\n\nexport function getRescoringSchedule(opts: {\n lastScoredAt: number;\n temporalNature?: \"factual\" | \"forecast\" | \"unknown\" | null;\n expectedBy?: number | null;\n predictionMeta?: { expectedBy?: number; outcome?: unknown } | null;\n confidence?: number;\n beliefStatus?: string | null;\n}): RescoringSchedule {\n const lifecycleStatus = resolveLifecycleBucket({\n beliefStatus: opts.beliefStatus,\n confidence: opts.confidence,\n predictionMeta: opts.predictionMeta,\n });\n\n const decayState = computeEffectiveDecay(\n opts.lastScoredAt,\n opts.expectedBy,\n lifecycleStatus\n );\n const daysUntilRescore =\n (decayState.rescoreByDate - Date.now()) / (1000 * 60 * 60 * 24);\n const isOverdue = daysUntilRescore < 0;\n\n const { priority, reason } = resolveRescoringPriority({\n confidence: opts.confidence,\n daysUntilRescore,\n decayState,\n isOverdue,\n lifecycleStatus,\n temporalNature: opts.temporalNature,\n });\n\n return {\n nextRescoreBy: decayState.rescoreByDate,\n daysUntilRescore: Math.round(daysUntilRescore),\n isOverdue,\n priority,\n reason,\n decay: decayState,\n };\n}\n\nexport function decay(\n current: Opinion,\n daysSinceLastUpdate: number,\n halfLifeDays = 90\n): Opinion {\n if (daysSinceLastUpdate <= 0) {\n return current;\n }\n\n const decayFactor = 0.5 ** (daysSinceLastUpdate / halfLifeDays);\n const certainty = current.b + current.d;\n const lostCertainty = certainty - certainty * decayFactor;\n\n return opinion(\n current.b * decayFactor,\n current.d * decayFactor,\n current.u + lostCertainty,\n current.a\n );\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../src/v1/operations/subjectiveLogic/index.ts","../../../../src/v1/operations/dynamics/defeat.ts"],"names":[],"mappings":"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","file":"defeat.js","sourcesContent":["import type { SLOpinion } from \"../../types\";\n\nexport function opinion(\n belief: number,\n disbelief: number,\n uncertainty: number,\n baseRate: number\n): SLOpinion {\n const b = Number.isFinite(belief) ? Math.max(0, belief) : 0;\n const d = Number.isFinite(disbelief) ? Math.max(0, disbelief) : 0;\n const u = Number.isFinite(uncertainty) ? Math.max(0, uncertainty) : 0;\n const a = Math.max(0, Math.min(1, baseRate));\n const sum = b + d + u;\n\n if (sum === 0) {\n return { b: 0, d: 0, u: 1, a } as SLOpinion;\n }\n\n return {\n b: b / sum,\n d: d / sum,\n u: u / sum,\n a,\n } as SLOpinion;\n}\n\nexport function mkOpinion(\n belief: number,\n disbelief: number,\n uncertainty: number,\n baseRate: number\n): SLOpinion {\n return opinion(belief, disbelief, uncertainty, baseRate);\n}\n\nexport function vacuous(baseRate: number): SLOpinion {\n return mkOpinion(0, 0, 1, baseRate);\n}\n\nexport function dogmatic(probability: number, baseRate: number): SLOpinion {\n const p = Math.max(0, Math.min(1, probability));\n return mkOpinion(p, 1 - p, 0, baseRate);\n}\n\nexport function project(o: SLOpinion): number {\n return o.b + o.a * o.u;\n}\n\nexport function confidenceLevel(o: SLOpinion): \"high\" | \"medium\" | \"low\" {\n const projected = project(o);\n if (o.u > 0.5) {\n return \"low\";\n }\n if (projected >= 0.8 && o.u < 0.2) {\n return \"high\";\n }\n if (projected >= 0.6) {\n return \"medium\";\n }\n return \"low\";\n}\n\nconst VACUOUS_IDENTITY_EPSILON = 1e-12;\n\n/**\n * Associative, vacuous-identity-preserving base rate for a fused opinion.\n *\n * The legacy `(left.a + right.a) / 2` arithmetic mean was the shared root of\n * RR.7 F1 (projected-confidence non-associativity) and F2 (a vacuous opinion of\n * a different base rate was not a fusion identity): averaging always pulled the\n * fused base rate toward the other operand even when that operand carried no\n * evidence. Subjective Logic requires every opinion over the same frame to share\n * one canonical base rate, so a correct fusion never *invents* a new base rate\n * from the operands' priors. We therefore:\n *\n * - return the informative operand's base rate when exactly one operand is\n * vacuous (the vacuous operand contributes no prior), making `vacuous(a)` a\n * true identity for any `a`; and\n * - require equal base rates otherwise (the canonical-frame contract). When\n * they coincide the result is that shared value — trivially associative.\n *\n * If two informative opinions carry genuinely different base rates they are not\n * opinions over the same frame and must be reconciled before fusion; we fall\n * back to the arithmetic mean ONLY in that ill-posed case to stay total, and the\n * property suite documents that this path is outside the order-independence\n * guarantee.\n */\nfunction fusedBaseRate(left: SLOpinion, right: SLOpinion): number {\n const leftVacuous = 1 - left.u <= VACUOUS_IDENTITY_EPSILON;\n const rightVacuous = 1 - right.u <= VACUOUS_IDENTITY_EPSILON;\n if (leftVacuous && !rightVacuous) {\n return right.a;\n }\n if (rightVacuous && !leftVacuous) {\n return left.a;\n }\n if (Math.abs(left.a - right.a) <= VACUOUS_IDENTITY_EPSILON) {\n return left.a;\n }\n return (left.a + right.a) / 2;\n}\n\nexport function cumulativeFusion(left: SLOpinion, right: SLOpinion): SLOpinion {\n const a = fusedBaseRate(left, right);\n\n // F2: a vacuous operand is the identity element of cumulative fusion. Return\n // the other operand verbatim (including its base rate) so fusion with the\n // vacuous opinion is a true no-op regardless of differing priors.\n if (1 - left.u <= VACUOUS_IDENTITY_EPSILON) {\n return opinion(right.b, right.d, right.u, a);\n }\n if (1 - right.u <= VACUOUS_IDENTITY_EPSILON) {\n return opinion(left.b, left.d, left.u, a);\n }\n\n // F4: dogmatic pair handled via the ε-limit of the cumulative rule rather than\n // the standalone `(b+d)/2` shortcut. As both uncertainties shrink at the same\n // rate, the cumulative formula's `(b_L·u_R + b_R·u_L)/k` term converges to the\n // arithmetic mean of the masses; deriving it from the same limit the interior\n // formula uses keeps mass-associativity intact (no special-case discontinuity).\n if (\n left.u <= VACUOUS_IDENTITY_EPSILON &&\n right.u <= VACUOUS_IDENTITY_EPSILON\n ) {\n return opinion((left.b + right.b) / 2, (left.d + right.d) / 2, 0, a);\n }\n\n const k = left.u + right.u - left.u * right.u;\n if (k === 0) {\n return vacuous(a);\n }\n\n return opinion(\n (left.b * right.u + right.b * left.u) / k,\n (left.d * right.u + right.d * left.u) / k,\n (left.u * right.u) / k,\n a\n );\n}\n\nexport function averagingFusion(left: SLOpinion, right: SLOpinion): SLOpinion {\n const a = fusedBaseRate(left, right);\n\n // F2: vacuous identity, mirroring cumulativeFusion.\n if (1 - left.u <= VACUOUS_IDENTITY_EPSILON) {\n return opinion(right.b, right.d, right.u, a);\n }\n if (1 - right.u <= VACUOUS_IDENTITY_EPSILON) {\n return opinion(left.b, left.d, left.u, a);\n }\n\n // F4: dogmatic pair via the ε-limit of the averaging rule.\n if (\n left.u <= VACUOUS_IDENTITY_EPSILON &&\n right.u <= VACUOUS_IDENTITY_EPSILON\n ) {\n return opinion((left.b + right.b) / 2, (left.d + right.d) / 2, 0, a);\n }\n\n const k = left.u + right.u;\n if (k === 0) {\n return vacuous(a);\n }\n\n return opinion(\n (left.b * right.u + right.b * left.u) / k,\n (left.d * right.u + right.d * left.u) / k,\n (2 * left.u * right.u) / k,\n a\n );\n}\n\nexport function trustDiscount(\n sourceOpinion: SLOpinion,\n trust: number\n): SLOpinion {\n const weight = Math.max(0, Math.min(1, Math.abs(trust)));\n return opinion(\n weight * sourceOpinion.b,\n weight * sourceOpinion.d,\n 1 - weight * (sourceOpinion.b + sourceOpinion.d),\n sourceOpinion.a\n );\n}\n\nconst EPSILON = 1e-9;\n\nfunction childBaseRateFallback(\n ifTrue: SLOpinion,\n ifFalse: SLOpinion,\n fallbackBaseRate: number | undefined\n): number {\n if (fallbackBaseRate !== undefined) {\n return Math.max(0, Math.min(1, fallbackBaseRate));\n }\n\n if (Math.abs(ifTrue.a - ifFalse.a) <= EPSILON) {\n return ifTrue.a;\n }\n\n return (ifTrue.a + ifFalse.a) / 2;\n}\n\nfunction computeConditionalDeductionBaseRate(\n opinionA: SLOpinion,\n ifTrue: SLOpinion,\n ifFalse: SLOpinion,\n fallbackBaseRate: number\n): number {\n const denominator = 1 - opinionA.a * ifTrue.u - (1 - opinionA.a) * ifFalse.u;\n\n if (ifTrue.u + ifFalse.u < 2 - EPSILON && Math.abs(denominator) > EPSILON) {\n const baseRate =\n (opinionA.a * ifTrue.b + (1 - opinionA.a) * ifFalse.b) / denominator;\n if (baseRate >= -EPSILON && baseRate <= 1 + EPSILON) {\n return Math.max(0, Math.min(1, baseRate));\n }\n }\n\n return fallbackBaseRate;\n}\n\nfunction safeCorrectionTerm(\n numerator: number,\n denominator: number\n): number | undefined {\n if (Math.abs(denominator) <= EPSILON) {\n return;\n }\n\n const value = numerator / denominator;\n if (!Number.isFinite(value)) {\n return;\n }\n\n return Math.max(0, value);\n}\n\ninterface ConditionalDeductionCorrectionContext {\n childBaseRate: number;\n ifFalse: SLOpinion;\n ifTrue: SLOpinion;\n intermediateBelief: number;\n intermediateDisbelief: number;\n opinionA: SLOpinion;\n projectedAntecedent: number;\n projectedAntecedentComplement: number;\n projectedConditionalA: number;\n projectedVacuousDeduction: number;\n}\n\nfunction correctionOrZero(numerator: number, denominator: number): number {\n return safeCorrectionTerm(numerator, denominator) ?? 0;\n}\n\nfunction hasNoConditionalDeductionCorrection(\n ifTrue: SLOpinion,\n ifFalse: SLOpinion\n): boolean {\n return (\n (ifTrue.b > ifFalse.b && ifTrue.d > ifFalse.d) ||\n (ifTrue.b <= ifFalse.b && ifTrue.d <= ifFalse.d)\n );\n}\n\nfunction usesLowerVacuousBranch(\n context: ConditionalDeductionCorrectionContext\n): boolean {\n return context.projectedVacuousDeduction <= context.projectedConditionalA;\n}\n\nfunction usesLowerAntecedentBranch(\n context: ConditionalDeductionCorrectionContext\n): boolean {\n return context.projectedAntecedent <= context.opinionA.a;\n}\n\nfunction computeTrueDominantDeductionCorrection(\n context: ConditionalDeductionCorrectionContext\n): number {\n const beliefGap = context.ifTrue.b - context.ifFalse.b;\n const disbeliefGap = context.ifFalse.d - context.ifTrue.d;\n const lowerVacuous = usesLowerVacuousBranch(context);\n const lowerAntecedent = usesLowerAntecedentBranch(context);\n\n if (lowerVacuous && lowerAntecedent) {\n return correctionOrZero(\n context.opinionA.a *\n context.opinionA.u *\n (context.intermediateBelief - context.ifTrue.b),\n context.projectedAntecedent * context.childBaseRate\n );\n }\n\n if (lowerVacuous) {\n return correctionOrZero(\n context.opinionA.a *\n context.opinionA.u *\n (context.intermediateDisbelief - context.ifTrue.d) *\n beliefGap,\n context.projectedAntecedentComplement *\n context.childBaseRate *\n disbeliefGap\n );\n }\n\n if (lowerAntecedent) {\n return correctionOrZero(\n (1 - context.opinionA.a) *\n context.opinionA.u *\n (context.intermediateBelief - context.ifTrue.b) *\n disbeliefGap,\n context.projectedAntecedent * (1 - context.childBaseRate) * beliefGap\n );\n }\n\n return correctionOrZero(\n (1 - context.opinionA.a) *\n context.opinionA.u *\n (context.intermediateDisbelief - context.ifTrue.d),\n context.projectedAntecedentComplement * (1 - context.childBaseRate)\n );\n}\n\nfunction computeFalseDominantDeductionCorrection(\n context: ConditionalDeductionCorrectionContext\n): number {\n const beliefGap = context.ifFalse.b - context.ifTrue.b;\n const disbeliefGap = context.ifTrue.d - context.ifFalse.d;\n const lowerVacuous = usesLowerVacuousBranch(context);\n const lowerAntecedent = usesLowerAntecedentBranch(context);\n\n if (lowerVacuous && lowerAntecedent) {\n return correctionOrZero(\n (1 - context.opinionA.a) *\n context.opinionA.u *\n (context.intermediateDisbelief - context.ifTrue.d) *\n beliefGap,\n context.projectedAntecedent * context.childBaseRate * disbeliefGap\n );\n }\n\n if (lowerVacuous) {\n return correctionOrZero(\n (1 - context.opinionA.a) *\n context.opinionA.u *\n (context.intermediateBelief - context.ifTrue.b),\n context.projectedAntecedentComplement * context.childBaseRate\n );\n }\n\n if (lowerAntecedent) {\n return correctionOrZero(\n context.opinionA.a *\n context.opinionA.u *\n (context.intermediateDisbelief - context.ifTrue.d),\n context.projectedAntecedent * (1 - context.childBaseRate)\n );\n }\n\n return correctionOrZero(\n context.opinionA.a *\n context.opinionA.u *\n (context.intermediateBelief - context.ifTrue.b) *\n disbeliefGap,\n context.projectedAntecedentComplement *\n (1 - context.childBaseRate) *\n beliefGap\n );\n}\n\nfunction computeConditionalDeductionCorrection(\n context: ConditionalDeductionCorrectionContext\n): number {\n if (hasNoConditionalDeductionCorrection(context.ifTrue, context.ifFalse)) {\n return 0;\n }\n\n if (\n context.ifTrue.b > context.ifFalse.b &&\n context.ifTrue.d <= context.ifFalse.d\n ) {\n return computeTrueDominantDeductionCorrection(context);\n }\n\n return computeFalseDominantDeductionCorrection(context);\n}\n\nexport function conditionalDeduction(\n opinionA: SLOpinion,\n ifTrue: SLOpinion,\n ifFalse: SLOpinion,\n fallbackBaseRate?: number\n): SLOpinion {\n const fallbackChildBaseRate = childBaseRateFallback(\n ifTrue,\n ifFalse,\n fallbackBaseRate\n );\n const childBaseRate = computeConditionalDeductionBaseRate(\n opinionA,\n ifTrue,\n ifFalse,\n fallbackChildBaseRate\n );\n const projectedAntecedent = project(opinionA);\n const projectedAntecedentComplement = 1 - projectedAntecedent;\n const intermediateBelief =\n opinionA.b * ifTrue.b +\n opinionA.d * ifFalse.b +\n opinionA.u * (ifTrue.b * opinionA.a + ifFalse.b * (1 - opinionA.a));\n const intermediateDisbelief =\n opinionA.b * ifTrue.d +\n opinionA.d * ifFalse.d +\n opinionA.u * (ifTrue.d * opinionA.a + ifFalse.d * (1 - opinionA.a));\n const intermediateUncertainty =\n opinionA.b * ifTrue.u +\n opinionA.d * ifFalse.u +\n opinionA.u * (ifTrue.u * opinionA.a + ifFalse.u * (1 - opinionA.a));\n const projectedVacuousDeduction =\n ifTrue.b * opinionA.a +\n ifFalse.b * (1 - opinionA.a) +\n childBaseRate * (ifTrue.u * opinionA.a + ifFalse.u * (1 - opinionA.a));\n const projectedConditionalA =\n ifTrue.b + childBaseRate * (1 - ifTrue.b - ifTrue.d);\n const correction = computeConditionalDeductionCorrection({\n childBaseRate,\n ifFalse,\n ifTrue,\n intermediateBelief,\n intermediateDisbelief,\n opinionA,\n projectedAntecedent,\n projectedAntecedentComplement,\n projectedConditionalA,\n projectedVacuousDeduction,\n });\n\n return opinion(\n intermediateBelief - childBaseRate * correction,\n intermediateDisbelief - (1 - childBaseRate) * correction,\n intermediateUncertainty + correction,\n childBaseRate\n );\n}\n\n/**\n * Abductive inference over a conditional.\n * Given an opinion on Y and conditionals P(Y|X), P(Y|~X), infer an opinion on X.\n */\nexport function conditionalAbduction(\n opinionY: SLOpinion,\n ifTrue: SLOpinion,\n ifFalse: SLOpinion,\n baseRateX: number\n): SLOpinion {\n const priorX = Math.max(0, Math.min(1, baseRateX));\n const probabilityY = project(opinionY);\n const probabilityGivenTrue = project(ifTrue);\n const probabilityGivenFalse = project(ifFalse);\n\n const posteriorIfYDenominator =\n probabilityGivenTrue * priorX + probabilityGivenFalse * (1 - priorX);\n const posteriorIfY =\n posteriorIfYDenominator === 0\n ? priorX\n : (probabilityGivenTrue * priorX) / posteriorIfYDenominator;\n\n const posteriorIfNotYDenominator =\n (1 - probabilityGivenTrue) * priorX +\n (1 - probabilityGivenFalse) * (1 - priorX);\n const posteriorIfNotY =\n posteriorIfNotYDenominator === 0\n ? priorX\n : ((1 - probabilityGivenTrue) * priorX) / posteriorIfNotYDenominator;\n\n const projectedX =\n probabilityY * posteriorIfY + (1 - probabilityY) * posteriorIfNotY;\n const uncertainty = Math.max(\n opinionY.u * 0.5,\n probabilityY * ifTrue.u + (1 - probabilityY) * ifFalse.u\n );\n\n return opinion(\n projectedX * (1 - uncertainty),\n (1 - projectedX) * (1 - uncertainty),\n uncertainty,\n priorX\n );\n}\n\nexport function negate(o: SLOpinion): SLOpinion {\n return mkOpinion(o.d, o.b, o.u, 1 - o.a);\n}\n\nexport function constraintFusion(\n left: SLOpinion,\n right: SLOpinion,\n mode: \"pressure\" | \"redistribute\" = \"pressure\"\n): { o1: SLOpinion; o2: SLOpinion } {\n if (mode === \"redistribute\") {\n const leftProjected = project(left);\n const rightProjected = project(right);\n const total = leftProjected + rightProjected;\n\n if (total <= 1) {\n return { o1: left, o2: right };\n }\n\n const scale = 1 / total;\n return {\n o1: opinion(\n left.b * scale,\n left.d + left.b * (1 - scale),\n left.u,\n left.a\n ),\n o2: opinion(\n right.b * scale,\n right.d + right.b * (1 - scale),\n right.u,\n right.a\n ),\n };\n }\n\n const pressureLeft = right.b * 0.5;\n const pressureRight = left.b * 0.5;\n\n return {\n o1: opinion(\n left.b - pressureLeft * 0.3,\n left.d + pressureLeft * 0.3,\n left.u,\n left.a\n ),\n o2: opinion(\n right.b - pressureRight * 0.3,\n right.d + pressureRight * 0.3,\n right.u,\n right.a\n ),\n };\n}\n\nexport function evidenceBalance(o: SLOpinion): number {\n const total = o.b + o.d;\n if (total === 0) {\n return 0;\n }\n return (o.b - o.d) / total;\n}\n\nexport function areTensioned(left: SLOpinion, right: SLOpinion): boolean {\n return (\n project(left) > 0.5 &&\n project(right) > 0.5 &&\n (left.d > 0.2 || right.d > 0.2)\n );\n}\n\nexport function informationGain(o: SLOpinion): number {\n if (o.u === 0) {\n return 0;\n }\n if (o.u === 1) {\n return 1;\n }\n return o.u * (1 - Math.abs(o.b - o.d));\n}\n","import type { EdgeMetadata, Opinion, PropagationResult } from \"../../types\";\nimport {\n constraintFusion,\n cumulativeFusion,\n mkOpinion,\n negate,\n project,\n trustDiscount,\n} from \"../subjectiveLogic\";\n\nexport function applyNegativeSupport(\n source: Opinion,\n target: Opinion,\n weight: number,\n metadata: EdgeMetadata = {}\n): PropagationResult {\n const sourceOpinion = mkOpinion(source.b, source.d, source.u, source.a);\n const targetOpinion = mkOpinion(target.b, target.d, target.u, target.a);\n if (metadata.constraint === \"xor\") {\n const result = constraintFusion(\n sourceOpinion,\n targetOpinion,\n metadata.normalization ?? \"pressure\"\n );\n return {\n opinion: result.o2,\n operator: \"constraint_fusion\",\n rationale: `XOR constraint: source belief at ${project(\n sourceOpinion\n ).toFixed(2)} pressures target`,\n };\n }\n\n const discounted = trustDiscount(negate(sourceOpinion), Math.abs(weight));\n return {\n opinion: cumulativeFusion(targetOpinion, discounted),\n operator: \"cumulative_fusion\",\n rationale: `Contradicting evidence (weight=${weight.toFixed(\n 2\n )}) from source at ${project(sourceOpinion).toFixed(2)}`,\n };\n}\n\nexport function applyNegativeEvidence(\n source: Opinion,\n target: Opinion,\n weight: number\n): PropagationResult {\n const sourceOpinion = mkOpinion(source.b, source.d, source.u, source.a);\n const targetOpinion = mkOpinion(target.b, target.d, target.u, target.a);\n const discounted = trustDiscount(negate(sourceOpinion), Math.abs(weight));\n return {\n opinion: cumulativeFusion(targetOpinion, discounted),\n operator: \"cumulative_fusion\",\n rationale: `Contradicting evidence (weight=${weight.toFixed(2)})`,\n };\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../src/v1/operations/subjectiveLogic/index.ts","../../../../src/v1/operations/dynamics/cascade.ts","../../../../src/v1/operations/dynamics/defeat.ts","../../../../src/v1/operations/dynamics/propagation.ts"],"names":[],"mappings":"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","file":"propagation.js","sourcesContent":["import type { SLOpinion } from \"../../types\";\n\nexport function opinion(\n belief: number,\n disbelief: number,\n uncertainty: number,\n baseRate: number\n): SLOpinion {\n const b = Number.isFinite(belief) ? Math.max(0, belief) : 0;\n const d = Number.isFinite(disbelief) ? Math.max(0, disbelief) : 0;\n const u = Number.isFinite(uncertainty) ? Math.max(0, uncertainty) : 0;\n const a = Math.max(0, Math.min(1, baseRate));\n const sum = b + d + u;\n\n if (sum === 0) {\n return { b: 0, d: 0, u: 1, a } as SLOpinion;\n }\n\n return {\n b: b / sum,\n d: d / sum,\n u: u / sum,\n a,\n } as SLOpinion;\n}\n\nexport function mkOpinion(\n belief: number,\n disbelief: number,\n uncertainty: number,\n baseRate: number\n): SLOpinion {\n return opinion(belief, disbelief, uncertainty, baseRate);\n}\n\nexport function vacuous(baseRate: number): SLOpinion {\n return mkOpinion(0, 0, 1, baseRate);\n}\n\nexport function dogmatic(probability: number, baseRate: number): SLOpinion {\n const p = Math.max(0, Math.min(1, probability));\n return mkOpinion(p, 1 - p, 0, baseRate);\n}\n\nexport function project(o: SLOpinion): number {\n return o.b + o.a * o.u;\n}\n\nexport function confidenceLevel(o: SLOpinion): \"high\" | \"medium\" | \"low\" {\n const projected = project(o);\n if (o.u > 0.5) {\n return \"low\";\n }\n if (projected >= 0.8 && o.u < 0.2) {\n return \"high\";\n }\n if (projected >= 0.6) {\n return \"medium\";\n }\n return \"low\";\n}\n\nconst VACUOUS_IDENTITY_EPSILON = 1e-12;\n\n/**\n * Associative, vacuous-identity-preserving base rate for a fused opinion.\n *\n * The legacy `(left.a + right.a) / 2` arithmetic mean was the shared root of\n * RR.7 F1 (projected-confidence non-associativity) and F2 (a vacuous opinion of\n * a different base rate was not a fusion identity): averaging always pulled the\n * fused base rate toward the other operand even when that operand carried no\n * evidence. Subjective Logic requires every opinion over the same frame to share\n * one canonical base rate, so a correct fusion never *invents* a new base rate\n * from the operands' priors. We therefore:\n *\n * - return the informative operand's base rate when exactly one operand is\n * vacuous (the vacuous operand contributes no prior), making `vacuous(a)` a\n * true identity for any `a`; and\n * - require equal base rates otherwise (the canonical-frame contract). When\n * they coincide the result is that shared value — trivially associative.\n *\n * If two informative opinions carry genuinely different base rates they are not\n * opinions over the same frame and must be reconciled before fusion; we fall\n * back to the arithmetic mean ONLY in that ill-posed case to stay total, and the\n * property suite documents that this path is outside the order-independence\n * guarantee.\n */\nfunction fusedBaseRate(left: SLOpinion, right: SLOpinion): number {\n const leftVacuous = 1 - left.u <= VACUOUS_IDENTITY_EPSILON;\n const rightVacuous = 1 - right.u <= VACUOUS_IDENTITY_EPSILON;\n if (leftVacuous && !rightVacuous) {\n return right.a;\n }\n if (rightVacuous && !leftVacuous) {\n return left.a;\n }\n if (Math.abs(left.a - right.a) <= VACUOUS_IDENTITY_EPSILON) {\n return left.a;\n }\n return (left.a + right.a) / 2;\n}\n\nexport function cumulativeFusion(left: SLOpinion, right: SLOpinion): SLOpinion {\n const a = fusedBaseRate(left, right);\n\n // F2: a vacuous operand is the identity element of cumulative fusion. Return\n // the other operand verbatim (including its base rate) so fusion with the\n // vacuous opinion is a true no-op regardless of differing priors.\n if (1 - left.u <= VACUOUS_IDENTITY_EPSILON) {\n return opinion(right.b, right.d, right.u, a);\n }\n if (1 - right.u <= VACUOUS_IDENTITY_EPSILON) {\n return opinion(left.b, left.d, left.u, a);\n }\n\n // F4: dogmatic pair handled via the ε-limit of the cumulative rule rather than\n // the standalone `(b+d)/2` shortcut. As both uncertainties shrink at the same\n // rate, the cumulative formula's `(b_L·u_R + b_R·u_L)/k` term converges to the\n // arithmetic mean of the masses; deriving it from the same limit the interior\n // formula uses keeps mass-associativity intact (no special-case discontinuity).\n if (\n left.u <= VACUOUS_IDENTITY_EPSILON &&\n right.u <= VACUOUS_IDENTITY_EPSILON\n ) {\n return opinion((left.b + right.b) / 2, (left.d + right.d) / 2, 0, a);\n }\n\n const k = left.u + right.u - left.u * right.u;\n if (k === 0) {\n return vacuous(a);\n }\n\n return opinion(\n (left.b * right.u + right.b * left.u) / k,\n (left.d * right.u + right.d * left.u) / k,\n (left.u * right.u) / k,\n a\n );\n}\n\nexport function averagingFusion(left: SLOpinion, right: SLOpinion): SLOpinion {\n const a = fusedBaseRate(left, right);\n\n // F2: vacuous identity, mirroring cumulativeFusion.\n if (1 - left.u <= VACUOUS_IDENTITY_EPSILON) {\n return opinion(right.b, right.d, right.u, a);\n }\n if (1 - right.u <= VACUOUS_IDENTITY_EPSILON) {\n return opinion(left.b, left.d, left.u, a);\n }\n\n // F4: dogmatic pair via the ε-limit of the averaging rule.\n if (\n left.u <= VACUOUS_IDENTITY_EPSILON &&\n right.u <= VACUOUS_IDENTITY_EPSILON\n ) {\n return opinion((left.b + right.b) / 2, (left.d + right.d) / 2, 0, a);\n }\n\n const k = left.u + right.u;\n if (k === 0) {\n return vacuous(a);\n }\n\n return opinion(\n (left.b * right.u + right.b * left.u) / k,\n (left.d * right.u + right.d * left.u) / k,\n (2 * left.u * right.u) / k,\n a\n );\n}\n\nexport function trustDiscount(\n sourceOpinion: SLOpinion,\n trust: number\n): SLOpinion {\n const weight = Math.max(0, Math.min(1, Math.abs(trust)));\n return opinion(\n weight * sourceOpinion.b,\n weight * sourceOpinion.d,\n 1 - weight * (sourceOpinion.b + sourceOpinion.d),\n sourceOpinion.a\n );\n}\n\nconst EPSILON = 1e-9;\n\nfunction childBaseRateFallback(\n ifTrue: SLOpinion,\n ifFalse: SLOpinion,\n fallbackBaseRate: number | undefined\n): number {\n if (fallbackBaseRate !== undefined) {\n return Math.max(0, Math.min(1, fallbackBaseRate));\n }\n\n if (Math.abs(ifTrue.a - ifFalse.a) <= EPSILON) {\n return ifTrue.a;\n }\n\n return (ifTrue.a + ifFalse.a) / 2;\n}\n\nfunction computeConditionalDeductionBaseRate(\n opinionA: SLOpinion,\n ifTrue: SLOpinion,\n ifFalse: SLOpinion,\n fallbackBaseRate: number\n): number {\n const denominator = 1 - opinionA.a * ifTrue.u - (1 - opinionA.a) * ifFalse.u;\n\n if (ifTrue.u + ifFalse.u < 2 - EPSILON && Math.abs(denominator) > EPSILON) {\n const baseRate =\n (opinionA.a * ifTrue.b + (1 - opinionA.a) * ifFalse.b) / denominator;\n if (baseRate >= -EPSILON && baseRate <= 1 + EPSILON) {\n return Math.max(0, Math.min(1, baseRate));\n }\n }\n\n return fallbackBaseRate;\n}\n\nfunction safeCorrectionTerm(\n numerator: number,\n denominator: number\n): number | undefined {\n if (Math.abs(denominator) <= EPSILON) {\n return;\n }\n\n const value = numerator / denominator;\n if (!Number.isFinite(value)) {\n return;\n }\n\n return Math.max(0, value);\n}\n\ninterface ConditionalDeductionCorrectionContext {\n childBaseRate: number;\n ifFalse: SLOpinion;\n ifTrue: SLOpinion;\n intermediateBelief: number;\n intermediateDisbelief: number;\n opinionA: SLOpinion;\n projectedAntecedent: number;\n projectedAntecedentComplement: number;\n projectedConditionalA: number;\n projectedVacuousDeduction: number;\n}\n\nfunction correctionOrZero(numerator: number, denominator: number): number {\n return safeCorrectionTerm(numerator, denominator) ?? 0;\n}\n\nfunction hasNoConditionalDeductionCorrection(\n ifTrue: SLOpinion,\n ifFalse: SLOpinion\n): boolean {\n return (\n (ifTrue.b > ifFalse.b && ifTrue.d > ifFalse.d) ||\n (ifTrue.b <= ifFalse.b && ifTrue.d <= ifFalse.d)\n );\n}\n\nfunction usesLowerVacuousBranch(\n context: ConditionalDeductionCorrectionContext\n): boolean {\n return context.projectedVacuousDeduction <= context.projectedConditionalA;\n}\n\nfunction usesLowerAntecedentBranch(\n context: ConditionalDeductionCorrectionContext\n): boolean {\n return context.projectedAntecedent <= context.opinionA.a;\n}\n\nfunction computeTrueDominantDeductionCorrection(\n context: ConditionalDeductionCorrectionContext\n): number {\n const beliefGap = context.ifTrue.b - context.ifFalse.b;\n const disbeliefGap = context.ifFalse.d - context.ifTrue.d;\n const lowerVacuous = usesLowerVacuousBranch(context);\n const lowerAntecedent = usesLowerAntecedentBranch(context);\n\n if (lowerVacuous && lowerAntecedent) {\n return correctionOrZero(\n context.opinionA.a *\n context.opinionA.u *\n (context.intermediateBelief - context.ifTrue.b),\n context.projectedAntecedent * context.childBaseRate\n );\n }\n\n if (lowerVacuous) {\n return correctionOrZero(\n context.opinionA.a *\n context.opinionA.u *\n (context.intermediateDisbelief - context.ifTrue.d) *\n beliefGap,\n context.projectedAntecedentComplement *\n context.childBaseRate *\n disbeliefGap\n );\n }\n\n if (lowerAntecedent) {\n return correctionOrZero(\n (1 - context.opinionA.a) *\n context.opinionA.u *\n (context.intermediateBelief - context.ifTrue.b) *\n disbeliefGap,\n context.projectedAntecedent * (1 - context.childBaseRate) * beliefGap\n );\n }\n\n return correctionOrZero(\n (1 - context.opinionA.a) *\n context.opinionA.u *\n (context.intermediateDisbelief - context.ifTrue.d),\n context.projectedAntecedentComplement * (1 - context.childBaseRate)\n );\n}\n\nfunction computeFalseDominantDeductionCorrection(\n context: ConditionalDeductionCorrectionContext\n): number {\n const beliefGap = context.ifFalse.b - context.ifTrue.b;\n const disbeliefGap = context.ifTrue.d - context.ifFalse.d;\n const lowerVacuous = usesLowerVacuousBranch(context);\n const lowerAntecedent = usesLowerAntecedentBranch(context);\n\n if (lowerVacuous && lowerAntecedent) {\n return correctionOrZero(\n (1 - context.opinionA.a) *\n context.opinionA.u *\n (context.intermediateDisbelief - context.ifTrue.d) *\n beliefGap,\n context.projectedAntecedent * context.childBaseRate * disbeliefGap\n );\n }\n\n if (lowerVacuous) {\n return correctionOrZero(\n (1 - context.opinionA.a) *\n context.opinionA.u *\n (context.intermediateBelief - context.ifTrue.b),\n context.projectedAntecedentComplement * context.childBaseRate\n );\n }\n\n if (lowerAntecedent) {\n return correctionOrZero(\n context.opinionA.a *\n context.opinionA.u *\n (context.intermediateDisbelief - context.ifTrue.d),\n context.projectedAntecedent * (1 - context.childBaseRate)\n );\n }\n\n return correctionOrZero(\n context.opinionA.a *\n context.opinionA.u *\n (context.intermediateBelief - context.ifTrue.b) *\n disbeliefGap,\n context.projectedAntecedentComplement *\n (1 - context.childBaseRate) *\n beliefGap\n );\n}\n\nfunction computeConditionalDeductionCorrection(\n context: ConditionalDeductionCorrectionContext\n): number {\n if (hasNoConditionalDeductionCorrection(context.ifTrue, context.ifFalse)) {\n return 0;\n }\n\n if (\n context.ifTrue.b > context.ifFalse.b &&\n context.ifTrue.d <= context.ifFalse.d\n ) {\n return computeTrueDominantDeductionCorrection(context);\n }\n\n return computeFalseDominantDeductionCorrection(context);\n}\n\nexport function conditionalDeduction(\n opinionA: SLOpinion,\n ifTrue: SLOpinion,\n ifFalse: SLOpinion,\n fallbackBaseRate?: number\n): SLOpinion {\n const fallbackChildBaseRate = childBaseRateFallback(\n ifTrue,\n ifFalse,\n fallbackBaseRate\n );\n const childBaseRate = computeConditionalDeductionBaseRate(\n opinionA,\n ifTrue,\n ifFalse,\n fallbackChildBaseRate\n );\n const projectedAntecedent = project(opinionA);\n const projectedAntecedentComplement = 1 - projectedAntecedent;\n const intermediateBelief =\n opinionA.b * ifTrue.b +\n opinionA.d * ifFalse.b +\n opinionA.u * (ifTrue.b * opinionA.a + ifFalse.b * (1 - opinionA.a));\n const intermediateDisbelief =\n opinionA.b * ifTrue.d +\n opinionA.d * ifFalse.d +\n opinionA.u * (ifTrue.d * opinionA.a + ifFalse.d * (1 - opinionA.a));\n const intermediateUncertainty =\n opinionA.b * ifTrue.u +\n opinionA.d * ifFalse.u +\n opinionA.u * (ifTrue.u * opinionA.a + ifFalse.u * (1 - opinionA.a));\n const projectedVacuousDeduction =\n ifTrue.b * opinionA.a +\n ifFalse.b * (1 - opinionA.a) +\n childBaseRate * (ifTrue.u * opinionA.a + ifFalse.u * (1 - opinionA.a));\n const projectedConditionalA =\n ifTrue.b + childBaseRate * (1 - ifTrue.b - ifTrue.d);\n const correction = computeConditionalDeductionCorrection({\n childBaseRate,\n ifFalse,\n ifTrue,\n intermediateBelief,\n intermediateDisbelief,\n opinionA,\n projectedAntecedent,\n projectedAntecedentComplement,\n projectedConditionalA,\n projectedVacuousDeduction,\n });\n\n return opinion(\n intermediateBelief - childBaseRate * correction,\n intermediateDisbelief - (1 - childBaseRate) * correction,\n intermediateUncertainty + correction,\n childBaseRate\n );\n}\n\n/**\n * Abductive inference over a conditional.\n * Given an opinion on Y and conditionals P(Y|X), P(Y|~X), infer an opinion on X.\n */\nexport function conditionalAbduction(\n opinionY: SLOpinion,\n ifTrue: SLOpinion,\n ifFalse: SLOpinion,\n baseRateX: number\n): SLOpinion {\n const priorX = Math.max(0, Math.min(1, baseRateX));\n const probabilityY = project(opinionY);\n const probabilityGivenTrue = project(ifTrue);\n const probabilityGivenFalse = project(ifFalse);\n\n const posteriorIfYDenominator =\n probabilityGivenTrue * priorX + probabilityGivenFalse * (1 - priorX);\n const posteriorIfY =\n posteriorIfYDenominator === 0\n ? priorX\n : (probabilityGivenTrue * priorX) / posteriorIfYDenominator;\n\n const posteriorIfNotYDenominator =\n (1 - probabilityGivenTrue) * priorX +\n (1 - probabilityGivenFalse) * (1 - priorX);\n const posteriorIfNotY =\n posteriorIfNotYDenominator === 0\n ? priorX\n : ((1 - probabilityGivenTrue) * priorX) / posteriorIfNotYDenominator;\n\n const projectedX =\n probabilityY * posteriorIfY + (1 - probabilityY) * posteriorIfNotY;\n const uncertainty = Math.max(\n opinionY.u * 0.5,\n probabilityY * ifTrue.u + (1 - probabilityY) * ifFalse.u\n );\n\n return opinion(\n projectedX * (1 - uncertainty),\n (1 - projectedX) * (1 - uncertainty),\n uncertainty,\n priorX\n );\n}\n\nexport function negate(o: SLOpinion): SLOpinion {\n return mkOpinion(o.d, o.b, o.u, 1 - o.a);\n}\n\nexport function constraintFusion(\n left: SLOpinion,\n right: SLOpinion,\n mode: \"pressure\" | \"redistribute\" = \"pressure\"\n): { o1: SLOpinion; o2: SLOpinion } {\n if (mode === \"redistribute\") {\n const leftProjected = project(left);\n const rightProjected = project(right);\n const total = leftProjected + rightProjected;\n\n if (total <= 1) {\n return { o1: left, o2: right };\n }\n\n const scale = 1 / total;\n return {\n o1: opinion(\n left.b * scale,\n left.d + left.b * (1 - scale),\n left.u,\n left.a\n ),\n o2: opinion(\n right.b * scale,\n right.d + right.b * (1 - scale),\n right.u,\n right.a\n ),\n };\n }\n\n const pressureLeft = right.b * 0.5;\n const pressureRight = left.b * 0.5;\n\n return {\n o1: opinion(\n left.b - pressureLeft * 0.3,\n left.d + pressureLeft * 0.3,\n left.u,\n left.a\n ),\n o2: opinion(\n right.b - pressureRight * 0.3,\n right.d + pressureRight * 0.3,\n right.u,\n right.a\n ),\n };\n}\n\nexport function evidenceBalance(o: SLOpinion): number {\n const total = o.b + o.d;\n if (total === 0) {\n return 0;\n }\n return (o.b - o.d) / total;\n}\n\nexport function areTensioned(left: SLOpinion, right: SLOpinion): boolean {\n return (\n project(left) > 0.5 &&\n project(right) > 0.5 &&\n (left.d > 0.2 || right.d > 0.2)\n );\n}\n\nexport function informationGain(o: SLOpinion): number {\n if (o.u === 0) {\n return 0;\n }\n if (o.u === 1) {\n return 1;\n }\n return o.u * (1 - Math.abs(o.b - o.d));\n}\n","import type { Opinion, PropagationMode, PropagationResult } from \"../../types\";\nimport { mkOpinion, opinion, project } from \"../subjectiveLogic\";\n\nexport function dampedDependencyOpinion(\n dependencyOpinion: Opinion,\n beliefOpinion: Opinion,\n mode: PropagationMode = \"continuous\",\n threshold = 0.3\n): Opinion {\n const dependencyProjection = project(\n mkOpinion(\n dependencyOpinion.b,\n dependencyOpinion.d,\n dependencyOpinion.u,\n dependencyOpinion.a\n )\n );\n\n if (mode === \"threshold\") {\n if (dependencyProjection < threshold) {\n return opinion(\n 0,\n beliefOpinion.d + beliefOpinion.b * 0.5,\n 0.5,\n beliefOpinion.a\n );\n }\n return beliefOpinion;\n }\n\n const dampingFactor = dependencyProjection ** 0.5;\n return opinion(\n beliefOpinion.b * dampingFactor,\n beliefOpinion.d + beliefOpinion.b * (1 - dampingFactor) * 0.3,\n beliefOpinion.u + beliefOpinion.b * (1 - dampingFactor) * 0.7,\n beliefOpinion.a\n );\n}\n\nexport function dampedDependencyCascade(\n dependencyOpinion: Opinion,\n beliefOpinion: Opinion,\n mode: PropagationMode = \"continuous\"\n): PropagationResult {\n return {\n opinion: dampedDependencyOpinion(dependencyOpinion, beliefOpinion, mode),\n operator: \"dependency_cascade\",\n rationale: `Damped dependency cascade (${mode}): prerequisite at ${project(\n mkOpinion(\n dependencyOpinion.b,\n dependencyOpinion.d,\n dependencyOpinion.u,\n dependencyOpinion.a\n )\n ).toFixed(2)}`,\n };\n}\n","import type { EdgeMetadata, Opinion, PropagationResult } from \"../../types\";\nimport {\n constraintFusion,\n cumulativeFusion,\n mkOpinion,\n negate,\n project,\n trustDiscount,\n} from \"../subjectiveLogic\";\n\nexport function applyNegativeSupport(\n source: Opinion,\n target: Opinion,\n weight: number,\n metadata: EdgeMetadata = {}\n): PropagationResult {\n const sourceOpinion = mkOpinion(source.b, source.d, source.u, source.a);\n const targetOpinion = mkOpinion(target.b, target.d, target.u, target.a);\n if (metadata.constraint === \"xor\") {\n const result = constraintFusion(\n sourceOpinion,\n targetOpinion,\n metadata.normalization ?? \"pressure\"\n );\n return {\n opinion: result.o2,\n operator: \"constraint_fusion\",\n rationale: `XOR constraint: source belief at ${project(\n sourceOpinion\n ).toFixed(2)} pressures target`,\n };\n }\n\n const discounted = trustDiscount(negate(sourceOpinion), Math.abs(weight));\n return {\n opinion: cumulativeFusion(targetOpinion, discounted),\n operator: \"cumulative_fusion\",\n rationale: `Contradicting evidence (weight=${weight.toFixed(\n 2\n )}) from source at ${project(sourceOpinion).toFixed(2)}`,\n };\n}\n\nexport function applyNegativeEvidence(\n source: Opinion,\n target: Opinion,\n weight: number\n): PropagationResult {\n const sourceOpinion = mkOpinion(source.b, source.d, source.u, source.a);\n const targetOpinion = mkOpinion(target.b, target.d, target.u, target.a);\n const discounted = trustDiscount(negate(sourceOpinion), Math.abs(weight));\n return {\n opinion: cumulativeFusion(targetOpinion, discounted),\n operator: \"cumulative_fusion\",\n rationale: `Contradicting evidence (weight=${weight.toFixed(2)})`,\n };\n}\n","import type {\n EdgeMetadata,\n Opinion,\n PropagationResult,\n SLOperator,\n} from \"../../types\";\nimport {\n conditionalDeduction,\n cumulativeFusion,\n mkOpinion,\n project,\n trustDiscount,\n} from \"../subjectiveLogic\";\nimport { dampedDependencyCascade } from \"./cascade\";\nimport { applyNegativeEvidence, applyNegativeSupport } from \"./defeat\";\n\ntype EdgeHandler = (\n source: Opinion,\n target: Opinion,\n weight: number,\n metadata: EdgeMetadata\n) => PropagationResult;\n\nexport type PropagationTraversalDirection = \"outgoing\" | \"incoming\";\n\ninterface EdgePropagationRule {\n direction: PropagationTraversalDirection;\n handler: EdgeHandler;\n}\n\nconst EDGE_PROPAGATION_RULES = {\n supports: {\n direction: \"outgoing\",\n handler: (source, target, weight, metadata) => {\n const sourceOpinion = mkOpinion(source.b, source.d, source.u, source.a);\n const targetOpinion = mkOpinion(target.b, target.d, target.u, target.a);\n if (weight < 0) {\n return applyNegativeSupport(\n sourceOpinion,\n targetOpinion,\n weight,\n metadata\n );\n }\n\n const discounted = trustDiscount(sourceOpinion, weight);\n return {\n opinion: cumulativeFusion(targetOpinion, discounted),\n operator: \"cumulative_fusion\",\n rationale: `Supporting evidence (weight=${weight.toFixed(\n 2\n )}) from source at ${project(sourceOpinion).toFixed(2)}`,\n };\n },\n },\n informs: {\n direction: \"outgoing\",\n handler: (source, target, weight) => {\n const sourceOpinion = mkOpinion(source.b, source.d, source.u, source.a);\n const targetOpinion = mkOpinion(target.b, target.d, target.u, target.a);\n if (weight < 0) {\n return applyNegativeEvidence(sourceOpinion, targetOpinion, weight);\n }\n\n const discounted = trustDiscount(sourceOpinion, Math.abs(weight));\n return {\n opinion: cumulativeFusion(targetOpinion, discounted),\n operator: \"cumulative_fusion\",\n rationale: `Supporting evidence (weight=${weight.toFixed(2)})`,\n };\n },\n },\n depends_on: {\n direction: \"incoming\",\n handler: (source, target, _weight, metadata) => {\n const sourceOpinion = mkOpinion(source.b, source.d, source.u, source.a);\n const targetOpinion = mkOpinion(target.b, target.d, target.u, target.a);\n if (metadata.conditionalA && metadata.conditionalNotA) {\n return {\n opinion: conditionalDeduction(\n sourceOpinion,\n mkOpinion(\n metadata.conditionalA.b,\n metadata.conditionalA.d,\n metadata.conditionalA.u,\n metadata.conditionalA.a\n ),\n mkOpinion(\n metadata.conditionalNotA.b,\n metadata.conditionalNotA.d,\n metadata.conditionalNotA.u,\n metadata.conditionalNotA.a\n ),\n targetOpinion.a\n ),\n operator: \"conditional_deduction\",\n rationale: `Conditional deduction: prerequisite at ${project(\n sourceOpinion\n ).toFixed(2)}`,\n };\n }\n\n return dampedDependencyCascade(\n sourceOpinion,\n targetOpinion,\n metadata.propagation ?? \"continuous\"\n );\n },\n },\n derived_from: {\n direction: \"incoming\",\n handler: (_source, target) => ({\n opinion: target,\n operator: \"trust_discount\",\n rationale: \"Provenance edge — no confidence propagation\",\n }),\n },\n contains: {\n direction: \"outgoing\",\n handler: (_source, target) => ({\n opinion: target,\n operator: \"trust_discount\",\n rationale: \"Containment edge — no confidence propagation\",\n }),\n },\n tests: {\n direction: \"outgoing\",\n handler: (_source, target) => ({\n opinion: target,\n operator: \"trust_discount\",\n rationale: \"Testing edge — no confidence propagation\",\n }),\n },\n} satisfies Record<string, EdgePropagationRule>;\n\nexport type PropagationEdgeType = keyof typeof EDGE_PROPAGATION_RULES;\n\nexport interface PropagationTraversalSpec {\n direction: PropagationTraversalDirection;\n edgeType: PropagationEdgeType;\n}\n\nexport const PROPAGATION_TRAVERSAL_SPECS: readonly PropagationTraversalSpec[] =\n Object.entries(EDGE_PROPAGATION_RULES).map(([edgeType, rule]) => ({\n edgeType: edgeType as PropagationEdgeType,\n direction: rule.direction,\n }));\n\nexport function isPropagationEdgeType(\n edgeType: string\n): edgeType is PropagationEdgeType {\n return edgeType in EDGE_PROPAGATION_RULES;\n}\n\nexport function getPropagationTraversalSpecs(): readonly PropagationTraversalSpec[] {\n return PROPAGATION_TRAVERSAL_SPECS;\n}\n\nexport function propagateThroughEdge(\n sourceOpinion: Opinion,\n targetOpinion: Opinion,\n edgeType: string,\n weight = 1,\n metadata: EdgeMetadata = {}\n): PropagationResult {\n const handler = isPropagationEdgeType(edgeType)\n ? EDGE_PROPAGATION_RULES[edgeType].handler\n : undefined;\n if (!handler) {\n return {\n opinion: targetOpinion,\n operator: \"no_op\",\n rationale: `Unknown edge type: ${edgeType} — no propagation`,\n };\n }\n return handler(sourceOpinion, targetOpinion, weight, metadata);\n}\n\nexport function propagateAllEdges(\n currentOpinion: Opinion,\n incomingEdges: Array<{\n sourceOpinion: Opinion;\n edgeType: string;\n weight: number;\n metadata: EdgeMetadata;\n }>\n): PropagationResult {\n let result = currentOpinion;\n const rationales: string[] = [];\n\n for (const edgeType of [\"depends_on\", \"informs\", \"supports\"]) {\n for (const incoming of incomingEdges.filter(\n (edge) => edge.edgeType === edgeType\n )) {\n const propagated = propagateThroughEdge(\n incoming.sourceOpinion,\n result,\n incoming.edgeType,\n incoming.weight,\n incoming.metadata\n );\n result = propagated.opinion;\n rationales.push(propagated.rationale);\n }\n }\n\n return {\n opinion: result,\n operator: \"cumulative_fusion\" as SLOperator,\n rationale: rationales.join(\"; \"),\n };\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../src/v1/operations/subjectiveLogic/index.ts","../../../../src/v1/operations/bridge/index.ts","../../../../src/v1/operations/dynamics/revision.ts"],"names":["clamp01"],"mappings":"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","file":"revision.js","sourcesContent":["import type { SLOpinion } from \"../../types\";\n\nexport function opinion(\n belief: number,\n disbelief: number,\n uncertainty: number,\n baseRate: number\n): SLOpinion {\n const b = Number.isFinite(belief) ? Math.max(0, belief) : 0;\n const d = Number.isFinite(disbelief) ? Math.max(0, disbelief) : 0;\n const u = Number.isFinite(uncertainty) ? Math.max(0, uncertainty) : 0;\n const a = Math.max(0, Math.min(1, baseRate));\n const sum = b + d + u;\n\n if (sum === 0) {\n return { b: 0, d: 0, u: 1, a } as SLOpinion;\n }\n\n return {\n b: b / sum,\n d: d / sum,\n u: u / sum,\n a,\n } as SLOpinion;\n}\n\nexport function mkOpinion(\n belief: number,\n disbelief: number,\n uncertainty: number,\n baseRate: number\n): SLOpinion {\n return opinion(belief, disbelief, uncertainty, baseRate);\n}\n\nexport function vacuous(baseRate: number): SLOpinion {\n return mkOpinion(0, 0, 1, baseRate);\n}\n\nexport function dogmatic(probability: number, baseRate: number): SLOpinion {\n const p = Math.max(0, Math.min(1, probability));\n return mkOpinion(p, 1 - p, 0, baseRate);\n}\n\nexport function project(o: SLOpinion): number {\n return o.b + o.a * o.u;\n}\n\nexport function confidenceLevel(o: SLOpinion): \"high\" | \"medium\" | \"low\" {\n const projected = project(o);\n if (o.u > 0.5) {\n return \"low\";\n }\n if (projected >= 0.8 && o.u < 0.2) {\n return \"high\";\n }\n if (projected >= 0.6) {\n return \"medium\";\n }\n return \"low\";\n}\n\nconst VACUOUS_IDENTITY_EPSILON = 1e-12;\n\n/**\n * Associative, vacuous-identity-preserving base rate for a fused opinion.\n *\n * The legacy `(left.a + right.a) / 2` arithmetic mean was the shared root of\n * RR.7 F1 (projected-confidence non-associativity) and F2 (a vacuous opinion of\n * a different base rate was not a fusion identity): averaging always pulled the\n * fused base rate toward the other operand even when that operand carried no\n * evidence. Subjective Logic requires every opinion over the same frame to share\n * one canonical base rate, so a correct fusion never *invents* a new base rate\n * from the operands' priors. We therefore:\n *\n * - return the informative operand's base rate when exactly one operand is\n * vacuous (the vacuous operand contributes no prior), making `vacuous(a)` a\n * true identity for any `a`; and\n * - require equal base rates otherwise (the canonical-frame contract). When\n * they coincide the result is that shared value — trivially associative.\n *\n * If two informative opinions carry genuinely different base rates they are not\n * opinions over the same frame and must be reconciled before fusion; we fall\n * back to the arithmetic mean ONLY in that ill-posed case to stay total, and the\n * property suite documents that this path is outside the order-independence\n * guarantee.\n */\nfunction fusedBaseRate(left: SLOpinion, right: SLOpinion): number {\n const leftVacuous = 1 - left.u <= VACUOUS_IDENTITY_EPSILON;\n const rightVacuous = 1 - right.u <= VACUOUS_IDENTITY_EPSILON;\n if (leftVacuous && !rightVacuous) {\n return right.a;\n }\n if (rightVacuous && !leftVacuous) {\n return left.a;\n }\n if (Math.abs(left.a - right.a) <= VACUOUS_IDENTITY_EPSILON) {\n return left.a;\n }\n return (left.a + right.a) / 2;\n}\n\nexport function cumulativeFusion(left: SLOpinion, right: SLOpinion): SLOpinion {\n const a = fusedBaseRate(left, right);\n\n // F2: a vacuous operand is the identity element of cumulative fusion. Return\n // the other operand verbatim (including its base rate) so fusion with the\n // vacuous opinion is a true no-op regardless of differing priors.\n if (1 - left.u <= VACUOUS_IDENTITY_EPSILON) {\n return opinion(right.b, right.d, right.u, a);\n }\n if (1 - right.u <= VACUOUS_IDENTITY_EPSILON) {\n return opinion(left.b, left.d, left.u, a);\n }\n\n // F4: dogmatic pair handled via the ε-limit of the cumulative rule rather than\n // the standalone `(b+d)/2` shortcut. As both uncertainties shrink at the same\n // rate, the cumulative formula's `(b_L·u_R + b_R·u_L)/k` term converges to the\n // arithmetic mean of the masses; deriving it from the same limit the interior\n // formula uses keeps mass-associativity intact (no special-case discontinuity).\n if (\n left.u <= VACUOUS_IDENTITY_EPSILON &&\n right.u <= VACUOUS_IDENTITY_EPSILON\n ) {\n return opinion((left.b + right.b) / 2, (left.d + right.d) / 2, 0, a);\n }\n\n const k = left.u + right.u - left.u * right.u;\n if (k === 0) {\n return vacuous(a);\n }\n\n return opinion(\n (left.b * right.u + right.b * left.u) / k,\n (left.d * right.u + right.d * left.u) / k,\n (left.u * right.u) / k,\n a\n );\n}\n\nexport function averagingFusion(left: SLOpinion, right: SLOpinion): SLOpinion {\n const a = fusedBaseRate(left, right);\n\n // F2: vacuous identity, mirroring cumulativeFusion.\n if (1 - left.u <= VACUOUS_IDENTITY_EPSILON) {\n return opinion(right.b, right.d, right.u, a);\n }\n if (1 - right.u <= VACUOUS_IDENTITY_EPSILON) {\n return opinion(left.b, left.d, left.u, a);\n }\n\n // F4: dogmatic pair via the ε-limit of the averaging rule.\n if (\n left.u <= VACUOUS_IDENTITY_EPSILON &&\n right.u <= VACUOUS_IDENTITY_EPSILON\n ) {\n return opinion((left.b + right.b) / 2, (left.d + right.d) / 2, 0, a);\n }\n\n const k = left.u + right.u;\n if (k === 0) {\n return vacuous(a);\n }\n\n return opinion(\n (left.b * right.u + right.b * left.u) / k,\n (left.d * right.u + right.d * left.u) / k,\n (2 * left.u * right.u) / k,\n a\n );\n}\n\nexport function trustDiscount(\n sourceOpinion: SLOpinion,\n trust: number\n): SLOpinion {\n const weight = Math.max(0, Math.min(1, Math.abs(trust)));\n return opinion(\n weight * sourceOpinion.b,\n weight * sourceOpinion.d,\n 1 - weight * (sourceOpinion.b + sourceOpinion.d),\n sourceOpinion.a\n );\n}\n\nconst EPSILON = 1e-9;\n\nfunction childBaseRateFallback(\n ifTrue: SLOpinion,\n ifFalse: SLOpinion,\n fallbackBaseRate: number | undefined\n): number {\n if (fallbackBaseRate !== undefined) {\n return Math.max(0, Math.min(1, fallbackBaseRate));\n }\n\n if (Math.abs(ifTrue.a - ifFalse.a) <= EPSILON) {\n return ifTrue.a;\n }\n\n return (ifTrue.a + ifFalse.a) / 2;\n}\n\nfunction computeConditionalDeductionBaseRate(\n opinionA: SLOpinion,\n ifTrue: SLOpinion,\n ifFalse: SLOpinion,\n fallbackBaseRate: number\n): number {\n const denominator = 1 - opinionA.a * ifTrue.u - (1 - opinionA.a) * ifFalse.u;\n\n if (ifTrue.u + ifFalse.u < 2 - EPSILON && Math.abs(denominator) > EPSILON) {\n const baseRate =\n (opinionA.a * ifTrue.b + (1 - opinionA.a) * ifFalse.b) / denominator;\n if (baseRate >= -EPSILON && baseRate <= 1 + EPSILON) {\n return Math.max(0, Math.min(1, baseRate));\n }\n }\n\n return fallbackBaseRate;\n}\n\nfunction safeCorrectionTerm(\n numerator: number,\n denominator: number\n): number | undefined {\n if (Math.abs(denominator) <= EPSILON) {\n return;\n }\n\n const value = numerator / denominator;\n if (!Number.isFinite(value)) {\n return;\n }\n\n return Math.max(0, value);\n}\n\ninterface ConditionalDeductionCorrectionContext {\n childBaseRate: number;\n ifFalse: SLOpinion;\n ifTrue: SLOpinion;\n intermediateBelief: number;\n intermediateDisbelief: number;\n opinionA: SLOpinion;\n projectedAntecedent: number;\n projectedAntecedentComplement: number;\n projectedConditionalA: number;\n projectedVacuousDeduction: number;\n}\n\nfunction correctionOrZero(numerator: number, denominator: number): number {\n return safeCorrectionTerm(numerator, denominator) ?? 0;\n}\n\nfunction hasNoConditionalDeductionCorrection(\n ifTrue: SLOpinion,\n ifFalse: SLOpinion\n): boolean {\n return (\n (ifTrue.b > ifFalse.b && ifTrue.d > ifFalse.d) ||\n (ifTrue.b <= ifFalse.b && ifTrue.d <= ifFalse.d)\n );\n}\n\nfunction usesLowerVacuousBranch(\n context: ConditionalDeductionCorrectionContext\n): boolean {\n return context.projectedVacuousDeduction <= context.projectedConditionalA;\n}\n\nfunction usesLowerAntecedentBranch(\n context: ConditionalDeductionCorrectionContext\n): boolean {\n return context.projectedAntecedent <= context.opinionA.a;\n}\n\nfunction computeTrueDominantDeductionCorrection(\n context: ConditionalDeductionCorrectionContext\n): number {\n const beliefGap = context.ifTrue.b - context.ifFalse.b;\n const disbeliefGap = context.ifFalse.d - context.ifTrue.d;\n const lowerVacuous = usesLowerVacuousBranch(context);\n const lowerAntecedent = usesLowerAntecedentBranch(context);\n\n if (lowerVacuous && lowerAntecedent) {\n return correctionOrZero(\n context.opinionA.a *\n context.opinionA.u *\n (context.intermediateBelief - context.ifTrue.b),\n context.projectedAntecedent * context.childBaseRate\n );\n }\n\n if (lowerVacuous) {\n return correctionOrZero(\n context.opinionA.a *\n context.opinionA.u *\n (context.intermediateDisbelief - context.ifTrue.d) *\n beliefGap,\n context.projectedAntecedentComplement *\n context.childBaseRate *\n disbeliefGap\n );\n }\n\n if (lowerAntecedent) {\n return correctionOrZero(\n (1 - context.opinionA.a) *\n context.opinionA.u *\n (context.intermediateBelief - context.ifTrue.b) *\n disbeliefGap,\n context.projectedAntecedent * (1 - context.childBaseRate) * beliefGap\n );\n }\n\n return correctionOrZero(\n (1 - context.opinionA.a) *\n context.opinionA.u *\n (context.intermediateDisbelief - context.ifTrue.d),\n context.projectedAntecedentComplement * (1 - context.childBaseRate)\n );\n}\n\nfunction computeFalseDominantDeductionCorrection(\n context: ConditionalDeductionCorrectionContext\n): number {\n const beliefGap = context.ifFalse.b - context.ifTrue.b;\n const disbeliefGap = context.ifTrue.d - context.ifFalse.d;\n const lowerVacuous = usesLowerVacuousBranch(context);\n const lowerAntecedent = usesLowerAntecedentBranch(context);\n\n if (lowerVacuous && lowerAntecedent) {\n return correctionOrZero(\n (1 - context.opinionA.a) *\n context.opinionA.u *\n (context.intermediateDisbelief - context.ifTrue.d) *\n beliefGap,\n context.projectedAntecedent * context.childBaseRate * disbeliefGap\n );\n }\n\n if (lowerVacuous) {\n return correctionOrZero(\n (1 - context.opinionA.a) *\n context.opinionA.u *\n (context.intermediateBelief - context.ifTrue.b),\n context.projectedAntecedentComplement * context.childBaseRate\n );\n }\n\n if (lowerAntecedent) {\n return correctionOrZero(\n context.opinionA.a *\n context.opinionA.u *\n (context.intermediateDisbelief - context.ifTrue.d),\n context.projectedAntecedent * (1 - context.childBaseRate)\n );\n }\n\n return correctionOrZero(\n context.opinionA.a *\n context.opinionA.u *\n (context.intermediateBelief - context.ifTrue.b) *\n disbeliefGap,\n context.projectedAntecedentComplement *\n (1 - context.childBaseRate) *\n beliefGap\n );\n}\n\nfunction computeConditionalDeductionCorrection(\n context: ConditionalDeductionCorrectionContext\n): number {\n if (hasNoConditionalDeductionCorrection(context.ifTrue, context.ifFalse)) {\n return 0;\n }\n\n if (\n context.ifTrue.b > context.ifFalse.b &&\n context.ifTrue.d <= context.ifFalse.d\n ) {\n return computeTrueDominantDeductionCorrection(context);\n }\n\n return computeFalseDominantDeductionCorrection(context);\n}\n\nexport function conditionalDeduction(\n opinionA: SLOpinion,\n ifTrue: SLOpinion,\n ifFalse: SLOpinion,\n fallbackBaseRate?: number\n): SLOpinion {\n const fallbackChildBaseRate = childBaseRateFallback(\n ifTrue,\n ifFalse,\n fallbackBaseRate\n );\n const childBaseRate = computeConditionalDeductionBaseRate(\n opinionA,\n ifTrue,\n ifFalse,\n fallbackChildBaseRate\n );\n const projectedAntecedent = project(opinionA);\n const projectedAntecedentComplement = 1 - projectedAntecedent;\n const intermediateBelief =\n opinionA.b * ifTrue.b +\n opinionA.d * ifFalse.b +\n opinionA.u * (ifTrue.b * opinionA.a + ifFalse.b * (1 - opinionA.a));\n const intermediateDisbelief =\n opinionA.b * ifTrue.d +\n opinionA.d * ifFalse.d +\n opinionA.u * (ifTrue.d * opinionA.a + ifFalse.d * (1 - opinionA.a));\n const intermediateUncertainty =\n opinionA.b * ifTrue.u +\n opinionA.d * ifFalse.u +\n opinionA.u * (ifTrue.u * opinionA.a + ifFalse.u * (1 - opinionA.a));\n const projectedVacuousDeduction =\n ifTrue.b * opinionA.a +\n ifFalse.b * (1 - opinionA.a) +\n childBaseRate * (ifTrue.u * opinionA.a + ifFalse.u * (1 - opinionA.a));\n const projectedConditionalA =\n ifTrue.b + childBaseRate * (1 - ifTrue.b - ifTrue.d);\n const correction = computeConditionalDeductionCorrection({\n childBaseRate,\n ifFalse,\n ifTrue,\n intermediateBelief,\n intermediateDisbelief,\n opinionA,\n projectedAntecedent,\n projectedAntecedentComplement,\n projectedConditionalA,\n projectedVacuousDeduction,\n });\n\n return opinion(\n intermediateBelief - childBaseRate * correction,\n intermediateDisbelief - (1 - childBaseRate) * correction,\n intermediateUncertainty + correction,\n childBaseRate\n );\n}\n\n/**\n * Abductive inference over a conditional.\n * Given an opinion on Y and conditionals P(Y|X), P(Y|~X), infer an opinion on X.\n */\nexport function conditionalAbduction(\n opinionY: SLOpinion,\n ifTrue: SLOpinion,\n ifFalse: SLOpinion,\n baseRateX: number\n): SLOpinion {\n const priorX = Math.max(0, Math.min(1, baseRateX));\n const probabilityY = project(opinionY);\n const probabilityGivenTrue = project(ifTrue);\n const probabilityGivenFalse = project(ifFalse);\n\n const posteriorIfYDenominator =\n probabilityGivenTrue * priorX + probabilityGivenFalse * (1 - priorX);\n const posteriorIfY =\n posteriorIfYDenominator === 0\n ? priorX\n : (probabilityGivenTrue * priorX) / posteriorIfYDenominator;\n\n const posteriorIfNotYDenominator =\n (1 - probabilityGivenTrue) * priorX +\n (1 - probabilityGivenFalse) * (1 - priorX);\n const posteriorIfNotY =\n posteriorIfNotYDenominator === 0\n ? priorX\n : ((1 - probabilityGivenTrue) * priorX) / posteriorIfNotYDenominator;\n\n const projectedX =\n probabilityY * posteriorIfY + (1 - probabilityY) * posteriorIfNotY;\n const uncertainty = Math.max(\n opinionY.u * 0.5,\n probabilityY * ifTrue.u + (1 - probabilityY) * ifFalse.u\n );\n\n return opinion(\n projectedX * (1 - uncertainty),\n (1 - projectedX) * (1 - uncertainty),\n uncertainty,\n priorX\n );\n}\n\nexport function negate(o: SLOpinion): SLOpinion {\n return mkOpinion(o.d, o.b, o.u, 1 - o.a);\n}\n\nexport function constraintFusion(\n left: SLOpinion,\n right: SLOpinion,\n mode: \"pressure\" | \"redistribute\" = \"pressure\"\n): { o1: SLOpinion; o2: SLOpinion } {\n if (mode === \"redistribute\") {\n const leftProjected = project(left);\n const rightProjected = project(right);\n const total = leftProjected + rightProjected;\n\n if (total <= 1) {\n return { o1: left, o2: right };\n }\n\n const scale = 1 / total;\n return {\n o1: opinion(\n left.b * scale,\n left.d + left.b * (1 - scale),\n left.u,\n left.a\n ),\n o2: opinion(\n right.b * scale,\n right.d + right.b * (1 - scale),\n right.u,\n right.a\n ),\n };\n }\n\n const pressureLeft = right.b * 0.5;\n const pressureRight = left.b * 0.5;\n\n return {\n o1: opinion(\n left.b - pressureLeft * 0.3,\n left.d + pressureLeft * 0.3,\n left.u,\n left.a\n ),\n o2: opinion(\n right.b - pressureRight * 0.3,\n right.d + pressureRight * 0.3,\n right.u,\n right.a\n ),\n };\n}\n\nexport function evidenceBalance(o: SLOpinion): number {\n const total = o.b + o.d;\n if (total === 0) {\n return 0;\n }\n return (o.b - o.d) / total;\n}\n\nexport function areTensioned(left: SLOpinion, right: SLOpinion): boolean {\n return (\n project(left) > 0.5 &&\n project(right) > 0.5 &&\n (left.d > 0.2 || right.d > 0.2)\n );\n}\n\nexport function informationGain(o: SLOpinion): number {\n if (o.u === 0) {\n return 0;\n }\n if (o.u === 1) {\n return 1;\n }\n return o.u * (1 - Math.abs(o.b - o.d));\n}\n","import type { DirichletOpinion, Opinion, SLOpinion } from \"../../types\";\nimport { mkOpinion } from \"../subjectiveLogic\";\n\nexport const DEFAULT_NON_INFORMATIVE_WEIGHT = 2;\n\nfunction clamp01(value: number): number {\n return Math.max(0, Math.min(1, value));\n}\n\nfunction clampNonNegative(value: number): number {\n return Number.isFinite(value) ? Math.max(0, value) : 0;\n}\n\nfunction normalizeNonInformativeWeight(weight?: number): number {\n if (weight === undefined) {\n return DEFAULT_NON_INFORMATIVE_WEIGHT;\n }\n return Number.isFinite(weight)\n ? Math.max(0, weight)\n : DEFAULT_NON_INFORMATIVE_WEIGHT;\n}\n\nfunction normalizeBaseRateVector(\n baseRate: readonly number[],\n size: number\n): number[] {\n if (size === 0) {\n return [];\n }\n\n if (baseRate.length !== size) {\n throw new Error(\n `Base-rate vector length ${baseRate.length} must match evidence vector length ${size}.`\n );\n }\n\n const normalized = baseRate.map((value) => clampNonNegative(value));\n const total = normalized.reduce((sum, value) => sum + value, 0);\n\n if (total === 0) {\n throw new Error(\n \"Base-rate vector must contain at least one positive value.\"\n );\n }\n\n return normalized.map((value) => value / total);\n}\n\nexport function opinionFromDirichlet(\n alpha: readonly number[],\n nonInformativeWeight: number,\n baseRate: readonly number[]\n): DirichletOpinion {\n const evidence = alpha.map((value) => clampNonNegative(value));\n const safeWeight = normalizeNonInformativeWeight(nonInformativeWeight);\n const normalizedBaseRate = normalizeBaseRateVector(baseRate, evidence.length);\n const totalEvidence = evidence.reduce((sum, value) => sum + value, 0);\n const denominator = totalEvidence + safeWeight;\n\n if (denominator === 0) {\n return {\n b: evidence.map(() => 0),\n u: 1,\n a: normalizedBaseRate,\n };\n }\n\n return {\n b: evidence.map((value) => value / denominator),\n u: safeWeight / denominator,\n a: normalizedBaseRate,\n };\n}\n\nexport function projectDirichletOpinion(opinion: DirichletOpinion): number[] {\n return opinion.b.map(\n (belief, index) => belief + (opinion.a[index] ?? 0) * opinion.u\n );\n}\n\nexport function opinionFromBeta(\n alpha: number,\n beta: number,\n nonInformativeWeight: number,\n baseRate: number\n): SLOpinion {\n const dirichlet = opinionFromDirichlet([alpha, beta], nonInformativeWeight, [\n clamp01(baseRate),\n 1 - clamp01(baseRate),\n ]);\n\n return mkOpinion(\n dirichlet.b[0] ?? 0,\n dirichlet.b[1] ?? 0,\n dirichlet.u,\n dirichlet.a[0] ?? clamp01(baseRate)\n );\n}\n\nexport function betaFromOpinion(\n opinion: Opinion,\n nonInformativeWeight: number = DEFAULT_NON_INFORMATIVE_WEIGHT\n): { alpha: number; beta: number } {\n if (opinion.u === 0) {\n return {\n alpha: Number.POSITIVE_INFINITY,\n beta: Number.POSITIVE_INFINITY,\n };\n }\n\n const safeWeight = normalizeNonInformativeWeight(nonInformativeWeight);\n const scale = safeWeight / opinion.u;\n\n return {\n alpha: opinion.b * scale,\n beta: opinion.d * scale,\n };\n}\n","import type { SLOpinion } from \"../../types\";\nimport { DEFAULT_NON_INFORMATIVE_WEIGHT, opinionFromBeta } from \"../bridge\";\nimport { project } from \"../subjectiveLogic\";\n\nfunction clamp01(value: number): number {\n return Math.max(0, Math.min(1, value));\n}\n\nfunction toEvidence(\n probability: number,\n weight: number\n): {\n alpha: number;\n beta: number;\n} {\n const safeProbability = clamp01(probability);\n const safeWeight = Number.isFinite(weight) ? Math.max(0, weight) : 0;\n\n return {\n alpha: safeProbability * safeWeight,\n beta: (1 - safeProbability) * safeWeight,\n };\n}\n\nexport function bayesianUpdate(\n priorConfidence: number,\n priorWeight: number,\n newAssessment: number,\n newWeight: number,\n options: {\n baseRate: number;\n nonInformativeWeight?: number;\n }\n): number {\n return reviseConfidence({\n priorConfidence,\n priorWeight,\n newAssessment,\n newWeight,\n baseRate: options?.baseRate,\n nonInformativeWeight: options?.nonInformativeWeight,\n });\n}\n\nexport function reviseConfidence(args: {\n priorConfidence: number;\n priorWeight: number;\n newAssessment: number;\n newWeight?: number;\n baseRate: number;\n nonInformativeWeight?: number;\n}): number {\n return project(reviseConfidenceOpinion(args));\n}\n\nexport function reviseConfidenceOpinion(args: {\n priorConfidence: number;\n priorWeight: number;\n newAssessment: number;\n newWeight?: number;\n baseRate: number;\n nonInformativeWeight?: number;\n}): SLOpinion {\n const priorEvidence = toEvidence(args.priorConfidence, args.priorWeight);\n const newEvidence = toEvidence(args.newAssessment, args.newWeight ?? 1);\n\n return opinionFromBeta(\n priorEvidence.alpha + newEvidence.alpha,\n priorEvidence.beta + newEvidence.beta,\n args.nonInformativeWeight ?? DEFAULT_NON_INFORMATIVE_WEIGHT,\n args.baseRate\n );\n}\n"]}