@lucern/graph-primitives 0.3.0-alpha.0 → 0.3.0-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/dist/{beliefDecay-Q_26RTc-.d.ts → beliefDecay-DZ6tkLYq.d.ts} +1 -1
  2. package/dist/beliefDecay.d.ts +1 -1
  3. package/dist/beliefDecay.js +188 -1144
  4. package/dist/beliefDecay.js.map +1 -1
  5. package/dist/{beliefEvidenceLinks-42FlR48t.d.ts → beliefEvidenceLinks-CWOXxxJg.d.ts} +1 -1
  6. package/dist/beliefEvidenceLinks.d.ts +1 -1
  7. package/dist/beliefEvidenceLinks.js +186 -871
  8. package/dist/beliefEvidenceLinks.js.map +1 -1
  9. package/dist/{beliefLifecycle-C-AehZgF.d.ts → beliefLifecycle-y8WLXqQj.d.ts} +1 -1
  10. package/dist/beliefLifecycle.d.ts +1 -1
  11. package/dist/confidencePropagationDispatch.d.ts +4 -4
  12. package/dist/confidencePropagationDispatch.js +31 -311
  13. package/dist/confidencePropagationDispatch.js.map +1 -1
  14. package/dist/{contradictions-Hdwl7zid.d.ts → contradictions-51VLsESq.d.ts} +1 -1
  15. package/dist/contradictions.d.ts +1 -1
  16. package/dist/contradictions.js +67 -800
  17. package/dist/contradictions.js.map +1 -1
  18. package/dist/debug.d.ts +4 -0
  19. package/dist/debug.js +34 -0
  20. package/dist/debug.js.map +1 -0
  21. package/dist/edges/contradicts.js +1 -122
  22. package/dist/edges/contradicts.js.map +1 -1
  23. package/dist/edges/dependsOn.js +14 -172
  24. package/dist/edges/dependsOn.js.map +1 -1
  25. package/dist/edges/elaborates.js +1 -49
  26. package/dist/edges/elaborates.js.map +1 -1
  27. package/dist/edges/index.js +15 -280
  28. package/dist/edges/index.js.map +1 -1
  29. package/dist/edges/informs.js +2 -65
  30. package/dist/edges/informs.js.map +1 -1
  31. package/dist/edges/propagationTypes.d.ts +2 -2
  32. package/dist/edges/propagationTypes.js.map +1 -1
  33. package/dist/edges/refutes.js +2 -65
  34. package/dist/edges/refutes.js.map +1 -1
  35. package/dist/edges/supports.js +1 -122
  36. package/dist/edges/supports.js.map +1 -1
  37. package/dist/edges/utils.d.ts +7 -7
  38. package/dist/edges/utils.js +2 -133
  39. package/dist/edges/utils.js.map +1 -1
  40. package/dist/embeddingTrigger.js +21 -1
  41. package/dist/embeddingTrigger.js.map +1 -1
  42. package/dist/entityBridge.js +3 -18
  43. package/dist/entityBridge.js.map +1 -1
  44. package/dist/{entityLifecycle-BkhRJ-XI.d.ts → entityLifecycle-CvgSK5FV.d.ts} +1 -1
  45. package/dist/entityLifecycle.d.ts +1 -1
  46. package/dist/entityLifecycle.js +193 -892
  47. package/dist/entityLifecycle.js.map +1 -1
  48. package/dist/{epistemicAnswers-DSP1slZ9.d.ts → epistemicAnswers-C5ib4z6_.d.ts} +1 -1
  49. package/dist/epistemicAnswers.d.ts +1 -1
  50. package/dist/epistemicAnswers.js +73 -810
  51. package/dist/epistemicAnswers.js.map +1 -1
  52. package/dist/{epistemicBeliefs-DtFVTp-k.d.ts → epistemicBeliefs-DzKjZAeC.d.ts} +3 -3
  53. package/dist/epistemicBeliefs.d.ts +2 -2
  54. package/dist/epistemicBeliefs.js +404 -1698
  55. package/dist/epistemicBeliefs.js.map +1 -1
  56. package/dist/epistemicContractHelpers.js +1 -318
  57. package/dist/epistemicContractHelpers.js.map +1 -1
  58. package/dist/epistemicContracts.d.ts +1 -1
  59. package/dist/epistemicContracts.js +417 -1980
  60. package/dist/epistemicContracts.js.map +1 -1
  61. package/dist/{epistemicEdges-DcA8ErUG.d.ts → epistemicEdges-CD5vxmlH.d.ts} +3 -3
  62. package/dist/epistemicEdges.d.ts +1 -1
  63. package/dist/epistemicEdges.js +248 -919
  64. package/dist/epistemicEdges.js.map +1 -1
  65. package/dist/{epistemicEvidence-Bo638XDP.d.ts → epistemicEvidence-xw6UUrwh.d.ts} +1 -1
  66. package/dist/epistemicEvidence.d.ts +1 -1
  67. package/dist/epistemicEvidence.js +229 -1087
  68. package/dist/epistemicEvidence.js.map +1 -1
  69. package/dist/{epistemicHelpers-Bd9xbaib.d.ts → epistemicHelpers-DevrYgPN.d.ts} +1 -1
  70. package/dist/epistemicHelpers.d.ts +1 -1
  71. package/dist/{epistemicLinking-CyeLOIzN.d.ts → epistemicLinking-CfE00tHJ.d.ts} +1 -1
  72. package/dist/epistemicLinking.d.ts +1 -1
  73. package/dist/epistemicLinking.js +3 -786
  74. package/dist/epistemicLinking.js.map +1 -1
  75. package/dist/{epistemicNodes-BpD6Koud.d.ts → epistemicNodes-NBrPW7fk.d.ts} +2 -2
  76. package/dist/epistemicNodes.d.ts +1 -1
  77. package/dist/epistemicNodes.js +172 -899
  78. package/dist/epistemicNodes.js.map +1 -1
  79. package/dist/{epistemicQuestions-CmEeY6zQ.d.ts → epistemicQuestions-B_nUclrH.d.ts} +1 -1
  80. package/dist/epistemicQuestions.d.ts +1 -1
  81. package/dist/epistemicQuestions.js +369 -1125
  82. package/dist/epistemicQuestions.js.map +1 -1
  83. package/dist/{epistemicSources-ZazxHOK1.d.ts → epistemicSources-dlKj58Jp.d.ts} +1 -1
  84. package/dist/epistemicSources.d.ts +1 -1
  85. package/dist/epistemicSources.js +86 -886
  86. package/dist/epistemicSources.js.map +1 -1
  87. package/dist/evaluators/index.js +417 -1980
  88. package/dist/evaluators/index.js.map +1 -1
  89. package/dist/evaluators/lintCheckerEvaluator.js.map +1 -1
  90. package/dist/evaluators/sentryCheckerEvaluator.js.map +1 -1
  91. package/dist/evaluators/shared.js +20 -1
  92. package/dist/evaluators/shared.js.map +1 -1
  93. package/dist/evaluators/testRunnerEvaluator.js +20 -1
  94. package/dist/evaluators/testRunnerEvaluator.js.map +1 -1
  95. package/dist/evaluators/tscCheckerEvaluator.js.map +1 -1
  96. package/dist/index.d.ts +20 -20
  97. package/dist/index.js +965 -3004
  98. package/dist/index.js.map +1 -1
  99. package/dist/{ontology-matching-Buhu23ss.d.ts → ontology-matching-C6rrz2VP.d.ts} +1 -1
  100. package/dist/ontology-matching.d.ts +1 -1
  101. package/dist/ontology-matching.js +1 -344
  102. package/dist/ontology-matching.js.map +1 -1
  103. package/dist/{ontologyApproval-Ba0Jjk1k.d.ts → ontologyApproval-CFYmqKmk.d.ts} +1 -1
  104. package/dist/ontologyApproval.d.ts +1 -1
  105. package/dist/ontologyApproval.js +1 -13
  106. package/dist/ontologyApproval.js.map +1 -1
  107. package/dist/ontologyDefinitions.js +6 -20
  108. package/dist/ontologyDefinitions.js.map +1 -1
  109. package/dist/ontologyHelpers.d.ts +1 -1
  110. package/dist/ontologyHelpers.js +4 -3
  111. package/dist/ontologyHelpers.js.map +1 -1
  112. package/dist/ontologyRegistry.js +2 -17
  113. package/dist/ontologyRegistry.js.map +1 -1
  114. package/dist/{projectionReconciliation-CxrXYGaB.d.ts → projectionReconciliation-jww2fBI0.d.ts} +1 -1
  115. package/dist/projectionReconciliation.d.ts +1 -1
  116. package/dist/projectionReconciliation.js +16 -37
  117. package/dist/projectionReconciliation.js.map +1 -1
  118. package/dist/{projectionStaleness-CAdpIsaW.d.ts → projectionStaleness-CmdbpjVK.d.ts} +1 -1
  119. package/dist/projectionStaleness.d.ts +1 -1
  120. package/dist/{questionEvidenceLinks-BdQD0TkM.d.ts → questionEvidenceLinks-DFlyPpAj.d.ts} +1 -1
  121. package/dist/questionEvidenceLinks.d.ts +1 -1
  122. package/dist/questionEvidenceLinks.js +199 -881
  123. package/dist/questionEvidenceLinks.js.map +1 -1
  124. package/dist/resolvers.js +86 -37
  125. package/dist/resolvers.js.map +1 -1
  126. package/dist/scopeResolverCompat.js +64 -7
  127. package/dist/scopeResolverCompat.js.map +1 -1
  128. package/dist/{text-matching-CMn2WnVD.d.ts → text-matching-DNg4M5Wd.d.ts} +1 -1
  129. package/dist/text-matching.d.ts +1 -1
  130. package/dist/text-matching.js +1 -244
  131. package/dist/text-matching.js.map +1 -1
  132. package/dist/topicProjectOverlay.js +56 -13
  133. package/dist/topicProjectOverlay.js.map +1 -1
  134. package/dist/topicScope.js +55 -6
  135. package/dist/topicScope.js.map +1 -1
  136. package/dist/workflowBridge.d.ts +27 -0
  137. package/dist/workflowBridge.js +352 -0
  138. package/dist/workflowBridge.js.map +1 -0
  139. package/dist/workspaceIsolation.js +56 -57
  140. package/dist/workspaceIsolation.js.map +1 -1
  141. package/package.json +6 -5
@@ -1,1440 +1,16 @@
1
1
  import { v } from 'convex/values';
2
- import { componentsGeneric, internalMutationGeneric, mutationGeneric, anyApi, queryGeneric, internalQueryGeneric } from 'convex/server';
2
+ import { normalizeTupleContradictionPolicy, mkOpinion, createInheritedContractRecord, confidenceFromSL, conditionalDeduction, project, dampedDependencyCascade, hasProjectedOpinionChanged, detectTupleContradiction, evaluateTupleContradictionTransition, readOpinionFromRecord, trustDiscount, applyNegativeSupport, cumulativeFusion, applyNegativeEvidence } from '@lucern/confidence';
3
+ import { checkScopeAccess, checkProjectAccess } from '@lucern/access-control/access';
4
+ import { canAudienceClassAccess, normalizeAudienceKey, classFromAudienceKey } from '@lucern/access-control/audience';
5
+ import { listAudienceRegistryRows } from '@lucern/access-control/audienceRegistry';
6
+ import { getCurrentUserId } from '@lucern/access-control/auth';
7
+ import { assertSchemaEnumValue } from '@lucern/contracts/schema-helpers/enumValidation';
8
+ import { permissiveReturn } from '@lucern/contracts/schema-helpers/validators';
9
+ import { componentsGeneric, anyApi, internalMutationGeneric, mutationGeneric, queryGeneric, internalQueryGeneric } from 'convex/server';
10
+ import { isNodeType, getLayerForNodeType } from '@lucern/contracts/schema-helpers/spine/tables/epistemicNodes';
3
11
 
4
12
  // src/epistemicBeliefs.ts
5
13
 
