@lucern/graph-primitives 1.0.29 → 1.0.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{beliefDecay-DZ6tkLYq.d.ts → beliefDecay-BmkEk5OJ.d.ts} +3 -3
- package/dist/beliefDecay.d.ts +1 -1
- package/dist/beliefDecay.js +448 -314
- package/dist/beliefDecay.js.map +1 -1
- package/dist/{beliefEvidenceLinks-CWOXxxJg.d.ts → beliefEvidenceLinks-BzfjON_6.d.ts} +13 -13
- package/dist/beliefEvidenceLinks.d.ts +1 -1
- package/dist/beliefEvidenceLinks.js +843 -624
- package/dist/beliefEvidenceLinks.js.map +1 -1
- package/dist/beliefEvidenceLinks.operational.d.ts +7 -5
- package/dist/beliefEvidenceLinks.operational.js +91 -18
- package/dist/beliefEvidenceLinks.operational.js.map +1 -1
- package/dist/beliefLifecycle.js.map +1 -1
- package/dist/confidencePropagationDispatch.d.ts +28 -27
- package/dist/confidencePropagationDispatch.js +157 -99
- package/dist/confidencePropagationDispatch.js.map +1 -1
- package/dist/{contradictions-51VLsESq.d.ts → contradictions-BATPuZTL.d.ts} +10 -10
- package/dist/contradictions.d.ts +1 -1
- package/dist/contradictions.js +395 -225
- package/dist/contradictions.js.map +1 -1
- package/dist/convex.d.ts +65 -30
- package/dist/convex.js +7 -3
- package/dist/convex.js.map +1 -1
- package/dist/debug.js.map +1 -1
- package/dist/edgeValidation.js +293 -85
- package/dist/edgeValidation.js.map +1 -1
- package/dist/edges/contains.d.ts +1 -1
- package/dist/edges/contains.js.map +1 -1
- package/dist/edges/contradicts.d.ts +1 -1
- package/dist/edges/contradicts.js.map +1 -1
- package/dist/edges/{dependsOn.d.ts → depends-on.d.ts} +1 -1
- package/dist/edges/{dependsOn.js → depends-on.js} +4 -4
- package/dist/edges/depends-on.js.map +1 -0
- package/dist/edges/{derivedFrom.d.ts → derived-from.d.ts} +1 -1
- package/dist/edges/{derivedFrom.js → derived-from.js} +3 -3
- package/dist/edges/derived-from.js.map +1 -0
- package/dist/edges/elaborates.d.ts +1 -1
- package/dist/edges/elaborates.js.map +1 -1
- package/dist/edges/index.d.ts +7 -3
- package/dist/edges/index.js +7 -4
- package/dist/edges/index.js.map +1 -1
- package/dist/edges/informs.d.ts +1 -1
- package/dist/edges/informs.js.map +1 -1
- package/dist/edges/{propagationTypes.d.ts → propagation-types.d.ts} +14 -14
- package/dist/edges/{propagationTypes.js → propagation-types.js} +3 -3
- package/dist/edges/propagation-types.js.map +1 -0
- package/dist/edges/refutes.d.ts +1 -1
- package/dist/edges/refutes.js.map +1 -1
- package/dist/edges/supports.d.ts +1 -1
- package/dist/edges/supports.js.map +1 -1
- package/dist/edges/tests.d.ts +1 -1
- package/dist/edges/tests.js.map +1 -1
- package/dist/edges/utils.d.ts +1 -1
- package/dist/edges/utils.js.map +1 -1
- package/dist/embeddingTrigger.d.ts +14 -6
- package/dist/embeddingTrigger.js +11 -14
- package/dist/embeddingTrigger.js.map +1 -1
- package/dist/{entityBridge-DMaKooYn.d.ts → entityBridge-BhVDM3pc.d.ts} +5 -5
- package/dist/entityBridge.d.ts +1 -1
- package/dist/entityBridge.js +602 -225
- package/dist/entityBridge.js.map +1 -1
- package/dist/entityCanonicalMatch.d.ts +14 -12
- package/dist/entityCanonicalMatch.js.map +1 -1
- package/dist/{entityLifecycle-CvgSK5FV.d.ts → entityLifecycle-BsfCz9pS.d.ts} +5 -9
- package/dist/entityLifecycle.d.ts +1 -1
- package/dist/entityLifecycle.js +854 -480
- package/dist/entityLifecycle.js.map +1 -1
- package/dist/{entityValidation-KLZ_Xl2D.d.ts → entityValidation-B1yNEHJx.d.ts} +7 -6
- package/dist/entityValidation.d.ts +3 -1
- package/dist/entityValidation.js +60 -8
- package/dist/entityValidation.js.map +1 -1
- package/dist/{epistemicAnswers-C5ib4z6_.d.ts → epistemicAnswers-f47YMu9U.d.ts} +6 -6
- package/dist/epistemicAnswers.d.ts +1 -1
- package/dist/epistemicAnswers.js +587 -545
- package/dist/epistemicAnswers.js.map +1 -1
- package/dist/epistemicBeliefs.admin.d.ts +8 -8
- package/dist/epistemicBeliefs.admin.js +365 -166
- package/dist/epistemicBeliefs.admin.js.map +1 -1
- package/dist/epistemicBeliefs.backfills.d.ts +8 -8
- package/dist/epistemicBeliefs.backfills.js +655 -289
- package/dist/epistemicBeliefs.backfills.js.map +1 -1
- package/dist/epistemicBeliefs.confidence.d.ts +19 -15
- package/dist/epistemicBeliefs.confidence.js +633 -386
- package/dist/epistemicBeliefs.confidence.js.map +1 -1
- package/dist/epistemicBeliefs.core.d.ts +6 -6
- package/dist/epistemicBeliefs.core.js +717 -371
- package/dist/epistemicBeliefs.core.js.map +1 -1
- package/dist/epistemicBeliefs.d.ts +11 -9
- package/dist/epistemicBeliefs.forkEvidence.d.ts +2 -0
- package/dist/epistemicBeliefs.forkEvidence.js +8 -8
- package/dist/epistemicBeliefs.forkEvidence.js.map +1 -1
- package/dist/epistemicBeliefs.helpers.d.ts +68 -49
- package/dist/epistemicBeliefs.helpers.js +358 -211
- package/dist/epistemicBeliefs.helpers.js.map +1 -1
- package/dist/epistemicBeliefs.internal.d.ts +5 -5
- package/dist/epistemicBeliefs.internal.js +1248 -1026
- package/dist/epistemicBeliefs.internal.js.map +1 -1
- package/dist/epistemicBeliefs.js +4942 -3590
- package/dist/epistemicBeliefs.js.map +1 -1
- package/dist/epistemicBeliefs.lifecycle.d.ts +5 -5
- package/dist/epistemicBeliefs.lifecycle.js +1138 -781
- package/dist/epistemicBeliefs.lifecycle.js.map +1 -1
- package/dist/epistemicBeliefs.links.d.ts +7 -7
- package/dist/epistemicBeliefs.links.js +404 -267
- package/dist/epistemicBeliefs.links.js.map +1 -1
- package/dist/epistemicBeliefs.queries.d.ts +4 -4
- package/dist/epistemicBeliefs.queries.js +175 -20
- package/dist/epistemicBeliefs.queries.js.map +1 -1
- package/dist/epistemicBeliefs.topicAnchor.d.ts +6 -4
- package/dist/epistemicBeliefs.topicAnchor.js +12 -5
- package/dist/epistemicBeliefs.topicAnchor.js.map +1 -1
- package/dist/epistemicContracts.d.ts +28 -3
- package/dist/epistemicContracts.evaluators.d.ts +2 -0
- package/dist/epistemicContracts.evaluators.js +1062 -576
- package/dist/epistemicContracts.evaluators.js.map +1 -1
- package/dist/epistemicContracts.handlers.d.ts +15 -32
- package/dist/epistemicContracts.handlers.js +1829 -1351
- package/dist/epistemicContracts.handlers.js.map +1 -1
- package/dist/epistemicContracts.js +1131 -636
- package/dist/epistemicContracts.js.map +1 -1
- package/dist/epistemicContracts.metrics.d.ts +2 -0
- package/dist/epistemicContracts.metrics.js +375 -158
- package/dist/epistemicContracts.metrics.js.map +1 -1
- package/dist/epistemicContracts.types.d.ts +87 -81
- package/dist/epistemicEdgeCreation.d.ts +2 -0
- package/dist/epistemicEdgeCreation.js +87 -16
- package/dist/epistemicEdgeCreation.js.map +1 -1
- package/dist/{epistemicEdges-BF-cn4i3.d.ts → epistemicEdges-BGBh0QSP.d.ts} +4 -7
- package/dist/epistemicEdges.d.ts +6 -5
- package/dist/epistemicEdges.handlers.d.ts +3 -3
- package/dist/epistemicEdges.handlers.js +129 -24
- package/dist/epistemicEdges.handlers.js.map +1 -1
- package/dist/epistemicEdges.helpers.d.ts +6 -4
- package/dist/epistemicEdges.helpers.js +37 -2
- package/dist/epistemicEdges.helpers.js.map +1 -1
- package/dist/epistemicEdges.js +1966 -1202
- package/dist/epistemicEdges.js.map +1 -1
- package/dist/epistemicEdges.mutations.d.ts +7 -7
- package/dist/epistemicEdges.mutations.js +956 -579
- package/dist/epistemicEdges.mutations.js.map +1 -1
- package/dist/epistemicEdges.queries.d.ts +16 -16
- package/dist/epistemicEdges.queries.js +639 -367
- package/dist/epistemicEdges.queries.js.map +1 -1
- package/dist/epistemicEdges.types.d.ts +10 -8
- package/dist/epistemicEvidence.d.ts +4 -1
- package/dist/epistemicEvidence.js +933 -532
- package/dist/epistemicEvidence.js.map +1 -1
- package/dist/epistemicEvidenceHelpers.d.ts +26 -10
- package/dist/epistemicEvidenceHelpers.js +239 -200
- package/dist/epistemicEvidenceHelpers.js.map +1 -1
- package/dist/epistemicEvidenceMutations.d.ts +8 -8
- package/dist/epistemicEvidenceMutations.js +840 -692
- package/dist/epistemicEvidenceMutations.js.map +1 -1
- package/dist/epistemicEvidenceQueries.d.ts +8 -8
- package/dist/epistemicEvidenceQueries.js +514 -238
- package/dist/epistemicEvidenceQueries.js.map +1 -1
- package/dist/epistemicHelpers.d.ts +4 -2
- package/dist/epistemicHelpers.js +308 -134
- package/dist/epistemicHelpers.js.map +1 -1
- package/dist/epistemicInsert.d.ts +16 -4
- package/dist/epistemicInsert.js +6 -3
- package/dist/epistemicInsert.js.map +1 -1
- package/dist/epistemicLayerRules.d.ts +10 -8
- package/dist/epistemicLayerRules.js +1 -5
- package/dist/epistemicLayerRules.js.map +1 -1
- package/dist/{epistemicLinking-CfE00tHJ.d.ts → epistemicLinking-CsCDv2cN.d.ts} +3 -3
- package/dist/epistemicLinking.d.ts +1 -1
- package/dist/epistemicLinking.js +177 -100
- package/dist/epistemicLinking.js.map +1 -1
- package/dist/epistemicNodeCreation.d.ts +2 -0
- package/dist/epistemicNodeCreation.js +203 -40
- package/dist/epistemicNodeCreation.js.map +1 -1
- package/dist/{epistemicNodes-BCQxpYx_.d.ts → epistemicNodes-CokAgBHg.d.ts} +3 -3
- package/dist/epistemicNodes.d.ts +3 -3
- package/dist/epistemicNodes.helpers.d.ts +24 -15
- package/dist/epistemicNodes.helpers.js.map +1 -1
- package/dist/epistemicNodes.internal.d.ts +6 -6
- package/dist/epistemicNodes.internal.js +389 -319
- package/dist/epistemicNodes.internal.js.map +1 -1
- package/dist/epistemicNodes.js +700 -504
- package/dist/epistemicNodes.js.map +1 -1
- package/dist/epistemicNodes.mutations.d.ts +6 -6
- package/dist/epistemicNodes.mutations.js +560 -463
- package/dist/epistemicNodes.mutations.js.map +1 -1
- package/dist/epistemicNodes.queries.d.ts +8 -8
- package/dist/epistemicNodes.queries.js +311 -314
- package/dist/epistemicNodes.queries.js.map +1 -1
- package/dist/epistemicNodes.validators.d.ts +2 -2
- package/dist/epistemicNodes.validators.js.map +1 -1
- package/dist/epistemicQuestions.conviction.d.ts +8 -8
- package/dist/epistemicQuestions.conviction.js +665 -484
- package/dist/epistemicQuestions.conviction.js.map +1 -1
- package/dist/epistemicQuestions.create.d.ts +4 -4
- package/dist/epistemicQuestions.create.js +640 -612
- package/dist/epistemicQuestions.create.js.map +1 -1
- package/dist/epistemicQuestions.d.ts +8 -5
- package/dist/epistemicQuestions.evidence.d.ts +2 -2
- package/dist/epistemicQuestions.evidence.js +475 -383
- package/dist/epistemicQuestions.evidence.js.map +1 -1
- package/dist/epistemicQuestions.helpers.d.ts +125 -24
- package/dist/epistemicQuestions.helpers.js +240 -209
- package/dist/epistemicQuestions.helpers.js.map +1 -1
- package/dist/epistemicQuestions.js +3474 -2823
- package/dist/epistemicQuestions.js.map +1 -1
- package/dist/epistemicQuestions.lifecycle.d.ts +2 -2
- package/dist/epistemicQuestions.lifecycle.js +607 -546
- package/dist/epistemicQuestions.lifecycle.js.map +1 -1
- package/dist/epistemicQuestions.queries.d.ts +12 -7
- package/dist/epistemicQuestions.queries.js +305 -244
- package/dist/epistemicQuestions.queries.js.map +1 -1
- package/dist/epistemicQuestions.sprint.d.ts +2 -2
- package/dist/epistemicQuestions.sprint.js +600 -394
- package/dist/epistemicQuestions.sprint.js.map +1 -1
- package/dist/epistemicQuestions.tail.d.ts +6 -6
- package/dist/epistemicQuestions.tail.js +572 -433
- package/dist/epistemicQuestions.tail.js.map +1 -1
- package/dist/{epistemicSources-dlKj58Jp.d.ts → epistemicSources-DQtaEkWs.d.ts} +4 -4
- package/dist/epistemicSources.d.ts +1 -1
- package/dist/epistemicSources.js +351 -311
- package/dist/epistemicSources.js.map +1 -1
- package/dist/evaluators/index.d.ts +8 -6
- package/dist/evaluators/index.js +399 -167
- package/dist/evaluators/index.js.map +1 -1
- package/dist/evaluators/lint-checker-evaluator.d.ts +16 -0
- package/dist/evaluators/{lintCheckerEvaluator.js → lint-checker-evaluator.js} +10 -5
- package/dist/evaluators/lint-checker-evaluator.js.map +1 -0
- package/dist/evaluators/{sentryCheckerEvaluator.d.ts → sentry-checker-evaluator.d.ts} +7 -2
- package/dist/evaluators/{sentryCheckerEvaluator.js → sentry-checker-evaluator.js} +3 -3
- package/dist/evaluators/sentry-checker-evaluator.js.map +1 -0
- package/dist/evaluators/shared.d.ts +2 -2
- package/dist/evaluators/shared.js +3 -1
- package/dist/evaluators/shared.js.map +1 -1
- package/dist/evaluators/{testRunnerEvaluator.d.ts → test-runner-evaluator.d.ts} +6 -1
- package/dist/evaluators/{testRunnerEvaluator.js → test-runner-evaluator.js} +6 -4
- package/dist/evaluators/test-runner-evaluator.js.map +1 -0
- package/dist/evaluators/tsc-checker-evaluator.d.ts +16 -0
- package/dist/evaluators/{tscCheckerEvaluator.js → tsc-checker-evaluator.js} +10 -5
- package/dist/evaluators/tsc-checker-evaluator.js.map +1 -0
- package/dist/graphTypes.js +6 -2
- package/dist/graphTypes.js.map +1 -1
- package/dist/helpers.d.ts +2 -0
- package/dist/helpers.js +313 -93
- package/dist/helpers.js.map +1 -1
- package/dist/{index-C-Kyd7hD.d.ts → index-DZxyC9Pb.d.ts} +7 -6
- package/dist/index.d.ts +86 -83
- package/dist/index.js +16914 -11760
- package/dist/index.js.map +1 -1
- package/dist/invariantEnforcement.d.ts +3 -3
- package/dist/invariantEnforcement.js.map +1 -1
- package/dist/logicalRoleInference.d.ts +2 -0
- package/dist/logicalRoleInference.js +1 -1
- package/dist/logicalRoleInference.js.map +1 -1
- package/dist/matcherFeedbackUtils.d.ts +2 -2
- package/dist/matcherFeedbackUtils.js.map +1 -1
- package/dist/{ontology-matching-C6rrz2VP.d.ts → ontology-matching-C-mYFrir.d.ts} +16 -16
- package/dist/ontology-matching.d.ts +1 -1
- package/dist/{ontologyApproval-CFYmqKmk.d.ts → ontologyApproval-BVt0feJi.d.ts} +10 -10
- package/dist/ontologyApproval.d.ts +1 -1
- package/dist/ontologyApproval.js +7 -1
- package/dist/ontologyApproval.js.map +1 -1
- package/dist/ontologyDefinitions.d.ts +14 -24
- package/dist/ontologyDefinitions.js +269 -34
- package/dist/ontologyDefinitions.js.map +1 -1
- package/dist/ontologyHelpers.d.ts +13 -13
- package/dist/ontologyHelpers.js.map +1 -1
- package/dist/{ontologyRegistry-B67rPJ16.d.ts → ontologyRegistry-CljS-ENv.d.ts} +2 -2
- package/dist/ontologyRegistry.d.ts +1 -1
- package/dist/ontologyRegistry.js +34 -6
- package/dist/ontologyRegistry.js.map +1 -1
- package/dist/{projectionReconciliation-jww2fBI0.d.ts → projectionReconciliation-DnrSgHSQ.d.ts} +4 -4
- package/dist/projectionReconciliation.d.ts +1 -1
- package/dist/projectionReconciliation.js +57 -10
- package/dist/projectionReconciliation.js.map +1 -1
- package/dist/{projectionStaleness-CmdbpjVK.d.ts → projectionStaleness-C8ImQ2zP.d.ts} +17 -17
- package/dist/projectionStaleness.d.ts +1 -1
- package/dist/projectionStaleness.js +8 -2
- package/dist/projectionStaleness.js.map +1 -1
- package/dist/proof-attestation.json +1 -1
- package/dist/{questionEvidenceLinks-DFlyPpAj.d.ts → questionEvidenceLinks-_nPRa-LY.d.ts} +10 -10
- package/dist/questionEvidenceLinks.d.ts +1 -1
- package/dist/questionEvidenceLinks.js +564 -347
- package/dist/questionEvidenceLinks.js.map +1 -1
- package/dist/{resolverTypes-CC8Ea2E2.d.ts → resolverTypes-BOXPxLET.d.ts} +8 -7
- package/dist/resolverTypes.d.ts +4 -2
- package/dist/{resolvers-Br1a6eLV.d.ts → resolvers-B1TIBmRO.d.ts} +3 -1
- package/dist/resolvers.d.ts +5 -3
- package/dist/resolvers.js +121 -77
- package/dist/resolvers.js.map +1 -1
- package/dist/scopeResolverCompat.d.ts +10 -7
- package/dist/scopeResolverCompat.js +106 -123
- package/dist/scopeResolverCompat.js.map +1 -1
- package/dist/{text-matching-DNg4M5Wd.d.ts → text-matching-DzFooju6.d.ts} +7 -7
- package/dist/text-matching.d.ts +1 -1
- package/dist/topicOntologyResolver.d.ts +22 -21
- package/dist/topicOntologyResolver.js +54 -32
- package/dist/topicOntologyResolver.js.map +1 -1
- package/dist/topicProjectOverlay.d.ts +30 -20
- package/dist/topicProjectOverlay.js +120 -76
- package/dist/topicProjectOverlay.js.map +1 -1
- package/dist/{topicScope-7zhyeGl7.d.ts → topicScope-DJVa0mLa.d.ts} +22 -7
- package/dist/topicScope.d.ts +3 -1
- package/dist/topicScope.js +104 -119
- package/dist/topicScope.js.map +1 -1
- package/dist/workflowBridge.d.ts +26 -15
- package/dist/workflowBridge.js +140 -144
- package/dist/workflowBridge.js.map +1 -1
- package/dist/workspaceIsolation.d.ts +14 -12
- package/dist/workspaceIsolation.js +108 -122
- package/dist/workspaceIsolation.js.map +1 -1
- package/package.json +4 -4
- package/dist/edges/dependsOn.js.map +0 -1
- package/dist/edges/derivedFrom.js.map +0 -1
- package/dist/edges/propagationTypes.js.map +0 -1
- package/dist/evaluators/lintCheckerEvaluator.d.ts +0 -11
- package/dist/evaluators/lintCheckerEvaluator.js.map +0 -1
- package/dist/evaluators/sentryCheckerEvaluator.js.map +0 -1
- package/dist/evaluators/testRunnerEvaluator.js.map +0 -1
- package/dist/evaluators/tscCheckerEvaluator.d.ts +0 -11
- package/dist/evaluators/tscCheckerEvaluator.js.map +0 -1
- package/dist/{epistemicQuestions-bwHd2FWE.d.ts → epistemicQuestions-Do1fhYm5.d.ts} +4 -4
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { v } from 'convex/values';
|
|
2
|
-
import { normalizeTupleContradictionPolicy, mkOpinion, conditionalDeduction, project, dampedDependencyCascade, hasProjectedOpinionChanged, confidenceFromSL, detectTupleContradiction, evaluateTupleContradictionTransition, trustDiscount, applyNegativeSupport, cumulativeFusion, applyNegativeEvidence, readOpinionFromRecord } from '@lucern/confidence';
|
|
3
1
|
import { requireScopeWriteAccess } from '@lucern/access-control/access';
|
|
2
|
+
import { normalizeTupleContradictionPolicy, mkOpinion, conditionalDeduction, project, dampedDependencyCascade, trustDiscount, applyNegativeSupport, cumulativeFusion, applyNegativeEvidence, confidenceFromSL, detectTupleContradiction, evaluateTupleContradictionTransition, readOpinionFromRecord, hasProjectedOpinionChanged } from '@lucern/confidence';
|
|
4
3
|
import { permissiveReturn } from '@lucern/contracts/schema-helpers/validators';
|
|
5
|
-
import {
|
|
4
|
+
import { v } from 'convex/values';
|
|
6
5
|
import '@lucern/contracts/schema-helpers/spine/tables/epistemicNodes';
|
|
7
|
-
import {
|
|
6
|
+
import { unsafeConvexAnyApi } from '@lucern/contracts/convex/unsafeAnyApi';
|
|
7
|
+
import { componentsGeneric, internalMutationGeneric } from 'convex/server';
|
|
8
8
|
import '@lucern/access-control/audience';
|
|
9
9
|
import '@lucern/access-control/auth';
|
|
10
|
+
import { throwStructuredMutationError } from '@lucern/access-control/structuredMutationError';
|
|
10
11
|
|
|
11
12
|
// src/epistemicBeliefs.confidence.ts
|
|
12
13
|
|
|
@@ -130,10 +131,6 @@ function promoteBeliefStatusAfterScoring(status, opts) {
|
|
|
130
131
|
}
|
|
131
132
|
return status;
|
|
132
133
|
}
|
|
133
|
-
var api = anyApi;
|
|
134
|
-
componentsGeneric();
|
|
135
|
-
var internal = anyApi;
|
|
136
|
-
var internalMutation = internalMutationGeneric;
|
|
137
134
|
|
|
138
135
|
// src/edges/contains.ts
|
|
139
136
|
var containsPropagationSpec = {
|
|
@@ -270,7 +267,7 @@ var dependsOnPropagationSpec = {
|
|
|
270
267
|
description: "Structural gating. Textbook conditional deduction when edge conditionals exist, otherwise damped dependency cascade through downstream chains."
|
|
271
268
|
};
|
|
272
269
|
|
|
273
|
-
// src/edges/
|
|
270
|
+
// src/edges/derived-from.ts
|
|
274
271
|
var derivedFromPropagationSpec = {
|
|
275
272
|
edgeType: "derived_from",
|
|
276
273
|
direction: "incoming",
|
|
@@ -323,7 +320,7 @@ var informsPropagationSpec = {
|
|
|
323
320
|
description: "Evidence-bearing influence. Informs can chain through the graph with light per-hop damping."
|
|
324
321
|
};
|
|
325
322
|
|
|
326
|
-
// src/edges/
|
|
323
|
+
// src/edges/propagation-types.ts
|
|
327
324
|
function isPropagationTraversalDirection(direction) {
|
|
328
325
|
return direction === "outgoing" || direction === "incoming";
|
|
329
326
|
}
|
|
@@ -396,6 +393,9 @@ var testsPropagationSpec = {
|
|
|
396
393
|
};
|
|
397
394
|
|
|
398
395
|
// src/edges/index.ts
|
|
396
|
+
var canContinueTransitively2 = canContinueTransitively;
|
|
397
|
+
var canTraverseHop2 = canTraverseHop;
|
|
398
|
+
var isPropagationTraversalDirection2 = isPropagationTraversalDirection;
|
|
399
399
|
var EDGE_PROPAGATION_SPECS = [
|
|
400
400
|
supportsPropagationSpec,
|
|
401
401
|
informsPropagationSpec,
|
|
@@ -412,11 +412,18 @@ function getEdgePropagationSpecs() {
|
|
|
412
412
|
return EDGE_PROPAGATION_SPECS;
|
|
413
413
|
}
|
|
414
414
|
function getTraversalDirections(direction) {
|
|
415
|
-
if (
|
|
415
|
+
if (isPropagationTraversalDirection2(direction)) {
|
|
416
416
|
return [direction];
|
|
417
417
|
}
|
|
418
418
|
return ["outgoing", "incoming"];
|
|
419
419
|
}
|
|
420
|
+
var unsafeApi = unsafeConvexAnyApi(
|
|
421
|
+
"graph-primitives top-level module bundle lacks a committed Convex _generated/api surface"
|
|
422
|
+
);
|
|
423
|
+
var api = unsafeApi;
|
|
424
|
+
componentsGeneric();
|
|
425
|
+
var internal = unsafeApi;
|
|
426
|
+
var internalMutation = internalMutationGeneric;
|
|
420
427
|
|
|
421
428
|
// src/debug.ts
|
|
422
429
|
function isGraphPrimitiveDebugEnabled() {
|
|
@@ -465,13 +472,15 @@ function asMappedProjectId(topic) {
|
|
|
465
472
|
if (!topic) {
|
|
466
473
|
return;
|
|
467
474
|
}
|
|
468
|
-
const directLegacyProjectId = normalizeScopeValue(
|
|
475
|
+
const directLegacyProjectId = normalizeScopeValue(
|
|
476
|
+
topic[LEGACY_SCOPE_FIELD]
|
|
477
|
+
);
|
|
469
478
|
if (directLegacyProjectId) {
|
|
470
479
|
return directLegacyProjectId;
|
|
471
480
|
}
|
|
472
481
|
const metadata = topic.metadata || {};
|
|
473
482
|
const candidate = metadata[LEGACY_SCOPE_FIELD] || metadata.legacyProjectId || metadata.projectId || metadata.scopeProjectId;
|
|
474
|
-
return candidate ? candidate : void 0;
|
|
483
|
+
return typeof candidate === "string" ? normalizeScopeValue(candidate) : void 0;
|
|
475
484
|
}
|
|
476
485
|
function normalizeScopeValue(value) {
|
|
477
486
|
if (typeof value !== "string") {
|
|
@@ -496,8 +505,9 @@ function pickPrimaryTopic(candidates) {
|
|
|
496
505
|
})[0];
|
|
497
506
|
}
|
|
498
507
|
async function findTopicsByScopeAlias(ctx, scopeId) {
|
|
508
|
+
const query = ctx.db.query("topics");
|
|
499
509
|
try {
|
|
500
|
-
return await
|
|
510
|
+
return await query.withIndex(
|
|
501
511
|
"by_graph_scope_project",
|
|
502
512
|
(q) => q.eq(LEGACY_SCOPE_FIELD, scopeId)
|
|
503
513
|
).collect();
|
|
@@ -509,7 +519,7 @@ async function findTopicsByScopeAlias(ctx, scopeId) {
|
|
|
509
519
|
scopeId
|
|
510
520
|
}
|
|
511
521
|
);
|
|
512
|
-
const topics = await
|
|
522
|
+
const topics = await query.collect();
|
|
513
523
|
return topics.filter((topic) => {
|
|
514
524
|
const normalizedGlobalId = normalizeScopeValue(topic.globalId);
|
|
515
525
|
const mappedProjectId = asMappedProjectId(topic);
|
|
@@ -565,137 +575,115 @@ async function resolveInheritedWorkspaceScope(ctx, topic) {
|
|
|
565
575
|
let current = topic;
|
|
566
576
|
for (let i = 0; i < MAX_DEPTH && current?.parentTopicId; i++) {
|
|
567
577
|
current = await ctx.db.get(current.parentTopicId);
|
|
568
|
-
if (!current)
|
|
578
|
+
if (!current) {
|
|
579
|
+
break;
|
|
580
|
+
}
|
|
569
581
|
if (!tenantId) {
|
|
570
582
|
tenantId = normalizeScopeValue(current.tenantId);
|
|
571
583
|
}
|
|
572
584
|
if (!workspaceId) {
|
|
573
585
|
workspaceId = normalizeScopeValue(current.workspaceId);
|
|
574
586
|
}
|
|
575
|
-
if (tenantId && workspaceId)
|
|
587
|
+
if (tenantId && workspaceId) {
|
|
588
|
+
break;
|
|
589
|
+
}
|
|
576
590
|
}
|
|
577
591
|
return { tenantId, workspaceId };
|
|
578
592
|
}
|
|
579
593
|
async function resolveTopicProjectScope(ctx, args) {
|
|
580
594
|
if (args.topicId) {
|
|
581
|
-
|
|
582
|
-
try {
|
|
583
|
-
topic = await ctx.db.get(
|
|
584
|
-
args.topicId
|
|
585
|
-
);
|
|
586
|
-
} catch (error) {
|
|
587
|
-
debugGraphPrimitiveFallback(
|
|
588
|
-
"[topicScope] Failed to load topic by direct id",
|
|
589
|
-
{
|
|
590
|
-
error,
|
|
591
|
-
topicId: args.topicId
|
|
592
|
-
}
|
|
593
|
-
);
|
|
594
|
-
}
|
|
595
|
-
if (!topic) {
|
|
596
|
-
topic = await tryResolveHostTopicById(ctx, String(args.topicId));
|
|
597
|
-
}
|
|
598
|
-
if (!topic) {
|
|
599
|
-
topic = pickPrimaryTopic(
|
|
600
|
-
await findTopicsByScopeAlias(ctx, String(args.topicId))
|
|
601
|
-
) ?? null;
|
|
602
|
-
}
|
|
603
|
-
if (!topic) {
|
|
604
|
-
const nodeScope = await resolveTopicNodeScopeOrNull(
|
|
605
|
-
ctx,
|
|
606
|
-
String(args.topicId)
|
|
607
|
-
);
|
|
608
|
-
if (nodeScope) {
|
|
609
|
-
return nodeScope;
|
|
610
|
-
}
|
|
611
|
-
throw new Error(`Topic not found: ${String(args.topicId)}`);
|
|
612
|
-
}
|
|
613
|
-
const inherited = await resolveInheritedWorkspaceScope(ctx, topic);
|
|
614
|
-
const mapped = asMappedProjectId(topic);
|
|
615
|
-
if (mapped) {
|
|
616
|
-
return {
|
|
617
|
-
topicId: topic._id,
|
|
618
|
-
projectId: mapped,
|
|
619
|
-
tenantId: inherited.tenantId,
|
|
620
|
-
workspaceId: inherited.workspaceId,
|
|
621
|
-
source: "topic"
|
|
622
|
-
};
|
|
623
|
-
}
|
|
624
|
-
return {
|
|
625
|
-
topicId: topic._id,
|
|
626
|
-
tenantId: inherited.tenantId,
|
|
627
|
-
workspaceId: inherited.workspaceId,
|
|
628
|
-
source: "topic"
|
|
629
|
-
};
|
|
595
|
+
return await resolveScopeFromTopicId(ctx, args.topicId);
|
|
630
596
|
}
|
|
631
597
|
if (args.projectId) {
|
|
632
|
-
|
|
633
|
-
try {
|
|
634
|
-
directTopic = await ctx.db.get(
|
|
635
|
-
args.projectId
|
|
636
|
-
);
|
|
637
|
-
} catch (error) {
|
|
638
|
-
debugGraphPrimitiveFallback(
|
|
639
|
-
"[topicScope] Failed to load direct project topic",
|
|
640
|
-
{
|
|
641
|
-
error,
|
|
642
|
-
projectId: args.projectId
|
|
643
|
-
}
|
|
644
|
-
);
|
|
645
|
-
}
|
|
646
|
-
if (directTopic) {
|
|
647
|
-
const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);
|
|
648
|
-
const mapped = asMappedProjectId(directTopic);
|
|
649
|
-
return {
|
|
650
|
-
topicId: directTopic._id,
|
|
651
|
-
projectId: mapped ?? args.projectId,
|
|
652
|
-
tenantId: inherited.tenantId,
|
|
653
|
-
workspaceId: inherited.workspaceId,
|
|
654
|
-
source: "topic_inferred"
|
|
655
|
-
};
|
|
656
|
-
}
|
|
657
|
-
directTopic = await tryResolveHostTopicByLegacyScope(ctx, args.projectId);
|
|
658
|
-
if (directTopic) {
|
|
659
|
-
const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);
|
|
660
|
-
const mapped = asMappedProjectId(directTopic);
|
|
661
|
-
return {
|
|
662
|
-
topicId: directTopic._id,
|
|
663
|
-
projectId: mapped ?? args.projectId,
|
|
664
|
-
tenantId: inherited.tenantId,
|
|
665
|
-
workspaceId: inherited.workspaceId,
|
|
666
|
-
source: "topic_inferred"
|
|
667
|
-
};
|
|
668
|
-
}
|
|
669
|
-
const topics = await findTopicsByScopeAlias(ctx, args.projectId);
|
|
670
|
-
const primary = pickPrimaryTopic(topics);
|
|
671
|
-
if (primary) {
|
|
672
|
-
const inherited = await resolveInheritedWorkspaceScope(ctx, primary);
|
|
673
|
-
return {
|
|
674
|
-
topicId: primary._id,
|
|
675
|
-
projectId: args.projectId,
|
|
676
|
-
tenantId: inherited.tenantId,
|
|
677
|
-
workspaceId: inherited.workspaceId,
|
|
678
|
-
source: "project_mapped_topic"
|
|
679
|
-
};
|
|
680
|
-
}
|
|
681
|
-
const nodeScope = await resolveTopicNodeScopeOrNull(
|
|
682
|
-
ctx,
|
|
683
|
-
String(args.projectId)
|
|
684
|
-
);
|
|
685
|
-
if (nodeScope) {
|
|
686
|
-
return {
|
|
687
|
-
...nodeScope,
|
|
688
|
-
projectId: nodeScope.projectId ?? String(args.projectId)
|
|
689
|
-
};
|
|
690
|
-
}
|
|
691
|
-
throw new Error(
|
|
692
|
-
`Legacy project scope ${String(args.projectId)} has no mapped topic.`
|
|
693
|
-
);
|
|
598
|
+
return await resolveScopeFromLegacyProjectId(ctx, args.projectId);
|
|
694
599
|
}
|
|
695
600
|
throw new Error(
|
|
696
601
|
"Missing scope: provide topicId (preferred) or legacy projectId alias."
|
|
697
602
|
);
|
|
698
603
|
}
|
|
604
|
+
async function resolveScopeFromTopicId(ctx, topicId) {
|
|
605
|
+
const topic = await resolveTopicDocFromTopicId(ctx, topicId);
|
|
606
|
+
if (topic) {
|
|
607
|
+
return await buildTopicScope(ctx, topic, "topic");
|
|
608
|
+
}
|
|
609
|
+
const nodeScope = await resolveTopicNodeScopeOrNull(ctx, String(topicId));
|
|
610
|
+
if (nodeScope) {
|
|
611
|
+
return nodeScope;
|
|
612
|
+
}
|
|
613
|
+
throw new Error(`Topic not found: ${String(topicId)}`);
|
|
614
|
+
}
|
|
615
|
+
async function resolveTopicDocFromTopicId(ctx, topicId) {
|
|
616
|
+
const direct = await tryReadTopicDoc(ctx, topicId, {
|
|
617
|
+
failureLog: "[topicScope] Failed to load topic by direct id",
|
|
618
|
+
idLogKey: "topicId"
|
|
619
|
+
});
|
|
620
|
+
if (direct) {
|
|
621
|
+
return direct;
|
|
622
|
+
}
|
|
623
|
+
const hostTopic = await tryResolveHostTopicById(ctx, String(topicId));
|
|
624
|
+
if (hostTopic) {
|
|
625
|
+
return hostTopic;
|
|
626
|
+
}
|
|
627
|
+
return pickPrimaryTopic(await findTopicsByScopeAlias(ctx, String(topicId))) ?? null;
|
|
628
|
+
}
|
|
629
|
+
async function resolveScopeFromLegacyProjectId(ctx, legacyProjectId) {
|
|
630
|
+
const directTopic = await resolveDirectLegacyProjectTopic(
|
|
631
|
+
ctx,
|
|
632
|
+
legacyProjectId
|
|
633
|
+
);
|
|
634
|
+
if (directTopic) {
|
|
635
|
+
return await buildTopicScope(ctx, directTopic, "topic_inferred", {
|
|
636
|
+
fallbackProjectId: legacyProjectId
|
|
637
|
+
});
|
|
638
|
+
}
|
|
639
|
+
const primary = pickPrimaryTopic(
|
|
640
|
+
await findTopicsByScopeAlias(ctx, legacyProjectId)
|
|
641
|
+
);
|
|
642
|
+
if (primary) {
|
|
643
|
+
return await buildTopicScope(ctx, primary, "project_mapped_topic", {
|
|
644
|
+
fallbackProjectId: legacyProjectId
|
|
645
|
+
});
|
|
646
|
+
}
|
|
647
|
+
const nodeScope = await resolveTopicNodeScopeOrNull(ctx, legacyProjectId);
|
|
648
|
+
if (nodeScope) {
|
|
649
|
+
return {
|
|
650
|
+
...nodeScope,
|
|
651
|
+
projectId: nodeScope.projectId ?? legacyProjectId
|
|
652
|
+
};
|
|
653
|
+
}
|
|
654
|
+
throw new Error(
|
|
655
|
+
`Legacy project scope ${legacyProjectId} has no mapped topic.`
|
|
656
|
+
);
|
|
657
|
+
}
|
|
658
|
+
async function resolveDirectLegacyProjectTopic(ctx, legacyProjectId) {
|
|
659
|
+
const directTopic = await tryReadTopicDoc(ctx, legacyProjectId, {
|
|
660
|
+
failureLog: "[topicScope] Failed to load direct project topic",
|
|
661
|
+
idLogKey: "projectId"
|
|
662
|
+
});
|
|
663
|
+
return directTopic ?? tryResolveHostTopicByLegacyScope(ctx, legacyProjectId);
|
|
664
|
+
}
|
|
665
|
+
async function tryReadTopicDoc(ctx, id, log) {
|
|
666
|
+
try {
|
|
667
|
+
return await ctx.db.get(id);
|
|
668
|
+
} catch (error) {
|
|
669
|
+
debugGraphPrimitiveFallback(log.failureLog, {
|
|
670
|
+
error,
|
|
671
|
+
[log.idLogKey]: id
|
|
672
|
+
});
|
|
673
|
+
return null;
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
async function buildTopicScope(ctx, topic, source, options = {}) {
|
|
677
|
+
const inherited = await resolveInheritedWorkspaceScope(ctx, topic);
|
|
678
|
+
const mapped = asMappedProjectId(topic);
|
|
679
|
+
return {
|
|
680
|
+
topicId: topic._id,
|
|
681
|
+
...mapped || options.fallbackProjectId ? { projectId: mapped ?? options.fallbackProjectId } : {},
|
|
682
|
+
tenantId: inherited.tenantId,
|
|
683
|
+
workspaceId: inherited.workspaceId,
|
|
684
|
+
source
|
|
685
|
+
};
|
|
686
|
+
}
|
|
699
687
|
({
|
|
700
688
|
projectId: v.optional(v.string()),
|
|
701
689
|
topicId: v.optional(v.string())
|
|
@@ -765,9 +753,10 @@ async function resolveNodeScopeForWorkspaceIsolation(ctx, node) {
|
|
|
765
753
|
if (resolved.tenantId || resolved.workspaceId) {
|
|
766
754
|
return resolved;
|
|
767
755
|
}
|
|
768
|
-
|
|
756
|
+
const topicId = normalizeScopeValue2(node.topicId);
|
|
757
|
+
if (topicId) {
|
|
769
758
|
const topicScope = await resolveTopicProjectScope(ctx, {
|
|
770
|
-
topicId
|
|
759
|
+
topicId
|
|
771
760
|
});
|
|
772
761
|
return {
|
|
773
762
|
...resolved,
|
|
@@ -789,9 +778,8 @@ async function resolveNodeScopeForWorkspaceIsolation(ctx, node) {
|
|
|
789
778
|
}
|
|
790
779
|
|
|
791
780
|
// src/confidencePropagationDispatch.ts
|
|
792
|
-
function
|
|
793
|
-
|
|
794
|
-
return targetNodeId ?? void 0;
|
|
781
|
+
function nodeIdToCacheKey(nodeId) {
|
|
782
|
+
return String(nodeId);
|
|
795
783
|
}
|
|
796
784
|
function readNodeOpinion(node) {
|
|
797
785
|
const metadata = node.metadata ?? {};
|
|
@@ -807,112 +795,168 @@ function readNodeOpinion(node) {
|
|
|
807
795
|
return mkOpinion(0, 0, 1, 0.5);
|
|
808
796
|
}
|
|
809
797
|
}
|
|
798
|
+
function resolveTraversalTargetNodeId(edge, direction) {
|
|
799
|
+
const targetNodeId = direction === "outgoing" ? edge.toNodeId : edge.fromNodeId;
|
|
800
|
+
return targetNodeId ?? void 0;
|
|
801
|
+
}
|
|
802
|
+
function buildInitialState(sourceNodeId, sourceOpinion) {
|
|
803
|
+
return {
|
|
804
|
+
nodeId: sourceNodeId,
|
|
805
|
+
opinion: sourceOpinion,
|
|
806
|
+
hop: 0,
|
|
807
|
+
visitedNodeIds: /* @__PURE__ */ new Set([nodeIdToCacheKey(sourceNodeId)])
|
|
808
|
+
};
|
|
809
|
+
}
|
|
810
|
+
function extendVisited(currentVisited, targetNodeId) {
|
|
811
|
+
return /* @__PURE__ */ new Set([...currentVisited, nodeIdToCacheKey(targetNodeId)]);
|
|
812
|
+
}
|
|
813
|
+
function makeTransitiveState(current, targetNodeId, projectedOpinion, nextHop) {
|
|
814
|
+
return {
|
|
815
|
+
nodeId: targetNodeId,
|
|
816
|
+
opinion: projectedOpinion,
|
|
817
|
+
hop: nextHop,
|
|
818
|
+
visitedNodeIds: extendVisited(current.visitedNodeIds, targetNodeId)
|
|
819
|
+
};
|
|
820
|
+
}
|
|
821
|
+
function makeDispatchRecord(targetNodeId, spec, direction, edge, projectedOpinion, nextHop, result, existingDispatch) {
|
|
822
|
+
return {
|
|
823
|
+
targetNodeId,
|
|
824
|
+
edgeType: spec.edgeType,
|
|
825
|
+
traversedDirection: direction,
|
|
826
|
+
weight: edge.weight ?? 1,
|
|
827
|
+
opinion: projectedOpinion,
|
|
828
|
+
operator: result.operator,
|
|
829
|
+
rationale: existingDispatch ? `${existingDispatch.rationale}; ${result.rationale}` : result.rationale,
|
|
830
|
+
hop: nextHop
|
|
831
|
+
};
|
|
832
|
+
}
|
|
833
|
+
async function loadCachedNode(scope, nodeId) {
|
|
834
|
+
const cacheKey = nodeIdToCacheKey(nodeId);
|
|
835
|
+
if (!scope.nodeCache.has(cacheKey)) {
|
|
836
|
+
scope.nodeCache.set(cacheKey, await scope.args.getNode(nodeId));
|
|
837
|
+
}
|
|
838
|
+
return scope.nodeCache.get(cacheKey) ?? null;
|
|
839
|
+
}
|
|
840
|
+
async function collectTargetDispatch(state, nextHop, spec, direction, edge, queue, scope) {
|
|
841
|
+
const sourceScope = scope.args.sourceScope;
|
|
842
|
+
if (sourceScope && !edgeMatchesWorkspaceReasoningScope(edge, sourceScope)) {
|
|
843
|
+
return;
|
|
844
|
+
}
|
|
845
|
+
const targetNodeId = resolveTraversalTargetNodeId(edge, direction);
|
|
846
|
+
if (!targetNodeId) {
|
|
847
|
+
return;
|
|
848
|
+
}
|
|
849
|
+
const targetNodeIdKey = nodeIdToCacheKey(targetNodeId);
|
|
850
|
+
if (state.visitedNodeIds.has(targetNodeIdKey)) {
|
|
851
|
+
return;
|
|
852
|
+
}
|
|
853
|
+
const targetNode = await loadCachedNode(scope, targetNodeId);
|
|
854
|
+
if (targetNode?.nodeType !== "belief") {
|
|
855
|
+
return;
|
|
856
|
+
}
|
|
857
|
+
if (sourceScope && !nodeMatchesWorkspaceReasoningScope(targetNode, sourceScope)) {
|
|
858
|
+
return;
|
|
859
|
+
}
|
|
860
|
+
const targetOpinion = scope.opinionCache.get(targetNodeIdKey) ?? readNodeOpinion(targetNode);
|
|
861
|
+
const result = spec.operator(state.opinion, targetOpinion, edge, {
|
|
862
|
+
hop: nextHop,
|
|
863
|
+
sourceNodeId: state.nodeId,
|
|
864
|
+
targetNodeId,
|
|
865
|
+
traversedDirection: direction,
|
|
866
|
+
spec
|
|
867
|
+
});
|
|
868
|
+
if (!(result && hasProjectedOpinionChanged(targetOpinion, result.opinion))) {
|
|
869
|
+
return;
|
|
870
|
+
}
|
|
871
|
+
const projectedOpinion = mkOpinion(
|
|
872
|
+
result.opinion.b,
|
|
873
|
+
result.opinion.d,
|
|
874
|
+
result.opinion.u,
|
|
875
|
+
result.opinion.a
|
|
876
|
+
);
|
|
877
|
+
scope.opinionCache.set(targetNodeIdKey, projectedOpinion);
|
|
878
|
+
const existingDispatch = scope.dispatchesByTargetId.get(targetNodeIdKey);
|
|
879
|
+
scope.dispatchesByTargetId.set(
|
|
880
|
+
targetNodeIdKey,
|
|
881
|
+
makeDispatchRecord(
|
|
882
|
+
targetNodeId,
|
|
883
|
+
spec,
|
|
884
|
+
direction,
|
|
885
|
+
edge,
|
|
886
|
+
projectedOpinion,
|
|
887
|
+
nextHop,
|
|
888
|
+
result,
|
|
889
|
+
existingDispatch
|
|
890
|
+
)
|
|
891
|
+
);
|
|
892
|
+
if (canContinueTransitively2(spec, nextHop)) {
|
|
893
|
+
queue.push(
|
|
894
|
+
makeTransitiveState(state, targetNodeId, projectedOpinion, nextHop)
|
|
895
|
+
);
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
async function processTraversalSpec(state, nextHop, spec, queue, scope) {
|
|
899
|
+
const sourceNodeId = state.nodeId;
|
|
900
|
+
for (const direction of getTraversalDirections(spec.direction)) {
|
|
901
|
+
const edges = await scope.args.queryEdges({
|
|
902
|
+
nodeId: sourceNodeId,
|
|
903
|
+
spec,
|
|
904
|
+
direction,
|
|
905
|
+
hop: nextHop
|
|
906
|
+
});
|
|
907
|
+
for (const edge of edges) {
|
|
908
|
+
await collectTargetDispatch(
|
|
909
|
+
state,
|
|
910
|
+
nextHop,
|
|
911
|
+
spec,
|
|
912
|
+
direction,
|
|
913
|
+
edge,
|
|
914
|
+
queue,
|
|
915
|
+
scope
|
|
916
|
+
);
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
async function processQueuedState(state, queue, scope) {
|
|
921
|
+
const nextHop = state.hop + 1;
|
|
922
|
+
for (const spec of scope.traversalSpecs) {
|
|
923
|
+
if (!canTraverseHop2(spec, nextHop)) {
|
|
924
|
+
continue;
|
|
925
|
+
}
|
|
926
|
+
await processTraversalSpec(state, nextHop, spec, queue, scope);
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
function sortDispatches(dispatches) {
|
|
930
|
+
return Array.from(dispatches).sort((left, right) => {
|
|
931
|
+
if (left.hop !== right.hop) {
|
|
932
|
+
return left.hop - right.hop;
|
|
933
|
+
}
|
|
934
|
+
return String(left.targetNodeId).localeCompare(String(right.targetNodeId));
|
|
935
|
+
});
|
|
936
|
+
}
|
|
810
937
|
async function collectConfidencePropagationDispatches(args) {
|
|
811
938
|
const dispatchesByTargetId = /* @__PURE__ */ new Map();
|
|
812
939
|
const opinionCache = /* @__PURE__ */ new Map();
|
|
813
940
|
const nodeCache = /* @__PURE__ */ new Map();
|
|
814
941
|
const traversalSpecs = args.traversalSpecs ?? getEdgePropagationSpecs();
|
|
942
|
+
const scope = {
|
|
943
|
+
args,
|
|
944
|
+
dispatchesByTargetId,
|
|
945
|
+
opinionCache,
|
|
946
|
+
nodeCache,
|
|
947
|
+
traversalSpecs
|
|
948
|
+
};
|
|
815
949
|
const queue = [
|
|
816
|
-
|
|
817
|
-
nodeId: args.sourceNodeId,
|
|
818
|
-
opinion: args.sourceOpinion,
|
|
819
|
-
hop: 0,
|
|
820
|
-
visitedNodeIds: /* @__PURE__ */ new Set([String(args.sourceNodeId)])
|
|
821
|
-
}
|
|
950
|
+
buildInitialState(args.sourceNodeId, args.sourceOpinion)
|
|
822
951
|
];
|
|
823
|
-
const loadNode = async (nodeId) => {
|
|
824
|
-
const cacheKey = String(nodeId);
|
|
825
|
-
if (!nodeCache.has(cacheKey)) {
|
|
826
|
-
nodeCache.set(cacheKey, await args.getNode(nodeId));
|
|
827
|
-
}
|
|
828
|
-
return nodeCache.get(cacheKey) ?? null;
|
|
829
|
-
};
|
|
830
952
|
while (queue.length > 0) {
|
|
831
953
|
const state = queue.shift();
|
|
832
954
|
if (!state) {
|
|
833
955
|
continue;
|
|
834
956
|
}
|
|
835
|
-
|
|
836
|
-
const nextHop = state.hop + 1;
|
|
837
|
-
if (!canTraverseHop(spec, nextHop)) {
|
|
838
|
-
continue;
|
|
839
|
-
}
|
|
840
|
-
for (const direction of getTraversalDirections(spec.direction)) {
|
|
841
|
-
const edges = await args.queryEdges({
|
|
842
|
-
nodeId: state.nodeId,
|
|
843
|
-
spec,
|
|
844
|
-
direction,
|
|
845
|
-
hop: nextHop
|
|
846
|
-
});
|
|
847
|
-
for (const edge of edges) {
|
|
848
|
-
if (args.sourceScope && !edgeMatchesWorkspaceReasoningScope(edge, args.sourceScope)) {
|
|
849
|
-
continue;
|
|
850
|
-
}
|
|
851
|
-
const targetNodeId = resolveTraversalTargetNodeId(edge, direction);
|
|
852
|
-
if (!targetNodeId) {
|
|
853
|
-
continue;
|
|
854
|
-
}
|
|
855
|
-
if (state.visitedNodeIds.has(String(targetNodeId))) {
|
|
856
|
-
continue;
|
|
857
|
-
}
|
|
858
|
-
const targetNode = await loadNode(targetNodeId);
|
|
859
|
-
if (!targetNode || targetNode.nodeType !== "belief") {
|
|
860
|
-
continue;
|
|
861
|
-
}
|
|
862
|
-
if (args.sourceScope && !nodeMatchesWorkspaceReasoningScope(targetNode, args.sourceScope)) {
|
|
863
|
-
continue;
|
|
864
|
-
}
|
|
865
|
-
const cacheKey = String(targetNodeId);
|
|
866
|
-
const targetOpinion = opinionCache.get(cacheKey) ?? readNodeOpinion(targetNode);
|
|
867
|
-
const result = spec.operator(state.opinion, targetOpinion, edge, {
|
|
868
|
-
hop: nextHop,
|
|
869
|
-
sourceNodeId: state.nodeId,
|
|
870
|
-
targetNodeId,
|
|
871
|
-
traversedDirection: direction,
|
|
872
|
-
spec
|
|
873
|
-
});
|
|
874
|
-
if (!result || !hasProjectedOpinionChanged(targetOpinion, result.opinion)) {
|
|
875
|
-
continue;
|
|
876
|
-
}
|
|
877
|
-
const projectedOpinion = mkOpinion(
|
|
878
|
-
result.opinion.b,
|
|
879
|
-
result.opinion.d,
|
|
880
|
-
result.opinion.u,
|
|
881
|
-
result.opinion.a
|
|
882
|
-
);
|
|
883
|
-
opinionCache.set(cacheKey, projectedOpinion);
|
|
884
|
-
const existingDispatch = dispatchesByTargetId.get(cacheKey);
|
|
885
|
-
dispatchesByTargetId.set(cacheKey, {
|
|
886
|
-
targetNodeId,
|
|
887
|
-
edgeType: spec.edgeType,
|
|
888
|
-
traversedDirection: direction,
|
|
889
|
-
weight: edge.weight ?? 1,
|
|
890
|
-
opinion: projectedOpinion,
|
|
891
|
-
operator: result.operator,
|
|
892
|
-
rationale: existingDispatch ? `${existingDispatch.rationale}; ${result.rationale}` : result.rationale,
|
|
893
|
-
hop: nextHop
|
|
894
|
-
});
|
|
895
|
-
if (canContinueTransitively(spec, nextHop)) {
|
|
896
|
-
queue.push({
|
|
897
|
-
nodeId: targetNodeId,
|
|
898
|
-
opinion: projectedOpinion,
|
|
899
|
-
hop: nextHop,
|
|
900
|
-
visitedNodeIds: /* @__PURE__ */ new Set([
|
|
901
|
-
...state.visitedNodeIds,
|
|
902
|
-
String(targetNodeId)
|
|
903
|
-
])
|
|
904
|
-
});
|
|
905
|
-
}
|
|
906
|
-
}
|
|
907
|
-
}
|
|
908
|
-
}
|
|
957
|
+
await processQueuedState(state, queue, scope);
|
|
909
958
|
}
|
|
910
|
-
return
|
|
911
|
-
if (left.hop !== right.hop) {
|
|
912
|
-
return left.hop - right.hop;
|
|
913
|
-
}
|
|
914
|
-
return String(left.targetNodeId).localeCompare(String(right.targetNodeId));
|
|
915
|
-
});
|
|
959
|
+
return sortDispatches(dispatchesByTargetId.values());
|
|
916
960
|
}
|
|
917
961
|
v.id("epistemicNodes");
|
|
918
962
|
var DEFAULT_CONFIDENCE_POLICY = {
|
|
@@ -993,7 +1037,10 @@ function resolveBeliefStatus(node, metadata) {
|
|
|
993
1037
|
});
|
|
994
1038
|
}
|
|
995
1039
|
async function hasCompletedWorktreeForBelief(ctx, beliefNodeId) {
|
|
996
|
-
const clusterMembership = await ctx.db.query("worktreeBeliefCluster").withIndex(
|
|
1040
|
+
const clusterMembership = await ctx.db.query("worktreeBeliefCluster").withIndex(
|
|
1041
|
+
"by_belief",
|
|
1042
|
+
(q) => q.eq("beliefId", beliefNodeId)
|
|
1043
|
+
).collect();
|
|
997
1044
|
for (const membership of clusterMembership) {
|
|
998
1045
|
const worktree = await ctx.db.get(membership.worktreeId);
|
|
999
1046
|
if (worktree?.status === "completed" || worktree?.status === "merged") {
|
|
@@ -1004,7 +1051,10 @@ async function hasCompletedWorktreeForBelief(ctx, beliefNodeId) {
|
|
|
1004
1051
|
}
|
|
1005
1052
|
async function getActiveConfidencePolicy(ctx) {
|
|
1006
1053
|
try {
|
|
1007
|
-
const activeConfig = await ctx.db.query("logicSprintScoring").withIndex(
|
|
1054
|
+
const activeConfig = await ctx.db.query("logicSprintScoring").withIndex(
|
|
1055
|
+
"by_active",
|
|
1056
|
+
(q) => q.eq("isActive", true)
|
|
1057
|
+
).first();
|
|
1008
1058
|
return {
|
|
1009
1059
|
scoringMode: activeConfig?.confidencePolicy === "always" ? "always" : DEFAULT_CONFIDENCE_POLICY.scoringMode,
|
|
1010
1060
|
tupleContradiction: normalizeTupleContradictionPolicy(
|
|
@@ -1023,9 +1073,189 @@ async function getActiveConfidencePolicy(ctx) {
|
|
|
1023
1073
|
}
|
|
1024
1074
|
|
|
1025
1075
|
// src/epistemicBeliefs.confidence.ts
|
|
1076
|
+
function isRecord(value) {
|
|
1077
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
1078
|
+
}
|
|
1079
|
+
function readConvexId(value) {
|
|
1080
|
+
return typeof value === "string" && value.trim().length > 0 ? value : void 0;
|
|
1081
|
+
}
|
|
1082
|
+
function readOptionalBoolean(value) {
|
|
1083
|
+
return typeof value === "boolean" ? value : void 0;
|
|
1084
|
+
}
|
|
1085
|
+
function readOptionalNumber(value) {
|
|
1086
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
1087
|
+
}
|
|
1088
|
+
function readOptionalString(value) {
|
|
1089
|
+
return typeof value === "string" && value.trim().length > 0 ? value : void 0;
|
|
1090
|
+
}
|
|
1091
|
+
function readRecord(value) {
|
|
1092
|
+
return isRecord(value) ? value : void 0;
|
|
1093
|
+
}
|
|
1094
|
+
function readConfidenceBeliefNode(value) {
|
|
1095
|
+
if (!isRecord(value)) {
|
|
1096
|
+
return null;
|
|
1097
|
+
}
|
|
1098
|
+
const id = readConvexId(value._id);
|
|
1099
|
+
const nodeType = readOptionalString(value.nodeType);
|
|
1100
|
+
const projectId = readOptionalString(value.projectId);
|
|
1101
|
+
if (!(id && nodeType === "belief" && projectId)) {
|
|
1102
|
+
return null;
|
|
1103
|
+
}
|
|
1104
|
+
const node = {
|
|
1105
|
+
_id: id,
|
|
1106
|
+
nodeType,
|
|
1107
|
+
projectId
|
|
1108
|
+
};
|
|
1109
|
+
const confidence = readOptionalNumber(value.confidence);
|
|
1110
|
+
const epistemicLayer = readOptionalString(value.epistemicLayer);
|
|
1111
|
+
const globalId = readOptionalString(value.globalId);
|
|
1112
|
+
const metadata = readRecord(value.metadata);
|
|
1113
|
+
const opinionA = readOptionalNumber(value.opinion_a);
|
|
1114
|
+
const opinionB = readOptionalNumber(value.opinion_b);
|
|
1115
|
+
const opinionD = readOptionalNumber(value.opinion_d);
|
|
1116
|
+
const opinionU = readOptionalNumber(value.opinion_u);
|
|
1117
|
+
const predictionMeta = readRecord(value.predictionMeta);
|
|
1118
|
+
const publicationStatus = readOptionalString(value.publicationStatus);
|
|
1119
|
+
const status = readOptionalString(value.status);
|
|
1120
|
+
const tenantId = readOptionalString(value.tenantId);
|
|
1121
|
+
const topicId = readOptionalString(value.topicId);
|
|
1122
|
+
const tupleContradicted = readOptionalBoolean(value.tupleContradicted);
|
|
1123
|
+
const workspaceId = readOptionalString(value.workspaceId);
|
|
1124
|
+
if (confidence !== void 0) {
|
|
1125
|
+
node.confidence = confidence;
|
|
1126
|
+
}
|
|
1127
|
+
if (epistemicLayer !== void 0) {
|
|
1128
|
+
node.epistemicLayer = epistemicLayer;
|
|
1129
|
+
}
|
|
1130
|
+
if (globalId !== void 0) {
|
|
1131
|
+
node.globalId = globalId;
|
|
1132
|
+
}
|
|
1133
|
+
if (metadata !== void 0) {
|
|
1134
|
+
node.metadata = metadata;
|
|
1135
|
+
}
|
|
1136
|
+
if (opinionA !== void 0) {
|
|
1137
|
+
node.opinion_a = opinionA;
|
|
1138
|
+
}
|
|
1139
|
+
if (opinionB !== void 0) {
|
|
1140
|
+
node.opinion_b = opinionB;
|
|
1141
|
+
}
|
|
1142
|
+
if (opinionD !== void 0) {
|
|
1143
|
+
node.opinion_d = opinionD;
|
|
1144
|
+
}
|
|
1145
|
+
if (opinionU !== void 0) {
|
|
1146
|
+
node.opinion_u = opinionU;
|
|
1147
|
+
}
|
|
1148
|
+
if (predictionMeta !== void 0) {
|
|
1149
|
+
node.predictionMeta = predictionMeta;
|
|
1150
|
+
}
|
|
1151
|
+
if (publicationStatus !== void 0) {
|
|
1152
|
+
node.publicationStatus = publicationStatus;
|
|
1153
|
+
}
|
|
1154
|
+
if (status !== void 0) {
|
|
1155
|
+
node.status = status;
|
|
1156
|
+
}
|
|
1157
|
+
if (tenantId !== void 0) {
|
|
1158
|
+
node.tenantId = tenantId;
|
|
1159
|
+
}
|
|
1160
|
+
if (topicId !== void 0) {
|
|
1161
|
+
node.topicId = topicId;
|
|
1162
|
+
}
|
|
1163
|
+
if (tupleContradicted !== void 0) {
|
|
1164
|
+
node.tupleContradicted = tupleContradicted;
|
|
1165
|
+
}
|
|
1166
|
+
if (workspaceId !== void 0) {
|
|
1167
|
+
node.workspaceId = workspaceId;
|
|
1168
|
+
}
|
|
1169
|
+
return node;
|
|
1170
|
+
}
|
|
1171
|
+
function readPropagationEdge(value) {
|
|
1172
|
+
if (!isRecord(value)) {
|
|
1173
|
+
return null;
|
|
1174
|
+
}
|
|
1175
|
+
const edgeType = readOptionalString(value.edgeType);
|
|
1176
|
+
if (!edgeType) {
|
|
1177
|
+
return null;
|
|
1178
|
+
}
|
|
1179
|
+
const edge = { edgeType };
|
|
1180
|
+
const fromNodeId = readConvexId(value.fromNodeId);
|
|
1181
|
+
const tenantId = readOptionalString(value.tenantId);
|
|
1182
|
+
const toNodeId = readConvexId(value.toNodeId);
|
|
1183
|
+
const weight = readOptionalNumber(value.weight);
|
|
1184
|
+
const workspaceId = readOptionalString(value.workspaceId);
|
|
1185
|
+
if (fromNodeId !== void 0) {
|
|
1186
|
+
edge.fromNodeId = fromNodeId;
|
|
1187
|
+
}
|
|
1188
|
+
if (tenantId !== void 0) {
|
|
1189
|
+
edge.tenantId = tenantId;
|
|
1190
|
+
}
|
|
1191
|
+
if (toNodeId !== void 0) {
|
|
1192
|
+
edge.toNodeId = toNodeId;
|
|
1193
|
+
}
|
|
1194
|
+
if (weight !== void 0) {
|
|
1195
|
+
edge.weight = weight;
|
|
1196
|
+
}
|
|
1197
|
+
if (workspaceId !== void 0) {
|
|
1198
|
+
edge.workspaceId = workspaceId;
|
|
1199
|
+
}
|
|
1200
|
+
return edge;
|
|
1201
|
+
}
|
|
1202
|
+
function readRowList(values, reader) {
|
|
1203
|
+
return values.flatMap((value) => {
|
|
1204
|
+
const row = reader(value);
|
|
1205
|
+
return row ? [row] : [];
|
|
1206
|
+
});
|
|
1207
|
+
}
|
|
1026
1208
|
async function applyBeliefConfidenceChange(ctx, args) {
|
|
1027
1209
|
const now = Date.now();
|
|
1028
|
-
const node = await ctx
|
|
1210
|
+
const node = await requireConfidenceBeliefNode(ctx, args);
|
|
1211
|
+
const state = await buildConfidenceChangeState(ctx, node, args);
|
|
1212
|
+
await assertConfidenceScoringPolicySatisfied(ctx, args, state);
|
|
1213
|
+
const tupleContradictionId = await createTupleContradictionIfNeeded(
|
|
1214
|
+
ctx,
|
|
1215
|
+
args,
|
|
1216
|
+
node,
|
|
1217
|
+
state
|
|
1218
|
+
);
|
|
1219
|
+
await patchBeliefConfidenceState(ctx, args, state);
|
|
1220
|
+
await scheduleFirstScoringThemeEdges(ctx, args, node, state);
|
|
1221
|
+
const beliefConfidenceId = await insertBeliefConfidenceRecord(
|
|
1222
|
+
ctx,
|
|
1223
|
+
args,
|
|
1224
|
+
state,
|
|
1225
|
+
tupleContradictionId,
|
|
1226
|
+
now
|
|
1227
|
+
);
|
|
1228
|
+
await ctx.scheduler.runAfter(0, internal.neo4jSync.syncNodeToNeo4j, {
|
|
1229
|
+
nodeId: args.nodeId,
|
|
1230
|
+
operation: "upsert"
|
|
1231
|
+
});
|
|
1232
|
+
await insertConfidenceAudit(
|
|
1233
|
+
ctx,
|
|
1234
|
+
args,
|
|
1235
|
+
node,
|
|
1236
|
+
state,
|
|
1237
|
+
tupleContradictionId,
|
|
1238
|
+
now
|
|
1239
|
+
);
|
|
1240
|
+
await insertTupleTransitionAuditIfNeeded(
|
|
1241
|
+
ctx,
|
|
1242
|
+
args,
|
|
1243
|
+
node,
|
|
1244
|
+
state,
|
|
1245
|
+
tupleContradictionId,
|
|
1246
|
+
now
|
|
1247
|
+
);
|
|
1248
|
+
await scheduleConfidenceFollowups(ctx, args, node, state);
|
|
1249
|
+
return {
|
|
1250
|
+
nodeId: args.nodeId,
|
|
1251
|
+
previousConfidence: state.previousConfidence,
|
|
1252
|
+
newConfidence: state.derivedConfidence,
|
|
1253
|
+
opinion: state.nextOpinion,
|
|
1254
|
+
beliefConfidenceId
|
|
1255
|
+
};
|
|
1256
|
+
}
|
|
1257
|
+
async function requireConfidenceBeliefNode(ctx, args) {
|
|
1258
|
+
const node = readConfidenceBeliefNode(await ctx.db.get(args.nodeId));
|
|
1029
1259
|
if (!node) {
|
|
1030
1260
|
throwStructuredMutationError({
|
|
1031
1261
|
message: "Node not found.",
|
|
@@ -1036,59 +1266,28 @@ async function applyBeliefConfidenceChange(ctx, args) {
|
|
|
1036
1266
|
details: { nodeId: args.nodeId }
|
|
1037
1267
|
});
|
|
1038
1268
|
}
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
invariantCode: "entity.no_confidence",
|
|
1045
|
-
suggestion: "Use entityLifecycle.updateEntityAttributes for entity mutations. appendSlScoring is for belief nodes only.",
|
|
1046
|
-
details: { nodeId: args.nodeId, nodeType: node.nodeType }
|
|
1047
|
-
});
|
|
1048
|
-
}
|
|
1049
|
-
if (!node.projectId) {
|
|
1050
|
-
throwStructuredMutationError({
|
|
1051
|
-
message: "Belief has no project scope.",
|
|
1052
|
-
status: 400,
|
|
1053
|
-
code: "MISSING_SCOPE",
|
|
1054
|
-
invariantCode: "belief.project_required",
|
|
1055
|
-
suggestion: "Belief must have a projectId before SL scoring can be appended.",
|
|
1056
|
-
details: { nodeId: args.nodeId }
|
|
1057
|
-
});
|
|
1058
|
-
}
|
|
1059
|
-
await requireScopeWriteAccess(
|
|
1060
|
-
ctx,
|
|
1061
|
-
node.projectId,
|
|
1062
|
-
args.authenticatedUserId
|
|
1063
|
-
);
|
|
1064
|
-
const existingMetadata = node.metadata || {};
|
|
1269
|
+
await requireScopeWriteAccess(ctx, node.projectId, args.authenticatedUserId);
|
|
1270
|
+
return node;
|
|
1271
|
+
}
|
|
1272
|
+
async function buildConfidenceChangeState(ctx, node, args) {
|
|
1273
|
+
const existingMetadata = readNodeMetadata(node);
|
|
1065
1274
|
const currentBeliefStatus = resolveBeliefStatus(node, existingMetadata);
|
|
1066
1275
|
const confidencePolicy = await getActiveConfidencePolicy(ctx);
|
|
1067
|
-
if (confidencePolicy.scoringMode === "after_worktree" && isPreValidationBeliefStatus(currentBeliefStatus)) {
|
|
1068
|
-
const hasCompletedWorktree = await hasCompletedWorktreeForBelief(
|
|
1069
|
-
ctx,
|
|
1070
|
-
args.nodeId
|
|
1071
|
-
);
|
|
1072
|
-
if (!hasCompletedWorktree) {
|
|
1073
|
-
throwStructuredMutationError({
|
|
1074
|
-
message: "Cannot score belief before worktree completion. Complete a worktree that tests this belief first.",
|
|
1075
|
-
status: 409,
|
|
1076
|
-
code: "CONFLICT",
|
|
1077
|
-
invariantCode: "belief.confidence_append_only",
|
|
1078
|
-
suggestion: "Complete a worktree linked to this belief before recording SL scoring.",
|
|
1079
|
-
details: { nodeId: args.nodeId }
|
|
1080
|
-
});
|
|
1081
|
-
}
|
|
1082
|
-
}
|
|
1083
1276
|
const previousConfidence = node.confidence || 0.5;
|
|
1084
1277
|
const predictionMeta = node.predictionMeta || existingMetadata.predictionMeta;
|
|
1085
1278
|
const previousOpinion = readBeliefOpinionSnapshot(node, existingMetadata);
|
|
1086
|
-
const
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1279
|
+
const nextOpinion = {
|
|
1280
|
+
b: args.belief,
|
|
1281
|
+
d: args.disbelief,
|
|
1282
|
+
u: args.uncertainty,
|
|
1283
|
+
a: args.baseRate ?? 0.5
|
|
1284
|
+
};
|
|
1285
|
+
const derivedConfidence = confidenceFromSL(
|
|
1286
|
+
nextOpinion.b,
|
|
1287
|
+
nextOpinion.d,
|
|
1288
|
+
nextOpinion.u,
|
|
1289
|
+
nextOpinion.a
|
|
1290
|
+
);
|
|
1092
1291
|
const isFirstScoring = typeof node.confidence !== "number" || !Number.isFinite(node.confidence);
|
|
1093
1292
|
const previousTupleContradicted = readTupleContradictedFlag(node.tupleContradicted) ?? readTupleContradictedFlag(existingMetadata.tupleContradicted) ?? detectTupleContradiction(
|
|
1094
1293
|
previousOpinion,
|
|
@@ -1109,79 +1308,121 @@ async function applyBeliefConfidenceChange(ctx, args) {
|
|
|
1109
1308
|
predictionMeta,
|
|
1110
1309
|
metadata: existingMetadata
|
|
1111
1310
|
});
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1311
|
+
const storedRationale = args.rationale ?? `Confidence changed from ${previousConfidence.toFixed(2)} (nodeId: ${args.nodeId})`;
|
|
1312
|
+
return {
|
|
1313
|
+
confidencePolicy,
|
|
1314
|
+
currentBeliefStatus,
|
|
1315
|
+
derivedConfidence,
|
|
1316
|
+
existingMetadata,
|
|
1317
|
+
isFirstScoring,
|
|
1318
|
+
newBeliefStatus,
|
|
1319
|
+
nextOpinion,
|
|
1320
|
+
previousConfidence,
|
|
1321
|
+
previousTupleContradicted,
|
|
1322
|
+
storedRationale,
|
|
1323
|
+
tupleContradictionDescription,
|
|
1324
|
+
tupleTransition
|
|
1325
|
+
};
|
|
1326
|
+
}
|
|
1327
|
+
function readNodeMetadata(node) {
|
|
1328
|
+
return node.metadata ?? {};
|
|
1329
|
+
}
|
|
1330
|
+
async function assertConfidenceScoringPolicySatisfied(ctx, args, state) {
|
|
1331
|
+
if (state.confidencePolicy.scoringMode !== "after_worktree" || !isPreValidationBeliefStatus(state.currentBeliefStatus)) {
|
|
1332
|
+
return;
|
|
1130
1333
|
}
|
|
1334
|
+
const hasCompletedWorktree = await hasCompletedWorktreeForBelief(
|
|
1335
|
+
ctx,
|
|
1336
|
+
args.nodeId
|
|
1337
|
+
);
|
|
1338
|
+
if (hasCompletedWorktree) {
|
|
1339
|
+
return;
|
|
1340
|
+
}
|
|
1341
|
+
throwStructuredMutationError({
|
|
1342
|
+
message: "Cannot score belief before worktree completion. Complete a worktree that tests this belief first.",
|
|
1343
|
+
status: 409,
|
|
1344
|
+
code: "CONFLICT",
|
|
1345
|
+
invariantCode: "belief.confidence_append_only",
|
|
1346
|
+
suggestion: "Complete a worktree linked to this belief before recording SL scoring.",
|
|
1347
|
+
details: { nodeId: args.nodeId }
|
|
1348
|
+
});
|
|
1349
|
+
}
|
|
1350
|
+
async function createTupleContradictionIfNeeded(ctx, args, node, state) {
|
|
1351
|
+
if (!state.tupleTransition.crossedIntoTupleContradiction) {
|
|
1352
|
+
return;
|
|
1353
|
+
}
|
|
1354
|
+
return await ctx.runMutation("contradictions:create", {
|
|
1355
|
+
projectId: node.projectId,
|
|
1356
|
+
topicId: node.topicId,
|
|
1357
|
+
beliefId: args.nodeId,
|
|
1358
|
+
beliefBId: args.nodeId,
|
|
1359
|
+
supportingInsightIds: [],
|
|
1360
|
+
contradictingInsightIds: [],
|
|
1361
|
+
severity: deriveTupleContradictionSeverity(node),
|
|
1362
|
+
source: "tuple_space",
|
|
1363
|
+
detectionMethod: "agent",
|
|
1364
|
+
description: state.tupleContradictionDescription,
|
|
1365
|
+
createdBy: args.authenticatedUserId
|
|
1366
|
+
});
|
|
1367
|
+
}
|
|
1368
|
+
async function patchBeliefConfidenceState(ctx, args, state) {
|
|
1131
1369
|
await ctx.db.patch(args.nodeId, {
|
|
1132
|
-
confidence: derivedConfidence,
|
|
1133
|
-
beliefStatus: newBeliefStatus,
|
|
1134
|
-
tupleContradicted: tupleTransition.tupleContradicted,
|
|
1135
|
-
updatedAt: now,
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
opinion_a: slA,
|
|
1370
|
+
confidence: state.derivedConfidence,
|
|
1371
|
+
beliefStatus: state.newBeliefStatus,
|
|
1372
|
+
tupleContradicted: state.tupleTransition.tupleContradicted,
|
|
1373
|
+
updatedAt: Date.now(),
|
|
1374
|
+
opinion_b: state.nextOpinion.b,
|
|
1375
|
+
opinion_d: state.nextOpinion.d,
|
|
1376
|
+
opinion_u: state.nextOpinion.u,
|
|
1377
|
+
opinion_a: state.nextOpinion.a,
|
|
1141
1378
|
metadata: {
|
|
1142
|
-
...existingMetadata,
|
|
1143
|
-
beliefStatus: newBeliefStatus,
|
|
1144
|
-
slBelief:
|
|
1145
|
-
slDisbelief:
|
|
1146
|
-
slUncertainty:
|
|
1147
|
-
slBaseRate:
|
|
1148
|
-
tupleContradicted: tupleTransition.tupleContradicted
|
|
1379
|
+
...state.existingMetadata,
|
|
1380
|
+
beliefStatus: state.newBeliefStatus,
|
|
1381
|
+
slBelief: state.nextOpinion.b,
|
|
1382
|
+
slDisbelief: state.nextOpinion.d,
|
|
1383
|
+
slUncertainty: state.nextOpinion.u,
|
|
1384
|
+
slBaseRate: state.nextOpinion.a,
|
|
1385
|
+
tupleContradicted: state.tupleTransition.tupleContradicted
|
|
1149
1386
|
}
|
|
1150
1387
|
});
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
edgeType: "relates_to_thesis",
|
|
1164
|
-
weight: derivedConfidence,
|
|
1165
|
-
createdBy: args.authenticatedUserId,
|
|
1166
|
-
topicId: String(node.projectId),
|
|
1167
|
-
fromNodeType: "belief",
|
|
1168
|
-
toNodeType: "theme",
|
|
1169
|
-
fromLayer: "L3",
|
|
1170
|
-
toLayer: "L3"
|
|
1171
|
-
});
|
|
1172
|
-
}
|
|
1388
|
+
}
|
|
1389
|
+
async function scheduleFirstScoringThemeEdges(ctx, args, node, state) {
|
|
1390
|
+
if (!state.isFirstScoring) {
|
|
1391
|
+
return;
|
|
1392
|
+
}
|
|
1393
|
+
const themeNodes = await ctx.db.query("epistemicNodes").withIndex(
|
|
1394
|
+
"by_topic",
|
|
1395
|
+
(q) => q.eq("topicId", node.topicId || node.projectId)
|
|
1396
|
+
).filter((q) => q.eq(q.field("nodeType"), "theme")).collect();
|
|
1397
|
+
for (const theme of themeNodes) {
|
|
1398
|
+
if (!(theme.globalId && node.globalId)) {
|
|
1399
|
+
continue;
|
|
1173
1400
|
}
|
|
1401
|
+
await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {
|
|
1402
|
+
globalId: `edge-${node.globalId}-relates_to_thesis-${theme.globalId}`,
|
|
1403
|
+
fromGlobalId: node.globalId,
|
|
1404
|
+
toGlobalId: theme.globalId,
|
|
1405
|
+
edgeType: "relates_to_thesis",
|
|
1406
|
+
weight: state.derivedConfidence,
|
|
1407
|
+
createdBy: args.authenticatedUserId,
|
|
1408
|
+
topicId: String(node.projectId),
|
|
1409
|
+
fromNodeType: "belief",
|
|
1410
|
+
toNodeType: "theme",
|
|
1411
|
+
fromLayer: "L3",
|
|
1412
|
+
toLayer: "L3"
|
|
1413
|
+
});
|
|
1174
1414
|
}
|
|
1175
|
-
|
|
1176
|
-
|
|
1415
|
+
}
|
|
1416
|
+
async function insertBeliefConfidenceRecord(ctx, args, state, tupleContradictionId, now) {
|
|
1417
|
+
return await ctx.db.insert("beliefConfidence", {
|
|
1177
1418
|
...buildBeliefConfidenceRow({
|
|
1178
1419
|
beliefId: args.nodeId,
|
|
1179
|
-
belief:
|
|
1180
|
-
disbelief:
|
|
1181
|
-
uncertainty:
|
|
1182
|
-
baseRate:
|
|
1420
|
+
belief: state.nextOpinion.b,
|
|
1421
|
+
disbelief: state.nextOpinion.d,
|
|
1422
|
+
uncertainty: state.nextOpinion.u,
|
|
1423
|
+
baseRate: state.nextOpinion.a,
|
|
1183
1424
|
trigger: args.trigger,
|
|
1184
|
-
rationale: storedRationale,
|
|
1425
|
+
rationale: state.storedRationale,
|
|
1185
1426
|
assessedBy: args.authenticatedUserId,
|
|
1186
1427
|
assessedAt: now,
|
|
1187
1428
|
slOperator: args.slOperator,
|
|
@@ -1190,25 +1431,23 @@ async function applyBeliefConfidenceChange(ctx, args) {
|
|
|
1190
1431
|
triggeringWorktreeId: args.triggeringWorktreeId
|
|
1191
1432
|
})
|
|
1192
1433
|
});
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
operation: "upsert"
|
|
1196
|
-
});
|
|
1434
|
+
}
|
|
1435
|
+
async function insertConfidenceAudit(ctx, args, node, state, tupleContradictionId, now) {
|
|
1197
1436
|
await ctx.db.insert("epistemicAudit", {
|
|
1198
1437
|
entityType: "belief",
|
|
1199
1438
|
entityId: args.nodeId,
|
|
1200
1439
|
changeType: "confidence_changed",
|
|
1201
1440
|
previousState: {
|
|
1202
|
-
confidence: previousConfidence,
|
|
1203
|
-
tupleContradicted: previousTupleContradicted
|
|
1441
|
+
confidence: state.previousConfidence,
|
|
1442
|
+
tupleContradicted: state.previousTupleContradicted
|
|
1204
1443
|
},
|
|
1205
1444
|
newState: {
|
|
1206
|
-
opinion: nextOpinion,
|
|
1207
|
-
confidence: derivedConfidence,
|
|
1445
|
+
opinion: state.nextOpinion,
|
|
1446
|
+
confidence: state.derivedConfidence,
|
|
1208
1447
|
trigger: args.trigger,
|
|
1209
|
-
rationale: storedRationale,
|
|
1210
|
-
tupleContradicted: tupleTransition.tupleContradicted,
|
|
1211
|
-
tupleContradictionPolicy: tupleTransition.policy,
|
|
1448
|
+
rationale: state.storedRationale,
|
|
1449
|
+
tupleContradicted: state.tupleTransition.tupleContradicted,
|
|
1450
|
+
tupleContradictionPolicy: state.tupleTransition.policy,
|
|
1212
1451
|
...tupleContradictionId ? { tupleContradictionId: String(tupleContradictionId) } : {}
|
|
1213
1452
|
},
|
|
1214
1453
|
changedBy: args.authenticatedUserId,
|
|
@@ -1217,28 +1456,39 @@ async function applyBeliefConfidenceChange(ctx, args) {
|
|
|
1217
1456
|
projectId: node.projectId,
|
|
1218
1457
|
topicId: node.topicId
|
|
1219
1458
|
});
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
changeType: "updated",
|
|
1225
|
-
previousState: { tupleContradicted: previousTupleContradicted },
|
|
1226
|
-
newState: {
|
|
1227
|
-
tupleContradicted: tupleTransition.tupleContradicted,
|
|
1228
|
-
action: tupleTransition.crossedIntoTupleContradiction ? "tuple_contradiction_detected" : "tuple_contradiction_cleared",
|
|
1229
|
-
opinion: nextOpinion,
|
|
1230
|
-
tupleContradictionPolicy: tupleTransition.policy,
|
|
1231
|
-
...tupleContradictionId ? { tupleContradictionId: String(tupleContradictionId) } : {}
|
|
1232
|
-
},
|
|
1233
|
-
rationale: tupleTransition.crossedIntoTupleContradiction ? tupleContradictionDescription : `Tuple-space contradiction cleared: b=${nextOpinion.b.toFixed(2)}, d=${nextOpinion.d.toFixed(2)} no longer exceed the configured policy thresholds.`,
|
|
1234
|
-
changedBy: args.authenticatedUserId,
|
|
1235
|
-
isAgent: false,
|
|
1236
|
-
changedAt: now,
|
|
1237
|
-
projectId: node.projectId,
|
|
1238
|
-
topicId: node.topicId
|
|
1239
|
-
});
|
|
1459
|
+
}
|
|
1460
|
+
async function insertTupleTransitionAuditIfNeeded(ctx, args, node, state, tupleContradictionId, now) {
|
|
1461
|
+
if (!(state.tupleTransition.crossedIntoTupleContradiction || state.tupleTransition.crossedOutOfTupleContradiction)) {
|
|
1462
|
+
return;
|
|
1240
1463
|
}
|
|
1241
|
-
|
|
1464
|
+
await ctx.db.insert("epistemicAudit", {
|
|
1465
|
+
entityType: "belief",
|
|
1466
|
+
entityId: args.nodeId,
|
|
1467
|
+
changeType: "updated",
|
|
1468
|
+
previousState: { tupleContradicted: state.previousTupleContradicted },
|
|
1469
|
+
newState: {
|
|
1470
|
+
tupleContradicted: state.tupleTransition.tupleContradicted,
|
|
1471
|
+
action: state.tupleTransition.crossedIntoTupleContradiction ? "tuple_contradiction_detected" : "tuple_contradiction_cleared",
|
|
1472
|
+
opinion: state.nextOpinion,
|
|
1473
|
+
tupleContradictionPolicy: state.tupleTransition.policy,
|
|
1474
|
+
...tupleContradictionId ? { tupleContradictionId: String(tupleContradictionId) } : {}
|
|
1475
|
+
},
|
|
1476
|
+
rationale: tupleAuditRationale(state),
|
|
1477
|
+
changedBy: args.authenticatedUserId,
|
|
1478
|
+
isAgent: false,
|
|
1479
|
+
changedAt: now,
|
|
1480
|
+
projectId: node.projectId,
|
|
1481
|
+
topicId: node.topicId
|
|
1482
|
+
});
|
|
1483
|
+
}
|
|
1484
|
+
function tupleAuditRationale(state) {
|
|
1485
|
+
if (state.tupleTransition.crossedIntoTupleContradiction) {
|
|
1486
|
+
return state.tupleContradictionDescription;
|
|
1487
|
+
}
|
|
1488
|
+
return `Tuple-space contradiction cleared: b=${state.nextOpinion.b.toFixed(2)}, d=${state.nextOpinion.d.toFixed(2)} no longer exceed the configured policy thresholds.`;
|
|
1489
|
+
}
|
|
1490
|
+
async function scheduleConfidenceFollowups(ctx, args, node, state) {
|
|
1491
|
+
if (Math.abs(state.derivedConfidence - state.previousConfidence) >= 0.15) {
|
|
1242
1492
|
await ctx.scheduler.runAfter(
|
|
1243
1493
|
5e3,
|
|
1244
1494
|
internal.bi.contradictionSemanticDetector.scanAffectedBeliefs,
|
|
@@ -1255,13 +1505,6 @@ async function applyBeliefConfidenceChange(ctx, args) {
|
|
|
1255
1505
|
{ nodeId: args.nodeId }
|
|
1256
1506
|
);
|
|
1257
1507
|
}
|
|
1258
|
-
return {
|
|
1259
|
-
nodeId: args.nodeId,
|
|
1260
|
-
previousConfidence,
|
|
1261
|
-
newConfidence: derivedConfidence,
|
|
1262
|
-
opinion: { b: slB, d: slD, u: slU, a: slA },
|
|
1263
|
-
beliefConfidenceId
|
|
1264
|
-
};
|
|
1265
1508
|
}
|
|
1266
1509
|
function propagationPressureLabel(edgeType, weight) {
|
|
1267
1510
|
if (edgeType === "contradicts" || edgeType === "refutes") {
|
|
@@ -1289,7 +1532,7 @@ var propagateConfidenceChange = internalMutation({
|
|
|
1289
1532
|
args.opinion_u,
|
|
1290
1533
|
args.opinion_a
|
|
1291
1534
|
);
|
|
1292
|
-
const sourceNode = await ctx.db.get(args.nodeId);
|
|
1535
|
+
const sourceNode = readConfidenceBeliefNode(await ctx.db.get(args.nodeId));
|
|
1293
1536
|
const sourceScope = await resolveNodeScopeForWorkspaceIsolation(
|
|
1294
1537
|
ctx,
|
|
1295
1538
|
sourceNode
|
|
@@ -1298,16 +1541,20 @@ var propagateConfidenceChange = internalMutation({
|
|
|
1298
1541
|
sourceNodeId: args.nodeId,
|
|
1299
1542
|
sourceOpinion,
|
|
1300
1543
|
sourceScope,
|
|
1301
|
-
queryEdges: async ({ nodeId, spec, direction }) =>
|
|
1302
|
-
|
|
1544
|
+
queryEdges: async ({ nodeId, spec, direction }) => readRowList(
|
|
1545
|
+
await ctx.db.query("epistemicEdges").withIndex(
|
|
1303
1546
|
direction === "outgoing" ? "by_from_type" : "by_to_type",
|
|
1304
1547
|
(q) => direction === "outgoing" ? q.eq("fromNodeId", nodeId).eq("edgeType", spec.edgeType) : q.eq("toNodeId", nodeId).eq("edgeType", spec.edgeType)
|
|
1305
|
-
).collect()
|
|
1306
|
-
|
|
1307
|
-
|
|
1548
|
+
).collect(),
|
|
1549
|
+
readPropagationEdge
|
|
1550
|
+
),
|
|
1551
|
+
getNode: async (nodeId) => readConfidenceBeliefNode(await ctx.db.get(nodeId))
|
|
1308
1552
|
});
|
|
1309
1553
|
for (const dispatch of dispatches) {
|
|
1310
|
-
const pressureLabel = propagationPressureLabel(
|
|
1554
|
+
const pressureLabel = propagationPressureLabel(
|
|
1555
|
+
dispatch.edgeType,
|
|
1556
|
+
dispatch.weight
|
|
1557
|
+
);
|
|
1311
1558
|
await applyBeliefConfidenceChange(ctx, {
|
|
1312
1559
|
nodeId: dispatch.targetNodeId,
|
|
1313
1560
|
belief: dispatch.opinion.b,
|