@lucern/graph-primitives 0.1.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (224) hide show
  1. package/README.md +29 -0
  2. package/dist/beliefDecay-Q_26RTc-.d.ts +72 -0
  3. package/dist/beliefDecay.d.ts +2 -0
  4. package/dist/beliefDecay.js +1628 -0
  5. package/dist/beliefDecay.js.map +1 -0
  6. package/dist/beliefEvidenceLinks-42FlR48t.d.ts +77 -0
  7. package/dist/beliefEvidenceLinks.d.ts +1 -0
  8. package/dist/beliefEvidenceLinks.js +1978 -0
  9. package/dist/beliefEvidenceLinks.js.map +1 -0
  10. package/dist/beliefLifecycle-C-AehZgF.d.ts +43 -0
  11. package/dist/beliefLifecycle.d.ts +1 -0
  12. package/dist/beliefLifecycle.js +98 -0
  13. package/dist/beliefLifecycle.js.map +1 -0
  14. package/dist/confidencePropagationDispatch.d.ts +46 -0
  15. package/dist/confidencePropagationDispatch.js +744 -0
  16. package/dist/confidencePropagationDispatch.js.map +1 -0
  17. package/dist/contradictions-Hdwl7zid.d.ts +71 -0
  18. package/dist/contradictions.d.ts +1 -0
  19. package/dist/contradictions.js +1557 -0
  20. package/dist/contradictions.js.map +1 -0
  21. package/dist/convex.d.ts +23 -0
  22. package/dist/convex.js +17 -0
  23. package/dist/convex.js.map +1 -0
  24. package/dist/edgeValidation-CeI0wc0r.d.ts +35 -0
  25. package/dist/edgeValidation.d.ts +2 -0
  26. package/dist/edgeValidation.js +307 -0
  27. package/dist/edgeValidation.js.map +1 -0
  28. package/dist/edges/contains.d.ts +6 -0
  29. package/dist/edges/contains.js +14 -0
  30. package/dist/edges/contains.js.map +1 -0
  31. package/dist/edges/contradicts.d.ts +6 -0
  32. package/dist/edges/contradicts.js +183 -0
  33. package/dist/edges/contradicts.js.map +1 -0
  34. package/dist/edges/dependsOn.d.ts +6 -0
  35. package/dist/edges/dependsOn.js +240 -0
  36. package/dist/edges/dependsOn.js.map +1 -0
  37. package/dist/edges/derivedFrom.d.ts +6 -0
  38. package/dist/edges/derivedFrom.js +14 -0
  39. package/dist/edges/derivedFrom.js.map +1 -0
  40. package/dist/edges/elaborates.d.ts +6 -0
  41. package/dist/edges/elaborates.js +100 -0
  42. package/dist/edges/elaborates.js.map +1 -0
  43. package/dist/edges/index.d.ts +3 -0
  44. package/dist/edges/index.js +556 -0
  45. package/dist/edges/index.js.map +1 -0
  46. package/dist/edges/informs.d.ts +6 -0
  47. package/dist/edges/informs.js +112 -0
  48. package/dist/edges/informs.js.map +1 -0
  49. package/dist/edges/propagationTypes.d.ts +39 -0
  50. package/dist/edges/propagationTypes.js +17 -0
  51. package/dist/edges/propagationTypes.js.map +1 -0
  52. package/dist/edges/refutes.d.ts +6 -0
  53. package/dist/edges/refutes.js +108 -0
  54. package/dist/edges/refutes.js.map +1 -0
  55. package/dist/edges/supports.d.ts +6 -0
  56. package/dist/edges/supports.js +193 -0
  57. package/dist/edges/supports.js.map +1 -0
  58. package/dist/edges/tests.d.ts +6 -0
  59. package/dist/edges/tests.js +14 -0
  60. package/dist/edges/tests.js.map +1 -0
  61. package/dist/edges/utils.d.ts +12 -0
  62. package/dist/edges/utils.js +188 -0
  63. package/dist/edges/utils.js.map +1 -0
  64. package/dist/embeddingTrigger.d.ts +24 -0
  65. package/dist/embeddingTrigger.js +24 -0
  66. package/dist/embeddingTrigger.js.map +1 -0
  67. package/dist/entityBridge-DMaKooYn.d.ts +59 -0
  68. package/dist/entityBridge.d.ts +1 -0
  69. package/dist/entityBridge.js +663 -0
  70. package/dist/entityBridge.js.map +1 -0
  71. package/dist/entityLifecycle-BkhRJ-XI.d.ts +69 -0
  72. package/dist/entityLifecycle.d.ts +1 -0
  73. package/dist/entityLifecycle.js +2083 -0
  74. package/dist/entityLifecycle.js.map +1 -0
  75. package/dist/entityValidation-KLZ_Xl2D.d.ts +50 -0
  76. package/dist/entityValidation.d.ts +3 -0
  77. package/dist/entityValidation.js +71 -0
  78. package/dist/entityValidation.js.map +1 -0
  79. package/dist/epistemicAnswers-DSP1slZ9.d.ts +67 -0
  80. package/dist/epistemicAnswers.d.ts +1 -0
  81. package/dist/epistemicAnswers.js +1650 -0
  82. package/dist/epistemicAnswers.js.map +1 -0
  83. package/dist/epistemicBeliefs-DtFVTp-k.d.ts +377 -0
  84. package/dist/epistemicBeliefs.d.ts +5 -0
  85. package/dist/epistemicBeliefs.js +6386 -0
  86. package/dist/epistemicBeliefs.js.map +1 -0
  87. package/dist/epistemicContractHelpers.d.ts +1 -0
  88. package/dist/epistemicContractHelpers.js +320 -0
  89. package/dist/epistemicContractHelpers.js.map +1 -0
  90. package/dist/epistemicContracts.d.ts +77 -0
  91. package/dist/epistemicContracts.js +8436 -0
  92. package/dist/epistemicContracts.js.map +1 -0
  93. package/dist/epistemicEdges-DcA8ErUG.d.ts +191 -0
  94. package/dist/epistemicEdges.d.ts +2 -0
  95. package/dist/epistemicEdges.js +2749 -0
  96. package/dist/epistemicEdges.js.map +1 -0
  97. package/dist/epistemicEvidence-Bo638XDP.d.ts +128 -0
  98. package/dist/epistemicEvidence.d.ts +3 -0
  99. package/dist/epistemicEvidence.js +3282 -0
  100. package/dist/epistemicEvidence.js.map +1 -0
  101. package/dist/epistemicHelpers-Bd9xbaib.d.ts +329 -0
  102. package/dist/epistemicHelpers.d.ts +4 -0
  103. package/dist/epistemicHelpers.js +999 -0
  104. package/dist/epistemicHelpers.js.map +1 -0
  105. package/dist/epistemicLinking-CyeLOIzN.d.ts +35 -0
  106. package/dist/epistemicLinking.d.ts +1 -0
  107. package/dist/epistemicLinking.js +1391 -0
  108. package/dist/epistemicLinking.js.map +1 -0
  109. package/dist/epistemicNodes-BpD6Koud.d.ts +167 -0
  110. package/dist/epistemicNodes.d.ts +2 -0
  111. package/dist/epistemicNodes.js +2942 -0
  112. package/dist/epistemicNodes.js.map +1 -0
  113. package/dist/epistemicQuestions-CmEeY6zQ.d.ts +214 -0
  114. package/dist/epistemicQuestions.d.ts +3 -0
  115. package/dist/epistemicQuestions.js +4993 -0
  116. package/dist/epistemicQuestions.js.map +1 -0
  117. package/dist/epistemicSources-ZazxHOK1.d.ts +25 -0
  118. package/dist/epistemicSources.d.ts +1 -0
  119. package/dist/epistemicSources.js +2025 -0
  120. package/dist/epistemicSources.js.map +1 -0
  121. package/dist/evaluators/index.d.ts +9 -0
  122. package/dist/evaluators/index.js +8440 -0
  123. package/dist/evaluators/index.js.map +1 -0
  124. package/dist/evaluators/lintCheckerEvaluator.d.ts +11 -0
  125. package/dist/evaluators/lintCheckerEvaluator.js +155 -0
  126. package/dist/evaluators/lintCheckerEvaluator.js.map +1 -0
  127. package/dist/evaluators/sentryCheckerEvaluator.d.ts +11 -0
  128. package/dist/evaluators/sentryCheckerEvaluator.js +126 -0
  129. package/dist/evaluators/sentryCheckerEvaluator.js.map +1 -0
  130. package/dist/evaluators/shared.d.ts +27 -0
  131. package/dist/evaluators/shared.js +92 -0
  132. package/dist/evaluators/shared.js.map +1 -0
  133. package/dist/evaluators/testRunnerEvaluator.d.ts +17 -0
  134. package/dist/evaluators/testRunnerEvaluator.js +232 -0
  135. package/dist/evaluators/testRunnerEvaluator.js.map +1 -0
  136. package/dist/evaluators/tscCheckerEvaluator.d.ts +11 -0
  137. package/dist/evaluators/tscCheckerEvaluator.js +189 -0
  138. package/dist/evaluators/tscCheckerEvaluator.js.map +1 -0
  139. package/dist/globalId-DKh9d_uD.d.ts +20 -0
  140. package/dist/globalId.d.ts +1 -0
  141. package/dist/globalId.js +15 -0
  142. package/dist/globalId.js.map +1 -0
  143. package/dist/graphTypes-CpgIuCdo.d.ts +52 -0
  144. package/dist/graphTypes.d.ts +1 -0
  145. package/dist/graphTypes.js +120 -0
  146. package/dist/graphTypes.js.map +1 -0
  147. package/dist/helpers-BYHIk5vU.d.ts +27 -0
  148. package/dist/helpers.d.ts +4 -0
  149. package/dist/helpers.js +313 -0
  150. package/dist/helpers.js.map +1 -0
  151. package/dist/index-Dct1T70K.d.ts +25 -0
  152. package/dist/index-Dq-7R-gi.d.ts +31 -0
  153. package/dist/index.d.ts +45 -0
  154. package/dist/index.js +22294 -0
  155. package/dist/index.js.map +1 -0
  156. package/dist/invariantEnforcement.d.ts +52 -0
  157. package/dist/invariantEnforcement.js +231 -0
  158. package/dist/invariantEnforcement.js.map +1 -0
  159. package/dist/logicalRoleInference-CJxqWi3u.d.ts +16 -0
  160. package/dist/logicalRoleInference.d.ts +3 -0
  161. package/dist/logicalRoleInference.js +64 -0
  162. package/dist/logicalRoleInference.js.map +1 -0
  163. package/dist/matcherFeedbackUtils.d.ts +33 -0
  164. package/dist/matcherFeedbackUtils.js +95 -0
  165. package/dist/matcherFeedbackUtils.js.map +1 -0
  166. package/dist/ontology-matching-Buhu23ss.d.ts +48 -0
  167. package/dist/ontology-matching.d.ts +2 -0
  168. package/dist/ontology-matching.js +346 -0
  169. package/dist/ontology-matching.js.map +1 -0
  170. package/dist/ontologyApproval-Ba0Jjk1k.d.ts +26 -0
  171. package/dist/ontologyApproval.d.ts +1 -0
  172. package/dist/ontologyApproval.js +78 -0
  173. package/dist/ontologyApproval.js.map +1 -0
  174. package/dist/ontologyDefinitions.d.ts +72 -0
  175. package/dist/ontologyDefinitions.js +635 -0
  176. package/dist/ontologyDefinitions.js.map +1 -0
  177. package/dist/ontologyHelpers.d.ts +79 -0
  178. package/dist/ontologyHelpers.js +81 -0
  179. package/dist/ontologyHelpers.js.map +1 -0
  180. package/dist/ontologyRegistry-B67rPJ16.d.ts +31 -0
  181. package/dist/ontologyRegistry.d.ts +1 -0
  182. package/dist/ontologyRegistry.js +296 -0
  183. package/dist/ontologyRegistry.js.map +1 -0
  184. package/dist/projectionReconciliation-CxrXYGaB.d.ts +20 -0
  185. package/dist/projectionReconciliation.d.ts +1 -0
  186. package/dist/projectionReconciliation.js +261 -0
  187. package/dist/projectionReconciliation.js.map +1 -0
  188. package/dist/projectionStaleness-CAdpIsaW.d.ts +51 -0
  189. package/dist/projectionStaleness.d.ts +1 -0
  190. package/dist/projectionStaleness.js +57 -0
  191. package/dist/projectionStaleness.js.map +1 -0
  192. package/dist/questionEvidenceLinks-BdQD0TkM.d.ts +34 -0
  193. package/dist/questionEvidenceLinks.d.ts +1 -0
  194. package/dist/questionEvidenceLinks.js +1690 -0
  195. package/dist/questionEvidenceLinks.js.map +1 -0
  196. package/dist/resolverTypes-CC8Ea2E2.d.ts +20 -0
  197. package/dist/resolverTypes.d.ts +4 -0
  198. package/dist/resolverTypes.js +3 -0
  199. package/dist/resolverTypes.js.map +1 -0
  200. package/dist/resolvers-Br1a6eLV.d.ts +14 -0
  201. package/dist/resolvers.d.ts +5 -0
  202. package/dist/resolvers.js +308 -0
  203. package/dist/resolvers.js.map +1 -0
  204. package/dist/scopeResolverCompat.d.ts +26 -0
  205. package/dist/scopeResolverCompat.js +242 -0
  206. package/dist/scopeResolverCompat.js.map +1 -0
  207. package/dist/text-matching-CMn2WnVD.d.ts +40 -0
  208. package/dist/text-matching.d.ts +2 -0
  209. package/dist/text-matching.js +246 -0
  210. package/dist/text-matching.js.map +1 -0
  211. package/dist/topicOntologyResolver.d.ts +80 -0
  212. package/dist/topicOntologyResolver.js +67 -0
  213. package/dist/topicOntologyResolver.js.map +1 -0
  214. package/dist/topicProjectOverlay.d.ts +92 -0
  215. package/dist/topicProjectOverlay.js +249 -0
  216. package/dist/topicProjectOverlay.js.map +1 -0
  217. package/dist/topicScope-By_zp4tt.d.ts +34 -0
  218. package/dist/topicScope.d.ts +3 -0
  219. package/dist/topicScope.js +206 -0
  220. package/dist/topicScope.js.map +1 -0
  221. package/dist/workspaceIsolation.d.ts +44 -0
  222. package/dist/workspaceIsolation.js +950 -0
  223. package/dist/workspaceIsolation.js.map +1 -0
  224. package/package.json +46 -0