6
- // ../confidence/src/v1/operations/subjectiveLogic/index.ts
7
- function opinion(belief, disbelief, uncertainty, baseRate = 0.5) {
8
- const b = Math.max(0, Math.min(1, belief));
9
- const d = Math.max(0, Math.min(1, disbelief));
10
- const u = Math.max(0, Math.min(1, uncertainty));
11
- const a = Math.max(0, Math.min(1, baseRate));
12
- const sum = b + d + u;
13
- if (sum === 0) {
14
- return { b: 0, d: 0, u: 1, a };
15
- }
16
- return {
17
- b: b / sum,
18
- d: d / sum,
19
- u: u / sum,
20
- a
21
- };
22
- }
23
- function vacuous(baseRate = 0.5) {
24
- return { b: 0, d: 0, u: 1, a: baseRate };
25
- }
26
- function project(o) {
27
- return o.b + o.a * o.u;
28
- }
29
- function cumulativeFusion(left, right) {
30
- if (left.u === 0 && right.u === 0) {
31
- return opinion(
32
- (left.b + right.b) / 2,
33
- (left.d + right.d) / 2,
34
- 0,
35
- (left.a + right.a) / 2
36
- );
37
- }
38
- const k = left.u + right.u - left.u * right.u;
39
- if (k === 0) {
40
- return vacuous((left.a + right.a) / 2);
41
- }
42
- return opinion(
43
- (left.b * right.u + right.b * left.u) / k,
44
- (left.d * right.u + right.d * left.u) / k,
45
- left.u * right.u / k,
46
- (left.a + right.a) / 2
47
- );
48
- }
49
- function trustDiscount(sourceOpinion, trust) {
50
- const weight = Math.max(0, Math.min(1, Math.abs(trust)));
51
- return opinion(
52
- weight * sourceOpinion.b,
53
- weight * sourceOpinion.d,
54
- 1 - weight * (sourceOpinion.b + sourceOpinion.d),
55
- sourceOpinion.a
56
- );
57
- }
58
- var EPSILON = 1e-9;
59
- function childBaseRateFallback(ifTrue, ifFalse, fallbackBaseRate) {
60
- if (fallbackBaseRate !== void 0) {
61
- return Math.max(0, Math.min(1, fallbackBaseRate));
62
- }
63
- if (Math.abs(ifTrue.a - ifFalse.a) <= EPSILON) {
64
- return ifTrue.a;
65
- }
66
- return (ifTrue.a + ifFalse.a) / 2;
67
- }
68
- function computeConditionalDeductionBaseRate(opinionA, ifTrue, ifFalse, fallbackBaseRate) {
69
- const denominator = 1 - opinionA.a * ifTrue.u - (1 - opinionA.a) * ifFalse.u;
70
- if (ifTrue.u + ifFalse.u < 2 - EPSILON && Math.abs(denominator) > EPSILON) {
71
- const baseRate = (opinionA.a * ifTrue.b + (1 - opinionA.a) * ifFalse.b) / denominator;
72
- if (baseRate >= -EPSILON && baseRate <= 1 + EPSILON) {
73
- return Math.max(0, Math.min(1, baseRate));
74
- }
75
- }
76
- return fallbackBaseRate;
77
- }
78
- function safeCorrectionTerm(numerator, denominator) {
79
- if (Math.abs(denominator) <= EPSILON) {
80
- return void 0;
81
- }
82
- const value = numerator / denominator;
83
- if (!Number.isFinite(value)) {
84
- return void 0;
85
- }
86
- return Math.max(0, value);
87
- }
88
- function conditionalDeduction(opinionA, ifTrue, ifFalse, fallbackBaseRate) {
89
- const fallbackChildBaseRate = childBaseRateFallback(
90
- ifTrue,
91
- ifFalse,
92
- fallbackBaseRate
93
- );
94
- const childBaseRate = computeConditionalDeductionBaseRate(
95
- opinionA,
96
- ifTrue,
97
- ifFalse,
98
- fallbackChildBaseRate
99
- );
100
- const projectedAntecedent = project(opinionA);
101
- const projectedAntecedentComplement = 1 - projectedAntecedent;
102
- const intermediateBelief = opinionA.b * ifTrue.b + opinionA.d * ifFalse.b + opinionA.u * (ifTrue.b * opinionA.a + ifFalse.b * (1 - opinionA.a));
103
- const intermediateDisbelief = opinionA.b * ifTrue.d + opinionA.d * ifFalse.d + opinionA.u * (ifTrue.d * opinionA.a + ifFalse.d * (1 - opinionA.a));
104
- const intermediateUncertainty = opinionA.b * ifTrue.u + opinionA.d * ifFalse.u + opinionA.u * (ifTrue.u * opinionA.a + ifFalse.u * (1 - opinionA.a));
105
- const projectedVacuousDeduction = ifTrue.b * opinionA.a + ifFalse.b * (1 - opinionA.a) + childBaseRate * (ifTrue.u * opinionA.a + ifFalse.u * (1 - opinionA.a));
106
- const projectedConditionalA = ifTrue.b + childBaseRate * (1 - ifTrue.b - ifTrue.d);
107
- let correction = 0;
108
- if (ifTrue.b > ifFalse.b && ifTrue.d > ifFalse.d || ifTrue.b <= ifFalse.b && ifTrue.d <= ifFalse.d) {
109
- correction = 0;
110
- } else if (ifTrue.b > ifFalse.b && ifTrue.d <= ifFalse.d) {
111
- const beliefGap = ifTrue.b - ifFalse.b;
112
- const disbeliefGap = ifFalse.d - ifTrue.d;
113
- if (projectedVacuousDeduction <= projectedConditionalA && projectedAntecedent <= opinionA.a) {
114
- correction = safeCorrectionTerm(
115
- opinionA.a * opinionA.u * (intermediateBelief - ifTrue.b),
116
- projectedAntecedent * childBaseRate
117
- ) ?? 0;
118
- } else if (projectedVacuousDeduction <= projectedConditionalA && projectedAntecedent > opinionA.a) {
119
- correction = safeCorrectionTerm(
120
- opinionA.a * opinionA.u * (intermediateDisbelief - ifTrue.d) * beliefGap,
121
- projectedAntecedentComplement * childBaseRate * disbeliefGap
122
- ) ?? 0;
123
- } else if (projectedVacuousDeduction > projectedConditionalA && projectedAntecedent <= opinionA.a) {
124
- correction = safeCorrectionTerm(
125
- (1 - opinionA.a) * opinionA.u * (intermediateBelief - ifTrue.b) * disbeliefGap,
126
- projectedAntecedent * (1 - childBaseRate) * beliefGap
127
- ) ?? 0;
128
- } else {
129
- correction = safeCorrectionTerm(
130
- (1 - opinionA.a) * opinionA.u * (intermediateDisbelief - ifTrue.d),
131
- projectedAntecedentComplement * (1 - childBaseRate)
132
- ) ?? 0;
133
- }
134
- } else {
135
- const beliefGap = ifFalse.b - ifTrue.b;
136
- const disbeliefGap = ifTrue.d - ifFalse.d;
137
- if (projectedVacuousDeduction <= projectedConditionalA && projectedAntecedent <= opinionA.a) {
138
- correction = safeCorrectionTerm(
139
- (1 - opinionA.a) * opinionA.u * (intermediateDisbelief - ifTrue.d) * beliefGap,
140
- projectedAntecedent * childBaseRate * disbeliefGap
141
- ) ?? 0;
142
- } else if (projectedVacuousDeduction <= projectedConditionalA && projectedAntecedent > opinionA.a) {
143
- correction = safeCorrectionTerm(
144
- (1 - opinionA.a) * opinionA.u * (intermediateBelief - ifTrue.b),
145
- projectedAntecedentComplement * childBaseRate
146
- ) ?? 0;
147
- } else if (projectedVacuousDeduction > projectedConditionalA && projectedAntecedent <= opinionA.a) {
148
- correction = safeCorrectionTerm(
149
- opinionA.a * opinionA.u * (intermediateDisbelief - ifTrue.d),
150
- projectedAntecedent * (1 - childBaseRate)
151
- ) ?? 0;
152
- } else {
153
- correction = safeCorrectionTerm(
154
- opinionA.a * opinionA.u * (intermediateBelief - ifTrue.b) * disbeliefGap,
155
- projectedAntecedentComplement * (1 - childBaseRate) * beliefGap
156
- ) ?? 0;
157
- }
158
- }
159
- return opinion(
160
- intermediateBelief - childBaseRate * correction,
161
- intermediateDisbelief - (1 - childBaseRate) * correction,
162
- intermediateUncertainty + correction,
163
- childBaseRate
164
- );
165
- }
166
- function negate(o) {
167
- return { b: o.d, d: o.b, u: o.u, a: 1 - o.a };
168
- }
169
- function constraintFusion(left, right, mode = "pressure") {
170
- if (mode === "redistribute") {
171
- const leftProjected = project(left);
172
- const rightProjected = project(right);
173
- const total = leftProjected + rightProjected;
174
- if (total <= 1) {
175
- return { o1: left, o2: right };
176
- }
177
- const scale = 1 / total;
178
- return {
179
- o1: opinion(
180
- left.b * scale,
181
- left.d + left.b * (1 - scale),
182
- left.u,
183
- left.a
184
- ),
185
- o2: opinion(
186
- right.b * scale,
187
- right.d + right.b * (1 - scale),
188
- right.u,
189
- right.a
190
- )
191
- };
192
- }
193
- const pressureLeft = right.b * 0.5;
194
- const pressureRight = left.b * 0.5;
195
- return {
196
- o1: opinion(
197
- left.b - pressureLeft * 0.3,
198
- left.d + pressureLeft * 0.3,
199
- left.u,
200
- left.a
201
- ),
202
- o2: opinion(
203
- right.b - pressureRight * 0.3,
204
- right.d + pressureRight * 0.3,
205
- right.u,
206
- right.a
207
- )
208
- };
209
- }
210
-
211
- // ../confidence/src/v1/operations/scoring.ts
212
- function finiteNumber(value) {
213
- return typeof value === "number" && Number.isFinite(value) ? value : void 0;
214
- }
215
- function clamp01(value) {
216
- return Math.max(0, Math.min(1, value));
217
- }
218
- function confidenceFromOpinion(opinion2) {
219
- return clamp01(opinion2.b + opinion2.a * opinion2.u);
220
- }
221
- function confidenceFromSL(belief, _disbelief, uncertainty, baseRate = 0.5) {
222
- return confidenceFromOpinion({
223
- b: belief,
224
- u: uncertainty,
225
- a: baseRate
226
- });
227
- }
228
- function readOpinionFromRecord(source, fallback = {}) {
229
- const record = source && typeof source === "object" ? source : {};
230
- return {
231
- b: finiteNumber(record.b) ?? finiteNumber(record.belief) ?? finiteNumber(record.slBelief) ?? finiteNumber(record.opinion_b) ?? fallback.b ?? 0,
232
- d: finiteNumber(record.d) ?? finiteNumber(record.disbelief) ?? finiteNumber(record.slDisbelief) ?? finiteNumber(record.opinion_d) ?? fallback.d ?? 0,
233
- u: finiteNumber(record.u) ?? finiteNumber(record.uncertainty) ?? finiteNumber(record.slUncertainty) ?? finiteNumber(record.opinion_u) ?? fallback.u ?? 1,
234
- a: finiteNumber(record.a) ?? finiteNumber(record.baseRate) ?? finiteNumber(record.slBaseRate) ?? finiteNumber(record.opinion_a) ?? fallback.a ?? 0.5
235
- };
236
- }
237
- function hasProjectedOpinionChanged(current, next, tolerance = 0.01) {
238
- return Math.abs(confidenceFromOpinion(next) - confidenceFromOpinion(current)) >= tolerance;
239
- }
240
-
241
- // ../confidence/src/v1/operations/contradiction/detectTupleContradiction.ts
242
- var DEFAULT_TUPLE_CONTRADICTION_BELIEF_THRESHOLD = 0.7;
243
- var DEFAULT_TUPLE_CONTRADICTION_DISBELIEF_THRESHOLD = 0.7;
244
- function normalizeTupleContradictionPolicy(policy = {}) {
245
- return {
246
- beliefThreshold: clamp01(
247
- policy.beliefThreshold ?? DEFAULT_TUPLE_CONTRADICTION_BELIEF_THRESHOLD
248
- ),
249
- disbeliefThreshold: clamp01(
250
- policy.disbeliefThreshold ?? DEFAULT_TUPLE_CONTRADICTION_DISBELIEF_THRESHOLD
251
- )
252
- };
253
- }
254
- function detectTupleContradiction(opinion2, tauB = DEFAULT_TUPLE_CONTRADICTION_BELIEF_THRESHOLD, tauD = DEFAULT_TUPLE_CONTRADICTION_DISBELIEF_THRESHOLD) {
255
- return opinion2.b > tauB && opinion2.d > tauD;
256
- }
257
- function evaluateTupleContradictionTransition(args) {
258
- const policy = normalizeTupleContradictionPolicy(args.policy);
259
- const tupleContradicted = detectTupleContradiction(
260
- args.opinion,
261
- policy.beliefThreshold,
262
- policy.disbeliefThreshold
263
- );
264
- const previousTupleContradicted = Boolean(args.previousTupleContradicted);
265
- return {
266
- tupleContradicted,
267
- crossedIntoTupleContradiction: !previousTupleContradicted && tupleContradicted,
268
- crossedOutOfTupleContradiction: previousTupleContradicted && !tupleContradicted,
269
- policy
270
- };
271
- }
272
-
273
- // ../confidence/src/v1/operations/dynamics/cascade.ts
274
- function dampedDependencyOpinion(dependencyOpinion, beliefOpinion, mode = "continuous", threshold = 0.3) {
275
- const dependencyProjection = project(dependencyOpinion);
276
- if (mode === "threshold") {
277
- if (dependencyProjection < threshold) {
278
- return opinion(
279
- 0,
280
- beliefOpinion.d + beliefOpinion.b * 0.5,
281
- 0.5,
282
- beliefOpinion.a
283
- );
284
- }
285
- return beliefOpinion;
286
- }
287
- const dampingFactor = Math.pow(dependencyProjection, 0.5);
288
- return opinion(
289
- beliefOpinion.b * dampingFactor,
290
- beliefOpinion.d + beliefOpinion.b * (1 - dampingFactor) * 0.3,
291
- beliefOpinion.u + beliefOpinion.b * (1 - dampingFactor) * 0.7,
292
- beliefOpinion.a
293
- );
294
- }
295
- function dampedDependencyCascade(dependencyOpinion, beliefOpinion, mode = "continuous") {
296
- return {
297
- opinion: dampedDependencyOpinion(dependencyOpinion, beliefOpinion, mode),
298
- operator: "dependency_cascade",
299
- rationale: `Damped dependency cascade (${mode}): prerequisite at ${project(
300
- dependencyOpinion
301
- ).toFixed(2)}`
302
- };
303
- }
304
-
305
- // ../confidence/src/v1/operations/dynamics/defeat.ts
306
- function applyNegativeSupport(source, target, weight, metadata = {}) {
307
- if (metadata.constraint === "xor") {
308
- const result = constraintFusion(
309
- source,
310
- target,
311
- metadata.normalization ?? "pressure"
312
- );
313
- return {
314
- opinion: result.o2,
315
- operator: "constraint_fusion",
316
- rationale: `XOR constraint: source belief at ${project(source).toFixed(
317
- 2
318
- )} pressures target`
319
- };
320
- }
321
- const discounted = trustDiscount(negate(source), Math.abs(weight));
322
- return {
323
- opinion: cumulativeFusion(target, discounted),
324
- operator: "cumulative_fusion",
325
- rationale: `Contradicting evidence (weight=${weight.toFixed(
326
- 2
327
- )}) from source at ${project(source).toFixed(2)}`
328
- };
329
- }
330
- function applyNegativeEvidence(source, target, weight) {
331
- const discounted = trustDiscount(negate(source), Math.abs(weight));
332
- return {
333
- opinion: cumulativeFusion(target, discounted),
334
- operator: "cumulative_fusion",
335
- rationale: `Contradicting evidence (weight=${weight.toFixed(2)})`
336
- };
337
- }
338
-
339
- // ../confidence/src/v1/operations/contracts/epistemicContract.ts
340
- function generateContractId() {
341
- if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
342
- return crypto.randomUUID();
343
- }
344
- return `contract-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
345
- }
346
- function createInheritedContractRecord(contract, args) {
347
- return {
348
- beliefNodeId: args.beliefNodeId,
349
- contractId: generateContractId(),
350
- title: contract.title,
351
- description: contract.description,
352
- conditionType: contract.conditionType,
353
- direction: contract.direction,
354
- condition: contract.condition,
355
- deadline: contract.deadline,
356
- compositeOf: contract.compositeOf,
357
- compositeOperator: contract.compositeOperator,
358
- modulation: contract.modulation,
359
- evaluationSchedule: contract.evaluationSchedule,
360
- periodicIntervalMs: contract.periodicIntervalMs,
361
- status: "active",
362
- lineageSource: "inherited",
363
- inheritedFromContractId: contract.contractId,
364
- inheritedFromBeliefNodeId: contract.beliefNodeId,
365
- inheritedAt: args.now,
366
- topicId: args.topicId,
367
- createdAt: args.now,
368
- createdBy: args.createdBy,
369
- updatedAt: args.now
370
- };
371
- }
372
- var api = anyApi;
373
- componentsGeneric();
374
-
375
- // ../access-control/src/topicProjectOverlay.ts
376
- var LEGACY_SCOPE_FIELD = "graphScopeProjectId";
377
- function readNonEmptyString(value) {
378
- if (typeof value !== "string") {
379
- return;
380
- }
381
- const normalized = value.trim();
382
- return normalized.length > 0 ? normalized : void 0;
383
- }
384
- function readStringArray(value) {
385
- if (!Array.isArray(value)) {
386
- return [];
387
- }
388
- return value.map((entry) => readNonEmptyString(entry)).filter((entry) => Boolean(entry));
389
- }
390
- function readMetadata(topic) {
391
- return topic.metadata && typeof topic.metadata === "object" ? topic.metadata : {};
392
- }
393
- function readLegacyProjectId(value) {
394
- if (!value) {
395
- return;
396
- }
397
- return readNonEmptyString(value[LEGACY_SCOPE_FIELD]);
398
- }
399
- function coerceVisibility(value) {
400
- return value === "private" || value === "team" || value === "firm" || value === "external" || value === "public" ? value : void 0;
401
- }
402
- function coerceStatus(value) {
403
- return value === "active" || value === "archived" || value === "watching" ? value : void 0;
404
- }
405
- function mapProjectType(topic, metadata) {
406
- const explicit = readNonEmptyString(metadata.projectType);
407
- if (explicit) {
408
- return explicit;
409
- }
410
- if (topic.type === "theme") {
411
- return "thematic";
412
- }
413
- return readNonEmptyString(topic.type) || "general";
414
- }
415
- function isProjectLikeTopic(topic) {
416
- const metadata = readMetadata(topic);
417
- return topic.type === "theme" || topic.type === "thematic" || topic.type === "deal" || topic.type === "monitoring" || readLegacyProjectId(topic) !== void 0 || readNonEmptyString(metadata.projectType) !== void 0;
418
- }
419
- async function resolveTopicDoc(ctx, scopeId) {
420
- if (ctx?.db && typeof ctx.db.get === "function") {
421
- try {
422
- const directTopic = await ctx.db.get(scopeId);
423
- if (directTopic) {
424
- return directTopic;
425
- }
426
- } catch {
427
- }
428
- }
429
- if (typeof ctx.runQuery !== "function") {
430
- return null;
431
- }
432
- try {
433
- const topic = await ctx.runQuery(api.topics.get, {
434
- id: String(scopeId)
435
- });
436
- if (topic?.name !== void 0 && topic?.type !== void 0) {
437
- return topic;
438
- }
439
- } catch {
440
- }
441
- try {
442
- const topic = await ctx.runQuery(api.topics.getByLegacyScopeId, {
443
- projectId: String(scopeId)
444
- });
445
- if (topic?.name !== void 0 && topic?.type !== void 0) {
446
- return topic;
447
- }
448
- } catch {
449
- }
450
- return null;
451
- }
452
- function materializeTopicProjectOverlay(topic, idMode = "legacy") {
453
- const metadata = readMetadata(topic);
454
- const topicId = String(topic._id);
455
- const legacyProjectId = readLegacyProjectId(topic) || readLegacyProjectId(metadata) || readNonEmptyString(metadata.legacyProjectId);
456
- const storageProjectId = legacyProjectId || topicId;
457
- const outwardId = idMode === "topic" ? topicId : storageProjectId;
458
- const visibility = coerceVisibility(topic.visibility) || coerceVisibility(metadata.visibility) || "private";
459
- const status = coerceStatus(topic.status) || coerceStatus(metadata.status) || "active";
460
- const createdAt = typeof topic.createdAt === "number" ? topic.createdAt : typeof topic._creationTime === "number" ? topic._creationTime : 0;
461
- const updatedAt = typeof topic.updatedAt === "number" ? topic.updatedAt : typeof metadata.updatedAt === "number" ? metadata.updatedAt : createdAt;
462
- return {
463
- ...metadata,
464
- _id: outwardId,
465
- projectId: outwardId,
466
- topicId,
467
- storageProjectId,
468
- legacyProjectId,
469
- name: readNonEmptyString(topic.name) || "Untitled Theme",
470
- type: mapProjectType(topic, metadata),
471
- description: readNonEmptyString(topic.description),
472
- ownerId: readNonEmptyString(metadata.ownerId) || readNonEmptyString(topic.createdBy) || "system",
473
- sharedWith: readStringArray(metadata.sharedWith),
474
- visibility,
475
- tenantId: readNonEmptyString(topic.tenantId) || readNonEmptyString(metadata.tenantId),
476
- workspaceId: readNonEmptyString(topic.workspaceId) || readNonEmptyString(metadata.workspaceId),
477
- status,
478
- tags: readStringArray(metadata.tags),
479
- chatCount: typeof metadata.chatCount === "number" ? metadata.chatCount : 0,
480
- artifactCount: typeof metadata.artifactCount === "number" ? metadata.artifactCount : 0,
481
- lastActivityAt: typeof metadata.lastActivityAt === "number" ? metadata.lastActivityAt : updatedAt,
482
- _creationTime: typeof topic._creationTime === "number" ? topic._creationTime : createdAt,
483
- createdAt,
484
- updatedAt
485
- };
486
- }
487
- async function resolveTopicProjectOverlay(ctx, scopeId, options = {}) {
488
- const topic = await resolveTopicDoc(ctx, scopeId);
489
- if (!topic) {
490
- return null;
491
- }
492
- if (options.projectLikeOnly !== false && !isProjectLikeTopic(topic)) {
493
- return null;
494
- }
495
- return materializeTopicProjectOverlay(topic, options.idMode);
496
- }
497
- async function listTopicProjectOverlays(ctx, options = {}) {
498
- let allTopics = [];
499
- if (ctx?.db?.query && typeof ctx.db.query === "function") {
500
- try {
501
- allTopics = await ctx.db.query("topics").collect();
502
- } catch {
503
- allTopics = [];
504
- }
505
- }
506
- if (allTopics.length === 0 && typeof ctx.runQuery === "function") {
507
- allTopics = (await ctx.runQuery(api.topics.list, {}) ?? []) || [];
508
- }
509
- return allTopics.filter(
510
- (topic) => options.projectLikeOnly === false || isProjectLikeTopic(topic)
511
- ).map((topic) => materializeTopicProjectOverlay(topic, options.idMode));
512
- }
513
-
514
- // ../access-control/src/projectGrantsBridge.ts
515
- var PROJECT_GRANT_STATUSES = ["active", "revoked", "expired"];
516
- function normalizeString(value) {
517
- if (typeof value !== "string") {
518
- return;
519
- }
520
- const trimmed = value.trim();
521
- return trimmed.length > 0 ? trimmed : void 0;
522
- }
523
- async function resolveGrantScopeIds(ctx, args) {
524
- const topicId = normalizeString(args.topicId);
525
- const projectId = normalizeString(args.projectId);
526
- for (const scopeId of [topicId, projectId]) {
527
- if (!scopeId) {
528
- continue;
529
- }
530
- try {
531
- const overlay = await resolveTopicProjectOverlay(ctx, scopeId, {
532
- idMode: "legacy",
533
- projectLikeOnly: false
534
- });
535
- if (overlay) {
536
- return {
537
- topicId: normalizeString(overlay.topicId) ?? topicId,
538
- projectId: normalizeString(overlay.projectId) ?? projectId ?? scopeId
539
- };
540
- }
541
- } catch {
542
- }
543
- }
544
- return { topicId, projectId };
545
- }
546
- async function normalizeProjectGrantRow(ctx, row) {
547
- const scope = await resolveGrantScopeIds(ctx, {
548
- topicId: row.topicId,
549
- projectId: row.projectId
550
- });
551
- return {
552
- ...row,
553
- ...scope.topicId ? { topicId: scope.topicId } : {},
554
- ...scope.projectId ?? scope.topicId ? { projectId: scope.projectId ?? scope.topicId } : {}
555
- };
556
- }
557
- async function normalizeProjectGrantRows(ctx, rows) {
558
- return await Promise.all(rows.map((row) => normalizeProjectGrantRow(ctx, row)));
559
- }
560
- async function listProjectGrantsByPrincipal(ctx, principalId) {
561
- const rows = await Promise.all(
562
- PROJECT_GRANT_STATUSES.map(
563
- (status) => ctx.db.query("projectGrants").withIndex(
564
- "by_principal_status",
565
- (q) => q.eq("principalId", principalId).eq("status", status)
566
- ).collect()
567
- )
568
- );
569
- return await normalizeProjectGrantRows(ctx, rows.flat());
570
- }
571
- async function listProjectGrantsByGroup(ctx, groupId) {
572
- const rows = await Promise.all(
573
- PROJECT_GRANT_STATUSES.map(
574
- (status) => ctx.db.query("projectGrants").withIndex(
575
- "by_group_status",
576
- (q) => q.eq("groupId", groupId).eq("status", status)
577
- ).collect()
578
- )
579
- );
580
- return await normalizeProjectGrantRows(ctx, rows.flat());
581
- }
582
- function buildScopeMatchers(inputScopeId, resolved) {
583
- return new Set(
584
- [inputScopeId, resolved.topicId, resolved.projectId].map((value) => normalizeString(value)).filter((value) => Boolean(value))
585
- );
586
- }
587
- function matchesResolvedScope(row, scopeIds) {
588
- const rowTopicId = normalizeString(row.topicId);
589
- const rowProjectId = normalizeString(row.projectId);
590
- return rowTopicId !== void 0 && scopeIds.has(rowTopicId) || rowProjectId !== void 0 && scopeIds.has(rowProjectId);
591
- }
592
- async function bridgeListProjectGrantsByTopicAndPrincipal(ctx, topicId, principalId) {
593
- const resolved = await resolveGrantScopeIds(ctx, { topicId });
594
- const scopeIds = buildScopeMatchers(topicId, resolved);
595
- const rows = await listProjectGrantsByPrincipal(ctx, principalId);
596
- return rows.filter((row) => matchesResolvedScope(row, scopeIds));
597
- }
598
- async function bridgeListProjectGrantsByTopicAndGroup(ctx, topicId, groupId) {
599
- const resolved = await resolveGrantScopeIds(ctx, { topicId });
600
- const scopeIds = buildScopeMatchers(topicId, resolved);
601
- const rows = await listProjectGrantsByGroup(ctx, groupId);
602
- return rows.filter((row) => matchesResolvedScope(row, scopeIds));
603
- }
604
- async function bridgeListProjectGrantsByPrincipalStatus(ctx, principalId, status) {
605
- const rows = await listProjectGrantsByPrincipal(ctx, principalId);
606
- return rows.filter((row) => row.status === status);
607
- }
608
- async function bridgeListProjectGrantsByGroupStatus(ctx, groupId, status) {
609
- const rows = await listProjectGrantsByGroup(ctx, groupId);
610
- return rows.filter((row) => row.status === status);
611
- }
612
- async function bridgeInsertProjectGrant(ctx, value) {
613
- const resolved = await resolveGrantScopeIds(ctx, value);
614
- return await ctx.db.insert("projectGrants", {
615
- ...value,
616
- ...resolved.topicId ? { topicId: resolved.topicId } : {},
617
- ...resolved.projectId ?? resolved.topicId ? { projectId: resolved.projectId ?? resolved.topicId } : {}
618
- });
619
- }
620
-
621
- // ../access-control/src/resolvers.ts
622
- async function findUserByClerkId(ctx, clerkId) {
623
- const normalizedClerkId = clerkId.trim();
624
- if (!normalizedClerkId) {
625
- return null;
626
- }
627
- if (typeof ctx.runQuery === "function") {
628
- try {
629
- const bridgedUser = await ctx.runQuery(api.users.getUserByClerkId, {
630
- clerkId: normalizedClerkId
631
- });
632
- if (bridgedUser) {
633
- return bridgedUser;
634
- }
635
- } catch {
636
- }
637
- }
638
- try {
639
- const users = await ctx.db.query("users").collect();
640
- return users.find((user) => String(user.clerkId ?? "") === normalizedClerkId) ?? null;
641
- } catch {
642
- return null;
643
- }
644
- }
645
- async function findUserByPrincipalId(ctx, principalId) {
646
- const normalizedPrincipalId = principalId.trim();
647
- if (!normalizedPrincipalId) {
648
- return null;
649
- }
650
- try {
651
- const users = await ctx.db.query("users").collect();
652
- return users.find(
653
- (user) => String(user.defaultPrincipalId ?? "") === normalizedPrincipalId
654
- ) ?? null;
655
- } catch {
656
- return null;
657
- }
658
- }
659
- async function findAgentByPrincipalId(ctx, principalId) {
660
- const normalizedPrincipalId = principalId.trim();
661
- if (!normalizedPrincipalId) {
662
- return null;
663
- }
664
- if (typeof ctx.runQuery === "function") {
665
- try {
666
- const bridgedAgent = await ctx.runQuery(
667
- api.agents.getAgentByPrincipalId,
668
- {
669
- principalId: normalizedPrincipalId
670
- }
671
- );
672
- if (bridgedAgent) {
673
- return bridgedAgent;
674
- }
675
- } catch {
676
- }
677
- }
678
- try {
679
- const agents = await ctx.db.query("agents").collect();
680
- return agents.find(
681
- (agent) => String(agent.principalId ?? "") === normalizedPrincipalId
682
- ) ?? null;
683
- } catch {
684
- return null;
685
- }
686
- }
687
- function defaultResolvers() {
688
- return {
689
- async getProject(ctx, topicId) {
690
- return await resolveTopicProjectOverlay(ctx, topicId, {
691
- idMode: "legacy",
692
- projectLikeOnly: false
693
- });
694
- },
695
- async listTopics(ctx) {
696
- return await listTopicProjectOverlays(ctx, { idMode: "legacy" });
697
- },
698
- async listTopicsByOwner(ctx, ownerId) {
699
- const topics = await listTopicProjectOverlays(ctx, { idMode: "legacy" });
700
- return topics.filter((topic) => topic.ownerId === ownerId);
701
- },
702
- async listTopicsByVisibility(ctx, visibility) {
703
- const topics = await listTopicProjectOverlays(ctx, { idMode: "legacy" });
704
- return topics.filter((topic) => topic.visibility === visibility);
705
- },
706
- async listProjectGrantsByProjectAndPrincipal(ctx, topicId, principalId) {
707
- return await bridgeListProjectGrantsByTopicAndPrincipal(
708
- ctx,
709
- topicId,
710
- principalId
711
- );
712
- },
713
- async listProjectGrantsByProjectAndGroup(ctx, topicId, groupId) {
714
- return await bridgeListProjectGrantsByTopicAndGroup(ctx, topicId, groupId);
715
- },
716
- async listProjectGrantsByPrincipalStatus(ctx, principalId, status) {
717
- return await bridgeListProjectGrantsByPrincipalStatus(
718
- ctx,
719
- principalId,
720
- status
721
- );
722
- },
723
- async listProjectGrantsByGroupStatus(ctx, groupId, status) {
724
- return await bridgeListProjectGrantsByGroupStatus(ctx, groupId, status);
725
- },
726
- async insertProjectGrant(ctx, value) {
727
- return await bridgeInsertProjectGrant(ctx, value);
728
- },
729
- async getAgentByPrincipalId(ctx, principalId) {
730
- return await findAgentByPrincipalId(ctx, principalId);
731
- },
732
- async getUserByClerkId(ctx, clerkId) {
733
- return await findUserByClerkId(ctx, clerkId);
734
- },
735
- async getUserByPrincipalId(ctx, principalId) {
736
- return await findUserByPrincipalId(ctx, principalId);
737
- }
738
- };
739
- }
740
- var resolverOverrides = {};
741
- function resolveAccessControlAppResolvers(_ctx) {
742
- return {
743
- ...defaultResolvers(),
744
- ...resolverOverrides
745
- };
746
- }
747
-
748
- // ../access-control/src/principalContext.ts
749
- function requireCanonicalResolvedUser(user, clerkId) {
750
- const resolved = user;
751
- if (!resolved) {
752
- throw new Error(
753
- `[AccessControl] Canonical user identity required for ${clerkId}. Sync users.upsertUser before user-bound access checks.`
754
- );
755
- }
756
- const { mcRole, defaultTenantId, defaultWorkspaceId, defaultPrincipalId } = resolved;
757
- if (mcRole !== "platform_admin" && mcRole !== "tenant_admin" && mcRole !== "workspace_admin" && mcRole !== "editor" && mcRole !== "viewer" && mcRole !== "auditor" && mcRole !== "service_agent") {
758
- throw new Error(
759
- `[AccessControl] Canonical MC role required for ${clerkId}. Re-sync Master Control identity before user-bound access checks.`
760
- );
761
- }
762
- if (typeof defaultTenantId !== "string" || defaultTenantId.trim().length === 0) {
763
- throw new Error(
764
- `[AccessControl] Canonical home tenant required for ${clerkId}. Re-sync Master Control identity before user-bound access checks.`
765
- );
766
- }
767
- if (typeof defaultWorkspaceId !== "string" || defaultWorkspaceId.trim().length === 0) {
768
- throw new Error(
769
- `[AccessControl] Canonical home workspace required for ${clerkId}. Re-sync Master Control identity before user-bound access checks.`
770
- );
771
- }
772
- if (typeof defaultPrincipalId !== "string" || defaultPrincipalId.trim().length === 0) {
773
- throw new Error(
774
- `[AccessControl] Canonical federated principal required for ${clerkId}. Re-sync Master Control identity before user-bound access checks.`
775
- );
776
- }
777
- return {
778
- mcRole,
779
- defaultTenantId: defaultTenantId.trim(),
780
- defaultWorkspaceId: defaultWorkspaceId.trim(),
781
- defaultPrincipalId: defaultPrincipalId.trim()
782
- };
783
- }
784
- function isPrincipalIdInput(value) {
785
- return value.startsWith("user:") || value.startsWith("group:") || value.startsWith("service:") || value.startsWith("agent:") || value.startsWith("external_viewer:");
786
- }
787
- async function resolveCanonicalUserRecord(ctx, actorId) {
788
- const normalizedActorId = actorId.trim();
789
- const clerkId = isPrincipalIdInput(normalizedActorId) && normalizedActorId.startsWith("user:") ? normalizedActorId.slice("user:".length) : normalizedActorId;
790
- const resolvers = resolveAccessControlAppResolvers();
791
- const resolvedByClerkId = await resolvers.getUserByClerkId(ctx, clerkId);
792
- if (resolvedByClerkId) {
793
- return {
794
- resolvedUser: resolvedByClerkId,
795
- clerkId,
796
- contextClerkId: clerkId
797
- };
798
- }
799
- const resolvedByPrincipalId = await resolvers.getUserByPrincipalId(
800
- ctx,
801
- normalizedActorId
802
- );
803
- return {
804
- resolvedUser: resolvedByPrincipalId ?? null,
805
- clerkId,
806
- contextClerkId: normalizedActorId.startsWith("user:") && clerkId.length > 0 ? clerkId : normalizedActorId
807
- };
808
- }
809
- function uniqRoles(roles) {
810
- const roleSet = /* @__PURE__ */ new Set();
811
- for (const role of roles) {
812
- if (role === "platform_admin" || role === "tenant_admin" || role === "workspace_admin" || role === "editor" || role === "viewer" || role === "auditor" || role === "service_agent") {
813
- roleSet.add(role);
814
- }
815
- }
816
- return [...roleSet];
817
- }
818
- function normalizeGroupIds(value) {
819
- if (!Array.isArray(value)) {
820
- return [];
821
- }
822
- return [...new Set(
823
- value.filter((entry) => typeof entry === "string").map((entry) => entry.trim()).filter(Boolean)
824
- )];
825
- }
826
- function requireServiceAgentUser(user, actorId) {
827
- const canonicalUser = requireCanonicalResolvedUser(user, actorId);
828
- if (canonicalUser.mcRole !== "service_agent") {
829
- throw new Error(
830
- `[AccessControl] Canonical service_agent identity required for ${actorId}. Sync users.upsertUser before agent-bound access checks.`
831
- );
832
- }
833
- return canonicalUser;
834
- }
835
- function requireCanonicalResolvedAgent(agent, actorId) {
836
- const resolved = agent;
837
- if (!resolved) {
838
- throw new Error(
839
- `[AccessControl] Agent "${actorId}" not found in agents or users table.`
840
- );
841
- }
842
- if (typeof resolved.principalId !== "string" || resolved.principalId.trim().length === 0) {
843
- throw new Error(
844
- `[AccessControl] Canonical agent principalId required for ${actorId}.`
845
- );
846
- }
847
- if (typeof resolved.tenantId !== "string" || resolved.tenantId.trim().length === 0) {
848
- throw new Error(
849
- `[AccessControl] Canonical home tenant required for ${actorId}.`
850
- );
851
- }
852
- if (typeof resolved.workspaceId !== "string" || resolved.workspaceId.trim().length === 0) {
853
- throw new Error(
854
- `[AccessControl] Canonical home workspace required for ${actorId}.`
855
- );
856
- }
857
- return {
858
- principalId: resolved.principalId.trim(),
859
- tenantId: resolved.tenantId.trim(),
860
- workspaceId: resolved.workspaceId.trim(),
861
- roles: uniqRoles(Array.isArray(resolved.roles) ? resolved.roles : []) ?? ["service_agent"],
862
- groupIds: normalizeGroupIds(resolved.groupIds)
863
- };
864
- }
865
- async function resolvePrincipalContext(ctx, actorId) {
866
- if (actorId.startsWith("agent:")) {
867
- const resolvers = resolveAccessControlAppResolvers();
868
- const resolvedAgent = await resolvers.getAgentByPrincipalId(ctx, actorId);
869
- if (resolvedAgent) {
870
- const agent = requireCanonicalResolvedAgent(
871
- resolvedAgent,
872
- actorId
873
- );
874
- return {
875
- principalId: agent.principalId,
876
- principalType: "service",
877
- clerkId: actorId,
878
- tenantId: agent.tenantId,
879
- workspaceId: agent.workspaceId,
880
- roles: agent.roles.length > 0 ? agent.roles : ["service_agent"],
881
- groupIds: agent.groupIds,
882
- isPlatformAdmin: false,
883
- isTenantAdmin: false,
884
- isWorkspaceAdmin: false,
885
- isSystemFallback: false
886
- };
887
- }
888
- const resolvedUser2 = await resolvers.getUserByClerkId(
889
- ctx,
890
- actorId
891
- );
892
- if (!resolvedUser2) {
893
- throw new Error(
894
- `[AccessControl] Agent "${actorId}" not found in agents or users table.`
895
- );
896
- }
897
- const user2 = requireServiceAgentUser(
898
- resolvedUser2,
899
- actorId
900
- );
901
- console.warn(
902
- `[AccessControl] Deprecated legacy service-agent fallback for ${actorId}; migrate this principal into identity.agents.`
903
- );
904
- return {
905
- principalId: user2.defaultPrincipalId,
906
- principalType: "service",
907
- clerkId: actorId,
908
- tenantId: user2.defaultTenantId,
909
- workspaceId: user2.defaultWorkspaceId,
910
- roles: ["service_agent"],
911
- groupIds: normalizeGroupIds(resolvedUser2?.principalGroupIds),
912
- isPlatformAdmin: false,
913
- isTenantAdmin: false,
914
- isWorkspaceAdmin: false,
915
- isSystemFallback: false
916
- };
917
- }
918
- const {
919
- resolvedUser,
920
- contextClerkId
921
- } = await resolveCanonicalUserRecord(ctx, actorId);
922
- const user = requireCanonicalResolvedUser(
923
- resolvedUser,
924
- contextClerkId
925
- );
926
- if (!user.defaultPrincipalId) {
927
- throw new Error(
928
- `[AccessControl] Canonical federated principal required for ${contextClerkId}. Re-sync Master Control identity before user-bound access checks.`
929
- );
930
- }
931
- if (user.mcRole === "service_agent") {
932
- return {
933
- principalId: user.defaultPrincipalId,
934
- principalType: "service",
935
- clerkId: contextClerkId,
936
- tenantId: user.defaultTenantId,
937
- workspaceId: user.defaultWorkspaceId,
938
- roles: ["service_agent"],
939
- groupIds: normalizeGroupIds(resolvedUser?.principalGroupIds),
940
- isPlatformAdmin: false,
941
- isTenantAdmin: false,
942
- isWorkspaceAdmin: false,
943
- isSystemFallback: false
944
- };
945
- }
946
- const principalId = user.defaultPrincipalId;
947
- const effectiveRole = user.mcRole;
948
- const roles = effectiveRole === "platform_admin" ? ["platform_admin", "tenant_admin"] : effectiveRole === "tenant_admin" ? ["tenant_admin"] : [effectiveRole];
949
- const tenantId = user.defaultTenantId;
950
- const workspaceId = user.defaultWorkspaceId;
951
- const isPlatformAdmin = effectiveRole === "platform_admin";
952
- return {
953
- principalId,
954
- principalType: "user",
955
- clerkId: contextClerkId,
956
- tenantId,
957
- workspaceId,
958
- roles: uniqRoles(roles),
959
- groupIds: normalizeGroupIds(resolvedUser?.principalGroupIds),
960
- isPlatformAdmin,
961
- isTenantAdmin: isPlatformAdmin || effectiveRole === "tenant_admin",
962
- isWorkspaceAdmin: isPlatformAdmin || effectiveRole === "tenant_admin" || effectiveRole === "workspace_admin",
963
- isSystemFallback: false
964
- };
965
- }
966
-
967
- // ../access-control/src/access.ts
968
- function isTopicInPrincipalTenant(topic, principalTenantId) {
969
- if (!topic.tenantId) {
970
- return false;
971
- }
972
- if (!principalTenantId) {
973
- return false;
974
- }
975
- return String(topic.tenantId) === String(principalTenantId);
976
- }
977
- function isTopicInPrincipalWorkspace(topic, principalWorkspaceId) {
978
- if (!topic.workspaceId) {
979
- return false;
980
- }
981
- if (!principalWorkspaceId) {
982
- return false;
983
- }
984
- return String(topic.workspaceId) === String(principalWorkspaceId);
985
- }
986
- function isLegacyUnscopedTopic(topic) {
987
- return !topic.tenantId || !topic.workspaceId;
988
- }
989
- function isGrantScopeAlignedToTopic(topic, grant) {
990
- if (topic.tenantId && grant.tenantId && String(topic.tenantId) !== String(grant.tenantId)) {
991
- return false;
992
- }
993
- if (topic.workspaceId && grant.workspaceId && String(topic.workspaceId) !== String(grant.workspaceId)) {
994
- return false;
995
- }
996
- return true;
997
- }
998
- function isGrantSourceAllowedForVisibility(visibility, source) {
999
- if (source !== "external_share") {
1000
- return true;
1001
- }
1002
- return visibility === "external" || visibility === "public";
1003
- }
1004
- function isGrantActive(grant) {
1005
- if (grant.status !== "active") {
1006
- return false;
1007
- }
1008
- if (grant.expiresAt !== void 0 && grant.expiresAt <= Date.now()) {
1009
- return false;
1010
- }
1011
- return true;
1012
- }
1013
- async function hasPrincipalGrant(ctx, args) {
1014
- const grants = await resolveAccessControlAppResolvers().listProjectGrantsByProjectAndPrincipal(
1015
- ctx,
1016
- args.topic._id,
1017
- args.principalId
1018
- );
1019
- if (grants.some(
1020
- (grant) => isGrantActive(grant) && isGrantScopeAlignedToTopic(args.topic, grant) && isGrantSourceAllowedForVisibility(
1021
- args.topic.visibility,
1022
- grant.source
1023
- ) && (!args.principalIsExternal || args.topic.visibility === "public" || grant.source === "external_share")
1024
- )) {
1025
- return true;
1026
- }
1027
- return false;
1028
- }
1029
- async function hasGroupGrant(ctx, args) {
1030
- if (args.groupIds.length === 0) {
1031
- return false;
1032
- }
1033
- for (const groupId of args.groupIds) {
1034
- const grants = await resolveAccessControlAppResolvers().listProjectGrantsByProjectAndGroup(ctx, args.topic._id, groupId);
1035
- if (grants.some(
1036
- (grant) => isGrantActive(grant) && isGrantScopeAlignedToTopic(args.topic, grant) && isGrantSourceAllowedForVisibility(
1037
- args.topic.visibility,
1038
- grant.source
1039
- )
1040
- )) {
1041
- return true;
1042
- }
1043
- }
1044
- return false;
1045
- }
1046
- function isExternalPrincipal(_ctx, _args) {
1047
- return false;
1048
- }
1049
- async function evaluateTopicAccessDetailed(ctx, args) {
1050
- if (args.legacyUserId) {
1051
- return {
1052
- hasAccess: true,
1053
- isAdmin: false,
1054
- isOwner: false,
1055
- isShared: false,
1056
- hasGrant: true,
1057
- isFirmVisible: true,
1058
- isExternalVisible: false,
1059
- isPublicVisible: false,
1060
- isTenantScopeMatch: true,
1061
- isWorkspaceScopeMatch: true,
1062
- isPrincipalExternal: false
1063
- };
1064
- }
1065
- const topic = await resolveAccessControlAppResolvers().getProject(
1066
- ctx,
1067
- args.topicId
1068
- );
1069
- if (!topic) {
1070
- return {
1071
- hasAccess: false,
1072
- isAdmin: false,
1073
- isOwner: false,
1074
- isShared: false,
1075
- hasGrant: false,
1076
- isFirmVisible: false,
1077
- isExternalVisible: false,
1078
- isPublicVisible: false,
1079
- isTenantScopeMatch: false,
1080
- isWorkspaceScopeMatch: false,
1081
- isPrincipalExternal: false
1082
- };
1083
- }
1084
- const { principalContext, legacyUserId } = args;
1085
- const userIsAdmin = principalContext.isPlatformAdmin;
1086
- const isOwner = topic.ownerId === legacyUserId;
1087
- const isShared = (topic.sharedWith ?? []).includes(legacyUserId);
1088
- const principalIsExternal = await isExternalPrincipal(ctx, {
1089
- groupIds: principalContext.groupIds,
1090
- topicTenantId: topic.tenantId,
1091
- topicWorkspaceId: topic.workspaceId
1092
- });
1093
- const hasPrincipalGrantResult = await hasPrincipalGrant(ctx, {
1094
- topic,
1095
- principalId: principalContext.principalId,
1096
- principalIsExternal
1097
- });
1098
- const hasGroupGrantResult = await hasGroupGrant(ctx, {
1099
- topic,
1100
- groupIds: principalContext.groupIds
1101
- });
1102
- const hasGrant = isShared || hasPrincipalGrantResult || hasGroupGrantResult;
1103
- const legacyUnscoped = isLegacyUnscopedTopic(topic);
1104
- const tenantScopeMatch = isTopicInPrincipalTenant(
1105
- topic,
1106
- principalContext.tenantId
1107
- );
1108
- const workspaceScopeMatch = isTopicInPrincipalWorkspace(
1109
- topic,
1110
- principalContext.workspaceId
1111
- );
1112
- const isPublicVisible = topic.visibility === "public";
1113
- const isFirmVisible = topic.visibility === "firm" && !legacyUnscoped && tenantScopeMatch && workspaceScopeMatch && !principalIsExternal;
1114
- const hasScopedGrant = hasGrant && (legacyUnscoped || tenantScopeMatch && workspaceScopeMatch);
1115
- const isExternalVisible = topic.visibility === "external" && hasScopedGrant;
1116
- const hasAccess = userIsAdmin || isOwner || hasScopedGrant || isPublicVisible || isFirmVisible;
1117
- return {
1118
- hasAccess,
1119
- isAdmin: userIsAdmin,
1120
- isOwner,
1121
- isShared,
1122
- hasGrant,
1123
- isFirmVisible,
1124
- isExternalVisible,
1125
- isPublicVisible,
1126
- isTenantScopeMatch: tenantScopeMatch,
1127
- isWorkspaceScopeMatch: workspaceScopeMatch,
1128
- isPrincipalExternal: principalIsExternal
1129
- };
1130
- }
1131
- async function checkTopicAccessDetailed(ctx, topicId, userId) {
1132
- const principalContext = await resolvePrincipalContext(ctx, userId);
1133
- return evaluateTopicAccessDetailed(ctx, {
1134
- topicId,
1135
- legacyUserId: userId,
1136
- principalContext
1137
- });
1138
- }
1139
- async function checkTopicAccess(ctx, topicId, userId) {
1140
- const result = await checkTopicAccessDetailed(ctx, topicId, userId);
1141
- return result.hasAccess;
1142
- }
1143
- async function checkScopeAccess(ctx, scopeId, userId) {
1144
- try {
1145
- const topic = await ctx.db.get(scopeId);
1146
- if (topic && topic.name !== void 0 && topic.type !== void 0) {
1147
- return true;
1148
- }
1149
- } catch {
1150
- }
1151
- try {
1152
- return await checkTopicAccess(ctx, scopeId, userId);
1153
- } catch {
1154
- return false;
1155
- }
1156
- }
1157
- var checkProjectAccess = checkTopicAccess;
1158
-
1159
- // ../access-control/src/audience.ts
1160
- var AUDIENCE_CLASS_RANK = {
1161
- public: 0,
1162
- restricted_external: 1,
1163
- internal: 2
1164
- };
1165
- function normalizeKey(key) {
1166
- return (key ?? "").trim().toLowerCase().replace(/[^a-z0-9:_-]+/g, "_").replace(/_+/g, "_").replace(/^_+|_+$/g, "");
1167
- }
1168
- function normalizeAudienceKey(key) {
1169
- return normalizeKey(key);
1170
- }
1171
- function classFromAudienceKey(audienceKey, fallback = "internal") {
1172
- const key = normalizeKey(audienceKey);
1173
- if (!key) {
1174
- return fallback;
1175
- }
1176
- if (key === "internal") {
1177
- return "internal";
1178
- }
1179
- if (key === "public") {
1180
- return "public";
1181
- }
1182
- if (key === "lp" || key === "external" || key === "client" || key === "partner" || key === "portfolio" || key === "network" || key === "restricted_external") {
1183
- return "restricted_external";
1184
- }
1185
- return fallback;
1186
- }
1187
- function canAudienceClassAccess(viewerClass, resourceClass) {
1188
- return AUDIENCE_CLASS_RANK[viewerClass] >= AUDIENCE_CLASS_RANK[resourceClass];
1189
- }
1190
-
1191
- // ../access-control/src/audienceRegistry.ts
1192
- var DEFAULT_AUDIENCES = [
1193
- {
1194
- audienceKey: "internal",
1195
- audienceLabel: "Internal",
1196
- audienceClass: "internal"
1197
- },
1198
- {
1199
- audienceKey: "lp",
1200
- audienceLabel: "Limited Partners",
1201
- audienceClass: "restricted_external"
1202
- },
1203
- {
1204
- audienceKey: "public",
1205
- audienceLabel: "Public",
1206
- audienceClass: "public"
1207
- }
1208
- ];
1209
- var AUDIENCE_CLASS_PRIORITY = {
1210
- internal: 0,
1211
- restricted_external: 1,
1212
- public: 2
1213
- };
1214
- function normalizeRegistryRow(row) {
1215
- return {
1216
- audienceKey: normalizeAudienceKey(row.audienceKey),
1217
- audienceLabel: row.audienceLabel,
1218
- audienceClass: row.audienceClass,
1219
- workspaceId: row.workspaceId
1220
- };
1221
- }
1222
- function dedupeRegistryRows(rows) {
1223
- const byKey = /* @__PURE__ */ new Map();
1224
- for (const row of rows) {
1225
- const key = normalizeAudienceKey(row.audienceKey);
1226
- if (!key) {
1227
- continue;
1228
- }
1229
- const existing = byKey.get(key);
1230
- const isWorkspaceScoped = row.workspaceId !== void 0;
1231
- const existingWorkspaceScoped = existing?.workspaceId !== void 0;
1232
- if (!existing || isWorkspaceScoped && !existingWorkspaceScoped) {
1233
- byKey.set(key, {
1234
- ...row,
1235
- audienceKey: key
1236
- });
1237
- }
1238
- }
1239
- const normalized = [...byKey.values()];
1240
- normalized.sort((a, b) => {
1241
- const classDelta = AUDIENCE_CLASS_PRIORITY[a.audienceClass] - AUDIENCE_CLASS_PRIORITY[b.audienceClass];
1242
- if (classDelta !== 0) {
1243
- return classDelta;
1244
- }
1245
- return a.audienceKey.localeCompare(b.audienceKey);
1246
- });
1247
- return normalized;
1248
- }
1249
- async function queryRegistryRows(ctx, args) {
1250
- if (!args.tenantId) {
1251
- return [...DEFAULT_AUDIENCES];
1252
- }
1253
- const rows = await ctx.db.query("platformAudiences").withIndex("by_tenantId", (q) => q.eq("tenantId", args.tenantId)).collect();
1254
- const workspaceIdString = args.workspaceId ? String(args.workspaceId) : null;
1255
- const tenantScoped = rows.filter((row) => row.status === "active");
1256
- const applicable = tenantScoped.filter((row) => {
1257
- if (!row.workspaceId) {
1258
- return true;
1259
- }
1260
- if (!workspaceIdString) {
1261
- return false;
1262
- }
1263
- return String(row.workspaceId) === workspaceIdString;
1264
- });
1265
- return dedupeRegistryRows([
1266
- ...DEFAULT_AUDIENCES,
1267
- ...applicable.map(
1268
- (row) => normalizeRegistryRow({
1269
- audienceKey: row.audienceKey,
1270
- audienceLabel: row.audienceLabel,
1271
- audienceClass: row.audienceClass,
1272
- workspaceId: row.workspaceId
1273
- })
1274
- )
1275
- ]);
1276
- }
1277
- async function listAudienceRegistryRows(ctx, args) {
1278
- return queryRegistryRows(ctx, args);
1279
- }
1280
-
1281
- // ../access-control/src/auth.ts
1282
- async function getCurrentUserId(ctx) {
1283
- const identity = await ctx.auth.getUserIdentity();
1284
- return identity?.subject ?? null;
1285
- }
1286
-
1287
- // ../../packages/contracts/src/schema-helpers/enumValidation.ts
1288
- var BUILTIN_ENUM_FALLBACK = {
1289
- topic_type: /* @__PURE__ */ new Set([
1290
- "domain",
1291
- "theme",
1292
- "deal",
1293
- "strategy",
1294
- "constitution",
1295
- "project",
1296
- "portfolio",
1297
- "architecture",
1298
- "capability",
1299
- "runtime",
1300
- "interface",
1301
- "governance",
1302
- "operations",
1303
- "security",
1304
- "data"
1305
- ]),
1306
- branch_schema: /* @__PURE__ */ new Set(["pillar", "track", "dimension", "axis", "phase"]),
1307
- lens_perspective_type: /* @__PURE__ */ new Set([
1308
- "investigation",
1309
- "monitoring",
1310
- "analysis",
1311
- "comparison",
1312
- "taxonomy"
1313
- ]),
1314
- belief_type: /* @__PURE__ */ new Set([
1315
- "belief",
1316
- "hypothesis",
1317
- "principle",
1318
- "invariant",
1319
- "assumption",
1320
- "tenet",
1321
- "prior",
1322
- "preference",
1323
- "goal",
1324
- "forecast",
1325
- "decision",
1326
- "constraint",
1327
- "tradeoff",
1328
- "policy",
1329
- "implementation_choice",
1330
- "implementation_decision",
1331
- "interface_contract",
1332
- "migration_state",
1333
- "code_pattern",
1334
- "deprecation_notice"
1335
- ]),
1336
- edge_type: /* @__PURE__ */ new Set([
1337
- "supports",
1338
- "informs",
1339
- "depends_on",
1340
- "derived_from",
1341
- "contains",
1342
- "tests",
1343
- "supersedes",
1344
- "responds_to",
1345
- "belongs_to",
1346
- "relates_to_thesis",
1347
- "works_at",
1348
- "invested_in",
1349
- "competes_with",
1350
- "participates_in",
1351
- "founded_by",
1352
- "evaluates",
1353
- "performs",
1354
- "function_in",
1355
- "impacts",
1356
- "raised_from",
1357
- "mentioned_in",
1358
- "perspective_on",
1359
- "plays_theme"
1360
- ]),
1361
- worktree_type: /* @__PURE__ */ new Set([
1362
- "belief_test",
1363
- "existential",
1364
- "contradiction",
1365
- "refinement",
1366
- "coverage",
1367
- "discovery",
1368
- "clarification",
1369
- "confirmation"
1370
- ]),
1371
- worktree_phase: /* @__PURE__ */ new Set([
1372
- "cluster_mapping",
1373
- "hypothesis_formation",
1374
- "question_generation",
1375
- "evidence_collection",
1376
- "synthesis",
1377
- "decision",
1378
- "retrospective"
1379
- ]),
1380
- activity_type: /* @__PURE__ */ new Set([
1381
- "create",
1382
- "update",
1383
- "review",
1384
- "merge",
1385
- "archive",
1386
- "comment",
1387
- "status_change",
1388
- "evidence_added",
1389
- "question_added"
1390
- ])
1391
- };
1392
- function normalizeEnumValue(value) {
1393
- return value.trim().toLowerCase();
1394
- }
1395
- async function validateSchemaEnumValue(_ctx, args) {
1396
- const normalized = normalizeEnumValue(args.value);
1397
- if (!normalized) {
1398
- return { valid: false, source: "none" };
1399
- }
1400
- if (BUILTIN_ENUM_FALLBACK[args.category].has(normalized)) {
1401
- return { valid: true, source: "builtin" };
1402
- }
1403
- return { valid: false, source: "none" };
1404
- }
1405
- async function assertSchemaEnumValue(ctx, args) {
1406
- if (typeof args.value !== "string") {
1407
- return;
1408
- }
1409
- const normalized = normalizeEnumValue(args.value);
1410
- if (!normalized) {
1411
- return;
1412
- }
1413
- const validation = await validateSchemaEnumValue(ctx, {
1414
- category: args.category,
1415
- value: normalized,
1416
- tenantId: args.tenantId
1417
- });
1418
- if (!validation.valid) {
1419
- const tenantHint = args.tenantId ? ` for tenant ${args.tenantId}` : "";
1420
- throw new Error(
1421
- `[${args.context}] Invalid value "${normalized}" for category "${args.category}"${tenantHint}. Add it to the contracts schema enum manifest before use.`
1422
- );
1423
- }
1424
- return normalized;
1425
- }
1426
- var permissiveReturn = v.optional(v.any());
1427
- var looseJsonObject = v.record(v.string(), v.any());
1428
- var looseJsonArray = v.array(v.any());
1429
- v.union(
1430
- v.string(),
1431
- v.number(),
1432
- v.boolean(),
1433
- v.null(),
1434
- looseJsonObject,
1435
- looseJsonArray
1436
- );
1437
-
1438
14
  // src/beliefLifecycle.ts
1439
15
  var BELIEF_STATUS_VALUES = [
1440
16
  "assumption",
@@ -1526,7 +102,7 @@ function promoteBeliefStatusAfterScoring(status, opts) {
1526
102
  }
1527
103
  return status === "fact" ? "fact" : "belief";
1528
104
  }
1529
- var api2 = anyApi;
105
+ var api = anyApi;
1530
106
  componentsGeneric();
1531
107
  var internal = anyApi;
1532
108
  var internalMutation = internalMutationGeneric;
@@ -1544,8 +120,6 @@ var containsPropagationSpec = {
1544
120
  operator: () => null,
1545
121
  description: "Structural containment only. Traversed for explicit semantics, but it never propagates opinions."
1546
122
  };
1547
-
1548
- // src/edges/utils.ts
1549
123
  function readEdgeMetadata(edge) {
1550
124
  return {
1551
125
  constraint: edge.constraint ?? void 0,
@@ -1595,9 +169,7 @@ function propagateNegativeSupportWithMetadata(sourceOpinion, targetOpinion, edge
1595
169
  readEdgeMetadata(edge)
1596
170
  );
1597
171
  }
1598
- function propagateNegativeInform(sourceOpinion, targetOpinion, edgeWeight) {
1599
- return applyNegativeEvidence(sourceOpinion, targetOpinion, edgeWeight);
1600
- }
172
+ var propagateNegativeInform = applyNegativeEvidence;
1601
173
 
1602
174
  // src/edges/contradicts.ts
1603
175
  var contradictsPropagationSpec = {
@@ -1622,8 +194,6 @@ var contradictsPropagationSpec = {
1622
194
  },
1623
195
  description: "Legacy contradiction edges move negative pressure in either direction, but never beyond one hop."
1624
196
  };
1625
-
1626
- // src/edges/dependsOn.ts
1627
197
  var dependsOnPropagationSpec = {
1628
198
  edgeType: "depends_on",
1629
199
  direction: "incoming",
@@ -1639,8 +209,18 @@ var dependsOnPropagationSpec = {
1639
209
  if (metadata.conditionalA && metadata.conditionalNotA) {
1640
210
  const deducedOpinion = conditionalDeduction(
1641
211
  dampedSource,
1642
- metadata.conditionalA,
1643
- metadata.conditionalNotA,
212
+ mkOpinion(
213
+ metadata.conditionalA.b,
214
+ metadata.conditionalA.d,
215
+ metadata.conditionalA.u,
216
+ metadata.conditionalA.a
217
+ ),
218
+ mkOpinion(
219
+ metadata.conditionalNotA.b,
220
+ metadata.conditionalNotA.d,
221
+ metadata.conditionalNotA.u,
222
+ metadata.conditionalNotA.a
223
+ ),
1644
224
  targetOpinion.a
1645
225
  );
1646
226
  return annotateRationale(
@@ -1813,69 +393,30 @@ function getTraversalDirections(direction) {
1813
393
  return ["outgoing", "incoming"];
1814
394
  }
1815
395
 
1816
- // ../../packages/contracts/src/schema-helpers/spine/tables/epistemicNodes.ts
1817
- var NODE_TYPES = [
1818
- "decision",
1819
- "belief",
1820
- "question",
1821
- "theme",
1822
- "deal",
1823
- "topic",
1824
- "claim",
1825
- "evidence",
1826
- "synthesis",
1827
- "answer",
1828
- "atomic_fact",
1829
- "excerpt",
1830
- "source",
1831
- "company",
1832
- "person",
1833
- "investor",
1834
- "function",
1835
- "value_chain"
1836
- ];
1837
- function isNodeType(value) {
1838
- return NODE_TYPES.includes(value);
396
+ // src/debug.ts
397
+ function isGraphPrimitiveDebugEnabled() {
398
+ const env = globalThis.process?.env;
399
+ return env?.LUCERN_COMPAT_FALLBACK_DEBUG === "1" || env?.LUCERN_GRAPH_DEBUG === "1";
1839
400
  }
1840
- function getLayerForNodeType(type) {
1841
- switch (type) {
1842
- case "decision":
1843
- return "L4";
1844
- case "belief":
1845
- case "question":
1846
- case "theme":
1847
- case "deal":
1848
- return "L3";
1849
- case "claim":
1850
- case "evidence":
1851
- case "synthesis":
1852
- case "answer":
1853
- return "L2";
1854
- case "atomic_fact":
1855
- case "excerpt":
1856
- case "source":
1857
- return "L1";
1858
- case "topic":
1859
- return "organizational";
1860
- case "company":
1861
- case "person":
1862
- case "investor":
1863
- case "function":
1864
- case "value_chain":
1865
- return "ontological";
401
+ function debugGraphPrimitiveFallback(message, context) {
402
+ if (!isGraphPrimitiveDebugEnabled()) {
403
+ return;
1866
404
  }
405
+ console.debug(message, context ?? {});
1867
406
  }
1868
- var LEGACY_SCOPE_FIELD2 = "graphScopeProjectId";
407
+
408
+ // src/topicScope.ts
409
+ var LEGACY_SCOPE_FIELD = "graphScopeProjectId";
1869
410
  function asMappedProjectId(topic) {
1870
411
  if (!topic) {
1871
412
  return;
1872
413
  }
1873
- const directLegacyProjectId = normalizeScopeValue(topic[LEGACY_SCOPE_FIELD2]);
414
+ const directLegacyProjectId = normalizeScopeValue(topic[LEGACY_SCOPE_FIELD]);
1874
415
  if (directLegacyProjectId) {
1875
416
  return directLegacyProjectId;
1876
417
  }
1877
418
  const metadata = topic.metadata || {};
1878
- const candidate = metadata[LEGACY_SCOPE_FIELD2] || metadata.legacyProjectId || metadata.projectId || metadata.scopeProjectId;
419
+ const candidate = metadata[LEGACY_SCOPE_FIELD] || metadata.legacyProjectId || metadata.projectId || metadata.scopeProjectId;
1879
420
  return candidate ? candidate : void 0;
1880
421
  }
1881
422
  function normalizeScopeValue(value) {
@@ -1904,9 +445,16 @@ async function findTopicsByScopeAlias(ctx, scopeId) {
1904
445
  try {
1905
446
  return await ctx.db.query("topics").withIndex(
1906
447
  "by_graph_scope_project",
1907
- (q) => q.eq(LEGACY_SCOPE_FIELD2, scopeId)
448
+ (q) => q.eq(LEGACY_SCOPE_FIELD, scopeId)
1908
449
  ).collect();
1909
- } catch {
450
+ } catch (error) {
451
+ debugGraphPrimitiveFallback(
452
+ "[topicScope] Failed to resolve scope alias via index",
453
+ {
454
+ error,
455
+ scopeId
456
+ }
457
+ );
1910
458
  const topics = await ctx.db.query("topics").collect();
1911
459
  return topics.filter((topic) => {
1912
460
  const normalizedGlobalId = normalizeScopeValue(topic.globalId);
@@ -1920,10 +468,17 @@ async function tryResolveHostTopicById(ctx, topicId) {
1920
468
  return null;
1921
469
  }
1922
470
  try {
1923
- return await ctx.runQuery(api2.topics.get, {
471
+ return await ctx.runQuery(api.topics.get, {
1924
472
  id: topicId
1925
473
  }) ?? null;
1926
- } catch {
474
+ } catch (error) {
475
+ debugGraphPrimitiveFallback(
476
+ "[topicScope] Failed to resolve topic by host query",
477
+ {
478
+ error,
479
+ topicId
480
+ }
481
+ );
1927
482
  return null;
1928
483
  }
1929
484
  }
@@ -1932,10 +487,17 @@ async function tryResolveHostTopicByLegacyScope(ctx, legacyScopeId) {
1932
487
  return null;
1933
488
  }
1934
489
  try {
1935
- return await ctx.runQuery(api2.topics.getByLegacyScopeId, {
490
+ return await ctx.runQuery(api.topics.getByLegacyScopeId, {
1936
491
  projectId: legacyScopeId
1937
492
  }) ?? null;
1938
- } catch {
493
+ } catch (error) {
494
+ debugGraphPrimitiveFallback(
495
+ "[topicScope] Failed to resolve topic by legacy scope",
496
+ {
497
+ error,
498
+ legacyScopeId
499
+ }
500
+ );
1939
501
  return null;
1940
502
  }
1941
503
  }
@@ -1964,8 +526,17 @@ async function resolveTopicProjectScope(ctx, args) {
1964
526
  if (args.topicId) {
1965
527
  let topic = null;
1966
528
  try {
1967
- topic = await ctx.db.get(args.topicId);
1968
- } catch {
529
+ topic = await ctx.db.get(
530
+ args.topicId
531
+ );
532
+ } catch (error) {
533
+ debugGraphPrimitiveFallback(
534
+ "[topicScope] Failed to load topic by direct id",
535
+ {
536
+ error,
537
+ topicId: args.topicId
538
+ }
539
+ );
1969
540
  }
1970
541
  if (!topic) {
1971
542
  topic = await tryResolveHostTopicById(ctx, String(args.topicId));
@@ -2002,7 +573,14 @@ async function resolveTopicProjectScope(ctx, args) {
2002
573
  directTopic = await ctx.db.get(
2003
574
  args.projectId
2004
575
  );
2005
- } catch {
576
+ } catch (error) {
577
+ debugGraphPrimitiveFallback(
578
+ "[topicScope] Failed to load direct project topic",
579
+ {
580
+ error,
581
+ projectId: args.projectId
582
+ }
583
+ );
2006
584
  }
2007
585
  if (directTopic) {
2008
586
  const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);
@@ -2209,16 +787,17 @@ function resolveTraversalTargetNodeId(edge, direction) {
2209
787
  }
2210
788
  function readNodeOpinion(node) {
2211
789
  const metadata = node.metadata ?? {};
2212
- return readOpinionFromRecord(
2213
- {
790
+ try {
791
+ return readOpinionFromRecord({
2214
792
  ...metadata,
2215
793
  opinion_b: node.opinion_b,
2216
794
  opinion_d: node.opinion_d,
2217
795
  opinion_u: node.opinion_u,
2218
796
  opinion_a: node.opinion_a
2219
- },
2220
- { b: 0, d: 0, u: 1, a: 0.5 }
2221
- );
797
+ });
798
+ } catch {
799
+ return mkOpinion(0, 0, 1, 0.5);
800
+ }
2222
801
  }
2223
802
  async function collectConfidencePropagationDispatches(args) {
2224
803
  const dispatchesByTargetId = /* @__PURE__ */ new Map();
@@ -2287,14 +866,20 @@ async function collectConfidencePropagationDispatches(args) {
2287
866
  if (!result || !hasProjectedOpinionChanged(targetOpinion, result.opinion)) {
2288
867
  continue;
2289
868
  }
2290
- opinionCache.set(cacheKey, result.opinion);
869
+ const projectedOpinion = mkOpinion(
870
+ result.opinion.b,
871
+ result.opinion.d,
872
+ result.opinion.u,
873
+ result.opinion.a
874
+ );
875
+ opinionCache.set(cacheKey, projectedOpinion);
2291
876
  const existingDispatch = dispatchesByTargetId.get(cacheKey);
2292
877
  dispatchesByTargetId.set(cacheKey, {
2293
878
  targetNodeId,
2294
879
  edgeType: spec.edgeType,
2295
880
  traversedDirection: direction,
2296
881
  weight: edge.weight ?? 1,
2297
- opinion: result.opinion,
882
+ opinion: projectedOpinion,
2298
883
  operator: result.operator,
2299
884
  rationale: existingDispatch ? `${existingDispatch.rationale}; ${result.rationale}` : result.rationale,
2300
885
  hop: nextHop
@@ -2302,7 +887,7 @@ async function collectConfidencePropagationDispatches(args) {
2302
887
  if (canContinueTransitively(spec, nextHop)) {
2303
888
  queue.push({
2304
889
  nodeId: targetNodeId,
2305
- opinion: result.opinion,
890
+ opinion: projectedOpinion,
2306
891
  hop: nextHop,
2307
892
  visitedNodeIds: /* @__PURE__ */ new Set([
2308
893
  ...state.visitedNodeIds,
@@ -2339,7 +924,15 @@ async function scheduleEmbeddingGeneration(args) {
2339
924
  confidence: args.confidence
2340
925
  }
2341
926
  );
2342
- } catch {
927
+ } catch (error) {
928
+ debugGraphPrimitiveFallback(
929
+ "[embeddingTrigger] Failed to schedule embedding generation",
930
+ {
931
+ error,
932
+ nodeId: String(args.nodeId),
933
+ nodeType: args.nodeType
934
+ }
935
+ );
2343
936
  }
2344
937
  }
2345
938
 
@@ -2417,96 +1010,125 @@ async function getQuestionsAnsweredByEvidence(ctx, evidenceId) {
2417
1010
  }
2418
1011
 
2419
1012
  // src/topicProjectOverlay.ts
2420
- var LEGACY_SCOPE_FIELD3 = "graphScopeProjectId";
2421
- function readNonEmptyString2(value) {
1013
+ var LEGACY_SCOPE_FIELD2 = "graphScopeProjectId";
1014
+ function readNonEmptyString(value) {
2422
1015
  if (typeof value !== "string") {
2423
1016
  return;
2424
1017
  }
2425
1018
  const normalized = value.trim();
2426
1019
  return normalized.length > 0 ? normalized : void 0;
2427
1020
  }
2428
- function readStringArray2(value) {
1021
+ function readStringArray(value) {
2429
1022
  if (!Array.isArray(value)) {
2430
1023
  return [];
2431
1024
  }
2432
- return value.map((entry) => readNonEmptyString2(entry)).filter((entry) => Boolean(entry));
1025
+ return value.map((entry) => readNonEmptyString(entry)).filter((entry) => Boolean(entry));
2433
1026
  }
2434
- function readMetadata2(topic) {
1027
+ function readMetadata(topic) {
2435
1028
  return topic.metadata && typeof topic.metadata === "object" ? topic.metadata : {};
2436
1029
  }
2437
- function readLegacyProjectId2(value) {
1030
+ function readLegacyProjectId(value) {
2438
1031
  if (!value) {
2439
1032
  return;
2440
1033
  }
2441
- return readNonEmptyString2(value[LEGACY_SCOPE_FIELD3]);
1034
+ return readNonEmptyString(value[LEGACY_SCOPE_FIELD2]);
2442
1035
  }
2443
- function coerceVisibility2(value) {
1036
+ function coerceVisibility(value) {
2444
1037
  return value === "private" || value === "team" || value === "firm" || value === "external" || value === "public" ? value : void 0;
2445
1038
  }
2446
- function coerceStatus2(value) {
1039
+ function coerceStatus(value) {
2447
1040
  return value === "active" || value === "archived" || value === "watching" ? value : void 0;
2448
1041
  }
2449
- function mapProjectType2(topic, metadata) {
2450
- const explicit = readNonEmptyString2(metadata.projectType);
1042
+ function mapProjectType(topic, metadata) {
1043
+ const explicit = readNonEmptyString(metadata.projectType);
2451
1044
  if (explicit) {
2452
1045
  return explicit;
2453
1046
  }
2454
1047
  if (topic.type === "theme") {
2455
1048
  return "thematic";
2456
1049
  }
2457
- return readNonEmptyString2(topic.type) || "general";
1050
+ return readNonEmptyString(topic.type) || "general";
2458
1051
  }
2459
- function isProjectLikeTopic2(topic) {
2460
- const metadata = readMetadata2(topic);
2461
- return topic.type === "theme" || topic.type === "thematic" || topic.type === "deal" || topic.type === "monitoring" || readLegacyProjectId2(topic) !== void 0 || readNonEmptyString2(metadata.projectType) !== void 0;
1052
+ function isProjectLikeTopic(topic) {
1053
+ const metadata = readMetadata(topic);
1054
+ return topic.type === "theme" || topic.type === "thematic" || topic.type === "deal" || topic.type === "monitoring" || readLegacyProjectId(topic) !== void 0 || readNonEmptyString(metadata.projectType) !== void 0;
2462
1055
  }
2463
1056
  function isMissingLucernChildComponentError(error) {
2464
- const message = error instanceof Error ? error.message : String(error);
1057
+ const message = getErrorMessage(error);
2465
1058
  return message.includes(
2466
1059
  'Child component ComponentName(Identifier("lucern")) not found'
2467
1060
  ) || message.includes("Child component") && message.includes("lucern") && message.includes("not found");
2468
1061
  }
2469
- async function resolveTopicDoc2(ctx, scopeId) {
1062
+ function getErrorMessage(error) {
1063
+ if (error instanceof Error) {
1064
+ return error.message;
1065
+ }
1066
+ if (typeof error === "object" && error !== null && "message" in error && typeof error.message === "string") {
1067
+ return error.message;
1068
+ }
1069
+ return "unknown error";
1070
+ }
1071
+ async function resolveTopicDoc(ctx, scopeId) {
2470
1072
  if (ctx?.db && typeof ctx.db.get === "function") {
2471
1073
  try {
2472
- const directTopic = await ctx.db.get(scopeId);
1074
+ const directTopic = await ctx.db.get(
1075
+ scopeId
1076
+ );
2473
1077
  if (directTopic) {
2474
1078
  return directTopic;
2475
1079
  }
2476
- } catch {
1080
+ } catch (error) {
1081
+ debugGraphPrimitiveFallback(
1082
+ "[topicProjectOverlay] Failed to resolve topic by direct ID",
1083
+ {
1084
+ error,
1085
+ scopeId
1086
+ }
1087
+ );
2477
1088
  }
2478
1089
  }
2479
1090
  if (typeof ctx.runQuery !== "function") {
2480
1091
  return null;
2481
1092
  }
2482
1093
  try {
2483
- const topic = await ctx.runQuery(api2.topics.get, {
1094
+ const topic = await ctx.runQuery(api.topics.get, {
2484
1095
  id: String(scopeId)
2485
1096
  });
2486
1097
  if (topic?.name !== void 0 && topic?.type !== void 0) {
2487
1098
  return topic;
2488
1099
  }
2489
- } catch {
1100
+ } catch (error) {
1101
+ debugGraphPrimitiveFallback(
1102
+ "[topicProjectOverlay] Failed to resolve topic by ID query",
1103
+ {
1104
+ error,
1105
+ scopeId
1106
+ }
1107
+ );
2490
1108
  }
2491
1109
  try {
2492
- const topic = await ctx.runQuery(api2.topics.getByLegacyScopeId, {
1110
+ const topic = await ctx.runQuery(api.topics.getByLegacyScopeId, {
2493
1111
  projectId: String(scopeId)
2494
1112
  });
2495
1113
  if (topic?.name !== void 0 && topic?.type !== void 0) {
2496
1114
  return topic;
2497
1115
  }
2498
- } catch {
1116
+ } catch (error) {
1117
+ debugGraphPrimitiveFallback(
1118
+ "[topicProjectOverlay] Failed to resolve topic by legacy scope ID",
1119
+ { error, scopeId }
1120
+ );
2499
1121
  }
2500
1122
  return null;
2501
1123
  }
2502
- function materializeTopicProjectOverlay2(topic, idMode = "legacy") {
2503
- const metadata = readMetadata2(topic);
1124
+ function materializeTopicProjectOverlay(topic, idMode = "legacy") {
1125
+ const metadata = readMetadata(topic);
2504
1126
  const topicId = String(topic._id);
2505
- const legacyProjectId = readLegacyProjectId2(topic) || readLegacyProjectId2(metadata) || readNonEmptyString2(metadata.legacyProjectId);
1127
+ const legacyProjectId = readLegacyProjectId(topic) || readLegacyProjectId(metadata) || readNonEmptyString(metadata.legacyProjectId);
2506
1128
  const storageProjectId = legacyProjectId || topicId;
2507
1129
  const outwardId = idMode === "topic" ? topicId : storageProjectId;
2508
- const visibility = coerceVisibility2(topic.visibility) || coerceVisibility2(metadata.visibility) || "private";
2509
- const status = coerceStatus2(topic.status) || coerceStatus2(metadata.status) || "active";
1130
+ const visibility = coerceVisibility(topic.visibility) || coerceVisibility(metadata.visibility) || "private";
1131
+ const status = coerceStatus(topic.status) || coerceStatus(metadata.status) || "active";
2510
1132
  const createdAt = typeof topic.createdAt === "number" ? topic.createdAt : typeof topic._creationTime === "number" ? topic._creationTime : 0;
2511
1133
  const updatedAt = typeof topic.updatedAt === "number" ? topic.updatedAt : typeof metadata.updatedAt === "number" ? metadata.updatedAt : createdAt;
2512
1134
  return {
@@ -2516,16 +1138,16 @@ function materializeTopicProjectOverlay2(topic, idMode = "legacy") {
2516
1138
  topicId,
2517
1139
  storageProjectId,
2518
1140
  legacyProjectId,
2519
- name: readNonEmptyString2(topic.name) || "Untitled Theme",
2520
- type: mapProjectType2(topic, metadata),
2521
- description: readNonEmptyString2(topic.description),
2522
- ownerId: readNonEmptyString2(metadata.ownerId) || readNonEmptyString2(topic.createdBy) || "system",
2523
- sharedWith: readStringArray2(metadata.sharedWith),
1141
+ name: readNonEmptyString(topic.name) || "Untitled Theme",
1142
+ type: mapProjectType(topic, metadata),
1143
+ description: readNonEmptyString(topic.description),
1144
+ ownerId: readNonEmptyString(metadata.ownerId) || readNonEmptyString(topic.createdBy) || "system",
1145
+ sharedWith: readStringArray(metadata.sharedWith),
2524
1146
  visibility,
2525
- tenantId: readNonEmptyString2(topic.tenantId) || readNonEmptyString2(metadata.tenantId),
2526
- workspaceId: readNonEmptyString2(topic.workspaceId) || readNonEmptyString2(metadata.workspaceId),
1147
+ tenantId: readNonEmptyString(topic.tenantId) || readNonEmptyString(metadata.tenantId),
1148
+ workspaceId: readNonEmptyString(topic.workspaceId) || readNonEmptyString(metadata.workspaceId),
2527
1149
  status,
2528
- tags: readStringArray2(metadata.tags),
1150
+ tags: readStringArray(metadata.tags),
2529
1151
  chatCount: typeof metadata.chatCount === "number" ? metadata.chatCount : 0,
2530
1152
  artifactCount: typeof metadata.artifactCount === "number" ? metadata.artifactCount : 0,
2531
1153
  lastActivityAt: typeof metadata.lastActivityAt === "number" ? metadata.lastActivityAt : updatedAt,
@@ -2534,38 +1156,42 @@ function materializeTopicProjectOverlay2(topic, idMode = "legacy") {
2534
1156
  updatedAt
2535
1157
  };
2536
1158
  }
2537
- async function resolveTopicProjectOverlay2(ctx, scopeId, options = {}) {
2538
- const topic = await resolveTopicDoc2(ctx, scopeId);
1159
+ async function resolveTopicProjectOverlay(ctx, scopeId, options = {}) {
1160
+ const topic = await resolveTopicDoc(ctx, scopeId);
2539
1161
  if (!topic) {
2540
1162
  return null;
2541
1163
  }
2542
- if (options.projectLikeOnly !== false && !isProjectLikeTopic2(topic)) {
1164
+ if (options.projectLikeOnly !== false && !isProjectLikeTopic(topic)) {
2543
1165
  return null;
2544
1166
  }
2545
- return materializeTopicProjectOverlay2(topic, options.idMode);
1167
+ return materializeTopicProjectOverlay(topic, options.idMode);
2546
1168
  }
2547
- async function listTopicProjectOverlays2(ctx, options = {}) {
1169
+ async function listTopicProjectOverlays(ctx, options = {}) {
2548
1170
  let allTopics = [];
2549
1171
  if (ctx?.db?.query && typeof ctx.db.query === "function") {
2550
1172
  try {
2551
1173
  allTopics = await ctx.db.query("topics").collect();
2552
- } catch {
1174
+ } catch (error) {
1175
+ debugGraphPrimitiveFallback(
1176
+ "[topicProjectOverlay] Failed to read topics table; falling back to API",
1177
+ { error }
1178
+ );
2553
1179
  allTopics = [];
2554
1180
  }
2555
1181
  }
2556
1182
  if (allTopics.length === 0 && typeof ctx.runQuery === "function") {
2557
- allTopics = (await ctx.runQuery(api2.topics.list, {}) ?? []) || [];
1183
+ allTopics = (await ctx.runQuery(api.topics.list, {}) ?? []) || [];
2558
1184
  }
2559
1185
  return allTopics.filter(
2560
- (topic) => options.projectLikeOnly === false || isProjectLikeTopic2(topic)
2561
- ).map((topic) => materializeTopicProjectOverlay2(topic, options.idMode));
1186
+ (topic) => options.projectLikeOnly === false || isProjectLikeTopic(topic)
1187
+ ).map((topic) => materializeTopicProjectOverlay(topic, options.idMode));
2562
1188
  }
2563
1189
  async function patchTopicProjectOverlay(ctx, scopeId, value) {
2564
- const topic = await resolveTopicDoc2(ctx, scopeId);
1190
+ const topic = await resolveTopicDoc(ctx, scopeId);
2565
1191
  if (!topic) {
2566
1192
  return null;
2567
1193
  }
2568
- const nextMetadata = { ...readMetadata2(topic) };
1194
+ const nextMetadata = { ...readMetadata(topic) };
2569
1195
  const patch = {};
2570
1196
  const topicUpdateArgs = {
2571
1197
  id: String(topic._id)
@@ -2590,7 +1216,7 @@ async function patchTopicProjectOverlay(ctx, scopeId, value) {
2590
1216
  `patchTopicProjectOverlay cannot mutate ${key} via component-owned topics`
2591
1217
  );
2592
1218
  case "status": {
2593
- const status = coerceStatus2(rawValue);
1219
+ const status = coerceStatus(rawValue);
2594
1220
  if (status) {
2595
1221
  patch.status = status;
2596
1222
  topicUpdateArgs.status = status;
@@ -2598,7 +1224,7 @@ async function patchTopicProjectOverlay(ctx, scopeId, value) {
2598
1224
  break;
2599
1225
  }
2600
1226
  case "visibility": {
2601
- const visibility = coerceVisibility2(rawValue);
1227
+ const visibility = coerceVisibility(rawValue);
2602
1228
  if (visibility) {
2603
1229
  patch.visibility = visibility;
2604
1230
  topicUpdateArgs.visibility = visibility;
@@ -2606,7 +1232,7 @@ async function patchTopicProjectOverlay(ctx, scopeId, value) {
2606
1232
  break;
2607
1233
  }
2608
1234
  case "type": {
2609
- const projectType = readNonEmptyString2(rawValue);
1235
+ const projectType = readNonEmptyString(rawValue);
2610
1236
  if (projectType) {
2611
1237
  nextMetadata.projectType = projectType;
2612
1238
  } else {
@@ -2630,7 +1256,7 @@ async function patchTopicProjectOverlay(ctx, scopeId, value) {
2630
1256
  topicUpdateArgs.metadata = nextMetadata;
2631
1257
  if (typeof ctx.runMutation === "function") {
2632
1258
  try {
2633
- await ctx.runMutation(api2.topics.update, topicUpdateArgs);
1259
+ await ctx.runMutation(api.topics.update, topicUpdateArgs);
2634
1260
  } catch (error) {
2635
1261
  if (!isMissingLucernChildComponentError(error) || !ctx?.db || typeof ctx.db.patch !== "function") {
2636
1262
  throw error;
@@ -2644,19 +1270,28 @@ async function patchTopicProjectOverlay(ctx, scopeId, value) {
2644
1270
  "Cannot patch topic without component adapter (ctx.runMutation unavailable)"
2645
1271
  );
2646
1272
  }
2647
- return materializeTopicProjectOverlay2(
2648
- {
2649
- ...topic,
2650
- ...patch,
2651
- metadata: nextMetadata
2652
- }
2653
- );
1273
+ return materializeTopicProjectOverlay({
1274
+ ...topic,
1275
+ ...patch,
1276
+ metadata: nextMetadata
1277
+ });
2654
1278
  }
2655
1279
 
2656
1280
  // src/resolvers.ts
2657
1281
  function isMissingLucernChildComponentError2(error) {
2658
- const message = error instanceof Error ? error.message : String(error);
2659
- return message.includes('Child component ComponentName(Identifier("lucern")) not found') || message.includes("Child component") && message.includes("lucern") && message.includes("not found");
1282
+ const message = getErrorMessage2(error);
1283
+ return message.includes(
1284
+ 'Child component ComponentName(Identifier("lucern")) not found'
1285
+ ) || message.includes("Child component") && message.includes("lucern") && message.includes("not found");
1286
+ }
1287
+ function getErrorMessage2(error) {
1288
+ if (error instanceof Error) {
1289
+ return error.message;
1290
+ }
1291
+ if (typeof error === "object" && error !== null && "message" in error && typeof error.message === "string") {
1292
+ return error.message;
1293
+ }
1294
+ return "unknown error";
2660
1295
  }
2661
1296
  function isAdvisoryTopicPatch(value) {
2662
1297
  const advisoryKeys = /* @__PURE__ */ new Set(["lastActivityAt", "updatedAt"]);
@@ -2670,39 +1305,34 @@ async function patchProjectWithTolerance(ctx, projectId, value) {
2670
1305
  if (!isAdvisoryTopicPatch(value) || !isMissingLucernChildComponentError2(error)) {
2671
1306
  throw error;
2672
1307
  }
2673
- console.warn("[lucern graph-primitives] Non-fatal advisory topic patch failure", {
2674
- projectId,
2675
- keys: Object.keys(value),
2676
- error: error instanceof Error ? error.message : error
2677
- });
1308
+ console.warn(
1309
+ "[lucern graph-primitives] Non-fatal advisory topic patch failure",
1310
+ {
1311
+ projectId,
1312
+ keys: Object.keys(value),
1313
+ error: getErrorMessage2(error)
1314
+ }
1315
+ );
2678
1316
  }
2679
1317
  }
2680
- function defaultResolvers2() {
1318
+ function defaultResolvers() {
2681
1319
  return {
2682
- async getProject(ctx, projectId) {
2683
- return await resolveTopicProjectOverlay2(ctx, projectId, {
2684
- idMode: "legacy",
2685
- projectLikeOnly: false
2686
- });
2687
- },
2688
- async patchProject(ctx, projectId, value) {
2689
- await patchProjectWithTolerance(ctx, projectId, value);
2690
- },
2691
- async listTopics(ctx) {
2692
- return await listTopicProjectOverlays2(ctx, {
2693
- idMode: "legacy"
2694
- });
2695
- },
2696
- async getFinalArtifact(ctx, artifactId) {
2697
- return await ctx.db.get(artifactId);
2698
- }
1320
+ getProject: (ctx, projectId) => resolveTopicProjectOverlay(ctx, projectId, {
1321
+ idMode: "legacy",
1322
+ projectLikeOnly: false
1323
+ }),
1324
+ patchProject: (ctx, projectId, value) => patchProjectWithTolerance(ctx, projectId, value),
1325
+ listTopics: (ctx) => listTopicProjectOverlays(ctx, {
1326
+ idMode: "legacy"
1327
+ }),
1328
+ getFinalArtifact: (ctx, artifactId) => ctx.db.get(artifactId)
2699
1329
  };
2700
1330
  }
2701
- var resolverOverrides2 = {};
1331
+ var resolverOverrides = {};
2702
1332
  function resolveGraphPrimitivesAppResolvers(_ctx) {
2703
1333
  return {
2704
- ...defaultResolvers2(),
2705
- ...resolverOverrides2
1334
+ ...defaultResolvers(),
1335
+ ...resolverOverrides
2706
1336
  };
2707
1337
  }
2708
1338
 
@@ -2727,7 +1357,7 @@ function throwStructuredMutationError(args) {
2727
1357
  function readFiniteNumber(value) {
2728
1358
  return typeof value === "number" && Number.isFinite(value) ? value : void 0;
2729
1359
  }
2730
- function clamp012(value) {
1360
+ function clamp01(value) {
2731
1361
  return Math.max(0, Math.min(1, value));
2732
1362
  }
2733
1363
  function assertBaseRateInRange(baseRate, field = "baseRate") {
@@ -2771,26 +1401,35 @@ function buildBeliefConfidenceRow(args) {
2771
1401
  ...args.triggeringWorktreeId ? { triggeringWorktreeId: args.triggeringWorktreeId } : {}
2772
1402
  };
2773
1403
  }
1404
+ function buildBeliefStatusSuccessResult() {
1405
+ return { success: true };
1406
+ }
1407
+ function buildBeliefEvidenceNotFoundResult() {
1408
+ const result = {};
1409
+ result.success = false;
1410
+ result.message = "Evidence node not found";
1411
+ return result;
1412
+ }
2774
1413
  function deriveSyntheticBackfillOpinion(source) {
2775
1414
  const belief = readFiniteNumber(source.opinion_b) ?? readFiniteNumber(source.belief);
2776
1415
  const disbelief = readFiniteNumber(source.opinion_d) ?? readFiniteNumber(source.disbelief);
2777
1416
  const uncertainty = readFiniteNumber(source.opinion_u) ?? readFiniteNumber(source.uncertainty);
2778
1417
  const baseRate = readFiniteNumber(source.opinion_a) ?? readFiniteNumber(source.baseRate);
2779
1418
  if (belief !== void 0 || disbelief !== void 0 || uncertainty !== void 0 || baseRate !== void 0) {
2780
- return readOpinionFromRecord(source, {
2781
- b: 0,
2782
- d: 0,
2783
- u: 1,
2784
- a: 0.5
2785
- });
1419
+ try {
1420
+ return readOpinionFromRecord(source);
1421
+ } catch (error) {
1422
+ debugGraphPrimitiveFallback(
1423
+ "[epistemicBeliefs] Failed to decode legacy belief opinion",
1424
+ {
1425
+ error
1426
+ }
1427
+ );
1428
+ return mkOpinion(0, 0, 1, 0.5);
1429
+ }
2786
1430
  }
2787
- const confidence = clamp012(readFiniteNumber(source.confidence) ?? 0);
2788
- return {
2789
- b: confidence,
2790
- d: 1 - confidence,
2791
- u: 0,
2792
- a: 0.5
2793
- };
1431
+ const confidence = clamp01(readFiniteNumber(source.confidence) ?? 0);
1432
+ return mkOpinion(confidence, 1 - confidence, 0, 0.5);
2794
1433
  }
2795
1434
  function clampBeliefLimit(limit, fallback = DEFAULT_PROJECT_BELIEF_LIMIT) {
2796
1435
  if (!Number.isFinite(limit)) {
@@ -2805,16 +1444,24 @@ function readTupleContradictedFlag(value) {
2805
1444
  return typeof value === "boolean" ? value : void 0;
2806
1445
  }
2807
1446
  function readBeliefOpinionSnapshot(node, metadata) {
2808
- return readOpinionFromRecord(
2809
- {
1447
+ try {
1448
+ return readOpinionFromRecord({
2810
1449
  ...metadata,
2811
1450
  opinion_b: node.opinion_b,
2812
1451
  opinion_d: node.opinion_d,
2813
1452
  opinion_u: node.opinion_u,
2814
1453
  opinion_a: node.opinion_a
2815
- },
2816
- { b: 0, d: 0, u: 1, a: 0.5 }
2817
- );
1454
+ });
1455
+ } catch (error) {
1456
+ debugGraphPrimitiveFallback(
1457
+ "[epistemicBeliefs] Failed to read belief opinion snapshot",
1458
+ {
1459
+ error,
1460
+ beliefId: node._id
1461
+ }
1462
+ );
1463
+ return mkOpinion(0, 0, 1, 0.5);
1464
+ }
2818
1465
  }
2819
1466
  function deriveTupleContradictionSeverity(node) {
2820
1467
  const metadata = node.metadata || {};
@@ -2905,7 +1552,15 @@ async function resolveBeliefScopeOrNull(ctx, args) {
2905
1552
  projectId: args.projectId ?? void 0,
2906
1553
  topicId: args.topicId ?? void 0
2907
1554
  });
2908
- } catch {
1555
+ } catch (error) {
1556
+ debugGraphPrimitiveFallback(
1557
+ "[epistemicBeliefs] Failed to resolve belief scope",
1558
+ {
1559
+ error,
1560
+ projectId: args.projectId,
1561
+ topicId: args.topicId
1562
+ }
1563
+ );
2909
1564
  return null;
2910
1565
  }
2911
1566
  }
@@ -3005,7 +1660,13 @@ async function getActiveConfidencePolicy(ctx) {
3005
1660
  activeConfig?.tupleContradictionPolicy
3006
1661
  )
3007
1662
  };
3008
- } catch {
1663
+ } catch (error) {
1664
+ debugGraphPrimitiveFallback(
1665
+ "[epistemicBeliefs] Failed to load active confidence policy",
1666
+ {
1667
+ error
1668
+ }
1669
+ );
3009
1670
  return DEFAULT_CONFIDENCE_POLICY;
3010
1671
  }
3011
1672
  }
@@ -3042,7 +1703,11 @@ async function applyBeliefConfidenceChange(ctx, args) {
3042
1703
  details: { nodeId: args.nodeId }
3043
1704
  });
3044
1705
  }
3045
- await requireProjectWriteAccess(ctx, node.projectId, args.authenticatedUserId);
1706
+ await requireProjectWriteAccess(
1707
+ ctx,
1708
+ node.projectId,
1709
+ args.authenticatedUserId
1710
+ );
3046
1711
  const existingMetadata = node.metadata || {};
3047
1712
  const currentBeliefStatus = resolveBeliefStatus(node, existingMetadata);
3048
1713
  const confidencePolicy = await getActiveConfidencePolicy(ctx);
@@ -3086,29 +1751,29 @@ async function applyBeliefConfidenceChange(ctx, args) {
3086
1751
  opinion: nextOpinion,
3087
1752
  policy: tupleTransition.policy
3088
1753
  });
3089
- const newBeliefStatus = promoteBeliefStatusAfterScoring(
3090
- currentBeliefStatus,
3091
- {
3092
- confidence: derivedConfidence,
3093
- predictionMeta,
3094
- metadata: existingMetadata
3095
- }
3096
- );
1754
+ const newBeliefStatus = promoteBeliefStatusAfterScoring(currentBeliefStatus, {
1755
+ confidence: derivedConfidence,
1756
+ predictionMeta,
1757
+ metadata: existingMetadata
1758
+ });
3097
1759
  let tupleContradictionId;
3098
1760
  if (tupleTransition.crossedIntoTupleContradiction) {
3099
- tupleContradictionId = await ctx.runMutation("contradictions:create", {
3100
- projectId: node.projectId,
3101
- topicId: node.topicId,
3102
- beliefId: args.nodeId,
3103
- beliefBId: args.nodeId,
3104
- supportingInsightIds: [],
3105
- contradictingInsightIds: [],
3106
- severity: deriveTupleContradictionSeverity(node),
3107
- source: "tuple_space",
3108
- detectionMethod: "agent",
3109
- description: tupleContradictionDescription,
3110
- createdBy: args.authenticatedUserId
3111
- });
1761
+ tupleContradictionId = await ctx.runMutation(
1762
+ "contradictions:create",
1763
+ {
1764
+ projectId: node.projectId,
1765
+ topicId: node.topicId,
1766
+ beliefId: args.nodeId,
1767
+ beliefBId: args.nodeId,
1768
+ supportingInsightIds: [],
1769
+ contradictingInsightIds: [],
1770
+ severity: deriveTupleContradictionSeverity(node),
1771
+ source: "tuple_space",
1772
+ detectionMethod: "agent",
1773
+ description: tupleContradictionDescription,
1774
+ createdBy: args.authenticatedUserId
1775
+ }
1776
+ );
3112
1777
  }
3113
1778
  await ctx.db.patch(args.nodeId, {
3114
1779
  confidence: derivedConfidence,
@@ -3132,7 +1797,10 @@ async function applyBeliefConfidenceChange(ctx, args) {
3132
1797
  });
3133
1798
  if (isFirstScoring) {
3134
1799
  const nodeTopicId = node.topicId;
3135
- const themeNodes = await ctx.db.query("epistemicNodes").withIndex("by_topic", (q) => q.eq("topicId", nodeTopicId || node.projectId)).filter((q) => q.eq(q.field("nodeType"), "theme")).collect();
1800
+ const themeNodes = await ctx.db.query("epistemicNodes").withIndex(
1801
+ "by_topic",
1802
+ (q) => q.eq("topicId", nodeTopicId || node.projectId)
1803
+ ).filter((q) => q.eq(q.field("nodeType"), "theme")).collect();
3136
1804
  for (const theme of themeNodes) {
3137
1805
  if (theme.globalId && node.globalId) {
3138
1806
  await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {
@@ -3262,12 +1930,12 @@ var propagateConfidenceChange = internalMutation({
3262
1930
  },
3263
1931
  returns: permissiveReturn,
3264
1932
  handler: async (ctx, args) => {
3265
- const sourceOpinion = {
3266
- b: args.opinion_b,
3267
- d: args.opinion_d,
3268
- u: args.opinion_u,
3269
- a: args.opinion_a
3270
- };
1933
+ const sourceOpinion = mkOpinion(
1934
+ args.opinion_b,
1935
+ args.opinion_d,
1936
+ args.opinion_u,
1937
+ args.opinion_a
1938
+ );
3271
1939
  const sourceNode = await ctx.db.get(args.nodeId);
3272
1940
  const sourceScope = await resolveNodeScopeForWorkspaceIsolation(
3273
1941
  ctx,
@@ -3374,7 +2042,7 @@ var create = mutation({
3374
2042
  expectedBy: v.optional(v.number())
3375
2043
  })
3376
2044
  ),
3377
- baseRate: v.number(),
2045
+ baseRate: v.optional(v.number()),
3378
2046
  metadata: v.optional(v.any())
3379
2047
  // Additional metadata including isConditional
3380
2048
  },
@@ -3405,7 +2073,7 @@ var create = mutation({
3405
2073
  );
3406
2074
  }
3407
2075
  const now = Date.now();
3408
- const baseRate = assertBaseRateInRange(args.baseRate);
2076
+ const baseRate = assertBaseRateInRange(args.baseRate ?? 0.5);
3409
2077
  const initialBeliefStatus = args.worktreeId ? "hypothesis" : "assumption";
3410
2078
  const initialEpistemicStatus = args.worktreeId ? "hypothesis" : "assumption";
3411
2079
  const seedOpinion = {
@@ -3730,7 +2398,15 @@ var getByProject = query({
3730
2398
  projectId: args.projectId,
3731
2399
  topicId: args.topicId
3732
2400
  });
3733
- } catch {
2401
+ } catch (error) {
2402
+ debugGraphPrimitiveFallback(
2403
+ "[epistemicBeliefs] Failed to resolve project scope",
2404
+ {
2405
+ error,
2406
+ projectId: args.projectId,
2407
+ topicId: args.topicId
2408
+ }
2409
+ );
3734
2410
  return [];
3735
2411
  }
3736
2412
  if (args.userId) {
@@ -3774,7 +2450,9 @@ var getByTopic = query({
3774
2450
  handler: async (ctx, args) => {
3775
2451
  const pageSize = clampBeliefLimit(args.limit);
3776
2452
  const scanLimit = Math.min(pageSize * 3, MAX_PROJECT_BELIEF_LIMIT);
3777
- const scope = await resolveTopicProjectScope(ctx, { topicId: args.topicId });
2453
+ const scope = await resolveTopicProjectScope(ctx, {
2454
+ topicId: args.topicId
2455
+ });
3778
2456
  const query2 = ctx.db.query("epistemicNodes").withIndex(
3779
2457
  "by_topic_type",
3780
2458
  (q) => q.eq("topicId", args.topicId).eq("nodeType", "belief")
@@ -3979,8 +2657,8 @@ var modulateConfidence = mutation({
3979
2657
  // d: evidence AGAINST [0,1]
3980
2658
  uncertainty: v.number(),
3981
2659
  // u: lack of evidence [0,1]
3982
- baseRate: v.optional(v.number()),
3983
- // a: prior probability [0,1], defaults to 0.5
2660
+ baseRate: v.number(),
2661
+ // a: prior probability [0,1]
3984
2662
  trigger: v.union(
3985
2663
  v.literal("evidence_added"),
3986
2664
  v.literal("evidence_removed"),
@@ -4000,16 +2678,18 @@ var modulateConfidence = mutation({
4000
2678
  rationale: v.optional(v.string()),
4001
2679
  userId: v.string(),
4002
2680
  // SL operator provenance (optional — defaults to manual_assessment)
4003
- slOperator: v.optional(v.union(
4004
- v.literal("cumulative_fusion"),
4005
- v.literal("averaging_fusion"),
4006
- v.literal("trust_discount"),
4007
- v.literal("conditional_deduction"),
4008
- v.literal("dependency_cascade"),
4009
- v.literal("negation"),
4010
- v.literal("constraint_fusion"),
4011
- v.literal("manual_assessment")
4012
- )),
2681
+ slOperator: v.optional(
2682
+ v.union(
2683
+ v.literal("cumulative_fusion"),
2684
+ v.literal("averaging_fusion"),
2685
+ v.literal("trust_discount"),
2686
+ v.literal("conditional_deduction"),
2687
+ v.literal("dependency_cascade"),
2688
+ v.literal("negation"),
2689
+ v.literal("constraint_fusion"),
2690
+ v.literal("manual_assessment")
2691
+ )
2692
+ ),
4013
2693
  triggeringEvidenceId: v.optional(v.id("epistemicNodes")),
4014
2694
  triggeringWorktreeId: v.optional(v.string())
4015
2695
  },
@@ -4240,10 +2920,7 @@ var getConfidenceHistory = query({
4240
2920
  if (!node || node.nodeType !== "belief") {
4241
2921
  return [];
4242
2922
  }
4243
- return await ctx.db.query("beliefConfidence").withIndex(
4244
- "by_beliefId_time",
4245
- (q) => q.eq("beliefId", args.nodeId)
4246
- ).order("asc").collect();
2923
+ return await ctx.db.query("beliefConfidence").withIndex("by_beliefId_time", (q) => q.eq("beliefId", args.nodeId)).order("asc").collect();
4247
2924
  }
4248
2925
  });
4249
2926
  var getLineage = query({
@@ -4547,7 +3224,7 @@ var unlinkEvidence = mutation({
4547
3224
  const now = Date.now();
4548
3225
  const evidenceNode = await ctx.db.get(args.insightId);
4549
3226
  if (!evidenceNode || evidenceNode.nodeType !== "evidence") {
4550
- return { success: false, message: "Evidence node not found" };
3227
+ return buildBeliefEvidenceNotFoundResult();
4551
3228
  }
4552
3229
  if (!evidenceNode.projectId) {
4553
3230
  throw new Error("Evidence has no project scope");
@@ -4588,7 +3265,7 @@ var unlinkEvidence = mutation({
4588
3265
  projectId: evidenceNode.projectId
4589
3266
  });
4590
3267
  }
4591
- return { success: true };
3268
+ return buildBeliefStatusSuccessResult();
4592
3269
  }
4593
3270
  });
4594
3271
  var getWithEvidence = query({
@@ -4700,7 +3377,7 @@ var deleteRelationship = mutation({
4700
3377
  changedAt: now,
4701
3378
  projectId: edge.projectId
4702
3379
  });
4703
- return { success: true };
3380
+ return buildBeliefStatusSuccessResult();
4704
3381
  }
4705
3382
  });
4706
3383
  var updateCriticality = mutation({
@@ -4829,13 +3506,23 @@ var batchUpdateCriticality = mutation({
4829
3506
  changedAt: now,
4830
3507
  projectId: node.projectId
4831
3508
  });
4832
- results.push({
4833
- beliefId: update.beliefId,
4834
- nodeId: node._id,
4835
- success: true
4836
- });
4837
- } catch {
4838
- results.push({ beliefId: update.beliefId, success: false });
3509
+ const result = {};
3510
+ result.beliefId = update.beliefId;
3511
+ result.nodeId = node._id;
3512
+ result.success = true;
3513
+ results.push(result);
3514
+ } catch (error) {
3515
+ debugGraphPrimitiveFallback(
3516
+ "[epistemicBeliefs] Failed to update belief criticality",
3517
+ {
3518
+ error,
3519
+ beliefId: update.beliefId
3520
+ }
3521
+ );
3522
+ const result = {};
3523
+ result.beliefId = update.beliefId;
3524
+ result.success = false;
3525
+ results.push(result);
4839
3526
  }
4840
3527
  }
4841
3528
  return { results, updatedCount: results.filter((r) => r.success).length };
@@ -4950,7 +3637,15 @@ var getByPillar = query({
4950
3637
  projectId: args.projectId,
4951
3638
  topicId: args.topicId
4952
3639
  });
4953
- } catch {
3640
+ } catch (error) {
3641
+ debugGraphPrimitiveFallback(
3642
+ "[epistemicBeliefs] Failed to resolve criticality scope",
3643
+ {
3644
+ error,
3645
+ projectId: args.projectId,
3646
+ topicId: args.topicId
3647
+ }
3648
+ );
4954
3649
  return [];
4955
3650
  }
4956
3651
  const nodes = await ctx.db.query("epistemicNodes").withIndex(
@@ -5071,7 +3766,9 @@ var internalGetByTopic = internalQuery({
5071
3766
  const pageSize = clampBeliefLimit(args.limit, 500);
5072
3767
  const scanLimit = Math.min(pageSize * 3, MAX_PROJECT_BELIEF_LIMIT);
5073
3768
  const audienceMode = args.audienceMode ?? "internal";
5074
- const scope = await resolveTopicProjectScope(ctx, { topicId: args.topicId });
3769
+ const scope = await resolveTopicProjectScope(ctx, {
3770
+ topicId: args.topicId
3771
+ });
5075
3772
  const registryRows = await listAudienceRegistryRows(ctx, {
5076
3773
  tenantId: scope.tenantId,
5077
3774
  workspaceId: scope.workspaceId
@@ -5131,7 +3828,7 @@ var internalCreate = internalMutation({
5131
3828
  args: {
5132
3829
  ...optionalBeliefScopeArgs,
5133
3830
  formulation: v.string(),
5134
- baseRate: v.number(),
3831
+ baseRate: v.optional(v.number()),
5135
3832
  confidence: v.optional(
5136
3833
  v.union(v.literal("high"), v.literal("medium"), v.literal("low"))
5137
3834
  ),
@@ -5167,7 +3864,7 @@ var internalCreate = internalMutation({
5167
3864
  returns: permissiveReturn,
5168
3865
  handler: async (ctx, args) => {
5169
3866
  const now = Date.now();
5170
- const baseRate = assertBaseRateInRange(args.baseRate);
3867
+ const baseRate = assertBaseRateInRange(args.baseRate ?? 0.5);
5171
3868
  const scope = await resolveTopicProjectScope(ctx, {
5172
3869
  topicId: args.topicId,
5173
3870
  projectId: args.projectId
@@ -5416,15 +4113,17 @@ var backfillSyntheticOpinionHistory = internalMutation({
5416
4113
  skippedHasHistory++;
5417
4114
  continue;
5418
4115
  }
5419
- const opinion2 = deriveSyntheticBackfillOpinion(node);
4116
+ const opinion = deriveSyntheticBackfillOpinion(
4117
+ node
4118
+ );
5420
4119
  await ctx.db.insert(
5421
4120
  "beliefConfidence",
5422
4121
  buildBeliefConfidenceRow({
5423
4122
  beliefId: node._id,
5424
- belief: opinion2.b,
5425
- disbelief: opinion2.d,
5426
- uncertainty: opinion2.u,
5427
- baseRate: opinion2.a,
4123
+ belief: opinion.b,
4124
+ disbelief: opinion.d,
4125
+ uncertainty: opinion.u,
4126
+ baseRate: opinion.a,
5428
4127
  trigger: "backfill_synthetic",
5429
4128
  rationale: "LK-6 backfill: synthesized t0 from node-level opinion fields (no prior beliefConfidence row found).",
5430
4129
  assessedAt: readFiniteNumber(node.createdAt) ?? readFiniteNumber(node.updatedAt) ?? Date.now(),
@@ -5722,7 +4421,13 @@ var getBeliefClusterPositions = query({
5722
4421
  return {
5723
4422
  positions: {},
5724
4423
  hasClusters: false,
5725
- counts: { raw: 0, hypothesis: 0, conditional: 0, unprocessed: 0, total: 0 }
4424
+ counts: {
4425
+ raw: 0,
4426
+ hypothesis: 0,
4427
+ conditional: 0,
4428
+ unprocessed: 0,
4429
+ total: 0
4430
+ }
5726
4431
  };
5727
4432
  }
5728
4433
  const allBeliefNodes = await getBeliefNodesForScope(ctx, scope);
@@ -5784,14 +4489,8 @@ var reassignBeliefsTopic = mutation({
5784
4489
  let connectedReassigned = 0;
5785
4490
  const alreadyReassigned = /* @__PURE__ */ new Set();
5786
4491
  for (const beliefId of movedBeliefIds) {
5787
- const outbound = await ctx.db.query("epistemicEdges").withIndex(
5788
- "by_from",
5789
- (q) => q.eq("fromNodeId", beliefId)
5790
- ).collect();
5791
- const inbound = await ctx.db.query("epistemicEdges").withIndex(
5792
- "by_to",
5793
- (q) => q.eq("toNodeId", beliefId)
5794
- ).collect();
4492
+ const outbound = await ctx.db.query("epistemicEdges").withIndex("by_from", (q) => q.eq("fromNodeId", beliefId)).collect();
4493
+ const inbound = await ctx.db.query("epistemicEdges").withIndex("by_to", (q) => q.eq("toNodeId", beliefId)).collect();
5795
4494
  const connectedNodeIds = /* @__PURE__ */ new Set();
5796
4495
  for (const edge of outbound) {
5797
4496
  if (edge.toNodeId) connectedNodeIds.add(String(edge.toNodeId));
@@ -5814,7 +4513,14 @@ var reassignBeliefsTopic = mutation({
5814
4513
  alreadyReassigned.add(connectedId);
5815
4514
  connectedReassigned++;
5816
4515
  }
5817
- } catch {
4516
+ } catch (error) {
4517
+ debugGraphPrimitiveFallback(
4518
+ "[epistemicBeliefs] Failed to reassign connected node",
4519
+ {
4520
+ error,
4521
+ connectedId
4522
+ }
4523
+ );
5818
4524
  }
5819
4525
  }
5820
4526
  }