@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,23 +1,138 @@
|
|
|
1
|
-
import { v } from 'convex/values';
|
|
2
1
|
import { canAudienceClassAccess, normalizeAudienceKey, classFromAudienceKey } from '@lucern/access-control/audience';
|
|
3
2
|
import { listAudienceRegistryRows } from '@lucern/access-control/audienceRegistry';
|
|
4
3
|
import { assertSchemaEnumValue } from '@lucern/contracts/schema-helpers/enumValidation';
|
|
5
4
|
import { permissiveReturn } from '@lucern/contracts/schema-helpers/validators';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import
|
|
5
|
+
import { v } from 'convex/values';
|
|
6
|
+
import { unsafeConvexAnyApi } from '@lucern/contracts/convex/unsafeAnyApi';
|
|
7
|
+
import { componentsGeneric, internalQueryGeneric, internalMutationGeneric } from 'convex/server';
|
|
8
|
+
import '@lucern/access-control/auth';
|
|
10
9
|
import { throwStructuredMutationError } from '@lucern/access-control/structuredMutationError';
|
|
11
10
|
import { normalizeTupleContradictionPolicy, confidenceFromSL } from '@lucern/confidence';
|
|
12
|
-
import '@lucern/
|
|
11
|
+
import { isNodeType, getLayerForNodeType } from '@lucern/contracts/schema-helpers/spine/tables/epistemicNodes';
|
|
12
|
+
import { assertEdgePolicyAllowed, edgePolicyManifest } from '@lucern/contracts';
|
|
13
|
+
import { generateGlobalId, assertUuidV7Identity, generateUuidV7, assertStorageEdgeVocabulary, assertUuidShapedEdgeEndpoint } from '@lucern/contracts/ids';
|
|
13
14
|
|
|
14
15
|
// src/epistemicBeliefs.internal.ts
|
|
15
|
-
var
|
|
16
|
+
var unsafeApi = unsafeConvexAnyApi(
|
|
17
|
+
"graph-primitives top-level module bundle lacks a committed Convex _generated/api surface"
|
|
18
|
+
);
|
|
19
|
+
var api = unsafeApi;
|
|
16
20
|
componentsGeneric();
|
|
17
|
-
var internal =
|
|
21
|
+
var internal = unsafeApi;
|
|
18
22
|
var internalMutation = internalMutationGeneric;
|
|
19
23
|
var internalQuery = internalQueryGeneric;
|
|
20
24
|
|
|
25
|
+
// src/beliefLifecycle.ts
|
|
26
|
+
var BELIEF_STATUS_VALUES = [
|
|
27
|
+
"assumption",
|
|
28
|
+
"hypothesis",
|
|
29
|
+
"active",
|
|
30
|
+
"superseded",
|
|
31
|
+
"resolved_true",
|
|
32
|
+
"resolved_false"
|
|
33
|
+
];
|
|
34
|
+
function isBeliefLifecycleStatus(value) {
|
|
35
|
+
return typeof value === "string" && BELIEF_STATUS_VALUES.includes(value);
|
|
36
|
+
}
|
|
37
|
+
function normalizeLegacyBeliefStatus(value) {
|
|
38
|
+
if (isBeliefLifecycleStatus(value)) {
|
|
39
|
+
return value;
|
|
40
|
+
}
|
|
41
|
+
if (value === "belief" || value === "established" || value === "emerging") {
|
|
42
|
+
return "active";
|
|
43
|
+
}
|
|
44
|
+
if (value === "fact" || value === "confirmed") {
|
|
45
|
+
return "resolved_true";
|
|
46
|
+
}
|
|
47
|
+
if (value === "disconfirmed" || value === "expired") {
|
|
48
|
+
return "resolved_false";
|
|
49
|
+
}
|
|
50
|
+
if (value === "deprecated") {
|
|
51
|
+
return "superseded";
|
|
52
|
+
}
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
function normalizeBeliefConfidence(confidence) {
|
|
56
|
+
if (typeof confidence !== "number" || !Number.isFinite(confidence)) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
if (confidence >= 0 && confidence <= 1) {
|
|
60
|
+
return confidence;
|
|
61
|
+
}
|
|
62
|
+
if (confidence > 1 && confidence <= 100) {
|
|
63
|
+
return confidence / 100;
|
|
64
|
+
}
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
function isResolvedByConfidence(confidence) {
|
|
68
|
+
const normalized = normalizeBeliefConfidence(confidence);
|
|
69
|
+
if (normalized === null) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
return normalized <= 0 || normalized >= 1;
|
|
73
|
+
}
|
|
74
|
+
function getPredictionMetaFromMetadata(metadata) {
|
|
75
|
+
return metadata?.predictionMeta;
|
|
76
|
+
}
|
|
77
|
+
function resolvedPredictionStatus(predictionMeta) {
|
|
78
|
+
if (!predictionMeta || typeof predictionMeta !== "object") {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
const outcome = predictionMeta.outcome;
|
|
82
|
+
if (outcome === "confirmed") {
|
|
83
|
+
return "resolved_true";
|
|
84
|
+
}
|
|
85
|
+
if (outcome === "disconfirmed" || outcome === "expired") {
|
|
86
|
+
return "resolved_false";
|
|
87
|
+
}
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
function shouldTreatBeliefAsResolved(opts) {
|
|
91
|
+
if (isResolvedByConfidence(opts.confidence)) {
|
|
92
|
+
const normalized = normalizeBeliefConfidence(opts.confidence);
|
|
93
|
+
return normalized === 0 ? "resolved_false" : "resolved_true";
|
|
94
|
+
}
|
|
95
|
+
const directPredictionStatus = resolvedPredictionStatus(opts.predictionMeta);
|
|
96
|
+
if (directPredictionStatus) {
|
|
97
|
+
return directPredictionStatus;
|
|
98
|
+
}
|
|
99
|
+
const metadataPredictionStatus = resolvedPredictionStatus(
|
|
100
|
+
getPredictionMetaFromMetadata(opts.metadata)
|
|
101
|
+
);
|
|
102
|
+
if (metadataPredictionStatus) {
|
|
103
|
+
return metadataPredictionStatus;
|
|
104
|
+
}
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
function resolveBeliefLifecycleStatus(opts) {
|
|
108
|
+
const resolvedStatus = shouldTreatBeliefAsResolved(opts);
|
|
109
|
+
if (resolvedStatus) {
|
|
110
|
+
return resolvedStatus;
|
|
111
|
+
}
|
|
112
|
+
const direct = opts.beliefStatus;
|
|
113
|
+
const normalizedDirect = normalizeLegacyBeliefStatus(direct);
|
|
114
|
+
if (normalizedDirect) {
|
|
115
|
+
const normalized = normalizeBeliefConfidence(opts.confidence);
|
|
116
|
+
if (normalized !== null && isPreValidationBeliefStatus(normalizedDirect)) {
|
|
117
|
+
return "active";
|
|
118
|
+
}
|
|
119
|
+
return normalizedDirect;
|
|
120
|
+
}
|
|
121
|
+
const metaStatus = opts.metadata?.beliefStatus;
|
|
122
|
+
const normalizedMetaStatus = normalizeLegacyBeliefStatus(metaStatus);
|
|
123
|
+
if (normalizedMetaStatus) {
|
|
124
|
+
const normalized = normalizeBeliefConfidence(opts.confidence);
|
|
125
|
+
if (normalized !== null && isPreValidationBeliefStatus(normalizedMetaStatus)) {
|
|
126
|
+
return "active";
|
|
127
|
+
}
|
|
128
|
+
return normalizedMetaStatus;
|
|
129
|
+
}
|
|
130
|
+
return "assumption";
|
|
131
|
+
}
|
|
132
|
+
function isPreValidationBeliefStatus(status) {
|
|
133
|
+
return status === "assumption" || status === "hypothesis";
|
|
134
|
+
}
|
|
135
|
+
|
|
21
136
|
// src/debug.ts
|
|
22
137
|
function isGraphPrimitiveDebugEnabled() {
|
|
23
138
|
const env = globalThis.process?.env;
|
|
@@ -30,980 +145,844 @@ function debugGraphPrimitiveFallback(message, context) {
|
|
|
30
145
|
console.debug(message, context ?? {});
|
|
31
146
|
}
|
|
32
147
|
|
|
33
|
-
// src/
|
|
148
|
+
// src/topicProjectOverlay.ts
|
|
34
149
|
var LEGACY_SCOPE_FIELD = "graphScopeProjectId";
|
|
35
|
-
|
|
36
|
-
if (
|
|
37
|
-
return
|
|
38
|
-
}
|
|
39
|
-
let node = null;
|
|
40
|
-
try {
|
|
41
|
-
const byGlobalId = await ctx.db.query("epistemicNodes").withIndex("by_globalId", (q) => q.eq("globalId", ref)).first();
|
|
42
|
-
if (byGlobalId && byGlobalId.nodeType === "topic") {
|
|
43
|
-
node = byGlobalId;
|
|
44
|
-
}
|
|
45
|
-
} catch (error) {
|
|
46
|
-
debugGraphPrimitiveFallback(
|
|
47
|
-
"[topicScope] topic-node scope lookup by globalId failed",
|
|
48
|
-
{ error, ref }
|
|
49
|
-
);
|
|
50
|
-
}
|
|
51
|
-
if (!node) {
|
|
52
|
-
return null;
|
|
150
|
+
function readNonEmptyString(value) {
|
|
151
|
+
if (typeof value !== "string") {
|
|
152
|
+
return;
|
|
53
153
|
}
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
154
|
+
const normalized = value.trim();
|
|
155
|
+
return normalized.length > 0 ? normalized : void 0;
|
|
156
|
+
}
|
|
157
|
+
function readStringArray(value) {
|
|
158
|
+
if (!Array.isArray(value)) {
|
|
159
|
+
return [];
|
|
57
160
|
}
|
|
58
|
-
return
|
|
59
|
-
topicId: scopeKey,
|
|
60
|
-
projectId: asMappedProjectId(node),
|
|
61
|
-
source: "topic_node"
|
|
62
|
-
};
|
|
161
|
+
return value.map((entry) => readNonEmptyString(entry)).filter((entry) => Boolean(entry));
|
|
63
162
|
}
|
|
64
|
-
function
|
|
65
|
-
|
|
163
|
+
function readMetadata(topic) {
|
|
164
|
+
return topic.metadata && typeof topic.metadata === "object" ? topic.metadata : {};
|
|
165
|
+
}
|
|
166
|
+
function omitMetadataKey(metadata, key) {
|
|
167
|
+
const { [key]: _omitted, ...rest } = metadata;
|
|
168
|
+
return rest;
|
|
169
|
+
}
|
|
170
|
+
function readLegacyProjectId(value) {
|
|
171
|
+
if (!value) {
|
|
66
172
|
return;
|
|
67
173
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
174
|
+
return readNonEmptyString(value[LEGACY_SCOPE_FIELD]);
|
|
175
|
+
}
|
|
176
|
+
function coerceVisibility(value) {
|
|
177
|
+
return value === "private" || value === "team" || value === "firm" || value === "external" || value === "public" ? value : void 0;
|
|
178
|
+
}
|
|
179
|
+
function coerceStatus(value) {
|
|
180
|
+
return value === "active" || value === "archived" || value === "watching" ? value : void 0;
|
|
181
|
+
}
|
|
182
|
+
function mapProjectType(topic, metadata) {
|
|
183
|
+
const explicit = readNonEmptyString(metadata.projectType);
|
|
184
|
+
if (explicit) {
|
|
185
|
+
return explicit;
|
|
71
186
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
187
|
+
if (topic.type === "theme") {
|
|
188
|
+
return "thematic";
|
|
189
|
+
}
|
|
190
|
+
return readNonEmptyString(topic.type) || "general";
|
|
75
191
|
}
|
|
76
|
-
function
|
|
77
|
-
|
|
78
|
-
|
|
192
|
+
function isProjectLikeTopic(topic) {
|
|
193
|
+
const metadata = readMetadata(topic);
|
|
194
|
+
return topic.type === "theme" || topic.type === "thematic" || topic.type === "deal" || topic.type === "monitoring" || readLegacyProjectId(topic) !== void 0 || readNonEmptyString(metadata.projectType) !== void 0;
|
|
195
|
+
}
|
|
196
|
+
function isMissingLucernChildComponentError(error) {
|
|
197
|
+
const message = getErrorMessage(error);
|
|
198
|
+
return message.includes(
|
|
199
|
+
'Child component ComponentName(Identifier("lucern")) not found'
|
|
200
|
+
) || message.includes("Child component") && message.includes("lucern") && message.includes("not found");
|
|
201
|
+
}
|
|
202
|
+
function getErrorMessage(error) {
|
|
203
|
+
if (error instanceof Error) {
|
|
204
|
+
return error.message;
|
|
79
205
|
}
|
|
80
|
-
|
|
81
|
-
|
|
206
|
+
if (typeof error === "object" && error !== null && "message" in error && typeof error.message === "string") {
|
|
207
|
+
return error.message;
|
|
208
|
+
}
|
|
209
|
+
return "unknown error";
|
|
82
210
|
}
|
|
83
|
-
function
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
211
|
+
async function resolveTopicDoc(ctx, scopeId) {
|
|
212
|
+
if (ctx?.db && typeof ctx.db.get === "function") {
|
|
213
|
+
try {
|
|
214
|
+
const directTopic = await ctx.db.get(
|
|
215
|
+
scopeId
|
|
216
|
+
);
|
|
217
|
+
if (directTopic) {
|
|
218
|
+
return directTopic;
|
|
219
|
+
}
|
|
220
|
+
} catch (error) {
|
|
221
|
+
debugGraphPrimitiveFallback(
|
|
222
|
+
"[topicProjectOverlay] Failed to resolve topic by direct ID",
|
|
223
|
+
{
|
|
224
|
+
error,
|
|
225
|
+
scopeId
|
|
226
|
+
}
|
|
227
|
+
);
|
|
94
228
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
229
|
+
}
|
|
230
|
+
if (typeof ctx.runQuery !== "function") {
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
99
233
|
try {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
234
|
+
const topic = await ctx.runQuery(api.topics.get, {
|
|
235
|
+
id: String(scopeId)
|
|
236
|
+
});
|
|
237
|
+
if (topic?.name !== void 0 && topic?.type !== void 0) {
|
|
238
|
+
return topic;
|
|
239
|
+
}
|
|
104
240
|
} catch (error) {
|
|
105
241
|
debugGraphPrimitiveFallback(
|
|
106
|
-
"[
|
|
242
|
+
"[topicProjectOverlay] Failed to resolve topic by ID query",
|
|
107
243
|
{
|
|
108
244
|
error,
|
|
109
245
|
scopeId
|
|
110
246
|
}
|
|
111
247
|
);
|
|
112
|
-
const topics = await ctx.db.query("topics").collect();
|
|
113
|
-
return topics.filter((topic) => {
|
|
114
|
-
const normalizedGlobalId = normalizeScopeValue(topic.globalId);
|
|
115
|
-
const mappedProjectId = asMappedProjectId(topic);
|
|
116
|
-
return String(topic._id) === scopeId || normalizedGlobalId === scopeId || mappedProjectId === scopeId;
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
async function tryResolveHostTopicById(ctx, topicId) {
|
|
121
|
-
if (typeof ctx.runQuery !== "function") {
|
|
122
|
-
return null;
|
|
123
248
|
}
|
|
124
249
|
try {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
}) ?? null;
|
|
128
|
-
} catch (error) {
|
|
129
|
-
debugGraphPrimitiveFallback(
|
|
130
|
-
"[topicScope] Failed to resolve topic by host query",
|
|
250
|
+
const topic = await ctx.runQuery(
|
|
251
|
+
api.topics.getByLegacyScopeId,
|
|
131
252
|
{
|
|
132
|
-
|
|
133
|
-
topicId
|
|
253
|
+
projectId: String(scopeId)
|
|
134
254
|
}
|
|
135
255
|
);
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
139
|
-
async function tryResolveHostTopicByLegacyScope(ctx, legacyScopeId) {
|
|
140
|
-
if (typeof ctx.runQuery !== "function") {
|
|
141
|
-
return null;
|
|
142
|
-
}
|
|
143
|
-
try {
|
|
144
|
-
return await ctx.runQuery(api.topics.getByLegacyScopeId, {
|
|
145
|
-
projectId: legacyScopeId
|
|
146
|
-
}) ?? null;
|
|
256
|
+
if (topic?.name !== void 0 && topic?.type !== void 0) {
|
|
257
|
+
return topic;
|
|
258
|
+
}
|
|
147
259
|
} catch (error) {
|
|
148
260
|
debugGraphPrimitiveFallback(
|
|
149
|
-
"[
|
|
150
|
-
{
|
|
151
|
-
error,
|
|
152
|
-
legacyScopeId
|
|
153
|
-
}
|
|
261
|
+
"[topicProjectOverlay] Failed to resolve topic by legacy scope ID",
|
|
262
|
+
{ error, scopeId }
|
|
154
263
|
);
|
|
155
|
-
return null;
|
|
156
264
|
}
|
|
265
|
+
return null;
|
|
157
266
|
}
|
|
158
|
-
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
267
|
+
function materializeTopicProjectOverlay(topic, idMode = "legacy") {
|
|
268
|
+
const metadata = readMetadata(topic);
|
|
269
|
+
const topicId = String(topic._id);
|
|
270
|
+
const legacyProjectId = readLegacyProjectId(topic) || readLegacyProjectId(metadata) || readNonEmptyString(metadata.legacyProjectId);
|
|
271
|
+
const storageProjectId = legacyProjectId || topicId;
|
|
272
|
+
const outwardId = idMode === "topic" ? topicId : storageProjectId;
|
|
273
|
+
const visibility = coerceVisibility(topic.visibility) || coerceVisibility(metadata.visibility) || "private";
|
|
274
|
+
const status = coerceStatus(topic.status) || coerceStatus(metadata.status) || "active";
|
|
275
|
+
let createdAt = 0;
|
|
276
|
+
if (typeof topic.createdAt === "number") {
|
|
277
|
+
createdAt = topic.createdAt;
|
|
278
|
+
} else if (typeof topic._creationTime === "number") {
|
|
279
|
+
createdAt = topic._creationTime;
|
|
280
|
+
}
|
|
281
|
+
let updatedAt = createdAt;
|
|
282
|
+
if (typeof topic.updatedAt === "number") {
|
|
283
|
+
updatedAt = topic.updatedAt;
|
|
284
|
+
} else if (typeof metadata.updatedAt === "number") {
|
|
285
|
+
updatedAt = metadata.updatedAt;
|
|
164
286
|
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
287
|
+
return {
|
|
288
|
+
...metadata,
|
|
289
|
+
_id: outwardId,
|
|
290
|
+
projectId: outwardId,
|
|
291
|
+
topicId,
|
|
292
|
+
storageProjectId,
|
|
293
|
+
legacyProjectId,
|
|
294
|
+
name: readNonEmptyString(topic.name) || "Untitled Theme",
|
|
295
|
+
type: mapProjectType(topic, metadata),
|
|
296
|
+
description: readNonEmptyString(topic.description),
|
|
297
|
+
ownerId: readNonEmptyString(metadata.ownerId) || readNonEmptyString(topic.createdBy) || "system",
|
|
298
|
+
// FR.7 creator-grant: surface the principal-shaped owner field (column-first,
|
|
299
|
+
// metadata fallback for legacy rows that recorded it in metadata).
|
|
300
|
+
ownerPrincipalId: readNonEmptyString(topic.ownerPrincipalId) || readNonEmptyString(metadata.ownerPrincipalId),
|
|
301
|
+
// RR.1 carrier: preserve the nested metadata carrier so the kernel's
|
|
302
|
+
// `checkProjectAccessDetailed` metadata-PRIMARY read
|
|
303
|
+
// (`project.metadata?.ownerPrincipalId`) resolves the grant. The `...metadata`
|
|
304
|
+
// spread above only flattens keys; it does not leave a nested `metadata`.
|
|
305
|
+
metadata,
|
|
306
|
+
sharedWith: readStringArray(metadata.sharedWith),
|
|
307
|
+
visibility,
|
|
308
|
+
tenantId: readNonEmptyString(topic.tenantId) || readNonEmptyString(metadata.tenantId),
|
|
309
|
+
workspaceId: readNonEmptyString(topic.workspaceId) || readNonEmptyString(metadata.workspaceId),
|
|
310
|
+
status,
|
|
311
|
+
tags: readStringArray(metadata.tags),
|
|
312
|
+
chatCount: typeof metadata.chatCount === "number" ? metadata.chatCount : 0,
|
|
313
|
+
artifactCount: typeof metadata.artifactCount === "number" ? metadata.artifactCount : 0,
|
|
314
|
+
lastActivityAt: typeof metadata.lastActivityAt === "number" ? metadata.lastActivityAt : updatedAt,
|
|
315
|
+
_creationTime: typeof topic._creationTime === "number" ? topic._creationTime : createdAt,
|
|
316
|
+
createdAt,
|
|
317
|
+
updatedAt
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
async function resolveTopicProjectOverlay(ctx, scopeId, options = {}) {
|
|
321
|
+
const topic = await resolveTopicDoc(ctx, scopeId);
|
|
322
|
+
if (!topic) {
|
|
323
|
+
return null;
|
|
176
324
|
}
|
|
177
|
-
|
|
325
|
+
if (options.projectLikeOnly !== false && !isProjectLikeTopic(topic)) {
|
|
326
|
+
return null;
|
|
327
|
+
}
|
|
328
|
+
return materializeTopicProjectOverlay(topic, options.idMode);
|
|
178
329
|
}
|
|
179
|
-
async function
|
|
180
|
-
|
|
181
|
-
|
|
330
|
+
async function listTopicProjectOverlays(ctx, options = {}) {
|
|
331
|
+
let allTopics = [];
|
|
332
|
+
if (ctx?.db?.query && typeof ctx.db.query === "function") {
|
|
182
333
|
try {
|
|
183
|
-
|
|
184
|
-
args.topicId
|
|
185
|
-
);
|
|
334
|
+
allTopics = await ctx.db.query("topics").collect();
|
|
186
335
|
} catch (error) {
|
|
187
336
|
debugGraphPrimitiveFallback(
|
|
188
|
-
"[
|
|
189
|
-
{
|
|
190
|
-
error,
|
|
191
|
-
topicId: args.topicId
|
|
192
|
-
}
|
|
337
|
+
"[topicProjectOverlay] Failed to read topics table; falling back to API",
|
|
338
|
+
{ error }
|
|
193
339
|
);
|
|
340
|
+
allTopics = [];
|
|
194
341
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
342
|
+
}
|
|
343
|
+
if (allTopics.length === 0 && typeof ctx.runQuery === "function") {
|
|
344
|
+
allTopics = (await ctx.runQuery(api.topics.list, {}) ?? []) || [];
|
|
345
|
+
}
|
|
346
|
+
return allTopics.filter(
|
|
347
|
+
(topic) => options.projectLikeOnly === false || isProjectLikeTopic(topic)
|
|
348
|
+
).map((topic) => materializeTopicProjectOverlay(topic, options.idMode));
|
|
349
|
+
}
|
|
350
|
+
async function patchTopicProjectOverlay(ctx, scopeId, value) {
|
|
351
|
+
const topic = await resolveTopicDoc(ctx, scopeId);
|
|
352
|
+
if (!topic) {
|
|
353
|
+
return null;
|
|
354
|
+
}
|
|
355
|
+
const plan = buildTopicProjectOverlayPatchPlan(topic, value);
|
|
356
|
+
await applyTopicProjectOverlayPatch(ctx, topic, plan);
|
|
357
|
+
return materializeTopicProjectOverlay({
|
|
358
|
+
...topic,
|
|
359
|
+
...plan.patch,
|
|
360
|
+
metadata: plan.nextMetadata
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
function buildTopicProjectOverlayPatchPlan(topic, value) {
|
|
364
|
+
const plan = {
|
|
365
|
+
nextMetadata: { ...readMetadata(topic) },
|
|
366
|
+
patch: {},
|
|
367
|
+
topicUpdateArgs: {
|
|
368
|
+
id: String(topic._id)
|
|
202
369
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
370
|
+
};
|
|
371
|
+
for (const [key, rawValue] of Object.entries(value)) {
|
|
372
|
+
applyTopicProjectOverlayPatchEntry(plan, key, rawValue);
|
|
373
|
+
}
|
|
374
|
+
plan.patch.updatedAt = Date.now();
|
|
375
|
+
plan.patch.metadata = plan.nextMetadata;
|
|
376
|
+
plan.topicUpdateArgs.metadata = plan.nextMetadata;
|
|
377
|
+
return plan;
|
|
378
|
+
}
|
|
379
|
+
function applyTopicProjectOverlayPatchEntry(plan, key, rawValue) {
|
|
380
|
+
switch (key) {
|
|
381
|
+
case "_id":
|
|
382
|
+
case "projectId":
|
|
383
|
+
case "topicId":
|
|
384
|
+
case "legacyProjectId":
|
|
385
|
+
case "storageProjectId":
|
|
386
|
+
case "updatedAt":
|
|
387
|
+
case "createdAt":
|
|
388
|
+
return;
|
|
389
|
+
case "name":
|
|
390
|
+
case "description":
|
|
391
|
+
plan.patch[key] = rawValue;
|
|
392
|
+
plan.topicUpdateArgs[key] = rawValue;
|
|
393
|
+
return;
|
|
394
|
+
case "tenantId":
|
|
395
|
+
case "workspaceId":
|
|
396
|
+
case "ownerId":
|
|
397
|
+
throw new Error(
|
|
398
|
+
`patchTopicProjectOverlay cannot mutate ${key} via component-owned topics`
|
|
207
399
|
);
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
return
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
400
|
+
case "status":
|
|
401
|
+
applyTopicStatusPatch(plan, rawValue);
|
|
402
|
+
return;
|
|
403
|
+
case "visibility":
|
|
404
|
+
applyTopicVisibilityPatch(plan, rawValue);
|
|
405
|
+
return;
|
|
406
|
+
case "type":
|
|
407
|
+
applyTopicProjectTypePatch(plan, rawValue);
|
|
408
|
+
return;
|
|
409
|
+
default:
|
|
410
|
+
applyTopicMetadataPatch(plan, key, rawValue);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
function applyTopicStatusPatch(plan, rawValue) {
|
|
414
|
+
const status = coerceStatus(rawValue);
|
|
415
|
+
if (status) {
|
|
416
|
+
plan.patch.status = status;
|
|
417
|
+
plan.topicUpdateArgs.status = status;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
function applyTopicVisibilityPatch(plan, rawValue) {
|
|
421
|
+
const visibility = coerceVisibility(rawValue);
|
|
422
|
+
if (visibility) {
|
|
423
|
+
plan.patch.visibility = visibility;
|
|
424
|
+
plan.topicUpdateArgs.visibility = visibility;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
function applyTopicProjectTypePatch(plan, rawValue) {
|
|
428
|
+
const projectType = readNonEmptyString(rawValue);
|
|
429
|
+
if (projectType) {
|
|
430
|
+
plan.nextMetadata.projectType = projectType;
|
|
431
|
+
return;
|
|
230
432
|
}
|
|
231
|
-
|
|
232
|
-
|
|
433
|
+
plan.nextMetadata = omitMetadataKey(plan.nextMetadata, "projectType");
|
|
434
|
+
}
|
|
435
|
+
function applyTopicMetadataPatch(plan, key, rawValue) {
|
|
436
|
+
if (rawValue === void 0) {
|
|
437
|
+
plan.nextMetadata = omitMetadataKey(plan.nextMetadata, key);
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
plan.nextMetadata[key] = rawValue;
|
|
441
|
+
}
|
|
442
|
+
async function applyTopicProjectOverlayPatch(ctx, topic, plan) {
|
|
443
|
+
if (typeof ctx.runMutation === "function") {
|
|
233
444
|
try {
|
|
234
|
-
|
|
235
|
-
args.projectId
|
|
236
|
-
);
|
|
445
|
+
await ctx.runMutation(api.topics.update, plan.topicUpdateArgs);
|
|
237
446
|
} catch (error) {
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
projectId: args.projectId
|
|
243
|
-
}
|
|
244
|
-
);
|
|
245
|
-
}
|
|
246
|
-
if (directTopic) {
|
|
247
|
-
const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);
|
|
248
|
-
const mapped = asMappedProjectId(directTopic);
|
|
249
|
-
return {
|
|
250
|
-
topicId: directTopic._id,
|
|
251
|
-
projectId: mapped ?? args.projectId,
|
|
252
|
-
tenantId: inherited.tenantId,
|
|
253
|
-
workspaceId: inherited.workspaceId,
|
|
254
|
-
source: "topic_inferred"
|
|
255
|
-
};
|
|
256
|
-
}
|
|
257
|
-
directTopic = await tryResolveHostTopicByLegacyScope(ctx, args.projectId);
|
|
258
|
-
if (directTopic) {
|
|
259
|
-
const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);
|
|
260
|
-
const mapped = asMappedProjectId(directTopic);
|
|
261
|
-
return {
|
|
262
|
-
topicId: directTopic._id,
|
|
263
|
-
projectId: mapped ?? args.projectId,
|
|
264
|
-
tenantId: inherited.tenantId,
|
|
265
|
-
workspaceId: inherited.workspaceId,
|
|
266
|
-
source: "topic_inferred"
|
|
267
|
-
};
|
|
268
|
-
}
|
|
269
|
-
const topics = await findTopicsByScopeAlias(ctx, args.projectId);
|
|
270
|
-
const primary = pickPrimaryTopic(topics);
|
|
271
|
-
if (primary) {
|
|
272
|
-
const inherited = await resolveInheritedWorkspaceScope(ctx, primary);
|
|
273
|
-
return {
|
|
274
|
-
topicId: primary._id,
|
|
275
|
-
projectId: args.projectId,
|
|
276
|
-
tenantId: inherited.tenantId,
|
|
277
|
-
workspaceId: inherited.workspaceId,
|
|
278
|
-
source: "project_mapped_topic"
|
|
279
|
-
};
|
|
280
|
-
}
|
|
281
|
-
const nodeScope = await resolveTopicNodeScopeOrNull(
|
|
282
|
-
ctx,
|
|
283
|
-
String(args.projectId)
|
|
284
|
-
);
|
|
285
|
-
if (nodeScope) {
|
|
286
|
-
return {
|
|
287
|
-
...nodeScope,
|
|
288
|
-
projectId: nodeScope.projectId ?? String(args.projectId)
|
|
289
|
-
};
|
|
447
|
+
if (!canPatchTopicViaLocalDb(ctx, error)) {
|
|
448
|
+
throw error;
|
|
449
|
+
}
|
|
450
|
+
await ctx.db.patch(topic._id, plan.patch);
|
|
290
451
|
}
|
|
452
|
+
} else if (ctx?.db && typeof ctx.db.patch === "function") {
|
|
453
|
+
await ctx.db.patch(topic._id, plan.patch);
|
|
454
|
+
} else {
|
|
291
455
|
throw new Error(
|
|
292
|
-
|
|
456
|
+
"Cannot patch topic without component adapter (ctx.runMutation unavailable)"
|
|
293
457
|
);
|
|
294
458
|
}
|
|
295
|
-
throw new Error(
|
|
296
|
-
"Missing scope: provide topicId (preferred) or legacy projectId alias."
|
|
297
|
-
);
|
|
298
459
|
}
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
topicId: v.optional(v.string())
|
|
302
|
-
};
|
|
303
|
-
async function insertEpistemicNode(ctx, doc) {
|
|
304
|
-
assertUuidV7Identity("epistemicNodes", doc.globalId);
|
|
305
|
-
return ctx.db.insert("epistemicNodes", doc);
|
|
460
|
+
function canPatchTopicViaLocalDb(ctx, error) {
|
|
461
|
+
return isMissingLucernChildComponentError(error) && Boolean(ctx?.db) && typeof ctx.db?.patch === "function";
|
|
306
462
|
}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
}
|
|
463
|
+
|
|
464
|
+
// src/resolvers.ts
|
|
465
|
+
function isMissingLucernChildComponentError2(error) {
|
|
466
|
+
const message = getErrorMessage2(error);
|
|
467
|
+
return message.includes(
|
|
468
|
+
'Child component ComponentName(Identifier("lucern")) not found'
|
|
469
|
+
) || message.includes("Child component") && message.includes("lucern") && message.includes("not found");
|
|
315
470
|
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
if (!doc.fromNodeId || typeof doc.fromNodeId !== "string") {
|
|
320
|
-
throw new Error(
|
|
321
|
-
"edge_endpoint_missing: epistemicEdges insert requires a non-empty fromNodeId"
|
|
322
|
-
);
|
|
471
|
+
function getErrorMessage2(error) {
|
|
472
|
+
if (error instanceof Error) {
|
|
473
|
+
return error.message;
|
|
323
474
|
}
|
|
324
|
-
if (
|
|
325
|
-
|
|
326
|
-
"edge_endpoint_missing: epistemicEdges insert requires a non-empty toNodeId"
|
|
327
|
-
);
|
|
475
|
+
if (typeof error === "object" && error !== null && "message" in error && typeof error.message === "string") {
|
|
476
|
+
return error.message;
|
|
328
477
|
}
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
478
|
+
return "unknown error";
|
|
479
|
+
}
|
|
480
|
+
function isAdvisoryTopicPatch(value) {
|
|
481
|
+
const advisoryKeys = /* @__PURE__ */ new Set(["lastActivityAt", "updatedAt"]);
|
|
482
|
+
const keys = Object.keys(value);
|
|
483
|
+
return keys.length > 0 && keys.every((key) => advisoryKeys.has(key));
|
|
484
|
+
}
|
|
485
|
+
async function patchProjectWithTolerance(ctx, projectId, value) {
|
|
486
|
+
try {
|
|
487
|
+
await patchTopicProjectOverlay(ctx, projectId, value);
|
|
488
|
+
} catch (error) {
|
|
489
|
+
if (!(isAdvisoryTopicPatch(value) && isMissingLucernChildComponentError2(error))) {
|
|
490
|
+
throw error;
|
|
491
|
+
}
|
|
492
|
+
console.warn(
|
|
493
|
+
"[lucern graph-primitives] Non-fatal advisory topic patch failure",
|
|
340
494
|
{
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
495
|
+
projectId,
|
|
496
|
+
keys: Object.keys(value),
|
|
497
|
+
error: getErrorMessage2(error)
|
|
344
498
|
}
|
|
345
499
|
);
|
|
346
500
|
}
|
|
347
|
-
return ctx.db.insert("epistemicEdges", doc);
|
|
348
501
|
}
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
502
|
+
function defaultResolvers() {
|
|
503
|
+
return {
|
|
504
|
+
getProject: (ctx, projectId) => resolveTopicProjectOverlay(ctx, projectId, {
|
|
505
|
+
idMode: "legacy",
|
|
506
|
+
projectLikeOnly: false
|
|
507
|
+
}),
|
|
508
|
+
patchProject: (ctx, projectId, value) => patchProjectWithTolerance(ctx, projectId, value),
|
|
509
|
+
listTopics: (ctx) => listTopicProjectOverlays(ctx, {
|
|
510
|
+
idMode: "legacy"
|
|
511
|
+
}),
|
|
512
|
+
getFinalArtifact: (ctx, artifactId) => ctx.db.get(artifactId)
|
|
513
|
+
};
|
|
353
514
|
}
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
if (!normalized) {
|
|
357
|
-
return [];
|
|
358
|
-
}
|
|
359
|
-
const candidates = [normalized];
|
|
360
|
-
if (normalized.startsWith("top_")) {
|
|
361
|
-
candidates.push(normalized.slice(4));
|
|
362
|
-
}
|
|
363
|
-
return [...new Set(candidates)];
|
|
364
|
-
}
|
|
365
|
-
function readTopicNodeRef(args) {
|
|
366
|
-
return cleanString(args.topicGlobalId) ?? cleanString(args.topicNodeId) ?? cleanString(args.topicId);
|
|
367
|
-
}
|
|
368
|
-
async function resolveRequiredTopicAnchor(ctx, topicRef) {
|
|
369
|
-
for (const candidate of topicNodeCandidates(topicRef)) {
|
|
370
|
-
try {
|
|
371
|
-
const direct = await ctx.db.get(candidate);
|
|
372
|
-
if (direct?.nodeType === "topic" && cleanString(direct.globalId)) {
|
|
373
|
-
return direct;
|
|
374
|
-
}
|
|
375
|
-
} catch (_) {
|
|
376
|
-
}
|
|
377
|
-
const byGlobalId = await ctx.db.query("epistemicNodes").withIndex("by_globalId", (q) => q.eq("globalId", candidate)).first();
|
|
378
|
-
if (byGlobalId?.nodeType === "topic" && cleanString(byGlobalId.globalId)) {
|
|
379
|
-
return byGlobalId;
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
throw new Error(
|
|
383
|
-
"Belief creation requires topicGlobalId or topicNodeId for a topic node in epistemicNodes. Legacy topics-table IDs are not valid belief anchors."
|
|
384
|
-
);
|
|
385
|
-
}
|
|
386
|
-
function scopeFromTopicAnchor(topicNode) {
|
|
515
|
+
var resolverOverrides = {};
|
|
516
|
+
function resolveGraphPrimitivesAppResolvers(_ctx) {
|
|
387
517
|
return {
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
tenantId: cleanString(topicNode.tenantId),
|
|
391
|
-
workspaceId: cleanString(topicNode.workspaceId),
|
|
392
|
-
source: "topic"
|
|
518
|
+
...defaultResolvers(),
|
|
519
|
+
...resolverOverrides
|
|
393
520
|
};
|
|
394
521
|
}
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
"by_from_to",
|
|
400
|
-
(q) => q.eq("fromNodeId", args.beliefGlobalId).eq("toNodeId", topicGlobalId)
|
|
401
|
-
).collect();
|
|
402
|
-
const existing = existingEdges.find((edge) => edge.edgeType === "belongs_to");
|
|
403
|
-
const edgeGlobalId = cleanString(existing?.globalId) ?? generateUuidV7();
|
|
404
|
-
if (!existing) {
|
|
405
|
-
await insertEpistemicEdge(ctx, {
|
|
406
|
-
globalId: edgeGlobalId,
|
|
407
|
-
fromNodeId: args.beliefGlobalId,
|
|
408
|
-
toNodeId: topicGlobalId,
|
|
409
|
-
sourceGlobalId: args.beliefGlobalId,
|
|
410
|
-
targetGlobalId: topicGlobalId,
|
|
411
|
-
edgeType: "belongs_to",
|
|
412
|
-
weight: 1,
|
|
413
|
-
confidence: 1,
|
|
414
|
-
context: "Belief creation topic anchor invariant.",
|
|
415
|
-
reasoningMethod: "implicit",
|
|
416
|
-
derivationType: "topic_scope_invariant",
|
|
417
|
-
metadata: {
|
|
418
|
-
invariant: "belief.topic_edge_required",
|
|
419
|
-
edgeUuid: edgeGlobalId,
|
|
420
|
-
fromUuid: args.beliefGlobalId,
|
|
421
|
-
toUuid: topicGlobalId
|
|
422
|
-
},
|
|
423
|
-
createdBy: args.createdBy,
|
|
424
|
-
createdAt: now,
|
|
425
|
-
updatedAt: now,
|
|
426
|
-
projectId: cleanString(args.topicNode.projectId),
|
|
427
|
-
topicId: topicGlobalId,
|
|
428
|
-
tenantId: cleanString(args.topicNode.tenantId),
|
|
429
|
-
workspaceId: cleanString(args.topicNode.workspaceId),
|
|
430
|
-
fromNodeType: "belief",
|
|
431
|
-
toNodeType: "topic",
|
|
432
|
-
fromLayer: "L3",
|
|
433
|
-
toLayer: args.topicNode.epistemicLayer ?? "ontological"
|
|
434
|
-
});
|
|
522
|
+
var LEGACY_SCOPE_FIELD2 = "graphScopeProjectId";
|
|
523
|
+
async function resolveTopicNodeScopeOrNull(ctx, ref) {
|
|
524
|
+
if (!ctx?.db || typeof ctx.db.query !== "function") {
|
|
525
|
+
return null;
|
|
435
526
|
}
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
weight: 1,
|
|
442
|
-
confidence: 1,
|
|
443
|
-
context: "Belief creation topic anchor invariant.",
|
|
444
|
-
projectId: cleanString(args.topicNode.projectId),
|
|
445
|
-
topicId: topicGlobalId,
|
|
446
|
-
createdBy: args.createdBy,
|
|
447
|
-
fromNodeType: "belief",
|
|
448
|
-
toNodeType: "topic",
|
|
449
|
-
fromLayer: "L3",
|
|
450
|
-
toLayer: args.topicNode.epistemicLayer ?? "ontological",
|
|
451
|
-
metadata: {
|
|
452
|
-
invariant: "belief.topic_edge_required",
|
|
453
|
-
edgeUuid: edgeGlobalId,
|
|
454
|
-
fromUuid: args.beliefGlobalId,
|
|
455
|
-
toUuid: topicGlobalId
|
|
527
|
+
let node = null;
|
|
528
|
+
try {
|
|
529
|
+
const byGlobalId = await ctx.db.query("epistemicNodes").withIndex("by_globalId", (q) => q.eq("globalId", ref)).first();
|
|
530
|
+
if (byGlobalId && byGlobalId.nodeType === "topic") {
|
|
531
|
+
node = byGlobalId;
|
|
456
532
|
}
|
|
457
|
-
})
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
}
|
|
463
|
-
const normalized = value.trim();
|
|
464
|
-
return normalized.length > 0 ? normalized : void 0;
|
|
465
|
-
}
|
|
466
|
-
function throwWorkspaceIsolationError(args) {
|
|
467
|
-
const error = new Error(args.message);
|
|
468
|
-
error.status = 409;
|
|
469
|
-
error.code = "INVARIANT_VIOLATION";
|
|
470
|
-
error.invariantCode = args.invariantCode;
|
|
471
|
-
error.suggestion = args.suggestion;
|
|
472
|
-
error.details = args.details;
|
|
473
|
-
throw error;
|
|
474
|
-
}
|
|
475
|
-
function assertWorkspaceScopedEpistemicNodeScope(args) {
|
|
476
|
-
const layer = isNodeType(args.nodeType) ? getLayerForNodeType(args.nodeType) : void 0;
|
|
477
|
-
if (layer === "ontological") {
|
|
478
|
-
return;
|
|
479
|
-
}
|
|
480
|
-
const workspaceId = normalizeScopeValue2(args.scope.workspaceId);
|
|
481
|
-
if (workspaceId) {
|
|
482
|
-
return;
|
|
533
|
+
} catch (error) {
|
|
534
|
+
debugGraphPrimitiveFallback(
|
|
535
|
+
"[topicScope] topic-node scope lookup by globalId failed",
|
|
536
|
+
{ error, ref }
|
|
537
|
+
);
|
|
483
538
|
}
|
|
484
|
-
throwWorkspaceIsolationError({
|
|
485
|
-
message: "Workspace-scoped reasoning isolation requires workspaceId on non-ontological node creation.",
|
|
486
|
-
invariantCode: "workspace.scope_required_for_epistemic_nodes",
|
|
487
|
-
suggestion: "Resolve the topic/project scope through a workspace-bound topic before creating epistemic nodes.",
|
|
488
|
-
details: {
|
|
489
|
-
mutationName: args.mutationName,
|
|
490
|
-
nodeType: args.nodeType,
|
|
491
|
-
topicId: args.scope.topicId,
|
|
492
|
-
projectId: args.scope.projectId
|
|
493
|
-
}
|
|
494
|
-
});
|
|
495
|
-
}
|
|
496
|
-
function nodeMatchesWorkspaceReasoningScope(node, scope) {
|
|
497
539
|
if (!node) {
|
|
498
|
-
return
|
|
499
|
-
}
|
|
500
|
-
const scopeTenantId = normalizeScopeValue2(scope.tenantId);
|
|
501
|
-
const scopeWorkspaceId = normalizeScopeValue2(scope.workspaceId);
|
|
502
|
-
const nodeTenantId = normalizeScopeValue2(node.tenantId);
|
|
503
|
-
const nodeWorkspaceId = normalizeScopeValue2(node.workspaceId);
|
|
504
|
-
const epistemicLayer = typeof node.epistemicLayer === "string" ? node.epistemicLayer : void 0;
|
|
505
|
-
if (scopeTenantId && nodeTenantId && scopeTenantId !== nodeTenantId) {
|
|
506
|
-
return false;
|
|
507
|
-
}
|
|
508
|
-
if (epistemicLayer === "ontological" && nodeWorkspaceId === void 0) {
|
|
509
|
-
return true;
|
|
510
|
-
}
|
|
511
|
-
if (!scopeWorkspaceId && node.publicationStatus === "published") {
|
|
512
|
-
return true;
|
|
513
|
-
}
|
|
514
|
-
if (!scopeWorkspaceId) {
|
|
515
|
-
return nodeWorkspaceId === void 0;
|
|
540
|
+
return null;
|
|
516
541
|
}
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
if (!args.runtimeToolName && !args.runtimePackKey && !args.runtimePackInstallScope) {
|
|
521
|
-
return;
|
|
542
|
+
const scopeKey = normalizeScopeValue(node.topicId) ?? normalizeScopeValue(node.globalId);
|
|
543
|
+
if (!scopeKey) {
|
|
544
|
+
return null;
|
|
522
545
|
}
|
|
523
546
|
return {
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
547
|
+
topicId: scopeKey,
|
|
548
|
+
projectId: asMappedProjectId(node),
|
|
549
|
+
source: "topic_node"
|
|
527
550
|
};
|
|
528
551
|
}
|
|
529
|
-
function
|
|
530
|
-
if (!
|
|
552
|
+
function asMappedProjectId(topic) {
|
|
553
|
+
if (!topic) {
|
|
531
554
|
return;
|
|
532
555
|
}
|
|
533
|
-
const
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
556
|
+
const directLegacyProjectId = normalizeScopeValue(
|
|
557
|
+
topic[LEGACY_SCOPE_FIELD2]
|
|
558
|
+
);
|
|
559
|
+
if (directLegacyProjectId) {
|
|
560
|
+
return directLegacyProjectId;
|
|
537
561
|
}
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
suggestion: "Use a workspace-scoped pack for workspace-local graph mutations, or route the change through tenant-global canonical entity flows.",
|
|
542
|
-
details: {
|
|
543
|
-
mutationName: args.mutationName,
|
|
544
|
-
toolName: args.runtime.toolName,
|
|
545
|
-
packKey: args.runtime.packKey,
|
|
546
|
-
targetWorkspaceId,
|
|
547
|
-
targetNodeType: args.target.nodeType,
|
|
548
|
-
targetLayer
|
|
549
|
-
}
|
|
550
|
-
});
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
// src/beliefLifecycle.ts
|
|
554
|
-
var BELIEF_STATUS_VALUES = [
|
|
555
|
-
"assumption",
|
|
556
|
-
"hypothesis",
|
|
557
|
-
"active",
|
|
558
|
-
"superseded",
|
|
559
|
-
"resolved_true",
|
|
560
|
-
"resolved_false"
|
|
561
|
-
];
|
|
562
|
-
function isBeliefLifecycleStatus(value) {
|
|
563
|
-
return typeof value === "string" && BELIEF_STATUS_VALUES.includes(value);
|
|
562
|
+
const metadata = topic.metadata || {};
|
|
563
|
+
const candidate = metadata[LEGACY_SCOPE_FIELD2] || metadata.legacyProjectId || metadata.projectId || metadata.scopeProjectId;
|
|
564
|
+
return typeof candidate === "string" ? normalizeScopeValue(candidate) : void 0;
|
|
564
565
|
}
|
|
565
|
-
function
|
|
566
|
-
if (
|
|
567
|
-
return
|
|
568
|
-
}
|
|
569
|
-
if (value === "belief" || value === "established" || value === "emerging") {
|
|
570
|
-
return "active";
|
|
571
|
-
}
|
|
572
|
-
if (value === "fact" || value === "confirmed") {
|
|
573
|
-
return "resolved_true";
|
|
574
|
-
}
|
|
575
|
-
if (value === "disconfirmed" || value === "expired") {
|
|
576
|
-
return "resolved_false";
|
|
577
|
-
}
|
|
578
|
-
if (value === "deprecated") {
|
|
579
|
-
return "superseded";
|
|
566
|
+
function normalizeScopeValue(value) {
|
|
567
|
+
if (typeof value !== "string") {
|
|
568
|
+
return;
|
|
580
569
|
}
|
|
581
|
-
|
|
570
|
+
const normalized = value.trim();
|
|
571
|
+
return normalized.length > 0 ? normalized : void 0;
|
|
582
572
|
}
|
|
583
|
-
function
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
573
|
+
function pickPrimaryTopic(candidates) {
|
|
574
|
+
return [...candidates].sort((a, b) => {
|
|
575
|
+
const depthA = a.depth ?? 9999;
|
|
576
|
+
const depthB = b.depth ?? 9999;
|
|
577
|
+
if (depthA !== depthB) {
|
|
578
|
+
return depthA - depthB;
|
|
579
|
+
}
|
|
580
|
+
const createdA = a.createdAt ?? Number.MAX_SAFE_INTEGER;
|
|
581
|
+
const createdB = b.createdAt ?? Number.MAX_SAFE_INTEGER;
|
|
582
|
+
if (createdA !== createdB) {
|
|
583
|
+
return createdA - createdB;
|
|
584
|
+
}
|
|
585
|
+
return String(a.name || "").localeCompare(String(b.name || ""));
|
|
586
|
+
})[0];
|
|
594
587
|
}
|
|
595
|
-
function
|
|
596
|
-
const
|
|
597
|
-
|
|
598
|
-
return
|
|
588
|
+
async function findTopicsByScopeAlias(ctx, scopeId) {
|
|
589
|
+
const query = ctx.db.query("topics");
|
|
590
|
+
try {
|
|
591
|
+
return await query.withIndex(
|
|
592
|
+
"by_graph_scope_project",
|
|
593
|
+
(q) => q.eq(LEGACY_SCOPE_FIELD2, scopeId)
|
|
594
|
+
).collect();
|
|
595
|
+
} catch (error) {
|
|
596
|
+
debugGraphPrimitiveFallback(
|
|
597
|
+
"[topicScope] Failed to resolve scope alias via index",
|
|
598
|
+
{
|
|
599
|
+
error,
|
|
600
|
+
scopeId
|
|
601
|
+
}
|
|
602
|
+
);
|
|
603
|
+
const topics = await query.collect();
|
|
604
|
+
return topics.filter((topic) => {
|
|
605
|
+
const normalizedGlobalId = normalizeScopeValue(topic.globalId);
|
|
606
|
+
const mappedProjectId = asMappedProjectId(topic);
|
|
607
|
+
return String(topic._id) === scopeId || normalizedGlobalId === scopeId || mappedProjectId === scopeId;
|
|
608
|
+
});
|
|
599
609
|
}
|
|
600
|
-
return normalized <= 0 || normalized >= 1;
|
|
601
|
-
}
|
|
602
|
-
function getPredictionMetaFromMetadata(metadata) {
|
|
603
|
-
return metadata?.predictionMeta;
|
|
604
610
|
}
|
|
605
|
-
function
|
|
606
|
-
if (
|
|
611
|
+
async function tryResolveHostTopicById(ctx, topicId) {
|
|
612
|
+
if (typeof ctx.runQuery !== "function") {
|
|
607
613
|
return null;
|
|
608
614
|
}
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
+
try {
|
|
616
|
+
return await ctx.runQuery(api.topics.get, {
|
|
617
|
+
id: topicId
|
|
618
|
+
}) ?? null;
|
|
619
|
+
} catch (error) {
|
|
620
|
+
debugGraphPrimitiveFallback(
|
|
621
|
+
"[topicScope] Failed to resolve topic by host query",
|
|
622
|
+
{
|
|
623
|
+
error,
|
|
624
|
+
topicId
|
|
625
|
+
}
|
|
626
|
+
);
|
|
627
|
+
return null;
|
|
615
628
|
}
|
|
616
|
-
return null;
|
|
617
629
|
}
|
|
618
|
-
function
|
|
619
|
-
if (
|
|
620
|
-
|
|
621
|
-
return normalized === 0 ? "resolved_false" : "resolved_true";
|
|
622
|
-
}
|
|
623
|
-
const directPredictionStatus = resolvedPredictionStatus(opts.predictionMeta);
|
|
624
|
-
if (directPredictionStatus) {
|
|
625
|
-
return directPredictionStatus;
|
|
630
|
+
async function tryResolveHostTopicByLegacyScope(ctx, legacyScopeId) {
|
|
631
|
+
if (typeof ctx.runQuery !== "function") {
|
|
632
|
+
return null;
|
|
626
633
|
}
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
634
|
+
try {
|
|
635
|
+
return await ctx.runQuery(api.topics.getByLegacyScopeId, {
|
|
636
|
+
projectId: legacyScopeId
|
|
637
|
+
}) ?? null;
|
|
638
|
+
} catch (error) {
|
|
639
|
+
debugGraphPrimitiveFallback(
|
|
640
|
+
"[topicScope] Failed to resolve topic by legacy scope",
|
|
641
|
+
{
|
|
642
|
+
error,
|
|
643
|
+
legacyScopeId
|
|
644
|
+
}
|
|
645
|
+
);
|
|
646
|
+
return null;
|
|
632
647
|
}
|
|
633
|
-
return null;
|
|
634
648
|
}
|
|
635
|
-
function
|
|
636
|
-
const
|
|
637
|
-
|
|
638
|
-
|
|
649
|
+
async function resolveInheritedWorkspaceScope(ctx, topic) {
|
|
650
|
+
const MAX_DEPTH = 10;
|
|
651
|
+
let tenantId = normalizeScopeValue(topic.tenantId);
|
|
652
|
+
let workspaceId = normalizeScopeValue(topic.workspaceId);
|
|
653
|
+
if (tenantId && workspaceId) {
|
|
654
|
+
return { tenantId, workspaceId };
|
|
639
655
|
}
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
return "active";
|
|
656
|
+
let current = topic;
|
|
657
|
+
for (let i = 0; i < MAX_DEPTH && current?.parentTopicId; i++) {
|
|
658
|
+
current = await ctx.db.get(current.parentTopicId);
|
|
659
|
+
if (!current) {
|
|
660
|
+
break;
|
|
646
661
|
}
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
if (
|
|
654
|
-
|
|
662
|
+
if (!tenantId) {
|
|
663
|
+
tenantId = normalizeScopeValue(current.tenantId);
|
|
664
|
+
}
|
|
665
|
+
if (!workspaceId) {
|
|
666
|
+
workspaceId = normalizeScopeValue(current.workspaceId);
|
|
667
|
+
}
|
|
668
|
+
if (tenantId && workspaceId) {
|
|
669
|
+
break;
|
|
655
670
|
}
|
|
656
|
-
return normalizedMetaStatus;
|
|
657
|
-
}
|
|
658
|
-
return "assumption";
|
|
659
|
-
}
|
|
660
|
-
function isPreValidationBeliefStatus(status) {
|
|
661
|
-
return status === "assumption" || status === "hypothesis";
|
|
662
|
-
}
|
|
663
|
-
|
|
664
|
-
// src/topicProjectOverlay.ts
|
|
665
|
-
var LEGACY_SCOPE_FIELD2 = "graphScopeProjectId";
|
|
666
|
-
function readNonEmptyString(value) {
|
|
667
|
-
if (typeof value !== "string") {
|
|
668
|
-
return;
|
|
669
671
|
}
|
|
670
|
-
|
|
671
|
-
return normalized.length > 0 ? normalized : void 0;
|
|
672
|
+
return { tenantId, workspaceId };
|
|
672
673
|
}
|
|
673
|
-
function
|
|
674
|
-
if (
|
|
675
|
-
return
|
|
674
|
+
async function resolveTopicProjectScope(ctx, args) {
|
|
675
|
+
if (args.topicId) {
|
|
676
|
+
return await resolveScopeFromTopicId(ctx, args.topicId);
|
|
676
677
|
}
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
function readMetadata(topic) {
|
|
680
|
-
return topic.metadata && typeof topic.metadata === "object" ? topic.metadata : {};
|
|
681
|
-
}
|
|
682
|
-
function readLegacyProjectId(value) {
|
|
683
|
-
if (!value) {
|
|
684
|
-
return;
|
|
678
|
+
if (args.projectId) {
|
|
679
|
+
return await resolveScopeFromLegacyProjectId(ctx, args.projectId);
|
|
685
680
|
}
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
return value === "private" || value === "team" || value === "firm" || value === "external" || value === "public" ? value : void 0;
|
|
690
|
-
}
|
|
691
|
-
function coerceStatus(value) {
|
|
692
|
-
return value === "active" || value === "archived" || value === "watching" ? value : void 0;
|
|
681
|
+
throw new Error(
|
|
682
|
+
"Missing scope: provide topicId (preferred) or legacy projectId alias."
|
|
683
|
+
);
|
|
693
684
|
}
|
|
694
|
-
function
|
|
695
|
-
const
|
|
696
|
-
if (
|
|
697
|
-
return
|
|
685
|
+
async function resolveScopeFromTopicId(ctx, topicId) {
|
|
686
|
+
const topic = await resolveTopicDocFromTopicId(ctx, topicId);
|
|
687
|
+
if (topic) {
|
|
688
|
+
return await buildTopicScope(ctx, topic, "topic");
|
|
698
689
|
}
|
|
699
|
-
|
|
700
|
-
|
|
690
|
+
const nodeScope = await resolveTopicNodeScopeOrNull(ctx, String(topicId));
|
|
691
|
+
if (nodeScope) {
|
|
692
|
+
return nodeScope;
|
|
701
693
|
}
|
|
702
|
-
|
|
703
|
-
}
|
|
704
|
-
function isProjectLikeTopic(topic) {
|
|
705
|
-
const metadata = readMetadata(topic);
|
|
706
|
-
return topic.type === "theme" || topic.type === "thematic" || topic.type === "deal" || topic.type === "monitoring" || readLegacyProjectId(topic) !== void 0 || readNonEmptyString(metadata.projectType) !== void 0;
|
|
694
|
+
throw new Error(`Topic not found: ${String(topicId)}`);
|
|
707
695
|
}
|
|
708
|
-
function
|
|
709
|
-
const
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
)
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
if (error instanceof Error) {
|
|
716
|
-
return error.message;
|
|
696
|
+
async function resolveTopicDocFromTopicId(ctx, topicId) {
|
|
697
|
+
const direct = await tryReadTopicDoc(ctx, topicId, {
|
|
698
|
+
failureLog: "[topicScope] Failed to load topic by direct id",
|
|
699
|
+
idLogKey: "topicId"
|
|
700
|
+
});
|
|
701
|
+
if (direct) {
|
|
702
|
+
return direct;
|
|
717
703
|
}
|
|
718
|
-
|
|
719
|
-
|
|
704
|
+
const hostTopic = await tryResolveHostTopicById(ctx, String(topicId));
|
|
705
|
+
if (hostTopic) {
|
|
706
|
+
return hostTopic;
|
|
720
707
|
}
|
|
721
|
-
return
|
|
708
|
+
return pickPrimaryTopic(await findTopicsByScopeAlias(ctx, String(topicId))) ?? null;
|
|
722
709
|
}
|
|
723
|
-
async function
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
} catch (error) {
|
|
733
|
-
debugGraphPrimitiveFallback(
|
|
734
|
-
"[topicProjectOverlay] Failed to resolve topic by direct ID",
|
|
735
|
-
{
|
|
736
|
-
error,
|
|
737
|
-
scopeId
|
|
738
|
-
}
|
|
739
|
-
);
|
|
740
|
-
}
|
|
741
|
-
}
|
|
742
|
-
if (typeof ctx.runQuery !== "function") {
|
|
743
|
-
return null;
|
|
710
|
+
async function resolveScopeFromLegacyProjectId(ctx, legacyProjectId) {
|
|
711
|
+
const directTopic = await resolveDirectLegacyProjectTopic(
|
|
712
|
+
ctx,
|
|
713
|
+
legacyProjectId
|
|
714
|
+
);
|
|
715
|
+
if (directTopic) {
|
|
716
|
+
return await buildTopicScope(ctx, directTopic, "topic_inferred", {
|
|
717
|
+
fallbackProjectId: legacyProjectId
|
|
718
|
+
});
|
|
744
719
|
}
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
720
|
+
const primary = pickPrimaryTopic(
|
|
721
|
+
await findTopicsByScopeAlias(ctx, legacyProjectId)
|
|
722
|
+
);
|
|
723
|
+
if (primary) {
|
|
724
|
+
return await buildTopicScope(ctx, primary, "project_mapped_topic", {
|
|
725
|
+
fallbackProjectId: legacyProjectId
|
|
748
726
|
});
|
|
749
|
-
if (topic?.name !== void 0 && topic?.type !== void 0) {
|
|
750
|
-
return topic;
|
|
751
|
-
}
|
|
752
|
-
} catch (error) {
|
|
753
|
-
debugGraphPrimitiveFallback(
|
|
754
|
-
"[topicProjectOverlay] Failed to resolve topic by ID query",
|
|
755
|
-
{
|
|
756
|
-
error,
|
|
757
|
-
scopeId
|
|
758
|
-
}
|
|
759
|
-
);
|
|
760
727
|
}
|
|
728
|
+
const nodeScope = await resolveTopicNodeScopeOrNull(ctx, legacyProjectId);
|
|
729
|
+
if (nodeScope) {
|
|
730
|
+
return {
|
|
731
|
+
...nodeScope,
|
|
732
|
+
projectId: nodeScope.projectId ?? legacyProjectId
|
|
733
|
+
};
|
|
734
|
+
}
|
|
735
|
+
throw new Error(
|
|
736
|
+
`Legacy project scope ${legacyProjectId} has no mapped topic.`
|
|
737
|
+
);
|
|
738
|
+
}
|
|
739
|
+
async function resolveDirectLegacyProjectTopic(ctx, legacyProjectId) {
|
|
740
|
+
const directTopic = await tryReadTopicDoc(ctx, legacyProjectId, {
|
|
741
|
+
failureLog: "[topicScope] Failed to load direct project topic",
|
|
742
|
+
idLogKey: "projectId"
|
|
743
|
+
});
|
|
744
|
+
return directTopic ?? tryResolveHostTopicByLegacyScope(ctx, legacyProjectId);
|
|
745
|
+
}
|
|
746
|
+
async function tryReadTopicDoc(ctx, id, log) {
|
|
761
747
|
try {
|
|
762
|
-
|
|
763
|
-
projectId: String(scopeId)
|
|
764
|
-
});
|
|
765
|
-
if (topic?.name !== void 0 && topic?.type !== void 0) {
|
|
766
|
-
return topic;
|
|
767
|
-
}
|
|
748
|
+
return await ctx.db.get(id);
|
|
768
749
|
} catch (error) {
|
|
769
|
-
debugGraphPrimitiveFallback(
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
);
|
|
750
|
+
debugGraphPrimitiveFallback(log.failureLog, {
|
|
751
|
+
error,
|
|
752
|
+
[log.idLogKey]: id
|
|
753
|
+
});
|
|
754
|
+
return null;
|
|
773
755
|
}
|
|
774
|
-
return null;
|
|
775
756
|
}
|
|
776
|
-
function
|
|
777
|
-
const
|
|
778
|
-
const
|
|
779
|
-
const legacyProjectId = readLegacyProjectId(topic) || readLegacyProjectId(metadata) || readNonEmptyString(metadata.legacyProjectId);
|
|
780
|
-
const storageProjectId = legacyProjectId || topicId;
|
|
781
|
-
const outwardId = idMode === "topic" ? topicId : storageProjectId;
|
|
782
|
-
const visibility = coerceVisibility(topic.visibility) || coerceVisibility(metadata.visibility) || "private";
|
|
783
|
-
const status = coerceStatus(topic.status) || coerceStatus(metadata.status) || "active";
|
|
784
|
-
const createdAt = typeof topic.createdAt === "number" ? topic.createdAt : typeof topic._creationTime === "number" ? topic._creationTime : 0;
|
|
785
|
-
const updatedAt = typeof topic.updatedAt === "number" ? topic.updatedAt : typeof metadata.updatedAt === "number" ? metadata.updatedAt : createdAt;
|
|
757
|
+
async function buildTopicScope(ctx, topic, source, options = {}) {
|
|
758
|
+
const inherited = await resolveInheritedWorkspaceScope(ctx, topic);
|
|
759
|
+
const mapped = asMappedProjectId(topic);
|
|
786
760
|
return {
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
legacyProjectId,
|
|
793
|
-
name: readNonEmptyString(topic.name) || "Untitled Theme",
|
|
794
|
-
type: mapProjectType(topic, metadata),
|
|
795
|
-
description: readNonEmptyString(topic.description),
|
|
796
|
-
ownerId: readNonEmptyString(metadata.ownerId) || readNonEmptyString(topic.createdBy) || "system",
|
|
797
|
-
// FR.7 creator-grant: surface the principal-shaped owner field (column-first,
|
|
798
|
-
// metadata fallback for legacy rows that recorded it in metadata).
|
|
799
|
-
ownerPrincipalId: readNonEmptyString(topic.ownerPrincipalId) || readNonEmptyString(metadata.ownerPrincipalId),
|
|
800
|
-
// RR.1 carrier: preserve the nested metadata carrier so the kernel's
|
|
801
|
-
// `checkProjectAccessDetailed` metadata-PRIMARY read
|
|
802
|
-
// (`project.metadata?.ownerPrincipalId`) resolves the grant. The `...metadata`
|
|
803
|
-
// spread above only flattens keys; it does not leave a nested `metadata`.
|
|
804
|
-
metadata,
|
|
805
|
-
sharedWith: readStringArray(metadata.sharedWith),
|
|
806
|
-
visibility,
|
|
807
|
-
tenantId: readNonEmptyString(topic.tenantId) || readNonEmptyString(metadata.tenantId),
|
|
808
|
-
workspaceId: readNonEmptyString(topic.workspaceId) || readNonEmptyString(metadata.workspaceId),
|
|
809
|
-
status,
|
|
810
|
-
tags: readStringArray(metadata.tags),
|
|
811
|
-
chatCount: typeof metadata.chatCount === "number" ? metadata.chatCount : 0,
|
|
812
|
-
artifactCount: typeof metadata.artifactCount === "number" ? metadata.artifactCount : 0,
|
|
813
|
-
lastActivityAt: typeof metadata.lastActivityAt === "number" ? metadata.lastActivityAt : updatedAt,
|
|
814
|
-
_creationTime: typeof topic._creationTime === "number" ? topic._creationTime : createdAt,
|
|
815
|
-
createdAt,
|
|
816
|
-
updatedAt
|
|
761
|
+
topicId: topic._id,
|
|
762
|
+
...mapped || options.fallbackProjectId ? { projectId: mapped ?? options.fallbackProjectId } : {},
|
|
763
|
+
tenantId: inherited.tenantId,
|
|
764
|
+
workspaceId: inherited.workspaceId,
|
|
765
|
+
source
|
|
817
766
|
};
|
|
818
767
|
}
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
if (
|
|
825
|
-
return
|
|
768
|
+
var optionalScopeArgs = {
|
|
769
|
+
projectId: v.optional(v.string()),
|
|
770
|
+
topicId: v.optional(v.string())
|
|
771
|
+
};
|
|
772
|
+
function normalizeScopeValue2(value) {
|
|
773
|
+
if (typeof value !== "string") {
|
|
774
|
+
return;
|
|
826
775
|
}
|
|
827
|
-
|
|
776
|
+
const normalized = value.trim();
|
|
777
|
+
return normalized.length > 0 ? normalized : void 0;
|
|
828
778
|
}
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
779
|
+
function throwWorkspaceIsolationError(args) {
|
|
780
|
+
const error = new Error(args.message);
|
|
781
|
+
error.status = 409;
|
|
782
|
+
error.code = "INVARIANT_VIOLATION";
|
|
783
|
+
error.invariantCode = args.invariantCode;
|
|
784
|
+
error.suggestion = args.suggestion;
|
|
785
|
+
error.details = args.details;
|
|
786
|
+
throw error;
|
|
787
|
+
}
|
|
788
|
+
function assertWorkspaceScopedEpistemicNodeScope(args) {
|
|
789
|
+
const layer = isNodeType(args.nodeType) ? getLayerForNodeType(args.nodeType) : void 0;
|
|
790
|
+
if (layer === "ontological") {
|
|
791
|
+
return;
|
|
792
|
+
}
|
|
793
|
+
const workspaceId = normalizeScopeValue2(args.scope.workspaceId);
|
|
794
|
+
if (workspaceId) {
|
|
795
|
+
return;
|
|
796
|
+
}
|
|
797
|
+
throwWorkspaceIsolationError({
|
|
798
|
+
message: "Workspace-scoped reasoning isolation requires workspaceId on non-ontological node creation.",
|
|
799
|
+
invariantCode: "workspace.scope_required_for_epistemic_nodes",
|
|
800
|
+
suggestion: "Resolve the topic/project scope through a workspace-bound topic before creating epistemic nodes.",
|
|
801
|
+
details: {
|
|
802
|
+
mutationName: args.mutationName,
|
|
803
|
+
nodeType: args.nodeType,
|
|
804
|
+
topicId: args.scope.topicId,
|
|
805
|
+
projectId: args.scope.projectId
|
|
840
806
|
}
|
|
807
|
+
});
|
|
808
|
+
}
|
|
809
|
+
function nodeMatchesWorkspaceReasoningScope(node, scope) {
|
|
810
|
+
if (!node) {
|
|
811
|
+
return false;
|
|
841
812
|
}
|
|
842
|
-
|
|
843
|
-
|
|
813
|
+
const scopeTenantId = normalizeScopeValue2(scope.tenantId);
|
|
814
|
+
const scopeWorkspaceId = normalizeScopeValue2(scope.workspaceId);
|
|
815
|
+
const nodeTenantId = normalizeScopeValue2(node.tenantId);
|
|
816
|
+
const nodeWorkspaceId = normalizeScopeValue2(node.workspaceId);
|
|
817
|
+
const epistemicLayer = typeof node.epistemicLayer === "string" ? node.epistemicLayer : void 0;
|
|
818
|
+
if (scopeTenantId && nodeTenantId && scopeTenantId !== nodeTenantId) {
|
|
819
|
+
return false;
|
|
844
820
|
}
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
821
|
+
if (epistemicLayer === "ontological" && nodeWorkspaceId === void 0) {
|
|
822
|
+
return true;
|
|
823
|
+
}
|
|
824
|
+
if (!scopeWorkspaceId && node.publicationStatus === "published") {
|
|
825
|
+
return true;
|
|
826
|
+
}
|
|
827
|
+
if (!scopeWorkspaceId) {
|
|
828
|
+
return nodeWorkspaceId === void 0;
|
|
829
|
+
}
|
|
830
|
+
return scopeWorkspaceId === nodeWorkspaceId;
|
|
848
831
|
}
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
return null;
|
|
832
|
+
function resolveRuntimePackMutationContext(args) {
|
|
833
|
+
if (!(args.runtimeToolName || args.runtimePackKey || args.runtimePackInstallScope)) {
|
|
834
|
+
return;
|
|
853
835
|
}
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
836
|
+
return {
|
|
837
|
+
toolName: args.runtimeToolName,
|
|
838
|
+
packKey: args.runtimePackKey,
|
|
839
|
+
packInstallScope: args.runtimePackInstallScope
|
|
858
840
|
};
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
case "topicId":
|
|
864
|
-
case "legacyProjectId":
|
|
865
|
-
case "storageProjectId":
|
|
866
|
-
break;
|
|
867
|
-
case "name":
|
|
868
|
-
case "description":
|
|
869
|
-
patch[key] = rawValue;
|
|
870
|
-
topicUpdateArgs[key] = rawValue;
|
|
871
|
-
break;
|
|
872
|
-
case "tenantId":
|
|
873
|
-
case "workspaceId":
|
|
874
|
-
case "ownerId":
|
|
875
|
-
throw new Error(
|
|
876
|
-
`patchTopicProjectOverlay cannot mutate ${key} via component-owned topics`
|
|
877
|
-
);
|
|
878
|
-
case "status": {
|
|
879
|
-
const status = coerceStatus(rawValue);
|
|
880
|
-
if (status) {
|
|
881
|
-
patch.status = status;
|
|
882
|
-
topicUpdateArgs.status = status;
|
|
883
|
-
}
|
|
884
|
-
break;
|
|
885
|
-
}
|
|
886
|
-
case "visibility": {
|
|
887
|
-
const visibility = coerceVisibility(rawValue);
|
|
888
|
-
if (visibility) {
|
|
889
|
-
patch.visibility = visibility;
|
|
890
|
-
topicUpdateArgs.visibility = visibility;
|
|
891
|
-
}
|
|
892
|
-
break;
|
|
893
|
-
}
|
|
894
|
-
case "type": {
|
|
895
|
-
const projectType = readNonEmptyString(rawValue);
|
|
896
|
-
if (projectType) {
|
|
897
|
-
nextMetadata.projectType = projectType;
|
|
898
|
-
} else {
|
|
899
|
-
delete nextMetadata.projectType;
|
|
900
|
-
}
|
|
901
|
-
break;
|
|
902
|
-
}
|
|
903
|
-
case "updatedAt":
|
|
904
|
-
case "createdAt":
|
|
905
|
-
break;
|
|
906
|
-
default:
|
|
907
|
-
if (rawValue === void 0) {
|
|
908
|
-
delete nextMetadata[key];
|
|
909
|
-
} else {
|
|
910
|
-
nextMetadata[key] = rawValue;
|
|
911
|
-
}
|
|
912
|
-
}
|
|
841
|
+
}
|
|
842
|
+
function assertTenantPackWorkspaceMutationAllowed(args) {
|
|
843
|
+
if (!args.runtime?.packKey || args.runtime.packInstallScope !== "tenant") {
|
|
844
|
+
return;
|
|
913
845
|
}
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
try {
|
|
919
|
-
await ctx.runMutation(api.topics.update, topicUpdateArgs);
|
|
920
|
-
} catch (error) {
|
|
921
|
-
if (!isMissingLucernChildComponentError(error) || !ctx?.db || typeof ctx.db.patch !== "function") {
|
|
922
|
-
throw error;
|
|
923
|
-
}
|
|
924
|
-
await ctx.db.patch(String(topic._id), patch);
|
|
925
|
-
}
|
|
926
|
-
} else if (ctx?.db && typeof ctx.db.patch === "function") {
|
|
927
|
-
await ctx.db.patch(String(topic._id), patch);
|
|
928
|
-
} else {
|
|
929
|
-
throw new Error(
|
|
930
|
-
"Cannot patch topic without component adapter (ctx.runMutation unavailable)"
|
|
931
|
-
);
|
|
846
|
+
const targetWorkspaceId = normalizeScopeValue2(args.target.workspaceId);
|
|
847
|
+
const targetLayer = typeof args.target.epistemicLayer === "string" ? args.target.epistemicLayer : void 0;
|
|
848
|
+
if (!targetWorkspaceId || targetLayer === "ontological") {
|
|
849
|
+
return;
|
|
932
850
|
}
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
851
|
+
throwWorkspaceIsolationError({
|
|
852
|
+
message: `Tenant-scoped pack "${args.runtime.packKey}" cannot mutate workspace-scoped reasoning state.`,
|
|
853
|
+
invariantCode: "workspace.tenant_pack_reasoning_write_forbidden",
|
|
854
|
+
suggestion: "Use a workspace-scoped pack for workspace-local graph mutations, or route the change through tenant-global canonical entity flows.",
|
|
855
|
+
details: {
|
|
856
|
+
mutationName: args.mutationName,
|
|
857
|
+
toolName: args.runtime.toolName,
|
|
858
|
+
packKey: args.runtime.packKey,
|
|
859
|
+
targetWorkspaceId,
|
|
860
|
+
targetNodeType: args.target.nodeType,
|
|
861
|
+
targetLayer
|
|
862
|
+
}
|
|
937
863
|
});
|
|
938
864
|
}
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
865
|
+
v.id("epistemicNodes");
|
|
866
|
+
var DEFAULT_PROJECT_BELIEF_LIMIT = 250;
|
|
867
|
+
var MAX_PROJECT_BELIEF_LIMIT = 1e3;
|
|
868
|
+
var optionalBeliefScopeArgs = optionalScopeArgs;
|
|
869
|
+
({
|
|
870
|
+
tupleContradiction: normalizeTupleContradictionPolicy()
|
|
871
|
+
});
|
|
872
|
+
function readFiniteNumber(value) {
|
|
873
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
946
874
|
}
|
|
947
|
-
function
|
|
948
|
-
|
|
949
|
-
return error.message;
|
|
950
|
-
}
|
|
951
|
-
if (typeof error === "object" && error !== null && "message" in error && typeof error.message === "string") {
|
|
952
|
-
return error.message;
|
|
953
|
-
}
|
|
954
|
-
return "unknown error";
|
|
875
|
+
function isRecord(value) {
|
|
876
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
955
877
|
}
|
|
956
|
-
function
|
|
957
|
-
|
|
958
|
-
const keys = Object.keys(value);
|
|
959
|
-
return keys.length > 0 && keys.every((key) => advisoryKeys.has(key));
|
|
878
|
+
function readOptionalString(value) {
|
|
879
|
+
return typeof value === "string" && value.trim().length > 0 ? value : void 0;
|
|
960
880
|
}
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
} catch (error) {
|
|
965
|
-
if (!isAdvisoryTopicPatch(value) || !isMissingLucernChildComponentError2(error)) {
|
|
966
|
-
throw error;
|
|
967
|
-
}
|
|
968
|
-
console.warn(
|
|
969
|
-
"[lucern graph-primitives] Non-fatal advisory topic patch failure",
|
|
970
|
-
{
|
|
971
|
-
projectId,
|
|
972
|
-
keys: Object.keys(value),
|
|
973
|
-
error: getErrorMessage2(error)
|
|
974
|
-
}
|
|
975
|
-
);
|
|
881
|
+
function readStringArray2(value) {
|
|
882
|
+
if (!Array.isArray(value)) {
|
|
883
|
+
return;
|
|
976
884
|
}
|
|
885
|
+
const strings = value.filter(
|
|
886
|
+
(item) => typeof item === "string" && item.length > 0
|
|
887
|
+
);
|
|
888
|
+
return strings.length === value.length ? strings : void 0;
|
|
977
889
|
}
|
|
978
|
-
function
|
|
979
|
-
return
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
890
|
+
function readRecord(value) {
|
|
891
|
+
return isRecord(value) ? value : void 0;
|
|
892
|
+
}
|
|
893
|
+
function readBeliefNodeView(value) {
|
|
894
|
+
if (!isRecord(value)) {
|
|
895
|
+
return null;
|
|
896
|
+
}
|
|
897
|
+
const id = readOptionalString(value._id);
|
|
898
|
+
const nodeType = readOptionalString(value.nodeType);
|
|
899
|
+
if (!(id && nodeType === "belief")) {
|
|
900
|
+
return null;
|
|
901
|
+
}
|
|
902
|
+
const node = {
|
|
903
|
+
_id: id,
|
|
904
|
+
nodeType
|
|
989
905
|
};
|
|
906
|
+
const creationTime = readFiniteNumber(value._creationTime);
|
|
907
|
+
if (creationTime !== void 0) {
|
|
908
|
+
node._creationTime = creationTime;
|
|
909
|
+
}
|
|
910
|
+
const metadata = readRecord(value.metadata);
|
|
911
|
+
if (metadata !== void 0) {
|
|
912
|
+
node.metadata = metadata;
|
|
913
|
+
}
|
|
914
|
+
const opinionA = readFiniteNumber(value.opinion_a);
|
|
915
|
+
if (opinionA !== void 0) {
|
|
916
|
+
node.opinion_a = opinionA;
|
|
917
|
+
}
|
|
918
|
+
const opinionB = readFiniteNumber(value.opinion_b);
|
|
919
|
+
if (opinionB !== void 0) {
|
|
920
|
+
node.opinion_b = opinionB;
|
|
921
|
+
}
|
|
922
|
+
const opinionD = readFiniteNumber(value.opinion_d);
|
|
923
|
+
if (opinionD !== void 0) {
|
|
924
|
+
node.opinion_d = opinionD;
|
|
925
|
+
}
|
|
926
|
+
const opinionU = readFiniteNumber(value.opinion_u);
|
|
927
|
+
if (opinionU !== void 0) {
|
|
928
|
+
node.opinion_u = opinionU;
|
|
929
|
+
}
|
|
930
|
+
const tupleContradicted = typeof value.tupleContradicted === "boolean" ? value.tupleContradicted : void 0;
|
|
931
|
+
if (tupleContradicted !== void 0) {
|
|
932
|
+
node.tupleContradicted = tupleContradicted;
|
|
933
|
+
}
|
|
934
|
+
const stringFields = {
|
|
935
|
+
anonymizationClass: value.anonymizationClass,
|
|
936
|
+
audienceLabel: value.audienceLabel,
|
|
937
|
+
canonicalText: value.canonicalText,
|
|
938
|
+
createdBy: value.createdBy,
|
|
939
|
+
epistemicLayer: value.epistemicLayer,
|
|
940
|
+
exportClass: value.exportClass,
|
|
941
|
+
globalId: value.globalId,
|
|
942
|
+
projectId: value.projectId,
|
|
943
|
+
publicationStatus: value.publicationStatus,
|
|
944
|
+
sensitivityTier: value.sensitivityTier,
|
|
945
|
+
status: value.status,
|
|
946
|
+
tenantId: value.tenantId,
|
|
947
|
+
topicId: value.topicId,
|
|
948
|
+
userId: value.userId,
|
|
949
|
+
workspaceId: value.workspaceId
|
|
950
|
+
};
|
|
951
|
+
for (const [field, fieldValue] of Object.entries(stringFields)) {
|
|
952
|
+
const normalized = readOptionalString(fieldValue);
|
|
953
|
+
if (normalized !== void 0) {
|
|
954
|
+
node[field] = normalized;
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
const createdAt = readFiniteNumber(value.createdAt);
|
|
958
|
+
if (createdAt !== void 0) {
|
|
959
|
+
node.createdAt = createdAt;
|
|
960
|
+
}
|
|
961
|
+
const updatedAt = readFiniteNumber(value.updatedAt);
|
|
962
|
+
if (updatedAt !== void 0) {
|
|
963
|
+
node.updatedAt = updatedAt;
|
|
964
|
+
}
|
|
965
|
+
if (value.beliefStatus !== void 0) {
|
|
966
|
+
node.beliefStatus = value.beliefStatus;
|
|
967
|
+
}
|
|
968
|
+
if (value.confidence !== void 0) {
|
|
969
|
+
node.confidence = value.confidence;
|
|
970
|
+
}
|
|
971
|
+
if (value.predictionMeta !== void 0) {
|
|
972
|
+
node.predictionMeta = value.predictionMeta;
|
|
973
|
+
}
|
|
974
|
+
const policyTags = readStringArray2(value.policyTags);
|
|
975
|
+
if (policyTags !== void 0) {
|
|
976
|
+
node.policyTags = policyTags;
|
|
977
|
+
}
|
|
978
|
+
return node;
|
|
990
979
|
}
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
};
|
|
980
|
+
function readBeliefNodeViews(values) {
|
|
981
|
+
return values.flatMap((value) => {
|
|
982
|
+
const node = readBeliefNodeView(value);
|
|
983
|
+
return node ? [node] : [];
|
|
984
|
+
});
|
|
997
985
|
}
|
|
998
|
-
|
|
999
|
-
// src/epistemicBeliefs.helpers.ts
|
|
1000
|
-
v.id("epistemicNodes");
|
|
1001
|
-
var DEFAULT_PROJECT_BELIEF_LIMIT = 250;
|
|
1002
|
-
var MAX_PROJECT_BELIEF_LIMIT = 1e3;
|
|
1003
|
-
var optionalBeliefScopeArgs = optionalScopeArgs;
|
|
1004
|
-
({
|
|
1005
|
-
tupleContradiction: normalizeTupleContradictionPolicy()
|
|
1006
|
-
});
|
|
1007
986
|
function assertBaseRateInRange(baseRate, field = "baseRate") {
|
|
1008
987
|
if (baseRate < 0 || baseRate > 1) {
|
|
1009
988
|
throwStructuredMutationError({
|
|
@@ -1098,7 +1077,7 @@ function normalizePillar(pillar) {
|
|
|
1098
1077
|
async function markBeliefGraphDirty(ctx, scope) {
|
|
1099
1078
|
const projectId = typeof scope.projectId === "string" && scope.projectId.trim().length > 0 ? scope.projectId : void 0;
|
|
1100
1079
|
const topicId = typeof scope.topicId === "string" && scope.topicId.trim().length > 0 ? scope.topicId : void 0;
|
|
1101
|
-
if (!projectId
|
|
1080
|
+
if (!(projectId || topicId)) {
|
|
1102
1081
|
return;
|
|
1103
1082
|
}
|
|
1104
1083
|
if (projectId) {
|
|
@@ -1115,16 +1094,22 @@ async function markBeliefGraphDirty(ctx, scope) {
|
|
|
1115
1094
|
{ topicId }
|
|
1116
1095
|
);
|
|
1117
1096
|
}
|
|
1097
|
+
const activityScopeId = topicId ?? projectId;
|
|
1098
|
+
if (!activityScopeId) {
|
|
1099
|
+
throw new Error(
|
|
1100
|
+
"Expected belief graph dirty scope to include a topic or project id."
|
|
1101
|
+
);
|
|
1102
|
+
}
|
|
1118
1103
|
await resolveGraphPrimitivesAppResolvers().patchProject(
|
|
1119
1104
|
ctx,
|
|
1120
|
-
|
|
1105
|
+
activityScopeId,
|
|
1121
1106
|
{
|
|
1122
1107
|
lastActivityAt: Date.now()
|
|
1123
1108
|
}
|
|
1124
1109
|
);
|
|
1125
1110
|
}
|
|
1126
1111
|
async function resolveBeliefScopeOrNull(ctx, args) {
|
|
1127
|
-
if (!args.projectId
|
|
1112
|
+
if (!(args.projectId || args.topicId)) {
|
|
1128
1113
|
return null;
|
|
1129
1114
|
}
|
|
1130
1115
|
try {
|
|
@@ -1149,14 +1134,17 @@ async function getBeliefNodesForScope(ctx, scope, args) {
|
|
|
1149
1134
|
"by_topic_type",
|
|
1150
1135
|
(q) => q.eq("topicId", scope.topicId).eq("nodeType", "belief")
|
|
1151
1136
|
);
|
|
1152
|
-
const
|
|
1137
|
+
const rows = typeof args?.scanLimit === "number" ? await baseQuery.order("desc").take(args.scanLimit) : await baseQuery.collect();
|
|
1138
|
+
const nodes = readBeliefNodeViews(rows);
|
|
1153
1139
|
const scopedNodes = nodes.filter(
|
|
1154
1140
|
(node) => nodeMatchesWorkspaceReasoningScope(node, scope)
|
|
1155
1141
|
);
|
|
1156
1142
|
if (!args?.status) {
|
|
1157
1143
|
return scopedNodes;
|
|
1158
1144
|
}
|
|
1159
|
-
return scopedNodes.filter(
|
|
1145
|
+
return scopedNodes.filter(
|
|
1146
|
+
(node) => node.status === args.status
|
|
1147
|
+
);
|
|
1160
1148
|
}
|
|
1161
1149
|
function createBeliefAudienceResolver(registryRows) {
|
|
1162
1150
|
const audienceClassByKey = new Map(
|
|
@@ -1176,9 +1164,7 @@ function createBeliefAudienceResolver(registryRows) {
|
|
|
1176
1164
|
function flattenBeliefNode(node) {
|
|
1177
1165
|
const meta = node.metadata || {};
|
|
1178
1166
|
const worktreeId = resolveBeliefWorktreeId(meta);
|
|
1179
|
-
const tupleContradicted = readTupleContradictedFlag(
|
|
1180
|
-
node.tupleContradicted
|
|
1181
|
-
) ?? readTupleContradictedFlag(meta.tupleContradicted) ?? false;
|
|
1167
|
+
const tupleContradicted = readTupleContradictedFlag(node.tupleContradicted) ?? readTupleContradictedFlag(meta.tupleContradicted) ?? false;
|
|
1182
1168
|
return {
|
|
1183
1169
|
_id: node._id,
|
|
1184
1170
|
_epistemicNodeId: node._id,
|
|
@@ -1223,8 +1209,172 @@ function resolveBeliefStatus(node, metadata) {
|
|
|
1223
1209
|
metadata
|
|
1224
1210
|
});
|
|
1225
1211
|
}
|
|
1212
|
+
function insertEpistemicNode(ctx, doc) {
|
|
1213
|
+
assertUuidV7Identity("epistemicNodes", doc.globalId);
|
|
1214
|
+
return ctx.db.insert("epistemicNodes", doc);
|
|
1215
|
+
}
|
|
1216
|
+
async function assertExistingNodeEndpoint(ctx, endpointRole, endpoint) {
|
|
1217
|
+
assertUuidShapedEdgeEndpoint(endpointRole, endpoint);
|
|
1218
|
+
const node = await ctx.db.query("epistemicNodes").withIndex(
|
|
1219
|
+
"by_globalId",
|
|
1220
|
+
(q) => q.eq("globalId", endpoint)
|
|
1221
|
+
).first();
|
|
1222
|
+
if (!node) {
|
|
1223
|
+
throw new Error(
|
|
1224
|
+
`edge_endpoint_not_canonical: epistemicEdges insert requires ${endpointRole} to be the globalId of an existing epistemicNodes row, received ${endpoint} (no node with that globalId)`
|
|
1225
|
+
);
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
async function insertEpistemicEdge(ctx, doc) {
|
|
1229
|
+
assertUuidV7Identity("epistemicEdges", doc.globalId);
|
|
1230
|
+
assertStorageEdgeVocabulary(doc.edgeType);
|
|
1231
|
+
if (!doc.fromNodeId || typeof doc.fromNodeId !== "string") {
|
|
1232
|
+
throw new Error(
|
|
1233
|
+
"edge_endpoint_missing: epistemicEdges insert requires a non-empty fromNodeId"
|
|
1234
|
+
);
|
|
1235
|
+
}
|
|
1236
|
+
if (!doc.toNodeId || typeof doc.toNodeId !== "string") {
|
|
1237
|
+
throw new Error(
|
|
1238
|
+
"edge_endpoint_missing: epistemicEdges insert requires a non-empty toNodeId"
|
|
1239
|
+
);
|
|
1240
|
+
}
|
|
1241
|
+
await assertExistingNodeEndpoint(ctx, "fromNodeId", doc.fromNodeId);
|
|
1242
|
+
await assertExistingNodeEndpoint(ctx, "toNodeId", doc.toNodeId);
|
|
1243
|
+
if (doc.fromNodeType && doc.toNodeType && doc.edgeType !== "extracted_from") {
|
|
1244
|
+
assertEdgePolicyAllowed(
|
|
1245
|
+
edgePolicyManifest,
|
|
1246
|
+
doc.edgeType,
|
|
1247
|
+
{
|
|
1248
|
+
kind: "epistemic_node",
|
|
1249
|
+
nodeId: doc.fromNodeId,
|
|
1250
|
+
nodeType: doc.fromNodeType
|
|
1251
|
+
},
|
|
1252
|
+
{
|
|
1253
|
+
kind: "epistemic_node",
|
|
1254
|
+
nodeId: doc.toNodeId,
|
|
1255
|
+
nodeType: doc.toNodeType
|
|
1256
|
+
}
|
|
1257
|
+
);
|
|
1258
|
+
}
|
|
1259
|
+
return ctx.db.insert("epistemicEdges", doc);
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1262
|
+
// src/epistemicBeliefs.topicAnchor.ts
|
|
1263
|
+
function cleanString(value) {
|
|
1264
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
1265
|
+
}
|
|
1266
|
+
function topicNodeCandidates(topicRef) {
|
|
1267
|
+
const normalized = topicRef.trim();
|
|
1268
|
+
if (!normalized) {
|
|
1269
|
+
return [];
|
|
1270
|
+
}
|
|
1271
|
+
const candidates = [normalized];
|
|
1272
|
+
if (normalized.startsWith("top_")) {
|
|
1273
|
+
candidates.push(normalized.slice(4));
|
|
1274
|
+
}
|
|
1275
|
+
return [...new Set(candidates)];
|
|
1276
|
+
}
|
|
1277
|
+
function readTopicNodeRef(args) {
|
|
1278
|
+
return cleanString(args.topicGlobalId) ?? cleanString(args.topicNodeId) ?? cleanString(args.topicId);
|
|
1279
|
+
}
|
|
1280
|
+
async function resolveRequiredTopicAnchor(ctx, topicRef) {
|
|
1281
|
+
for (const candidate of topicNodeCandidates(topicRef)) {
|
|
1282
|
+
try {
|
|
1283
|
+
const direct = await ctx.db.get(candidate);
|
|
1284
|
+
if (direct?.nodeType === "topic" && cleanString(direct.globalId)) {
|
|
1285
|
+
return direct;
|
|
1286
|
+
}
|
|
1287
|
+
} catch {
|
|
1288
|
+
}
|
|
1289
|
+
const byGlobalId = await ctx.db.query("epistemicNodes").withIndex("by_globalId", (q) => q.eq("globalId", candidate)).first();
|
|
1290
|
+
if (byGlobalId?.nodeType === "topic" && cleanString(byGlobalId.globalId)) {
|
|
1291
|
+
return byGlobalId;
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
throw new Error(
|
|
1295
|
+
"Belief creation requires topicGlobalId or topicNodeId for a topic node in epistemicNodes. Legacy topics-table IDs are not valid belief anchors."
|
|
1296
|
+
);
|
|
1297
|
+
}
|
|
1298
|
+
function scopeFromTopicAnchor(topicNode) {
|
|
1299
|
+
return {
|
|
1300
|
+
topicId: topicNode.globalId,
|
|
1301
|
+
projectId: cleanString(topicNode.projectId),
|
|
1302
|
+
tenantId: cleanString(topicNode.tenantId),
|
|
1303
|
+
workspaceId: cleanString(topicNode.workspaceId),
|
|
1304
|
+
source: "topic"
|
|
1305
|
+
};
|
|
1306
|
+
}
|
|
1307
|
+
async function createRequiredBeliefTopicEdge(ctx, args) {
|
|
1308
|
+
const topicGlobalId = args.topicNode.globalId;
|
|
1309
|
+
const now = Date.now();
|
|
1310
|
+
const existingEdges = await ctx.db.query("epistemicEdges").withIndex(
|
|
1311
|
+
"by_from_to",
|
|
1312
|
+
(q) => q.eq("fromNodeId", args.beliefGlobalId).eq("toNodeId", topicGlobalId)
|
|
1313
|
+
).collect();
|
|
1314
|
+
const existing = existingEdges.find((edge) => edge.edgeType === "belongs_to");
|
|
1315
|
+
const edgeGlobalId = cleanString(existing?.globalId) ?? generateUuidV7();
|
|
1316
|
+
if (!existing) {
|
|
1317
|
+
await insertEpistemicEdge(ctx, {
|
|
1318
|
+
globalId: edgeGlobalId,
|
|
1319
|
+
fromNodeId: args.beliefGlobalId,
|
|
1320
|
+
toNodeId: topicGlobalId,
|
|
1321
|
+
sourceGlobalId: args.beliefGlobalId,
|
|
1322
|
+
targetGlobalId: topicGlobalId,
|
|
1323
|
+
edgeType: "belongs_to",
|
|
1324
|
+
weight: 1,
|
|
1325
|
+
confidence: 1,
|
|
1326
|
+
context: "Belief creation topic anchor invariant.",
|
|
1327
|
+
reasoningMethod: "implicit",
|
|
1328
|
+
derivationType: "topic_scope_invariant",
|
|
1329
|
+
metadata: {
|
|
1330
|
+
invariant: "belief.topic_edge_required",
|
|
1331
|
+
edgeUuid: edgeGlobalId,
|
|
1332
|
+
fromUuid: args.beliefGlobalId,
|
|
1333
|
+
toUuid: topicGlobalId
|
|
1334
|
+
},
|
|
1335
|
+
createdBy: args.createdBy,
|
|
1336
|
+
createdAt: now,
|
|
1337
|
+
updatedAt: now,
|
|
1338
|
+
projectId: cleanString(args.topicNode.projectId),
|
|
1339
|
+
topicId: topicGlobalId,
|
|
1340
|
+
tenantId: cleanString(args.topicNode.tenantId),
|
|
1341
|
+
workspaceId: cleanString(args.topicNode.workspaceId),
|
|
1342
|
+
fromNodeType: "belief",
|
|
1343
|
+
toNodeType: "topic",
|
|
1344
|
+
fromLayer: "L3",
|
|
1345
|
+
toLayer: args.topicNode.epistemicLayer ?? "ontological"
|
|
1346
|
+
});
|
|
1347
|
+
}
|
|
1348
|
+
await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {
|
|
1349
|
+
globalId: edgeGlobalId,
|
|
1350
|
+
fromGlobalId: args.beliefGlobalId,
|
|
1351
|
+
toGlobalId: topicGlobalId,
|
|
1352
|
+
edgeType: "belongs_to",
|
|
1353
|
+
weight: 1,
|
|
1354
|
+
confidence: 1,
|
|
1355
|
+
context: "Belief creation topic anchor invariant.",
|
|
1356
|
+
projectId: cleanString(args.topicNode.projectId),
|
|
1357
|
+
topicId: topicGlobalId,
|
|
1358
|
+
createdBy: args.createdBy,
|
|
1359
|
+
fromNodeType: "belief",
|
|
1360
|
+
toNodeType: "topic",
|
|
1361
|
+
fromLayer: "L3",
|
|
1362
|
+
toLayer: args.topicNode.epistemicLayer ?? "ontological",
|
|
1363
|
+
metadata: {
|
|
1364
|
+
invariant: "belief.topic_edge_required",
|
|
1365
|
+
edgeUuid: edgeGlobalId,
|
|
1366
|
+
fromUuid: args.beliefGlobalId,
|
|
1367
|
+
toUuid: topicGlobalId
|
|
1368
|
+
}
|
|
1369
|
+
});
|
|
1370
|
+
}
|
|
1226
1371
|
|
|
1227
1372
|
// src/epistemicBeliefs.internal.ts
|
|
1373
|
+
var BELIEF_CATEGORIZATION_ACTION = "beliefCategorization:autoCategorizeBelief";
|
|
1374
|
+
var EMBEDDING_GENERATION_ACTION = "embeddingActions:generateEpistemicNodeEmbedding";
|
|
1375
|
+
function readOptionalString2(value) {
|
|
1376
|
+
return typeof value === "string" && value.trim().length > 0 ? value : void 0;
|
|
1377
|
+
}
|
|
1228
1378
|
var internalGetByProject = internalQuery({
|
|
1229
1379
|
args: {
|
|
1230
1380
|
...optionalBeliefScopeArgs,
|
|
@@ -1259,7 +1409,7 @@ var internalGetByProject = internalQuery({
|
|
|
1259
1409
|
let filtered = nodes.filter(
|
|
1260
1410
|
(node) => canAudienceClassAccess(
|
|
1261
1411
|
viewerClass,
|
|
1262
|
-
resolveAudienceClass(node.audienceLabel, "internal")
|
|
1412
|
+
resolveAudienceClass(readOptionalString2(node.audienceLabel), "internal")
|
|
1263
1413
|
)
|
|
1264
1414
|
);
|
|
1265
1415
|
if (args.status) {
|
|
@@ -1298,15 +1448,18 @@ var internalGetByTopic = internalQuery({
|
|
|
1298
1448
|
});
|
|
1299
1449
|
const resolveAudienceClass = createBeliefAudienceResolver(registryRows);
|
|
1300
1450
|
const viewerClass = resolveAudienceClass(audienceMode, "public");
|
|
1301
|
-
const
|
|
1451
|
+
const query = ctx.db.query("epistemicNodes").withIndex(
|
|
1302
1452
|
"by_topic_type",
|
|
1303
1453
|
(q) => q.eq("topicId", args.topicId).eq("nodeType", "belief")
|
|
1304
1454
|
);
|
|
1305
|
-
const nodes = await
|
|
1455
|
+
const nodes = (await query.order("desc").take(scanLimit)).flatMap((row) => {
|
|
1456
|
+
const node = readBeliefNodeView(row);
|
|
1457
|
+
return node ? [node] : [];
|
|
1458
|
+
});
|
|
1306
1459
|
let filtered = nodes.filter(
|
|
1307
1460
|
(node) => canAudienceClassAccess(
|
|
1308
1461
|
viewerClass,
|
|
1309
|
-
resolveAudienceClass(node.audienceLabel, "internal")
|
|
1462
|
+
resolveAudienceClass(readOptionalString2(node.audienceLabel), "internal")
|
|
1310
1463
|
)
|
|
1311
1464
|
);
|
|
1312
1465
|
if (args.status) {
|
|
@@ -1340,11 +1493,16 @@ var internalGetById = internalQuery({
|
|
|
1340
1493
|
},
|
|
1341
1494
|
returns: permissiveReturn,
|
|
1342
1495
|
handler: async (ctx, args) => {
|
|
1343
|
-
const
|
|
1344
|
-
if (!
|
|
1496
|
+
const nodeId = ctx.db.normalizeId?.("epistemicNodes", args.beliefId);
|
|
1497
|
+
if (!nodeId) {
|
|
1498
|
+
return null;
|
|
1499
|
+
}
|
|
1500
|
+
const node = await ctx.db.get(nodeId);
|
|
1501
|
+
const beliefNode = readBeliefNodeView(node);
|
|
1502
|
+
if (!beliefNode) {
|
|
1345
1503
|
return null;
|
|
1346
1504
|
}
|
|
1347
|
-
return flattenBeliefNode(
|
|
1505
|
+
return flattenBeliefNode(beliefNode);
|
|
1348
1506
|
}
|
|
1349
1507
|
});
|
|
1350
1508
|
var internalCreate = internalMutation({
|
|
@@ -1387,171 +1545,235 @@ var internalCreate = internalMutation({
|
|
|
1387
1545
|
)
|
|
1388
1546
|
},
|
|
1389
1547
|
returns: permissiveReturn,
|
|
1390
|
-
handler: async (ctx, args) =>
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
mutationName: "epistemicBeliefs.internalCreate"
|
|
1415
|
-
});
|
|
1416
|
-
const normalizedBeliefType = await assertSchemaEnumValue(ctx, {
|
|
1417
|
-
category: "belief_type",
|
|
1418
|
-
value: args.beliefType,
|
|
1419
|
-
tenantId: scope.tenantId,
|
|
1420
|
-
context: "epistemicBeliefs.internalCreate"
|
|
1421
|
-
});
|
|
1422
|
-
const globalId = generateGlobalId();
|
|
1423
|
-
const contentHash = generateContentHash(args.formulation);
|
|
1424
|
-
const requestedConfidence = args.confidence;
|
|
1425
|
-
const seedOpinion = {
|
|
1426
|
-
opinion_b: 0,
|
|
1427
|
-
opinion_d: 0,
|
|
1428
|
-
opinion_u: 1,
|
|
1429
|
-
opinion_a: baseRate
|
|
1430
|
-
};
|
|
1431
|
-
const nodeId = await insertEpistemicNode(ctx, {
|
|
1548
|
+
handler: async (ctx, args) => await createInternalBelief(ctx, args)
|
|
1549
|
+
});
|
|
1550
|
+
async function createInternalBelief(ctx, args) {
|
|
1551
|
+
const now = Date.now();
|
|
1552
|
+
const baseRate = assertBaseRateInRange(args.baseRate ?? 0.5);
|
|
1553
|
+
const topicNode = await resolveInternalCreateTopicAnchor(ctx, args);
|
|
1554
|
+
const anchoredScope = scopeFromTopicAnchor(topicNode);
|
|
1555
|
+
const scope = {
|
|
1556
|
+
...anchoredScope,
|
|
1557
|
+
topicId: anchoredScope.topicId
|
|
1558
|
+
};
|
|
1559
|
+
assertInternalCreateScope(args, scope);
|
|
1560
|
+
const normalizedBeliefType = await assertSchemaEnumValue(ctx, {
|
|
1561
|
+
category: "belief_type",
|
|
1562
|
+
value: args.beliefType,
|
|
1563
|
+
tenantId: scope.tenantId,
|
|
1564
|
+
context: "epistemicBeliefs.internalCreate"
|
|
1565
|
+
});
|
|
1566
|
+
const seedOpinion = buildSeedOpinion(baseRate);
|
|
1567
|
+
const globalId = generateGlobalId();
|
|
1568
|
+
const nodeId = await insertEpistemicNode(
|
|
1569
|
+
ctx,
|
|
1570
|
+
buildInternalBeliefNode({
|
|
1571
|
+
args,
|
|
1432
1572
|
globalId,
|
|
1433
|
-
|
|
1434
|
-
|
|
1573
|
+
normalizedBeliefType,
|
|
1574
|
+
now,
|
|
1575
|
+
scope,
|
|
1576
|
+
seedOpinion
|
|
1577
|
+
})
|
|
1578
|
+
);
|
|
1579
|
+
await insertInternalBeliefConfidence(ctx, {
|
|
1580
|
+
args,
|
|
1581
|
+
baseRate,
|
|
1582
|
+
nodeId,
|
|
1583
|
+
now,
|
|
1584
|
+
seedOpinion
|
|
1585
|
+
});
|
|
1586
|
+
await createRequiredBeliefTopicEdge(ctx, {
|
|
1587
|
+
beliefGlobalId: globalId,
|
|
1588
|
+
topicNode,
|
|
1589
|
+
createdBy: args.userId
|
|
1590
|
+
});
|
|
1591
|
+
await scheduleInternalBeliefSideEffects(ctx, {
|
|
1592
|
+
args,
|
|
1593
|
+
baseRate,
|
|
1594
|
+
nodeId,
|
|
1595
|
+
now,
|
|
1596
|
+
scope,
|
|
1597
|
+
seedOpinion
|
|
1598
|
+
});
|
|
1599
|
+
return { nodeId };
|
|
1600
|
+
}
|
|
1601
|
+
async function resolveInternalCreateTopicAnchor(ctx, args) {
|
|
1602
|
+
const topicRef = readTopicNodeRef(args);
|
|
1603
|
+
if (!topicRef) {
|
|
1604
|
+
throw new Error(
|
|
1605
|
+
"Belief creation requires topicGlobalId or topicNodeId for a topic node in epistemicNodes."
|
|
1606
|
+
);
|
|
1607
|
+
}
|
|
1608
|
+
return await resolveRequiredTopicAnchor(ctx, topicRef);
|
|
1609
|
+
}
|
|
1610
|
+
function assertInternalCreateScope(args, scope) {
|
|
1611
|
+
assertWorkspaceScopedEpistemicNodeScope({
|
|
1612
|
+
scope,
|
|
1613
|
+
nodeType: "belief",
|
|
1614
|
+
mutationName: "epistemicBeliefs.internalCreate"
|
|
1615
|
+
});
|
|
1616
|
+
assertTenantPackWorkspaceMutationAllowed({
|
|
1617
|
+
runtime: resolveRuntimePackMutationContext(args),
|
|
1618
|
+
target: {
|
|
1435
1619
|
tenantId: scope.tenantId,
|
|
1436
1620
|
workspaceId: scope.workspaceId,
|
|
1437
1621
|
nodeType: "belief",
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1622
|
+
epistemicLayer: "L3"
|
|
1623
|
+
},
|
|
1624
|
+
mutationName: "epistemicBeliefs.internalCreate"
|
|
1625
|
+
});
|
|
1626
|
+
}
|
|
1627
|
+
function buildSeedOpinion(baseRate) {
|
|
1628
|
+
return {
|
|
1629
|
+
opinion_b: 0,
|
|
1630
|
+
opinion_d: 0,
|
|
1631
|
+
opinion_u: 1,
|
|
1632
|
+
opinion_a: baseRate
|
|
1633
|
+
};
|
|
1634
|
+
}
|
|
1635
|
+
function buildInternalBeliefNode(args) {
|
|
1636
|
+
return {
|
|
1637
|
+
globalId: args.globalId,
|
|
1638
|
+
topicId: args.scope.topicId,
|
|
1639
|
+
projectId: args.scope.projectId,
|
|
1640
|
+
tenantId: args.scope.tenantId,
|
|
1641
|
+
workspaceId: args.scope.workspaceId,
|
|
1642
|
+
nodeType: "belief",
|
|
1643
|
+
canonicalText: args.args.formulation,
|
|
1644
|
+
contentHash: generateContentHash(args.args.formulation),
|
|
1645
|
+
status: "active",
|
|
1646
|
+
epistemicLayer: "L3",
|
|
1647
|
+
sourceType: args.args.userId.startsWith("agent:") ? "ai_generated" : "human",
|
|
1648
|
+
...args.normalizedBeliefType ? { beliefType: args.normalizedBeliefType } : {},
|
|
1649
|
+
createdAt: args.now,
|
|
1650
|
+
updatedAt: args.now,
|
|
1651
|
+
createdBy: args.args.userId,
|
|
1652
|
+
...args.seedOpinion,
|
|
1653
|
+
tupleContradicted: false,
|
|
1654
|
+
metadata: buildInternalBeliefMetadata(args.args, args.normalizedBeliefType)
|
|
1655
|
+
};
|
|
1656
|
+
}
|
|
1657
|
+
function buildInternalBeliefMetadata(args, normalizedBeliefType) {
|
|
1658
|
+
return {
|
|
1659
|
+
...args.confidence ? { confidence: args.confidence } : {},
|
|
1660
|
+
tupleContradicted: false,
|
|
1661
|
+
rationale: args.rationale || "",
|
|
1662
|
+
topic: args.topic || args.pillar || "",
|
|
1663
|
+
pillar: args.pillar || args.topic || "",
|
|
1664
|
+
category: args.category || "",
|
|
1665
|
+
subcategory: args.subcategory || "",
|
|
1666
|
+
categoryIcon: args.categoryIcon || "",
|
|
1667
|
+
sprintId: args.sprintId,
|
|
1668
|
+
sourceBeliefIds: args.sourceBeliefIds || [],
|
|
1669
|
+
criticality: args.criticality || "unanalyzed",
|
|
1670
|
+
...normalizedBeliefType ? { beliefType: normalizedBeliefType } : {},
|
|
1671
|
+
supportingEvidenceIds: [],
|
|
1672
|
+
contradictingEvidenceIds: [],
|
|
1673
|
+
testingQuestionIds: [],
|
|
1674
|
+
linkedInsightIds: [],
|
|
1675
|
+
...isRecord2(args.extraMetadata) ? args.extraMetadata : {}
|
|
1676
|
+
};
|
|
1677
|
+
}
|
|
1678
|
+
function isRecord2(value) {
|
|
1679
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1680
|
+
}
|
|
1681
|
+
async function insertInternalBeliefConfidence(ctx, args) {
|
|
1682
|
+
await ctx.db.insert(
|
|
1683
|
+
"beliefConfidence",
|
|
1684
|
+
buildBeliefConfidenceRow({
|
|
1685
|
+
beliefId: args.nodeId,
|
|
1686
|
+
belief: args.seedOpinion.opinion_b,
|
|
1687
|
+
disbelief: args.seedOpinion.opinion_d,
|
|
1688
|
+
uncertainty: args.seedOpinion.opinion_u,
|
|
1689
|
+
baseRate: args.baseRate,
|
|
1690
|
+
trigger: "initial",
|
|
1691
|
+
rationale: "LKC-2 mandatory prior: seeded vacuous opinion at belief creation.",
|
|
1692
|
+
assessedBy: args.args.userId,
|
|
1693
|
+
assessedAt: args.now,
|
|
1694
|
+
slOperator: "prior_seed"
|
|
1695
|
+
})
|
|
1696
|
+
);
|
|
1697
|
+
}
|
|
1698
|
+
async function scheduleInternalBeliefSideEffects(ctx, args) {
|
|
1699
|
+
await scheduleInternalNeo4jSync(ctx, args.nodeId);
|
|
1700
|
+
await insertInternalBeliefAudit(ctx, args);
|
|
1701
|
+
await scheduleInternalBeliefEmbedding(ctx, args);
|
|
1702
|
+
await scheduleInternalBeliefCategorization(ctx, args);
|
|
1703
|
+
await markBeliefGraphDirty(ctx, {
|
|
1704
|
+
projectId: args.scope.projectId,
|
|
1705
|
+
topicId: String(args.scope.topicId)
|
|
1706
|
+
});
|
|
1707
|
+
}
|
|
1708
|
+
async function scheduleInternalNeo4jSync(ctx, nodeId) {
|
|
1709
|
+
await ctx.scheduler.runAfter(0, internal.neo4jSync.syncNodeToNeo4j, {
|
|
1710
|
+
nodeId,
|
|
1711
|
+
operation: "upsert"
|
|
1712
|
+
});
|
|
1713
|
+
}
|
|
1714
|
+
async function insertInternalBeliefAudit(ctx, args) {
|
|
1715
|
+
await ctx.db.insert("epistemicAudit", {
|
|
1716
|
+
entityType: "belief",
|
|
1717
|
+
entityId: args.nodeId,
|
|
1718
|
+
changeType: "created",
|
|
1719
|
+
changedAt: args.now,
|
|
1720
|
+
changedBy: args.args.userId,
|
|
1721
|
+
isAgent: false,
|
|
1722
|
+
newState: {
|
|
1723
|
+
formulation: args.args.formulation,
|
|
1724
|
+
baseRate: args.baseRate,
|
|
1725
|
+
confidence: args.args.confidence,
|
|
1726
|
+
opinion: {
|
|
1727
|
+
b: args.seedOpinion.opinion_b,
|
|
1728
|
+
d: args.seedOpinion.opinion_d,
|
|
1729
|
+
u: args.seedOpinion.opinion_u,
|
|
1730
|
+
a: args.seedOpinion.opinion_a
|
|
1514
1731
|
},
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
}
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1732
|
+
tupleContradicted: false,
|
|
1733
|
+
source: "internal"
|
|
1734
|
+
},
|
|
1735
|
+
projectId: args.scope.projectId,
|
|
1736
|
+
topicId: String(args.scope.topicId)
|
|
1737
|
+
});
|
|
1738
|
+
}
|
|
1739
|
+
async function scheduleInternalBeliefEmbedding(ctx, args) {
|
|
1740
|
+
if (!(args.scope.projectId || args.scope.topicId)) {
|
|
1741
|
+
return;
|
|
1742
|
+
}
|
|
1743
|
+
await ctx.scheduler.runAfter(0, EMBEDDING_GENERATION_ACTION, {
|
|
1744
|
+
nodeId: args.nodeId,
|
|
1745
|
+
projectId: args.scope.projectId,
|
|
1746
|
+
topicId: args.scope.topicId ? String(args.scope.topicId) : void 0,
|
|
1747
|
+
createdBy: args.args.userId,
|
|
1748
|
+
nodeType: "belief",
|
|
1749
|
+
text: buildBeliefEmbeddingText(args.args),
|
|
1750
|
+
...args.args.confidence ? { confidence: numericRequestedConfidence(args.args.confidence) } : {}
|
|
1751
|
+
});
|
|
1752
|
+
}
|
|
1753
|
+
function buildBeliefEmbeddingText(args) {
|
|
1754
|
+
return args.rationale ? `${args.formulation}
|
|
1529
1755
|
|
|
1530
|
-
Rationale: ${args.rationale}` : args.formulation
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
);
|
|
1536
|
-
}
|
|
1537
|
-
if (normalizePillar(args.pillar || args.topic) === "other" && (scope.projectId || scope.topicId)) {
|
|
1538
|
-
await ctx.scheduler.runAfter(
|
|
1539
|
-
2500,
|
|
1540
|
-
"beliefCategorization:autoCategorizeBelief",
|
|
1541
|
-
{
|
|
1542
|
-
nodeId,
|
|
1543
|
-
projectId: scope.projectId,
|
|
1544
|
-
topicId: String(scope.topicId)
|
|
1545
|
-
}
|
|
1546
|
-
);
|
|
1547
|
-
}
|
|
1548
|
-
await markBeliefGraphDirty(ctx, {
|
|
1549
|
-
projectId: scope.projectId,
|
|
1550
|
-
topicId: String(scope.topicId)
|
|
1551
|
-
});
|
|
1552
|
-
return { nodeId };
|
|
1756
|
+
Rationale: ${args.rationale}` : args.formulation;
|
|
1757
|
+
}
|
|
1758
|
+
function numericRequestedConfidence(confidence) {
|
|
1759
|
+
if (confidence === "high") {
|
|
1760
|
+
return 0.8;
|
|
1553
1761
|
}
|
|
1554
|
-
|
|
1762
|
+
if (confidence === "low") {
|
|
1763
|
+
return 0.3;
|
|
1764
|
+
}
|
|
1765
|
+
return 0.5;
|
|
1766
|
+
}
|
|
1767
|
+
async function scheduleInternalBeliefCategorization(ctx, args) {
|
|
1768
|
+
if (normalizePillar(args.args.pillar || args.args.topic) !== "other" || !(args.scope.projectId || args.scope.topicId)) {
|
|
1769
|
+
return;
|
|
1770
|
+
}
|
|
1771
|
+
await ctx.scheduler.runAfter(2500, BELIEF_CATEGORIZATION_ACTION, {
|
|
1772
|
+
nodeId: args.nodeId,
|
|
1773
|
+
projectId: args.scope.projectId,
|
|
1774
|
+
topicId: String(args.scope.topicId)
|
|
1775
|
+
});
|
|
1776
|
+
}
|
|
1555
1777
|
|
|
1556
1778
|
export { internalCreate, internalGetActive, internalGetById, internalGetByProject, internalGetByTopic };
|
|
1557
1779
|
//# sourceMappingURL=epistemicBeliefs.internal.js.map
|