@lucern/graph-primitives 1.0.29 → 1.0.30
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/dist/{beliefDecay-DZ6tkLYq.d.ts → beliefDecay-BmkEk5OJ.d.ts} +3 -3
- package/dist/beliefDecay.d.ts +1 -1
- package/dist/beliefDecay.js +448 -314
- package/dist/beliefDecay.js.map +1 -1
- package/dist/{beliefEvidenceLinks-CWOXxxJg.d.ts → beliefEvidenceLinks-BzfjON_6.d.ts} +13 -13
- package/dist/beliefEvidenceLinks.d.ts +1 -1
- package/dist/beliefEvidenceLinks.js +843 -624
- package/dist/beliefEvidenceLinks.js.map +1 -1
- package/dist/beliefEvidenceLinks.operational.d.ts +7 -5
- package/dist/beliefEvidenceLinks.operational.js +91 -18
- package/dist/beliefEvidenceLinks.operational.js.map +1 -1
- package/dist/beliefLifecycle.js.map +1 -1
- package/dist/confidencePropagationDispatch.d.ts +28 -27
- package/dist/confidencePropagationDispatch.js +157 -99
- package/dist/confidencePropagationDispatch.js.map +1 -1
- package/dist/{contradictions-51VLsESq.d.ts → contradictions-BATPuZTL.d.ts} +10 -10
- package/dist/contradictions.d.ts +1 -1
- package/dist/contradictions.js +395 -225
- package/dist/contradictions.js.map +1 -1
- package/dist/convex.d.ts +65 -30
- package/dist/convex.js +7 -3
- package/dist/convex.js.map +1 -1
- package/dist/debug.js.map +1 -1
- package/dist/edgeValidation.js +293 -85
- package/dist/edgeValidation.js.map +1 -1
- package/dist/edges/contains.d.ts +1 -1
- package/dist/edges/contains.js.map +1 -1
- package/dist/edges/contradicts.d.ts +1 -1
- package/dist/edges/contradicts.js.map +1 -1
- package/dist/edges/{dependsOn.d.ts → depends-on.d.ts} +1 -1
- package/dist/edges/{dependsOn.js → depends-on.js} +4 -4
- package/dist/edges/depends-on.js.map +1 -0
- package/dist/edges/{derivedFrom.d.ts → derived-from.d.ts} +1 -1
- package/dist/edges/{derivedFrom.js → derived-from.js} +3 -3
- package/dist/edges/derived-from.js.map +1 -0
- package/dist/edges/elaborates.d.ts +1 -1
- package/dist/edges/elaborates.js.map +1 -1
- package/dist/edges/index.d.ts +7 -3
- package/dist/edges/index.js +7 -4
- package/dist/edges/index.js.map +1 -1
- package/dist/edges/informs.d.ts +1 -1
- package/dist/edges/informs.js.map +1 -1
- package/dist/edges/{propagationTypes.d.ts → propagation-types.d.ts} +14 -14
- package/dist/edges/{propagationTypes.js → propagation-types.js} +3 -3
- package/dist/edges/propagation-types.js.map +1 -0
- package/dist/edges/refutes.d.ts +1 -1
- package/dist/edges/refutes.js.map +1 -1
- package/dist/edges/supports.d.ts +1 -1
- package/dist/edges/supports.js.map +1 -1
- package/dist/edges/tests.d.ts +1 -1
- package/dist/edges/tests.js.map +1 -1
- package/dist/edges/utils.d.ts +1 -1
- package/dist/edges/utils.js.map +1 -1
- package/dist/embeddingTrigger.d.ts +14 -6
- package/dist/embeddingTrigger.js +11 -14
- package/dist/embeddingTrigger.js.map +1 -1
- package/dist/{entityBridge-DMaKooYn.d.ts → entityBridge-BhVDM3pc.d.ts} +5 -5
- package/dist/entityBridge.d.ts +1 -1
- package/dist/entityBridge.js +602 -225
- package/dist/entityBridge.js.map +1 -1
- package/dist/entityCanonicalMatch.d.ts +14 -12
- package/dist/entityCanonicalMatch.js.map +1 -1
- package/dist/{entityLifecycle-CvgSK5FV.d.ts → entityLifecycle-BsfCz9pS.d.ts} +5 -9
- package/dist/entityLifecycle.d.ts +1 -1
- package/dist/entityLifecycle.js +854 -480
- package/dist/entityLifecycle.js.map +1 -1
- package/dist/{entityValidation-KLZ_Xl2D.d.ts → entityValidation-B1yNEHJx.d.ts} +7 -6
- package/dist/entityValidation.d.ts +3 -1
- package/dist/entityValidation.js +60 -8
- package/dist/entityValidation.js.map +1 -1
- package/dist/{epistemicAnswers-C5ib4z6_.d.ts → epistemicAnswers-f47YMu9U.d.ts} +6 -6
- package/dist/epistemicAnswers.d.ts +1 -1
- package/dist/epistemicAnswers.js +587 -545
- package/dist/epistemicAnswers.js.map +1 -1
- package/dist/epistemicBeliefs.admin.d.ts +8 -8
- package/dist/epistemicBeliefs.admin.js +365 -166
- package/dist/epistemicBeliefs.admin.js.map +1 -1
- package/dist/epistemicBeliefs.backfills.d.ts +8 -8
- package/dist/epistemicBeliefs.backfills.js +655 -289
- package/dist/epistemicBeliefs.backfills.js.map +1 -1
- package/dist/epistemicBeliefs.confidence.d.ts +19 -15
- package/dist/epistemicBeliefs.confidence.js +633 -386
- package/dist/epistemicBeliefs.confidence.js.map +1 -1
- package/dist/epistemicBeliefs.core.d.ts +6 -6
- package/dist/epistemicBeliefs.core.js +717 -371
- package/dist/epistemicBeliefs.core.js.map +1 -1
- package/dist/epistemicBeliefs.d.ts +11 -9
- package/dist/epistemicBeliefs.forkEvidence.d.ts +2 -0
- package/dist/epistemicBeliefs.forkEvidence.js +8 -8
- package/dist/epistemicBeliefs.forkEvidence.js.map +1 -1
- package/dist/epistemicBeliefs.helpers.d.ts +68 -49
- package/dist/epistemicBeliefs.helpers.js +358 -211
- package/dist/epistemicBeliefs.helpers.js.map +1 -1
- package/dist/epistemicBeliefs.internal.d.ts +5 -5
- package/dist/epistemicBeliefs.internal.js +1248 -1026
- package/dist/epistemicBeliefs.internal.js.map +1 -1
- package/dist/epistemicBeliefs.js +4942 -3590
- package/dist/epistemicBeliefs.js.map +1 -1
- package/dist/epistemicBeliefs.lifecycle.d.ts +5 -5
- package/dist/epistemicBeliefs.lifecycle.js +1138 -781
- package/dist/epistemicBeliefs.lifecycle.js.map +1 -1
- package/dist/epistemicBeliefs.links.d.ts +7 -7
- package/dist/epistemicBeliefs.links.js +404 -267
- package/dist/epistemicBeliefs.links.js.map +1 -1
- package/dist/epistemicBeliefs.queries.d.ts +4 -4
- package/dist/epistemicBeliefs.queries.js +175 -20
- package/dist/epistemicBeliefs.queries.js.map +1 -1
- package/dist/epistemicBeliefs.topicAnchor.d.ts +6 -4
- package/dist/epistemicBeliefs.topicAnchor.js +12 -5
- package/dist/epistemicBeliefs.topicAnchor.js.map +1 -1
- package/dist/epistemicContracts.d.ts +28 -3
- package/dist/epistemicContracts.evaluators.d.ts +2 -0
- package/dist/epistemicContracts.evaluators.js +1062 -576
- package/dist/epistemicContracts.evaluators.js.map +1 -1
- package/dist/epistemicContracts.handlers.d.ts +15 -32
- package/dist/epistemicContracts.handlers.js +1829 -1351
- package/dist/epistemicContracts.handlers.js.map +1 -1
- package/dist/epistemicContracts.js +1131 -636
- package/dist/epistemicContracts.js.map +1 -1
- package/dist/epistemicContracts.metrics.d.ts +2 -0
- package/dist/epistemicContracts.metrics.js +375 -158
- package/dist/epistemicContracts.metrics.js.map +1 -1
- package/dist/epistemicContracts.types.d.ts +87 -81
- package/dist/epistemicEdgeCreation.d.ts +2 -0
- package/dist/epistemicEdgeCreation.js +87 -16
- package/dist/epistemicEdgeCreation.js.map +1 -1
- package/dist/{epistemicEdges-BF-cn4i3.d.ts → epistemicEdges-BGBh0QSP.d.ts} +4 -7
- package/dist/epistemicEdges.d.ts +6 -5
- package/dist/epistemicEdges.handlers.d.ts +3 -3
- package/dist/epistemicEdges.handlers.js +129 -24
- package/dist/epistemicEdges.handlers.js.map +1 -1
- package/dist/epistemicEdges.helpers.d.ts +6 -4
- package/dist/epistemicEdges.helpers.js +37 -2
- package/dist/epistemicEdges.helpers.js.map +1 -1
- package/dist/epistemicEdges.js +1966 -1202
- package/dist/epistemicEdges.js.map +1 -1
- package/dist/epistemicEdges.mutations.d.ts +7 -7
- package/dist/epistemicEdges.mutations.js +956 -579
- package/dist/epistemicEdges.mutations.js.map +1 -1
- package/dist/epistemicEdges.queries.d.ts +16 -16
- package/dist/epistemicEdges.queries.js +639 -367
- package/dist/epistemicEdges.queries.js.map +1 -1
- package/dist/epistemicEdges.types.d.ts +10 -8
- package/dist/epistemicEvidence.d.ts +4 -1
- package/dist/epistemicEvidence.js +933 -532
- package/dist/epistemicEvidence.js.map +1 -1
- package/dist/epistemicEvidenceHelpers.d.ts +26 -10
- package/dist/epistemicEvidenceHelpers.js +239 -200
- package/dist/epistemicEvidenceHelpers.js.map +1 -1
- package/dist/epistemicEvidenceMutations.d.ts +8 -8
- package/dist/epistemicEvidenceMutations.js +840 -692
- package/dist/epistemicEvidenceMutations.js.map +1 -1
- package/dist/epistemicEvidenceQueries.d.ts +8 -8
- package/dist/epistemicEvidenceQueries.js +514 -238
- package/dist/epistemicEvidenceQueries.js.map +1 -1
- package/dist/epistemicHelpers.d.ts +4 -2
- package/dist/epistemicHelpers.js +308 -134
- package/dist/epistemicHelpers.js.map +1 -1
- package/dist/epistemicInsert.d.ts +16 -4
- package/dist/epistemicInsert.js +6 -3
- package/dist/epistemicInsert.js.map +1 -1
- package/dist/epistemicLayerRules.d.ts +10 -8
- package/dist/epistemicLayerRules.js +1 -5
- package/dist/epistemicLayerRules.js.map +1 -1
- package/dist/{epistemicLinking-CfE00tHJ.d.ts → epistemicLinking-CsCDv2cN.d.ts} +3 -3
- package/dist/epistemicLinking.d.ts +1 -1
- package/dist/epistemicLinking.js +177 -100
- package/dist/epistemicLinking.js.map +1 -1
- package/dist/epistemicNodeCreation.d.ts +2 -0
- package/dist/epistemicNodeCreation.js +203 -40
- package/dist/epistemicNodeCreation.js.map +1 -1
- package/dist/{epistemicNodes-BCQxpYx_.d.ts → epistemicNodes-CokAgBHg.d.ts} +3 -3
- package/dist/epistemicNodes.d.ts +3 -3
- package/dist/epistemicNodes.helpers.d.ts +24 -15
- package/dist/epistemicNodes.helpers.js.map +1 -1
- package/dist/epistemicNodes.internal.d.ts +6 -6
- package/dist/epistemicNodes.internal.js +389 -319
- package/dist/epistemicNodes.internal.js.map +1 -1
- package/dist/epistemicNodes.js +700 -504
- package/dist/epistemicNodes.js.map +1 -1
- package/dist/epistemicNodes.mutations.d.ts +6 -6
- package/dist/epistemicNodes.mutations.js +560 -463
- package/dist/epistemicNodes.mutations.js.map +1 -1
- package/dist/epistemicNodes.queries.d.ts +8 -8
- package/dist/epistemicNodes.queries.js +311 -314
- package/dist/epistemicNodes.queries.js.map +1 -1
- package/dist/epistemicNodes.validators.d.ts +2 -2
- package/dist/epistemicNodes.validators.js.map +1 -1
- package/dist/epistemicQuestions.conviction.d.ts +8 -8
- package/dist/epistemicQuestions.conviction.js +665 -484
- package/dist/epistemicQuestions.conviction.js.map +1 -1
- package/dist/epistemicQuestions.create.d.ts +4 -4
- package/dist/epistemicQuestions.create.js +640 -612
- package/dist/epistemicQuestions.create.js.map +1 -1
- package/dist/epistemicQuestions.d.ts +8 -5
- package/dist/epistemicQuestions.evidence.d.ts +2 -2
- package/dist/epistemicQuestions.evidence.js +475 -383
- package/dist/epistemicQuestions.evidence.js.map +1 -1
- package/dist/epistemicQuestions.helpers.d.ts +125 -24
- package/dist/epistemicQuestions.helpers.js +240 -209
- package/dist/epistemicQuestions.helpers.js.map +1 -1
- package/dist/epistemicQuestions.js +3474 -2823
- package/dist/epistemicQuestions.js.map +1 -1
- package/dist/epistemicQuestions.lifecycle.d.ts +2 -2
- package/dist/epistemicQuestions.lifecycle.js +607 -546
- package/dist/epistemicQuestions.lifecycle.js.map +1 -1
- package/dist/epistemicQuestions.queries.d.ts +12 -7
- package/dist/epistemicQuestions.queries.js +305 -244
- package/dist/epistemicQuestions.queries.js.map +1 -1
- package/dist/epistemicQuestions.sprint.d.ts +2 -2
- package/dist/epistemicQuestions.sprint.js +600 -394
- package/dist/epistemicQuestions.sprint.js.map +1 -1
- package/dist/epistemicQuestions.tail.d.ts +6 -6
- package/dist/epistemicQuestions.tail.js +572 -433
- package/dist/epistemicQuestions.tail.js.map +1 -1
- package/dist/{epistemicSources-dlKj58Jp.d.ts → epistemicSources-DQtaEkWs.d.ts} +4 -4
- package/dist/epistemicSources.d.ts +1 -1
- package/dist/epistemicSources.js +351 -311
- package/dist/epistemicSources.js.map +1 -1
- package/dist/evaluators/index.d.ts +8 -6
- package/dist/evaluators/index.js +399 -167
- package/dist/evaluators/index.js.map +1 -1
- package/dist/evaluators/lint-checker-evaluator.d.ts +16 -0
- package/dist/evaluators/{lintCheckerEvaluator.js → lint-checker-evaluator.js} +10 -5
- package/dist/evaluators/lint-checker-evaluator.js.map +1 -0
- package/dist/evaluators/{sentryCheckerEvaluator.d.ts → sentry-checker-evaluator.d.ts} +7 -2
- package/dist/evaluators/{sentryCheckerEvaluator.js → sentry-checker-evaluator.js} +3 -3
- package/dist/evaluators/sentry-checker-evaluator.js.map +1 -0
- package/dist/evaluators/shared.d.ts +2 -2
- package/dist/evaluators/shared.js +3 -1
- package/dist/evaluators/shared.js.map +1 -1
- package/dist/evaluators/{testRunnerEvaluator.d.ts → test-runner-evaluator.d.ts} +6 -1
- package/dist/evaluators/{testRunnerEvaluator.js → test-runner-evaluator.js} +6 -4
- package/dist/evaluators/test-runner-evaluator.js.map +1 -0
- package/dist/evaluators/tsc-checker-evaluator.d.ts +16 -0
- package/dist/evaluators/{tscCheckerEvaluator.js → tsc-checker-evaluator.js} +10 -5
- package/dist/evaluators/tsc-checker-evaluator.js.map +1 -0
- package/dist/graphTypes.js +6 -2
- package/dist/graphTypes.js.map +1 -1
- package/dist/helpers.d.ts +2 -0
- package/dist/helpers.js +313 -93
- package/dist/helpers.js.map +1 -1
- package/dist/{index-C-Kyd7hD.d.ts → index-DZxyC9Pb.d.ts} +7 -6
- package/dist/index.d.ts +86 -83
- package/dist/index.js +16914 -11760
- package/dist/index.js.map +1 -1
- package/dist/invariantEnforcement.d.ts +3 -3
- package/dist/invariantEnforcement.js.map +1 -1
- package/dist/logicalRoleInference.d.ts +2 -0
- package/dist/logicalRoleInference.js +1 -1
- package/dist/logicalRoleInference.js.map +1 -1
- package/dist/matcherFeedbackUtils.d.ts +2 -2
- package/dist/matcherFeedbackUtils.js.map +1 -1
- package/dist/{ontology-matching-C6rrz2VP.d.ts → ontology-matching-C-mYFrir.d.ts} +16 -16
- package/dist/ontology-matching.d.ts +1 -1
- package/dist/{ontologyApproval-CFYmqKmk.d.ts → ontologyApproval-BVt0feJi.d.ts} +10 -10
- package/dist/ontologyApproval.d.ts +1 -1
- package/dist/ontologyApproval.js +7 -1
- package/dist/ontologyApproval.js.map +1 -1
- package/dist/ontologyDefinitions.d.ts +14 -24
- package/dist/ontologyDefinitions.js +269 -34
- package/dist/ontologyDefinitions.js.map +1 -1
- package/dist/ontologyHelpers.d.ts +13 -13
- package/dist/ontologyHelpers.js.map +1 -1
- package/dist/{ontologyRegistry-B67rPJ16.d.ts → ontologyRegistry-CljS-ENv.d.ts} +2 -2
- package/dist/ontologyRegistry.d.ts +1 -1
- package/dist/ontologyRegistry.js +34 -6
- package/dist/ontologyRegistry.js.map +1 -1
- package/dist/{projectionReconciliation-jww2fBI0.d.ts → projectionReconciliation-DnrSgHSQ.d.ts} +4 -4
- package/dist/projectionReconciliation.d.ts +1 -1
- package/dist/projectionReconciliation.js +57 -10
- package/dist/projectionReconciliation.js.map +1 -1
- package/dist/{projectionStaleness-CmdbpjVK.d.ts → projectionStaleness-C8ImQ2zP.d.ts} +17 -17
- package/dist/projectionStaleness.d.ts +1 -1
- package/dist/projectionStaleness.js +8 -2
- package/dist/projectionStaleness.js.map +1 -1
- package/dist/proof-attestation.json +1 -1
- package/dist/{questionEvidenceLinks-DFlyPpAj.d.ts → questionEvidenceLinks-_nPRa-LY.d.ts} +10 -10
- package/dist/questionEvidenceLinks.d.ts +1 -1
- package/dist/questionEvidenceLinks.js +564 -347
- package/dist/questionEvidenceLinks.js.map +1 -1
- package/dist/{resolverTypes-CC8Ea2E2.d.ts → resolverTypes-BOXPxLET.d.ts} +8 -7
- package/dist/resolverTypes.d.ts +4 -2
- package/dist/{resolvers-Br1a6eLV.d.ts → resolvers-B1TIBmRO.d.ts} +3 -1
- package/dist/resolvers.d.ts +5 -3
- package/dist/resolvers.js +121 -77
- package/dist/resolvers.js.map +1 -1
- package/dist/scopeResolverCompat.d.ts +10 -7
- package/dist/scopeResolverCompat.js +106 -123
- package/dist/scopeResolverCompat.js.map +1 -1
- package/dist/{text-matching-DNg4M5Wd.d.ts → text-matching-DzFooju6.d.ts} +7 -7
- package/dist/text-matching.d.ts +1 -1
- package/dist/topicOntologyResolver.d.ts +22 -21
- package/dist/topicOntologyResolver.js +54 -32
- package/dist/topicOntologyResolver.js.map +1 -1
- package/dist/topicProjectOverlay.d.ts +30 -20
- package/dist/topicProjectOverlay.js +120 -76
- package/dist/topicProjectOverlay.js.map +1 -1
- package/dist/{topicScope-7zhyeGl7.d.ts → topicScope-DJVa0mLa.d.ts} +22 -7
- package/dist/topicScope.d.ts +3 -1
- package/dist/topicScope.js +104 -119
- package/dist/topicScope.js.map +1 -1
- package/dist/workflowBridge.d.ts +26 -15
- package/dist/workflowBridge.js +140 -144
- package/dist/workflowBridge.js.map +1 -1
- package/dist/workspaceIsolation.d.ts +14 -12
- package/dist/workspaceIsolation.js +108 -122
- package/dist/workspaceIsolation.js.map +1 -1
- package/package.json +4 -4
- package/dist/edges/dependsOn.js.map +0 -1
- package/dist/edges/derivedFrom.js.map +0 -1
- package/dist/edges/propagationTypes.js.map +0 -1
- package/dist/evaluators/lintCheckerEvaluator.d.ts +0 -11
- package/dist/evaluators/lintCheckerEvaluator.js.map +0 -1
- package/dist/evaluators/sentryCheckerEvaluator.js.map +0 -1
- package/dist/evaluators/testRunnerEvaluator.js.map +0 -1
- package/dist/evaluators/tscCheckerEvaluator.d.ts +0 -11
- package/dist/evaluators/tscCheckerEvaluator.js.map +0 -1
- package/dist/{epistemicQuestions-bwHd2FWE.d.ts → epistemicQuestions-Do1fhYm5.d.ts} +4 -4
|
@@ -1,82 +1,25 @@
|
|
|
1
|
-
import { v } from 'convex/values';
|
|
2
1
|
import { requireScopeWriteAccess } from '@lucern/access-control/access';
|
|
3
2
|
import { permissiveReturn } from '@lucern/contracts/schema-helpers/validators';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { normalizeTupleContradictionPolicy } from '@lucern/confidence';
|
|
3
|
+
import { v } from 'convex/values';
|
|
4
|
+
import { unsafeConvexAnyApi } from '@lucern/contracts/convex/unsafeAnyApi';
|
|
5
|
+
import { componentsGeneric, mutationGeneric, queryGeneric } from 'convex/server';
|
|
8
6
|
import '@lucern/access-control/audience';
|
|
9
7
|
import { getCurrentUserId } from '@lucern/access-control/auth';
|
|
8
|
+
import { throwStructuredMutationError } from '@lucern/access-control/structuredMutationError';
|
|
9
|
+
import { normalizeTupleContradictionPolicy } from '@lucern/confidence';
|
|
10
10
|
import { assertEdgePolicyAllowed, edgePolicyManifest } from '@lucern/contracts';
|
|
11
|
+
import { generateGlobalId, assertUuidV7Identity, assertStorageEdgeVocabulary, assertUuidShapedEdgeEndpoint } from '@lucern/contracts/ids';
|
|
11
12
|
|
|
12
13
|
// src/epistemicBeliefs.links.ts
|
|
13
|
-
var
|
|
14
|
+
var unsafeApi = unsafeConvexAnyApi(
|
|
15
|
+
"graph-primitives top-level module bundle lacks a committed Convex _generated/api surface"
|
|
16
|
+
);
|
|
17
|
+
var api = unsafeApi;
|
|
14
18
|
componentsGeneric();
|
|
15
|
-
var internal =
|
|
19
|
+
var internal = unsafeApi;
|
|
16
20
|
var mutation = mutationGeneric;
|
|
17
21
|
var query = queryGeneric;
|
|
18
22
|
|
|
19
|
-
// src/logicalRoleInference.ts
|
|
20
|
-
var PILLAR_IMPORTANCE = {
|
|
21
|
-
market: 1,
|
|
22
|
-
competition: 2,
|
|
23
|
-
product: 3,
|
|
24
|
-
team: 4,
|
|
25
|
-
financials: 5,
|
|
26
|
-
timing: 6,
|
|
27
|
-
other: 10
|
|
28
|
-
};
|
|
29
|
-
async function computeLogicalRole(ctx, evidenceId, beliefId) {
|
|
30
|
-
const belief = await ctx.db.get(beliefId);
|
|
31
|
-
if (!belief || belief.nodeType !== "belief") {
|
|
32
|
-
return "contributory";
|
|
33
|
-
}
|
|
34
|
-
const beliefMetadata = belief.metadata;
|
|
35
|
-
const pillar = beliefMetadata?.pillar || "other";
|
|
36
|
-
const pillarRank = PILLAR_IMPORTANCE[pillar] ?? 10;
|
|
37
|
-
const isSynthesized = await checkIfSynthesizedHypothesis(ctx, beliefId);
|
|
38
|
-
const testingQuestions = await getTestingQuestionsForBelief(ctx, beliefId);
|
|
39
|
-
const answeredQuestions = await getQuestionsAnsweredByEvidence(
|
|
40
|
-
ctx,
|
|
41
|
-
evidenceId
|
|
42
|
-
);
|
|
43
|
-
const directlyTests = testingQuestions.filter(
|
|
44
|
-
(questionId) => answeredQuestions.includes(questionId)
|
|
45
|
-
);
|
|
46
|
-
if (directlyTests.length === 0) {
|
|
47
|
-
return "contributory";
|
|
48
|
-
}
|
|
49
|
-
if (isSynthesized && pillarRank <= 2) {
|
|
50
|
-
return directlyTests.length > 1 ? "necessary_sufficient" : "necessary";
|
|
51
|
-
}
|
|
52
|
-
if (isSynthesized) {
|
|
53
|
-
return "necessary";
|
|
54
|
-
}
|
|
55
|
-
return directlyTests.length > 1 ? "necessary" : "contributory";
|
|
56
|
-
}
|
|
57
|
-
async function checkIfSynthesizedHypothesis(ctx, beliefId) {
|
|
58
|
-
const belief = await ctx.db.get(beliefId);
|
|
59
|
-
if (!belief) {
|
|
60
|
-
return false;
|
|
61
|
-
}
|
|
62
|
-
const metadata = belief.metadata;
|
|
63
|
-
return metadata?.isSynthesized === true || metadata?.beliefStatus === "hypothesis";
|
|
64
|
-
}
|
|
65
|
-
async function getTestingQuestionsForBelief(ctx, beliefId) {
|
|
66
|
-
const testEdges = await ctx.db.query("epistemicEdges").withIndex(
|
|
67
|
-
"by_to_type",
|
|
68
|
-
(q) => q.eq("toNodeId", beliefId).eq("edgeType", "tests")
|
|
69
|
-
).collect();
|
|
70
|
-
return testEdges.map((edge) => edge.fromNodeId).filter((id) => id !== void 0);
|
|
71
|
-
}
|
|
72
|
-
async function getQuestionsAnsweredByEvidence(ctx, evidenceId) {
|
|
73
|
-
const answerEdges = await ctx.db.query("epistemicEdges").withIndex(
|
|
74
|
-
"by_from_type",
|
|
75
|
-
(q) => q.eq("fromNodeId", evidenceId).eq("edgeType", "derived_from")
|
|
76
|
-
).collect();
|
|
77
|
-
return answerEdges.map((edge) => edge.toNodeId).filter((id) => id !== void 0);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
23
|
// src/debug.ts
|
|
81
24
|
function isGraphPrimitiveDebugEnabled() {
|
|
82
25
|
const env = globalThis.process?.env;
|
|
@@ -122,13 +65,15 @@ function asMappedProjectId(topic) {
|
|
|
122
65
|
if (!topic) {
|
|
123
66
|
return;
|
|
124
67
|
}
|
|
125
|
-
const directLegacyProjectId = normalizeScopeValue(
|
|
68
|
+
const directLegacyProjectId = normalizeScopeValue(
|
|
69
|
+
topic[LEGACY_SCOPE_FIELD]
|
|
70
|
+
);
|
|
126
71
|
if (directLegacyProjectId) {
|
|
127
72
|
return directLegacyProjectId;
|
|
128
73
|
}
|
|
129
74
|
const metadata = topic.metadata || {};
|
|
130
75
|
const candidate = metadata[LEGACY_SCOPE_FIELD] || metadata.legacyProjectId || metadata.projectId || metadata.scopeProjectId;
|
|
131
|
-
return candidate ? candidate : void 0;
|
|
76
|
+
return typeof candidate === "string" ? normalizeScopeValue(candidate) : void 0;
|
|
132
77
|
}
|
|
133
78
|
function normalizeScopeValue(value) {
|
|
134
79
|
if (typeof value !== "string") {
|
|
@@ -153,8 +98,9 @@ function pickPrimaryTopic(candidates) {
|
|
|
153
98
|
})[0];
|
|
154
99
|
}
|
|
155
100
|
async function findTopicsByScopeAlias(ctx, scopeId) {
|
|
101
|
+
const query2 = ctx.db.query("topics");
|
|
156
102
|
try {
|
|
157
|
-
return await
|
|
103
|
+
return await query2.withIndex(
|
|
158
104
|
"by_graph_scope_project",
|
|
159
105
|
(q) => q.eq(LEGACY_SCOPE_FIELD, scopeId)
|
|
160
106
|
).collect();
|
|
@@ -166,7 +112,7 @@ async function findTopicsByScopeAlias(ctx, scopeId) {
|
|
|
166
112
|
scopeId
|
|
167
113
|
}
|
|
168
114
|
);
|
|
169
|
-
const topics = await
|
|
115
|
+
const topics = await query2.collect();
|
|
170
116
|
return topics.filter((topic) => {
|
|
171
117
|
const normalizedGlobalId = normalizeScopeValue(topic.globalId);
|
|
172
118
|
const mappedProjectId = asMappedProjectId(topic);
|
|
@@ -222,143 +168,119 @@ async function resolveInheritedWorkspaceScope(ctx, topic) {
|
|
|
222
168
|
let current = topic;
|
|
223
169
|
for (let i = 0; i < MAX_DEPTH && current?.parentTopicId; i++) {
|
|
224
170
|
current = await ctx.db.get(current.parentTopicId);
|
|
225
|
-
if (!current)
|
|
171
|
+
if (!current) {
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
226
174
|
if (!tenantId) {
|
|
227
175
|
tenantId = normalizeScopeValue(current.tenantId);
|
|
228
176
|
}
|
|
229
177
|
if (!workspaceId) {
|
|
230
178
|
workspaceId = normalizeScopeValue(current.workspaceId);
|
|
231
179
|
}
|
|
232
|
-
if (tenantId && workspaceId)
|
|
180
|
+
if (tenantId && workspaceId) {
|
|
181
|
+
break;
|
|
182
|
+
}
|
|
233
183
|
}
|
|
234
184
|
return { tenantId, workspaceId };
|
|
235
185
|
}
|
|
236
186
|
async function resolveTopicProjectScope(ctx, args) {
|
|
237
187
|
if (args.topicId) {
|
|
238
|
-
|
|
239
|
-
try {
|
|
240
|
-
topic = await ctx.db.get(
|
|
241
|
-
args.topicId
|
|
242
|
-
);
|
|
243
|
-
} catch (error) {
|
|
244
|
-
debugGraphPrimitiveFallback(
|
|
245
|
-
"[topicScope] Failed to load topic by direct id",
|
|
246
|
-
{
|
|
247
|
-
error,
|
|
248
|
-
topicId: args.topicId
|
|
249
|
-
}
|
|
250
|
-
);
|
|
251
|
-
}
|
|
252
|
-
if (!topic) {
|
|
253
|
-
topic = await tryResolveHostTopicById(ctx, String(args.topicId));
|
|
254
|
-
}
|
|
255
|
-
if (!topic) {
|
|
256
|
-
topic = pickPrimaryTopic(
|
|
257
|
-
await findTopicsByScopeAlias(ctx, String(args.topicId))
|
|
258
|
-
) ?? null;
|
|
259
|
-
}
|
|
260
|
-
if (!topic) {
|
|
261
|
-
const nodeScope = await resolveTopicNodeScopeOrNull(
|
|
262
|
-
ctx,
|
|
263
|
-
String(args.topicId)
|
|
264
|
-
);
|
|
265
|
-
if (nodeScope) {
|
|
266
|
-
return nodeScope;
|
|
267
|
-
}
|
|
268
|
-
throw new Error(`Topic not found: ${String(args.topicId)}`);
|
|
269
|
-
}
|
|
270
|
-
const inherited = await resolveInheritedWorkspaceScope(ctx, topic);
|
|
271
|
-
const mapped = asMappedProjectId(topic);
|
|
272
|
-
if (mapped) {
|
|
273
|
-
return {
|
|
274
|
-
topicId: topic._id,
|
|
275
|
-
projectId: mapped,
|
|
276
|
-
tenantId: inherited.tenantId,
|
|
277
|
-
workspaceId: inherited.workspaceId,
|
|
278
|
-
source: "topic"
|
|
279
|
-
};
|
|
280
|
-
}
|
|
281
|
-
return {
|
|
282
|
-
topicId: topic._id,
|
|
283
|
-
tenantId: inherited.tenantId,
|
|
284
|
-
workspaceId: inherited.workspaceId,
|
|
285
|
-
source: "topic"
|
|
286
|
-
};
|
|
188
|
+
return await resolveScopeFromTopicId(ctx, args.topicId);
|
|
287
189
|
}
|
|
288
190
|
if (args.projectId) {
|
|
289
|
-
|
|
290
|
-
try {
|
|
291
|
-
directTopic = await ctx.db.get(
|
|
292
|
-
args.projectId
|
|
293
|
-
);
|
|
294
|
-
} catch (error) {
|
|
295
|
-
debugGraphPrimitiveFallback(
|
|
296
|
-
"[topicScope] Failed to load direct project topic",
|
|
297
|
-
{
|
|
298
|
-
error,
|
|
299
|
-
projectId: args.projectId
|
|
300
|
-
}
|
|
301
|
-
);
|
|
302
|
-
}
|
|
303
|
-
if (directTopic) {
|
|
304
|
-
const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);
|
|
305
|
-
const mapped = asMappedProjectId(directTopic);
|
|
306
|
-
return {
|
|
307
|
-
topicId: directTopic._id,
|
|
308
|
-
projectId: mapped ?? args.projectId,
|
|
309
|
-
tenantId: inherited.tenantId,
|
|
310
|
-
workspaceId: inherited.workspaceId,
|
|
311
|
-
source: "topic_inferred"
|
|
312
|
-
};
|
|
313
|
-
}
|
|
314
|
-
directTopic = await tryResolveHostTopicByLegacyScope(ctx, args.projectId);
|
|
315
|
-
if (directTopic) {
|
|
316
|
-
const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);
|
|
317
|
-
const mapped = asMappedProjectId(directTopic);
|
|
318
|
-
return {
|
|
319
|
-
topicId: directTopic._id,
|
|
320
|
-
projectId: mapped ?? args.projectId,
|
|
321
|
-
tenantId: inherited.tenantId,
|
|
322
|
-
workspaceId: inherited.workspaceId,
|
|
323
|
-
source: "topic_inferred"
|
|
324
|
-
};
|
|
325
|
-
}
|
|
326
|
-
const topics = await findTopicsByScopeAlias(ctx, args.projectId);
|
|
327
|
-
const primary = pickPrimaryTopic(topics);
|
|
328
|
-
if (primary) {
|
|
329
|
-
const inherited = await resolveInheritedWorkspaceScope(ctx, primary);
|
|
330
|
-
return {
|
|
331
|
-
topicId: primary._id,
|
|
332
|
-
projectId: args.projectId,
|
|
333
|
-
tenantId: inherited.tenantId,
|
|
334
|
-
workspaceId: inherited.workspaceId,
|
|
335
|
-
source: "project_mapped_topic"
|
|
336
|
-
};
|
|
337
|
-
}
|
|
338
|
-
const nodeScope = await resolveTopicNodeScopeOrNull(
|
|
339
|
-
ctx,
|
|
340
|
-
String(args.projectId)
|
|
341
|
-
);
|
|
342
|
-
if (nodeScope) {
|
|
343
|
-
return {
|
|
344
|
-
...nodeScope,
|
|
345
|
-
projectId: nodeScope.projectId ?? String(args.projectId)
|
|
346
|
-
};
|
|
347
|
-
}
|
|
348
|
-
throw new Error(
|
|
349
|
-
`Legacy project scope ${String(args.projectId)} has no mapped topic.`
|
|
350
|
-
);
|
|
191
|
+
return await resolveScopeFromLegacyProjectId(ctx, args.projectId);
|
|
351
192
|
}
|
|
352
193
|
throw new Error(
|
|
353
194
|
"Missing scope: provide topicId (preferred) or legacy projectId alias."
|
|
354
195
|
);
|
|
355
196
|
}
|
|
197
|
+
async function resolveScopeFromTopicId(ctx, topicId) {
|
|
198
|
+
const topic = await resolveTopicDocFromTopicId(ctx, topicId);
|
|
199
|
+
if (topic) {
|
|
200
|
+
return await buildTopicScope(ctx, topic, "topic");
|
|
201
|
+
}
|
|
202
|
+
const nodeScope = await resolveTopicNodeScopeOrNull(ctx, String(topicId));
|
|
203
|
+
if (nodeScope) {
|
|
204
|
+
return nodeScope;
|
|
205
|
+
}
|
|
206
|
+
throw new Error(`Topic not found: ${String(topicId)}`);
|
|
207
|
+
}
|
|
208
|
+
async function resolveTopicDocFromTopicId(ctx, topicId) {
|
|
209
|
+
const direct = await tryReadTopicDoc(ctx, topicId, {
|
|
210
|
+
failureLog: "[topicScope] Failed to load topic by direct id",
|
|
211
|
+
idLogKey: "topicId"
|
|
212
|
+
});
|
|
213
|
+
if (direct) {
|
|
214
|
+
return direct;
|
|
215
|
+
}
|
|
216
|
+
const hostTopic = await tryResolveHostTopicById(ctx, String(topicId));
|
|
217
|
+
if (hostTopic) {
|
|
218
|
+
return hostTopic;
|
|
219
|
+
}
|
|
220
|
+
return pickPrimaryTopic(await findTopicsByScopeAlias(ctx, String(topicId))) ?? null;
|
|
221
|
+
}
|
|
222
|
+
async function resolveScopeFromLegacyProjectId(ctx, legacyProjectId) {
|
|
223
|
+
const directTopic = await resolveDirectLegacyProjectTopic(
|
|
224
|
+
ctx,
|
|
225
|
+
legacyProjectId
|
|
226
|
+
);
|
|
227
|
+
if (directTopic) {
|
|
228
|
+
return await buildTopicScope(ctx, directTopic, "topic_inferred", {
|
|
229
|
+
fallbackProjectId: legacyProjectId
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
const primary = pickPrimaryTopic(
|
|
233
|
+
await findTopicsByScopeAlias(ctx, legacyProjectId)
|
|
234
|
+
);
|
|
235
|
+
if (primary) {
|
|
236
|
+
return await buildTopicScope(ctx, primary, "project_mapped_topic", {
|
|
237
|
+
fallbackProjectId: legacyProjectId
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
const nodeScope = await resolveTopicNodeScopeOrNull(ctx, legacyProjectId);
|
|
241
|
+
if (nodeScope) {
|
|
242
|
+
return {
|
|
243
|
+
...nodeScope,
|
|
244
|
+
projectId: nodeScope.projectId ?? legacyProjectId
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
throw new Error(
|
|
248
|
+
`Legacy project scope ${legacyProjectId} has no mapped topic.`
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
async function resolveDirectLegacyProjectTopic(ctx, legacyProjectId) {
|
|
252
|
+
const directTopic = await tryReadTopicDoc(ctx, legacyProjectId, {
|
|
253
|
+
failureLog: "[topicScope] Failed to load direct project topic",
|
|
254
|
+
idLogKey: "projectId"
|
|
255
|
+
});
|
|
256
|
+
return directTopic ?? tryResolveHostTopicByLegacyScope(ctx, legacyProjectId);
|
|
257
|
+
}
|
|
258
|
+
async function tryReadTopicDoc(ctx, id, log) {
|
|
259
|
+
try {
|
|
260
|
+
return await ctx.db.get(id);
|
|
261
|
+
} catch (error) {
|
|
262
|
+
debugGraphPrimitiveFallback(log.failureLog, {
|
|
263
|
+
error,
|
|
264
|
+
[log.idLogKey]: id
|
|
265
|
+
});
|
|
266
|
+
return null;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
async function buildTopicScope(ctx, topic, source, options = {}) {
|
|
270
|
+
const inherited = await resolveInheritedWorkspaceScope(ctx, topic);
|
|
271
|
+
const mapped = asMappedProjectId(topic);
|
|
272
|
+
return {
|
|
273
|
+
topicId: topic._id,
|
|
274
|
+
...mapped || options.fallbackProjectId ? { projectId: mapped ?? options.fallbackProjectId } : {},
|
|
275
|
+
tenantId: inherited.tenantId,
|
|
276
|
+
workspaceId: inherited.workspaceId,
|
|
277
|
+
source
|
|
278
|
+
};
|
|
279
|
+
}
|
|
356
280
|
var optionalScopeArgs = {
|
|
357
281
|
projectId: v.optional(v.string()),
|
|
358
282
|
topicId: v.optional(v.string())
|
|
359
283
|
};
|
|
360
|
-
|
|
361
|
-
// src/epistemicBeliefs.helpers.ts
|
|
362
284
|
var insightIdUnion = v.id("epistemicNodes");
|
|
363
285
|
var optionalBeliefScopeArgs = optionalScopeArgs;
|
|
364
286
|
({
|
|
@@ -374,7 +296,7 @@ function buildBeliefEvidenceNotFoundResult() {
|
|
|
374
296
|
return result;
|
|
375
297
|
}
|
|
376
298
|
async function resolveBeliefScopeOrNull(ctx, args) {
|
|
377
|
-
if (!args.projectId
|
|
299
|
+
if (!(args.projectId || args.topicId)) {
|
|
378
300
|
return null;
|
|
379
301
|
}
|
|
380
302
|
try {
|
|
@@ -411,7 +333,10 @@ async function requireAuthenticatedUserId(ctx) {
|
|
|
411
333
|
}
|
|
412
334
|
async function assertExistingNodeEndpoint(ctx, endpointRole, endpoint) {
|
|
413
335
|
assertUuidShapedEdgeEndpoint(endpointRole, endpoint);
|
|
414
|
-
const node = await ctx.db.query("epistemicNodes").withIndex(
|
|
336
|
+
const node = await ctx.db.query("epistemicNodes").withIndex(
|
|
337
|
+
"by_globalId",
|
|
338
|
+
(q) => q.eq("globalId", endpoint)
|
|
339
|
+
).first();
|
|
415
340
|
if (!node) {
|
|
416
341
|
throw new Error(
|
|
417
342
|
`edge_endpoint_not_canonical: epistemicEdges insert requires ${endpointRole} to be the globalId of an existing epistemicNodes row, received ${endpoint} (no node with that globalId)`
|
|
@@ -452,7 +377,193 @@ async function insertEpistemicEdge(ctx, doc) {
|
|
|
452
377
|
return ctx.db.insert("epistemicEdges", doc);
|
|
453
378
|
}
|
|
454
379
|
|
|
380
|
+
// src/logicalRoleInference.ts
|
|
381
|
+
var PILLAR_IMPORTANCE = {
|
|
382
|
+
market: 1,
|
|
383
|
+
competition: 2,
|
|
384
|
+
product: 3,
|
|
385
|
+
team: 4,
|
|
386
|
+
financials: 5,
|
|
387
|
+
timing: 6,
|
|
388
|
+
other: 10
|
|
389
|
+
};
|
|
390
|
+
async function computeLogicalRole(ctx, evidenceId, beliefId) {
|
|
391
|
+
const belief = await ctx.db.get(beliefId);
|
|
392
|
+
if (belief?.nodeType !== "belief") {
|
|
393
|
+
return "contributory";
|
|
394
|
+
}
|
|
395
|
+
const beliefMetadata = belief.metadata;
|
|
396
|
+
const pillar = beliefMetadata?.pillar || "other";
|
|
397
|
+
const pillarRank = PILLAR_IMPORTANCE[pillar] ?? 10;
|
|
398
|
+
const isSynthesized = await checkIfSynthesizedHypothesis(ctx, beliefId);
|
|
399
|
+
const testingQuestions = await getTestingQuestionsForBelief(ctx, beliefId);
|
|
400
|
+
const answeredQuestions = await getQuestionsAnsweredByEvidence(
|
|
401
|
+
ctx,
|
|
402
|
+
evidenceId
|
|
403
|
+
);
|
|
404
|
+
const directlyTests = testingQuestions.filter(
|
|
405
|
+
(questionId) => answeredQuestions.includes(questionId)
|
|
406
|
+
);
|
|
407
|
+
if (directlyTests.length === 0) {
|
|
408
|
+
return "contributory";
|
|
409
|
+
}
|
|
410
|
+
if (isSynthesized && pillarRank <= 2) {
|
|
411
|
+
return directlyTests.length > 1 ? "necessary_sufficient" : "necessary";
|
|
412
|
+
}
|
|
413
|
+
if (isSynthesized) {
|
|
414
|
+
return "necessary";
|
|
415
|
+
}
|
|
416
|
+
return directlyTests.length > 1 ? "necessary" : "contributory";
|
|
417
|
+
}
|
|
418
|
+
async function checkIfSynthesizedHypothesis(ctx, beliefId) {
|
|
419
|
+
const belief = await ctx.db.get(beliefId);
|
|
420
|
+
if (!belief) {
|
|
421
|
+
return false;
|
|
422
|
+
}
|
|
423
|
+
const metadata = belief.metadata;
|
|
424
|
+
return metadata?.isSynthesized === true || metadata?.beliefStatus === "hypothesis";
|
|
425
|
+
}
|
|
426
|
+
async function getTestingQuestionsForBelief(ctx, beliefId) {
|
|
427
|
+
const testEdges = await ctx.db.query("epistemicEdges").withIndex(
|
|
428
|
+
"by_to_type",
|
|
429
|
+
(q) => q.eq("toNodeId", beliefId).eq("edgeType", "tests")
|
|
430
|
+
).collect();
|
|
431
|
+
return testEdges.map((edge) => edge.fromNodeId).filter((id) => id !== void 0);
|
|
432
|
+
}
|
|
433
|
+
async function getQuestionsAnsweredByEvidence(ctx, evidenceId) {
|
|
434
|
+
const answerEdges = await ctx.db.query("epistemicEdges").withIndex(
|
|
435
|
+
"by_from_type",
|
|
436
|
+
(q) => q.eq("fromNodeId", evidenceId).eq("edgeType", "derived_from")
|
|
437
|
+
).collect();
|
|
438
|
+
return answerEdges.map((edge) => edge.toNodeId).filter((id) => id !== void 0);
|
|
439
|
+
}
|
|
440
|
+
|
|
455
441
|
// src/epistemicBeliefs.links.ts
|
|
442
|
+
function isRecord(value) {
|
|
443
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
444
|
+
}
|
|
445
|
+
function readOptionalNumber(value) {
|
|
446
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
447
|
+
}
|
|
448
|
+
function readOptionalString(value) {
|
|
449
|
+
return typeof value === "string" && value.trim().length > 0 ? value : void 0;
|
|
450
|
+
}
|
|
451
|
+
function readRecord(value) {
|
|
452
|
+
return isRecord(value) ? value : void 0;
|
|
453
|
+
}
|
|
454
|
+
function readConvexId(value) {
|
|
455
|
+
const normalized = readOptionalString(value);
|
|
456
|
+
return normalized;
|
|
457
|
+
}
|
|
458
|
+
function readEpistemicNodeRow(value) {
|
|
459
|
+
if (!isRecord(value)) {
|
|
460
|
+
return null;
|
|
461
|
+
}
|
|
462
|
+
const id = readConvexId(value._id);
|
|
463
|
+
const nodeType = readOptionalString(value.nodeType);
|
|
464
|
+
if (!(id && nodeType)) {
|
|
465
|
+
return null;
|
|
466
|
+
}
|
|
467
|
+
const row = { _id: id, nodeType };
|
|
468
|
+
const globalId = readOptionalString(value.globalId);
|
|
469
|
+
if (globalId !== void 0) {
|
|
470
|
+
row.globalId = globalId;
|
|
471
|
+
}
|
|
472
|
+
const metadata = readRecord(value.metadata);
|
|
473
|
+
if (metadata !== void 0) {
|
|
474
|
+
row.metadata = metadata;
|
|
475
|
+
}
|
|
476
|
+
const projectId = readOptionalString(value.projectId);
|
|
477
|
+
if (projectId !== void 0) {
|
|
478
|
+
row.projectId = projectId;
|
|
479
|
+
}
|
|
480
|
+
const status = readOptionalString(value.status);
|
|
481
|
+
if (status !== void 0) {
|
|
482
|
+
row.status = status;
|
|
483
|
+
}
|
|
484
|
+
const topicId = readOptionalString(value.topicId);
|
|
485
|
+
if (topicId !== void 0) {
|
|
486
|
+
row.topicId = topicId;
|
|
487
|
+
}
|
|
488
|
+
return row;
|
|
489
|
+
}
|
|
490
|
+
function requireEpistemicNodeRow(value, nodeType, message) {
|
|
491
|
+
const node = readEpistemicNodeRow(value);
|
|
492
|
+
if (!node || node.nodeType !== nodeType) {
|
|
493
|
+
throw new Error(message);
|
|
494
|
+
}
|
|
495
|
+
return node;
|
|
496
|
+
}
|
|
497
|
+
function requireNodeGlobalId(node, context) {
|
|
498
|
+
if (!node.globalId) {
|
|
499
|
+
throw new Error(
|
|
500
|
+
`${context} requires node.globalId for canonical edge endpoints`
|
|
501
|
+
);
|
|
502
|
+
}
|
|
503
|
+
return node.globalId;
|
|
504
|
+
}
|
|
505
|
+
function readEpistemicEdgeRow(value) {
|
|
506
|
+
if (!isRecord(value)) {
|
|
507
|
+
return null;
|
|
508
|
+
}
|
|
509
|
+
const id = readConvexId(value._id);
|
|
510
|
+
const globalId = readOptionalString(value.globalId);
|
|
511
|
+
if (!(id && globalId)) {
|
|
512
|
+
return null;
|
|
513
|
+
}
|
|
514
|
+
const row = { _id: id, globalId };
|
|
515
|
+
const edgeType = readOptionalString(value.edgeType);
|
|
516
|
+
if (edgeType !== void 0) {
|
|
517
|
+
row.edgeType = edgeType;
|
|
518
|
+
}
|
|
519
|
+
const fromGlobalId = readOptionalString(value.fromGlobalId);
|
|
520
|
+
if (fromGlobalId !== void 0) {
|
|
521
|
+
row.fromGlobalId = fromGlobalId;
|
|
522
|
+
}
|
|
523
|
+
const fromNodeId = readOptionalString(value.fromNodeId);
|
|
524
|
+
if (fromNodeId !== void 0) {
|
|
525
|
+
row.fromNodeId = fromNodeId;
|
|
526
|
+
}
|
|
527
|
+
const fromNodeType = readOptionalString(value.fromNodeType);
|
|
528
|
+
if (fromNodeType !== void 0) {
|
|
529
|
+
row.fromNodeType = fromNodeType;
|
|
530
|
+
}
|
|
531
|
+
const fromUuid = readOptionalString(value.fromUuid);
|
|
532
|
+
if (fromUuid !== void 0) {
|
|
533
|
+
row.fromUuid = fromUuid;
|
|
534
|
+
}
|
|
535
|
+
const sourceGlobalId = readOptionalString(value.sourceGlobalId);
|
|
536
|
+
if (sourceGlobalId !== void 0) {
|
|
537
|
+
row.sourceGlobalId = sourceGlobalId;
|
|
538
|
+
}
|
|
539
|
+
const targetGlobalId = readOptionalString(value.targetGlobalId);
|
|
540
|
+
if (targetGlobalId !== void 0) {
|
|
541
|
+
row.targetGlobalId = targetGlobalId;
|
|
542
|
+
}
|
|
543
|
+
const toGlobalId = readOptionalString(value.toGlobalId);
|
|
544
|
+
if (toGlobalId !== void 0) {
|
|
545
|
+
row.toGlobalId = toGlobalId;
|
|
546
|
+
}
|
|
547
|
+
const toNodeId = readOptionalString(value.toNodeId);
|
|
548
|
+
if (toNodeId !== void 0) {
|
|
549
|
+
row.toNodeId = toNodeId;
|
|
550
|
+
}
|
|
551
|
+
const toUuid = readOptionalString(value.toUuid);
|
|
552
|
+
if (toUuid !== void 0) {
|
|
553
|
+
row.toUuid = toUuid;
|
|
554
|
+
}
|
|
555
|
+
const weight = readOptionalNumber(value.weight);
|
|
556
|
+
if (weight !== void 0) {
|
|
557
|
+
row.weight = weight;
|
|
558
|
+
}
|
|
559
|
+
return row;
|
|
560
|
+
}
|
|
561
|
+
function readEpistemicEdgeRows(values) {
|
|
562
|
+
return values.flatMap((value) => {
|
|
563
|
+
const row = readEpistemicEdgeRow(value);
|
|
564
|
+
return row ? [row] : [];
|
|
565
|
+
});
|
|
566
|
+
}
|
|
456
567
|
function assertSignedImpactScore(value, context) {
|
|
457
568
|
if (typeof value !== "number" || !Number.isFinite(value) || value === 0 || value < -1 || value > 1) {
|
|
458
569
|
throw new Error(`${context} requires explicit nonzero weight in [-1, 1]`);
|
|
@@ -483,10 +594,11 @@ var updatePillar = mutation({
|
|
|
483
594
|
handler: async (ctx, args) => {
|
|
484
595
|
const authenticatedUserId = await requireAuthenticatedUserId(ctx);
|
|
485
596
|
const now = Date.now();
|
|
486
|
-
const existingNode =
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
597
|
+
const existingNode = requireEpistemicNodeRow(
|
|
598
|
+
await ctx.db.get(args.nodeId),
|
|
599
|
+
"belief",
|
|
600
|
+
"Belief not found"
|
|
601
|
+
);
|
|
490
602
|
if (!existingNode.projectId) {
|
|
491
603
|
throw new Error("Belief has no project scope");
|
|
492
604
|
}
|
|
@@ -496,7 +608,7 @@ var updatePillar = mutation({
|
|
|
496
608
|
authenticatedUserId
|
|
497
609
|
);
|
|
498
610
|
let previousPillar = null;
|
|
499
|
-
const metadata = existingNode.metadata
|
|
611
|
+
const metadata = existingNode.metadata ?? {};
|
|
500
612
|
previousPillar = metadata.pillar;
|
|
501
613
|
await ctx.db.patch(args.nodeId, {
|
|
502
614
|
metadata: {
|
|
@@ -512,7 +624,7 @@ var updatePillar = mutation({
|
|
|
512
624
|
});
|
|
513
625
|
await ctx.db.insert("epistemicAudit", {
|
|
514
626
|
entityType: "belief",
|
|
515
|
-
entityId: args.nodeId,
|
|
627
|
+
entityId: String(args.nodeId),
|
|
516
628
|
changeType: "pillar_changed",
|
|
517
629
|
projectId: existingNode.projectId,
|
|
518
630
|
changedBy: authenticatedUserId,
|
|
@@ -538,10 +650,13 @@ var getCountByStatus = query({
|
|
|
538
650
|
if (!scope) {
|
|
539
651
|
return { active: 0, superseded: 0, archived: 0, total: 0 };
|
|
540
652
|
}
|
|
541
|
-
const nodes = await ctx.db.query("epistemicNodes").withIndex(
|
|
653
|
+
const nodes = (await ctx.db.query("epistemicNodes").withIndex(
|
|
542
654
|
"by_topic_type",
|
|
543
655
|
(q) => q.eq("topicId", scope.topicId).eq("nodeType", "belief")
|
|
544
|
-
).collect()
|
|
656
|
+
).collect()).flatMap((row) => {
|
|
657
|
+
const node = readEpistemicNodeRow(row);
|
|
658
|
+
return node?.nodeType === "belief" ? [node] : [];
|
|
659
|
+
});
|
|
545
660
|
const counts = {
|
|
546
661
|
active: 0,
|
|
547
662
|
superseded: 0,
|
|
@@ -582,31 +697,31 @@ var linkBeliefs = mutation({
|
|
|
582
697
|
returns: permissiveReturn,
|
|
583
698
|
handler: async (ctx, args) => {
|
|
584
699
|
const authenticatedUserId = await requireAuthenticatedUserId(ctx);
|
|
585
|
-
const fromNode =
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
700
|
+
const fromNode = requireEpistemicNodeRow(
|
|
701
|
+
await ctx.db.get(args.fromNodeId),
|
|
702
|
+
"belief",
|
|
703
|
+
"One or both belief nodes not found"
|
|
704
|
+
);
|
|
705
|
+
const toNode = requireEpistemicNodeRow(
|
|
706
|
+
await ctx.db.get(args.toNodeId),
|
|
707
|
+
"belief",
|
|
708
|
+
"One or both belief nodes not found"
|
|
709
|
+
);
|
|
593
710
|
if (fromNode.projectId !== toNode.projectId) {
|
|
594
711
|
throw new Error("Cannot link beliefs across different projects");
|
|
595
712
|
}
|
|
596
713
|
if (!fromNode.projectId) {
|
|
597
714
|
throw new Error("Belief has no project scope");
|
|
598
715
|
}
|
|
599
|
-
await requireScopeWriteAccess(
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
authenticatedUserId
|
|
603
|
-
);
|
|
716
|
+
await requireScopeWriteAccess(ctx, fromNode.projectId, authenticatedUserId);
|
|
717
|
+
const fromGlobalId = requireNodeGlobalId(fromNode, "Belief link");
|
|
718
|
+
const toGlobalId = requireNodeGlobalId(toNode, "Belief link");
|
|
604
719
|
const now = Date.now();
|
|
605
720
|
const edgeGlobalId = generateGlobalId();
|
|
606
721
|
await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {
|
|
607
722
|
globalId: edgeGlobalId,
|
|
608
|
-
fromGlobalId
|
|
609
|
-
toGlobalId
|
|
723
|
+
fromGlobalId,
|
|
724
|
+
toGlobalId,
|
|
610
725
|
edgeType: args.edgeType,
|
|
611
726
|
weight: args.weight ?? 1,
|
|
612
727
|
context: args.context,
|
|
@@ -645,23 +760,26 @@ var linkEvidence = mutation({
|
|
|
645
760
|
returns: permissiveReturn,
|
|
646
761
|
handler: async (ctx, args) => {
|
|
647
762
|
const authenticatedUserId = await requireAuthenticatedUserId(ctx);
|
|
648
|
-
const belief =
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
763
|
+
const belief = requireEpistemicNodeRow(
|
|
764
|
+
await ctx.db.get(args.beliefNodeId),
|
|
765
|
+
"belief",
|
|
766
|
+
"Belief not found"
|
|
767
|
+
);
|
|
652
768
|
if (!belief.projectId) {
|
|
653
769
|
throw new Error("Belief has no project scope");
|
|
654
770
|
}
|
|
655
771
|
await requireScopeWriteAccess(ctx, belief.projectId, authenticatedUserId);
|
|
656
|
-
const insight =
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
772
|
+
const insight = requireEpistemicNodeRow(
|
|
773
|
+
await ctx.db.get(args.insightId),
|
|
774
|
+
"evidence",
|
|
775
|
+
"Insight not found"
|
|
776
|
+
);
|
|
777
|
+
if (insight.projectId && insight.projectId !== belief.projectId) {
|
|
661
778
|
throw new Error("Insight belongs to a different project");
|
|
662
779
|
}
|
|
663
780
|
const evidenceNodeId = insight._id;
|
|
664
|
-
const evidenceGlobalId = insight
|
|
781
|
+
const evidenceGlobalId = requireNodeGlobalId(insight, "Evidence link");
|
|
782
|
+
const beliefGlobalId = requireNodeGlobalId(belief, "Evidence link");
|
|
665
783
|
const weight = assertSignedImpactScore(args.weight, "Evidence link");
|
|
666
784
|
if (args.type === "supporting" && weight < 0) {
|
|
667
785
|
throw new Error("Supporting evidence links require positive weight");
|
|
@@ -677,9 +795,9 @@ var linkEvidence = mutation({
|
|
|
677
795
|
globalId: edgeGlobalId,
|
|
678
796
|
// C2-RR.4 Defect E — canonical UUIDv7 endpoints, not Convex doc ids.
|
|
679
797
|
fromNodeId: evidenceGlobalId,
|
|
680
|
-
toNodeId:
|
|
798
|
+
toNodeId: beliefGlobalId,
|
|
681
799
|
sourceGlobalId: evidenceGlobalId,
|
|
682
|
-
targetGlobalId:
|
|
800
|
+
targetGlobalId: beliefGlobalId,
|
|
683
801
|
edgeType,
|
|
684
802
|
weight,
|
|
685
803
|
confidence,
|
|
@@ -707,7 +825,7 @@ var linkEvidence = mutation({
|
|
|
707
825
|
await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {
|
|
708
826
|
globalId: edgeGlobalId,
|
|
709
827
|
fromGlobalId: evidenceGlobalId,
|
|
710
|
-
toGlobalId:
|
|
828
|
+
toGlobalId: beliefGlobalId,
|
|
711
829
|
edgeType,
|
|
712
830
|
weight,
|
|
713
831
|
confidence,
|
|
@@ -736,8 +854,9 @@ var unlinkEvidence = mutation({
|
|
|
736
854
|
handler: async (ctx, args) => {
|
|
737
855
|
const authenticatedUserId = await requireAuthenticatedUserId(ctx);
|
|
738
856
|
const now = Date.now();
|
|
739
|
-
const
|
|
740
|
-
|
|
857
|
+
const evidenceNodeRaw = await ctx.db.get(args.insightId);
|
|
858
|
+
const evidenceNode = readEpistemicNodeRow(evidenceNodeRaw);
|
|
859
|
+
if (evidenceNode?.nodeType !== "evidence") {
|
|
741
860
|
return buildBeliefEvidenceNotFoundResult();
|
|
742
861
|
}
|
|
743
862
|
if (!evidenceNode.projectId) {
|
|
@@ -748,17 +867,25 @@ var unlinkEvidence = mutation({
|
|
|
748
867
|
evidenceNode.projectId,
|
|
749
868
|
authenticatedUserId
|
|
750
869
|
);
|
|
751
|
-
const beliefNode =
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
870
|
+
const beliefNode = requireEpistemicNodeRow(
|
|
871
|
+
await ctx.db.get(args.beliefNodeId),
|
|
872
|
+
"belief",
|
|
873
|
+
"Belief not found"
|
|
874
|
+
);
|
|
755
875
|
if (beliefNode.projectId !== evidenceNode.projectId) {
|
|
756
876
|
throw new Error("Belief and evidence belong to different projects");
|
|
757
877
|
}
|
|
758
|
-
const
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
)
|
|
878
|
+
const evidenceGlobalId = requireNodeGlobalId(
|
|
879
|
+
evidenceNode,
|
|
880
|
+
"Evidence unlink"
|
|
881
|
+
);
|
|
882
|
+
const beliefGlobalId = requireNodeGlobalId(beliefNode, "Evidence unlink");
|
|
883
|
+
const edge = readEpistemicEdgeRow(
|
|
884
|
+
await ctx.db.query("epistemicEdges").withIndex(
|
|
885
|
+
"by_from_to",
|
|
886
|
+
(q) => q.eq("fromNodeId", evidenceGlobalId).eq("toNodeId", beliefGlobalId)
|
|
887
|
+
).first()
|
|
888
|
+
);
|
|
762
889
|
if (edge) {
|
|
763
890
|
await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.deleteEdge, {
|
|
764
891
|
globalId: edge.globalId
|
|
@@ -788,25 +915,31 @@ var getWithEvidence = query({
|
|
|
788
915
|
},
|
|
789
916
|
returns: permissiveReturn,
|
|
790
917
|
handler: async (ctx, args) => {
|
|
791
|
-
const belief = await ctx.db.get(args.nodeId);
|
|
792
|
-
if (
|
|
918
|
+
const belief = readEpistemicNodeRow(await ctx.db.get(args.nodeId));
|
|
919
|
+
if (belief?.nodeType !== "belief") {
|
|
793
920
|
return null;
|
|
794
921
|
}
|
|
795
|
-
const
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
evidenceNodeIds.map((id) => ctx.db.get(id))
|
|
922
|
+
const beliefGlobalId = requireNodeGlobalId(belief, "Belief evidence read");
|
|
923
|
+
const incomingEdges = readEpistemicEdgeRows(
|
|
924
|
+
await ctx.db.query("epistemicEdges").withIndex(
|
|
925
|
+
"by_to_type",
|
|
926
|
+
(q) => q.eq("toNodeId", beliefGlobalId).eq("edgeType", "informs")
|
|
927
|
+
).collect()
|
|
802
928
|
);
|
|
803
929
|
const supporting = [];
|
|
804
930
|
const contradicting = [];
|
|
805
|
-
for (
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
931
|
+
for (const edge of incomingEdges.filter(
|
|
932
|
+
(incomingEdge) => incomingEdge.fromNodeType === "evidence"
|
|
933
|
+
)) {
|
|
934
|
+
const node = readEpistemicNodeRow(
|
|
935
|
+
await resolveRelationshipEndpoint(
|
|
936
|
+
ctx,
|
|
937
|
+
edge.fromNodeId,
|
|
938
|
+
edge.sourceGlobalId ?? edge.fromGlobalId ?? edge.fromUuid
|
|
939
|
+
)
|
|
940
|
+
);
|
|
941
|
+
if (node?.nodeType === "evidence") {
|
|
942
|
+
if ((edge.weight ?? 0) >= 0) {
|
|
810
943
|
supporting.push(node);
|
|
811
944
|
} else {
|
|
812
945
|
contradicting.push(node);
|
|
@@ -834,13 +967,13 @@ async function collectRelationshipNodeRefs(ctx, nodeId) {
|
|
|
834
967
|
}
|
|
835
968
|
function endpointMatches(q, fields, refs) {
|
|
836
969
|
return q.or(
|
|
837
|
-
...fields.flatMap(
|
|
838
|
-
(field) => refs.map((ref) => q.eq(q.field(field), ref))
|
|
839
|
-
)
|
|
970
|
+
...fields.flatMap((field) => refs.map((ref) => q.eq(q.field(field), ref)))
|
|
840
971
|
);
|
|
841
972
|
}
|
|
842
973
|
async function resolveRelationshipEndpoint(ctx, endpointId, globalEndpointId) {
|
|
843
|
-
const candidates = [endpointId, globalEndpointId].map((value) => typeof value === "string" ? value.trim() : "").filter(
|
|
974
|
+
const candidates = [endpointId, globalEndpointId].map((value) => typeof value === "string" ? value.trim() : "").filter(
|
|
975
|
+
(value, index, values) => value.length > 0 && values.indexOf(value) === index
|
|
976
|
+
);
|
|
844
977
|
for (const candidate of candidates) {
|
|
845
978
|
try {
|
|
846
979
|
const direct = await ctx.db.get(candidate);
|
|
@@ -872,13 +1005,15 @@ var getRelationships = query({
|
|
|
872
1005
|
};
|
|
873
1006
|
const nodeRefs = await collectRelationshipNodeRefs(ctx, args.nodeId);
|
|
874
1007
|
if (direction === "in" || direction === "both") {
|
|
875
|
-
const inEdges =
|
|
876
|
-
(
|
|
877
|
-
q
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
1008
|
+
const inEdges = readEpistemicEdgeRows(
|
|
1009
|
+
await ctx.db.query("epistemicEdges").filter(
|
|
1010
|
+
(q) => endpointMatches(
|
|
1011
|
+
q,
|
|
1012
|
+
["toNodeId", "targetGlobalId", "toGlobalId", "toUuid"],
|
|
1013
|
+
nodeRefs
|
|
1014
|
+
)
|
|
1015
|
+
).collect()
|
|
1016
|
+
);
|
|
882
1017
|
for (const edge of inEdges) {
|
|
883
1018
|
const sourceNode = await resolveRelationshipEndpoint(
|
|
884
1019
|
ctx,
|
|
@@ -889,13 +1024,15 @@ var getRelationships = query({
|
|
|
889
1024
|
}
|
|
890
1025
|
}
|
|
891
1026
|
if (direction === "out" || direction === "both") {
|
|
892
|
-
const outEdges =
|
|
893
|
-
(
|
|
894
|
-
q
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
1027
|
+
const outEdges = readEpistemicEdgeRows(
|
|
1028
|
+
await ctx.db.query("epistemicEdges").filter(
|
|
1029
|
+
(q) => endpointMatches(
|
|
1030
|
+
q,
|
|
1031
|
+
["fromNodeId", "sourceGlobalId", "fromGlobalId", "fromUuid"],
|
|
1032
|
+
nodeRefs
|
|
1033
|
+
)
|
|
1034
|
+
).collect()
|
|
1035
|
+
);
|
|
899
1036
|
for (const edge of outEdges) {
|
|
900
1037
|
const targetNode = await resolveRelationshipEndpoint(
|
|
901
1038
|
ctx,
|