@@ -0,0 +1,950 @@
1
+ import { defineTable, componentsGeneric, anyApi } from 'convex/server';
2
+ import { v } from 'convex/values';
3
+
4
+ // ../schema-management/src/spine/tables/epistemicNodes.ts
5
+ v.optional(v.any());
6
+ var looseJsonObject = v.record(v.string(), v.any());
7
+ var looseJsonArray = v.array(v.any());
8
+ v.union(
9
+ v.string(),
10
+ v.number(),
11
+ v.boolean(),
12
+ v.null(),
13
+ looseJsonObject,
14
+ looseJsonArray
15
+ );
16
+
17
+ // ../schema-management/src/shared/common.ts
18
+ v.number();
19
+ v.union(
20
+ v.literal("very_high"),
21
+ // 0.9+
22
+ v.literal("high"),
23
+ // 0.7-0.9
24
+ v.literal("medium"),
25
+ // 0.4-0.7
26
+ v.literal("low"),
27
+ // 0.2-0.4
28
+ v.literal("very_low")
29
+ // 0-0.2
30
+ );
31
+ v.union(
32
+ v.literal(1),
33
+ // Critical
34
+ v.literal(2),
35
+ // High
36
+ v.literal(3),
37
+ // Medium
38
+ v.literal(4),
39
+ // Low
40
+ v.literal(5)
41
+ // Backlog
42
+ );
43
+ v.union(
44
+ v.literal("critical"),
45
+ v.literal("high"),
46
+ v.literal("medium"),
47
+ v.literal("low"),
48
+ v.literal("backlog")
49
+ );
50
+ v.union(
51
+ v.literal("active"),
52
+ v.literal("paused"),
53
+ v.literal("completed"),
54
+ v.literal("archived")
55
+ );
56
+ v.union(
57
+ v.literal("pending"),
58
+ v.literal("processing"),
59
+ v.literal("completed"),
60
+ v.literal("failed")
61
+ );
62
+ v.object({
63
+ crunchbaseId: v.optional(v.string()),
64
+ linkedinUrl: v.optional(v.string()),
65
+ pitchbookId: v.optional(v.string()),
66
+ twitterUrl: v.optional(v.string()),
67
+ domain: v.optional(v.string())
68
+ });
69
+ var sourceType = v.union(
70
+ v.literal("proprietary"),
71
+ // Internal Stack research
72
+ v.literal("primary"),
73
+ // Direct interviews, calls
74
+ v.literal("secondary"),
75
+ // Published sources
76
+ v.literal("ai_generated"),
77
+ // AI-synthesized
78
+ v.literal("user_input"),
79
+ // Manual user entry
80
+ v.literal("inferred")
81
+ // System inference
82
+ );
83
+ v.object({
84
+ sourceType: v.optional(sourceType),
85
+ sourceId: v.optional(v.string()),
86
+ // Reference to source entity
87
+ sourceUrl: v.optional(v.string()),
88
+ sourceDate: v.optional(v.number()),
89
+ sourceName: v.optional(v.string())
90
+ });
91
+ v.object({
92
+ cursor: v.optional(v.string()),
93
+ limit: v.optional(v.number())
94
+ });
95
+ v.object({
96
+ hasMore: v.boolean(),
97
+ nextCursor: v.optional(v.string()),
98
+ totalCount: v.optional(v.number())
99
+ });
100
+ var richTextContent = v.object({
101
+ type: v.literal("doc"),
102
+ content: looseJsonArray
103
+ });
104
+ v.union(v.string(), richTextContent);
105
+ v.object({
106
+ promptTokens: v.optional(v.number()),
107
+ completionTokens: v.optional(v.number()),
108
+ totalTokens: v.optional(v.number())
109
+ });
110
+ v.object({
111
+ fileName: v.optional(v.string()),
112
+ fileSize: v.optional(v.number()),
113
+ mimeType: v.optional(v.string()),
114
+ storageId: v.optional(v.id("_storage")),
115
+ externalUrl: v.optional(v.string())
116
+ });
117
+
118
+ // ../schema-management/src/spine/tables/epistemicNodes.ts
119
+ var nodeType = v.union(
120
+ // --- L4: Audit Targets (decisions, outcomes) ---
121
+ v.literal("decision"),
122
+ // Investment decision with knowledge horizon snapshot
123
+ // --- L3: Traversal Anchors (epistemic structure) ---
124
+ v.literal("belief"),
125
+ // Structured conviction (immutable formulation)
126
+ v.literal("question"),
127
+ // Unit of uncertainty
128
+ v.literal("theme"),
129
+ // Investment thesis / conviction cluster
130
+ v.literal("deal"),
131
+ // Investment evaluation process
132
+ v.literal("topic"),
133
+ // Hierarchical knowledge container
134
+ // --- L2: Compression Boundary (minimum reasoning unit) ---
135
+ v.literal("claim"),
136
+ // Atomic assertion that can be true/false
137
+ v.literal("evidence"),
138
+ // Interpreted signal linked to beliefs
139
+ v.literal("synthesis"),
140
+ // Primers, deep research
141
+ v.literal("answer"),
142
+ // Immutable answer snapshot for a question
143
+ // --- L1: Terminal Leaves (non-traversable, grounding) ---
144
+ v.literal("atomic_fact"),
145
+ // Raw fact from source (not interpreted)
146
+ v.literal("excerpt"),
147
+ // Direct quote from source document
148
+ v.literal("source"),
149
+ // News, documents, transcripts
150
+ // --- Ontological Entities (things in the world) ---
151
+ v.literal("company"),
152
+ // Organization (subtype: private, corporate, portfolio)
153
+ v.literal("person"),
154
+ // Individual (founder, expert, LP, contact)
155
+ v.literal("investor"),
156
+ // Investment entity (subtype: vc, lp, cvc, pe, family_office, angel)
157
+ v.literal("function"),
158
+ // What a company does (from classifier)
159
+ v.literal("value_chain")
160
+ // Market structure / value flow
161
+ );
162
+ var epistemicLayer = v.union(
163
+ v.literal("L4"),
164
+ // Decisions, outcomes - audit targets
165
+ v.literal("L3"),
166
+ // Beliefs, questions, themes - traversal anchors
167
+ v.literal("L2"),
168
+ // Claims, evidence, synthesis - compression boundary
169
+ v.literal("L1"),
170
+ // Atomic facts, excerpts, sources - terminal leaves
171
+ v.literal("ontological"),
172
+ // Companies, people, etc - not epistemic
173
+ v.literal("organizational")
174
+ // Topics, lenses, worktrees — structural containers
175
+ );
176
+ var nodeStatus = v.union(
177
+ v.literal("active"),
178
+ v.literal("superseded"),
179
+ // Replaced by newer version
180
+ v.literal("archived"),
181
+ v.literal("deleted")
182
+ );
183
+ var sourceType2 = v.union(
184
+ v.literal("human"),
185
+ // User created directly
186
+ v.literal("ai_extracted"),
187
+ // LLM extracted from a source
188
+ v.literal("ai_generated"),
189
+ // LLM synthesized/created
190
+ v.literal("imported"),
191
+ // External system import
192
+ v.literal("system"),
193
+ // System-generated (migrations, classifiers)
194
+ v.literal("verified"),
195
+ // Human-verified source
196
+ v.literal("proprietary")
197
+ // Proprietary/internal data
198
+ );
199
+ var verificationStatus = v.union(
200
+ v.literal("unverified"),
201
+ v.literal("human_verified"),
202
+ v.literal("ai_verified"),
203
+ v.literal("contradicted"),
204
+ v.literal("outdated")
205
+ );
206
+ var syncStatus = v.union(
207
+ v.literal("synced"),
208
+ // Node and edges fully synced to Neo4j
209
+ v.literal("pending_edges"),
210
+ // Node created, edges being created
211
+ v.literal("edge_creation_failed")
212
+ // Edge creation failed, needs retry
213
+ );
214
+ var audienceLabel = v.string();
215
+ var sensitivityTier = v.union(
216
+ v.literal("low"),
217
+ v.literal("medium"),
218
+ v.literal("high"),
219
+ v.literal("restricted")
220
+ );
221
+ var exportClass = v.union(
222
+ v.literal("internal_only"),
223
+ v.literal("client_safe"),
224
+ v.literal("public_safe"),
225
+ v.literal("restricted")
226
+ );
227
+ var anonymizationClass = v.union(
228
+ v.literal("none"),
229
+ v.literal("standard"),
230
+ v.literal("strict")
231
+ );
232
+ var epistemicStatus = v.union(
233
+ v.literal("hypothesis"),
234
+ // Initial conjecture, low evidence
235
+ v.literal("emerging"),
236
+ // Building evidence, gaining traction
237
+ v.literal("established"),
238
+ // Well-evidenced, core to thesis
239
+ v.literal("challenged"),
240
+ // Contradicting evidence appeared
241
+ v.literal("assumption"),
242
+ // Taken as given, not actively tested
243
+ v.literal("deprecated")
244
+ // Superseded or abandoned
245
+ );
246
+ var beliefStatus = v.union(
247
+ v.literal("assumption"),
248
+ v.literal("hypothesis"),
249
+ v.literal("belief"),
250
+ v.literal("fact")
251
+ );
252
+ var reversibility = v.union(
253
+ v.literal("irreversible"),
254
+ // One-way door decision
255
+ v.literal("hard_to_reverse"),
256
+ // Significant cost to undo
257
+ v.literal("reversible"),
258
+ // Can change course with moderate effort
259
+ v.literal("trivial")
260
+ // Easy to adjust
261
+ );
262
+ var predictionOutcome = v.union(
263
+ v.literal("pending"),
264
+ v.literal("confirmed"),
265
+ v.literal("disconfirmed"),
266
+ v.literal("partial"),
267
+ v.literal("expired")
268
+ );
269
+ var predictionMeta = v.object({
270
+ isPrediction: v.boolean(),
271
+ registeredAt: v.number(),
272
+ // When prediction was made
273
+ expectedBy: v.optional(v.number()),
274
+ // When we expect resolution
275
+ outcome: v.optional(predictionOutcome),
276
+ outcomeRecordedAt: v.optional(v.number()),
277
+ outcomeEvidenceId: v.optional(v.string()),
278
+ // globalId of confirming evidence
279
+ confidenceAtPrediction: v.optional(v.number()),
280
+ // 0-1
281
+ actualVsPredicted: v.optional(v.string())
282
+ // Notes on how outcome compared
283
+ });
284
+ var methodology = v.union(
285
+ // Primary Research (high value)
286
+ v.literal("primary_research"),
287
+ // Direct investigation
288
+ v.literal("expert_interview"),
289
+ // Expert call/interview
290
+ v.literal("customer_interview"),
291
+ // Customer research
292
+ v.literal("field_observation"),
293
+ // On-site observation
294
+ v.literal("proprietary_data"),
295
+ // Internal data analysis
296
+ // Secondary Research
297
+ v.literal("desk_research"),
298
+ // Public sources
299
+ v.literal("regulatory_filing"),
300
+ // SEC, regulatory docs
301
+ v.literal("news_article"),
302
+ // News/press
303
+ v.literal("academic_paper"),
304
+ // Academic research
305
+ // AI-Assisted
306
+ v.literal("ai_synthesis"),
307
+ // AI-generated synthesis
308
+ v.literal("ai_extraction")
309
+ // AI-extracted from source
310
+ );
311
+ var informationAsymmetry = v.union(
312
+ v.literal("proprietary"),
313
+ // Only we have this
314
+ v.literal("early"),
315
+ // We're early but others will get it
316
+ v.literal("common")
317
+ // Everyone has access
318
+ );
319
+ var temporalNature = v.union(
320
+ v.literal("factual"),
321
+ // Resolved outcome. Grounded in reality.
322
+ v.literal("forecast"),
323
+ // Prediction. Will resolve. Discounted weight.
324
+ v.literal("unknown")
325
+ // Not yet classified.
326
+ );
327
+ var questionType = v.union(
328
+ v.literal("validation"),
329
+ // Does evidence support this belief?
330
+ v.literal("falsification"),
331
+ // What would prove this belief wrong?
332
+ v.literal("assumption_probe"),
333
+ // Is this unstated assumption true?
334
+ v.literal("prediction_test"),
335
+ // Will this predicted outcome occur?
336
+ v.literal("counterfactual"),
337
+ // What would we expect if X were false?
338
+ v.literal("discovery"),
339
+ // What don't we know yet?
340
+ v.literal("clarification"),
341
+ // What does X actually mean?
342
+ v.literal("comparison"),
343
+ // How does X compare to Y?
344
+ v.literal("causal"),
345
+ // What caused X?
346
+ v.literal("mechanism"),
347
+ // How does X work?
348
+ v.literal("general")
349
+ // Unclassified
350
+ );
351
+ var questionPriority = v.union(
352
+ v.literal("critical"),
353
+ // Blocks decision-making
354
+ v.literal("high"),
355
+ // Important for thesis
356
+ v.literal("medium"),
357
+ // Would be nice to know
358
+ v.literal("low")
359
+ // Background/curiosity
360
+ );
361
+ var answerQuality = v.union(
362
+ v.literal("definitive"),
363
+ // Clear, well-supported
364
+ v.literal("strong"),
365
+ // Good evidence, high confidence
366
+ v.literal("moderate"),
367
+ // Some evidence
368
+ v.literal("weak"),
369
+ // Limited evidence
370
+ v.literal("speculative"),
371
+ // Mostly conjecture
372
+ v.literal("unanswered")
373
+ // No answer yet
374
+ );
375
+ var consensusView = v.union(
376
+ v.literal("aligned"),
377
+ // We agree with market consensus
378
+ v.literal("ahead_of"),
379
+ // We see this before consensus does
380
+ v.literal("contrarian"),
381
+ // We actively disagree with consensus
382
+ v.literal("orthogonal"),
383
+ // We're looking at something consensus isn't discussing
384
+ v.literal("unknown")
385
+ // We don't know what consensus thinks
386
+ );
387
+ var themeConviction = v.union(
388
+ v.literal("high"),
389
+ // Strong conviction, actively deploying
390
+ v.literal("medium"),
391
+ // Building conviction
392
+ v.literal("low"),
393
+ // Exploring, not convicted
394
+ v.literal("negative")
395
+ // Actively avoiding
396
+ );
397
+ var decisionType = v.union(
398
+ v.literal("invest"),
399
+ v.literal("pass"),
400
+ v.literal("follow_on"),
401
+ v.literal("exit"),
402
+ v.literal("deep_dive"),
403
+ v.literal("monitor"),
404
+ v.literal("deprioritize"),
405
+ v.literal("thesis_adopt"),
406
+ v.literal("thesis_revise"),
407
+ v.literal("thesis_abandon")
408
+ );
409
+ var decisionOutcome = v.union(
410
+ v.literal("pending"),
411
+ v.literal("successful"),
412
+ v.literal("unsuccessful"),
413
+ v.literal("mixed"),
414
+ v.literal("unknown")
415
+ );
416
+ var externalIds2 = v.object({
417
+ crunchbase: v.optional(v.string()),
418
+ linkedin: v.optional(v.string()),
419
+ pitchbook: v.optional(v.string()),
420
+ twitter: v.optional(v.string()),
421
+ website: v.optional(v.string())
422
+ });
423
+ defineTable({
424
+ // === IDENTITY ===
425
+ globalId: v.string(),
426
+ // UUID - survives migration to Neo4j
427
+ // === TYPE ===
428
+ nodeType,
429
+ // === EPISTEMIC LAYER ===
430
+ epistemicLayer: v.optional(epistemicLayer),
431
+ // === SUBTYPE (for typed entities) ===
432
+ subtype: v.optional(v.string()),
433
+ // company: private|corporate|portfolio, investor: vc|lp|cvc|pe|family_office|angel
434
+ // === CONTENT ===
435
+ canonicalText: v.string(),
436
+ // The core content (belief statement, company name, etc.)
437
+ contentHash: v.string(),
438
+ // SHA256(nodeType + canonicalText) for deduplication
439
+ // Extended content (for sources/syntheses)
440
+ content: v.optional(v.string()),
441
+ // Full text for documents/articles
442
+ contentType: v.optional(v.string()),
443
+ // "markdown", "html", "pdf", "text"
444
+ // === METADATA ===
445
+ title: v.optional(v.string()),
446
+ // Display title
447
+ tags: v.optional(v.array(v.string())),
448
+ domain: v.optional(v.string()),
449
+ // For companies: website domain
450
+ // Type-specific metadata (flexible object - LEGACY)
451
+ // New code should use the typed fields below when available
452
+ metadata: v.optional(looseJsonObject),
453
+ // === POLICY / ENTITLEMENT ===
454
+ tenantId: v.optional(v.string()),
455
+ workspaceId: v.optional(v.string()),
456
+ ownerPrincipalId: v.optional(v.string()),
457
+ audienceLabel: v.optional(audienceLabel),
458
+ policyTags: v.optional(v.array(v.string())),
459
+ sensitivityTier: v.optional(sensitivityTier),
460
+ exportClass: v.optional(exportClass),
461
+ anonymizationClass: v.optional(anonymizationClass),
462
+ // === PUBLICATION (visibility-based, not copy-based) ===
463
+ // Publication expands who can see a workspace-local node — the node stays
464
+ // in its workspace, like a microservice exposing part of its API surface.
465
+ // Rules-based: pack/tenant-level publicationRules auto-evaluate on
466
+ // confidence changes and node creation. No manual click-by-click.
467
+ publicationStatus: v.optional(
468
+ v.union(
469
+ v.literal("unpublished"),
470
+ // Default: workspace-local only
471
+ v.literal("published"),
472
+ // Visible at tenant scope (rules matched)
473
+ v.literal("suppressed")
474
+ // Manually blocked even if rules match
475
+ )
476
+ ),
477
+ publishedAt: v.optional(v.number()),
478
+ // When publication status last changed to published
479
+ publishedBy: v.optional(v.string()),
480
+ // userId or "system:publication_rules" for auto-publish
481
+ // === TYPED METADATA FIELDS ===
482
+ // --- Belief ---
483
+ // Belief type — validated against schemaEnumConfig category "belief_type"
484
+ // Platform core: hypothesis, belief, principle, invariant, assumption,
485
+ // tenet, prior, preference, goal, forecast
486
+ beliefType: v.optional(v.string()),
487
+ beliefStatus: v.optional(beliefStatus),
488
+ epistemicStatus: v.optional(epistemicStatus),
489
+ reversibility: v.optional(reversibility),
490
+ predictionMeta: v.optional(predictionMeta),
491
+ // Consensus tracking (for non-consensus detection)
492
+ consensusView: v.optional(consensusView),
493
+ consensusConfidence: v.optional(v.number()),
494
+ // 0-1: What we think consensus confidence is
495
+ consensusSource: v.optional(v.string()),
496
+ // Where we got the consensus view (twitter, reports, etc.)
497
+ // --- Evidence ---
498
+ methodology: v.optional(methodology),
499
+ informationAsymmetry: v.optional(informationAsymmetry),
500
+ temporalNature: v.optional(temporalNature),
501
+ // --- Question ---
502
+ questionType: v.optional(questionType),
503
+ questionPriority: v.optional(questionPriority),
504
+ answerQuality: v.optional(answerQuality),
505
+ // --- Theme ---
506
+ themeConviction: v.optional(themeConviction),
507
+ // Market timing (for "early on theme" detection)
508
+ marketAwarenessDate: v.optional(v.number()),
509
+ // When this theme became broadly discussed
510
+ marketAwarenessSource: v.optional(v.string()),
511
+ // How we know (first major report, twitter volume spike, etc.)
512
+ earlySignalIds: v.optional(v.array(v.string())),
513
+ // globalIds of evidence we had before market awareness
514
+ // --- Decision ---
515
+ decisionType: v.optional(decisionType),
516
+ decisionOutcome: v.optional(decisionOutcome),
517
+ // === EXTERNAL IDS (for ontological entities) ===
518
+ externalIds: v.optional(externalIds2),
519
+ // === PROVENANCE ===
520
+ sourceType: sourceType2,
521
+ aiProvider: v.optional(v.string()),
522
+ // "claude", "gemini", "gpt-4", etc.
523
+ extractedFromNodeId: v.optional(v.id("epistemicNodes")),
524
+ // Quick reference to source
525
+ // === EXTRACTION CONTEXT ===
526
+ extractionModel: v.optional(v.string()),
527
+ // "claude-sonnet-4-20250514"
528
+ extractionPromptName: v.optional(v.string()),
529
+ // "lucern/extract-evidence"
530
+ extractionPromptVersion: v.optional(v.number()),
531
+ extractionTemperature: v.optional(v.number()),
532
+ extractionLangfuseTraceId: v.optional(v.string()),
533
+ // === GROUNDING VERIFICATION ===
534
+ groundingVerified: v.optional(v.boolean()),
535
+ groundingConfidence: v.optional(v.number()),
536
+ // 0-1 match quality
537
+ groundingMatchedText: v.optional(v.string()),
538
+ // Actual text from source
539
+ groundingStartOffset: v.optional(v.number()),
540
+ groundingEndOffset: v.optional(v.number()),
541
+ groundingRejectionReason: v.optional(v.string()),
542
+ // === CONFIDENCE & VERIFICATION ===
543
+ confidence: v.optional(v.number()),
544
+ // 0-1 projected probability P(x) = b + a*u
545
+ verificationStatus: v.optional(verificationStatus),
546
+ // === SL OPINION (Subjective Logic — Kernel v2) ===
547
+ // Replaces scalar confidence with rich epistemic state.
548
+ // b + d + u = 1. P(x) = b + a*u is stored in `confidence` for backward compat.
549
+ opinion_b: v.optional(v.number()),
550
+ // Belief: evidence FOR (0-1)
551
+ opinion_d: v.optional(v.number()),
552
+ // Disbelief: evidence AGAINST (0-1)
553
+ opinion_u: v.optional(v.number()),
554
+ // Uncertainty: absence of evidence (0-1)
555
+ opinion_a: v.optional(v.number()),
556
+ // Base rate / prior probability (0-1)
557
+ tupleContradicted: v.optional(v.boolean()),
558
+ // Single-belief tuple-space contradiction flag
559
+ // === LIFECYCLE ===
560
+ status: nodeStatus,
561
+ supersededBy: v.optional(v.id("epistemicNodes")),
562
+ // === OWNERSHIP ===
563
+ topicId: v.optional(v.string()),
564
+ // Canonical scope container (topic-first model)
565
+ projectId: v.optional(v.string()),
566
+ // DEPRECATED: Use belongs_to edges
567
+ createdBy: v.string(),
568
+ // Clerk user ID
569
+ createdAt: v.number(),
570
+ updatedAt: v.number(),
571
+ // === NEO4J SYNC STATUS ===
572
+ syncStatus: v.optional(syncStatus),
573
+ syncError: v.optional(v.string())
574
+ // Error message if sync failed
575
+ }).index("by_globalId", ["globalId"]).index("by_contentHash", ["contentHash"]).index("by_nodeType", ["nodeType"]).index("by_subtype", ["nodeType", "subtype"]).index("by_domain", ["domain"]).index("by_project", ["projectId"]).index("by_project_type", ["projectId", "nodeType"]).index("by_topic", ["topicId"]).index("by_topic_type", ["topicId", "nodeType"]).index("by_tenantId", ["tenantId"]).index("by_workspaceId", ["workspaceId"]).index("by_tenant_workspace", ["tenantId", "workspaceId"]).index("by_audienceLabel", ["audienceLabel"]).index("by_sensitivityTier", ["sensitivityTier"]).index("by_exportClass", ["exportClass"]).index("by_status", ["status"]).index("by_sourceType", ["sourceType"]).index("by_verification", ["verificationStatus"]).index("by_layer", ["epistemicLayer"]).index("by_layer_type", ["epistemicLayer", "nodeType"]).index("by_syncStatus", ["syncStatus"]).index("by_publicationStatus", ["publicationStatus"]).index("by_tenant_publicationStatus", ["tenantId", "publicationStatus"]).index("by_belief_status", ["nodeType", "beliefStatus"]).index("by_epistemic_status", ["nodeType", "epistemicStatus"]).index("by_temporal_nature", ["nodeType", "temporalNature"]).index("by_methodology", ["nodeType", "methodology"]).index("by_reversibility", ["nodeType", "reversibility"]).index("by_questionType", ["nodeType", "questionType"]).index("by_questionPriority", ["nodeType", "questionPriority"]).searchIndex("search_canonicalText", {
576
+ searchField: "canonicalText",
577
+ filterFields: ["nodeType", "projectId", "topicId", "status"]
578
+ });
579
+ function getLayerForNodeType(type) {
580
+ switch (type) {
581
+ case "decision":
582
+ return "L4";
583
+ case "belief":
584
+ case "question":
585
+ case "theme":
586
+ case "deal":
587
+ return "L3";
588
+ case "claim":
589
+ case "evidence":
590
+ case "synthesis":
591
+ case "answer":
592
+ return "L2";
593
+ case "atomic_fact":
594
+ case "excerpt":
595
+ case "source":
596
+ return "L1";
597
+ case "topic":
598
+ return "organizational";
599
+ case "company":
600
+ case "person":
601
+ case "investor":
602
+ case "function":
603
+ case "value_chain":
604
+ return "ontological";
605
+ }
606
+ }
607
+ var api = anyApi;
608
+ componentsGeneric();
609
+
610
+ // src/topicScope.ts
611
+ var LEGACY_SCOPE_FIELD = "graphScopeProjectId";
612
+ function asMappedProjectId(topic) {
613
+ if (!topic) {
614
+ return;
615
+ }
616
+ const directLegacyProjectId = normalizeScopeValue(topic[LEGACY_SCOPE_FIELD]);
617
+ if (directLegacyProjectId) {
618
+ return directLegacyProjectId;
619
+ }
620
+ const metadata = topic.metadata || {};
621
+ const candidate = metadata[LEGACY_SCOPE_FIELD] || metadata.legacyProjectId || metadata.projectId || metadata.scopeProjectId;
622
+ return candidate ? candidate : void 0;
623
+ }
624
+ function normalizeScopeValue(value) {
625
+ if (typeof value !== "string") {
626
+ return;
627
+ }
628
+ const normalized = value.trim();
629
+ return normalized.length > 0 ? normalized : void 0;
630
+ }
631
+ function pickPrimaryTopic(candidates) {
632
+ return [...candidates].sort((a, b) => {
633
+ const depthA = a.depth ?? 9999;
634
+ const depthB = b.depth ?? 9999;
635
+ if (depthA !== depthB) {
636
+ return depthA - depthB;
637
+ }
638
+ const createdA = a.createdAt ?? Number.MAX_SAFE_INTEGER;
639
+ const createdB = b.createdAt ?? Number.MAX_SAFE_INTEGER;
640
+ if (createdA !== createdB) {
641
+ return createdA - createdB;
642
+ }
643
+ return String(a.name || "").localeCompare(String(b.name || ""));
644
+ })[0];
645
+ }
646
+ async function findTopicsByScopeAlias(ctx, scopeId) {
647
+ try {
648
+ return await ctx.db.query("topics").withIndex(
649
+ "by_graph_scope_project",
650
+ (q) => q.eq(LEGACY_SCOPE_FIELD, scopeId)
651
+ ).collect();
652
+ } catch {
653
+ const topics = await ctx.db.query("topics").collect();
654
+ return topics.filter((topic) => {
655
+ const normalizedGlobalId = normalizeScopeValue(topic.globalId);
656
+ const mappedProjectId = asMappedProjectId(topic);
657
+ return String(topic._id) === scopeId || normalizedGlobalId === scopeId || mappedProjectId === scopeId;
658
+ });
659
+ }
660
+ }
661
+ async function tryResolveHostTopicById(ctx, topicId) {
662
+ if (typeof ctx.runQuery !== "function") {
663
+ return null;
664
+ }
665
+ try {
666
+ return await ctx.runQuery(api.topics.get, {
667
+ id: topicId
668
+ }) ?? null;
669
+ } catch {
670
+ return null;
671
+ }
672
+ }
673
+ async function tryResolveHostTopicByLegacyScope(ctx, legacyScopeId) {
674
+ if (typeof ctx.runQuery !== "function") {
675
+ return null;
676
+ }
677
+ try {
678
+ return await ctx.runQuery(api.topics.getByLegacyScopeId, {
679
+ projectId: legacyScopeId
680
+ }) ?? null;
681
+ } catch {
682
+ return null;
683
+ }
684
+ }
685
+ async function resolveInheritedWorkspaceScope(ctx, topic) {
686
+ const MAX_DEPTH = 10;
687
+ let tenantId = normalizeScopeValue(topic.tenantId);
688
+ let workspaceId = normalizeScopeValue(topic.workspaceId);
689
+ if (tenantId && workspaceId) {
690
+ return { tenantId, workspaceId };
691
+ }
692
+ let current = topic;
693
+ for (let i = 0; i < MAX_DEPTH && current?.parentTopicId; i++) {
694
+ current = await ctx.db.get(current.parentTopicId);
695
+ if (!current) break;
696
+ if (!tenantId) {
697
+ tenantId = normalizeScopeValue(current.tenantId);
698
+ }
699
+ if (!workspaceId) {
700
+ workspaceId = normalizeScopeValue(current.workspaceId);
701
+ }
702
+ if (tenantId && workspaceId) break;
703
+ }
704
+ return { tenantId, workspaceId };
705
+ }
706
+ async function resolveTopicProjectScope(ctx, args) {
707
+ if (args.topicId) {
708
+ let topic = null;
709
+ try {
710
+ topic = await ctx.db.get(args.topicId);
711
+ } catch {
712
+ }
713
+ if (!topic) {
714
+ topic = await tryResolveHostTopicById(ctx, String(args.topicId));
715
+ }
716
+ if (!topic) {
717
+ topic = pickPrimaryTopic(
718
+ await findTopicsByScopeAlias(ctx, String(args.topicId))
719
+ ) ?? null;
720
+ }
721
+ if (!topic) {
722
+ throw new Error(`Topic not found: ${String(args.topicId)}`);
723
+ }
724
+ const inherited = await resolveInheritedWorkspaceScope(ctx, topic);
725
+ const mapped = asMappedProjectId(topic);
726
+ if (mapped) {
727
+ return {
728
+ topicId: topic._id,
729
+ projectId: mapped,
730
+ tenantId: inherited.tenantId,
731
+ workspaceId: inherited.workspaceId,
732
+ source: "topic"
733
+ };
734
+ }
735
+ return {
736
+ topicId: topic._id,
737
+ tenantId: inherited.tenantId,
738
+ workspaceId: inherited.workspaceId,
739
+ source: "topic"
740
+ };
741
+ }
742
+ if (args.projectId) {
743
+ let directTopic = null;
744
+ try {
745
+ directTopic = await ctx.db.get(
746
+ args.projectId
747
+ );
748
+ } catch {
749
+ }
750
+ if (directTopic) {
751
+ const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);
752
+ const mapped = asMappedProjectId(directTopic);
753
+ return {
754
+ topicId: directTopic._id,
755
+ projectId: mapped ?? args.projectId,
756
+ tenantId: inherited.tenantId,
757
+ workspaceId: inherited.workspaceId,
758
+ source: "topic_inferred"
759
+ };
760
+ }
761
+ directTopic = await tryResolveHostTopicByLegacyScope(ctx, args.projectId);
762
+ if (directTopic) {
763
+ const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);
764
+ const mapped = asMappedProjectId(directTopic);
765
+ return {
766
+ topicId: directTopic._id,
767
+ projectId: mapped ?? args.projectId,
768
+ tenantId: inherited.tenantId,
769
+ workspaceId: inherited.workspaceId,
770
+ source: "topic_inferred"
771
+ };
772
+ }
773
+ const topics = await findTopicsByScopeAlias(ctx, args.projectId);
774
+ const primary = pickPrimaryTopic(topics);
775
+ if (primary) {
776
+ const inherited = await resolveInheritedWorkspaceScope(ctx, primary);
777
+ return {
778
+ topicId: primary._id,
779
+ projectId: args.projectId,
780
+ tenantId: inherited.tenantId,
781
+ workspaceId: inherited.workspaceId,
782
+ source: "project_mapped_topic"
783
+ };
784
+ }
785
+ throw new Error(
786
+ `Legacy project scope ${String(args.projectId)} has no mapped topic.`
787
+ );
788
+ }
789
+ throw new Error(
790
+ "Missing scope: provide topicId (preferred) or legacy projectId alias."
791
+ );
792
+ }
793
+ ({
794
+ projectId: v.optional(v.string()),
795
+ topicId: v.optional(v.string())
796
+ });
797
+
798
+ // src/workspaceIsolation.ts
799
+ function normalizeScopeValue2(value) {
800
+ if (typeof value !== "string") {
801
+ return;
802
+ }
803
+ const normalized = value.trim();
804
+ return normalized.length > 0 ? normalized : void 0;
805
+ }
806
+ function throwWorkspaceIsolationError(args) {
807
+ const error = new Error(args.message);
808
+ error.status = 409;
809
+ error.code = "INVARIANT_VIOLATION";
810
+ error.invariantCode = args.invariantCode;
811
+ error.suggestion = args.suggestion;
812
+ error.details = args.details;
813
+ throw error;
814
+ }
815
+ function assertWorkspaceScopedEpistemicNodeScope(args) {
816
+ const layer = getLayerForNodeType(args.nodeType);
817
+ if (layer === "ontological") {
818
+ return;
819
+ }
820
+ const workspaceId = normalizeScopeValue2(args.scope.workspaceId);
821
+ if (workspaceId) {
822
+ return;
823
+ }
824
+ throwWorkspaceIsolationError({
825
+ message: "Workspace-scoped reasoning isolation requires workspaceId on non-ontological node creation.",
826
+ invariantCode: "workspace.scope_required_for_epistemic_nodes",
827
+ suggestion: "Resolve the topic/project scope through a workspace-bound topic before creating epistemic nodes.",
828
+ details: {
829
+ mutationName: args.mutationName,
830
+ nodeType: args.nodeType,
831
+ topicId: args.scope.topicId,
832
+ projectId: args.scope.projectId
833
+ }
834
+ });
835
+ }
836
+ function nodeMatchesWorkspaceReasoningScope(node, scope) {
837
+ if (!node) {
838
+ return false;
839
+ }
840
+ const scopeTenantId = normalizeScopeValue2(scope.tenantId);
841
+ const scopeWorkspaceId = normalizeScopeValue2(scope.workspaceId);
842
+ const nodeTenantId = normalizeScopeValue2(node.tenantId);
843
+ const nodeWorkspaceId = normalizeScopeValue2(node.workspaceId);
844
+ const epistemicLayer2 = typeof node.epistemicLayer === "string" ? node.epistemicLayer : void 0;
845
+ if (scopeTenantId && nodeTenantId && scopeTenantId !== nodeTenantId) {
846
+ return false;
847
+ }
848
+ if (epistemicLayer2 === "ontological" && nodeWorkspaceId === void 0) {
849
+ return true;
850
+ }
851
+ if (!scopeWorkspaceId && node.publicationStatus === "published") {
852
+ return true;
853
+ }
854
+ if (!scopeWorkspaceId) {
855
+ return nodeWorkspaceId === void 0;
856
+ }
857
+ return scopeWorkspaceId === nodeWorkspaceId;
858
+ }
859
+ function edgeMatchesWorkspaceReasoningScope(edge, scope) {
860
+ if (!edge) {
861
+ return false;
862
+ }
863
+ const scopeTenantId = normalizeScopeValue2(scope.tenantId);
864
+ const scopeWorkspaceId = normalizeScopeValue2(scope.workspaceId);
865
+ const edgeTenantId = normalizeScopeValue2(edge.tenantId);
866
+ const edgeWorkspaceId = normalizeScopeValue2(edge.workspaceId);
867
+ if (scopeTenantId && edgeTenantId && scopeTenantId !== edgeTenantId) {
868
+ return false;
869
+ }
870
+ if (!scopeWorkspaceId) {
871
+ return edgeWorkspaceId === void 0;
872
+ }
873
+ return scopeWorkspaceId === edgeWorkspaceId;
874
+ }
875
+ async function resolveNodeScopeForWorkspaceIsolation(ctx, node) {
876
+ const epistemicLayer2 = typeof node?.epistemicLayer === "string" ? node.epistemicLayer : void 0;
877
+ const resolved = {
878
+ tenantId: normalizeScopeValue2(node?.tenantId),
879
+ workspaceId: normalizeScopeValue2(node?.workspaceId),
880
+ epistemicLayer: epistemicLayer2,
881
+ nodeType: typeof node?.nodeType === "string" ? node.nodeType : void 0
882
+ };
883
+ if (!node) {
884
+ return resolved;
885
+ }
886
+ if (resolved.epistemicLayer === "ontological") {
887
+ return resolved;
888
+ }
889
+ if (resolved.tenantId || resolved.workspaceId) {
890
+ return resolved;
891
+ }
892
+ if (node.topicId) {
893
+ const topicScope = await resolveTopicProjectScope(ctx, {
894
+ topicId: node.topicId
895
+ });
896
+ return {
897
+ ...resolved,
898
+ tenantId: topicScope.tenantId,
899
+ workspaceId: topicScope.workspaceId
900
+ };
901
+ }
902
+ if (node.projectId) {
903
+ const topicScope = await resolveTopicProjectScope(ctx, {
904
+ projectId: String(node.projectId)
905
+ });
906
+ return {
907
+ ...resolved,
908
+ tenantId: topicScope.tenantId,
909
+ workspaceId: topicScope.workspaceId
910
+ };
911
+ }
912
+ return resolved;
913
+ }
914
+ function resolveRuntimePackMutationContext(args) {
915
+ if (!args.runtimeToolName && !args.runtimePackKey && !args.runtimePackInstallScope) {
916
+ return;
917
+ }
918
+ return {
919
+ toolName: args.runtimeToolName,
920
+ packKey: args.runtimePackKey,
921
+ packInstallScope: args.runtimePackInstallScope
922
+ };
923
+ }
924
+ function assertTenantPackWorkspaceMutationAllowed(args) {
925
+ if (!args.runtime?.packKey || args.runtime.packInstallScope !== "tenant") {
926
+ return;
927
+ }
928
+ const targetWorkspaceId = normalizeScopeValue2(args.target.workspaceId);
929
+ const targetLayer = typeof args.target.epistemicLayer === "string" ? args.target.epistemicLayer : void 0;
930
+ if (!targetWorkspaceId || targetLayer === "ontological") {
931
+ return;
932
+ }
933
+ throwWorkspaceIsolationError({
934
+ message: `Tenant-scoped pack "${args.runtime.packKey}" cannot mutate workspace-scoped reasoning state.`,
935
+ invariantCode: "workspace.tenant_pack_reasoning_write_forbidden",
936
+ suggestion: "Use a workspace-scoped pack for workspace-local graph mutations, or route the change through tenant-global canonical entity flows.",
937
+ details: {
938
+ mutationName: args.mutationName,
939
+ toolName: args.runtime.toolName,
940
+ packKey: args.runtime.packKey,
941
+ targetWorkspaceId,
942
+ targetNodeType: args.target.nodeType,
943
+ targetLayer
944
+ }
945
+ });
946
+ }
947
+
948
+ export { assertTenantPackWorkspaceMutationAllowed, assertWorkspaceScopedEpistemicNodeScope, edgeMatchesWorkspaceReasoningScope, nodeMatchesWorkspaceReasoningScope, normalizeScopeValue2 as normalizeScopeValue, resolveNodeScopeForWorkspaceIsolation, resolveRuntimePackMutationContext };
949
+ //# sourceMappingURL=workspaceIsolation.js.map
950
+ //# sourceMappingURL=workspaceIsolation.js.map