@lucern/graph-primitives 1.0.29 → 1.0.31
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,14 +1,25 @@
|
|
|
1
1
|
import { canAudienceClassAccess, normalizeAudienceKey, classFromAudienceKey } from '@lucern/access-control/audience';
|
|
2
|
-
import {
|
|
2
|
+
import { unsafeConvexAnyApi } from '@lucern/contracts/convex/unsafeAnyApi';
|
|
3
|
+
import { componentsGeneric, mutationGeneric, internalMutationGeneric, queryGeneric, internalQueryGeneric } from 'convex/server';
|
|
3
4
|
import { v } from 'convex/values';
|
|
4
5
|
import { requireScopeWriteAccess, checkScopeAccess } from '@lucern/access-control/access';
|
|
6
|
+
import { EVIDENCE_SOURCE_QUALITY_VALUES, EVIDENCE_METHODOLOGY_VALUES, EVIDENCE_INFORMATION_ASYMMETRY_VALUES, assertEdgePolicyAllowed, edgePolicyManifest } from '@lucern/contracts';
|
|
5
7
|
import { permissiveReturn } from '@lucern/contracts/schema-helpers/validators';
|
|
6
8
|
import { generateGlobalId, assertUuidV7Identity, assertStorageEdgeVocabulary, assertUuidShapedEdgeEndpoint } from '@lucern/contracts/ids';
|
|
7
9
|
import { isNodeType, getLayerForNodeType } from '@lucern/contracts/schema-helpers/spine/tables/epistemicNodes';
|
|
8
|
-
import { assertEdgePolicyAllowed, edgePolicyManifest } from '@lucern/contracts';
|
|
9
10
|
import { listAudienceRegistryRows } from '@lucern/access-control/audienceRegistry';
|
|
10
11
|
|
|
11
12
|
// src/epistemicEvidenceHelpers.ts
|
|
13
|
+
var unsafeApi = unsafeConvexAnyApi(
|
|
14
|
+
"graph-primitives top-level module bundle lacks a committed Convex _generated/api surface"
|
|
15
|
+
);
|
|
16
|
+
var api = unsafeApi;
|
|
17
|
+
componentsGeneric();
|
|
18
|
+
var internal = unsafeApi;
|
|
19
|
+
var internalMutation = internalMutationGeneric;
|
|
20
|
+
var internalQuery = internalQueryGeneric;
|
|
21
|
+
var mutation = mutationGeneric;
|
|
22
|
+
var query = queryGeneric;
|
|
12
23
|
|
|
13
24
|
// src/debug.ts
|
|
14
25
|
function isGraphPrimitiveDebugEnabled() {
|
|
@@ -21,13 +32,6 @@ function debugGraphPrimitiveFallback(message, context) {
|
|
|
21
32
|
}
|
|
22
33
|
console.debug(message, context ?? {});
|
|
23
34
|
}
|
|
24
|
-
var api = anyApi;
|
|
25
|
-
componentsGeneric();
|
|
26
|
-
var internal = anyApi;
|
|
27
|
-
var internalMutation = internalMutationGeneric;
|
|
28
|
-
var internalQuery = internalQueryGeneric;
|
|
29
|
-
var mutation = mutationGeneric;
|
|
30
|
-
var query = queryGeneric;
|
|
31
35
|
|
|
32
36
|
// src/topicProjectOverlay.ts
|
|
33
37
|
var LEGACY_SCOPE_FIELD = "graphScopeProjectId";
|
|
@@ -47,6 +51,10 @@ function readStringArray(value) {
|
|
|
47
51
|
function readMetadata(topic) {
|
|
48
52
|
return topic.metadata && typeof topic.metadata === "object" ? topic.metadata : {};
|
|
49
53
|
}
|
|
54
|
+
function omitMetadataKey(metadata, key) {
|
|
55
|
+
const { [key]: _omitted, ...rest } = metadata;
|
|
56
|
+
return rest;
|
|
57
|
+
}
|
|
50
58
|
function readLegacyProjectId(value) {
|
|
51
59
|
if (!value) {
|
|
52
60
|
return;
|
|
@@ -127,9 +135,12 @@ async function resolveTopicDoc(ctx, scopeId) {
|
|
|
127
135
|
);
|
|
128
136
|
}
|
|
129
137
|
try {
|
|
130
|
-
const topic = await ctx.runQuery(
|
|
131
|
-
|
|
132
|
-
|
|
138
|
+
const topic = await ctx.runQuery(
|
|
139
|
+
api.topics.getByLegacyScopeId,
|
|
140
|
+
{
|
|
141
|
+
projectId: String(scopeId)
|
|
142
|
+
}
|
|
143
|
+
);
|
|
133
144
|
if (topic?.name !== void 0 && topic?.type !== void 0) {
|
|
134
145
|
return topic;
|
|
135
146
|
}
|
|
@@ -149,8 +160,18 @@ function materializeTopicProjectOverlay(topic, idMode = "legacy") {
|
|
|
149
160
|
const outwardId = idMode === "topic" ? topicId : storageProjectId;
|
|
150
161
|
const visibility = coerceVisibility(topic.visibility) || coerceVisibility(metadata.visibility) || "private";
|
|
151
162
|
const status = coerceStatus(topic.status) || coerceStatus(metadata.status) || "active";
|
|
152
|
-
|
|
153
|
-
|
|
163
|
+
let createdAt = 0;
|
|
164
|
+
if (typeof topic.createdAt === "number") {
|
|
165
|
+
createdAt = topic.createdAt;
|
|
166
|
+
} else if (typeof topic._creationTime === "number") {
|
|
167
|
+
createdAt = topic._creationTime;
|
|
168
|
+
}
|
|
169
|
+
let updatedAt = createdAt;
|
|
170
|
+
if (typeof topic.updatedAt === "number") {
|
|
171
|
+
updatedAt = topic.updatedAt;
|
|
172
|
+
} else if (typeof metadata.updatedAt === "number") {
|
|
173
|
+
updatedAt = metadata.updatedAt;
|
|
174
|
+
}
|
|
154
175
|
return {
|
|
155
176
|
...metadata,
|
|
156
177
|
_id: outwardId,
|
|
@@ -219,90 +240,113 @@ async function patchTopicProjectOverlay(ctx, scopeId, value) {
|
|
|
219
240
|
if (!topic) {
|
|
220
241
|
return null;
|
|
221
242
|
}
|
|
222
|
-
const
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
243
|
+
const plan = buildTopicProjectOverlayPatchPlan(topic, value);
|
|
244
|
+
await applyTopicProjectOverlayPatch(ctx, topic, plan);
|
|
245
|
+
return materializeTopicProjectOverlay({
|
|
246
|
+
...topic,
|
|
247
|
+
...plan.patch,
|
|
248
|
+
metadata: plan.nextMetadata
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
function buildTopicProjectOverlayPatchPlan(topic, value) {
|
|
252
|
+
const plan = {
|
|
253
|
+
nextMetadata: { ...readMetadata(topic) },
|
|
254
|
+
patch: {},
|
|
255
|
+
topicUpdateArgs: {
|
|
256
|
+
id: String(topic._id)
|
|
257
|
+
}
|
|
226
258
|
};
|
|
227
259
|
for (const [key, rawValue] of Object.entries(value)) {
|
|
228
|
-
|
|
229
|
-
case "_id":
|
|
230
|
-
case "projectId":
|
|
231
|
-
case "topicId":
|
|
232
|
-
case "legacyProjectId":
|
|
233
|
-
case "storageProjectId":
|
|
234
|
-
break;
|
|
235
|
-
case "name":
|
|
236
|
-
case "description":
|
|
237
|
-
patch[key] = rawValue;
|
|
238
|
-
topicUpdateArgs[key] = rawValue;
|
|
239
|
-
break;
|
|
240
|
-
case "tenantId":
|
|
241
|
-
case "workspaceId":
|
|
242
|
-
case "ownerId":
|
|
243
|
-
throw new Error(
|
|
244
|
-
`patchTopicProjectOverlay cannot mutate ${key} via component-owned topics`
|
|
245
|
-
);
|
|
246
|
-
case "status": {
|
|
247
|
-
const status = coerceStatus(rawValue);
|
|
248
|
-
if (status) {
|
|
249
|
-
patch.status = status;
|
|
250
|
-
topicUpdateArgs.status = status;
|
|
251
|
-
}
|
|
252
|
-
break;
|
|
253
|
-
}
|
|
254
|
-
case "visibility": {
|
|
255
|
-
const visibility = coerceVisibility(rawValue);
|
|
256
|
-
if (visibility) {
|
|
257
|
-
patch.visibility = visibility;
|
|
258
|
-
topicUpdateArgs.visibility = visibility;
|
|
259
|
-
}
|
|
260
|
-
break;
|
|
261
|
-
}
|
|
262
|
-
case "type": {
|
|
263
|
-
const projectType = readNonEmptyString(rawValue);
|
|
264
|
-
if (projectType) {
|
|
265
|
-
nextMetadata.projectType = projectType;
|
|
266
|
-
} else {
|
|
267
|
-
delete nextMetadata.projectType;
|
|
268
|
-
}
|
|
269
|
-
break;
|
|
270
|
-
}
|
|
271
|
-
case "updatedAt":
|
|
272
|
-
case "createdAt":
|
|
273
|
-
break;
|
|
274
|
-
default:
|
|
275
|
-
if (rawValue === void 0) {
|
|
276
|
-
delete nextMetadata[key];
|
|
277
|
-
} else {
|
|
278
|
-
nextMetadata[key] = rawValue;
|
|
279
|
-
}
|
|
280
|
-
}
|
|
260
|
+
applyTopicProjectOverlayPatchEntry(plan, key, rawValue);
|
|
281
261
|
}
|
|
282
|
-
patch.updatedAt = Date.now();
|
|
283
|
-
patch.metadata = nextMetadata;
|
|
284
|
-
topicUpdateArgs.metadata = nextMetadata;
|
|
262
|
+
plan.patch.updatedAt = Date.now();
|
|
263
|
+
plan.patch.metadata = plan.nextMetadata;
|
|
264
|
+
plan.topicUpdateArgs.metadata = plan.nextMetadata;
|
|
265
|
+
return plan;
|
|
266
|
+
}
|
|
267
|
+
function applyTopicProjectOverlayPatchEntry(plan, key, rawValue) {
|
|
268
|
+
switch (key) {
|
|
269
|
+
case "_id":
|
|
270
|
+
case "projectId":
|
|
271
|
+
case "topicId":
|
|
272
|
+
case "legacyProjectId":
|
|
273
|
+
case "storageProjectId":
|
|
274
|
+
case "updatedAt":
|
|
275
|
+
case "createdAt":
|
|
276
|
+
return;
|
|
277
|
+
case "name":
|
|
278
|
+
case "description":
|
|
279
|
+
plan.patch[key] = rawValue;
|
|
280
|
+
plan.topicUpdateArgs[key] = rawValue;
|
|
281
|
+
return;
|
|
282
|
+
case "tenantId":
|
|
283
|
+
case "workspaceId":
|
|
284
|
+
case "ownerId":
|
|
285
|
+
throw new Error(
|
|
286
|
+
`patchTopicProjectOverlay cannot mutate ${key} via component-owned topics`
|
|
287
|
+
);
|
|
288
|
+
case "status":
|
|
289
|
+
applyTopicStatusPatch(plan, rawValue);
|
|
290
|
+
return;
|
|
291
|
+
case "visibility":
|
|
292
|
+
applyTopicVisibilityPatch(plan, rawValue);
|
|
293
|
+
return;
|
|
294
|
+
case "type":
|
|
295
|
+
applyTopicProjectTypePatch(plan, rawValue);
|
|
296
|
+
return;
|
|
297
|
+
default:
|
|
298
|
+
applyTopicMetadataPatch(plan, key, rawValue);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
function applyTopicStatusPatch(plan, rawValue) {
|
|
302
|
+
const status = coerceStatus(rawValue);
|
|
303
|
+
if (status) {
|
|
304
|
+
plan.patch.status = status;
|
|
305
|
+
plan.topicUpdateArgs.status = status;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
function applyTopicVisibilityPatch(plan, rawValue) {
|
|
309
|
+
const visibility = coerceVisibility(rawValue);
|
|
310
|
+
if (visibility) {
|
|
311
|
+
plan.patch.visibility = visibility;
|
|
312
|
+
plan.topicUpdateArgs.visibility = visibility;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
function applyTopicProjectTypePatch(plan, rawValue) {
|
|
316
|
+
const projectType = readNonEmptyString(rawValue);
|
|
317
|
+
if (projectType) {
|
|
318
|
+
plan.nextMetadata.projectType = projectType;
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
plan.nextMetadata = omitMetadataKey(plan.nextMetadata, "projectType");
|
|
322
|
+
}
|
|
323
|
+
function applyTopicMetadataPatch(plan, key, rawValue) {
|
|
324
|
+
if (rawValue === void 0) {
|
|
325
|
+
plan.nextMetadata = omitMetadataKey(plan.nextMetadata, key);
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
plan.nextMetadata[key] = rawValue;
|
|
329
|
+
}
|
|
330
|
+
async function applyTopicProjectOverlayPatch(ctx, topic, plan) {
|
|
285
331
|
if (typeof ctx.runMutation === "function") {
|
|
286
332
|
try {
|
|
287
|
-
await ctx.runMutation(api.topics.update, topicUpdateArgs);
|
|
333
|
+
await ctx.runMutation(api.topics.update, plan.topicUpdateArgs);
|
|
288
334
|
} catch (error) {
|
|
289
|
-
if (!
|
|
335
|
+
if (!canPatchTopicViaLocalDb(ctx, error)) {
|
|
290
336
|
throw error;
|
|
291
337
|
}
|
|
292
|
-
await ctx.db.patch(
|
|
338
|
+
await ctx.db.patch(topic._id, plan.patch);
|
|
293
339
|
}
|
|
294
340
|
} else if (ctx?.db && typeof ctx.db.patch === "function") {
|
|
295
|
-
await ctx.db.patch(
|
|
341
|
+
await ctx.db.patch(topic._id, plan.patch);
|
|
296
342
|
} else {
|
|
297
343
|
throw new Error(
|
|
298
344
|
"Cannot patch topic without component adapter (ctx.runMutation unavailable)"
|
|
299
345
|
);
|
|
300
346
|
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
metadata: nextMetadata
|
|
305
|
-
});
|
|
347
|
+
}
|
|
348
|
+
function canPatchTopicViaLocalDb(ctx, error) {
|
|
349
|
+
return isMissingLucernChildComponentError(error) && Boolean(ctx?.db) && typeof ctx.db?.patch === "function";
|
|
306
350
|
}
|
|
307
351
|
|
|
308
352
|
// src/resolvers.ts
|
|
@@ -330,7 +374,7 @@ async function patchProjectWithTolerance(ctx, projectId, value) {
|
|
|
330
374
|
try {
|
|
331
375
|
await patchTopicProjectOverlay(ctx, projectId, value);
|
|
332
376
|
} catch (error) {
|
|
333
|
-
if (!isAdvisoryTopicPatch(value)
|
|
377
|
+
if (!(isAdvisoryTopicPatch(value) && isMissingLucernChildComponentError2(error))) {
|
|
334
378
|
throw error;
|
|
335
379
|
}
|
|
336
380
|
console.warn(
|
|
@@ -397,13 +441,15 @@ function asMappedProjectId(topic) {
|
|
|
397
441
|
if (!topic) {
|
|
398
442
|
return;
|
|
399
443
|
}
|
|
400
|
-
const directLegacyProjectId = normalizeScopeValue(
|
|
444
|
+
const directLegacyProjectId = normalizeScopeValue(
|
|
445
|
+
topic[LEGACY_SCOPE_FIELD2]
|
|
446
|
+
);
|
|
401
447
|
if (directLegacyProjectId) {
|
|
402
448
|
return directLegacyProjectId;
|
|
403
449
|
}
|
|
404
450
|
const metadata = topic.metadata || {};
|
|
405
451
|
const candidate = metadata[LEGACY_SCOPE_FIELD2] || metadata.legacyProjectId || metadata.projectId || metadata.scopeProjectId;
|
|
406
|
-
return candidate ? candidate : void 0;
|
|
452
|
+
return typeof candidate === "string" ? normalizeScopeValue(candidate) : void 0;
|
|
407
453
|
}
|
|
408
454
|
function normalizeScopeValue(value) {
|
|
409
455
|
if (typeof value !== "string") {
|
|
@@ -428,8 +474,9 @@ function pickPrimaryTopic(candidates) {
|
|
|
428
474
|
})[0];
|
|
429
475
|
}
|
|
430
476
|
async function findTopicsByScopeAlias(ctx, scopeId) {
|
|
477
|
+
const query2 = ctx.db.query("topics");
|
|
431
478
|
try {
|
|
432
|
-
return await
|
|
479
|
+
return await query2.withIndex(
|
|
433
480
|
"by_graph_scope_project",
|
|
434
481
|
(q) => q.eq(LEGACY_SCOPE_FIELD2, scopeId)
|
|
435
482
|
).collect();
|
|
@@ -441,7 +488,7 @@ async function findTopicsByScopeAlias(ctx, scopeId) {
|
|
|
441
488
|
scopeId
|
|
442
489
|
}
|
|
443
490
|
);
|
|
444
|
-
const topics = await
|
|
491
|
+
const topics = await query2.collect();
|
|
445
492
|
return topics.filter((topic) => {
|
|
446
493
|
const normalizedGlobalId = normalizeScopeValue(topic.globalId);
|
|
447
494
|
const mappedProjectId = asMappedProjectId(topic);
|
|
@@ -497,137 +544,115 @@ async function resolveInheritedWorkspaceScope(ctx, topic) {
|
|
|
497
544
|
let current = topic;
|
|
498
545
|
for (let i = 0; i < MAX_DEPTH && current?.parentTopicId; i++) {
|
|
499
546
|
current = await ctx.db.get(current.parentTopicId);
|
|
500
|
-
if (!current)
|
|
547
|
+
if (!current) {
|
|
548
|
+
break;
|
|
549
|
+
}
|
|
501
550
|
if (!tenantId) {
|
|
502
551
|
tenantId = normalizeScopeValue(current.tenantId);
|
|
503
552
|
}
|
|
504
553
|
if (!workspaceId) {
|
|
505
554
|
workspaceId = normalizeScopeValue(current.workspaceId);
|
|
506
555
|
}
|
|
507
|
-
if (tenantId && workspaceId)
|
|
556
|
+
if (tenantId && workspaceId) {
|
|
557
|
+
break;
|
|
558
|
+
}
|
|
508
559
|
}
|
|
509
560
|
return { tenantId, workspaceId };
|
|
510
561
|
}
|
|
511
562
|
async function resolveTopicProjectScope(ctx, args) {
|
|
512
563
|
if (args.topicId) {
|
|
513
|
-
|
|
514
|
-
try {
|
|
515
|
-
topic = await ctx.db.get(
|
|
516
|
-
args.topicId
|
|
517
|
-
);
|
|
518
|
-
} catch (error) {
|
|
519
|
-
debugGraphPrimitiveFallback(
|
|
520
|
-
"[topicScope] Failed to load topic by direct id",
|
|
521
|
-
{
|
|
522
|
-
error,
|
|
523
|
-
topicId: args.topicId
|
|
524
|
-
}
|
|
525
|
-
);
|
|
526
|
-
}
|
|
527
|
-
if (!topic) {
|
|
528
|
-
topic = await tryResolveHostTopicById(ctx, String(args.topicId));
|
|
529
|
-
}
|
|
530
|
-
if (!topic) {
|
|
531
|
-
topic = pickPrimaryTopic(
|
|
532
|
-
await findTopicsByScopeAlias(ctx, String(args.topicId))
|
|
533
|
-
) ?? null;
|
|
534
|
-
}
|
|
535
|
-
if (!topic) {
|
|
536
|
-
const nodeScope = await resolveTopicNodeScopeOrNull(
|
|
537
|
-
ctx,
|
|
538
|
-
String(args.topicId)
|
|
539
|
-
);
|
|
540
|
-
if (nodeScope) {
|
|
541
|
-
return nodeScope;
|
|
542
|
-
}
|
|
543
|
-
throw new Error(`Topic not found: ${String(args.topicId)}`);
|
|
544
|
-
}
|
|
545
|
-
const inherited = await resolveInheritedWorkspaceScope(ctx, topic);
|
|
546
|
-
const mapped = asMappedProjectId(topic);
|
|
547
|
-
if (mapped) {
|
|
548
|
-
return {
|
|
549
|
-
topicId: topic._id,
|
|
550
|
-
projectId: mapped,
|
|
551
|
-
tenantId: inherited.tenantId,
|
|
552
|
-
workspaceId: inherited.workspaceId,
|
|
553
|
-
source: "topic"
|
|
554
|
-
};
|
|
555
|
-
}
|
|
556
|
-
return {
|
|
557
|
-
topicId: topic._id,
|
|
558
|
-
tenantId: inherited.tenantId,
|
|
559
|
-
workspaceId: inherited.workspaceId,
|
|
560
|
-
source: "topic"
|
|
561
|
-
};
|
|
564
|
+
return await resolveScopeFromTopicId(ctx, args.topicId);
|
|
562
565
|
}
|
|
563
566
|
if (args.projectId) {
|
|
564
|
-
|
|
565
|
-
try {
|
|
566
|
-
directTopic = await ctx.db.get(
|
|
567
|
-
args.projectId
|
|
568
|
-
);
|
|
569
|
-
} catch (error) {
|
|
570
|
-
debugGraphPrimitiveFallback(
|
|
571
|
-
"[topicScope] Failed to load direct project topic",
|
|
572
|
-
{
|
|
573
|
-
error,
|
|
574
|
-
projectId: args.projectId
|
|
575
|
-
}
|
|
576
|
-
);
|
|
577
|
-
}
|
|
578
|
-
if (directTopic) {
|
|
579
|
-
const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);
|
|
580
|
-
const mapped = asMappedProjectId(directTopic);
|
|
581
|
-
return {
|
|
582
|
-
topicId: directTopic._id,
|
|
583
|
-
projectId: mapped ?? args.projectId,
|
|
584
|
-
tenantId: inherited.tenantId,
|
|
585
|
-
workspaceId: inherited.workspaceId,
|
|
586
|
-
source: "topic_inferred"
|
|
587
|
-
};
|
|
588
|
-
}
|
|
589
|
-
directTopic = await tryResolveHostTopicByLegacyScope(ctx, args.projectId);
|
|
590
|
-
if (directTopic) {
|
|
591
|
-
const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);
|
|
592
|
-
const mapped = asMappedProjectId(directTopic);
|
|
593
|
-
return {
|
|
594
|
-
topicId: directTopic._id,
|
|
595
|
-
projectId: mapped ?? args.projectId,
|
|
596
|
-
tenantId: inherited.tenantId,
|
|
597
|
-
workspaceId: inherited.workspaceId,
|
|
598
|
-
source: "topic_inferred"
|
|
599
|
-
};
|
|
600
|
-
}
|
|
601
|
-
const topics = await findTopicsByScopeAlias(ctx, args.projectId);
|
|
602
|
-
const primary = pickPrimaryTopic(topics);
|
|
603
|
-
if (primary) {
|
|
604
|
-
const inherited = await resolveInheritedWorkspaceScope(ctx, primary);
|
|
605
|
-
return {
|
|
606
|
-
topicId: primary._id,
|
|
607
|
-
projectId: args.projectId,
|
|
608
|
-
tenantId: inherited.tenantId,
|
|
609
|
-
workspaceId: inherited.workspaceId,
|
|
610
|
-
source: "project_mapped_topic"
|
|
611
|
-
};
|
|
612
|
-
}
|
|
613
|
-
const nodeScope = await resolveTopicNodeScopeOrNull(
|
|
614
|
-
ctx,
|
|
615
|
-
String(args.projectId)
|
|
616
|
-
);
|
|
617
|
-
if (nodeScope) {
|
|
618
|
-
return {
|
|
619
|
-
...nodeScope,
|
|
620
|
-
projectId: nodeScope.projectId ?? String(args.projectId)
|
|
621
|
-
};
|
|
622
|
-
}
|
|
623
|
-
throw new Error(
|
|
624
|
-
`Legacy project scope ${String(args.projectId)} has no mapped topic.`
|
|
625
|
-
);
|
|
567
|
+
return await resolveScopeFromLegacyProjectId(ctx, args.projectId);
|
|
626
568
|
}
|
|
627
569
|
throw new Error(
|
|
628
570
|
"Missing scope: provide topicId (preferred) or legacy projectId alias."
|
|
629
571
|
);
|
|
630
572
|
}
|
|
573
|
+
async function resolveScopeFromTopicId(ctx, topicId) {
|
|
574
|
+
const topic = await resolveTopicDocFromTopicId(ctx, topicId);
|
|
575
|
+
if (topic) {
|
|
576
|
+
return await buildTopicScope(ctx, topic, "topic");
|
|
577
|
+
}
|
|
578
|
+
const nodeScope = await resolveTopicNodeScopeOrNull(ctx, String(topicId));
|
|
579
|
+
if (nodeScope) {
|
|
580
|
+
return nodeScope;
|
|
581
|
+
}
|
|
582
|
+
throw new Error(`Topic not found: ${String(topicId)}`);
|
|
583
|
+
}
|
|
584
|
+
async function resolveTopicDocFromTopicId(ctx, topicId) {
|
|
585
|
+
const direct = await tryReadTopicDoc(ctx, topicId, {
|
|
586
|
+
failureLog: "[topicScope] Failed to load topic by direct id",
|
|
587
|
+
idLogKey: "topicId"
|
|
588
|
+
});
|
|
589
|
+
if (direct) {
|
|
590
|
+
return direct;
|
|
591
|
+
}
|
|
592
|
+
const hostTopic = await tryResolveHostTopicById(ctx, String(topicId));
|
|
593
|
+
if (hostTopic) {
|
|
594
|
+
return hostTopic;
|
|
595
|
+
}
|
|
596
|
+
return pickPrimaryTopic(await findTopicsByScopeAlias(ctx, String(topicId))) ?? null;
|
|
597
|
+
}
|
|
598
|
+
async function resolveScopeFromLegacyProjectId(ctx, legacyProjectId) {
|
|
599
|
+
const directTopic = await resolveDirectLegacyProjectTopic(
|
|
600
|
+
ctx,
|
|
601
|
+
legacyProjectId
|
|
602
|
+
);
|
|
603
|
+
if (directTopic) {
|
|
604
|
+
return await buildTopicScope(ctx, directTopic, "topic_inferred", {
|
|
605
|
+
fallbackProjectId: legacyProjectId
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
const primary = pickPrimaryTopic(
|
|
609
|
+
await findTopicsByScopeAlias(ctx, legacyProjectId)
|
|
610
|
+
);
|
|
611
|
+
if (primary) {
|
|
612
|
+
return await buildTopicScope(ctx, primary, "project_mapped_topic", {
|
|
613
|
+
fallbackProjectId: legacyProjectId
|
|
614
|
+
});
|
|
615
|
+
}
|
|
616
|
+
const nodeScope = await resolveTopicNodeScopeOrNull(ctx, legacyProjectId);
|
|
617
|
+
if (nodeScope) {
|
|
618
|
+
return {
|
|
619
|
+
...nodeScope,
|
|
620
|
+
projectId: nodeScope.projectId ?? legacyProjectId
|
|
621
|
+
};
|
|
622
|
+
}
|
|
623
|
+
throw new Error(
|
|
624
|
+
`Legacy project scope ${legacyProjectId} has no mapped topic.`
|
|
625
|
+
);
|
|
626
|
+
}
|
|
627
|
+
async function resolveDirectLegacyProjectTopic(ctx, legacyProjectId) {
|
|
628
|
+
const directTopic = await tryReadTopicDoc(ctx, legacyProjectId, {
|
|
629
|
+
failureLog: "[topicScope] Failed to load direct project topic",
|
|
630
|
+
idLogKey: "projectId"
|
|
631
|
+
});
|
|
632
|
+
return directTopic ?? tryResolveHostTopicByLegacyScope(ctx, legacyProjectId);
|
|
633
|
+
}
|
|
634
|
+
async function tryReadTopicDoc(ctx, id, log) {
|
|
635
|
+
try {
|
|
636
|
+
return await ctx.db.get(id);
|
|
637
|
+
} catch (error) {
|
|
638
|
+
debugGraphPrimitiveFallback(log.failureLog, {
|
|
639
|
+
error,
|
|
640
|
+
[log.idLogKey]: id
|
|
641
|
+
});
|
|
642
|
+
return null;
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
async function buildTopicScope(ctx, topic, source, options = {}) {
|
|
646
|
+
const inherited = await resolveInheritedWorkspaceScope(ctx, topic);
|
|
647
|
+
const mapped = asMappedProjectId(topic);
|
|
648
|
+
return {
|
|
649
|
+
topicId: topic._id,
|
|
650
|
+
...mapped || options.fallbackProjectId ? { projectId: mapped ?? options.fallbackProjectId } : {},
|
|
651
|
+
tenantId: inherited.tenantId,
|
|
652
|
+
workspaceId: inherited.workspaceId,
|
|
653
|
+
source
|
|
654
|
+
};
|
|
655
|
+
}
|
|
631
656
|
var optionalScopeArgs = {
|
|
632
657
|
projectId: v.optional(v.string()),
|
|
633
658
|
topicId: v.optional(v.string())
|
|
@@ -670,7 +695,7 @@ function normalizeSourceType(sourceType) {
|
|
|
670
695
|
async function markProjectGraphDirty(ctx, projectId, topicId) {
|
|
671
696
|
const normalizedProjectId = typeof projectId === "string" && projectId.trim().length > 0 ? projectId : void 0;
|
|
672
697
|
const normalizedTopicId = typeof topicId === "string" && topicId.trim().length > 0 ? topicId : void 0;
|
|
673
|
-
if (!normalizedProjectId
|
|
698
|
+
if (!(normalizedProjectId || normalizedTopicId)) {
|
|
674
699
|
return;
|
|
675
700
|
}
|
|
676
701
|
if (normalizedProjectId) {
|
|
@@ -691,9 +716,15 @@ async function markProjectGraphDirty(ctx, projectId, topicId) {
|
|
|
691
716
|
}
|
|
692
717
|
);
|
|
693
718
|
}
|
|
719
|
+
const activityScopeId = normalizedTopicId ?? normalizedProjectId;
|
|
720
|
+
if (!activityScopeId) {
|
|
721
|
+
throw new Error(
|
|
722
|
+
"Expected evidence graph dirty scope to include a topic or project id."
|
|
723
|
+
);
|
|
724
|
+
}
|
|
694
725
|
await resolveGraphPrimitivesAppResolvers().patchProject(
|
|
695
726
|
ctx,
|
|
696
|
-
|
|
727
|
+
activityScopeId,
|
|
697
728
|
{
|
|
698
729
|
lastActivityAt: Date.now()
|
|
699
730
|
}
|
|
@@ -722,7 +753,15 @@ function dedupeEvidenceNodes(nodes) {
|
|
|
722
753
|
return deduped;
|
|
723
754
|
}
|
|
724
755
|
function evidenceMatchesScope(node, scope) {
|
|
725
|
-
|
|
756
|
+
const record = node && typeof node === "object" && !Array.isArray(node) ? node : null;
|
|
757
|
+
if (!record) {
|
|
758
|
+
return false;
|
|
759
|
+
}
|
|
760
|
+
const nodeTopicId = typeof record.topicId === "string" ? record.topicId : void 0;
|
|
761
|
+
const nodeProjectId = typeof record.projectId === "string" ? record.projectId : void 0;
|
|
762
|
+
const scopeTopicId = scope.topicId === void 0 ? void 0 : String(scope.topicId);
|
|
763
|
+
const scopeProjectId = scope.projectId === void 0 ? void 0 : String(scope.projectId);
|
|
764
|
+
return scopeTopicId !== void 0 && nodeTopicId === scopeTopicId || scopeProjectId !== void 0 && nodeProjectId === scopeProjectId;
|
|
726
765
|
}
|
|
727
766
|
function resolveEvidenceLinkedWorktreeId(metadata) {
|
|
728
767
|
const worktreeId = metadata?.linkedWorktreeId;
|
|
@@ -733,7 +772,7 @@ function resolveEvidenceLinkedWorktreeId(metadata) {
|
|
|
733
772
|
return typeof sprintId === "string" && sprintId.trim().length > 0 ? sprintId : void 0;
|
|
734
773
|
}
|
|
735
774
|
async function resolveEvidenceScopeOrNull(ctx, args) {
|
|
736
|
-
if (!args.projectId
|
|
775
|
+
if (!(args.projectId || args.topicId)) {
|
|
737
776
|
return null;
|
|
738
777
|
}
|
|
739
778
|
try {
|
|
@@ -829,22 +868,19 @@ function formatEvidenceNode(n) {
|
|
|
829
868
|
}
|
|
830
869
|
|
|
831
870
|
// src/embeddingTrigger.ts
|
|
871
|
+
var embeddingActionRef = "embeddingActions:generateEpistemicNodeEmbedding";
|
|
832
872
|
async function scheduleEmbeddingGeneration(args) {
|
|
833
873
|
try {
|
|
834
|
-
await args.ctx.scheduler.runAfter(
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
hasAnswer: args.hasAnswer,
|
|
845
|
-
confidence: args.confidence
|
|
846
|
-
}
|
|
847
|
-
);
|
|
874
|
+
await args.ctx.scheduler.runAfter(0, embeddingActionRef, {
|
|
875
|
+
nodeId: args.nodeId,
|
|
876
|
+
projectId: args.projectId ? String(args.projectId) : void 0,
|
|
877
|
+
topicId: args.topicId ? String(args.topicId) : void 0,
|
|
878
|
+
createdBy: args.createdBy,
|
|
879
|
+
nodeType: args.nodeType,
|
|
880
|
+
text: args.text.slice(0, 2e4),
|
|
881
|
+
hasAnswer: args.hasAnswer,
|
|
882
|
+
confidence: args.confidence
|
|
883
|
+
});
|
|
848
884
|
} catch (error) {
|
|
849
885
|
debugGraphPrimitiveFallback(
|
|
850
886
|
"[embeddingTrigger] Failed to schedule embedding generation",
|
|
@@ -856,6 +892,55 @@ async function scheduleEmbeddingGeneration(args) {
|
|
|
856
892
|
);
|
|
857
893
|
}
|
|
858
894
|
}
|
|
895
|
+
function insertEpistemicNode(ctx, doc) {
|
|
896
|
+
assertUuidV7Identity("epistemicNodes", doc.globalId);
|
|
897
|
+
return ctx.db.insert("epistemicNodes", doc);
|
|
898
|
+
}
|
|
899
|
+
async function assertExistingNodeEndpoint(ctx, endpointRole, endpoint) {
|
|
900
|
+
assertUuidShapedEdgeEndpoint(endpointRole, endpoint);
|
|
901
|
+
const node = await ctx.db.query("epistemicNodes").withIndex(
|
|
902
|
+
"by_globalId",
|
|
903
|
+
(q) => q.eq("globalId", endpoint)
|
|
904
|
+
).first();
|
|
905
|
+
if (!node) {
|
|
906
|
+
throw new Error(
|
|
907
|
+
`edge_endpoint_not_canonical: epistemicEdges insert requires ${endpointRole} to be the globalId of an existing epistemicNodes row, received ${endpoint} (no node with that globalId)`
|
|
908
|
+
);
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
async function insertEpistemicEdge(ctx, doc) {
|
|
912
|
+
assertUuidV7Identity("epistemicEdges", doc.globalId);
|
|
913
|
+
assertStorageEdgeVocabulary(doc.edgeType);
|
|
914
|
+
if (!doc.fromNodeId || typeof doc.fromNodeId !== "string") {
|
|
915
|
+
throw new Error(
|
|
916
|
+
"edge_endpoint_missing: epistemicEdges insert requires a non-empty fromNodeId"
|
|
917
|
+
);
|
|
918
|
+
}
|
|
919
|
+
if (!doc.toNodeId || typeof doc.toNodeId !== "string") {
|
|
920
|
+
throw new Error(
|
|
921
|
+
"edge_endpoint_missing: epistemicEdges insert requires a non-empty toNodeId"
|
|
922
|
+
);
|
|
923
|
+
}
|
|
924
|
+
await assertExistingNodeEndpoint(ctx, "fromNodeId", doc.fromNodeId);
|
|
925
|
+
await assertExistingNodeEndpoint(ctx, "toNodeId", doc.toNodeId);
|
|
926
|
+
if (doc.fromNodeType && doc.toNodeType && doc.edgeType !== "extracted_from") {
|
|
927
|
+
assertEdgePolicyAllowed(
|
|
928
|
+
edgePolicyManifest,
|
|
929
|
+
doc.edgeType,
|
|
930
|
+
{
|
|
931
|
+
kind: "epistemic_node",
|
|
932
|
+
nodeId: doc.fromNodeId,
|
|
933
|
+
nodeType: doc.fromNodeType
|
|
934
|
+
},
|
|
935
|
+
{
|
|
936
|
+
kind: "epistemic_node",
|
|
937
|
+
nodeId: doc.toNodeId,
|
|
938
|
+
nodeType: doc.toNodeType
|
|
939
|
+
}
|
|
940
|
+
);
|
|
941
|
+
}
|
|
942
|
+
return ctx.db.insert("epistemicEdges", doc);
|
|
943
|
+
}
|
|
859
944
|
function normalizeScopeValue2(value) {
|
|
860
945
|
if (typeof value !== "string") {
|
|
861
946
|
return;
|
|
@@ -917,7 +1002,7 @@ function nodeMatchesWorkspaceReasoningScope(node, scope) {
|
|
|
917
1002
|
return scopeWorkspaceId === nodeWorkspaceId;
|
|
918
1003
|
}
|
|
919
1004
|
function resolveRuntimePackMutationContext(args) {
|
|
920
|
-
if (!args.runtimeToolName
|
|
1005
|
+
if (!(args.runtimeToolName || args.runtimePackKey || args.runtimePackInstallScope)) {
|
|
921
1006
|
return;
|
|
922
1007
|
}
|
|
923
1008
|
return {
|
|
@@ -949,54 +1034,118 @@ function assertTenantPackWorkspaceMutationAllowed(args) {
|
|
|
949
1034
|
}
|
|
950
1035
|
});
|
|
951
1036
|
}
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
1037
|
+
|
|
1038
|
+
// src/epistemicEvidenceMutations.ts
|
|
1039
|
+
var EMBEDDING_GENERATION_ACTION = "embeddingActions:generateEpistemicNodeEmbedding";
|
|
1040
|
+
function isRecord(value) {
|
|
1041
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
955
1042
|
}
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
);
|
|
1043
|
+
function metadataRecord(value) {
|
|
1044
|
+
return isRecord(value) ? value : {};
|
|
1045
|
+
}
|
|
1046
|
+
function readOptionalString(value) {
|
|
1047
|
+
if (typeof value !== "string") {
|
|
1048
|
+
return;
|
|
963
1049
|
}
|
|
1050
|
+
const trimmed = value.trim();
|
|
1051
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
964
1052
|
}
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
);
|
|
1053
|
+
function readConvexId(value) {
|
|
1054
|
+
const normalized = readOptionalString(value);
|
|
1055
|
+
return normalized;
|
|
1056
|
+
}
|
|
1057
|
+
function assertBeliefNode(node, errorMessage) {
|
|
1058
|
+
if (!isRecord(node) || node.nodeType !== "belief" || typeof node.globalId !== "string") {
|
|
1059
|
+
throw new Error(errorMessage);
|
|
972
1060
|
}
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
1061
|
+
return node;
|
|
1062
|
+
}
|
|
1063
|
+
function assertEvidenceNode(node, errorMessage) {
|
|
1064
|
+
if (!isRecord(node)) {
|
|
1065
|
+
throw new Error(errorMessage);
|
|
977
1066
|
}
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
1067
|
+
const id = readConvexId(node._id);
|
|
1068
|
+
if (!(id && node.nodeType === "evidence")) {
|
|
1069
|
+
throw new Error(errorMessage);
|
|
1070
|
+
}
|
|
1071
|
+
const evidence = { _id: id, nodeType: "evidence" };
|
|
1072
|
+
const canonicalText = readOptionalString(node.canonicalText);
|
|
1073
|
+
if (canonicalText !== void 0) {
|
|
1074
|
+
evidence.canonicalText = canonicalText;
|
|
1075
|
+
}
|
|
1076
|
+
const createdBy = readOptionalString(node.createdBy);
|
|
1077
|
+
if (createdBy !== void 0) {
|
|
1078
|
+
evidence.createdBy = createdBy;
|
|
1079
|
+
}
|
|
1080
|
+
if ("metadata" in node) {
|
|
1081
|
+
evidence.metadata = node.metadata;
|
|
1082
|
+
}
|
|
1083
|
+
const projectId = readOptionalString(node.projectId);
|
|
1084
|
+
if (projectId !== void 0) {
|
|
1085
|
+
evidence.projectId = projectId;
|
|
1086
|
+
}
|
|
1087
|
+
const status = readOptionalString(node.status);
|
|
1088
|
+
if (status !== void 0) {
|
|
1089
|
+
evidence.status = status;
|
|
1090
|
+
}
|
|
1091
|
+
const topicId = readOptionalString(node.topicId);
|
|
1092
|
+
if (topicId !== void 0) {
|
|
1093
|
+
evidence.topicId = topicId;
|
|
1094
|
+
}
|
|
1095
|
+
return evidence;
|
|
1096
|
+
}
|
|
1097
|
+
function readEvidenceNodeOrNull(node) {
|
|
1098
|
+
if (!isRecord(node) || node.nodeType !== "evidence") {
|
|
1099
|
+
return null;
|
|
1100
|
+
}
|
|
1101
|
+
try {
|
|
1102
|
+
return assertEvidenceNode(node, "Evidence node not found");
|
|
1103
|
+
} catch {
|
|
1104
|
+
return null;
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
function optionalTrimmedString(value) {
|
|
1108
|
+
if (typeof value !== "string") {
|
|
1109
|
+
return;
|
|
1110
|
+
}
|
|
1111
|
+
const trimmed = value.trim();
|
|
1112
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
1113
|
+
}
|
|
1114
|
+
async function resolveEvidenceNodeId(ctx, args) {
|
|
1115
|
+
if (args.nodeId) {
|
|
1116
|
+
return args.nodeId;
|
|
1117
|
+
}
|
|
1118
|
+
const insightId = readOptionalString(args.insightId);
|
|
1119
|
+
if (!insightId) {
|
|
1120
|
+
throw new Error("Either nodeId or insightId is required");
|
|
1121
|
+
}
|
|
1122
|
+
const normalizedId = ctx.db.normalizeId?.("epistemicNodes", insightId) ?? readConvexId(insightId);
|
|
1123
|
+
if (normalizedId) {
|
|
1124
|
+
try {
|
|
1125
|
+
const direct = readEvidenceNodeOrNull(await ctx.db.get(normalizedId));
|
|
1126
|
+
if (direct) {
|
|
1127
|
+
return direct._id;
|
|
993
1128
|
}
|
|
994
|
-
|
|
1129
|
+
} catch {
|
|
1130
|
+
}
|
|
995
1131
|
}
|
|
996
|
-
|
|
1132
|
+
const byGlobalId = readEvidenceNodeOrNull(
|
|
1133
|
+
await ctx.db.query("epistemicNodes").withIndex("by_globalId", (q) => q.eq("globalId", insightId)).first()
|
|
1134
|
+
);
|
|
1135
|
+
if (!byGlobalId) {
|
|
1136
|
+
throw new Error("Evidence node not found");
|
|
1137
|
+
}
|
|
1138
|
+
return byGlobalId._id;
|
|
1139
|
+
}
|
|
1140
|
+
function optionalLiteral(values, value, fieldName) {
|
|
1141
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
1142
|
+
return;
|
|
1143
|
+
}
|
|
1144
|
+
if (values.includes(value)) {
|
|
1145
|
+
return value;
|
|
1146
|
+
}
|
|
1147
|
+
throw new Error(`Evidence ${fieldName} must be one of: ${values.join(", ")}`);
|
|
997
1148
|
}
|
|
998
|
-
|
|
999
|
-
// src/epistemicEvidenceMutations.ts
|
|
1000
1149
|
function assertSignedImpactScore(value, context) {
|
|
1001
1150
|
if (typeof value !== "number" || !Number.isFinite(value) || value === 0 || value < -1 || value > 1) {
|
|
1002
1151
|
throw new Error(`${context} requires explicit nonzero weight in [-1, 1]`);
|
|
@@ -1009,12 +1158,121 @@ function normalizeEvidenceRelation(relation, weight, context) {
|
|
|
1009
1158
|
throw new Error(`${context} supports relation requires positive weight`);
|
|
1010
1159
|
}
|
|
1011
1160
|
if (relation === "contradicts" && weight > 0) {
|
|
1012
|
-
throw new Error(
|
|
1161
|
+
throw new Error(
|
|
1162
|
+
`${context} contradicts relation requires negative weight`
|
|
1163
|
+
);
|
|
1013
1164
|
}
|
|
1014
1165
|
return relation;
|
|
1015
1166
|
}
|
|
1016
1167
|
return weight < 0 ? "contradicts" : "supports";
|
|
1017
1168
|
}
|
|
1169
|
+
function planEvidenceImpact(args, context) {
|
|
1170
|
+
const weight = assertSignedImpactScore(args.weight, context);
|
|
1171
|
+
const signedImpact = args.signedImpact === void 0 ? weight : assertSignedImpactScore(args.signedImpact, `${context} signedImpact`);
|
|
1172
|
+
return {
|
|
1173
|
+
confidence: Math.abs(weight),
|
|
1174
|
+
evidenceRelation: normalizeEvidenceRelation(
|
|
1175
|
+
args.evidenceRelation,
|
|
1176
|
+
weight,
|
|
1177
|
+
context
|
|
1178
|
+
),
|
|
1179
|
+
signedImpact,
|
|
1180
|
+
weight
|
|
1181
|
+
};
|
|
1182
|
+
}
|
|
1183
|
+
function evidenceTaxonomyProjection(args) {
|
|
1184
|
+
const sourceRef = optionalTrimmedString(args.sourceRef);
|
|
1185
|
+
const sourceQuality = optionalLiteral(
|
|
1186
|
+
EVIDENCE_SOURCE_QUALITY_VALUES,
|
|
1187
|
+
args.sourceQuality,
|
|
1188
|
+
"sourceQuality"
|
|
1189
|
+
);
|
|
1190
|
+
const methodology = optionalLiteral(
|
|
1191
|
+
EVIDENCE_METHODOLOGY_VALUES,
|
|
1192
|
+
args.methodology,
|
|
1193
|
+
"methodology"
|
|
1194
|
+
);
|
|
1195
|
+
const informationAsymmetry = optionalLiteral(
|
|
1196
|
+
EVIDENCE_INFORMATION_ASYMMETRY_VALUES,
|
|
1197
|
+
args.informationAsymmetry,
|
|
1198
|
+
"informationAsymmetry"
|
|
1199
|
+
);
|
|
1200
|
+
const sourceDescription = optionalTrimmedString(args.sourceDescription);
|
|
1201
|
+
return {
|
|
1202
|
+
...sourceRef ? { sourceRef } : {},
|
|
1203
|
+
...sourceQuality ? { sourceQuality } : {},
|
|
1204
|
+
...methodology ? { methodology } : {},
|
|
1205
|
+
...informationAsymmetry ? { informationAsymmetry } : {},
|
|
1206
|
+
...sourceDescription ? { sourceDescription } : {}
|
|
1207
|
+
};
|
|
1208
|
+
}
|
|
1209
|
+
function evidenceTextProjection(args) {
|
|
1210
|
+
const title = optionalTrimmedString(args.title);
|
|
1211
|
+
const contentType = optionalTrimmedString(args.contentType);
|
|
1212
|
+
return {
|
|
1213
|
+
...title ? { title } : {},
|
|
1214
|
+
...typeof args.content === "string" && args.content.length > 0 ? { content: args.content } : {},
|
|
1215
|
+
...contentType ? { contentType } : {}
|
|
1216
|
+
};
|
|
1217
|
+
}
|
|
1218
|
+
function evidenceMetadata(args, impact, kind, profile) {
|
|
1219
|
+
const base = {
|
|
1220
|
+
kind,
|
|
1221
|
+
tags: args.tags || [],
|
|
1222
|
+
linkedBeliefNodeId: args.linkedBeliefNodeId,
|
|
1223
|
+
evidenceRelation: impact.evidenceRelation,
|
|
1224
|
+
confidence: impact.confidence,
|
|
1225
|
+
weight: impact.weight,
|
|
1226
|
+
impactScore: impact.weight
|
|
1227
|
+
};
|
|
1228
|
+
const sourceContext = profile === "createAndLink" ? {} : {
|
|
1229
|
+
externalSourceType: args.externalSourceType,
|
|
1230
|
+
sourceUrl: args.sourceUrl,
|
|
1231
|
+
sourceQuestionId: args.sourceQuestionId,
|
|
1232
|
+
rationale: args.rationale
|
|
1233
|
+
};
|
|
1234
|
+
const publicCreateTaxonomy = profile === "create" ? {
|
|
1235
|
+
methodology: args.methodology,
|
|
1236
|
+
informationAsymmetry: args.informationAsymmetry,
|
|
1237
|
+
sourceDescription: args.sourceDescription
|
|
1238
|
+
} : {};
|
|
1239
|
+
return {
|
|
1240
|
+
...base,
|
|
1241
|
+
...sourceContext,
|
|
1242
|
+
...publicCreateTaxonomy,
|
|
1243
|
+
...metadataRecord(args.metadata)
|
|
1244
|
+
};
|
|
1245
|
+
}
|
|
1246
|
+
function buildEvidenceNodeInsert(args) {
|
|
1247
|
+
return {
|
|
1248
|
+
globalId: args.globalId,
|
|
1249
|
+
topicId: args.scope.topicId,
|
|
1250
|
+
projectId: args.scope.projectId,
|
|
1251
|
+
tenantId: args.scope.tenantId,
|
|
1252
|
+
workspaceId: args.scope.workspaceId,
|
|
1253
|
+
nodeType: "evidence",
|
|
1254
|
+
canonicalText: args.write.text,
|
|
1255
|
+
contentHash: generateContentHash(args.write.text),
|
|
1256
|
+
...evidenceTextProjection(args.write),
|
|
1257
|
+
status: "active",
|
|
1258
|
+
epistemicLayer: "L2",
|
|
1259
|
+
sourceType: args.sourceType,
|
|
1260
|
+
// RC.1 taxonomy fields — top-level projection
|
|
1261
|
+
evidenceRelation: args.impact.evidenceRelation,
|
|
1262
|
+
signedImpact: args.impact.signedImpact,
|
|
1263
|
+
targetBeliefId: String(args.linkedBeliefNodeId),
|
|
1264
|
+
...evidenceTaxonomyProjection(args.write),
|
|
1265
|
+
createdAt: args.now,
|
|
1266
|
+
updatedAt: args.now,
|
|
1267
|
+
createdBy: args.write.userId,
|
|
1268
|
+
metadata: evidenceMetadata(
|
|
1269
|
+
args.write,
|
|
1270
|
+
args.impact,
|
|
1271
|
+
args.kind,
|
|
1272
|
+
args.metadataProfile
|
|
1273
|
+
)
|
|
1274
|
+
};
|
|
1275
|
+
}
|
|
1018
1276
|
async function createEvidenceBeliefEdge(ctx, args) {
|
|
1019
1277
|
const edgeGlobalId = generateGlobalId();
|
|
1020
1278
|
const confidence = Math.abs(args.weight);
|
|
@@ -1139,66 +1397,27 @@ var create = mutation({
|
|
|
1139
1397
|
}
|
|
1140
1398
|
const now = Date.now();
|
|
1141
1399
|
const globalId = generateGlobalId();
|
|
1142
|
-
const contentHash = generateContentHash(args.text);
|
|
1143
1400
|
const kind = normalizeKind(args.kind);
|
|
1144
1401
|
const sourceType = normalizeSourceType(args.sourceType);
|
|
1145
|
-
const
|
|
1146
|
-
const
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
weight,
|
|
1150
|
-
"Evidence creation"
|
|
1402
|
+
const impact = planEvidenceImpact(args, "Evidence creation");
|
|
1403
|
+
const linkedBeliefNode = assertBeliefNode(
|
|
1404
|
+
await ctx.db.get(args.linkedBeliefNodeId),
|
|
1405
|
+
"Evidence creation requires a linked belief node"
|
|
1151
1406
|
);
|
|
1152
|
-
const
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
const nodeId = await insertEpistemicNode(ctx, {
|
|
1158
|
-
globalId,
|
|
1159
|
-
topicId: scope.topicId,
|
|
1160
|
-
projectId: scope.projectId,
|
|
1161
|
-
tenantId: scope.tenantId,
|
|
1162
|
-
workspaceId: scope.workspaceId,
|
|
1163
|
-
nodeType: "evidence",
|
|
1164
|
-
canonicalText: args.text,
|
|
1165
|
-
contentHash,
|
|
1166
|
-
...typeof args.title === "string" && args.title.trim().length > 0 ? { title: args.title.trim() } : {},
|
|
1167
|
-
...typeof args.content === "string" && args.content.length > 0 ? { content: args.content } : {},
|
|
1168
|
-
...typeof args.contentType === "string" && args.contentType.trim().length > 0 ? { contentType: args.contentType.trim() } : {},
|
|
1169
|
-
status: "active",
|
|
1170
|
-
epistemicLayer: "L2",
|
|
1171
|
-
sourceType,
|
|
1172
|
-
// RC.1 taxonomy fields — top-level projection
|
|
1173
|
-
evidenceRelation,
|
|
1174
|
-
signedImpact,
|
|
1175
|
-
targetBeliefId: String(args.linkedBeliefNodeId),
|
|
1176
|
-
...typeof args.sourceRef === "string" && args.sourceRef.trim().length > 0 ? { sourceRef: args.sourceRef.trim() } : {},
|
|
1177
|
-
...typeof args.sourceQuality === "string" && args.sourceQuality.length > 0 ? { sourceQuality: args.sourceQuality } : {},
|
|
1178
|
-
...typeof args.methodology === "string" && args.methodology.length > 0 ? { methodology: args.methodology } : {},
|
|
1179
|
-
...typeof args.informationAsymmetry === "string" && args.informationAsymmetry.length > 0 ? { informationAsymmetry: args.informationAsymmetry } : {},
|
|
1180
|
-
...typeof args.sourceDescription === "string" && args.sourceDescription.trim().length > 0 ? { sourceDescription: args.sourceDescription.trim() } : {},
|
|
1181
|
-
createdAt: now,
|
|
1182
|
-
updatedAt: now,
|
|
1183
|
-
createdBy: args.userId,
|
|
1184
|
-
metadata: {
|
|
1407
|
+
const nodeId = await insertEpistemicNode(
|
|
1408
|
+
ctx,
|
|
1409
|
+
buildEvidenceNodeInsert({
|
|
1410
|
+
globalId,
|
|
1411
|
+
impact,
|
|
1185
1412
|
kind,
|
|
1186
|
-
tags: args.tags || [],
|
|
1187
|
-
externalSourceType: args.externalSourceType,
|
|
1188
|
-
sourceUrl: args.sourceUrl,
|
|
1189
|
-
sourceQuestionId: args.sourceQuestionId,
|
|
1190
|
-
rationale: args.rationale,
|
|
1191
1413
|
linkedBeliefNodeId: args.linkedBeliefNodeId,
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
...additionalMetadata
|
|
1200
|
-
}
|
|
1201
|
-
});
|
|
1414
|
+
metadataProfile: "create",
|
|
1415
|
+
now,
|
|
1416
|
+
scope,
|
|
1417
|
+
sourceType,
|
|
1418
|
+
write: args
|
|
1419
|
+
})
|
|
1420
|
+
);
|
|
1202
1421
|
await ctx.scheduler.runAfter(0, internal.neo4jSync.syncNodeToNeo4j, {
|
|
1203
1422
|
nodeId,
|
|
1204
1423
|
operation: "upsert"
|
|
@@ -1216,8 +1435,8 @@ var create = mutation({
|
|
|
1216
1435
|
evidenceGlobalId: globalId,
|
|
1217
1436
|
beliefNodeId: args.linkedBeliefNodeId,
|
|
1218
1437
|
beliefGlobalId: linkedBeliefNode.globalId,
|
|
1219
|
-
relation: evidenceRelation,
|
|
1220
|
-
weight,
|
|
1438
|
+
relation: impact.evidenceRelation,
|
|
1439
|
+
weight: impact.weight,
|
|
1221
1440
|
userId: args.userId,
|
|
1222
1441
|
topicId: scope.topicId ? String(scope.topicId) : void 0,
|
|
1223
1442
|
projectId: scope.projectId ? String(scope.projectId) : void 0,
|
|
@@ -1237,23 +1456,19 @@ var create = mutation({
|
|
|
1237
1456
|
kind,
|
|
1238
1457
|
sourceType,
|
|
1239
1458
|
linkedBeliefNodeId: args.linkedBeliefNodeId,
|
|
1240
|
-
evidenceRelation,
|
|
1241
|
-
weight
|
|
1459
|
+
evidenceRelation: impact.evidenceRelation,
|
|
1460
|
+
weight: impact.weight
|
|
1242
1461
|
}
|
|
1243
1462
|
});
|
|
1244
1463
|
if (scope.projectId || scope.topicId) {
|
|
1245
|
-
await ctx.scheduler.runAfter(
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
nodeType: "evidence",
|
|
1254
|
-
text: args.text
|
|
1255
|
-
}
|
|
1256
|
-
);
|
|
1464
|
+
await ctx.scheduler.runAfter(0, EMBEDDING_GENERATION_ACTION, {
|
|
1465
|
+
nodeId,
|
|
1466
|
+
projectId: scope.projectId,
|
|
1467
|
+
topicId: scope.topicId ? String(scope.topicId) : void 0,
|
|
1468
|
+
createdBy: args.userId,
|
|
1469
|
+
nodeType: "evidence",
|
|
1470
|
+
text: args.text
|
|
1471
|
+
});
|
|
1257
1472
|
}
|
|
1258
1473
|
if (scope.projectId || scope.topicId) {
|
|
1259
1474
|
await ctx.scheduler.runAfter(
|
|
@@ -1267,7 +1482,11 @@ var create = mutation({
|
|
|
1267
1482
|
}
|
|
1268
1483
|
);
|
|
1269
1484
|
}
|
|
1270
|
-
await markProjectGraphDirty(
|
|
1485
|
+
await markProjectGraphDirty(
|
|
1486
|
+
ctx,
|
|
1487
|
+
scope.projectId,
|
|
1488
|
+
scope.topicId ? String(scope.topicId) : void 0
|
|
1489
|
+
);
|
|
1271
1490
|
return { nodeId };
|
|
1272
1491
|
}
|
|
1273
1492
|
});
|
|
@@ -1305,58 +1524,39 @@ var createAndLink = mutation({
|
|
|
1305
1524
|
if (!scope) {
|
|
1306
1525
|
throw new Error("Invalid scope: projectId or topicId is required");
|
|
1307
1526
|
}
|
|
1308
|
-
|
|
1527
|
+
const accessScopeId = scope.projectId ?? (scope.topicId ? String(scope.topicId) : void 0);
|
|
1528
|
+
if (!accessScopeId) {
|
|
1529
|
+
throw new Error("Resolved evidence scope has no access-control id");
|
|
1530
|
+
}
|
|
1531
|
+
await requireScopeWriteAccess(ctx, accessScopeId, args.userId);
|
|
1309
1532
|
const now = Date.now();
|
|
1310
1533
|
const globalId = generateGlobalId();
|
|
1311
|
-
const contentHash = generateContentHash(args.text);
|
|
1312
1534
|
const kind = normalizeKind(args.kind);
|
|
1313
1535
|
const sourceType = normalizeSourceType(args.sourceType);
|
|
1314
|
-
const
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
args.
|
|
1318
|
-
|
|
1319
|
-
|
|
1536
|
+
const write = {
|
|
1537
|
+
...args,
|
|
1538
|
+
evidenceRelation: args.relation,
|
|
1539
|
+
linkedBeliefNodeId: args.beliefNodeId
|
|
1540
|
+
};
|
|
1541
|
+
const impact = planEvidenceImpact(write, "Evidence createAndLink");
|
|
1542
|
+
const beliefNode = assertBeliefNode(
|
|
1543
|
+
await ctx.db.get(args.beliefNodeId),
|
|
1544
|
+
"Belief node not found for edge creation"
|
|
1320
1545
|
);
|
|
1321
|
-
const
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
const nodeId = await insertEpistemicNode(ctx, {
|
|
1327
|
-
globalId,
|
|
1328
|
-
topicId: scope.topicId,
|
|
1329
|
-
projectId: scope.projectId,
|
|
1330
|
-
tenantId: scope.tenantId,
|
|
1331
|
-
workspaceId: scope.workspaceId,
|
|
1332
|
-
nodeType: "evidence",
|
|
1333
|
-
canonicalText: args.text,
|
|
1334
|
-
contentHash,
|
|
1335
|
-
status: "active",
|
|
1336
|
-
epistemicLayer: "L2",
|
|
1337
|
-
sourceType,
|
|
1338
|
-
// RC.1 taxonomy fields — top-level projection
|
|
1339
|
-
evidenceRelation: relation,
|
|
1340
|
-
signedImpact,
|
|
1341
|
-
targetBeliefId: String(args.beliefNodeId),
|
|
1342
|
-
...typeof args.sourceRef === "string" && args.sourceRef.trim().length > 0 ? { sourceRef: args.sourceRef.trim() } : {},
|
|
1343
|
-
...typeof args.sourceQuality === "string" && args.sourceQuality.length > 0 ? { sourceQuality: args.sourceQuality } : {},
|
|
1344
|
-
...typeof args.methodology === "string" && args.methodology.length > 0 ? { methodology: args.methodology } : {},
|
|
1345
|
-
...typeof args.informationAsymmetry === "string" && args.informationAsymmetry.length > 0 ? { informationAsymmetry: args.informationAsymmetry } : {},
|
|
1346
|
-
...typeof args.sourceDescription === "string" && args.sourceDescription.trim().length > 0 ? { sourceDescription: args.sourceDescription.trim() } : {},
|
|
1347
|
-
createdAt: now,
|
|
1348
|
-
updatedAt: now,
|
|
1349
|
-
createdBy: args.userId,
|
|
1350
|
-
metadata: {
|
|
1546
|
+
const nodeId = await insertEpistemicNode(
|
|
1547
|
+
ctx,
|
|
1548
|
+
buildEvidenceNodeInsert({
|
|
1549
|
+
globalId,
|
|
1550
|
+
impact,
|
|
1351
1551
|
kind,
|
|
1352
|
-
tags: args.tags || [],
|
|
1353
1552
|
linkedBeliefNodeId: args.beliefNodeId,
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1553
|
+
metadataProfile: "createAndLink",
|
|
1554
|
+
now,
|
|
1555
|
+
scope,
|
|
1556
|
+
sourceType,
|
|
1557
|
+
write
|
|
1558
|
+
})
|
|
1559
|
+
);
|
|
1360
1560
|
await ctx.scheduler.runAfter(0, internal.neo4jSync.syncNodeToNeo4j, {
|
|
1361
1561
|
nodeId,
|
|
1362
1562
|
operation: "upsert"
|
|
@@ -1365,13 +1565,17 @@ var createAndLink = mutation({
|
|
|
1365
1565
|
evidenceGlobalId: globalId,
|
|
1366
1566
|
beliefNodeId: args.beliefNodeId,
|
|
1367
1567
|
beliefGlobalId: beliefNode.globalId,
|
|
1368
|
-
relation,
|
|
1369
|
-
weight,
|
|
1568
|
+
relation: impact.evidenceRelation,
|
|
1569
|
+
weight: impact.weight,
|
|
1370
1570
|
userId: args.userId,
|
|
1371
1571
|
topicId: scope.topicId ? String(scope.topicId) : void 0,
|
|
1372
1572
|
projectId: scope.projectId ? String(scope.projectId) : void 0
|
|
1373
1573
|
});
|
|
1374
|
-
await markProjectGraphDirty(
|
|
1574
|
+
await markProjectGraphDirty(
|
|
1575
|
+
ctx,
|
|
1576
|
+
scope.projectId,
|
|
1577
|
+
scope.topicId ? String(scope.topicId) : void 0
|
|
1578
|
+
);
|
|
1375
1579
|
return { nodeId, edgeGlobalId };
|
|
1376
1580
|
}
|
|
1377
1581
|
});
|
|
@@ -1387,10 +1591,10 @@ var updateStatus = mutation({
|
|
|
1387
1591
|
},
|
|
1388
1592
|
returns: permissiveReturn,
|
|
1389
1593
|
handler: async (ctx, args) => {
|
|
1390
|
-
const node =
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1594
|
+
const node = assertEvidenceNode(
|
|
1595
|
+
await ctx.db.get(args.nodeId),
|
|
1596
|
+
"Evidence not found"
|
|
1597
|
+
);
|
|
1394
1598
|
const now = Date.now();
|
|
1395
1599
|
await ctx.db.patch(args.nodeId, {
|
|
1396
1600
|
status: args.status,
|
|
@@ -1479,63 +1683,27 @@ var internalCreate = internalMutation({
|
|
|
1479
1683
|
mutationName: "epistemicEvidence.internalCreate"
|
|
1480
1684
|
});
|
|
1481
1685
|
const globalId = generateGlobalId();
|
|
1482
|
-
const contentHash = generateContentHash(args.text);
|
|
1483
1686
|
const kind = normalizeKind(args.kind);
|
|
1484
1687
|
const sourceType = normalizeSourceType(args.sourceType);
|
|
1485
|
-
const
|
|
1486
|
-
const
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
weight,
|
|
1490
|
-
"Internal evidence creation"
|
|
1688
|
+
const impact = planEvidenceImpact(args, "Internal evidence creation");
|
|
1689
|
+
const linkedBeliefNode = assertBeliefNode(
|
|
1690
|
+
await ctx.db.get(args.linkedBeliefNodeId),
|
|
1691
|
+
"Internal evidence creation requires a linked belief node"
|
|
1491
1692
|
);
|
|
1492
|
-
const
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
const nodeId = await insertEpistemicNode(ctx, {
|
|
1498
|
-
globalId,
|
|
1499
|
-
topicId: scope.topicId,
|
|
1500
|
-
projectId: scope.projectId,
|
|
1501
|
-
tenantId: scope.tenantId,
|
|
1502
|
-
workspaceId: scope.workspaceId,
|
|
1503
|
-
nodeType: "evidence",
|
|
1504
|
-
canonicalText: args.text,
|
|
1505
|
-
contentHash,
|
|
1506
|
-
...typeof args.title === "string" && args.title.trim().length > 0 ? { title: args.title.trim() } : {},
|
|
1507
|
-
...typeof args.content === "string" && args.content.length > 0 ? { content: args.content } : {},
|
|
1508
|
-
...typeof args.contentType === "string" && args.contentType.trim().length > 0 ? { contentType: args.contentType.trim() } : {},
|
|
1509
|
-
status: "active",
|
|
1510
|
-
epistemicLayer: "L2",
|
|
1511
|
-
sourceType,
|
|
1512
|
-
// RC.1 taxonomy fields — top-level projection
|
|
1513
|
-
evidenceRelation,
|
|
1514
|
-
signedImpact,
|
|
1515
|
-
targetBeliefId: String(args.linkedBeliefNodeId),
|
|
1516
|
-
...typeof args.sourceRef === "string" && args.sourceRef.trim().length > 0 ? { sourceRef: args.sourceRef.trim() } : {},
|
|
1517
|
-
...typeof args.sourceQuality === "string" && args.sourceQuality.length > 0 ? { sourceQuality: args.sourceQuality } : {},
|
|
1518
|
-
...typeof args.methodology === "string" && args.methodology.length > 0 ? { methodology: args.methodology } : {},
|
|
1519
|
-
...typeof args.informationAsymmetry === "string" && args.informationAsymmetry.length > 0 ? { informationAsymmetry: args.informationAsymmetry } : {},
|
|
1520
|
-
...typeof args.sourceDescription === "string" && args.sourceDescription.trim().length > 0 ? { sourceDescription: args.sourceDescription.trim() } : {},
|
|
1521
|
-
createdAt: now,
|
|
1522
|
-
updatedAt: now,
|
|
1523
|
-
createdBy: args.userId,
|
|
1524
|
-
metadata: {
|
|
1693
|
+
const nodeId = await insertEpistemicNode(
|
|
1694
|
+
ctx,
|
|
1695
|
+
buildEvidenceNodeInsert({
|
|
1696
|
+
globalId,
|
|
1697
|
+
impact,
|
|
1525
1698
|
kind,
|
|
1526
|
-
tags: args.tags || [],
|
|
1527
|
-
externalSourceType: args.externalSourceType,
|
|
1528
|
-
sourceUrl: args.sourceUrl,
|
|
1529
|
-
sourceQuestionId: args.sourceQuestionId,
|
|
1530
|
-
rationale: args.rationale,
|
|
1531
1699
|
linkedBeliefNodeId: args.linkedBeliefNodeId,
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
}
|
|
1538
|
-
|
|
1700
|
+
metadataProfile: "internalCreate",
|
|
1701
|
+
now,
|
|
1702
|
+
scope,
|
|
1703
|
+
sourceType,
|
|
1704
|
+
write: args
|
|
1705
|
+
})
|
|
1706
|
+
);
|
|
1539
1707
|
await ctx.db.insert("epistemicAudit", {
|
|
1540
1708
|
entityType: "evidence",
|
|
1541
1709
|
entityId: String(nodeId),
|
|
@@ -1552,9 +1720,9 @@ var internalCreate = internalMutation({
|
|
|
1552
1720
|
externalSourceType: args.externalSourceType,
|
|
1553
1721
|
sourceUrl: args.sourceUrl,
|
|
1554
1722
|
linkedBeliefNodeId: args.linkedBeliefNodeId,
|
|
1555
|
-
evidenceRelation,
|
|
1556
|
-
confidence:
|
|
1557
|
-
weight
|
|
1723
|
+
evidenceRelation: impact.evidenceRelation,
|
|
1724
|
+
confidence: impact.confidence,
|
|
1725
|
+
weight: impact.weight
|
|
1558
1726
|
},
|
|
1559
1727
|
triggeringAction: "epistemicEvidence.internalCreate"
|
|
1560
1728
|
});
|
|
@@ -1566,28 +1734,28 @@ var internalCreate = internalMutation({
|
|
|
1566
1734
|
evidenceGlobalId: globalId,
|
|
1567
1735
|
beliefNodeId: args.linkedBeliefNodeId,
|
|
1568
1736
|
beliefGlobalId: linkedBeliefNode.globalId,
|
|
1569
|
-
relation: evidenceRelation,
|
|
1570
|
-
weight,
|
|
1737
|
+
relation: impact.evidenceRelation,
|
|
1738
|
+
weight: impact.weight,
|
|
1571
1739
|
userId: args.userId,
|
|
1572
1740
|
topicId: scope.topicId ? String(scope.topicId) : void 0,
|
|
1573
1741
|
projectId: scope.projectId ? String(scope.projectId) : void 0,
|
|
1574
1742
|
rationale: args.rationale
|
|
1575
1743
|
});
|
|
1576
1744
|
if (scope.projectId || scope.topicId) {
|
|
1577
|
-
await ctx.scheduler.runAfter(
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
nodeType: "evidence",
|
|
1586
|
-
text: args.text
|
|
1587
|
-
}
|
|
1588
|
-
);
|
|
1745
|
+
await ctx.scheduler.runAfter(0, EMBEDDING_GENERATION_ACTION, {
|
|
1746
|
+
nodeId,
|
|
1747
|
+
projectId: scope.projectId,
|
|
1748
|
+
topicId: scope.topicId ? String(scope.topicId) : void 0,
|
|
1749
|
+
createdBy: args.userId,
|
|
1750
|
+
nodeType: "evidence",
|
|
1751
|
+
text: args.text
|
|
1752
|
+
});
|
|
1589
1753
|
}
|
|
1590
|
-
await markProjectGraphDirty(
|
|
1754
|
+
await markProjectGraphDirty(
|
|
1755
|
+
ctx,
|
|
1756
|
+
scope.projectId,
|
|
1757
|
+
scope.topicId ? String(scope.topicId) : void 0
|
|
1758
|
+
);
|
|
1591
1759
|
return { nodeId };
|
|
1592
1760
|
}
|
|
1593
1761
|
});
|
|
@@ -1600,11 +1768,11 @@ var updateVerificationStatus = mutation({
|
|
|
1600
1768
|
},
|
|
1601
1769
|
returns: permissiveReturn,
|
|
1602
1770
|
handler: async (ctx, args) => {
|
|
1603
|
-
const node =
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
const metadata = node.metadata
|
|
1771
|
+
const node = assertEvidenceNode(
|
|
1772
|
+
await ctx.db.get(args.nodeId),
|
|
1773
|
+
"Evidence node not found"
|
|
1774
|
+
);
|
|
1775
|
+
const metadata = metadataRecord(node.metadata);
|
|
1608
1776
|
await ctx.db.patch(args.nodeId, {
|
|
1609
1777
|
metadata: {
|
|
1610
1778
|
...metadata,
|
|
@@ -1630,20 +1798,17 @@ var update = mutation({
|
|
|
1630
1798
|
},
|
|
1631
1799
|
returns: permissiveReturn,
|
|
1632
1800
|
handler: async (ctx, args) => {
|
|
1633
|
-
const resolvedId =
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
if (!node || node.nodeType !== "evidence") {
|
|
1639
|
-
throw new Error("Evidence node not found");
|
|
1640
|
-
}
|
|
1801
|
+
const resolvedId = await resolveEvidenceNodeId(ctx, args);
|
|
1802
|
+
const node = assertEvidenceNode(
|
|
1803
|
+
await ctx.db.get(resolvedId),
|
|
1804
|
+
"Evidence node not found"
|
|
1805
|
+
);
|
|
1641
1806
|
if (!node.projectId) {
|
|
1642
1807
|
throw new Error("Evidence has no project scope");
|
|
1643
1808
|
}
|
|
1644
1809
|
await requireScopeWriteAccess(ctx, node.projectId, args.userId);
|
|
1645
1810
|
const now = Date.now();
|
|
1646
|
-
const existingMeta = node.metadata
|
|
1811
|
+
const existingMeta = metadataRecord(node.metadata);
|
|
1647
1812
|
const metaUpdates = { ...existingMeta };
|
|
1648
1813
|
if (args.kind !== void 0) {
|
|
1649
1814
|
metaUpdates.kind = args.kind;
|
|
@@ -1675,17 +1840,13 @@ var update = mutation({
|
|
|
1675
1840
|
newState: { text: (args.text ?? node.canonicalText)?.slice(0, 200) }
|
|
1676
1841
|
});
|
|
1677
1842
|
if (args.text !== void 0) {
|
|
1678
|
-
await ctx.scheduler.runAfter(
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
nodeType: "evidence",
|
|
1686
|
-
text: args.text
|
|
1687
|
-
}
|
|
1688
|
-
);
|
|
1843
|
+
await ctx.scheduler.runAfter(0, EMBEDDING_GENERATION_ACTION, {
|
|
1844
|
+
nodeId: resolvedId,
|
|
1845
|
+
topicId: node.projectId,
|
|
1846
|
+
createdBy: node.createdBy ?? args.userId,
|
|
1847
|
+
nodeType: "evidence",
|
|
1848
|
+
text: args.text
|
|
1849
|
+
});
|
|
1689
1850
|
}
|
|
1690
1851
|
await markProjectGraphDirty(ctx, node.projectId, node.topicId);
|
|
1691
1852
|
return { nodeId: resolvedId };
|
|
@@ -1701,15 +1862,15 @@ var flagAsIncorrect = mutation({
|
|
|
1701
1862
|
returns: permissiveReturn,
|
|
1702
1863
|
handler: async (ctx, args) => {
|
|
1703
1864
|
const now = Date.now();
|
|
1704
|
-
const node =
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1865
|
+
const node = assertEvidenceNode(
|
|
1866
|
+
await ctx.db.get(args.insightId),
|
|
1867
|
+
"Evidence not found in epistemic spine"
|
|
1868
|
+
);
|
|
1708
1869
|
if (!node.projectId) {
|
|
1709
1870
|
throw new Error("Evidence has no project scope");
|
|
1710
1871
|
}
|
|
1711
1872
|
await requireScopeWriteAccess(ctx, node.projectId, args.userId);
|
|
1712
|
-
const existingMeta = node.metadata
|
|
1873
|
+
const existingMeta = metadataRecord(node.metadata);
|
|
1713
1874
|
await ctx.db.patch(node._id, {
|
|
1714
1875
|
verificationStatus: "contradicted",
|
|
1715
1876
|
metadata: {
|
|
@@ -1765,14 +1926,11 @@ var remove = mutation({
|
|
|
1765
1926
|
},
|
|
1766
1927
|
returns: permissiveReturn,
|
|
1767
1928
|
handler: async (ctx, args) => {
|
|
1768
|
-
const resolvedId =
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
if (!node || node.nodeType !== "evidence") {
|
|
1774
|
-
throw new Error("Evidence node not found");
|
|
1775
|
-
}
|
|
1929
|
+
const resolvedId = await resolveEvidenceNodeId(ctx, args);
|
|
1930
|
+
const node = assertEvidenceNode(
|
|
1931
|
+
await ctx.db.get(resolvedId),
|
|
1932
|
+
"Evidence node not found"
|
|
1933
|
+
);
|
|
1776
1934
|
if (node.createdBy !== args.userId) {
|
|
1777
1935
|
throw new Error("Only the creator can archive this evidence");
|
|
1778
1936
|
}
|
|
@@ -1800,6 +1958,224 @@ var remove = mutation({
|
|
|
1800
1958
|
return { nodeId: resolvedId };
|
|
1801
1959
|
}
|
|
1802
1960
|
});
|
|
1961
|
+
function readOptionalString2(value) {
|
|
1962
|
+
return typeof value === "string" && value.trim().length > 0 ? value : void 0;
|
|
1963
|
+
}
|
|
1964
|
+
function readOptionalNumber(value) {
|
|
1965
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
1966
|
+
}
|
|
1967
|
+
function readConvexId2(value) {
|
|
1968
|
+
const normalized = readOptionalString2(value);
|
|
1969
|
+
return normalized;
|
|
1970
|
+
}
|
|
1971
|
+
function readRecord(value) {
|
|
1972
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
1973
|
+
}
|
|
1974
|
+
function readOptionalStringArray(value) {
|
|
1975
|
+
return Array.isArray(value) && value.every((item) => typeof item === "string") ? value : void 0;
|
|
1976
|
+
}
|
|
1977
|
+
function readEvidenceNodeRow(value, fallbackProjectId) {
|
|
1978
|
+
const record = readRecord(value);
|
|
1979
|
+
if (!record) {
|
|
1980
|
+
return null;
|
|
1981
|
+
}
|
|
1982
|
+
const id = readConvexId2(record._id);
|
|
1983
|
+
const canonicalText = readOptionalString2(record.canonicalText);
|
|
1984
|
+
const createdAt = readOptionalNumber(record.createdAt);
|
|
1985
|
+
const createdBy = readOptionalString2(record.createdBy);
|
|
1986
|
+
const nodeType = readOptionalString2(record.nodeType);
|
|
1987
|
+
const sourceType = readOptionalString2(record.sourceType);
|
|
1988
|
+
const status = readOptionalString2(record.status);
|
|
1989
|
+
const updatedAt = readOptionalNumber(record.updatedAt);
|
|
1990
|
+
if (!(id && canonicalText && createdAt !== void 0 && createdBy && nodeType === "evidence" && sourceType && status && updatedAt !== void 0)) {
|
|
1991
|
+
return null;
|
|
1992
|
+
}
|
|
1993
|
+
const metadata = readRecord(record.metadata) ?? void 0;
|
|
1994
|
+
const node = {
|
|
1995
|
+
...record,
|
|
1996
|
+
_id: id,
|
|
1997
|
+
canonicalText,
|
|
1998
|
+
createdAt,
|
|
1999
|
+
createdBy,
|
|
2000
|
+
nodeType: "evidence",
|
|
2001
|
+
sourceType,
|
|
2002
|
+
status,
|
|
2003
|
+
updatedAt
|
|
2004
|
+
};
|
|
2005
|
+
const projectId = readOptionalString2(record.projectId) ?? readOptionalString2(fallbackProjectId);
|
|
2006
|
+
if (projectId !== void 0) {
|
|
2007
|
+
node.projectId = projectId;
|
|
2008
|
+
}
|
|
2009
|
+
const topicId = readOptionalString2(record.topicId);
|
|
2010
|
+
if (topicId !== void 0) {
|
|
2011
|
+
node.topicId = topicId;
|
|
2012
|
+
}
|
|
2013
|
+
const tenantId = readOptionalString2(record.tenantId);
|
|
2014
|
+
if (tenantId !== void 0) {
|
|
2015
|
+
node.tenantId = tenantId;
|
|
2016
|
+
}
|
|
2017
|
+
const workspaceId = readOptionalString2(record.workspaceId);
|
|
2018
|
+
if (workspaceId !== void 0) {
|
|
2019
|
+
node.workspaceId = workspaceId;
|
|
2020
|
+
}
|
|
2021
|
+
const globalId = readOptionalString2(record.globalId);
|
|
2022
|
+
if (globalId !== void 0) {
|
|
2023
|
+
node.globalId = globalId;
|
|
2024
|
+
}
|
|
2025
|
+
const title = readOptionalString2(record.title);
|
|
2026
|
+
if (title !== void 0) {
|
|
2027
|
+
node.title = title;
|
|
2028
|
+
}
|
|
2029
|
+
const audienceLabel = readOptionalString2(record.audienceLabel);
|
|
2030
|
+
if (audienceLabel !== void 0) {
|
|
2031
|
+
node.audienceLabel = audienceLabel;
|
|
2032
|
+
}
|
|
2033
|
+
const epistemicLayer = readOptionalString2(record.epistemicLayer);
|
|
2034
|
+
if (epistemicLayer !== void 0) {
|
|
2035
|
+
node.epistemicLayer = epistemicLayer;
|
|
2036
|
+
}
|
|
2037
|
+
const sensitivityTier = readOptionalString2(record.sensitivityTier);
|
|
2038
|
+
if (sensitivityTier !== void 0) {
|
|
2039
|
+
node.sensitivityTier = sensitivityTier;
|
|
2040
|
+
}
|
|
2041
|
+
const exportClass = readOptionalString2(record.exportClass);
|
|
2042
|
+
if (exportClass !== void 0) {
|
|
2043
|
+
node.exportClass = exportClass;
|
|
2044
|
+
}
|
|
2045
|
+
const policyTags = readOptionalStringArray(record.policyTags);
|
|
2046
|
+
if (policyTags !== void 0) {
|
|
2047
|
+
node.policyTags = policyTags;
|
|
2048
|
+
}
|
|
2049
|
+
if (metadata !== void 0) {
|
|
2050
|
+
node.metadata = metadata;
|
|
2051
|
+
}
|
|
2052
|
+
return node;
|
|
2053
|
+
}
|
|
2054
|
+
function readEvidenceNodeRows(values, fallbackProjectId) {
|
|
2055
|
+
return values.flatMap((value) => {
|
|
2056
|
+
const node = readEvidenceNodeRow(value, fallbackProjectId);
|
|
2057
|
+
return node ? [node] : [];
|
|
2058
|
+
});
|
|
2059
|
+
}
|
|
2060
|
+
function dedupeEvidenceNodeRows(nodes) {
|
|
2061
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2062
|
+
const deduped = [];
|
|
2063
|
+
for (const node of nodes) {
|
|
2064
|
+
const id = String(node._id);
|
|
2065
|
+
if (seen.has(id)) {
|
|
2066
|
+
continue;
|
|
2067
|
+
}
|
|
2068
|
+
seen.add(id);
|
|
2069
|
+
deduped.push(node);
|
|
2070
|
+
}
|
|
2071
|
+
return deduped;
|
|
2072
|
+
}
|
|
2073
|
+
function readEvidenceEdgeRow(value) {
|
|
2074
|
+
const record = readRecord(value);
|
|
2075
|
+
if (!record) {
|
|
2076
|
+
return null;
|
|
2077
|
+
}
|
|
2078
|
+
const id = readConvexId2(record._id);
|
|
2079
|
+
const edgeType = readOptionalString2(record.edgeType);
|
|
2080
|
+
if (!(id && edgeType)) {
|
|
2081
|
+
return null;
|
|
2082
|
+
}
|
|
2083
|
+
const edge = { _id: id, edgeType };
|
|
2084
|
+
const weight = readOptionalNumber(record.weight);
|
|
2085
|
+
if (weight !== void 0) {
|
|
2086
|
+
edge.weight = weight;
|
|
2087
|
+
}
|
|
2088
|
+
for (const field of [
|
|
2089
|
+
"fromNodeId",
|
|
2090
|
+
"toNodeId",
|
|
2091
|
+
"sourceGlobalId",
|
|
2092
|
+
"targetGlobalId",
|
|
2093
|
+
"fromGlobalId",
|
|
2094
|
+
"toGlobalId",
|
|
2095
|
+
"fromLayer",
|
|
2096
|
+
"toLayer",
|
|
2097
|
+
"topicId"
|
|
2098
|
+
]) {
|
|
2099
|
+
const valueForField = readOptionalString2(record[field]);
|
|
2100
|
+
if (valueForField !== void 0) {
|
|
2101
|
+
edge[field] = valueForField;
|
|
2102
|
+
}
|
|
2103
|
+
}
|
|
2104
|
+
return edge;
|
|
2105
|
+
}
|
|
2106
|
+
function readEvidenceEdgeRows(values) {
|
|
2107
|
+
return values.flatMap((value) => {
|
|
2108
|
+
const edge = readEvidenceEdgeRow(value);
|
|
2109
|
+
return edge ? [edge] : [];
|
|
2110
|
+
});
|
|
2111
|
+
}
|
|
2112
|
+
function dedupeEvidenceEdges(edges) {
|
|
2113
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2114
|
+
const deduped = [];
|
|
2115
|
+
for (const edge of edges) {
|
|
2116
|
+
const id = String(edge._id);
|
|
2117
|
+
if (seen.has(id)) {
|
|
2118
|
+
continue;
|
|
2119
|
+
}
|
|
2120
|
+
seen.add(id);
|
|
2121
|
+
deduped.push(edge);
|
|
2122
|
+
}
|
|
2123
|
+
return deduped;
|
|
2124
|
+
}
|
|
2125
|
+
function evidenceSourceRef(edge) {
|
|
2126
|
+
return edge.sourceGlobalId ?? edge.fromGlobalId ?? edge.fromNodeId;
|
|
2127
|
+
}
|
|
2128
|
+
async function resolveEvidenceNodeSoft(ctx, nodeRef) {
|
|
2129
|
+
const normalizedId = ctx.db.normalizeId?.("epistemicNodes", nodeRef) ?? readConvexId2(nodeRef);
|
|
2130
|
+
if (normalizedId) {
|
|
2131
|
+
try {
|
|
2132
|
+
const direct = readEvidenceNodeRow(await ctx.db.get(normalizedId));
|
|
2133
|
+
if (direct) {
|
|
2134
|
+
return direct;
|
|
2135
|
+
}
|
|
2136
|
+
} catch (error) {
|
|
2137
|
+
debugGraphPrimitiveFallback(
|
|
2138
|
+
"[epistemicEvidence] Direct evidence lookup failed",
|
|
2139
|
+
{ error, nodeRef }
|
|
2140
|
+
);
|
|
2141
|
+
}
|
|
2142
|
+
}
|
|
2143
|
+
return readEvidenceNodeRow(
|
|
2144
|
+
await ctx.db.query("epistemicNodes").withIndex("by_globalId", (q) => q.eq("globalId", nodeRef)).first()
|
|
2145
|
+
);
|
|
2146
|
+
}
|
|
2147
|
+
async function collectNodeReferenceIds(ctx, nodeId) {
|
|
2148
|
+
const refs = /* @__PURE__ */ new Set([String(nodeId)]);
|
|
2149
|
+
const node = await ctx.db.get(nodeId);
|
|
2150
|
+
const globalId = readOptionalString2(readRecord(node)?.globalId);
|
|
2151
|
+
if (globalId) {
|
|
2152
|
+
refs.add(globalId);
|
|
2153
|
+
}
|
|
2154
|
+
return [...refs];
|
|
2155
|
+
}
|
|
2156
|
+
async function collectInformsEdgesToNode(ctx, nodeId) {
|
|
2157
|
+
const refs = await collectNodeReferenceIds(ctx, nodeId);
|
|
2158
|
+
const reads = [];
|
|
2159
|
+
for (const ref of refs) {
|
|
2160
|
+
reads.push(
|
|
2161
|
+
ctx.db.query("epistemicEdges").withIndex(
|
|
2162
|
+
"by_to_type",
|
|
2163
|
+
(q) => q.eq("toNodeId", ref).eq("edgeType", "informs")
|
|
2164
|
+
).collect(),
|
|
2165
|
+
ctx.db.query("epistemicEdges").withIndex(
|
|
2166
|
+
"by_target_global_id",
|
|
2167
|
+
(q) => q.eq("targetGlobalId", ref)
|
|
2168
|
+
).collect()
|
|
2169
|
+
);
|
|
2170
|
+
}
|
|
2171
|
+
const edges = readEvidenceEdgeRows((await Promise.all(reads)).flat()).filter(
|
|
2172
|
+
(edge) => edge.edgeType === "informs"
|
|
2173
|
+
);
|
|
2174
|
+
return dedupeEvidenceEdges(edges);
|
|
2175
|
+
}
|
|
2176
|
+
function hasProjectId(node) {
|
|
2177
|
+
return typeof node.projectId === "string" && node.projectId.length > 0;
|
|
2178
|
+
}
|
|
1803
2179
|
var getById = query({
|
|
1804
2180
|
args: {
|
|
1805
2181
|
nodeId: v.optional(v.id("epistemicNodes")),
|
|
@@ -1812,11 +2188,7 @@ var getById = query({
|
|
|
1812
2188
|
if (!id) {
|
|
1813
2189
|
return null;
|
|
1814
2190
|
}
|
|
1815
|
-
|
|
1816
|
-
if (!node || node.nodeType !== "evidence") {
|
|
1817
|
-
return null;
|
|
1818
|
-
}
|
|
1819
|
-
return node;
|
|
2191
|
+
return await resolveEvidenceNodeSoft(ctx, String(id));
|
|
1820
2192
|
}
|
|
1821
2193
|
});
|
|
1822
2194
|
var getByProject = query({
|
|
@@ -1828,7 +2200,7 @@ var getByProject = query({
|
|
|
1828
2200
|
},
|
|
1829
2201
|
returns: permissiveReturn,
|
|
1830
2202
|
handler: async (ctx, args) => {
|
|
1831
|
-
if (!args.projectId
|
|
2203
|
+
if (!(args.projectId || args.topicId)) {
|
|
1832
2204
|
return [];
|
|
1833
2205
|
}
|
|
1834
2206
|
const pageSize = clampEvidenceLimit(args.limit);
|
|
@@ -1864,9 +2236,9 @@ var getByProject = query({
|
|
|
1864
2236
|
"by_topic_type",
|
|
1865
2237
|
(q) => q.eq("topicId", scope.topicId).eq("nodeType", "evidence")
|
|
1866
2238
|
).order("desc").take(scanLimit);
|
|
1867
|
-
const scopedNodes =
|
|
1868
|
-
(
|
|
1869
|
-
);
|
|
2239
|
+
const scopedNodes = dedupeEvidenceNodeRows(
|
|
2240
|
+
readEvidenceNodeRows(topicNodes, scope.projectId)
|
|
2241
|
+
).filter((node) => evidenceMatchesScope(node, scope));
|
|
1870
2242
|
const filteredNodes = args.status ? scopedNodes.filter((node) => node.status === args.status) : scopedNodes;
|
|
1871
2243
|
return filteredNodes.map(flattenEvidenceNode).slice(0, pageSize);
|
|
1872
2244
|
}
|
|
@@ -1889,9 +2261,9 @@ var getByTopic = query({
|
|
|
1889
2261
|
"by_topic_type",
|
|
1890
2262
|
(q) => q.eq("topicId", scope.topicId).eq("nodeType", "evidence")
|
|
1891
2263
|
).order("desc").take(scanLimit);
|
|
1892
|
-
const scopedNodes =
|
|
1893
|
-
(
|
|
1894
|
-
);
|
|
2264
|
+
const scopedNodes = dedupeEvidenceNodeRows(
|
|
2265
|
+
readEvidenceNodeRows(topicNodes, scope.projectId)
|
|
2266
|
+
).filter((node) => evidenceMatchesScope(node, scope));
|
|
1895
2267
|
const filteredNodes = args.status ? scopedNodes.filter((node) => node.status === args.status) : scopedNodes;
|
|
1896
2268
|
return filteredNodes.map(flattenEvidenceNode).slice(0, pageSize);
|
|
1897
2269
|
}
|
|
@@ -1902,20 +2274,29 @@ var getForBelief = query({
|
|
|
1902
2274
|
},
|
|
1903
2275
|
returns: permissiveReturn,
|
|
1904
2276
|
handler: async (ctx, args) => {
|
|
1905
|
-
const edges = await ctx.
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
2277
|
+
const edges = await collectInformsEdgesToNode(ctx, args.beliefNodeId);
|
|
2278
|
+
const evidenceNodeIds = edges.flatMap((edge) => {
|
|
2279
|
+
const sourceRef = evidenceSourceRef(edge);
|
|
2280
|
+
return sourceRef ? [sourceRef] : [];
|
|
2281
|
+
});
|
|
1910
2282
|
const evidenceNodes = await Promise.all(
|
|
1911
|
-
evidenceNodeIds.map((id) => ctx
|
|
2283
|
+
evidenceNodeIds.map((id) => resolveEvidenceNodeSoft(ctx, id))
|
|
1912
2284
|
);
|
|
1913
|
-
return evidenceNodes.
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
2285
|
+
return evidenceNodes.flatMap((e, i) => {
|
|
2286
|
+
const edge = edges[i];
|
|
2287
|
+
if (!(e && edge)) {
|
|
2288
|
+
return [];
|
|
2289
|
+
}
|
|
2290
|
+
const weight = edge.weight ?? 0;
|
|
2291
|
+
return [
|
|
2292
|
+
{
|
|
2293
|
+
...e,
|
|
2294
|
+
relation: weight >= 0 ? "supports" : "contradicts",
|
|
2295
|
+
confidence: Math.abs(weight),
|
|
2296
|
+
edgeId: edge._id
|
|
2297
|
+
}
|
|
2298
|
+
];
|
|
2299
|
+
});
|
|
1919
2300
|
}
|
|
1920
2301
|
});
|
|
1921
2302
|
var internalGetByProject = internalQuery({
|
|
@@ -1934,21 +2315,30 @@ var internalGetByProject = internalQuery({
|
|
|
1934
2315
|
return [];
|
|
1935
2316
|
}
|
|
1936
2317
|
const audienceMode = args.audienceMode ?? "internal";
|
|
2318
|
+
const projectScopeId = scope.topicId ? String(scope.topicId) : scope.projectId;
|
|
2319
|
+
if (!projectScopeId) {
|
|
2320
|
+
return [];
|
|
2321
|
+
}
|
|
1937
2322
|
const project = await resolveGraphPrimitivesAppResolvers().getProject(
|
|
1938
2323
|
ctx,
|
|
1939
|
-
|
|
2324
|
+
projectScopeId
|
|
1940
2325
|
);
|
|
2326
|
+
const tenantId = project?.tenantId;
|
|
2327
|
+
const workspaceId = project?.workspaceId;
|
|
1941
2328
|
const registryRows = await listAudienceRegistryRows(ctx, {
|
|
1942
|
-
tenantId
|
|
1943
|
-
workspaceId
|
|
2329
|
+
tenantId,
|
|
2330
|
+
workspaceId
|
|
1944
2331
|
});
|
|
1945
2332
|
const resolveAudienceClass = createEvidenceAudienceResolver(registryRows);
|
|
1946
2333
|
const viewerClass = resolveAudienceClass(audienceMode, "public");
|
|
1947
|
-
const nodes =
|
|
2334
|
+
const nodes = readEvidenceNodeRows(
|
|
2335
|
+
await getEvidenceNodesForScope(ctx, scope, { scanLimit }),
|
|
2336
|
+
scope.projectId
|
|
2337
|
+
);
|
|
1948
2338
|
const workspaceScopedNodes = nodes.filter(
|
|
1949
2339
|
(node) => nodeMatchesWorkspaceReasoningScope(node, {
|
|
1950
|
-
tenantId
|
|
1951
|
-
workspaceId
|
|
2340
|
+
tenantId,
|
|
2341
|
+
workspaceId
|
|
1952
2342
|
})
|
|
1953
2343
|
);
|
|
1954
2344
|
return workspaceScopedNodes.filter(
|
|
@@ -2007,7 +2397,10 @@ var internalGetByTopic = internalQuery({
|
|
|
2007
2397
|
"by_topic_type",
|
|
2008
2398
|
(q) => q.eq("topicId", args.topicId).eq("nodeType", "evidence")
|
|
2009
2399
|
).order("desc").take(scanLimit);
|
|
2010
|
-
const workspaceScopedNodes =
|
|
2400
|
+
const workspaceScopedNodes = readEvidenceNodeRows(
|
|
2401
|
+
nodes,
|
|
2402
|
+
scope.projectId
|
|
2403
|
+
).filter(
|
|
2011
2404
|
(node) => nodeMatchesWorkspaceReasoningScope(node, {
|
|
2012
2405
|
tenantId: scope.tenantId,
|
|
2013
2406
|
workspaceId: scope.workspaceId
|
|
@@ -2058,13 +2451,16 @@ var getByProjectSystem = query({
|
|
|
2058
2451
|
if (!scope) {
|
|
2059
2452
|
return [];
|
|
2060
2453
|
}
|
|
2061
|
-
const nodes =
|
|
2454
|
+
const nodes = readEvidenceNodeRows(
|
|
2455
|
+
await getEvidenceNodesForScope(ctx, scope, { scanLimit }),
|
|
2456
|
+
scope.projectId
|
|
2457
|
+
);
|
|
2062
2458
|
const filtered = args.kind ? nodes.filter((n) => {
|
|
2063
2459
|
const meta = n.metadata || {};
|
|
2064
2460
|
return meta.kind === args.kind;
|
|
2065
2461
|
}) : nodes;
|
|
2066
2462
|
filtered.sort((a, b) => b.createdAt - a.createdAt);
|
|
2067
|
-
return filtered.slice(0, pageSize).map((n) => formatEvidenceNode(n));
|
|
2463
|
+
return filtered.filter(hasProjectId).slice(0, pageSize).map((n) => formatEvidenceNode(n));
|
|
2068
2464
|
}
|
|
2069
2465
|
});
|
|
2070
2466
|
var getEvidenceBalance = query({
|
|
@@ -2078,16 +2474,21 @@ var getEvidenceBalance = query({
|
|
|
2078
2474
|
topicId: args.topicId,
|
|
2079
2475
|
projectId: args.projectId
|
|
2080
2476
|
});
|
|
2081
|
-
const
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
);
|
|
2477
|
+
const scopeId = scope.topicId ? String(scope.topicId) : scope.projectId;
|
|
2478
|
+
if (!scopeId) {
|
|
2479
|
+
return { supporting: 0, challenging: 0, total: 0 };
|
|
2480
|
+
}
|
|
2481
|
+
const hasAccess = await checkScopeAccess(ctx, scopeId, args.userId);
|
|
2086
2482
|
if (!hasAccess) {
|
|
2087
2483
|
return { supporting: 0, challenging: 0, total: 0 };
|
|
2088
2484
|
}
|
|
2089
2485
|
const resolvedTopicId = scope.topicId || scope.projectId;
|
|
2090
|
-
const edges = resolvedTopicId ?
|
|
2486
|
+
const edges = resolvedTopicId ? readEvidenceEdgeRows(
|
|
2487
|
+
await ctx.db.query("epistemicEdges").withIndex(
|
|
2488
|
+
"by_topic",
|
|
2489
|
+
(q) => q.eq("topicId", resolvedTopicId)
|
|
2490
|
+
).collect()
|
|
2491
|
+
) : [];
|
|
2091
2492
|
const evidenceEdges = edges.filter(
|
|
2092
2493
|
(e) => e.edgeType === "informs" && e.fromLayer === "L2" && e.toLayer === "L3"
|
|
2093
2494
|
);
|