@lucern/graph-primitives 1.0.28 → 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 +398 -228
- 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 +857 -515
- 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 +366 -203
- package/dist/epistemicBeliefs.admin.js.map +1 -1
- package/dist/epistemicBeliefs.backfills.d.ts +8 -8
- package/dist/epistemicBeliefs.backfills.js +655 -308
- package/dist/epistemicBeliefs.backfills.js.map +1 -1
- package/dist/epistemicBeliefs.confidence.d.ts +19 -14
- package/dist/epistemicBeliefs.confidence.js +634 -423
- package/dist/epistemicBeliefs.confidence.js.map +1 -1
- package/dist/epistemicBeliefs.core.d.ts +6 -6
- package/dist/epistemicBeliefs.core.js +719 -411
- package/dist/epistemicBeliefs.core.js.map +1 -1
- package/dist/epistemicBeliefs.d.ts +11 -8
- package/dist/epistemicBeliefs.forkEvidence.d.ts +2 -0
- package/dist/epistemicBeliefs.forkEvidence.js +8 -28
- package/dist/epistemicBeliefs.forkEvidence.js.map +1 -1
- package/dist/epistemicBeliefs.helpers.d.ts +69 -74
- package/dist/epistemicBeliefs.helpers.js +359 -248
- package/dist/epistemicBeliefs.helpers.js.map +1 -1
- package/dist/epistemicBeliefs.internal.d.ts +5 -5
- package/dist/epistemicBeliefs.internal.js +1246 -1044
- package/dist/epistemicBeliefs.internal.js.map +1 -1
- package/dist/epistemicBeliefs.js +4922 -3608
- package/dist/epistemicBeliefs.js.map +1 -1
- package/dist/epistemicBeliefs.lifecycle.d.ts +5 -5
- package/dist/epistemicBeliefs.lifecycle.js +1137 -818
- package/dist/epistemicBeliefs.lifecycle.js.map +1 -1
- package/dist/epistemicBeliefs.links.d.ts +7 -7
- package/dist/epistemicBeliefs.links.js +408 -307
- 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 +1063 -613
- package/dist/epistemicContracts.evaluators.js.map +1 -1
- package/dist/epistemicContracts.handlers.d.ts +15 -32
- package/dist/epistemicContracts.handlers.js +2086 -1644
- package/dist/epistemicContracts.handlers.js.map +1 -1
- package/dist/epistemicContracts.js +1131 -672
- 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 +1969 -1205
- package/dist/epistemicEdges.js.map +1 -1
- package/dist/epistemicEdges.mutations.d.ts +7 -7
- package/dist/epistemicEdges.mutations.js +960 -583
- 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 +937 -536
- 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 +844 -696
- 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 +704 -508
- package/dist/epistemicNodes.js.map +1 -1
- package/dist/epistemicNodes.mutations.d.ts +6 -6
- package/dist/epistemicNodes.mutations.js +564 -467
- 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 +352 -312
- 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 +87 -83
- package/dist/index.js +15677 -10594
- 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,81 +1,25 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { requireScopeWriteAccess } from '@lucern/access-control/access';
|
|
2
2
|
import { permissiveReturn } from '@lucern/contracts/schema-helpers/validators';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { checkProjectAccess } from '@lucern/access-control/access';
|
|
3
|
+
import { v } from 'convex/values';
|
|
4
|
+
import { unsafeConvexAnyApi } from '@lucern/contracts/convex/unsafeAnyApi';
|
|
5
|
+
import { componentsGeneric, mutationGeneric, queryGeneric } from 'convex/server';
|
|
7
6
|
import '@lucern/access-control/audience';
|
|
8
7
|
import { getCurrentUserId } from '@lucern/access-control/auth';
|
|
8
|
+
import { throwStructuredMutationError } from '@lucern/access-control/structuredMutationError';
|
|
9
|
+
import { normalizeTupleContradictionPolicy } from '@lucern/confidence';
|
|
9
10
|
import { assertEdgePolicyAllowed, edgePolicyManifest } from '@lucern/contracts';
|
|
11
|
+
import { generateGlobalId, assertUuidV7Identity, assertStorageEdgeVocabulary, assertUuidShapedEdgeEndpoint } from '@lucern/contracts/ids';
|
|
10
12
|
|
|
11
13
|
// src/epistemicBeliefs.links.ts
|
|
12
|
-
var
|
|
14
|
+
var unsafeApi = unsafeConvexAnyApi(
|
|
15
|
+
"graph-primitives top-level module bundle lacks a committed Convex _generated/api surface"
|
|
16
|
+
);
|
|
17
|
+
var api = unsafeApi;
|
|
13
18
|
componentsGeneric();
|
|
14
|
-
var internal =
|
|
19
|
+
var internal = unsafeApi;
|
|
15
20
|
var mutation = mutationGeneric;
|
|
16
21
|
var query = queryGeneric;
|
|
17
22
|
|
|
18
|
-
// src/logicalRoleInference.ts
|
|
19
|
-
var PILLAR_IMPORTANCE = {
|
|
20
|
-
market: 1,
|
|
21
|
-
competition: 2,
|
|
22
|
-
product: 3,
|
|
23
|
-
team: 4,
|
|
24
|
-
financials: 5,
|
|
25
|
-
timing: 6,
|
|
26
|
-
other: 10
|
|
27
|
-
};
|
|
28
|
-
async function computeLogicalRole(ctx, evidenceId, beliefId) {
|
|
29
|
-
const belief = await ctx.db.get(beliefId);
|
|
30
|
-
if (!belief || belief.nodeType !== "belief") {
|
|
31
|
-
return "contributory";
|
|
32
|
-
}
|
|
33
|
-
const beliefMetadata = belief.metadata;
|
|
34
|
-
const pillar = beliefMetadata?.pillar || "other";
|
|
35
|
-
const pillarRank = PILLAR_IMPORTANCE[pillar] ?? 10;
|
|
36
|
-
const isSynthesized = await checkIfSynthesizedHypothesis(ctx, beliefId);
|
|
37
|
-
const testingQuestions = await getTestingQuestionsForBelief(ctx, beliefId);
|
|
38
|
-
const answeredQuestions = await getQuestionsAnsweredByEvidence(
|
|
39
|
-
ctx,
|
|
40
|
-
evidenceId
|
|
41
|
-
);
|
|
42
|
-
const directlyTests = testingQuestions.filter(
|
|
43
|
-
(questionId) => answeredQuestions.includes(questionId)
|
|
44
|
-
);
|
|
45
|
-
if (directlyTests.length === 0) {
|
|
46
|
-
return "contributory";
|
|
47
|
-
}
|
|
48
|
-
if (isSynthesized && pillarRank <= 2) {
|
|
49
|
-
return directlyTests.length > 1 ? "necessary_sufficient" : "necessary";
|
|
50
|
-
}
|
|
51
|
-
if (isSynthesized) {
|
|
52
|
-
return "necessary";
|
|
53
|
-
}
|
|
54
|
-
return directlyTests.length > 1 ? "necessary" : "contributory";
|
|
55
|
-
}
|
|
56
|
-
async function checkIfSynthesizedHypothesis(ctx, beliefId) {
|
|
57
|
-
const belief = await ctx.db.get(beliefId);
|
|
58
|
-
if (!belief) {
|
|
59
|
-
return false;
|
|
60
|
-
}
|
|
61
|
-
const metadata = belief.metadata;
|
|
62
|
-
return metadata?.isSynthesized === true || metadata?.beliefStatus === "hypothesis";
|
|
63
|
-
}
|
|
64
|
-
async function getTestingQuestionsForBelief(ctx, beliefId) {
|
|
65
|
-
const testEdges = await ctx.db.query("epistemicEdges").withIndex(
|
|
66
|
-
"by_to_type",
|
|
67
|
-
(q) => q.eq("toNodeId", beliefId).eq("edgeType", "tests")
|
|
68
|
-
).collect();
|
|
69
|
-
return testEdges.map((edge) => edge.fromNodeId).filter((id) => id !== void 0);
|
|
70
|
-
}
|
|
71
|
-
async function getQuestionsAnsweredByEvidence(ctx, evidenceId) {
|
|
72
|
-
const answerEdges = await ctx.db.query("epistemicEdges").withIndex(
|
|
73
|
-
"by_from_type",
|
|
74
|
-
(q) => q.eq("fromNodeId", evidenceId).eq("edgeType", "derived_from")
|
|
75
|
-
).collect();
|
|
76
|
-
return answerEdges.map((edge) => edge.toNodeId).filter((id) => id !== void 0);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
23
|
// src/debug.ts
|
|
80
24
|
function isGraphPrimitiveDebugEnabled() {
|
|
81
25
|
const env = globalThis.process?.env;
|
|
@@ -121,13 +65,15 @@ function asMappedProjectId(topic) {
|
|
|
121
65
|
if (!topic) {
|
|
122
66
|
return;
|
|
123
67
|
}
|
|
124
|
-
const directLegacyProjectId = normalizeScopeValue(
|
|
68
|
+
const directLegacyProjectId = normalizeScopeValue(
|
|
69
|
+
topic[LEGACY_SCOPE_FIELD]
|
|
70
|
+
);
|
|
125
71
|
if (directLegacyProjectId) {
|
|
126
72
|
return directLegacyProjectId;
|
|
127
73
|
}
|
|
128
74
|
const metadata = topic.metadata || {};
|
|
129
75
|
const candidate = metadata[LEGACY_SCOPE_FIELD] || metadata.legacyProjectId || metadata.projectId || metadata.scopeProjectId;
|
|
130
|
-
return candidate ? candidate : void 0;
|
|
76
|
+
return typeof candidate === "string" ? normalizeScopeValue(candidate) : void 0;
|
|
131
77
|
}
|
|
132
78
|
function normalizeScopeValue(value) {
|
|
133
79
|
if (typeof value !== "string") {
|
|
@@ -152,8 +98,9 @@ function pickPrimaryTopic(candidates) {
|
|
|
152
98
|
})[0];
|
|
153
99
|
}
|
|
154
100
|
async function findTopicsByScopeAlias(ctx, scopeId) {
|
|
101
|
+
const query2 = ctx.db.query("topics");
|
|
155
102
|
try {
|
|
156
|
-
return await
|
|
103
|
+
return await query2.withIndex(
|
|
157
104
|
"by_graph_scope_project",
|
|
158
105
|
(q) => q.eq(LEGACY_SCOPE_FIELD, scopeId)
|
|
159
106
|
).collect();
|
|
@@ -165,7 +112,7 @@ async function findTopicsByScopeAlias(ctx, scopeId) {
|
|
|
165
112
|
scopeId
|
|
166
113
|
}
|
|
167
114
|
);
|
|
168
|
-
const topics = await
|
|
115
|
+
const topics = await query2.collect();
|
|
169
116
|
return topics.filter((topic) => {
|
|
170
117
|
const normalizedGlobalId = normalizeScopeValue(topic.globalId);
|
|
171
118
|
const mappedProjectId = asMappedProjectId(topic);
|
|
@@ -221,168 +168,124 @@ async function resolveInheritedWorkspaceScope(ctx, topic) {
|
|
|
221
168
|
let current = topic;
|
|
222
169
|
for (let i = 0; i < MAX_DEPTH && current?.parentTopicId; i++) {
|
|
223
170
|
current = await ctx.db.get(current.parentTopicId);
|
|
224
|
-
if (!current)
|
|
171
|
+
if (!current) {
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
225
174
|
if (!tenantId) {
|
|
226
175
|
tenantId = normalizeScopeValue(current.tenantId);
|
|
227
176
|
}
|
|
228
177
|
if (!workspaceId) {
|
|
229
178
|
workspaceId = normalizeScopeValue(current.workspaceId);
|
|
230
179
|
}
|
|
231
|
-
if (tenantId && workspaceId)
|
|
180
|
+
if (tenantId && workspaceId) {
|
|
181
|
+
break;
|
|
182
|
+
}
|
|
232
183
|
}
|
|
233
184
|
return { tenantId, workspaceId };
|
|
234
185
|
}
|
|
235
186
|
async function resolveTopicProjectScope(ctx, args) {
|
|
236
187
|
if (args.topicId) {
|
|
237
|
-
|
|
238
|
-
try {
|
|
239
|
-
topic = await ctx.db.get(
|
|
240
|
-
args.topicId
|
|
241
|
-
);
|
|
242
|
-
} catch (error) {
|
|
243
|
-
debugGraphPrimitiveFallback(
|
|
244
|
-
"[topicScope] Failed to load topic by direct id",
|
|
245
|
-
{
|
|
246
|
-
error,
|
|
247
|
-
topicId: args.topicId
|
|
248
|
-
}
|
|
249
|
-
);
|
|
250
|
-
}
|
|
251
|
-
if (!topic) {
|
|
252
|
-
topic = await tryResolveHostTopicById(ctx, String(args.topicId));
|
|
253
|
-
}
|
|
254
|
-
if (!topic) {
|
|
255
|
-
topic = pickPrimaryTopic(
|
|
256
|
-
await findTopicsByScopeAlias(ctx, String(args.topicId))
|
|
257
|
-
) ?? null;
|
|
258
|
-
}
|
|
259
|
-
if (!topic) {
|
|
260
|
-
const nodeScope = await resolveTopicNodeScopeOrNull(
|
|
261
|
-
ctx,
|
|
262
|
-
String(args.topicId)
|
|
263
|
-
);
|
|
264
|
-
if (nodeScope) {
|
|
265
|
-
return nodeScope;
|
|
266
|
-
}
|
|
267
|
-
throw new Error(`Topic not found: ${String(args.topicId)}`);
|
|
268
|
-
}
|
|
269
|
-
const inherited = await resolveInheritedWorkspaceScope(ctx, topic);
|
|
270
|
-
const mapped = asMappedProjectId(topic);
|
|
271
|
-
if (mapped) {
|
|
272
|
-
return {
|
|
273
|
-
topicId: topic._id,
|
|
274
|
-
projectId: mapped,
|
|
275
|
-
tenantId: inherited.tenantId,
|
|
276
|
-
workspaceId: inherited.workspaceId,
|
|
277
|
-
source: "topic"
|
|
278
|
-
};
|
|
279
|
-
}
|
|
280
|
-
return {
|
|
281
|
-
topicId: topic._id,
|
|
282
|
-
tenantId: inherited.tenantId,
|
|
283
|
-
workspaceId: inherited.workspaceId,
|
|
284
|
-
source: "topic"
|
|
285
|
-
};
|
|
188
|
+
return await resolveScopeFromTopicId(ctx, args.topicId);
|
|
286
189
|
}
|
|
287
190
|
if (args.projectId) {
|
|
288
|
-
|
|
289
|
-
try {
|
|
290
|
-
directTopic = await ctx.db.get(
|
|
291
|
-
args.projectId
|
|
292
|
-
);
|
|
293
|
-
} catch (error) {
|
|
294
|
-
debugGraphPrimitiveFallback(
|
|
295
|
-
"[topicScope] Failed to load direct project topic",
|
|
296
|
-
{
|
|
297
|
-
error,
|
|
298
|
-
projectId: args.projectId
|
|
299
|
-
}
|
|
300
|
-
);
|
|
301
|
-
}
|
|
302
|
-
if (directTopic) {
|
|
303
|
-
const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);
|
|
304
|
-
const mapped = asMappedProjectId(directTopic);
|
|
305
|
-
return {
|
|
306
|
-
topicId: directTopic._id,
|
|
307
|
-
projectId: mapped ?? args.projectId,
|
|
308
|
-
tenantId: inherited.tenantId,
|
|
309
|
-
workspaceId: inherited.workspaceId,
|
|
310
|
-
source: "topic_inferred"
|
|
311
|
-
};
|
|
312
|
-
}
|
|
313
|
-
directTopic = await tryResolveHostTopicByLegacyScope(ctx, args.projectId);
|
|
314
|
-
if (directTopic) {
|
|
315
|
-
const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);
|
|
316
|
-
const mapped = asMappedProjectId(directTopic);
|
|
317
|
-
return {
|
|
318
|
-
topicId: directTopic._id,
|
|
319
|
-
projectId: mapped ?? args.projectId,
|
|
320
|
-
tenantId: inherited.tenantId,
|
|
321
|
-
workspaceId: inherited.workspaceId,
|
|
322
|
-
source: "topic_inferred"
|
|
323
|
-
};
|
|
324
|
-
}
|
|
325
|
-
const topics = await findTopicsByScopeAlias(ctx, args.projectId);
|
|
326
|
-
const primary = pickPrimaryTopic(topics);
|
|
327
|
-
if (primary) {
|
|
328
|
-
const inherited = await resolveInheritedWorkspaceScope(ctx, primary);
|
|
329
|
-
return {
|
|
330
|
-
topicId: primary._id,
|
|
331
|
-
projectId: args.projectId,
|
|
332
|
-
tenantId: inherited.tenantId,
|
|
333
|
-
workspaceId: inherited.workspaceId,
|
|
334
|
-
source: "project_mapped_topic"
|
|
335
|
-
};
|
|
336
|
-
}
|
|
337
|
-
const nodeScope = await resolveTopicNodeScopeOrNull(
|
|
338
|
-
ctx,
|
|
339
|
-
String(args.projectId)
|
|
340
|
-
);
|
|
341
|
-
if (nodeScope) {
|
|
342
|
-
return {
|
|
343
|
-
...nodeScope,
|
|
344
|
-
projectId: nodeScope.projectId ?? String(args.projectId)
|
|
345
|
-
};
|
|
346
|
-
}
|
|
347
|
-
throw new Error(
|
|
348
|
-
`Legacy project scope ${String(args.projectId)} has no mapped topic.`
|
|
349
|
-
);
|
|
191
|
+
return await resolveScopeFromLegacyProjectId(ctx, args.projectId);
|
|
350
192
|
}
|
|
351
193
|
throw new Error(
|
|
352
194
|
"Missing scope: provide topicId (preferred) or legacy projectId alias."
|
|
353
195
|
);
|
|
354
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
|
+
}
|
|
355
280
|
var optionalScopeArgs = {
|
|
356
281
|
projectId: v.optional(v.string()),
|
|
357
282
|
topicId: v.optional(v.string())
|
|
358
283
|
};
|
|
359
|
-
|
|
360
|
-
// src/epistemicBeliefs.helpers.ts
|
|
361
284
|
var insightIdUnion = v.id("epistemicNodes");
|
|
362
285
|
var optionalBeliefScopeArgs = optionalScopeArgs;
|
|
363
286
|
({
|
|
364
287
|
tupleContradiction: normalizeTupleContradictionPolicy()
|
|
365
288
|
});
|
|
366
|
-
function throwStructuredMutationError(args) {
|
|
367
|
-
const data = {
|
|
368
|
-
structuredMutationError: true,
|
|
369
|
-
message: args.message,
|
|
370
|
-
status: args.status,
|
|
371
|
-
code: args.code,
|
|
372
|
-
invariantCode: args.invariantCode,
|
|
373
|
-
suggestion: args.suggestion,
|
|
374
|
-
details: args.details
|
|
375
|
-
};
|
|
376
|
-
const error = new ConvexError(
|
|
377
|
-
data
|
|
378
|
-
);
|
|
379
|
-
error.status = args.status;
|
|
380
|
-
error.code = args.code;
|
|
381
|
-
error.invariantCode = args.invariantCode;
|
|
382
|
-
error.suggestion = args.suggestion;
|
|
383
|
-
error.details = args.details;
|
|
384
|
-
throw error;
|
|
385
|
-
}
|
|
386
289
|
function buildBeliefStatusSuccessResult() {
|
|
387
290
|
return { success: true };
|
|
388
291
|
}
|
|
@@ -393,7 +296,7 @@ function buildBeliefEvidenceNotFoundResult() {
|
|
|
393
296
|
return result;
|
|
394
297
|
}
|
|
395
298
|
async function resolveBeliefScopeOrNull(ctx, args) {
|
|
396
|
-
if (!args.projectId
|
|
299
|
+
if (!(args.projectId || args.topicId)) {
|
|
397
300
|
return null;
|
|
398
301
|
}
|
|
399
302
|
try {
|
|
@@ -428,26 +331,12 @@ async function requireAuthenticatedUserId(ctx) {
|
|
|
428
331
|
}
|
|
429
332
|
return userId;
|
|
430
333
|
}
|
|
431
|
-
async function requireProjectWriteAccess(ctx, projectId, userId) {
|
|
432
|
-
const hasAccess = await checkProjectAccess(
|
|
433
|
-
ctx,
|
|
434
|
-
projectId,
|
|
435
|
-
userId
|
|
436
|
-
);
|
|
437
|
-
if (!hasAccess) {
|
|
438
|
-
throwStructuredMutationError({
|
|
439
|
-
message: `Project write access denied for topic ${projectId}.`,
|
|
440
|
-
status: 403,
|
|
441
|
-
code: "PROJECT_ACCESS_DENIED",
|
|
442
|
-
invariantCode: "policy.scope_required",
|
|
443
|
-
suggestion: "The acting principal lacks project-write access to this topic. Request a topic grant (or, if the principal created this topic, run the creator-grant backfill) and retry.",
|
|
444
|
-
details: { topicId: projectId, principalId: userId }
|
|
445
|
-
});
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
334
|
async function assertExistingNodeEndpoint(ctx, endpointRole, endpoint) {
|
|
449
335
|
assertUuidShapedEdgeEndpoint(endpointRole, endpoint);
|
|
450
|
-
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();
|
|
451
340
|
if (!node) {
|
|
452
341
|
throw new Error(
|
|
453
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)`
|
|
@@ -488,7 +377,193 @@ async function insertEpistemicEdge(ctx, doc) {
|
|
|
488
377
|
return ctx.db.insert("epistemicEdges", doc);
|
|
489
378
|
}
|
|
490
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
|
+
|
|
491
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
|
+
}
|
|
492
567
|
function assertSignedImpactScore(value, context) {
|
|
493
568
|
if (typeof value !== "number" || !Number.isFinite(value) || value === 0 || value < -1 || value > 1) {
|
|
494
569
|
throw new Error(`${context} requires explicit nonzero weight in [-1, 1]`);
|
|
@@ -519,20 +594,21 @@ var updatePillar = mutation({
|
|
|
519
594
|
handler: async (ctx, args) => {
|
|
520
595
|
const authenticatedUserId = await requireAuthenticatedUserId(ctx);
|
|
521
596
|
const now = Date.now();
|
|
522
|
-
const existingNode =
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
597
|
+
const existingNode = requireEpistemicNodeRow(
|
|
598
|
+
await ctx.db.get(args.nodeId),
|
|
599
|
+
"belief",
|
|
600
|
+
"Belief not found"
|
|
601
|
+
);
|
|
526
602
|
if (!existingNode.projectId) {
|
|
527
603
|
throw new Error("Belief has no project scope");
|
|
528
604
|
}
|
|
529
|
-
await
|
|
605
|
+
await requireScopeWriteAccess(
|
|
530
606
|
ctx,
|
|
531
607
|
existingNode.projectId,
|
|
532
608
|
authenticatedUserId
|
|
533
609
|
);
|
|
534
610
|
let previousPillar = null;
|
|
535
|
-
const metadata = existingNode.metadata
|
|
611
|
+
const metadata = existingNode.metadata ?? {};
|
|
536
612
|
previousPillar = metadata.pillar;
|
|
537
613
|
await ctx.db.patch(args.nodeId, {
|
|
538
614
|
metadata: {
|
|
@@ -548,7 +624,7 @@ var updatePillar = mutation({
|
|
|
548
624
|
});
|
|
549
625
|
await ctx.db.insert("epistemicAudit", {
|
|
550
626
|
entityType: "belief",
|
|
551
|
-
entityId: args.nodeId,
|
|
627
|
+
entityId: String(args.nodeId),
|
|
552
628
|
changeType: "pillar_changed",
|
|
553
629
|
projectId: existingNode.projectId,
|
|
554
630
|
changedBy: authenticatedUserId,
|
|
@@ -574,10 +650,13 @@ var getCountByStatus = query({
|
|
|
574
650
|
if (!scope) {
|
|
575
651
|
return { active: 0, superseded: 0, archived: 0, total: 0 };
|
|
576
652
|
}
|
|
577
|
-
const nodes = await ctx.db.query("epistemicNodes").withIndex(
|
|
653
|
+
const nodes = (await ctx.db.query("epistemicNodes").withIndex(
|
|
578
654
|
"by_topic_type",
|
|
579
655
|
(q) => q.eq("topicId", scope.topicId).eq("nodeType", "belief")
|
|
580
|
-
).collect()
|
|
656
|
+
).collect()).flatMap((row) => {
|
|
657
|
+
const node = readEpistemicNodeRow(row);
|
|
658
|
+
return node?.nodeType === "belief" ? [node] : [];
|
|
659
|
+
});
|
|
581
660
|
const counts = {
|
|
582
661
|
active: 0,
|
|
583
662
|
superseded: 0,
|
|
@@ -618,31 +697,31 @@ var linkBeliefs = mutation({
|
|
|
618
697
|
returns: permissiveReturn,
|
|
619
698
|
handler: async (ctx, args) => {
|
|
620
699
|
const authenticatedUserId = await requireAuthenticatedUserId(ctx);
|
|
621
|
-
const fromNode =
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
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
|
+
);
|
|
629
710
|
if (fromNode.projectId !== toNode.projectId) {
|
|
630
711
|
throw new Error("Cannot link beliefs across different projects");
|
|
631
712
|
}
|
|
632
713
|
if (!fromNode.projectId) {
|
|
633
714
|
throw new Error("Belief has no project scope");
|
|
634
715
|
}
|
|
635
|
-
await
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
authenticatedUserId
|
|
639
|
-
);
|
|
716
|
+
await requireScopeWriteAccess(ctx, fromNode.projectId, authenticatedUserId);
|
|
717
|
+
const fromGlobalId = requireNodeGlobalId(fromNode, "Belief link");
|
|
718
|
+
const toGlobalId = requireNodeGlobalId(toNode, "Belief link");
|
|
640
719
|
const now = Date.now();
|
|
641
720
|
const edgeGlobalId = generateGlobalId();
|
|
642
721
|
await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {
|
|
643
722
|
globalId: edgeGlobalId,
|
|
644
|
-
fromGlobalId
|
|
645
|
-
toGlobalId
|
|
723
|
+
fromGlobalId,
|
|
724
|
+
toGlobalId,
|
|
646
725
|
edgeType: args.edgeType,
|
|
647
726
|
weight: args.weight ?? 1,
|
|
648
727
|
context: args.context,
|
|
@@ -681,23 +760,26 @@ var linkEvidence = mutation({
|
|
|
681
760
|
returns: permissiveReturn,
|
|
682
761
|
handler: async (ctx, args) => {
|
|
683
762
|
const authenticatedUserId = await requireAuthenticatedUserId(ctx);
|
|
684
|
-
const belief =
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
763
|
+
const belief = requireEpistemicNodeRow(
|
|
764
|
+
await ctx.db.get(args.beliefNodeId),
|
|
765
|
+
"belief",
|
|
766
|
+
"Belief not found"
|
|
767
|
+
);
|
|
688
768
|
if (!belief.projectId) {
|
|
689
769
|
throw new Error("Belief has no project scope");
|
|
690
770
|
}
|
|
691
|
-
await
|
|
692
|
-
const insight =
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
771
|
+
await requireScopeWriteAccess(ctx, belief.projectId, authenticatedUserId);
|
|
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) {
|
|
697
778
|
throw new Error("Insight belongs to a different project");
|
|
698
779
|
}
|
|
699
780
|
const evidenceNodeId = insight._id;
|
|
700
|
-
const evidenceGlobalId = insight
|
|
781
|
+
const evidenceGlobalId = requireNodeGlobalId(insight, "Evidence link");
|
|
782
|
+
const beliefGlobalId = requireNodeGlobalId(belief, "Evidence link");
|
|
701
783
|
const weight = assertSignedImpactScore(args.weight, "Evidence link");
|
|
702
784
|
if (args.type === "supporting" && weight < 0) {
|
|
703
785
|
throw new Error("Supporting evidence links require positive weight");
|
|
@@ -713,9 +795,9 @@ var linkEvidence = mutation({
|
|
|
713
795
|
globalId: edgeGlobalId,
|
|
714
796
|
// C2-RR.4 Defect E — canonical UUIDv7 endpoints, not Convex doc ids.
|
|
715
797
|
fromNodeId: evidenceGlobalId,
|
|
716
|
-
toNodeId:
|
|
798
|
+
toNodeId: beliefGlobalId,
|
|
717
799
|
sourceGlobalId: evidenceGlobalId,
|
|
718
|
-
targetGlobalId:
|
|
800
|
+
targetGlobalId: beliefGlobalId,
|
|
719
801
|
edgeType,
|
|
720
802
|
weight,
|
|
721
803
|
confidence,
|
|
@@ -743,7 +825,7 @@ var linkEvidence = mutation({
|
|
|
743
825
|
await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {
|
|
744
826
|
globalId: edgeGlobalId,
|
|
745
827
|
fromGlobalId: evidenceGlobalId,
|
|
746
|
-
toGlobalId:
|
|
828
|
+
toGlobalId: beliefGlobalId,
|
|
747
829
|
edgeType,
|
|
748
830
|
weight,
|
|
749
831
|
confidence,
|
|
@@ -772,29 +854,38 @@ var unlinkEvidence = mutation({
|
|
|
772
854
|
handler: async (ctx, args) => {
|
|
773
855
|
const authenticatedUserId = await requireAuthenticatedUserId(ctx);
|
|
774
856
|
const now = Date.now();
|
|
775
|
-
const
|
|
776
|
-
|
|
857
|
+
const evidenceNodeRaw = await ctx.db.get(args.insightId);
|
|
858
|
+
const evidenceNode = readEpistemicNodeRow(evidenceNodeRaw);
|
|
859
|
+
if (evidenceNode?.nodeType !== "evidence") {
|
|
777
860
|
return buildBeliefEvidenceNotFoundResult();
|
|
778
861
|
}
|
|
779
862
|
if (!evidenceNode.projectId) {
|
|
780
863
|
throw new Error("Evidence has no project scope");
|
|
781
864
|
}
|
|
782
|
-
await
|
|
865
|
+
await requireScopeWriteAccess(
|
|
783
866
|
ctx,
|
|
784
867
|
evidenceNode.projectId,
|
|
785
868
|
authenticatedUserId
|
|
786
869
|
);
|
|
787
|
-
const beliefNode =
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
870
|
+
const beliefNode = requireEpistemicNodeRow(
|
|
871
|
+
await ctx.db.get(args.beliefNodeId),
|
|
872
|
+
"belief",
|
|
873
|
+
"Belief not found"
|
|
874
|
+
);
|
|
791
875
|
if (beliefNode.projectId !== evidenceNode.projectId) {
|
|
792
876
|
throw new Error("Belief and evidence belong to different projects");
|
|
793
877
|
}
|
|
794
|
-
const
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
)
|
|
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
|
+
);
|
|
798
889
|
if (edge) {
|
|
799
890
|
await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.deleteEdge, {
|
|
800
891
|
globalId: edge.globalId
|
|
@@ -824,25 +915,31 @@ var getWithEvidence = query({
|
|
|
824
915
|
},
|
|
825
916
|
returns: permissiveReturn,
|
|
826
917
|
handler: async (ctx, args) => {
|
|
827
|
-
const belief = await ctx.db.get(args.nodeId);
|
|
828
|
-
if (
|
|
918
|
+
const belief = readEpistemicNodeRow(await ctx.db.get(args.nodeId));
|
|
919
|
+
if (belief?.nodeType !== "belief") {
|
|
829
920
|
return null;
|
|
830
921
|
}
|
|
831
|
-
const
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
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()
|
|
838
928
|
);
|
|
839
929
|
const supporting = [];
|
|
840
930
|
const contradicting = [];
|
|
841
|
-
for (
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
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) {
|
|
846
943
|
supporting.push(node);
|
|
847
944
|
} else {
|
|
848
945
|
contradicting.push(node);
|
|
@@ -870,13 +967,13 @@ async function collectRelationshipNodeRefs(ctx, nodeId) {
|
|
|
870
967
|
}
|
|
871
968
|
function endpointMatches(q, fields, refs) {
|
|
872
969
|
return q.or(
|
|
873
|
-
...fields.flatMap(
|
|
874
|
-
(field) => refs.map((ref) => q.eq(q.field(field), ref))
|
|
875
|
-
)
|
|
970
|
+
...fields.flatMap((field) => refs.map((ref) => q.eq(q.field(field), ref)))
|
|
876
971
|
);
|
|
877
972
|
}
|
|
878
973
|
async function resolveRelationshipEndpoint(ctx, endpointId, globalEndpointId) {
|
|
879
|
-
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
|
+
);
|
|
880
977
|
for (const candidate of candidates) {
|
|
881
978
|
try {
|
|
882
979
|
const direct = await ctx.db.get(candidate);
|
|
@@ -908,13 +1005,15 @@ var getRelationships = query({
|
|
|
908
1005
|
};
|
|
909
1006
|
const nodeRefs = await collectRelationshipNodeRefs(ctx, args.nodeId);
|
|
910
1007
|
if (direction === "in" || direction === "both") {
|
|
911
|
-
const inEdges =
|
|
912
|
-
(
|
|
913
|
-
q
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
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
|
+
);
|
|
918
1017
|
for (const edge of inEdges) {
|
|
919
1018
|
const sourceNode = await resolveRelationshipEndpoint(
|
|
920
1019
|
ctx,
|
|
@@ -925,13 +1024,15 @@ var getRelationships = query({
|
|
|
925
1024
|
}
|
|
926
1025
|
}
|
|
927
1026
|
if (direction === "out" || direction === "both") {
|
|
928
|
-
const outEdges =
|
|
929
|
-
(
|
|
930
|
-
q
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
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
|
+
);
|
|
935
1036
|
for (const edge of outEdges) {
|
|
936
1037
|
const targetNode = await resolveRelationshipEndpoint(
|
|
937
1038
|
ctx,
|