@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.
- package/README.md +29 -0
- package/dist/beliefDecay-Q_26RTc-.d.ts +72 -0
- package/dist/beliefDecay.d.ts +2 -0
- package/dist/beliefDecay.js +1628 -0
- package/dist/beliefDecay.js.map +1 -0
- package/dist/beliefEvidenceLinks-42FlR48t.d.ts +77 -0
- package/dist/beliefEvidenceLinks.d.ts +1 -0
- package/dist/beliefEvidenceLinks.js +1978 -0
- package/dist/beliefEvidenceLinks.js.map +1 -0
- package/dist/beliefLifecycle-C-AehZgF.d.ts +43 -0
- package/dist/beliefLifecycle.d.ts +1 -0
- package/dist/beliefLifecycle.js +98 -0
- package/dist/beliefLifecycle.js.map +1 -0
- package/dist/confidencePropagationDispatch.d.ts +46 -0
- package/dist/confidencePropagationDispatch.js +744 -0
- package/dist/confidencePropagationDispatch.js.map +1 -0
- package/dist/contradictions-Hdwl7zid.d.ts +71 -0
- package/dist/contradictions.d.ts +1 -0
- package/dist/contradictions.js +1557 -0
- package/dist/contradictions.js.map +1 -0
- package/dist/convex.d.ts +23 -0
- package/dist/convex.js +17 -0
- package/dist/convex.js.map +1 -0
- package/dist/edgeValidation-CeI0wc0r.d.ts +35 -0
- package/dist/edgeValidation.d.ts +2 -0
- package/dist/edgeValidation.js +307 -0
- package/dist/edgeValidation.js.map +1 -0
- package/dist/edges/contains.d.ts +6 -0
- package/dist/edges/contains.js +14 -0
- package/dist/edges/contains.js.map +1 -0
- package/dist/edges/contradicts.d.ts +6 -0
- package/dist/edges/contradicts.js +183 -0
- package/dist/edges/contradicts.js.map +1 -0
- package/dist/edges/dependsOn.d.ts +6 -0
- package/dist/edges/dependsOn.js +240 -0
- package/dist/edges/dependsOn.js.map +1 -0
- package/dist/edges/derivedFrom.d.ts +6 -0
- package/dist/edges/derivedFrom.js +14 -0
- package/dist/edges/derivedFrom.js.map +1 -0
- package/dist/edges/elaborates.d.ts +6 -0
- package/dist/edges/elaborates.js +100 -0
- package/dist/edges/elaborates.js.map +1 -0
- package/dist/edges/index.d.ts +3 -0
- package/dist/edges/index.js +556 -0
- package/dist/edges/index.js.map +1 -0
- package/dist/edges/informs.d.ts +6 -0
- package/dist/edges/informs.js +112 -0
- package/dist/edges/informs.js.map +1 -0
- package/dist/edges/propagationTypes.d.ts +39 -0
- package/dist/edges/propagationTypes.js +17 -0
- package/dist/edges/propagationTypes.js.map +1 -0
- package/dist/edges/refutes.d.ts +6 -0
- package/dist/edges/refutes.js +108 -0
- package/dist/edges/refutes.js.map +1 -0
- package/dist/edges/supports.d.ts +6 -0
- package/dist/edges/supports.js +193 -0
- package/dist/edges/supports.js.map +1 -0
- package/dist/edges/tests.d.ts +6 -0
- package/dist/edges/tests.js +14 -0
- package/dist/edges/tests.js.map +1 -0
- package/dist/edges/utils.d.ts +12 -0
- package/dist/edges/utils.js +188 -0
- package/dist/edges/utils.js.map +1 -0
- package/dist/embeddingTrigger.d.ts +24 -0
- package/dist/embeddingTrigger.js +24 -0
- package/dist/embeddingTrigger.js.map +1 -0
- package/dist/entityBridge-DMaKooYn.d.ts +59 -0
- package/dist/entityBridge.d.ts +1 -0
- package/dist/entityBridge.js +663 -0
- package/dist/entityBridge.js.map +1 -0
- package/dist/entityLifecycle-BkhRJ-XI.d.ts +69 -0
- package/dist/entityLifecycle.d.ts +1 -0
- package/dist/entityLifecycle.js +2083 -0
- package/dist/entityLifecycle.js.map +1 -0
- package/dist/entityValidation-KLZ_Xl2D.d.ts +50 -0
- package/dist/entityValidation.d.ts +3 -0
- package/dist/entityValidation.js +71 -0
- package/dist/entityValidation.js.map +1 -0
- package/dist/epistemicAnswers-DSP1slZ9.d.ts +67 -0
- package/dist/epistemicAnswers.d.ts +1 -0
- package/dist/epistemicAnswers.js +1650 -0
- package/dist/epistemicAnswers.js.map +1 -0
- package/dist/epistemicBeliefs-DtFVTp-k.d.ts +377 -0
- package/dist/epistemicBeliefs.d.ts +5 -0
- package/dist/epistemicBeliefs.js +6386 -0
- package/dist/epistemicBeliefs.js.map +1 -0
- package/dist/epistemicContractHelpers.d.ts +1 -0
- package/dist/epistemicContractHelpers.js +320 -0
- package/dist/epistemicContractHelpers.js.map +1 -0
- package/dist/epistemicContracts.d.ts +77 -0
- package/dist/epistemicContracts.js +8436 -0
- package/dist/epistemicContracts.js.map +1 -0
- package/dist/epistemicEdges-DcA8ErUG.d.ts +191 -0
- package/dist/epistemicEdges.d.ts +2 -0
- package/dist/epistemicEdges.js +2749 -0
- package/dist/epistemicEdges.js.map +1 -0
- package/dist/epistemicEvidence-Bo638XDP.d.ts +128 -0
- package/dist/epistemicEvidence.d.ts +3 -0
- package/dist/epistemicEvidence.js +3282 -0
- package/dist/epistemicEvidence.js.map +1 -0
- package/dist/epistemicHelpers-Bd9xbaib.d.ts +329 -0
- package/dist/epistemicHelpers.d.ts +4 -0
- package/dist/epistemicHelpers.js +999 -0
- package/dist/epistemicHelpers.js.map +1 -0
- package/dist/epistemicLinking-CyeLOIzN.d.ts +35 -0
- package/dist/epistemicLinking.d.ts +1 -0
- package/dist/epistemicLinking.js +1391 -0
- package/dist/epistemicLinking.js.map +1 -0
- package/dist/epistemicNodes-BpD6Koud.d.ts +167 -0
- package/dist/epistemicNodes.d.ts +2 -0
- package/dist/epistemicNodes.js +2942 -0
- package/dist/epistemicNodes.js.map +1 -0
- package/dist/epistemicQuestions-CmEeY6zQ.d.ts +214 -0
- package/dist/epistemicQuestions.d.ts +3 -0
- package/dist/epistemicQuestions.js +4993 -0
- package/dist/epistemicQuestions.js.map +1 -0
- package/dist/epistemicSources-ZazxHOK1.d.ts +25 -0
- package/dist/epistemicSources.d.ts +1 -0
- package/dist/epistemicSources.js +2025 -0
- package/dist/epistemicSources.js.map +1 -0
- package/dist/evaluators/index.d.ts +9 -0
- package/dist/evaluators/index.js +8440 -0
- package/dist/evaluators/index.js.map +1 -0
- package/dist/evaluators/lintCheckerEvaluator.d.ts +11 -0
- package/dist/evaluators/lintCheckerEvaluator.js +155 -0
- package/dist/evaluators/lintCheckerEvaluator.js.map +1 -0
- package/dist/evaluators/sentryCheckerEvaluator.d.ts +11 -0
- package/dist/evaluators/sentryCheckerEvaluator.js +126 -0
- package/dist/evaluators/sentryCheckerEvaluator.js.map +1 -0
- package/dist/evaluators/shared.d.ts +27 -0
- package/dist/evaluators/shared.js +92 -0
- package/dist/evaluators/shared.js.map +1 -0
- package/dist/evaluators/testRunnerEvaluator.d.ts +17 -0
- package/dist/evaluators/testRunnerEvaluator.js +232 -0
- package/dist/evaluators/testRunnerEvaluator.js.map +1 -0
- package/dist/evaluators/tscCheckerEvaluator.d.ts +11 -0
- package/dist/evaluators/tscCheckerEvaluator.js +189 -0
- package/dist/evaluators/tscCheckerEvaluator.js.map +1 -0
- package/dist/globalId-DKh9d_uD.d.ts +20 -0
- package/dist/globalId.d.ts +1 -0
- package/dist/globalId.js +15 -0
- package/dist/globalId.js.map +1 -0
- package/dist/graphTypes-CpgIuCdo.d.ts +52 -0
- package/dist/graphTypes.d.ts +1 -0
- package/dist/graphTypes.js +120 -0
- package/dist/graphTypes.js.map +1 -0
- package/dist/helpers-BYHIk5vU.d.ts +27 -0
- package/dist/helpers.d.ts +4 -0
- package/dist/helpers.js +313 -0
- package/dist/helpers.js.map +1 -0
- package/dist/index-Dct1T70K.d.ts +25 -0
- package/dist/index-Dq-7R-gi.d.ts +31 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.js +22294 -0
- package/dist/index.js.map +1 -0
- package/dist/invariantEnforcement.d.ts +52 -0
- package/dist/invariantEnforcement.js +231 -0
- package/dist/invariantEnforcement.js.map +1 -0
- package/dist/logicalRoleInference-CJxqWi3u.d.ts +16 -0
- package/dist/logicalRoleInference.d.ts +3 -0
- package/dist/logicalRoleInference.js +64 -0
- package/dist/logicalRoleInference.js.map +1 -0
- package/dist/matcherFeedbackUtils.d.ts +33 -0
- package/dist/matcherFeedbackUtils.js +95 -0
- package/dist/matcherFeedbackUtils.js.map +1 -0
- package/dist/ontology-matching-Buhu23ss.d.ts +48 -0
- package/dist/ontology-matching.d.ts +2 -0
- package/dist/ontology-matching.js +346 -0
- package/dist/ontology-matching.js.map +1 -0
- package/dist/ontologyApproval-Ba0Jjk1k.d.ts +26 -0
- package/dist/ontologyApproval.d.ts +1 -0
- package/dist/ontologyApproval.js +78 -0
- package/dist/ontologyApproval.js.map +1 -0
- package/dist/ontologyDefinitions.d.ts +72 -0
- package/dist/ontologyDefinitions.js +635 -0
- package/dist/ontologyDefinitions.js.map +1 -0
- package/dist/ontologyHelpers.d.ts +79 -0
- package/dist/ontologyHelpers.js +81 -0
- package/dist/ontologyHelpers.js.map +1 -0
- package/dist/ontologyRegistry-B67rPJ16.d.ts +31 -0
- package/dist/ontologyRegistry.d.ts +1 -0
- package/dist/ontologyRegistry.js +296 -0
- package/dist/ontologyRegistry.js.map +1 -0
- package/dist/projectionReconciliation-CxrXYGaB.d.ts +20 -0
- package/dist/projectionReconciliation.d.ts +1 -0
- package/dist/projectionReconciliation.js +261 -0
- package/dist/projectionReconciliation.js.map +1 -0
- package/dist/projectionStaleness-CAdpIsaW.d.ts +51 -0
- package/dist/projectionStaleness.d.ts +1 -0
- package/dist/projectionStaleness.js +57 -0
- package/dist/projectionStaleness.js.map +1 -0
- package/dist/questionEvidenceLinks-BdQD0TkM.d.ts +34 -0
- package/dist/questionEvidenceLinks.d.ts +1 -0
- package/dist/questionEvidenceLinks.js +1690 -0
- package/dist/questionEvidenceLinks.js.map +1 -0
- package/dist/resolverTypes-CC8Ea2E2.d.ts +20 -0
- package/dist/resolverTypes.d.ts +4 -0
- package/dist/resolverTypes.js +3 -0
- package/dist/resolverTypes.js.map +1 -0
- package/dist/resolvers-Br1a6eLV.d.ts +14 -0
- package/dist/resolvers.d.ts +5 -0
- package/dist/resolvers.js +308 -0
- package/dist/resolvers.js.map +1 -0
- package/dist/scopeResolverCompat.d.ts +26 -0
- package/dist/scopeResolverCompat.js +242 -0
- package/dist/scopeResolverCompat.js.map +1 -0
- package/dist/text-matching-CMn2WnVD.d.ts +40 -0
- package/dist/text-matching.d.ts +2 -0
- package/dist/text-matching.js +246 -0
- package/dist/text-matching.js.map +1 -0
- package/dist/topicOntologyResolver.d.ts +80 -0
- package/dist/topicOntologyResolver.js +67 -0
- package/dist/topicOntologyResolver.js.map +1 -0
- package/dist/topicProjectOverlay.d.ts +92 -0
- package/dist/topicProjectOverlay.js +249 -0
- package/dist/topicProjectOverlay.js.map +1 -0
- package/dist/topicScope-By_zp4tt.d.ts +34 -0
- package/dist/topicScope.d.ts +3 -0
- package/dist/topicScope.js +206 -0
- package/dist/topicScope.js.map +1 -0
- package/dist/workspaceIsolation.d.ts +44 -0
- package/dist/workspaceIsolation.js +950 -0
- package/dist/workspaceIsolation.js.map +1 -0
- 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
|