@lucern/graph-primitives 1.0.28 → 1.0.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{beliefDecay-DZ6tkLYq.d.ts → beliefDecay-BmkEk5OJ.d.ts} +3 -3
- package/dist/beliefDecay.d.ts +1 -1
- package/dist/beliefDecay.js +448 -314
- package/dist/beliefDecay.js.map +1 -1
- package/dist/{beliefEvidenceLinks-CWOXxxJg.d.ts → beliefEvidenceLinks-BzfjON_6.d.ts} +13 -13
- package/dist/beliefEvidenceLinks.d.ts +1 -1
- package/dist/beliefEvidenceLinks.js +843 -624
- package/dist/beliefEvidenceLinks.js.map +1 -1
- package/dist/beliefEvidenceLinks.operational.d.ts +7 -5
- package/dist/beliefEvidenceLinks.operational.js +91 -18
- package/dist/beliefEvidenceLinks.operational.js.map +1 -1
- package/dist/beliefLifecycle.js.map +1 -1
- package/dist/confidencePropagationDispatch.d.ts +28 -27
- package/dist/confidencePropagationDispatch.js +157 -99
- package/dist/confidencePropagationDispatch.js.map +1 -1
- package/dist/{contradictions-51VLsESq.d.ts → contradictions-BATPuZTL.d.ts} +10 -10
- package/dist/contradictions.d.ts +1 -1
- package/dist/contradictions.js +398 -228
- package/dist/contradictions.js.map +1 -1
- package/dist/convex.d.ts +65 -30
- package/dist/convex.js +7 -3
- package/dist/convex.js.map +1 -1
- package/dist/debug.js.map +1 -1
- package/dist/edgeValidation.js +293 -85
- package/dist/edgeValidation.js.map +1 -1
- package/dist/edges/contains.d.ts +1 -1
- package/dist/edges/contains.js.map +1 -1
- package/dist/edges/contradicts.d.ts +1 -1
- package/dist/edges/contradicts.js.map +1 -1
- package/dist/edges/{dependsOn.d.ts → depends-on.d.ts} +1 -1
- package/dist/edges/{dependsOn.js → depends-on.js} +4 -4
- package/dist/edges/depends-on.js.map +1 -0
- package/dist/edges/{derivedFrom.d.ts → derived-from.d.ts} +1 -1
- package/dist/edges/{derivedFrom.js → derived-from.js} +3 -3
- package/dist/edges/derived-from.js.map +1 -0
- package/dist/edges/elaborates.d.ts +1 -1
- package/dist/edges/elaborates.js.map +1 -1
- package/dist/edges/index.d.ts +7 -3
- package/dist/edges/index.js +7 -4
- package/dist/edges/index.js.map +1 -1
- package/dist/edges/informs.d.ts +1 -1
- package/dist/edges/informs.js.map +1 -1
- package/dist/edges/{propagationTypes.d.ts → propagation-types.d.ts} +14 -14
- package/dist/edges/{propagationTypes.js → propagation-types.js} +3 -3
- package/dist/edges/propagation-types.js.map +1 -0
- package/dist/edges/refutes.d.ts +1 -1
- package/dist/edges/refutes.js.map +1 -1
- package/dist/edges/supports.d.ts +1 -1
- package/dist/edges/supports.js.map +1 -1
- package/dist/edges/tests.d.ts +1 -1
- package/dist/edges/tests.js.map +1 -1
- package/dist/edges/utils.d.ts +1 -1
- package/dist/edges/utils.js.map +1 -1
- package/dist/embeddingTrigger.d.ts +14 -6
- package/dist/embeddingTrigger.js +11 -14
- package/dist/embeddingTrigger.js.map +1 -1
- package/dist/{entityBridge-DMaKooYn.d.ts → entityBridge-BhVDM3pc.d.ts} +5 -5
- package/dist/entityBridge.d.ts +1 -1
- package/dist/entityBridge.js +602 -225
- package/dist/entityBridge.js.map +1 -1
- package/dist/entityCanonicalMatch.d.ts +14 -12
- package/dist/entityCanonicalMatch.js.map +1 -1
- package/dist/{entityLifecycle-CvgSK5FV.d.ts → entityLifecycle-BsfCz9pS.d.ts} +5 -9
- package/dist/entityLifecycle.d.ts +1 -1
- package/dist/entityLifecycle.js +857 -515
- package/dist/entityLifecycle.js.map +1 -1
- package/dist/{entityValidation-KLZ_Xl2D.d.ts → entityValidation-B1yNEHJx.d.ts} +7 -6
- package/dist/entityValidation.d.ts +3 -1
- package/dist/entityValidation.js +60 -8
- package/dist/entityValidation.js.map +1 -1
- package/dist/{epistemicAnswers-C5ib4z6_.d.ts → epistemicAnswers-f47YMu9U.d.ts} +6 -6
- package/dist/epistemicAnswers.d.ts +1 -1
- package/dist/epistemicAnswers.js +587 -545
- package/dist/epistemicAnswers.js.map +1 -1
- package/dist/epistemicBeliefs.admin.d.ts +8 -8
- package/dist/epistemicBeliefs.admin.js +366 -203
- package/dist/epistemicBeliefs.admin.js.map +1 -1
- package/dist/epistemicBeliefs.backfills.d.ts +8 -8
- package/dist/epistemicBeliefs.backfills.js +655 -308
- package/dist/epistemicBeliefs.backfills.js.map +1 -1
- package/dist/epistemicBeliefs.confidence.d.ts +19 -14
- package/dist/epistemicBeliefs.confidence.js +634 -423
- package/dist/epistemicBeliefs.confidence.js.map +1 -1
- package/dist/epistemicBeliefs.core.d.ts +6 -6
- package/dist/epistemicBeliefs.core.js +719 -411
- package/dist/epistemicBeliefs.core.js.map +1 -1
- package/dist/epistemicBeliefs.d.ts +11 -8
- package/dist/epistemicBeliefs.forkEvidence.d.ts +2 -0
- package/dist/epistemicBeliefs.forkEvidence.js +8 -28
- package/dist/epistemicBeliefs.forkEvidence.js.map +1 -1
- package/dist/epistemicBeliefs.helpers.d.ts +69 -74
- package/dist/epistemicBeliefs.helpers.js +359 -248
- package/dist/epistemicBeliefs.helpers.js.map +1 -1
- package/dist/epistemicBeliefs.internal.d.ts +5 -5
- package/dist/epistemicBeliefs.internal.js +1246 -1044
- package/dist/epistemicBeliefs.internal.js.map +1 -1
- package/dist/epistemicBeliefs.js +4922 -3608
- package/dist/epistemicBeliefs.js.map +1 -1
- package/dist/epistemicBeliefs.lifecycle.d.ts +5 -5
- package/dist/epistemicBeliefs.lifecycle.js +1137 -818
- package/dist/epistemicBeliefs.lifecycle.js.map +1 -1
- package/dist/epistemicBeliefs.links.d.ts +7 -7
- package/dist/epistemicBeliefs.links.js +408 -307
- package/dist/epistemicBeliefs.links.js.map +1 -1
- package/dist/epistemicBeliefs.queries.d.ts +4 -4
- package/dist/epistemicBeliefs.queries.js +175 -20
- package/dist/epistemicBeliefs.queries.js.map +1 -1
- package/dist/epistemicBeliefs.topicAnchor.d.ts +6 -4
- package/dist/epistemicBeliefs.topicAnchor.js +12 -5
- package/dist/epistemicBeliefs.topicAnchor.js.map +1 -1
- package/dist/epistemicContracts.d.ts +28 -3
- package/dist/epistemicContracts.evaluators.d.ts +2 -0
- package/dist/epistemicContracts.evaluators.js +1063 -613
- package/dist/epistemicContracts.evaluators.js.map +1 -1
- package/dist/epistemicContracts.handlers.d.ts +15 -32
- package/dist/epistemicContracts.handlers.js +2086 -1644
- package/dist/epistemicContracts.handlers.js.map +1 -1
- package/dist/epistemicContracts.js +1131 -672
- package/dist/epistemicContracts.js.map +1 -1
- package/dist/epistemicContracts.metrics.d.ts +2 -0
- package/dist/epistemicContracts.metrics.js +375 -158
- package/dist/epistemicContracts.metrics.js.map +1 -1
- package/dist/epistemicContracts.types.d.ts +87 -81
- package/dist/epistemicEdgeCreation.d.ts +2 -0
- package/dist/epistemicEdgeCreation.js +87 -16
- package/dist/epistemicEdgeCreation.js.map +1 -1
- package/dist/{epistemicEdges-BF-cn4i3.d.ts → epistemicEdges-BGBh0QSP.d.ts} +4 -7
- package/dist/epistemicEdges.d.ts +6 -5
- package/dist/epistemicEdges.handlers.d.ts +3 -3
- package/dist/epistemicEdges.handlers.js +129 -24
- package/dist/epistemicEdges.handlers.js.map +1 -1
- package/dist/epistemicEdges.helpers.d.ts +6 -4
- package/dist/epistemicEdges.helpers.js +37 -2
- package/dist/epistemicEdges.helpers.js.map +1 -1
- package/dist/epistemicEdges.js +1969 -1205
- package/dist/epistemicEdges.js.map +1 -1
- package/dist/epistemicEdges.mutations.d.ts +7 -7
- package/dist/epistemicEdges.mutations.js +960 -583
- package/dist/epistemicEdges.mutations.js.map +1 -1
- package/dist/epistemicEdges.queries.d.ts +16 -16
- package/dist/epistemicEdges.queries.js +639 -367
- package/dist/epistemicEdges.queries.js.map +1 -1
- package/dist/epistemicEdges.types.d.ts +10 -8
- package/dist/epistemicEvidence.d.ts +4 -1
- package/dist/epistemicEvidence.js +937 -536
- package/dist/epistemicEvidence.js.map +1 -1
- package/dist/epistemicEvidenceHelpers.d.ts +26 -10
- package/dist/epistemicEvidenceHelpers.js +239 -200
- package/dist/epistemicEvidenceHelpers.js.map +1 -1
- package/dist/epistemicEvidenceMutations.d.ts +8 -8
- package/dist/epistemicEvidenceMutations.js +844 -696
- package/dist/epistemicEvidenceMutations.js.map +1 -1
- package/dist/epistemicEvidenceQueries.d.ts +8 -8
- package/dist/epistemicEvidenceQueries.js +514 -238
- package/dist/epistemicEvidenceQueries.js.map +1 -1
- package/dist/epistemicHelpers.d.ts +4 -2
- package/dist/epistemicHelpers.js +308 -134
- package/dist/epistemicHelpers.js.map +1 -1
- package/dist/epistemicInsert.d.ts +16 -4
- package/dist/epistemicInsert.js +6 -3
- package/dist/epistemicInsert.js.map +1 -1
- package/dist/epistemicLayerRules.d.ts +10 -8
- package/dist/epistemicLayerRules.js +1 -5
- package/dist/epistemicLayerRules.js.map +1 -1
- package/dist/{epistemicLinking-CfE00tHJ.d.ts → epistemicLinking-CsCDv2cN.d.ts} +3 -3
- package/dist/epistemicLinking.d.ts +1 -1
- package/dist/epistemicLinking.js +177 -100
- package/dist/epistemicLinking.js.map +1 -1
- package/dist/epistemicNodeCreation.d.ts +2 -0
- package/dist/epistemicNodeCreation.js +203 -40
- package/dist/epistemicNodeCreation.js.map +1 -1
- package/dist/{epistemicNodes-BCQxpYx_.d.ts → epistemicNodes-CokAgBHg.d.ts} +3 -3
- package/dist/epistemicNodes.d.ts +3 -3
- package/dist/epistemicNodes.helpers.d.ts +24 -15
- package/dist/epistemicNodes.helpers.js.map +1 -1
- package/dist/epistemicNodes.internal.d.ts +6 -6
- package/dist/epistemicNodes.internal.js +389 -319
- package/dist/epistemicNodes.internal.js.map +1 -1
- package/dist/epistemicNodes.js +704 -508
- package/dist/epistemicNodes.js.map +1 -1
- package/dist/epistemicNodes.mutations.d.ts +6 -6
- package/dist/epistemicNodes.mutations.js +564 -467
- package/dist/epistemicNodes.mutations.js.map +1 -1
- package/dist/epistemicNodes.queries.d.ts +8 -8
- package/dist/epistemicNodes.queries.js +311 -314
- package/dist/epistemicNodes.queries.js.map +1 -1
- package/dist/epistemicNodes.validators.d.ts +2 -2
- package/dist/epistemicNodes.validators.js.map +1 -1
- package/dist/epistemicQuestions.conviction.d.ts +8 -8
- package/dist/epistemicQuestions.conviction.js +665 -484
- package/dist/epistemicQuestions.conviction.js.map +1 -1
- package/dist/epistemicQuestions.create.d.ts +4 -4
- package/dist/epistemicQuestions.create.js +640 -612
- package/dist/epistemicQuestions.create.js.map +1 -1
- package/dist/epistemicQuestions.d.ts +8 -5
- package/dist/epistemicQuestions.evidence.d.ts +2 -2
- package/dist/epistemicQuestions.evidence.js +475 -383
- package/dist/epistemicQuestions.evidence.js.map +1 -1
- package/dist/epistemicQuestions.helpers.d.ts +125 -24
- package/dist/epistemicQuestions.helpers.js +240 -209
- package/dist/epistemicQuestions.helpers.js.map +1 -1
- package/dist/epistemicQuestions.js +3474 -2823
- package/dist/epistemicQuestions.js.map +1 -1
- package/dist/epistemicQuestions.lifecycle.d.ts +2 -2
- package/dist/epistemicQuestions.lifecycle.js +607 -546
- package/dist/epistemicQuestions.lifecycle.js.map +1 -1
- package/dist/epistemicQuestions.queries.d.ts +12 -7
- package/dist/epistemicQuestions.queries.js +305 -244
- package/dist/epistemicQuestions.queries.js.map +1 -1
- package/dist/epistemicQuestions.sprint.d.ts +2 -2
- package/dist/epistemicQuestions.sprint.js +600 -394
- package/dist/epistemicQuestions.sprint.js.map +1 -1
- package/dist/epistemicQuestions.tail.d.ts +6 -6
- package/dist/epistemicQuestions.tail.js +572 -433
- package/dist/epistemicQuestions.tail.js.map +1 -1
- package/dist/{epistemicSources-dlKj58Jp.d.ts → epistemicSources-DQtaEkWs.d.ts} +4 -4
- package/dist/epistemicSources.d.ts +1 -1
- package/dist/epistemicSources.js +352 -312
- package/dist/epistemicSources.js.map +1 -1
- package/dist/evaluators/index.d.ts +8 -6
- package/dist/evaluators/index.js +399 -167
- package/dist/evaluators/index.js.map +1 -1
- package/dist/evaluators/lint-checker-evaluator.d.ts +16 -0
- package/dist/evaluators/{lintCheckerEvaluator.js → lint-checker-evaluator.js} +10 -5
- package/dist/evaluators/lint-checker-evaluator.js.map +1 -0
- package/dist/evaluators/{sentryCheckerEvaluator.d.ts → sentry-checker-evaluator.d.ts} +7 -2
- package/dist/evaluators/{sentryCheckerEvaluator.js → sentry-checker-evaluator.js} +3 -3
- package/dist/evaluators/sentry-checker-evaluator.js.map +1 -0
- package/dist/evaluators/shared.d.ts +2 -2
- package/dist/evaluators/shared.js +3 -1
- package/dist/evaluators/shared.js.map +1 -1
- package/dist/evaluators/{testRunnerEvaluator.d.ts → test-runner-evaluator.d.ts} +6 -1
- package/dist/evaluators/{testRunnerEvaluator.js → test-runner-evaluator.js} +6 -4
- package/dist/evaluators/test-runner-evaluator.js.map +1 -0
- package/dist/evaluators/tsc-checker-evaluator.d.ts +16 -0
- package/dist/evaluators/{tscCheckerEvaluator.js → tsc-checker-evaluator.js} +10 -5
- package/dist/evaluators/tsc-checker-evaluator.js.map +1 -0
- package/dist/graphTypes.js +6 -2
- package/dist/graphTypes.js.map +1 -1
- package/dist/helpers.d.ts +2 -0
- package/dist/helpers.js +313 -93
- package/dist/helpers.js.map +1 -1
- package/dist/{index-C-Kyd7hD.d.ts → index-DZxyC9Pb.d.ts} +7 -6
- package/dist/index.d.ts +87 -83
- package/dist/index.js +15677 -10594
- package/dist/index.js.map +1 -1
- package/dist/invariantEnforcement.d.ts +3 -3
- package/dist/invariantEnforcement.js.map +1 -1
- package/dist/logicalRoleInference.d.ts +2 -0
- package/dist/logicalRoleInference.js +1 -1
- package/dist/logicalRoleInference.js.map +1 -1
- package/dist/matcherFeedbackUtils.d.ts +2 -2
- package/dist/matcherFeedbackUtils.js.map +1 -1
- package/dist/{ontology-matching-C6rrz2VP.d.ts → ontology-matching-C-mYFrir.d.ts} +16 -16
- package/dist/ontology-matching.d.ts +1 -1
- package/dist/{ontologyApproval-CFYmqKmk.d.ts → ontologyApproval-BVt0feJi.d.ts} +10 -10
- package/dist/ontologyApproval.d.ts +1 -1
- package/dist/ontologyApproval.js +7 -1
- package/dist/ontologyApproval.js.map +1 -1
- package/dist/ontologyDefinitions.d.ts +14 -24
- package/dist/ontologyDefinitions.js +269 -34
- package/dist/ontologyDefinitions.js.map +1 -1
- package/dist/ontologyHelpers.d.ts +13 -13
- package/dist/ontologyHelpers.js.map +1 -1
- package/dist/{ontologyRegistry-B67rPJ16.d.ts → ontologyRegistry-CljS-ENv.d.ts} +2 -2
- package/dist/ontologyRegistry.d.ts +1 -1
- package/dist/ontologyRegistry.js +34 -6
- package/dist/ontologyRegistry.js.map +1 -1
- package/dist/{projectionReconciliation-jww2fBI0.d.ts → projectionReconciliation-DnrSgHSQ.d.ts} +4 -4
- package/dist/projectionReconciliation.d.ts +1 -1
- package/dist/projectionReconciliation.js +57 -10
- package/dist/projectionReconciliation.js.map +1 -1
- package/dist/{projectionStaleness-CmdbpjVK.d.ts → projectionStaleness-C8ImQ2zP.d.ts} +17 -17
- package/dist/projectionStaleness.d.ts +1 -1
- package/dist/projectionStaleness.js +8 -2
- package/dist/projectionStaleness.js.map +1 -1
- package/dist/proof-attestation.json +1 -1
- package/dist/{questionEvidenceLinks-DFlyPpAj.d.ts → questionEvidenceLinks-_nPRa-LY.d.ts} +10 -10
- package/dist/questionEvidenceLinks.d.ts +1 -1
- package/dist/questionEvidenceLinks.js +564 -347
- package/dist/questionEvidenceLinks.js.map +1 -1
- package/dist/{resolverTypes-CC8Ea2E2.d.ts → resolverTypes-BOXPxLET.d.ts} +8 -7
- package/dist/resolverTypes.d.ts +4 -2
- package/dist/{resolvers-Br1a6eLV.d.ts → resolvers-B1TIBmRO.d.ts} +3 -1
- package/dist/resolvers.d.ts +5 -3
- package/dist/resolvers.js +121 -77
- package/dist/resolvers.js.map +1 -1
- package/dist/scopeResolverCompat.d.ts +10 -7
- package/dist/scopeResolverCompat.js +106 -123
- package/dist/scopeResolverCompat.js.map +1 -1
- package/dist/{text-matching-DNg4M5Wd.d.ts → text-matching-DzFooju6.d.ts} +7 -7
- package/dist/text-matching.d.ts +1 -1
- package/dist/topicOntologyResolver.d.ts +22 -21
- package/dist/topicOntologyResolver.js +54 -32
- package/dist/topicOntologyResolver.js.map +1 -1
- package/dist/topicProjectOverlay.d.ts +30 -20
- package/dist/topicProjectOverlay.js +120 -76
- package/dist/topicProjectOverlay.js.map +1 -1
- package/dist/{topicScope-7zhyeGl7.d.ts → topicScope-DJVa0mLa.d.ts} +22 -7
- package/dist/topicScope.d.ts +3 -1
- package/dist/topicScope.js +104 -119
- package/dist/topicScope.js.map +1 -1
- package/dist/workflowBridge.d.ts +26 -15
- package/dist/workflowBridge.js +140 -144
- package/dist/workflowBridge.js.map +1 -1
- package/dist/workspaceIsolation.d.ts +14 -12
- package/dist/workspaceIsolation.js +108 -122
- package/dist/workspaceIsolation.js.map +1 -1
- package/package.json +4 -4
- package/dist/edges/dependsOn.js.map +0 -1
- package/dist/edges/derivedFrom.js.map +0 -1
- package/dist/edges/propagationTypes.js.map +0 -1
- package/dist/evaluators/lintCheckerEvaluator.d.ts +0 -11
- package/dist/evaluators/lintCheckerEvaluator.js.map +0 -1
- package/dist/evaluators/sentryCheckerEvaluator.js.map +0 -1
- package/dist/evaluators/testRunnerEvaluator.js.map +0 -1
- package/dist/evaluators/tscCheckerEvaluator.d.ts +0 -11
- package/dist/evaluators/tscCheckerEvaluator.js.map +0 -1
- package/dist/{epistemicQuestions-bwHd2FWE.d.ts → epistemicQuestions-Do1fhYm5.d.ts} +4 -4
|
@@ -1,13 +1,17 @@
|
|
|
1
|
-
import { v } from 'convex/values';
|
|
2
|
-
import { canAudienceClassAccess, normalizeAudienceKey, classFromAudienceKey } from '@lucern/access-control/audience';
|
|
3
1
|
import { checkScopeAccess } from '@lucern/access-control/access';
|
|
4
|
-
import {
|
|
5
|
-
import { componentsGeneric, queryGeneric, internalQueryGeneric, anyApi } from 'convex/server';
|
|
2
|
+
import { canAudienceClassAccess, normalizeAudienceKey, classFromAudienceKey } from '@lucern/access-control/audience';
|
|
6
3
|
import { listAudienceRegistryRows } from '@lucern/access-control/audienceRegistry';
|
|
4
|
+
import { permissiveReturn } from '@lucern/contracts/schema-helpers/validators';
|
|
5
|
+
import { v } from 'convex/values';
|
|
6
|
+
import { unsafeConvexAnyApi } from '@lucern/contracts/convex/unsafeAnyApi';
|
|
7
|
+
import { componentsGeneric, queryGeneric, internalQueryGeneric } from 'convex/server';
|
|
7
8
|
import '@lucern/contracts/schema-helpers/spine/tables/epistemicNodes';
|
|
8
9
|
|
|
9
10
|
// src/epistemicEvidenceQueries.ts
|
|
10
|
-
var
|
|
11
|
+
var unsafeApi = unsafeConvexAnyApi(
|
|
12
|
+
"graph-primitives top-level module bundle lacks a committed Convex _generated/api surface"
|
|
13
|
+
);
|
|
14
|
+
var api = unsafeApi;
|
|
11
15
|
componentsGeneric();
|
|
12
16
|
var internalQuery = internalQueryGeneric;
|
|
13
17
|
var query = queryGeneric;
|
|
@@ -42,6 +46,10 @@ function readStringArray(value) {
|
|
|
42
46
|
function readMetadata(topic) {
|
|
43
47
|
return topic.metadata && typeof topic.metadata === "object" ? topic.metadata : {};
|
|
44
48
|
}
|
|
49
|
+
function omitMetadataKey(metadata, key) {
|
|
50
|
+
const { [key]: _omitted, ...rest } = metadata;
|
|
51
|
+
return rest;
|
|
52
|
+
}
|
|
45
53
|
function readLegacyProjectId(value) {
|
|
46
54
|
if (!value) {
|
|
47
55
|
return;
|
|
@@ -122,9 +130,12 @@ async function resolveTopicDoc(ctx, scopeId) {
|
|
|
122
130
|
);
|
|
123
131
|
}
|
|
124
132
|
try {
|
|
125
|
-
const topic = await ctx.runQuery(
|
|
126
|
-
|
|
127
|
-
|
|
133
|
+
const topic = await ctx.runQuery(
|
|
134
|
+
api.topics.getByLegacyScopeId,
|
|
135
|
+
{
|
|
136
|
+
projectId: String(scopeId)
|
|
137
|
+
}
|
|
138
|
+
);
|
|
128
139
|
if (topic?.name !== void 0 && topic?.type !== void 0) {
|
|
129
140
|
return topic;
|
|
130
141
|
}
|
|
@@ -144,8 +155,18 @@ function materializeTopicProjectOverlay(topic, idMode = "legacy") {
|
|
|
144
155
|
const outwardId = idMode === "topic" ? topicId : storageProjectId;
|
|
145
156
|
const visibility = coerceVisibility(topic.visibility) || coerceVisibility(metadata.visibility) || "private";
|
|
146
157
|
const status = coerceStatus(topic.status) || coerceStatus(metadata.status) || "active";
|
|
147
|
-
|
|
148
|
-
|
|
158
|
+
let createdAt = 0;
|
|
159
|
+
if (typeof topic.createdAt === "number") {
|
|
160
|
+
createdAt = topic.createdAt;
|
|
161
|
+
} else if (typeof topic._creationTime === "number") {
|
|
162
|
+
createdAt = topic._creationTime;
|
|
163
|
+
}
|
|
164
|
+
let updatedAt = createdAt;
|
|
165
|
+
if (typeof topic.updatedAt === "number") {
|
|
166
|
+
updatedAt = topic.updatedAt;
|
|
167
|
+
} else if (typeof metadata.updatedAt === "number") {
|
|
168
|
+
updatedAt = metadata.updatedAt;
|
|
169
|
+
}
|
|
149
170
|
return {
|
|
150
171
|
...metadata,
|
|
151
172
|
_id: outwardId,
|
|
@@ -214,90 +235,113 @@ async function patchTopicProjectOverlay(ctx, scopeId, value) {
|
|
|
214
235
|
if (!topic) {
|
|
215
236
|
return null;
|
|
216
237
|
}
|
|
217
|
-
const
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
238
|
+
const plan = buildTopicProjectOverlayPatchPlan(topic, value);
|
|
239
|
+
await applyTopicProjectOverlayPatch(ctx, topic, plan);
|
|
240
|
+
return materializeTopicProjectOverlay({
|
|
241
|
+
...topic,
|
|
242
|
+
...plan.patch,
|
|
243
|
+
metadata: plan.nextMetadata
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
function buildTopicProjectOverlayPatchPlan(topic, value) {
|
|
247
|
+
const plan = {
|
|
248
|
+
nextMetadata: { ...readMetadata(topic) },
|
|
249
|
+
patch: {},
|
|
250
|
+
topicUpdateArgs: {
|
|
251
|
+
id: String(topic._id)
|
|
252
|
+
}
|
|
221
253
|
};
|
|
222
254
|
for (const [key, rawValue] of Object.entries(value)) {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
255
|
+
applyTopicProjectOverlayPatchEntry(plan, key, rawValue);
|
|
256
|
+
}
|
|
257
|
+
plan.patch.updatedAt = Date.now();
|
|
258
|
+
plan.patch.metadata = plan.nextMetadata;
|
|
259
|
+
plan.topicUpdateArgs.metadata = plan.nextMetadata;
|
|
260
|
+
return plan;
|
|
261
|
+
}
|
|
262
|
+
function applyTopicProjectOverlayPatchEntry(plan, key, rawValue) {
|
|
263
|
+
switch (key) {
|
|
264
|
+
case "_id":
|
|
265
|
+
case "projectId":
|
|
266
|
+
case "topicId":
|
|
267
|
+
case "legacyProjectId":
|
|
268
|
+
case "storageProjectId":
|
|
269
|
+
case "updatedAt":
|
|
270
|
+
case "createdAt":
|
|
271
|
+
return;
|
|
272
|
+
case "name":
|
|
273
|
+
case "description":
|
|
274
|
+
plan.patch[key] = rawValue;
|
|
275
|
+
plan.topicUpdateArgs[key] = rawValue;
|
|
276
|
+
return;
|
|
277
|
+
case "tenantId":
|
|
278
|
+
case "workspaceId":
|
|
279
|
+
case "ownerId":
|
|
280
|
+
throw new Error(
|
|
281
|
+
`patchTopicProjectOverlay cannot mutate ${key} via component-owned topics`
|
|
282
|
+
);
|
|
283
|
+
case "status":
|
|
284
|
+
applyTopicStatusPatch(plan, rawValue);
|
|
285
|
+
return;
|
|
286
|
+
case "visibility":
|
|
287
|
+
applyTopicVisibilityPatch(plan, rawValue);
|
|
288
|
+
return;
|
|
289
|
+
case "type":
|
|
290
|
+
applyTopicProjectTypePatch(plan, rawValue);
|
|
291
|
+
return;
|
|
292
|
+
default:
|
|
293
|
+
applyTopicMetadataPatch(plan, key, rawValue);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
function applyTopicStatusPatch(plan, rawValue) {
|
|
297
|
+
const status = coerceStatus(rawValue);
|
|
298
|
+
if (status) {
|
|
299
|
+
plan.patch.status = status;
|
|
300
|
+
plan.topicUpdateArgs.status = status;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
function applyTopicVisibilityPatch(plan, rawValue) {
|
|
304
|
+
const visibility = coerceVisibility(rawValue);
|
|
305
|
+
if (visibility) {
|
|
306
|
+
plan.patch.visibility = visibility;
|
|
307
|
+
plan.topicUpdateArgs.visibility = visibility;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
function applyTopicProjectTypePatch(plan, rawValue) {
|
|
311
|
+
const projectType = readNonEmptyString(rawValue);
|
|
312
|
+
if (projectType) {
|
|
313
|
+
plan.nextMetadata.projectType = projectType;
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
plan.nextMetadata = omitMetadataKey(plan.nextMetadata, "projectType");
|
|
317
|
+
}
|
|
318
|
+
function applyTopicMetadataPatch(plan, key, rawValue) {
|
|
319
|
+
if (rawValue === void 0) {
|
|
320
|
+
plan.nextMetadata = omitMetadataKey(plan.nextMetadata, key);
|
|
321
|
+
return;
|
|
276
322
|
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
323
|
+
plan.nextMetadata[key] = rawValue;
|
|
324
|
+
}
|
|
325
|
+
async function applyTopicProjectOverlayPatch(ctx, topic, plan) {
|
|
280
326
|
if (typeof ctx.runMutation === "function") {
|
|
281
327
|
try {
|
|
282
|
-
await ctx.runMutation(api.topics.update, topicUpdateArgs);
|
|
328
|
+
await ctx.runMutation(api.topics.update, plan.topicUpdateArgs);
|
|
283
329
|
} catch (error) {
|
|
284
|
-
if (!
|
|
330
|
+
if (!canPatchTopicViaLocalDb(ctx, error)) {
|
|
285
331
|
throw error;
|
|
286
332
|
}
|
|
287
|
-
await ctx.db.patch(
|
|
333
|
+
await ctx.db.patch(topic._id, plan.patch);
|
|
288
334
|
}
|
|
289
335
|
} else if (ctx?.db && typeof ctx.db.patch === "function") {
|
|
290
|
-
await ctx.db.patch(
|
|
336
|
+
await ctx.db.patch(topic._id, plan.patch);
|
|
291
337
|
} else {
|
|
292
338
|
throw new Error(
|
|
293
339
|
"Cannot patch topic without component adapter (ctx.runMutation unavailable)"
|
|
294
340
|
);
|
|
295
341
|
}
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
metadata: nextMetadata
|
|
300
|
-
});
|
|
342
|
+
}
|
|
343
|
+
function canPatchTopicViaLocalDb(ctx, error) {
|
|
344
|
+
return isMissingLucernChildComponentError(error) && Boolean(ctx?.db) && typeof ctx.db?.patch === "function";
|
|
301
345
|
}
|
|
302
346
|
|
|
303
347
|
// src/resolvers.ts
|
|
@@ -325,7 +369,7 @@ async function patchProjectWithTolerance(ctx, projectId, value) {
|
|
|
325
369
|
try {
|
|
326
370
|
await patchTopicProjectOverlay(ctx, projectId, value);
|
|
327
371
|
} catch (error) {
|
|
328
|
-
if (!isAdvisoryTopicPatch(value)
|
|
372
|
+
if (!(isAdvisoryTopicPatch(value) && isMissingLucernChildComponentError2(error))) {
|
|
329
373
|
throw error;
|
|
330
374
|
}
|
|
331
375
|
console.warn(
|
|
@@ -392,13 +436,15 @@ function asMappedProjectId(topic) {
|
|
|
392
436
|
if (!topic) {
|
|
393
437
|
return;
|
|
394
438
|
}
|
|
395
|
-
const directLegacyProjectId = normalizeScopeValue(
|
|
439
|
+
const directLegacyProjectId = normalizeScopeValue(
|
|
440
|
+
topic[LEGACY_SCOPE_FIELD2]
|
|
441
|
+
);
|
|
396
442
|
if (directLegacyProjectId) {
|
|
397
443
|
return directLegacyProjectId;
|
|
398
444
|
}
|
|
399
445
|
const metadata = topic.metadata || {};
|
|
400
446
|
const candidate = metadata[LEGACY_SCOPE_FIELD2] || metadata.legacyProjectId || metadata.projectId || metadata.scopeProjectId;
|
|
401
|
-
return candidate ? candidate : void 0;
|
|
447
|
+
return typeof candidate === "string" ? normalizeScopeValue(candidate) : void 0;
|
|
402
448
|
}
|
|
403
449
|
function normalizeScopeValue(value) {
|
|
404
450
|
if (typeof value !== "string") {
|
|
@@ -423,8 +469,9 @@ function pickPrimaryTopic(candidates) {
|
|
|
423
469
|
})[0];
|
|
424
470
|
}
|
|
425
471
|
async function findTopicsByScopeAlias(ctx, scopeId) {
|
|
472
|
+
const query2 = ctx.db.query("topics");
|
|
426
473
|
try {
|
|
427
|
-
return await
|
|
474
|
+
return await query2.withIndex(
|
|
428
475
|
"by_graph_scope_project",
|
|
429
476
|
(q) => q.eq(LEGACY_SCOPE_FIELD2, scopeId)
|
|
430
477
|
).collect();
|
|
@@ -436,7 +483,7 @@ async function findTopicsByScopeAlias(ctx, scopeId) {
|
|
|
436
483
|
scopeId
|
|
437
484
|
}
|
|
438
485
|
);
|
|
439
|
-
const topics = await
|
|
486
|
+
const topics = await query2.collect();
|
|
440
487
|
return topics.filter((topic) => {
|
|
441
488
|
const normalizedGlobalId = normalizeScopeValue(topic.globalId);
|
|
442
489
|
const mappedProjectId = asMappedProjectId(topic);
|
|
@@ -492,137 +539,115 @@ async function resolveInheritedWorkspaceScope(ctx, topic) {
|
|
|
492
539
|
let current = topic;
|
|
493
540
|
for (let i = 0; i < MAX_DEPTH && current?.parentTopicId; i++) {
|
|
494
541
|
current = await ctx.db.get(current.parentTopicId);
|
|
495
|
-
if (!current)
|
|
542
|
+
if (!current) {
|
|
543
|
+
break;
|
|
544
|
+
}
|
|
496
545
|
if (!tenantId) {
|
|
497
546
|
tenantId = normalizeScopeValue(current.tenantId);
|
|
498
547
|
}
|
|
499
548
|
if (!workspaceId) {
|
|
500
549
|
workspaceId = normalizeScopeValue(current.workspaceId);
|
|
501
550
|
}
|
|
502
|
-
if (tenantId && workspaceId)
|
|
551
|
+
if (tenantId && workspaceId) {
|
|
552
|
+
break;
|
|
553
|
+
}
|
|
503
554
|
}
|
|
504
555
|
return { tenantId, workspaceId };
|
|
505
556
|
}
|
|
506
557
|
async function resolveTopicProjectScope(ctx, args) {
|
|
507
558
|
if (args.topicId) {
|
|
508
|
-
|
|
509
|
-
try {
|
|
510
|
-
topic = await ctx.db.get(
|
|
511
|
-
args.topicId
|
|
512
|
-
);
|
|
513
|
-
} catch (error) {
|
|
514
|
-
debugGraphPrimitiveFallback(
|
|
515
|
-
"[topicScope] Failed to load topic by direct id",
|
|
516
|
-
{
|
|
517
|
-
error,
|
|
518
|
-
topicId: args.topicId
|
|
519
|
-
}
|
|
520
|
-
);
|
|
521
|
-
}
|
|
522
|
-
if (!topic) {
|
|
523
|
-
topic = await tryResolveHostTopicById(ctx, String(args.topicId));
|
|
524
|
-
}
|
|
525
|
-
if (!topic) {
|
|
526
|
-
topic = pickPrimaryTopic(
|
|
527
|
-
await findTopicsByScopeAlias(ctx, String(args.topicId))
|
|
528
|
-
) ?? null;
|
|
529
|
-
}
|
|
530
|
-
if (!topic) {
|
|
531
|
-
const nodeScope = await resolveTopicNodeScopeOrNull(
|
|
532
|
-
ctx,
|
|
533
|
-
String(args.topicId)
|
|
534
|
-
);
|
|
535
|
-
if (nodeScope) {
|
|
536
|
-
return nodeScope;
|
|
537
|
-
}
|
|
538
|
-
throw new Error(`Topic not found: ${String(args.topicId)}`);
|
|
539
|
-
}
|
|
540
|
-
const inherited = await resolveInheritedWorkspaceScope(ctx, topic);
|
|
541
|
-
const mapped = asMappedProjectId(topic);
|
|
542
|
-
if (mapped) {
|
|
543
|
-
return {
|
|
544
|
-
topicId: topic._id,
|
|
545
|
-
projectId: mapped,
|
|
546
|
-
tenantId: inherited.tenantId,
|
|
547
|
-
workspaceId: inherited.workspaceId,
|
|
548
|
-
source: "topic"
|
|
549
|
-
};
|
|
550
|
-
}
|
|
551
|
-
return {
|
|
552
|
-
topicId: topic._id,
|
|
553
|
-
tenantId: inherited.tenantId,
|
|
554
|
-
workspaceId: inherited.workspaceId,
|
|
555
|
-
source: "topic"
|
|
556
|
-
};
|
|
559
|
+
return await resolveScopeFromTopicId(ctx, args.topicId);
|
|
557
560
|
}
|
|
558
561
|
if (args.projectId) {
|
|
559
|
-
|
|
560
|
-
try {
|
|
561
|
-
directTopic = await ctx.db.get(
|
|
562
|
-
args.projectId
|
|
563
|
-
);
|
|
564
|
-
} catch (error) {
|
|
565
|
-
debugGraphPrimitiveFallback(
|
|
566
|
-
"[topicScope] Failed to load direct project topic",
|
|
567
|
-
{
|
|
568
|
-
error,
|
|
569
|
-
projectId: args.projectId
|
|
570
|
-
}
|
|
571
|
-
);
|
|
572
|
-
}
|
|
573
|
-
if (directTopic) {
|
|
574
|
-
const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);
|
|
575
|
-
const mapped = asMappedProjectId(directTopic);
|
|
576
|
-
return {
|
|
577
|
-
topicId: directTopic._id,
|
|
578
|
-
projectId: mapped ?? args.projectId,
|
|
579
|
-
tenantId: inherited.tenantId,
|
|
580
|
-
workspaceId: inherited.workspaceId,
|
|
581
|
-
source: "topic_inferred"
|
|
582
|
-
};
|
|
583
|
-
}
|
|
584
|
-
directTopic = await tryResolveHostTopicByLegacyScope(ctx, args.projectId);
|
|
585
|
-
if (directTopic) {
|
|
586
|
-
const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);
|
|
587
|
-
const mapped = asMappedProjectId(directTopic);
|
|
588
|
-
return {
|
|
589
|
-
topicId: directTopic._id,
|
|
590
|
-
projectId: mapped ?? args.projectId,
|
|
591
|
-
tenantId: inherited.tenantId,
|
|
592
|
-
workspaceId: inherited.workspaceId,
|
|
593
|
-
source: "topic_inferred"
|
|
594
|
-
};
|
|
595
|
-
}
|
|
596
|
-
const topics = await findTopicsByScopeAlias(ctx, args.projectId);
|
|
597
|
-
const primary = pickPrimaryTopic(topics);
|
|
598
|
-
if (primary) {
|
|
599
|
-
const inherited = await resolveInheritedWorkspaceScope(ctx, primary);
|
|
600
|
-
return {
|
|
601
|
-
topicId: primary._id,
|
|
602
|
-
projectId: args.projectId,
|
|
603
|
-
tenantId: inherited.tenantId,
|
|
604
|
-
workspaceId: inherited.workspaceId,
|
|
605
|
-
source: "project_mapped_topic"
|
|
606
|
-
};
|
|
607
|
-
}
|
|
608
|
-
const nodeScope = await resolveTopicNodeScopeOrNull(
|
|
609
|
-
ctx,
|
|
610
|
-
String(args.projectId)
|
|
611
|
-
);
|
|
612
|
-
if (nodeScope) {
|
|
613
|
-
return {
|
|
614
|
-
...nodeScope,
|
|
615
|
-
projectId: nodeScope.projectId ?? String(args.projectId)
|
|
616
|
-
};
|
|
617
|
-
}
|
|
618
|
-
throw new Error(
|
|
619
|
-
`Legacy project scope ${String(args.projectId)} has no mapped topic.`
|
|
620
|
-
);
|
|
562
|
+
return await resolveScopeFromLegacyProjectId(ctx, args.projectId);
|
|
621
563
|
}
|
|
622
564
|
throw new Error(
|
|
623
565
|
"Missing scope: provide topicId (preferred) or legacy projectId alias."
|
|
624
566
|
);
|
|
625
567
|
}
|
|
568
|
+
async function resolveScopeFromTopicId(ctx, topicId) {
|
|
569
|
+
const topic = await resolveTopicDocFromTopicId(ctx, topicId);
|
|
570
|
+
if (topic) {
|
|
571
|
+
return await buildTopicScope(ctx, topic, "topic");
|
|
572
|
+
}
|
|
573
|
+
const nodeScope = await resolveTopicNodeScopeOrNull(ctx, String(topicId));
|
|
574
|
+
if (nodeScope) {
|
|
575
|
+
return nodeScope;
|
|
576
|
+
}
|
|
577
|
+
throw new Error(`Topic not found: ${String(topicId)}`);
|
|
578
|
+
}
|
|
579
|
+
async function resolveTopicDocFromTopicId(ctx, topicId) {
|
|
580
|
+
const direct = await tryReadTopicDoc(ctx, topicId, {
|
|
581
|
+
failureLog: "[topicScope] Failed to load topic by direct id",
|
|
582
|
+
idLogKey: "topicId"
|
|
583
|
+
});
|
|
584
|
+
if (direct) {
|
|
585
|
+
return direct;
|
|
586
|
+
}
|
|
587
|
+
const hostTopic = await tryResolveHostTopicById(ctx, String(topicId));
|
|
588
|
+
if (hostTopic) {
|
|
589
|
+
return hostTopic;
|
|
590
|
+
}
|
|
591
|
+
return pickPrimaryTopic(await findTopicsByScopeAlias(ctx, String(topicId))) ?? null;
|
|
592
|
+
}
|
|
593
|
+
async function resolveScopeFromLegacyProjectId(ctx, legacyProjectId) {
|
|
594
|
+
const directTopic = await resolveDirectLegacyProjectTopic(
|
|
595
|
+
ctx,
|
|
596
|
+
legacyProjectId
|
|
597
|
+
);
|
|
598
|
+
if (directTopic) {
|
|
599
|
+
return await buildTopicScope(ctx, directTopic, "topic_inferred", {
|
|
600
|
+
fallbackProjectId: legacyProjectId
|
|
601
|
+
});
|
|
602
|
+
}
|
|
603
|
+
const primary = pickPrimaryTopic(
|
|
604
|
+
await findTopicsByScopeAlias(ctx, legacyProjectId)
|
|
605
|
+
);
|
|
606
|
+
if (primary) {
|
|
607
|
+
return await buildTopicScope(ctx, primary, "project_mapped_topic", {
|
|
608
|
+
fallbackProjectId: legacyProjectId
|
|
609
|
+
});
|
|
610
|
+
}
|
|
611
|
+
const nodeScope = await resolveTopicNodeScopeOrNull(ctx, legacyProjectId);
|
|
612
|
+
if (nodeScope) {
|
|
613
|
+
return {
|
|
614
|
+
...nodeScope,
|
|
615
|
+
projectId: nodeScope.projectId ?? legacyProjectId
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
throw new Error(
|
|
619
|
+
`Legacy project scope ${legacyProjectId} has no mapped topic.`
|
|
620
|
+
);
|
|
621
|
+
}
|
|
622
|
+
async function resolveDirectLegacyProjectTopic(ctx, legacyProjectId) {
|
|
623
|
+
const directTopic = await tryReadTopicDoc(ctx, legacyProjectId, {
|
|
624
|
+
failureLog: "[topicScope] Failed to load direct project topic",
|
|
625
|
+
idLogKey: "projectId"
|
|
626
|
+
});
|
|
627
|
+
return directTopic ?? tryResolveHostTopicByLegacyScope(ctx, legacyProjectId);
|
|
628
|
+
}
|
|
629
|
+
async function tryReadTopicDoc(ctx, id, log) {
|
|
630
|
+
try {
|
|
631
|
+
return await ctx.db.get(id);
|
|
632
|
+
} catch (error) {
|
|
633
|
+
debugGraphPrimitiveFallback(log.failureLog, {
|
|
634
|
+
error,
|
|
635
|
+
[log.idLogKey]: id
|
|
636
|
+
});
|
|
637
|
+
return null;
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
async function buildTopicScope(ctx, topic, source, options = {}) {
|
|
641
|
+
const inherited = await resolveInheritedWorkspaceScope(ctx, topic);
|
|
642
|
+
const mapped = asMappedProjectId(topic);
|
|
643
|
+
return {
|
|
644
|
+
topicId: topic._id,
|
|
645
|
+
...mapped || options.fallbackProjectId ? { projectId: mapped ?? options.fallbackProjectId } : {},
|
|
646
|
+
tenantId: inherited.tenantId,
|
|
647
|
+
workspaceId: inherited.workspaceId,
|
|
648
|
+
source
|
|
649
|
+
};
|
|
650
|
+
}
|
|
626
651
|
var optionalScopeArgs = {
|
|
627
652
|
projectId: v.optional(v.string()),
|
|
628
653
|
topicId: v.optional(v.string())
|
|
@@ -656,7 +681,15 @@ function dedupeEvidenceNodes(nodes) {
|
|
|
656
681
|
return deduped;
|
|
657
682
|
}
|
|
658
683
|
function evidenceMatchesScope(node, scope) {
|
|
659
|
-
|
|
684
|
+
const record = node && typeof node === "object" && !Array.isArray(node) ? node : null;
|
|
685
|
+
if (!record) {
|
|
686
|
+
return false;
|
|
687
|
+
}
|
|
688
|
+
const nodeTopicId = typeof record.topicId === "string" ? record.topicId : void 0;
|
|
689
|
+
const nodeProjectId = typeof record.projectId === "string" ? record.projectId : void 0;
|
|
690
|
+
const scopeTopicId = scope.topicId === void 0 ? void 0 : String(scope.topicId);
|
|
691
|
+
const scopeProjectId = scope.projectId === void 0 ? void 0 : String(scope.projectId);
|
|
692
|
+
return scopeTopicId !== void 0 && nodeTopicId === scopeTopicId || scopeProjectId !== void 0 && nodeProjectId === scopeProjectId;
|
|
660
693
|
}
|
|
661
694
|
function resolveEvidenceLinkedWorktreeId(metadata) {
|
|
662
695
|
const worktreeId = metadata?.linkedWorktreeId;
|
|
@@ -667,7 +700,7 @@ function resolveEvidenceLinkedWorktreeId(metadata) {
|
|
|
667
700
|
return typeof sprintId === "string" && sprintId.trim().length > 0 ? sprintId : void 0;
|
|
668
701
|
}
|
|
669
702
|
async function resolveEvidenceScopeOrNull(ctx, args) {
|
|
670
|
-
if (!args.projectId
|
|
703
|
+
if (!(args.projectId || args.topicId)) {
|
|
671
704
|
return null;
|
|
672
705
|
}
|
|
673
706
|
try {
|
|
@@ -793,6 +826,224 @@ function nodeMatchesWorkspaceReasoningScope(node, scope) {
|
|
|
793
826
|
}
|
|
794
827
|
|
|
795
828
|
// src/epistemicEvidenceQueries.ts
|
|
829
|
+
function readOptionalString(value) {
|
|
830
|
+
return typeof value === "string" && value.trim().length > 0 ? value : void 0;
|
|
831
|
+
}
|
|
832
|
+
function readOptionalNumber(value) {
|
|
833
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
834
|
+
}
|
|
835
|
+
function readConvexId(value) {
|
|
836
|
+
const normalized = readOptionalString(value);
|
|
837
|
+
return normalized;
|
|
838
|
+
}
|
|
839
|
+
function readRecord(value) {
|
|
840
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
841
|
+
}
|
|
842
|
+
function readOptionalStringArray(value) {
|
|
843
|
+
return Array.isArray(value) && value.every((item) => typeof item === "string") ? value : void 0;
|
|
844
|
+
}
|
|
845
|
+
function readEvidenceNodeRow(value, fallbackProjectId) {
|
|
846
|
+
const record = readRecord(value);
|
|
847
|
+
if (!record) {
|
|
848
|
+
return null;
|
|
849
|
+
}
|
|
850
|
+
const id = readConvexId(record._id);
|
|
851
|
+
const canonicalText = readOptionalString(record.canonicalText);
|
|
852
|
+
const createdAt = readOptionalNumber(record.createdAt);
|
|
853
|
+
const createdBy = readOptionalString(record.createdBy);
|
|
854
|
+
const nodeType = readOptionalString(record.nodeType);
|
|
855
|
+
const sourceType = readOptionalString(record.sourceType);
|
|
856
|
+
const status = readOptionalString(record.status);
|
|
857
|
+
const updatedAt = readOptionalNumber(record.updatedAt);
|
|
858
|
+
if (!(id && canonicalText && createdAt !== void 0 && createdBy && nodeType === "evidence" && sourceType && status && updatedAt !== void 0)) {
|
|
859
|
+
return null;
|
|
860
|
+
}
|
|
861
|
+
const metadata = readRecord(record.metadata) ?? void 0;
|
|
862
|
+
const node = {
|
|
863
|
+
...record,
|
|
864
|
+
_id: id,
|
|
865
|
+
canonicalText,
|
|
866
|
+
createdAt,
|
|
867
|
+
createdBy,
|
|
868
|
+
nodeType: "evidence",
|
|
869
|
+
sourceType,
|
|
870
|
+
status,
|
|
871
|
+
updatedAt
|
|
872
|
+
};
|
|
873
|
+
const projectId = readOptionalString(record.projectId) ?? readOptionalString(fallbackProjectId);
|
|
874
|
+
if (projectId !== void 0) {
|
|
875
|
+
node.projectId = projectId;
|
|
876
|
+
}
|
|
877
|
+
const topicId = readOptionalString(record.topicId);
|
|
878
|
+
if (topicId !== void 0) {
|
|
879
|
+
node.topicId = topicId;
|
|
880
|
+
}
|
|
881
|
+
const tenantId = readOptionalString(record.tenantId);
|
|
882
|
+
if (tenantId !== void 0) {
|
|
883
|
+
node.tenantId = tenantId;
|
|
884
|
+
}
|
|
885
|
+
const workspaceId = readOptionalString(record.workspaceId);
|
|
886
|
+
if (workspaceId !== void 0) {
|
|
887
|
+
node.workspaceId = workspaceId;
|
|
888
|
+
}
|
|
889
|
+
const globalId = readOptionalString(record.globalId);
|
|
890
|
+
if (globalId !== void 0) {
|
|
891
|
+
node.globalId = globalId;
|
|
892
|
+
}
|
|
893
|
+
const title = readOptionalString(record.title);
|
|
894
|
+
if (title !== void 0) {
|
|
895
|
+
node.title = title;
|
|
896
|
+
}
|
|
897
|
+
const audienceLabel = readOptionalString(record.audienceLabel);
|
|
898
|
+
if (audienceLabel !== void 0) {
|
|
899
|
+
node.audienceLabel = audienceLabel;
|
|
900
|
+
}
|
|
901
|
+
const epistemicLayer = readOptionalString(record.epistemicLayer);
|
|
902
|
+
if (epistemicLayer !== void 0) {
|
|
903
|
+
node.epistemicLayer = epistemicLayer;
|
|
904
|
+
}
|
|
905
|
+
const sensitivityTier = readOptionalString(record.sensitivityTier);
|
|
906
|
+
if (sensitivityTier !== void 0) {
|
|
907
|
+
node.sensitivityTier = sensitivityTier;
|
|
908
|
+
}
|
|
909
|
+
const exportClass = readOptionalString(record.exportClass);
|
|
910
|
+
if (exportClass !== void 0) {
|
|
911
|
+
node.exportClass = exportClass;
|
|
912
|
+
}
|
|
913
|
+
const policyTags = readOptionalStringArray(record.policyTags);
|
|
914
|
+
if (policyTags !== void 0) {
|
|
915
|
+
node.policyTags = policyTags;
|
|
916
|
+
}
|
|
917
|
+
if (metadata !== void 0) {
|
|
918
|
+
node.metadata = metadata;
|
|
919
|
+
}
|
|
920
|
+
return node;
|
|
921
|
+
}
|
|
922
|
+
function readEvidenceNodeRows(values, fallbackProjectId) {
|
|
923
|
+
return values.flatMap((value) => {
|
|
924
|
+
const node = readEvidenceNodeRow(value, fallbackProjectId);
|
|
925
|
+
return node ? [node] : [];
|
|
926
|
+
});
|
|
927
|
+
}
|
|
928
|
+
function dedupeEvidenceNodeRows(nodes) {
|
|
929
|
+
const seen = /* @__PURE__ */ new Set();
|
|
930
|
+
const deduped = [];
|
|
931
|
+
for (const node of nodes) {
|
|
932
|
+
const id = String(node._id);
|
|
933
|
+
if (seen.has(id)) {
|
|
934
|
+
continue;
|
|
935
|
+
}
|
|
936
|
+
seen.add(id);
|
|
937
|
+
deduped.push(node);
|
|
938
|
+
}
|
|
939
|
+
return deduped;
|
|
940
|
+
}
|
|
941
|
+
function readEvidenceEdgeRow(value) {
|
|
942
|
+
const record = readRecord(value);
|
|
943
|
+
if (!record) {
|
|
944
|
+
return null;
|
|
945
|
+
}
|
|
946
|
+
const id = readConvexId(record._id);
|
|
947
|
+
const edgeType = readOptionalString(record.edgeType);
|
|
948
|
+
if (!(id && edgeType)) {
|
|
949
|
+
return null;
|
|
950
|
+
}
|
|
951
|
+
const edge = { _id: id, edgeType };
|
|
952
|
+
const weight = readOptionalNumber(record.weight);
|
|
953
|
+
if (weight !== void 0) {
|
|
954
|
+
edge.weight = weight;
|
|
955
|
+
}
|
|
956
|
+
for (const field of [
|
|
957
|
+
"fromNodeId",
|
|
958
|
+
"toNodeId",
|
|
959
|
+
"sourceGlobalId",
|
|
960
|
+
"targetGlobalId",
|
|
961
|
+
"fromGlobalId",
|
|
962
|
+
"toGlobalId",
|
|
963
|
+
"fromLayer",
|
|
964
|
+
"toLayer",
|
|
965
|
+
"topicId"
|
|
966
|
+
]) {
|
|
967
|
+
const valueForField = readOptionalString(record[field]);
|
|
968
|
+
if (valueForField !== void 0) {
|
|
969
|
+
edge[field] = valueForField;
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
return edge;
|
|
973
|
+
}
|
|
974
|
+
function readEvidenceEdgeRows(values) {
|
|
975
|
+
return values.flatMap((value) => {
|
|
976
|
+
const edge = readEvidenceEdgeRow(value);
|
|
977
|
+
return edge ? [edge] : [];
|
|
978
|
+
});
|
|
979
|
+
}
|
|
980
|
+
function dedupeEvidenceEdges(edges) {
|
|
981
|
+
const seen = /* @__PURE__ */ new Set();
|
|
982
|
+
const deduped = [];
|
|
983
|
+
for (const edge of edges) {
|
|
984
|
+
const id = String(edge._id);
|
|
985
|
+
if (seen.has(id)) {
|
|
986
|
+
continue;
|
|
987
|
+
}
|
|
988
|
+
seen.add(id);
|
|
989
|
+
deduped.push(edge);
|
|
990
|
+
}
|
|
991
|
+
return deduped;
|
|
992
|
+
}
|
|
993
|
+
function evidenceSourceRef(edge) {
|
|
994
|
+
return edge.sourceGlobalId ?? edge.fromGlobalId ?? edge.fromNodeId;
|
|
995
|
+
}
|
|
996
|
+
async function resolveEvidenceNodeSoft(ctx, nodeRef) {
|
|
997
|
+
const normalizedId = ctx.db.normalizeId?.("epistemicNodes", nodeRef) ?? readConvexId(nodeRef);
|
|
998
|
+
if (normalizedId) {
|
|
999
|
+
try {
|
|
1000
|
+
const direct = readEvidenceNodeRow(await ctx.db.get(normalizedId));
|
|
1001
|
+
if (direct) {
|
|
1002
|
+
return direct;
|
|
1003
|
+
}
|
|
1004
|
+
} catch (error) {
|
|
1005
|
+
debugGraphPrimitiveFallback(
|
|
1006
|
+
"[epistemicEvidence] Direct evidence lookup failed",
|
|
1007
|
+
{ error, nodeRef }
|
|
1008
|
+
);
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
return readEvidenceNodeRow(
|
|
1012
|
+
await ctx.db.query("epistemicNodes").withIndex("by_globalId", (q) => q.eq("globalId", nodeRef)).first()
|
|
1013
|
+
);
|
|
1014
|
+
}
|
|
1015
|
+
async function collectNodeReferenceIds(ctx, nodeId) {
|
|
1016
|
+
const refs = /* @__PURE__ */ new Set([String(nodeId)]);
|
|
1017
|
+
const node = await ctx.db.get(nodeId);
|
|
1018
|
+
const globalId = readOptionalString(readRecord(node)?.globalId);
|
|
1019
|
+
if (globalId) {
|
|
1020
|
+
refs.add(globalId);
|
|
1021
|
+
}
|
|
1022
|
+
return [...refs];
|
|
1023
|
+
}
|
|
1024
|
+
async function collectInformsEdgesToNode(ctx, nodeId) {
|
|
1025
|
+
const refs = await collectNodeReferenceIds(ctx, nodeId);
|
|
1026
|
+
const reads = [];
|
|
1027
|
+
for (const ref of refs) {
|
|
1028
|
+
reads.push(
|
|
1029
|
+
ctx.db.query("epistemicEdges").withIndex(
|
|
1030
|
+
"by_to_type",
|
|
1031
|
+
(q) => q.eq("toNodeId", ref).eq("edgeType", "informs")
|
|
1032
|
+
).collect(),
|
|
1033
|
+
ctx.db.query("epistemicEdges").withIndex(
|
|
1034
|
+
"by_target_global_id",
|
|
1035
|
+
(q) => q.eq("targetGlobalId", ref)
|
|
1036
|
+
).collect()
|
|
1037
|
+
);
|
|
1038
|
+
}
|
|
1039
|
+
const edges = readEvidenceEdgeRows((await Promise.all(reads)).flat()).filter(
|
|
1040
|
+
(edge) => edge.edgeType === "informs"
|
|
1041
|
+
);
|
|
1042
|
+
return dedupeEvidenceEdges(edges);
|
|
1043
|
+
}
|
|
1044
|
+
function hasProjectId(node) {
|
|
1045
|
+
return typeof node.projectId === "string" && node.projectId.length > 0;
|
|
1046
|
+
}
|
|
796
1047
|
var getById = query({
|
|
797
1048
|
args: {
|
|
798
1049
|
nodeId: v.optional(v.id("epistemicNodes")),
|
|
@@ -805,11 +1056,7 @@ var getById = query({
|
|
|
805
1056
|
if (!id) {
|
|
806
1057
|
return null;
|
|
807
1058
|
}
|
|
808
|
-
|
|
809
|
-
if (!node || node.nodeType !== "evidence") {
|
|
810
|
-
return null;
|
|
811
|
-
}
|
|
812
|
-
return node;
|
|
1059
|
+
return await resolveEvidenceNodeSoft(ctx, String(id));
|
|
813
1060
|
}
|
|
814
1061
|
});
|
|
815
1062
|
var getByProject = query({
|
|
@@ -821,7 +1068,7 @@ var getByProject = query({
|
|
|
821
1068
|
},
|
|
822
1069
|
returns: permissiveReturn,
|
|
823
1070
|
handler: async (ctx, args) => {
|
|
824
|
-
if (!args.projectId
|
|
1071
|
+
if (!(args.projectId || args.topicId)) {
|
|
825
1072
|
return [];
|
|
826
1073
|
}
|
|
827
1074
|
const pageSize = clampEvidenceLimit(args.limit);
|
|
@@ -857,9 +1104,9 @@ var getByProject = query({
|
|
|
857
1104
|
"by_topic_type",
|
|
858
1105
|
(q) => q.eq("topicId", scope.topicId).eq("nodeType", "evidence")
|
|
859
1106
|
).order("desc").take(scanLimit);
|
|
860
|
-
const scopedNodes =
|
|
861
|
-
(
|
|
862
|
-
);
|
|
1107
|
+
const scopedNodes = dedupeEvidenceNodeRows(
|
|
1108
|
+
readEvidenceNodeRows(topicNodes, scope.projectId)
|
|
1109
|
+
).filter((node) => evidenceMatchesScope(node, scope));
|
|
863
1110
|
const filteredNodes = args.status ? scopedNodes.filter((node) => node.status === args.status) : scopedNodes;
|
|
864
1111
|
return filteredNodes.map(flattenEvidenceNode).slice(0, pageSize);
|
|
865
1112
|
}
|
|
@@ -882,9 +1129,9 @@ var getByTopic = query({
|
|
|
882
1129
|
"by_topic_type",
|
|
883
1130
|
(q) => q.eq("topicId", scope.topicId).eq("nodeType", "evidence")
|
|
884
1131
|
).order("desc").take(scanLimit);
|
|
885
|
-
const scopedNodes =
|
|
886
|
-
(
|
|
887
|
-
);
|
|
1132
|
+
const scopedNodes = dedupeEvidenceNodeRows(
|
|
1133
|
+
readEvidenceNodeRows(topicNodes, scope.projectId)
|
|
1134
|
+
).filter((node) => evidenceMatchesScope(node, scope));
|
|
888
1135
|
const filteredNodes = args.status ? scopedNodes.filter((node) => node.status === args.status) : scopedNodes;
|
|
889
1136
|
return filteredNodes.map(flattenEvidenceNode).slice(0, pageSize);
|
|
890
1137
|
}
|
|
@@ -895,20 +1142,29 @@ var getForBelief = query({
|
|
|
895
1142
|
},
|
|
896
1143
|
returns: permissiveReturn,
|
|
897
1144
|
handler: async (ctx, args) => {
|
|
898
|
-
const edges = await ctx.
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
1145
|
+
const edges = await collectInformsEdgesToNode(ctx, args.beliefNodeId);
|
|
1146
|
+
const evidenceNodeIds = edges.flatMap((edge) => {
|
|
1147
|
+
const sourceRef = evidenceSourceRef(edge);
|
|
1148
|
+
return sourceRef ? [sourceRef] : [];
|
|
1149
|
+
});
|
|
903
1150
|
const evidenceNodes = await Promise.all(
|
|
904
|
-
evidenceNodeIds.map((id) => ctx
|
|
1151
|
+
evidenceNodeIds.map((id) => resolveEvidenceNodeSoft(ctx, id))
|
|
905
1152
|
);
|
|
906
|
-
return evidenceNodes.
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
1153
|
+
return evidenceNodes.flatMap((e, i) => {
|
|
1154
|
+
const edge = edges[i];
|
|
1155
|
+
if (!(e && edge)) {
|
|
1156
|
+
return [];
|
|
1157
|
+
}
|
|
1158
|
+
const weight = edge.weight ?? 0;
|
|
1159
|
+
return [
|
|
1160
|
+
{
|
|
1161
|
+
...e,
|
|
1162
|
+
relation: weight >= 0 ? "supports" : "contradicts",
|
|
1163
|
+
confidence: Math.abs(weight),
|
|
1164
|
+
edgeId: edge._id
|
|
1165
|
+
}
|
|
1166
|
+
];
|
|
1167
|
+
});
|
|
912
1168
|
}
|
|
913
1169
|
});
|
|
914
1170
|
var internalGetByProject = internalQuery({
|
|
@@ -927,21 +1183,30 @@ var internalGetByProject = internalQuery({
|
|
|
927
1183
|
return [];
|
|
928
1184
|
}
|
|
929
1185
|
const audienceMode = args.audienceMode ?? "internal";
|
|
1186
|
+
const projectScopeId = scope.topicId ? String(scope.topicId) : scope.projectId;
|
|
1187
|
+
if (!projectScopeId) {
|
|
1188
|
+
return [];
|
|
1189
|
+
}
|
|
930
1190
|
const project = await resolveGraphPrimitivesAppResolvers().getProject(
|
|
931
1191
|
ctx,
|
|
932
|
-
|
|
1192
|
+
projectScopeId
|
|
933
1193
|
);
|
|
1194
|
+
const tenantId = project?.tenantId;
|
|
1195
|
+
const workspaceId = project?.workspaceId;
|
|
934
1196
|
const registryRows = await listAudienceRegistryRows(ctx, {
|
|
935
|
-
tenantId
|
|
936
|
-
workspaceId
|
|
1197
|
+
tenantId,
|
|
1198
|
+
workspaceId
|
|
937
1199
|
});
|
|
938
1200
|
const resolveAudienceClass = createEvidenceAudienceResolver(registryRows);
|
|
939
1201
|
const viewerClass = resolveAudienceClass(audienceMode, "public");
|
|
940
|
-
const nodes =
|
|
1202
|
+
const nodes = readEvidenceNodeRows(
|
|
1203
|
+
await getEvidenceNodesForScope(ctx, scope, { scanLimit }),
|
|
1204
|
+
scope.projectId
|
|
1205
|
+
);
|
|
941
1206
|
const workspaceScopedNodes = nodes.filter(
|
|
942
1207
|
(node) => nodeMatchesWorkspaceReasoningScope(node, {
|
|
943
|
-
tenantId
|
|
944
|
-
workspaceId
|
|
1208
|
+
tenantId,
|
|
1209
|
+
workspaceId
|
|
945
1210
|
})
|
|
946
1211
|
);
|
|
947
1212
|
return workspaceScopedNodes.filter(
|
|
@@ -1000,7 +1265,10 @@ var internalGetByTopic = internalQuery({
|
|
|
1000
1265
|
"by_topic_type",
|
|
1001
1266
|
(q) => q.eq("topicId", args.topicId).eq("nodeType", "evidence")
|
|
1002
1267
|
).order("desc").take(scanLimit);
|
|
1003
|
-
const workspaceScopedNodes =
|
|
1268
|
+
const workspaceScopedNodes = readEvidenceNodeRows(
|
|
1269
|
+
nodes,
|
|
1270
|
+
scope.projectId
|
|
1271
|
+
).filter(
|
|
1004
1272
|
(node) => nodeMatchesWorkspaceReasoningScope(node, {
|
|
1005
1273
|
tenantId: scope.tenantId,
|
|
1006
1274
|
workspaceId: scope.workspaceId
|
|
@@ -1051,13 +1319,16 @@ var getByProjectSystem = query({
|
|
|
1051
1319
|
if (!scope) {
|
|
1052
1320
|
return [];
|
|
1053
1321
|
}
|
|
1054
|
-
const nodes =
|
|
1322
|
+
const nodes = readEvidenceNodeRows(
|
|
1323
|
+
await getEvidenceNodesForScope(ctx, scope, { scanLimit }),
|
|
1324
|
+
scope.projectId
|
|
1325
|
+
);
|
|
1055
1326
|
const filtered = args.kind ? nodes.filter((n) => {
|
|
1056
1327
|
const meta = n.metadata || {};
|
|
1057
1328
|
return meta.kind === args.kind;
|
|
1058
1329
|
}) : nodes;
|
|
1059
1330
|
filtered.sort((a, b) => b.createdAt - a.createdAt);
|
|
1060
|
-
return filtered.slice(0, pageSize).map((n) => formatEvidenceNode(n));
|
|
1331
|
+
return filtered.filter(hasProjectId).slice(0, pageSize).map((n) => formatEvidenceNode(n));
|
|
1061
1332
|
}
|
|
1062
1333
|
});
|
|
1063
1334
|
var getEvidenceBalance = query({
|
|
@@ -1071,16 +1342,21 @@ var getEvidenceBalance = query({
|
|
|
1071
1342
|
topicId: args.topicId,
|
|
1072
1343
|
projectId: args.projectId
|
|
1073
1344
|
});
|
|
1074
|
-
const
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
);
|
|
1345
|
+
const scopeId = scope.topicId ? String(scope.topicId) : scope.projectId;
|
|
1346
|
+
if (!scopeId) {
|
|
1347
|
+
return { supporting: 0, challenging: 0, total: 0 };
|
|
1348
|
+
}
|
|
1349
|
+
const hasAccess = await checkScopeAccess(ctx, scopeId, args.userId);
|
|
1079
1350
|
if (!hasAccess) {
|
|
1080
1351
|
return { supporting: 0, challenging: 0, total: 0 };
|
|
1081
1352
|
}
|
|
1082
1353
|
const resolvedTopicId = scope.topicId || scope.projectId;
|
|
1083
|
-
const edges = resolvedTopicId ?
|
|
1354
|
+
const edges = resolvedTopicId ? readEvidenceEdgeRows(
|
|
1355
|
+
await ctx.db.query("epistemicEdges").withIndex(
|
|
1356
|
+
"by_topic",
|
|
1357
|
+
(q) => q.eq("topicId", resolvedTopicId)
|
|
1358
|
+
).collect()
|
|
1359
|
+
) : [];
|
|
1084
1360
|
const evidenceEdges = edges.filter(
|
|
1085
1361
|
(e) => e.edgeType === "informs" && e.fromLayer === "L2" && e.toLayer === "L3"
|
|
1086
1362
|
);
|