@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,34 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { checkProjectAccess } from '@lucern/access-control/access';
|
|
1
|
+
import { unsafeConvexAnyApi } from '@lucern/contracts/convex/unsafeAnyApi';
|
|
2
|
+
import { componentsGeneric, internalMutationGeneric } from 'convex/server';
|
|
4
3
|
import '@lucern/access-control/audience';
|
|
5
4
|
import '@lucern/access-control/auth';
|
|
6
|
-
import {
|
|
5
|
+
import { throwStructuredMutationError } from '@lucern/access-control/structuredMutationError';
|
|
6
|
+
import { normalizeTupleContradictionPolicy, mkOpinion, conditionalDeduction, project, dampedDependencyCascade, trustDiscount, applyNegativeSupport, cumulativeFusion, applyNegativeEvidence, confidenceFromSL, detectTupleContradiction, evaluateTupleContradictionTransition, readOpinionFromRecord, hasProjectedOpinionChanged, deriveContractModulationPlan, deriveContractStatus, parseEvidentialEvaluatorConfig, compareMetricValue, resolveComparisonResult, buildEvidentialRationale, parseMetricCheckerConfig, getEvaluatorInputRecord, pickFiniteNumber, buildComparisonRationale, parseReferenceCheckCounterConfig, parseTemporalDeadlineConfig, parseMarketIndexComparatorConfig } from '@lucern/confidence';
|
|
7
|
+
import { v } from 'convex/values';
|
|
7
8
|
import '@lucern/contracts/schema-helpers/spine/tables/epistemicNodes';
|
|
9
|
+
import { requireScopeWriteAccess } from '@lucern/access-control/access';
|
|
8
10
|
import { permissiveReturn } from '@lucern/contracts/schema-helpers/validators';
|
|
9
11
|
|
|
10
|
-
// src/
|
|
12
|
+
// src/convex.ts
|
|
13
|
+
var unsafeApi = unsafeConvexAnyApi(
|
|
14
|
+
"graph-primitives top-level module bundle lacks a committed Convex _generated/api surface"
|
|
15
|
+
);
|
|
16
|
+
var api = unsafeApi;
|
|
17
|
+
componentsGeneric();
|
|
18
|
+
var internal = unsafeApi;
|
|
19
|
+
var internalMutation = internalMutationGeneric;
|
|
20
|
+
|
|
21
|
+
// src/debug.ts
|
|
22
|
+
function isGraphPrimitiveDebugEnabled() {
|
|
23
|
+
const env = globalThis.process?.env;
|
|
24
|
+
return env?.LUCERN_COMPAT_FALLBACK_DEBUG === "1" || env?.LUCERN_GRAPH_DEBUG === "1";
|
|
25
|
+
}
|
|
26
|
+
function debugGraphPrimitiveFallback(message, context) {
|
|
27
|
+
if (!isGraphPrimitiveDebugEnabled()) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
console.debug(message, context ?? {});
|
|
31
|
+
}
|
|
11
32
|
|
|
12
33
|
// src/beliefLifecycle.ts
|
|
13
34
|
var BELIEF_STATUS_VALUES = [
|
|
@@ -129,22 +150,6 @@ function promoteBeliefStatusAfterScoring(status, opts) {
|
|
|
129
150
|
}
|
|
130
151
|
return status;
|
|
131
152
|
}
|
|
132
|
-
var api = anyApi;
|
|
133
|
-
componentsGeneric();
|
|
134
|
-
var internal = anyApi;
|
|
135
|
-
var internalMutation = internalMutationGeneric;
|
|
136
|
-
|
|
137
|
-
// src/debug.ts
|
|
138
|
-
function isGraphPrimitiveDebugEnabled() {
|
|
139
|
-
const env = globalThis.process?.env;
|
|
140
|
-
return env?.LUCERN_COMPAT_FALLBACK_DEBUG === "1" || env?.LUCERN_GRAPH_DEBUG === "1";
|
|
141
|
-
}
|
|
142
|
-
function debugGraphPrimitiveFallback(message, context) {
|
|
143
|
-
if (!isGraphPrimitiveDebugEnabled()) {
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
console.debug(message, context ?? {});
|
|
147
|
-
}
|
|
148
153
|
var LEGACY_SCOPE_FIELD = "graphScopeProjectId";
|
|
149
154
|
async function resolveTopicNodeScopeOrNull(ctx, ref) {
|
|
150
155
|
if (!ctx?.db || typeof ctx.db.query !== "function") {
|
|
@@ -179,13 +184,15 @@ function asMappedProjectId(topic) {
|
|
|
179
184
|
if (!topic) {
|
|
180
185
|
return;
|
|
181
186
|
}
|
|
182
|
-
const directLegacyProjectId = normalizeScopeValue(
|
|
187
|
+
const directLegacyProjectId = normalizeScopeValue(
|
|
188
|
+
topic[LEGACY_SCOPE_FIELD]
|
|
189
|
+
);
|
|
183
190
|
if (directLegacyProjectId) {
|
|
184
191
|
return directLegacyProjectId;
|
|
185
192
|
}
|
|
186
193
|
const metadata = topic.metadata || {};
|
|
187
194
|
const candidate = metadata[LEGACY_SCOPE_FIELD] || metadata.legacyProjectId || metadata.projectId || metadata.scopeProjectId;
|
|
188
|
-
return candidate ? candidate : void 0;
|
|
195
|
+
return typeof candidate === "string" ? normalizeScopeValue(candidate) : void 0;
|
|
189
196
|
}
|
|
190
197
|
function normalizeScopeValue(value) {
|
|
191
198
|
if (typeof value !== "string") {
|
|
@@ -210,8 +217,9 @@ function pickPrimaryTopic(candidates) {
|
|
|
210
217
|
})[0];
|
|
211
218
|
}
|
|
212
219
|
async function findTopicsByScopeAlias(ctx, scopeId) {
|
|
220
|
+
const query = ctx.db.query("topics");
|
|
213
221
|
try {
|
|
214
|
-
return await
|
|
222
|
+
return await query.withIndex(
|
|
215
223
|
"by_graph_scope_project",
|
|
216
224
|
(q) => q.eq(LEGACY_SCOPE_FIELD, scopeId)
|
|
217
225
|
).collect();
|
|
@@ -223,7 +231,7 @@ async function findTopicsByScopeAlias(ctx, scopeId) {
|
|
|
223
231
|
scopeId
|
|
224
232
|
}
|
|
225
233
|
);
|
|
226
|
-
const topics = await
|
|
234
|
+
const topics = await query.collect();
|
|
227
235
|
return topics.filter((topic) => {
|
|
228
236
|
const normalizedGlobalId = normalizeScopeValue(topic.globalId);
|
|
229
237
|
const mappedProjectId = asMappedProjectId(topic);
|
|
@@ -279,137 +287,115 @@ async function resolveInheritedWorkspaceScope(ctx, topic) {
|
|
|
279
287
|
let current = topic;
|
|
280
288
|
for (let i = 0; i < MAX_DEPTH && current?.parentTopicId; i++) {
|
|
281
289
|
current = await ctx.db.get(current.parentTopicId);
|
|
282
|
-
if (!current)
|
|
290
|
+
if (!current) {
|
|
291
|
+
break;
|
|
292
|
+
}
|
|
283
293
|
if (!tenantId) {
|
|
284
294
|
tenantId = normalizeScopeValue(current.tenantId);
|
|
285
295
|
}
|
|
286
296
|
if (!workspaceId) {
|
|
287
297
|
workspaceId = normalizeScopeValue(current.workspaceId);
|
|
288
298
|
}
|
|
289
|
-
if (tenantId && workspaceId)
|
|
299
|
+
if (tenantId && workspaceId) {
|
|
300
|
+
break;
|
|
301
|
+
}
|
|
290
302
|
}
|
|
291
303
|
return { tenantId, workspaceId };
|
|
292
304
|
}
|
|
293
305
|
async function resolveTopicProjectScope(ctx, args) {
|
|
294
306
|
if (args.topicId) {
|
|
295
|
-
|
|
296
|
-
try {
|
|
297
|
-
topic = await ctx.db.get(
|
|
298
|
-
args.topicId
|
|
299
|
-
);
|
|
300
|
-
} catch (error) {
|
|
301
|
-
debugGraphPrimitiveFallback(
|
|
302
|
-
"[topicScope] Failed to load topic by direct id",
|
|
303
|
-
{
|
|
304
|
-
error,
|
|
305
|
-
topicId: args.topicId
|
|
306
|
-
}
|
|
307
|
-
);
|
|
308
|
-
}
|
|
309
|
-
if (!topic) {
|
|
310
|
-
topic = await tryResolveHostTopicById(ctx, String(args.topicId));
|
|
311
|
-
}
|
|
312
|
-
if (!topic) {
|
|
313
|
-
topic = pickPrimaryTopic(
|
|
314
|
-
await findTopicsByScopeAlias(ctx, String(args.topicId))
|
|
315
|
-
) ?? null;
|
|
316
|
-
}
|
|
317
|
-
if (!topic) {
|
|
318
|
-
const nodeScope = await resolveTopicNodeScopeOrNull(
|
|
319
|
-
ctx,
|
|
320
|
-
String(args.topicId)
|
|
321
|
-
);
|
|
322
|
-
if (nodeScope) {
|
|
323
|
-
return nodeScope;
|
|
324
|
-
}
|
|
325
|
-
throw new Error(`Topic not found: ${String(args.topicId)}`);
|
|
326
|
-
}
|
|
327
|
-
const inherited = await resolveInheritedWorkspaceScope(ctx, topic);
|
|
328
|
-
const mapped = asMappedProjectId(topic);
|
|
329
|
-
if (mapped) {
|
|
330
|
-
return {
|
|
331
|
-
topicId: topic._id,
|
|
332
|
-
projectId: mapped,
|
|
333
|
-
tenantId: inherited.tenantId,
|
|
334
|
-
workspaceId: inherited.workspaceId,
|
|
335
|
-
source: "topic"
|
|
336
|
-
};
|
|
337
|
-
}
|
|
338
|
-
return {
|
|
339
|
-
topicId: topic._id,
|
|
340
|
-
tenantId: inherited.tenantId,
|
|
341
|
-
workspaceId: inherited.workspaceId,
|
|
342
|
-
source: "topic"
|
|
343
|
-
};
|
|
307
|
+
return await resolveScopeFromTopicId(ctx, args.topicId);
|
|
344
308
|
}
|
|
345
309
|
if (args.projectId) {
|
|
346
|
-
|
|
347
|
-
try {
|
|
348
|
-
directTopic = await ctx.db.get(
|
|
349
|
-
args.projectId
|
|
350
|
-
);
|
|
351
|
-
} catch (error) {
|
|
352
|
-
debugGraphPrimitiveFallback(
|
|
353
|
-
"[topicScope] Failed to load direct project topic",
|
|
354
|
-
{
|
|
355
|
-
error,
|
|
356
|
-
projectId: args.projectId
|
|
357
|
-
}
|
|
358
|
-
);
|
|
359
|
-
}
|
|
360
|
-
if (directTopic) {
|
|
361
|
-
const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);
|
|
362
|
-
const mapped = asMappedProjectId(directTopic);
|
|
363
|
-
return {
|
|
364
|
-
topicId: directTopic._id,
|
|
365
|
-
projectId: mapped ?? args.projectId,
|
|
366
|
-
tenantId: inherited.tenantId,
|
|
367
|
-
workspaceId: inherited.workspaceId,
|
|
368
|
-
source: "topic_inferred"
|
|
369
|
-
};
|
|
370
|
-
}
|
|
371
|
-
directTopic = await tryResolveHostTopicByLegacyScope(ctx, args.projectId);
|
|
372
|
-
if (directTopic) {
|
|
373
|
-
const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);
|
|
374
|
-
const mapped = asMappedProjectId(directTopic);
|
|
375
|
-
return {
|
|
376
|
-
topicId: directTopic._id,
|
|
377
|
-
projectId: mapped ?? args.projectId,
|
|
378
|
-
tenantId: inherited.tenantId,
|
|
379
|
-
workspaceId: inherited.workspaceId,
|
|
380
|
-
source: "topic_inferred"
|
|
381
|
-
};
|
|
382
|
-
}
|
|
383
|
-
const topics = await findTopicsByScopeAlias(ctx, args.projectId);
|
|
384
|
-
const primary = pickPrimaryTopic(topics);
|
|
385
|
-
if (primary) {
|
|
386
|
-
const inherited = await resolveInheritedWorkspaceScope(ctx, primary);
|
|
387
|
-
return {
|
|
388
|
-
topicId: primary._id,
|
|
389
|
-
projectId: args.projectId,
|
|
390
|
-
tenantId: inherited.tenantId,
|
|
391
|
-
workspaceId: inherited.workspaceId,
|
|
392
|
-
source: "project_mapped_topic"
|
|
393
|
-
};
|
|
394
|
-
}
|
|
395
|
-
const nodeScope = await resolveTopicNodeScopeOrNull(
|
|
396
|
-
ctx,
|
|
397
|
-
String(args.projectId)
|
|
398
|
-
);
|
|
399
|
-
if (nodeScope) {
|
|
400
|
-
return {
|
|
401
|
-
...nodeScope,
|
|
402
|
-
projectId: nodeScope.projectId ?? String(args.projectId)
|
|
403
|
-
};
|
|
404
|
-
}
|
|
405
|
-
throw new Error(
|
|
406
|
-
`Legacy project scope ${String(args.projectId)} has no mapped topic.`
|
|
407
|
-
);
|
|
310
|
+
return await resolveScopeFromLegacyProjectId(ctx, args.projectId);
|
|
408
311
|
}
|
|
409
312
|
throw new Error(
|
|
410
313
|
"Missing scope: provide topicId (preferred) or legacy projectId alias."
|
|
411
314
|
);
|
|
412
315
|
}
|
|
316
|
+
async function resolveScopeFromTopicId(ctx, topicId) {
|
|
317
|
+
const topic = await resolveTopicDocFromTopicId(ctx, topicId);
|
|
318
|
+
if (topic) {
|
|
319
|
+
return await buildTopicScope(ctx, topic, "topic");
|
|
320
|
+
}
|
|
321
|
+
const nodeScope = await resolveTopicNodeScopeOrNull(ctx, String(topicId));
|
|
322
|
+
if (nodeScope) {
|
|
323
|
+
return nodeScope;
|
|
324
|
+
}
|
|
325
|
+
throw new Error(`Topic not found: ${String(topicId)}`);
|
|
326
|
+
}
|
|
327
|
+
async function resolveTopicDocFromTopicId(ctx, topicId) {
|
|
328
|
+
const direct = await tryReadTopicDoc(ctx, topicId, {
|
|
329
|
+
failureLog: "[topicScope] Failed to load topic by direct id",
|
|
330
|
+
idLogKey: "topicId"
|
|
331
|
+
});
|
|
332
|
+
if (direct) {
|
|
333
|
+
return direct;
|
|
334
|
+
}
|
|
335
|
+
const hostTopic = await tryResolveHostTopicById(ctx, String(topicId));
|
|
336
|
+
if (hostTopic) {
|
|
337
|
+
return hostTopic;
|
|
338
|
+
}
|
|
339
|
+
return pickPrimaryTopic(await findTopicsByScopeAlias(ctx, String(topicId))) ?? null;
|
|
340
|
+
}
|
|
341
|
+
async function resolveScopeFromLegacyProjectId(ctx, legacyProjectId) {
|
|
342
|
+
const directTopic = await resolveDirectLegacyProjectTopic(
|
|
343
|
+
ctx,
|
|
344
|
+
legacyProjectId
|
|
345
|
+
);
|
|
346
|
+
if (directTopic) {
|
|
347
|
+
return await buildTopicScope(ctx, directTopic, "topic_inferred", {
|
|
348
|
+
fallbackProjectId: legacyProjectId
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
const primary = pickPrimaryTopic(
|
|
352
|
+
await findTopicsByScopeAlias(ctx, legacyProjectId)
|
|
353
|
+
);
|
|
354
|
+
if (primary) {
|
|
355
|
+
return await buildTopicScope(ctx, primary, "project_mapped_topic", {
|
|
356
|
+
fallbackProjectId: legacyProjectId
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
const nodeScope = await resolveTopicNodeScopeOrNull(ctx, legacyProjectId);
|
|
360
|
+
if (nodeScope) {
|
|
361
|
+
return {
|
|
362
|
+
...nodeScope,
|
|
363
|
+
projectId: nodeScope.projectId ?? legacyProjectId
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
throw new Error(
|
|
367
|
+
`Legacy project scope ${legacyProjectId} has no mapped topic.`
|
|
368
|
+
);
|
|
369
|
+
}
|
|
370
|
+
async function resolveDirectLegacyProjectTopic(ctx, legacyProjectId) {
|
|
371
|
+
const directTopic = await tryReadTopicDoc(ctx, legacyProjectId, {
|
|
372
|
+
failureLog: "[topicScope] Failed to load direct project topic",
|
|
373
|
+
idLogKey: "projectId"
|
|
374
|
+
});
|
|
375
|
+
return directTopic ?? tryResolveHostTopicByLegacyScope(ctx, legacyProjectId);
|
|
376
|
+
}
|
|
377
|
+
async function tryReadTopicDoc(ctx, id, log) {
|
|
378
|
+
try {
|
|
379
|
+
return await ctx.db.get(id);
|
|
380
|
+
} catch (error) {
|
|
381
|
+
debugGraphPrimitiveFallback(log.failureLog, {
|
|
382
|
+
error,
|
|
383
|
+
[log.idLogKey]: id
|
|
384
|
+
});
|
|
385
|
+
return null;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
async function buildTopicScope(ctx, topic, source, options = {}) {
|
|
389
|
+
const inherited = await resolveInheritedWorkspaceScope(ctx, topic);
|
|
390
|
+
const mapped = asMappedProjectId(topic);
|
|
391
|
+
return {
|
|
392
|
+
topicId: topic._id,
|
|
393
|
+
...mapped || options.fallbackProjectId ? { projectId: mapped ?? options.fallbackProjectId } : {},
|
|
394
|
+
tenantId: inherited.tenantId,
|
|
395
|
+
workspaceId: inherited.workspaceId,
|
|
396
|
+
source
|
|
397
|
+
};
|
|
398
|
+
}
|
|
413
399
|
({
|
|
414
400
|
projectId: v.optional(v.string()),
|
|
415
401
|
topicId: v.optional(v.string())
|
|
@@ -477,9 +463,10 @@ async function resolveNodeScopeForWorkspaceIsolation(ctx, node) {
|
|
|
477
463
|
if (resolved.tenantId || resolved.workspaceId) {
|
|
478
464
|
return resolved;
|
|
479
465
|
}
|
|
480
|
-
|
|
466
|
+
const topicId = normalizeScopeValue2(node.topicId);
|
|
467
|
+
if (topicId) {
|
|
481
468
|
const topicScope = await resolveTopicProjectScope(ctx, {
|
|
482
|
-
topicId
|
|
469
|
+
topicId
|
|
483
470
|
});
|
|
484
471
|
return {
|
|
485
472
|
...resolved,
|
|
@@ -499,33 +486,11 @@ async function resolveNodeScopeForWorkspaceIsolation(ctx, node) {
|
|
|
499
486
|
}
|
|
500
487
|
return resolved;
|
|
501
488
|
}
|
|
502
|
-
|
|
503
|
-
// src/epistemicBeliefs.helpers.ts
|
|
504
489
|
v.id("epistemicNodes");
|
|
505
490
|
var DEFAULT_CONFIDENCE_POLICY = {
|
|
506
491
|
scoringMode: "after_worktree",
|
|
507
492
|
tupleContradiction: normalizeTupleContradictionPolicy()
|
|
508
493
|
};
|
|
509
|
-
function throwStructuredMutationError(args) {
|
|
510
|
-
const data = {
|
|
511
|
-
structuredMutationError: true,
|
|
512
|
-
message: args.message,
|
|
513
|
-
status: args.status,
|
|
514
|
-
code: args.code,
|
|
515
|
-
invariantCode: args.invariantCode,
|
|
516
|
-
suggestion: args.suggestion,
|
|
517
|
-
details: args.details
|
|
518
|
-
};
|
|
519
|
-
const error = new ConvexError(
|
|
520
|
-
data
|
|
521
|
-
);
|
|
522
|
-
error.status = args.status;
|
|
523
|
-
error.code = args.code;
|
|
524
|
-
error.invariantCode = args.invariantCode;
|
|
525
|
-
error.suggestion = args.suggestion;
|
|
526
|
-
error.details = args.details;
|
|
527
|
-
throw error;
|
|
528
|
-
}
|
|
529
494
|
function buildBeliefConfidenceRow(args) {
|
|
530
495
|
return {
|
|
531
496
|
beliefId: args.beliefId,
|
|
@@ -600,7 +565,10 @@ function resolveBeliefStatus(node, metadata) {
|
|
|
600
565
|
});
|
|
601
566
|
}
|
|
602
567
|
async function hasCompletedWorktreeForBelief(ctx, beliefNodeId) {
|
|
603
|
-
const clusterMembership = await ctx.db.query("worktreeBeliefCluster").withIndex(
|
|
568
|
+
const clusterMembership = await ctx.db.query("worktreeBeliefCluster").withIndex(
|
|
569
|
+
"by_belief",
|
|
570
|
+
(q) => q.eq("beliefId", beliefNodeId)
|
|
571
|
+
).collect();
|
|
604
572
|
for (const membership of clusterMembership) {
|
|
605
573
|
const worktree = await ctx.db.get(membership.worktreeId);
|
|
606
574
|
if (worktree?.status === "completed" || worktree?.status === "merged") {
|
|
@@ -611,7 +579,10 @@ async function hasCompletedWorktreeForBelief(ctx, beliefNodeId) {
|
|
|
611
579
|
}
|
|
612
580
|
async function getActiveConfidencePolicy(ctx) {
|
|
613
581
|
try {
|
|
614
|
-
const activeConfig = await ctx.db.query("logicSprintScoring").withIndex(
|
|
582
|
+
const activeConfig = await ctx.db.query("logicSprintScoring").withIndex(
|
|
583
|
+
"by_active",
|
|
584
|
+
(q) => q.eq("isActive", true)
|
|
585
|
+
).first();
|
|
615
586
|
return {
|
|
616
587
|
scoringMode: activeConfig?.confidencePolicy === "always" ? "always" : DEFAULT_CONFIDENCE_POLICY.scoringMode,
|
|
617
588
|
tupleContradiction: normalizeTupleContradictionPolicy(
|
|
@@ -628,23 +599,6 @@ async function getActiveConfidencePolicy(ctx) {
|
|
|
628
599
|
return DEFAULT_CONFIDENCE_POLICY;
|
|
629
600
|
}
|
|
630
601
|
}
|
|
631
|
-
async function requireProjectWriteAccess(ctx, projectId, userId) {
|
|
632
|
-
const hasAccess = await checkProjectAccess(
|
|
633
|
-
ctx,
|
|
634
|
-
projectId,
|
|
635
|
-
userId
|
|
636
|
-
);
|
|
637
|
-
if (!hasAccess) {
|
|
638
|
-
throwStructuredMutationError({
|
|
639
|
-
message: `Project write access denied for topic ${projectId}.`,
|
|
640
|
-
status: 403,
|
|
641
|
-
code: "PROJECT_ACCESS_DENIED",
|
|
642
|
-
invariantCode: "policy.scope_required",
|
|
643
|
-
suggestion: "The acting principal lacks project-write access to this topic. Request a topic grant (or, if the principal created this topic, run the creator-grant backfill) and retry.",
|
|
644
|
-
details: { topicId: projectId, principalId: userId }
|
|
645
|
-
});
|
|
646
|
-
}
|
|
647
|
-
}
|
|
648
602
|
|
|
649
603
|
// src/edges/contains.ts
|
|
650
604
|
var containsPropagationSpec = {
|
|
@@ -781,7 +735,7 @@ var dependsOnPropagationSpec = {
|
|
|
781
735
|
description: "Structural gating. Textbook conditional deduction when edge conditionals exist, otherwise damped dependency cascade through downstream chains."
|
|
782
736
|
};
|
|
783
737
|
|
|
784
|
-
// src/edges/
|
|
738
|
+
// src/edges/derived-from.ts
|
|
785
739
|
var derivedFromPropagationSpec = {
|
|
786
740
|
edgeType: "derived_from",
|
|
787
741
|
direction: "incoming",
|
|
@@ -834,7 +788,7 @@ var informsPropagationSpec = {
|
|
|
834
788
|
description: "Evidence-bearing influence. Informs can chain through the graph with light per-hop damping."
|
|
835
789
|
};
|
|
836
790
|
|
|
837
|
-
// src/edges/
|
|
791
|
+
// src/edges/propagation-types.ts
|
|
838
792
|
function isPropagationTraversalDirection(direction) {
|
|
839
793
|
return direction === "outgoing" || direction === "incoming";
|
|
840
794
|
}
|
|
@@ -907,6 +861,9 @@ var testsPropagationSpec = {
|
|
|
907
861
|
};
|
|
908
862
|
|
|
909
863
|
// src/edges/index.ts
|
|
864
|
+
var canContinueTransitively2 = canContinueTransitively;
|
|
865
|
+
var canTraverseHop2 = canTraverseHop;
|
|
866
|
+
var isPropagationTraversalDirection2 = isPropagationTraversalDirection;
|
|
910
867
|
var EDGE_PROPAGATION_SPECS = [
|
|
911
868
|
supportsPropagationSpec,
|
|
912
869
|
informsPropagationSpec,
|
|
@@ -923,16 +880,15 @@ function getEdgePropagationSpecs() {
|
|
|
923
880
|
return EDGE_PROPAGATION_SPECS;
|
|
924
881
|
}
|
|
925
882
|
function getTraversalDirections(direction) {
|
|
926
|
-
if (
|
|
883
|
+
if (isPropagationTraversalDirection2(direction)) {
|
|
927
884
|
return [direction];
|
|
928
885
|
}
|
|
929
886
|
return ["outgoing", "incoming"];
|
|
930
887
|
}
|
|
931
888
|
|
|
932
889
|
// src/confidencePropagationDispatch.ts
|
|
933
|
-
function
|
|
934
|
-
|
|
935
|
-
return targetNodeId ?? void 0;
|
|
890
|
+
function nodeIdToCacheKey(nodeId) {
|
|
891
|
+
return String(nodeId);
|
|
936
892
|
}
|
|
937
893
|
function readNodeOpinion(node) {
|
|
938
894
|
const metadata = node.metadata ?? {};
|
|
@@ -948,118 +904,354 @@ function readNodeOpinion(node) {
|
|
|
948
904
|
return mkOpinion(0, 0, 1, 0.5);
|
|
949
905
|
}
|
|
950
906
|
}
|
|
907
|
+
function resolveTraversalTargetNodeId(edge, direction) {
|
|
908
|
+
const targetNodeId = direction === "outgoing" ? edge.toNodeId : edge.fromNodeId;
|
|
909
|
+
return targetNodeId ?? void 0;
|
|
910
|
+
}
|
|
911
|
+
function buildInitialState(sourceNodeId, sourceOpinion) {
|
|
912
|
+
return {
|
|
913
|
+
nodeId: sourceNodeId,
|
|
914
|
+
opinion: sourceOpinion,
|
|
915
|
+
hop: 0,
|
|
916
|
+
visitedNodeIds: /* @__PURE__ */ new Set([nodeIdToCacheKey(sourceNodeId)])
|
|
917
|
+
};
|
|
918
|
+
}
|
|
919
|
+
function extendVisited(currentVisited, targetNodeId) {
|
|
920
|
+
return /* @__PURE__ */ new Set([...currentVisited, nodeIdToCacheKey(targetNodeId)]);
|
|
921
|
+
}
|
|
922
|
+
function makeTransitiveState(current, targetNodeId, projectedOpinion, nextHop) {
|
|
923
|
+
return {
|
|
924
|
+
nodeId: targetNodeId,
|
|
925
|
+
opinion: projectedOpinion,
|
|
926
|
+
hop: nextHop,
|
|
927
|
+
visitedNodeIds: extendVisited(current.visitedNodeIds, targetNodeId)
|
|
928
|
+
};
|
|
929
|
+
}
|
|
930
|
+
function makeDispatchRecord(targetNodeId, spec, direction, edge, projectedOpinion, nextHop, result, existingDispatch) {
|
|
931
|
+
return {
|
|
932
|
+
targetNodeId,
|
|
933
|
+
edgeType: spec.edgeType,
|
|
934
|
+
traversedDirection: direction,
|
|
935
|
+
weight: edge.weight ?? 1,
|
|
936
|
+
opinion: projectedOpinion,
|
|
937
|
+
operator: result.operator,
|
|
938
|
+
rationale: existingDispatch ? `${existingDispatch.rationale}; ${result.rationale}` : result.rationale,
|
|
939
|
+
hop: nextHop
|
|
940
|
+
};
|
|
941
|
+
}
|
|
942
|
+
async function loadCachedNode(scope, nodeId) {
|
|
943
|
+
const cacheKey = nodeIdToCacheKey(nodeId);
|
|
944
|
+
if (!scope.nodeCache.has(cacheKey)) {
|
|
945
|
+
scope.nodeCache.set(cacheKey, await scope.args.getNode(nodeId));
|
|
946
|
+
}
|
|
947
|
+
return scope.nodeCache.get(cacheKey) ?? null;
|
|
948
|
+
}
|
|
949
|
+
async function collectTargetDispatch(state, nextHop, spec, direction, edge, queue, scope) {
|
|
950
|
+
const sourceScope = scope.args.sourceScope;
|
|
951
|
+
if (sourceScope && !edgeMatchesWorkspaceReasoningScope(edge, sourceScope)) {
|
|
952
|
+
return;
|
|
953
|
+
}
|
|
954
|
+
const targetNodeId = resolveTraversalTargetNodeId(edge, direction);
|
|
955
|
+
if (!targetNodeId) {
|
|
956
|
+
return;
|
|
957
|
+
}
|
|
958
|
+
const targetNodeIdKey = nodeIdToCacheKey(targetNodeId);
|
|
959
|
+
if (state.visitedNodeIds.has(targetNodeIdKey)) {
|
|
960
|
+
return;
|
|
961
|
+
}
|
|
962
|
+
const targetNode = await loadCachedNode(scope, targetNodeId);
|
|
963
|
+
if (targetNode?.nodeType !== "belief") {
|
|
964
|
+
return;
|
|
965
|
+
}
|
|
966
|
+
if (sourceScope && !nodeMatchesWorkspaceReasoningScope(targetNode, sourceScope)) {
|
|
967
|
+
return;
|
|
968
|
+
}
|
|
969
|
+
const targetOpinion = scope.opinionCache.get(targetNodeIdKey) ?? readNodeOpinion(targetNode);
|
|
970
|
+
const result = spec.operator(state.opinion, targetOpinion, edge, {
|
|
971
|
+
hop: nextHop,
|
|
972
|
+
sourceNodeId: state.nodeId,
|
|
973
|
+
targetNodeId,
|
|
974
|
+
traversedDirection: direction,
|
|
975
|
+
spec
|
|
976
|
+
});
|
|
977
|
+
if (!(result && hasProjectedOpinionChanged(targetOpinion, result.opinion))) {
|
|
978
|
+
return;
|
|
979
|
+
}
|
|
980
|
+
const projectedOpinion = mkOpinion(
|
|
981
|
+
result.opinion.b,
|
|
982
|
+
result.opinion.d,
|
|
983
|
+
result.opinion.u,
|
|
984
|
+
result.opinion.a
|
|
985
|
+
);
|
|
986
|
+
scope.opinionCache.set(targetNodeIdKey, projectedOpinion);
|
|
987
|
+
const existingDispatch = scope.dispatchesByTargetId.get(targetNodeIdKey);
|
|
988
|
+
scope.dispatchesByTargetId.set(
|
|
989
|
+
targetNodeIdKey,
|
|
990
|
+
makeDispatchRecord(
|
|
991
|
+
targetNodeId,
|
|
992
|
+
spec,
|
|
993
|
+
direction,
|
|
994
|
+
edge,
|
|
995
|
+
projectedOpinion,
|
|
996
|
+
nextHop,
|
|
997
|
+
result,
|
|
998
|
+
existingDispatch
|
|
999
|
+
)
|
|
1000
|
+
);
|
|
1001
|
+
if (canContinueTransitively2(spec, nextHop)) {
|
|
1002
|
+
queue.push(
|
|
1003
|
+
makeTransitiveState(state, targetNodeId, projectedOpinion, nextHop)
|
|
1004
|
+
);
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
async function processTraversalSpec(state, nextHop, spec, queue, scope) {
|
|
1008
|
+
const sourceNodeId = state.nodeId;
|
|
1009
|
+
for (const direction of getTraversalDirections(spec.direction)) {
|
|
1010
|
+
const edges = await scope.args.queryEdges({
|
|
1011
|
+
nodeId: sourceNodeId,
|
|
1012
|
+
spec,
|
|
1013
|
+
direction,
|
|
1014
|
+
hop: nextHop
|
|
1015
|
+
});
|
|
1016
|
+
for (const edge of edges) {
|
|
1017
|
+
await collectTargetDispatch(
|
|
1018
|
+
state,
|
|
1019
|
+
nextHop,
|
|
1020
|
+
spec,
|
|
1021
|
+
direction,
|
|
1022
|
+
edge,
|
|
1023
|
+
queue,
|
|
1024
|
+
scope
|
|
1025
|
+
);
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
async function processQueuedState(state, queue, scope) {
|
|
1030
|
+
const nextHop = state.hop + 1;
|
|
1031
|
+
for (const spec of scope.traversalSpecs) {
|
|
1032
|
+
if (!canTraverseHop2(spec, nextHop)) {
|
|
1033
|
+
continue;
|
|
1034
|
+
}
|
|
1035
|
+
await processTraversalSpec(state, nextHop, spec, queue, scope);
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
function sortDispatches(dispatches) {
|
|
1039
|
+
return Array.from(dispatches).sort((left, right) => {
|
|
1040
|
+
if (left.hop !== right.hop) {
|
|
1041
|
+
return left.hop - right.hop;
|
|
1042
|
+
}
|
|
1043
|
+
return String(left.targetNodeId).localeCompare(String(right.targetNodeId));
|
|
1044
|
+
});
|
|
1045
|
+
}
|
|
951
1046
|
async function collectConfidencePropagationDispatches(args) {
|
|
952
1047
|
const dispatchesByTargetId = /* @__PURE__ */ new Map();
|
|
953
1048
|
const opinionCache = /* @__PURE__ */ new Map();
|
|
954
1049
|
const nodeCache = /* @__PURE__ */ new Map();
|
|
955
1050
|
const traversalSpecs = args.traversalSpecs ?? getEdgePropagationSpecs();
|
|
1051
|
+
const scope = {
|
|
1052
|
+
args,
|
|
1053
|
+
dispatchesByTargetId,
|
|
1054
|
+
opinionCache,
|
|
1055
|
+
nodeCache,
|
|
1056
|
+
traversalSpecs
|
|
1057
|
+
};
|
|
956
1058
|
const queue = [
|
|
957
|
-
|
|
958
|
-
nodeId: args.sourceNodeId,
|
|
959
|
-
opinion: args.sourceOpinion,
|
|
960
|
-
hop: 0,
|
|
961
|
-
visitedNodeIds: /* @__PURE__ */ new Set([String(args.sourceNodeId)])
|
|
962
|
-
}
|
|
1059
|
+
buildInitialState(args.sourceNodeId, args.sourceOpinion)
|
|
963
1060
|
];
|
|
964
|
-
const loadNode = async (nodeId) => {
|
|
965
|
-
const cacheKey = String(nodeId);
|
|
966
|
-
if (!nodeCache.has(cacheKey)) {
|
|
967
|
-
nodeCache.set(cacheKey, await args.getNode(nodeId));
|
|
968
|
-
}
|
|
969
|
-
return nodeCache.get(cacheKey) ?? null;
|
|
970
|
-
};
|
|
971
1061
|
while (queue.length > 0) {
|
|
972
1062
|
const state = queue.shift();
|
|
973
1063
|
if (!state) {
|
|
974
1064
|
continue;
|
|
975
1065
|
}
|
|
976
|
-
|
|
977
|
-
const nextHop = state.hop + 1;
|
|
978
|
-
if (!canTraverseHop(spec, nextHop)) {
|
|
979
|
-
continue;
|
|
980
|
-
}
|
|
981
|
-
for (const direction of getTraversalDirections(spec.direction)) {
|
|
982
|
-
const edges = await args.queryEdges({
|
|
983
|
-
nodeId: state.nodeId,
|
|
984
|
-
spec,
|
|
985
|
-
direction,
|
|
986
|
-
hop: nextHop
|
|
987
|
-
});
|
|
988
|
-
for (const edge of edges) {
|
|
989
|
-
if (args.sourceScope && !edgeMatchesWorkspaceReasoningScope(edge, args.sourceScope)) {
|
|
990
|
-
continue;
|
|
991
|
-
}
|
|
992
|
-
const targetNodeId = resolveTraversalTargetNodeId(edge, direction);
|
|
993
|
-
if (!targetNodeId) {
|
|
994
|
-
continue;
|
|
995
|
-
}
|
|
996
|
-
if (state.visitedNodeIds.has(String(targetNodeId))) {
|
|
997
|
-
continue;
|
|
998
|
-
}
|
|
999
|
-
const targetNode = await loadNode(targetNodeId);
|
|
1000
|
-
if (!targetNode || targetNode.nodeType !== "belief") {
|
|
1001
|
-
continue;
|
|
1002
|
-
}
|
|
1003
|
-
if (args.sourceScope && !nodeMatchesWorkspaceReasoningScope(targetNode, args.sourceScope)) {
|
|
1004
|
-
continue;
|
|
1005
|
-
}
|
|
1006
|
-
const cacheKey = String(targetNodeId);
|
|
1007
|
-
const targetOpinion = opinionCache.get(cacheKey) ?? readNodeOpinion(targetNode);
|
|
1008
|
-
const result = spec.operator(state.opinion, targetOpinion, edge, {
|
|
1009
|
-
hop: nextHop,
|
|
1010
|
-
sourceNodeId: state.nodeId,
|
|
1011
|
-
targetNodeId,
|
|
1012
|
-
traversedDirection: direction,
|
|
1013
|
-
spec
|
|
1014
|
-
});
|
|
1015
|
-
if (!result || !hasProjectedOpinionChanged(targetOpinion, result.opinion)) {
|
|
1016
|
-
continue;
|
|
1017
|
-
}
|
|
1018
|
-
const projectedOpinion = mkOpinion(
|
|
1019
|
-
result.opinion.b,
|
|
1020
|
-
result.opinion.d,
|
|
1021
|
-
result.opinion.u,
|
|
1022
|
-
result.opinion.a
|
|
1023
|
-
);
|
|
1024
|
-
opinionCache.set(cacheKey, projectedOpinion);
|
|
1025
|
-
const existingDispatch = dispatchesByTargetId.get(cacheKey);
|
|
1026
|
-
dispatchesByTargetId.set(cacheKey, {
|
|
1027
|
-
targetNodeId,
|
|
1028
|
-
edgeType: spec.edgeType,
|
|
1029
|
-
traversedDirection: direction,
|
|
1030
|
-
weight: edge.weight ?? 1,
|
|
1031
|
-
opinion: projectedOpinion,
|
|
1032
|
-
operator: result.operator,
|
|
1033
|
-
rationale: existingDispatch ? `${existingDispatch.rationale}; ${result.rationale}` : result.rationale,
|
|
1034
|
-
hop: nextHop
|
|
1035
|
-
});
|
|
1036
|
-
if (canContinueTransitively(spec, nextHop)) {
|
|
1037
|
-
queue.push({
|
|
1038
|
-
nodeId: targetNodeId,
|
|
1039
|
-
opinion: projectedOpinion,
|
|
1040
|
-
hop: nextHop,
|
|
1041
|
-
visitedNodeIds: /* @__PURE__ */ new Set([
|
|
1042
|
-
...state.visitedNodeIds,
|
|
1043
|
-
String(targetNodeId)
|
|
1044
|
-
])
|
|
1045
|
-
});
|
|
1046
|
-
}
|
|
1047
|
-
}
|
|
1048
|
-
}
|
|
1049
|
-
}
|
|
1066
|
+
await processQueuedState(state, queue, scope);
|
|
1050
1067
|
}
|
|
1051
|
-
return
|
|
1052
|
-
if (left.hop !== right.hop) {
|
|
1053
|
-
return left.hop - right.hop;
|
|
1054
|
-
}
|
|
1055
|
-
return String(left.targetNodeId).localeCompare(String(right.targetNodeId));
|
|
1056
|
-
});
|
|
1068
|
+
return sortDispatches(dispatchesByTargetId.values());
|
|
1057
1069
|
}
|
|
1058
1070
|
|
|
1059
1071
|
// src/epistemicBeliefs.confidence.ts
|
|
1072
|
+
function isRecord(value) {
|
|
1073
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
1074
|
+
}
|
|
1075
|
+
function readConvexId(value) {
|
|
1076
|
+
return typeof value === "string" && value.trim().length > 0 ? value : void 0;
|
|
1077
|
+
}
|
|
1078
|
+
function readOptionalBoolean(value) {
|
|
1079
|
+
return typeof value === "boolean" ? value : void 0;
|
|
1080
|
+
}
|
|
1081
|
+
function readOptionalNumber(value) {
|
|
1082
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
1083
|
+
}
|
|
1084
|
+
function readOptionalString(value) {
|
|
1085
|
+
return typeof value === "string" && value.trim().length > 0 ? value : void 0;
|
|
1086
|
+
}
|
|
1087
|
+
function readRecord(value) {
|
|
1088
|
+
return isRecord(value) ? value : void 0;
|
|
1089
|
+
}
|
|
1090
|
+
function readConfidenceBeliefNode(value) {
|
|
1091
|
+
if (!isRecord(value)) {
|
|
1092
|
+
return null;
|
|
1093
|
+
}
|
|
1094
|
+
const id = readConvexId(value._id);
|
|
1095
|
+
const nodeType = readOptionalString(value.nodeType);
|
|
1096
|
+
const projectId = readOptionalString(value.projectId);
|
|
1097
|
+
if (!(id && nodeType === "belief" && projectId)) {
|
|
1098
|
+
return null;
|
|
1099
|
+
}
|
|
1100
|
+
const node = {
|
|
1101
|
+
_id: id,
|
|
1102
|
+
nodeType,
|
|
1103
|
+
projectId
|
|
1104
|
+
};
|
|
1105
|
+
const confidence = readOptionalNumber(value.confidence);
|
|
1106
|
+
const epistemicLayer = readOptionalString(value.epistemicLayer);
|
|
1107
|
+
const globalId = readOptionalString(value.globalId);
|
|
1108
|
+
const metadata = readRecord(value.metadata);
|
|
1109
|
+
const opinionA = readOptionalNumber(value.opinion_a);
|
|
1110
|
+
const opinionB = readOptionalNumber(value.opinion_b);
|
|
1111
|
+
const opinionD = readOptionalNumber(value.opinion_d);
|
|
1112
|
+
const opinionU = readOptionalNumber(value.opinion_u);
|
|
1113
|
+
const predictionMeta = readRecord(value.predictionMeta);
|
|
1114
|
+
const publicationStatus = readOptionalString(value.publicationStatus);
|
|
1115
|
+
const status = readOptionalString(value.status);
|
|
1116
|
+
const tenantId = readOptionalString(value.tenantId);
|
|
1117
|
+
const topicId = readOptionalString(value.topicId);
|
|
1118
|
+
const tupleContradicted = readOptionalBoolean(value.tupleContradicted);
|
|
1119
|
+
const workspaceId = readOptionalString(value.workspaceId);
|
|
1120
|
+
if (confidence !== void 0) {
|
|
1121
|
+
node.confidence = confidence;
|
|
1122
|
+
}
|
|
1123
|
+
if (epistemicLayer !== void 0) {
|
|
1124
|
+
node.epistemicLayer = epistemicLayer;
|
|
1125
|
+
}
|
|
1126
|
+
if (globalId !== void 0) {
|
|
1127
|
+
node.globalId = globalId;
|
|
1128
|
+
}
|
|
1129
|
+
if (metadata !== void 0) {
|
|
1130
|
+
node.metadata = metadata;
|
|
1131
|
+
}
|
|
1132
|
+
if (opinionA !== void 0) {
|
|
1133
|
+
node.opinion_a = opinionA;
|
|
1134
|
+
}
|
|
1135
|
+
if (opinionB !== void 0) {
|
|
1136
|
+
node.opinion_b = opinionB;
|
|
1137
|
+
}
|
|
1138
|
+
if (opinionD !== void 0) {
|
|
1139
|
+
node.opinion_d = opinionD;
|
|
1140
|
+
}
|
|
1141
|
+
if (opinionU !== void 0) {
|
|
1142
|
+
node.opinion_u = opinionU;
|
|
1143
|
+
}
|
|
1144
|
+
if (predictionMeta !== void 0) {
|
|
1145
|
+
node.predictionMeta = predictionMeta;
|
|
1146
|
+
}
|
|
1147
|
+
if (publicationStatus !== void 0) {
|
|
1148
|
+
node.publicationStatus = publicationStatus;
|
|
1149
|
+
}
|
|
1150
|
+
if (status !== void 0) {
|
|
1151
|
+
node.status = status;
|
|
1152
|
+
}
|
|
1153
|
+
if (tenantId !== void 0) {
|
|
1154
|
+
node.tenantId = tenantId;
|
|
1155
|
+
}
|
|
1156
|
+
if (topicId !== void 0) {
|
|
1157
|
+
node.topicId = topicId;
|
|
1158
|
+
}
|
|
1159
|
+
if (tupleContradicted !== void 0) {
|
|
1160
|
+
node.tupleContradicted = tupleContradicted;
|
|
1161
|
+
}
|
|
1162
|
+
if (workspaceId !== void 0) {
|
|
1163
|
+
node.workspaceId = workspaceId;
|
|
1164
|
+
}
|
|
1165
|
+
return node;
|
|
1166
|
+
}
|
|
1167
|
+
function readPropagationEdge(value) {
|
|
1168
|
+
if (!isRecord(value)) {
|
|
1169
|
+
return null;
|
|
1170
|
+
}
|
|
1171
|
+
const edgeType = readOptionalString(value.edgeType);
|
|
1172
|
+
if (!edgeType) {
|
|
1173
|
+
return null;
|
|
1174
|
+
}
|
|
1175
|
+
const edge = { edgeType };
|
|
1176
|
+
const fromNodeId = readConvexId(value.fromNodeId);
|
|
1177
|
+
const tenantId = readOptionalString(value.tenantId);
|
|
1178
|
+
const toNodeId = readConvexId(value.toNodeId);
|
|
1179
|
+
const weight = readOptionalNumber(value.weight);
|
|
1180
|
+
const workspaceId = readOptionalString(value.workspaceId);
|
|
1181
|
+
if (fromNodeId !== void 0) {
|
|
1182
|
+
edge.fromNodeId = fromNodeId;
|
|
1183
|
+
}
|
|
1184
|
+
if (tenantId !== void 0) {
|
|
1185
|
+
edge.tenantId = tenantId;
|
|
1186
|
+
}
|
|
1187
|
+
if (toNodeId !== void 0) {
|
|
1188
|
+
edge.toNodeId = toNodeId;
|
|
1189
|
+
}
|
|
1190
|
+
if (weight !== void 0) {
|
|
1191
|
+
edge.weight = weight;
|
|
1192
|
+
}
|
|
1193
|
+
if (workspaceId !== void 0) {
|
|
1194
|
+
edge.workspaceId = workspaceId;
|
|
1195
|
+
}
|
|
1196
|
+
return edge;
|
|
1197
|
+
}
|
|
1198
|
+
function readRowList(values, reader) {
|
|
1199
|
+
return values.flatMap((value) => {
|
|
1200
|
+
const row = reader(value);
|
|
1201
|
+
return row ? [row] : [];
|
|
1202
|
+
});
|
|
1203
|
+
}
|
|
1060
1204
|
async function applyBeliefConfidenceChange(ctx, args) {
|
|
1061
1205
|
const now = Date.now();
|
|
1062
|
-
const node = await ctx
|
|
1206
|
+
const node = await requireConfidenceBeliefNode(ctx, args);
|
|
1207
|
+
const state = await buildConfidenceChangeState(ctx, node, args);
|
|
1208
|
+
await assertConfidenceScoringPolicySatisfied(ctx, args, state);
|
|
1209
|
+
const tupleContradictionId = await createTupleContradictionIfNeeded(
|
|
1210
|
+
ctx,
|
|
1211
|
+
args,
|
|
1212
|
+
node,
|
|
1213
|
+
state
|
|
1214
|
+
);
|
|
1215
|
+
await patchBeliefConfidenceState(ctx, args, state);
|
|
1216
|
+
await scheduleFirstScoringThemeEdges(ctx, args, node, state);
|
|
1217
|
+
const beliefConfidenceId = await insertBeliefConfidenceRecord(
|
|
1218
|
+
ctx,
|
|
1219
|
+
args,
|
|
1220
|
+
state,
|
|
1221
|
+
tupleContradictionId,
|
|
1222
|
+
now
|
|
1223
|
+
);
|
|
1224
|
+
await ctx.scheduler.runAfter(0, internal.neo4jSync.syncNodeToNeo4j, {
|
|
1225
|
+
nodeId: args.nodeId,
|
|
1226
|
+
operation: "upsert"
|
|
1227
|
+
});
|
|
1228
|
+
await insertConfidenceAudit(
|
|
1229
|
+
ctx,
|
|
1230
|
+
args,
|
|
1231
|
+
node,
|
|
1232
|
+
state,
|
|
1233
|
+
tupleContradictionId,
|
|
1234
|
+
now
|
|
1235
|
+
);
|
|
1236
|
+
await insertTupleTransitionAuditIfNeeded(
|
|
1237
|
+
ctx,
|
|
1238
|
+
args,
|
|
1239
|
+
node,
|
|
1240
|
+
state,
|
|
1241
|
+
tupleContradictionId,
|
|
1242
|
+
now
|
|
1243
|
+
);
|
|
1244
|
+
await scheduleConfidenceFollowups(ctx, args, node, state);
|
|
1245
|
+
return {
|
|
1246
|
+
nodeId: args.nodeId,
|
|
1247
|
+
previousConfidence: state.previousConfidence,
|
|
1248
|
+
newConfidence: state.derivedConfidence,
|
|
1249
|
+
opinion: state.nextOpinion,
|
|
1250
|
+
beliefConfidenceId
|
|
1251
|
+
};
|
|
1252
|
+
}
|
|
1253
|
+
async function requireConfidenceBeliefNode(ctx, args) {
|
|
1254
|
+
const node = readConfidenceBeliefNode(await ctx.db.get(args.nodeId));
|
|
1063
1255
|
if (!node) {
|
|
1064
1256
|
throwStructuredMutationError({
|
|
1065
1257
|
message: "Node not found.",
|
|
@@ -1070,59 +1262,28 @@ async function applyBeliefConfidenceChange(ctx, args) {
|
|
|
1070
1262
|
details: { nodeId: args.nodeId }
|
|
1071
1263
|
});
|
|
1072
1264
|
}
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
invariantCode: "entity.no_confidence",
|
|
1079
|
-
suggestion: "Use entityLifecycle.updateEntityAttributes for entity mutations. appendSlScoring is for belief nodes only.",
|
|
1080
|
-
details: { nodeId: args.nodeId, nodeType: node.nodeType }
|
|
1081
|
-
});
|
|
1082
|
-
}
|
|
1083
|
-
if (!node.projectId) {
|
|
1084
|
-
throwStructuredMutationError({
|
|
1085
|
-
message: "Belief has no project scope.",
|
|
1086
|
-
status: 400,
|
|
1087
|
-
code: "MISSING_SCOPE",
|
|
1088
|
-
invariantCode: "belief.project_required",
|
|
1089
|
-
suggestion: "Belief must have a projectId before SL scoring can be appended.",
|
|
1090
|
-
details: { nodeId: args.nodeId }
|
|
1091
|
-
});
|
|
1092
|
-
}
|
|
1093
|
-
await requireProjectWriteAccess(
|
|
1094
|
-
ctx,
|
|
1095
|
-
node.projectId,
|
|
1096
|
-
args.authenticatedUserId
|
|
1097
|
-
);
|
|
1098
|
-
const existingMetadata = node.metadata || {};
|
|
1265
|
+
await requireScopeWriteAccess(ctx, node.projectId, args.authenticatedUserId);
|
|
1266
|
+
return node;
|
|
1267
|
+
}
|
|
1268
|
+
async function buildConfidenceChangeState(ctx, node, args) {
|
|
1269
|
+
const existingMetadata = readNodeMetadata(node);
|
|
1099
1270
|
const currentBeliefStatus = resolveBeliefStatus(node, existingMetadata);
|
|
1100
1271
|
const confidencePolicy = await getActiveConfidencePolicy(ctx);
|
|
1101
|
-
if (confidencePolicy.scoringMode === "after_worktree" && isPreValidationBeliefStatus(currentBeliefStatus)) {
|
|
1102
|
-
const hasCompletedWorktree = await hasCompletedWorktreeForBelief(
|
|
1103
|
-
ctx,
|
|
1104
|
-
args.nodeId
|
|
1105
|
-
);
|
|
1106
|
-
if (!hasCompletedWorktree) {
|
|
1107
|
-
throwStructuredMutationError({
|
|
1108
|
-
message: "Cannot score belief before worktree completion. Complete a worktree that tests this belief first.",
|
|
1109
|
-
status: 409,
|
|
1110
|
-
code: "CONFLICT",
|
|
1111
|
-
invariantCode: "belief.confidence_append_only",
|
|
1112
|
-
suggestion: "Complete a worktree linked to this belief before recording SL scoring.",
|
|
1113
|
-
details: { nodeId: args.nodeId }
|
|
1114
|
-
});
|
|
1115
|
-
}
|
|
1116
|
-
}
|
|
1117
1272
|
const previousConfidence = node.confidence || 0.5;
|
|
1118
1273
|
const predictionMeta = node.predictionMeta || existingMetadata.predictionMeta;
|
|
1119
1274
|
const previousOpinion = readBeliefOpinionSnapshot(node, existingMetadata);
|
|
1120
|
-
const
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1275
|
+
const nextOpinion = {
|
|
1276
|
+
b: args.belief,
|
|
1277
|
+
d: args.disbelief,
|
|
1278
|
+
u: args.uncertainty,
|
|
1279
|
+
a: args.baseRate ?? 0.5
|
|
1280
|
+
};
|
|
1281
|
+
const derivedConfidence = confidenceFromSL(
|
|
1282
|
+
nextOpinion.b,
|
|
1283
|
+
nextOpinion.d,
|
|
1284
|
+
nextOpinion.u,
|
|
1285
|
+
nextOpinion.a
|
|
1286
|
+
);
|
|
1126
1287
|
const isFirstScoring = typeof node.confidence !== "number" || !Number.isFinite(node.confidence);
|
|
1127
1288
|
const previousTupleContradicted = readTupleContradictedFlag(node.tupleContradicted) ?? readTupleContradictedFlag(existingMetadata.tupleContradicted) ?? detectTupleContradiction(
|
|
1128
1289
|
previousOpinion,
|
|
@@ -1143,79 +1304,121 @@ async function applyBeliefConfidenceChange(ctx, args) {
|
|
|
1143
1304
|
predictionMeta,
|
|
1144
1305
|
metadata: existingMetadata
|
|
1145
1306
|
});
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1307
|
+
const storedRationale = args.rationale ?? `Confidence changed from ${previousConfidence.toFixed(2)} (nodeId: ${args.nodeId})`;
|
|
1308
|
+
return {
|
|
1309
|
+
confidencePolicy,
|
|
1310
|
+
currentBeliefStatus,
|
|
1311
|
+
derivedConfidence,
|
|
1312
|
+
existingMetadata,
|
|
1313
|
+
isFirstScoring,
|
|
1314
|
+
newBeliefStatus,
|
|
1315
|
+
nextOpinion,
|
|
1316
|
+
previousConfidence,
|
|
1317
|
+
previousTupleContradicted,
|
|
1318
|
+
storedRationale,
|
|
1319
|
+
tupleContradictionDescription,
|
|
1320
|
+
tupleTransition
|
|
1321
|
+
};
|
|
1322
|
+
}
|
|
1323
|
+
function readNodeMetadata(node) {
|
|
1324
|
+
return node.metadata ?? {};
|
|
1325
|
+
}
|
|
1326
|
+
async function assertConfidenceScoringPolicySatisfied(ctx, args, state) {
|
|
1327
|
+
if (state.confidencePolicy.scoringMode !== "after_worktree" || !isPreValidationBeliefStatus(state.currentBeliefStatus)) {
|
|
1328
|
+
return;
|
|
1164
1329
|
}
|
|
1330
|
+
const hasCompletedWorktree = await hasCompletedWorktreeForBelief(
|
|
1331
|
+
ctx,
|
|
1332
|
+
args.nodeId
|
|
1333
|
+
);
|
|
1334
|
+
if (hasCompletedWorktree) {
|
|
1335
|
+
return;
|
|
1336
|
+
}
|
|
1337
|
+
throwStructuredMutationError({
|
|
1338
|
+
message: "Cannot score belief before worktree completion. Complete a worktree that tests this belief first.",
|
|
1339
|
+
status: 409,
|
|
1340
|
+
code: "CONFLICT",
|
|
1341
|
+
invariantCode: "belief.confidence_append_only",
|
|
1342
|
+
suggestion: "Complete a worktree linked to this belief before recording SL scoring.",
|
|
1343
|
+
details: { nodeId: args.nodeId }
|
|
1344
|
+
});
|
|
1345
|
+
}
|
|
1346
|
+
async function createTupleContradictionIfNeeded(ctx, args, node, state) {
|
|
1347
|
+
if (!state.tupleTransition.crossedIntoTupleContradiction) {
|
|
1348
|
+
return;
|
|
1349
|
+
}
|
|
1350
|
+
return await ctx.runMutation("contradictions:create", {
|
|
1351
|
+
projectId: node.projectId,
|
|
1352
|
+
topicId: node.topicId,
|
|
1353
|
+
beliefId: args.nodeId,
|
|
1354
|
+
beliefBId: args.nodeId,
|
|
1355
|
+
supportingInsightIds: [],
|
|
1356
|
+
contradictingInsightIds: [],
|
|
1357
|
+
severity: deriveTupleContradictionSeverity(node),
|
|
1358
|
+
source: "tuple_space",
|
|
1359
|
+
detectionMethod: "agent",
|
|
1360
|
+
description: state.tupleContradictionDescription,
|
|
1361
|
+
createdBy: args.authenticatedUserId
|
|
1362
|
+
});
|
|
1363
|
+
}
|
|
1364
|
+
async function patchBeliefConfidenceState(ctx, args, state) {
|
|
1165
1365
|
await ctx.db.patch(args.nodeId, {
|
|
1166
|
-
confidence: derivedConfidence,
|
|
1167
|
-
beliefStatus: newBeliefStatus,
|
|
1168
|
-
tupleContradicted: tupleTransition.tupleContradicted,
|
|
1169
|
-
updatedAt: now,
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
opinion_a: slA,
|
|
1366
|
+
confidence: state.derivedConfidence,
|
|
1367
|
+
beliefStatus: state.newBeliefStatus,
|
|
1368
|
+
tupleContradicted: state.tupleTransition.tupleContradicted,
|
|
1369
|
+
updatedAt: Date.now(),
|
|
1370
|
+
opinion_b: state.nextOpinion.b,
|
|
1371
|
+
opinion_d: state.nextOpinion.d,
|
|
1372
|
+
opinion_u: state.nextOpinion.u,
|
|
1373
|
+
opinion_a: state.nextOpinion.a,
|
|
1175
1374
|
metadata: {
|
|
1176
|
-
...existingMetadata,
|
|
1177
|
-
beliefStatus: newBeliefStatus,
|
|
1178
|
-
slBelief:
|
|
1179
|
-
slDisbelief:
|
|
1180
|
-
slUncertainty:
|
|
1181
|
-
slBaseRate:
|
|
1182
|
-
tupleContradicted: tupleTransition.tupleContradicted
|
|
1375
|
+
...state.existingMetadata,
|
|
1376
|
+
beliefStatus: state.newBeliefStatus,
|
|
1377
|
+
slBelief: state.nextOpinion.b,
|
|
1378
|
+
slDisbelief: state.nextOpinion.d,
|
|
1379
|
+
slUncertainty: state.nextOpinion.u,
|
|
1380
|
+
slBaseRate: state.nextOpinion.a,
|
|
1381
|
+
tupleContradicted: state.tupleTransition.tupleContradicted
|
|
1183
1382
|
}
|
|
1184
1383
|
});
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
edgeType: "relates_to_thesis",
|
|
1198
|
-
weight: derivedConfidence,
|
|
1199
|
-
createdBy: args.authenticatedUserId,
|
|
1200
|
-
topicId: String(node.projectId),
|
|
1201
|
-
fromNodeType: "belief",
|
|
1202
|
-
toNodeType: "theme",
|
|
1203
|
-
fromLayer: "L3",
|
|
1204
|
-
toLayer: "L3"
|
|
1205
|
-
});
|
|
1206
|
-
}
|
|
1384
|
+
}
|
|
1385
|
+
async function scheduleFirstScoringThemeEdges(ctx, args, node, state) {
|
|
1386
|
+
if (!state.isFirstScoring) {
|
|
1387
|
+
return;
|
|
1388
|
+
}
|
|
1389
|
+
const themeNodes = await ctx.db.query("epistemicNodes").withIndex(
|
|
1390
|
+
"by_topic",
|
|
1391
|
+
(q) => q.eq("topicId", node.topicId || node.projectId)
|
|
1392
|
+
).filter((q) => q.eq(q.field("nodeType"), "theme")).collect();
|
|
1393
|
+
for (const theme of themeNodes) {
|
|
1394
|
+
if (!(theme.globalId && node.globalId)) {
|
|
1395
|
+
continue;
|
|
1207
1396
|
}
|
|
1397
|
+
await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {
|
|
1398
|
+
globalId: `edge-${node.globalId}-relates_to_thesis-${theme.globalId}`,
|
|
1399
|
+
fromGlobalId: node.globalId,
|
|
1400
|
+
toGlobalId: theme.globalId,
|
|
1401
|
+
edgeType: "relates_to_thesis",
|
|
1402
|
+
weight: state.derivedConfidence,
|
|
1403
|
+
createdBy: args.authenticatedUserId,
|
|
1404
|
+
topicId: String(node.projectId),
|
|
1405
|
+
fromNodeType: "belief",
|
|
1406
|
+
toNodeType: "theme",
|
|
1407
|
+
fromLayer: "L3",
|
|
1408
|
+
toLayer: "L3"
|
|
1409
|
+
});
|
|
1208
1410
|
}
|
|
1209
|
-
|
|
1210
|
-
|
|
1411
|
+
}
|
|
1412
|
+
async function insertBeliefConfidenceRecord(ctx, args, state, tupleContradictionId, now) {
|
|
1413
|
+
return await ctx.db.insert("beliefConfidence", {
|
|
1211
1414
|
...buildBeliefConfidenceRow({
|
|
1212
1415
|
beliefId: args.nodeId,
|
|
1213
|
-
belief:
|
|
1214
|
-
disbelief:
|
|
1215
|
-
uncertainty:
|
|
1216
|
-
baseRate:
|
|
1416
|
+
belief: state.nextOpinion.b,
|
|
1417
|
+
disbelief: state.nextOpinion.d,
|
|
1418
|
+
uncertainty: state.nextOpinion.u,
|
|
1419
|
+
baseRate: state.nextOpinion.a,
|
|
1217
1420
|
trigger: args.trigger,
|
|
1218
|
-
rationale: storedRationale,
|
|
1421
|
+
rationale: state.storedRationale,
|
|
1219
1422
|
assessedBy: args.authenticatedUserId,
|
|
1220
1423
|
assessedAt: now,
|
|
1221
1424
|
slOperator: args.slOperator,
|
|
@@ -1224,25 +1427,23 @@ async function applyBeliefConfidenceChange(ctx, args) {
|
|
|
1224
1427
|
triggeringWorktreeId: args.triggeringWorktreeId
|
|
1225
1428
|
})
|
|
1226
1429
|
});
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
operation: "upsert"
|
|
1230
|
-
});
|
|
1430
|
+
}
|
|
1431
|
+
async function insertConfidenceAudit(ctx, args, node, state, tupleContradictionId, now) {
|
|
1231
1432
|
await ctx.db.insert("epistemicAudit", {
|
|
1232
1433
|
entityType: "belief",
|
|
1233
1434
|
entityId: args.nodeId,
|
|
1234
1435
|
changeType: "confidence_changed",
|
|
1235
1436
|
previousState: {
|
|
1236
|
-
confidence: previousConfidence,
|
|
1237
|
-
tupleContradicted: previousTupleContradicted
|
|
1437
|
+
confidence: state.previousConfidence,
|
|
1438
|
+
tupleContradicted: state.previousTupleContradicted
|
|
1238
1439
|
},
|
|
1239
1440
|
newState: {
|
|
1240
|
-
opinion: nextOpinion,
|
|
1241
|
-
confidence: derivedConfidence,
|
|
1441
|
+
opinion: state.nextOpinion,
|
|
1442
|
+
confidence: state.derivedConfidence,
|
|
1242
1443
|
trigger: args.trigger,
|
|
1243
|
-
rationale: storedRationale,
|
|
1244
|
-
tupleContradicted: tupleTransition.tupleContradicted,
|
|
1245
|
-
tupleContradictionPolicy: tupleTransition.policy,
|
|
1444
|
+
rationale: state.storedRationale,
|
|
1445
|
+
tupleContradicted: state.tupleTransition.tupleContradicted,
|
|
1446
|
+
tupleContradictionPolicy: state.tupleTransition.policy,
|
|
1246
1447
|
...tupleContradictionId ? { tupleContradictionId: String(tupleContradictionId) } : {}
|
|
1247
1448
|
},
|
|
1248
1449
|
changedBy: args.authenticatedUserId,
|
|
@@ -1251,28 +1452,39 @@ async function applyBeliefConfidenceChange(ctx, args) {
|
|
|
1251
1452
|
projectId: node.projectId,
|
|
1252
1453
|
topicId: node.topicId
|
|
1253
1454
|
});
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1455
|
+
}
|
|
1456
|
+
async function insertTupleTransitionAuditIfNeeded(ctx, args, node, state, tupleContradictionId, now) {
|
|
1457
|
+
if (!(state.tupleTransition.crossedIntoTupleContradiction || state.tupleTransition.crossedOutOfTupleContradiction)) {
|
|
1458
|
+
return;
|
|
1459
|
+
}
|
|
1460
|
+
await ctx.db.insert("epistemicAudit", {
|
|
1461
|
+
entityType: "belief",
|
|
1462
|
+
entityId: args.nodeId,
|
|
1463
|
+
changeType: "updated",
|
|
1464
|
+
previousState: { tupleContradicted: state.previousTupleContradicted },
|
|
1465
|
+
newState: {
|
|
1466
|
+
tupleContradicted: state.tupleTransition.tupleContradicted,
|
|
1467
|
+
action: state.tupleTransition.crossedIntoTupleContradiction ? "tuple_contradiction_detected" : "tuple_contradiction_cleared",
|
|
1468
|
+
opinion: state.nextOpinion,
|
|
1469
|
+
tupleContradictionPolicy: state.tupleTransition.policy,
|
|
1470
|
+
...tupleContradictionId ? { tupleContradictionId: String(tupleContradictionId) } : {}
|
|
1471
|
+
},
|
|
1472
|
+
rationale: tupleAuditRationale(state),
|
|
1473
|
+
changedBy: args.authenticatedUserId,
|
|
1474
|
+
isAgent: false,
|
|
1475
|
+
changedAt: now,
|
|
1476
|
+
projectId: node.projectId,
|
|
1477
|
+
topicId: node.topicId
|
|
1478
|
+
});
|
|
1479
|
+
}
|
|
1480
|
+
function tupleAuditRationale(state) {
|
|
1481
|
+
if (state.tupleTransition.crossedIntoTupleContradiction) {
|
|
1482
|
+
return state.tupleContradictionDescription;
|
|
1274
1483
|
}
|
|
1275
|
-
|
|
1484
|
+
return `Tuple-space contradiction cleared: b=${state.nextOpinion.b.toFixed(2)}, d=${state.nextOpinion.d.toFixed(2)} no longer exceed the configured policy thresholds.`;
|
|
1485
|
+
}
|
|
1486
|
+
async function scheduleConfidenceFollowups(ctx, args, node, state) {
|
|
1487
|
+
if (Math.abs(state.derivedConfidence - state.previousConfidence) >= 0.15) {
|
|
1276
1488
|
await ctx.scheduler.runAfter(
|
|
1277
1489
|
5e3,
|
|
1278
1490
|
internal.bi.contradictionSemanticDetector.scanAffectedBeliefs,
|
|
@@ -1289,13 +1501,6 @@ async function applyBeliefConfidenceChange(ctx, args) {
|
|
|
1289
1501
|
{ nodeId: args.nodeId }
|
|
1290
1502
|
);
|
|
1291
1503
|
}
|
|
1292
|
-
return {
|
|
1293
|
-
nodeId: args.nodeId,
|
|
1294
|
-
previousConfidence,
|
|
1295
|
-
newConfidence: derivedConfidence,
|
|
1296
|
-
opinion: { b: slB, d: slD, u: slU, a: slA },
|
|
1297
|
-
beliefConfidenceId
|
|
1298
|
-
};
|
|
1299
1504
|
}
|
|
1300
1505
|
function propagationPressureLabel(edgeType, weight) {
|
|
1301
1506
|
if (edgeType === "contradicts" || edgeType === "refutes") {
|
|
@@ -1323,7 +1528,7 @@ internalMutation({
|
|
|
1323
1528
|
args.opinion_u,
|
|
1324
1529
|
args.opinion_a
|
|
1325
1530
|
);
|
|
1326
|
-
const sourceNode = await ctx.db.get(args.nodeId);
|
|
1531
|
+
const sourceNode = readConfidenceBeliefNode(await ctx.db.get(args.nodeId));
|
|
1327
1532
|
const sourceScope = await resolveNodeScopeForWorkspaceIsolation(
|
|
1328
1533
|
ctx,
|
|
1329
1534
|
sourceNode
|
|
@@ -1332,16 +1537,20 @@ internalMutation({
|
|
|
1332
1537
|
sourceNodeId: args.nodeId,
|
|
1333
1538
|
sourceOpinion,
|
|
1334
1539
|
sourceScope,
|
|
1335
|
-
queryEdges: async ({ nodeId, spec, direction }) =>
|
|
1336
|
-
|
|
1540
|
+
queryEdges: async ({ nodeId, spec, direction }) => readRowList(
|
|
1541
|
+
await ctx.db.query("epistemicEdges").withIndex(
|
|
1337
1542
|
direction === "outgoing" ? "by_from_type" : "by_to_type",
|
|
1338
1543
|
(q) => direction === "outgoing" ? q.eq("fromNodeId", nodeId).eq("edgeType", spec.edgeType) : q.eq("toNodeId", nodeId).eq("edgeType", spec.edgeType)
|
|
1339
|
-
).collect()
|
|
1340
|
-
|
|
1341
|
-
|
|
1544
|
+
).collect(),
|
|
1545
|
+
readPropagationEdge
|
|
1546
|
+
),
|
|
1547
|
+
getNode: async (nodeId) => readConfidenceBeliefNode(await ctx.db.get(nodeId))
|
|
1342
1548
|
});
|
|
1343
1549
|
for (const dispatch of dispatches) {
|
|
1344
|
-
const pressureLabel = propagationPressureLabel(
|
|
1550
|
+
const pressureLabel = propagationPressureLabel(
|
|
1551
|
+
dispatch.edgeType,
|
|
1552
|
+
dispatch.weight
|
|
1553
|
+
);
|
|
1345
1554
|
await applyBeliefConfidenceChange(ctx, {
|
|
1346
1555
|
nodeId: dispatch.targetNodeId,
|
|
1347
1556
|
belief: dispatch.opinion.b,
|
|
@@ -1371,9 +1580,7 @@ var ACTIVE_CONTRADICTION_STATUSES = /* @__PURE__ */ new Set([
|
|
|
1371
1580
|
"investigating",
|
|
1372
1581
|
"accepted_as_permanent"
|
|
1373
1582
|
]);
|
|
1374
|
-
var DEPENDENT_EDGE_TYPES = /* @__PURE__ */ new Set([
|
|
1375
|
-
"depends_on"
|
|
1376
|
-
]);
|
|
1583
|
+
var DEPENDENT_EDGE_TYPES = /* @__PURE__ */ new Set(["depends_on"]);
|
|
1377
1584
|
function classifyContradictionStatus(status) {
|
|
1378
1585
|
if (typeof status !== "string") {
|
|
1379
1586
|
return "active";
|
|
@@ -1386,6 +1593,99 @@ function classifyContradictionStatus(status) {
|
|
|
1386
1593
|
}
|
|
1387
1594
|
return "resolved";
|
|
1388
1595
|
}
|
|
1596
|
+
function isRecord2(value) {
|
|
1597
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
1598
|
+
}
|
|
1599
|
+
function readOptionalNumber2(value) {
|
|
1600
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
1601
|
+
}
|
|
1602
|
+
function readOptionalString2(value) {
|
|
1603
|
+
return typeof value === "string" && value.trim().length > 0 ? value : void 0;
|
|
1604
|
+
}
|
|
1605
|
+
function readConvexId2(value) {
|
|
1606
|
+
const normalized = readOptionalString2(value);
|
|
1607
|
+
return normalized;
|
|
1608
|
+
}
|
|
1609
|
+
function readMetricNodeDoc(value) {
|
|
1610
|
+
if (!isRecord2(value)) {
|
|
1611
|
+
return null;
|
|
1612
|
+
}
|
|
1613
|
+
const id = readConvexId2(value._id);
|
|
1614
|
+
const nodeType = readOptionalString2(value.nodeType);
|
|
1615
|
+
if (!(id && nodeType)) {
|
|
1616
|
+
return null;
|
|
1617
|
+
}
|
|
1618
|
+
const node = { _id: id, nodeType };
|
|
1619
|
+
const globalId = readOptionalString2(value.globalId);
|
|
1620
|
+
if (globalId !== void 0) {
|
|
1621
|
+
node.globalId = globalId;
|
|
1622
|
+
}
|
|
1623
|
+
if ("metadata" in value) {
|
|
1624
|
+
node.metadata = value.metadata;
|
|
1625
|
+
}
|
|
1626
|
+
const status = readOptionalString2(value.status);
|
|
1627
|
+
if (status !== void 0) {
|
|
1628
|
+
node.status = status;
|
|
1629
|
+
}
|
|
1630
|
+
return node;
|
|
1631
|
+
}
|
|
1632
|
+
function readIncomingEdgeRow(value) {
|
|
1633
|
+
if (!isRecord2(value)) {
|
|
1634
|
+
return null;
|
|
1635
|
+
}
|
|
1636
|
+
const fromNodeId = readOptionalString2(value.fromNodeId);
|
|
1637
|
+
if (!fromNodeId) {
|
|
1638
|
+
return null;
|
|
1639
|
+
}
|
|
1640
|
+
const edge = { fromNodeId };
|
|
1641
|
+
const id = readConvexId2(value._id);
|
|
1642
|
+
if (id !== void 0) {
|
|
1643
|
+
edge._id = id;
|
|
1644
|
+
}
|
|
1645
|
+
const edgeType = readOptionalString2(value.edgeType);
|
|
1646
|
+
if (edgeType !== void 0) {
|
|
1647
|
+
edge.edgeType = edgeType;
|
|
1648
|
+
}
|
|
1649
|
+
const fromGlobalId = readOptionalString2(value.fromGlobalId);
|
|
1650
|
+
if (fromGlobalId !== void 0) {
|
|
1651
|
+
edge.fromGlobalId = fromGlobalId;
|
|
1652
|
+
}
|
|
1653
|
+
const fromUuid = readOptionalString2(value.fromUuid);
|
|
1654
|
+
if (fromUuid !== void 0) {
|
|
1655
|
+
edge.fromUuid = fromUuid;
|
|
1656
|
+
}
|
|
1657
|
+
const sourceGlobalId = readOptionalString2(value.sourceGlobalId);
|
|
1658
|
+
if (sourceGlobalId !== void 0) {
|
|
1659
|
+
edge.sourceGlobalId = sourceGlobalId;
|
|
1660
|
+
}
|
|
1661
|
+
const targetGlobalId = readOptionalString2(value.targetGlobalId);
|
|
1662
|
+
if (targetGlobalId !== void 0) {
|
|
1663
|
+
edge.targetGlobalId = targetGlobalId;
|
|
1664
|
+
}
|
|
1665
|
+
const toGlobalId = readOptionalString2(value.toGlobalId);
|
|
1666
|
+
if (toGlobalId !== void 0) {
|
|
1667
|
+
edge.toGlobalId = toGlobalId;
|
|
1668
|
+
}
|
|
1669
|
+
const toNodeId = readOptionalString2(value.toNodeId);
|
|
1670
|
+
if (toNodeId !== void 0) {
|
|
1671
|
+
edge.toNodeId = toNodeId;
|
|
1672
|
+
}
|
|
1673
|
+
const toUuid = readOptionalString2(value.toUuid);
|
|
1674
|
+
if (toUuid !== void 0) {
|
|
1675
|
+
edge.toUuid = toUuid;
|
|
1676
|
+
}
|
|
1677
|
+
const weight = readOptionalNumber2(value.weight);
|
|
1678
|
+
if (weight !== void 0) {
|
|
1679
|
+
edge.weight = weight;
|
|
1680
|
+
}
|
|
1681
|
+
for (const timestampField of ["_creationTime", "createdAt", "updatedAt"]) {
|
|
1682
|
+
const timestamp = readOptionalNumber2(value[timestampField]);
|
|
1683
|
+
if (timestamp !== void 0) {
|
|
1684
|
+
edge[timestampField] = timestamp;
|
|
1685
|
+
}
|
|
1686
|
+
}
|
|
1687
|
+
return edge;
|
|
1688
|
+
}
|
|
1389
1689
|
function getEdgeTimestamp(edge) {
|
|
1390
1690
|
if (typeof edge.updatedAt === "number") {
|
|
1391
1691
|
return edge.updatedAt;
|
|
@@ -1398,22 +1698,86 @@ function getEdgeTimestamp(edge) {
|
|
|
1398
1698
|
}
|
|
1399
1699
|
return null;
|
|
1400
1700
|
}
|
|
1701
|
+
async function collectNodeEndpointRefs(ctx, nodeId) {
|
|
1702
|
+
const refs = /* @__PURE__ */ new Set([String(nodeId)]);
|
|
1703
|
+
const node = readMetricNodeDoc(await ctx.db.get(nodeId));
|
|
1704
|
+
if (node?.globalId) {
|
|
1705
|
+
refs.add(node.globalId);
|
|
1706
|
+
}
|
|
1707
|
+
return [...refs];
|
|
1708
|
+
}
|
|
1709
|
+
async function collectIncomingEdgeRows(ctx, nodeId, edgeType) {
|
|
1710
|
+
const refs = await collectNodeEndpointRefs(ctx, nodeId);
|
|
1711
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1712
|
+
const edges = [];
|
|
1713
|
+
for (const ref of refs) {
|
|
1714
|
+
const rows = edgeType === void 0 ? await ctx.db.query("epistemicEdges").withIndex("by_to", (q) => q.eq("toNodeId", ref)).collect() : await ctx.db.query("epistemicEdges").withIndex(
|
|
1715
|
+
"by_to_type",
|
|
1716
|
+
(q) => q.eq("toNodeId", ref).eq("edgeType", edgeType)
|
|
1717
|
+
).collect();
|
|
1718
|
+
for (const row of rows) {
|
|
1719
|
+
const edge = readIncomingEdgeRow(row);
|
|
1720
|
+
if (!edge) {
|
|
1721
|
+
continue;
|
|
1722
|
+
}
|
|
1723
|
+
if (edgeType !== void 0 && edge.edgeType !== edgeType) {
|
|
1724
|
+
continue;
|
|
1725
|
+
}
|
|
1726
|
+
const key = edge._id === void 0 ? `${edge.fromNodeId}->${edge.toNodeId ?? ref}:${edge.edgeType ?? ""}` : String(edge._id);
|
|
1727
|
+
if (seen.has(key)) {
|
|
1728
|
+
continue;
|
|
1729
|
+
}
|
|
1730
|
+
seen.add(key);
|
|
1731
|
+
edges.push(edge);
|
|
1732
|
+
}
|
|
1733
|
+
}
|
|
1734
|
+
return edges;
|
|
1735
|
+
}
|
|
1736
|
+
function sourceEndpointRefs(edge) {
|
|
1737
|
+
return [
|
|
1738
|
+
edge.fromNodeId,
|
|
1739
|
+
edge.sourceGlobalId,
|
|
1740
|
+
edge.fromGlobalId,
|
|
1741
|
+
edge.fromUuid
|
|
1742
|
+
].filter((value) => value !== void 0);
|
|
1743
|
+
}
|
|
1744
|
+
async function resolveEndpointNode(ctx, refs) {
|
|
1745
|
+
const candidates = refs.map((value) => value.trim()).filter(
|
|
1746
|
+
(value, index, values) => value.length > 0 && values.indexOf(value) === index
|
|
1747
|
+
);
|
|
1748
|
+
for (const candidate of candidates) {
|
|
1749
|
+
try {
|
|
1750
|
+
const direct = readMetricNodeDoc(
|
|
1751
|
+
await ctx.db.get(candidate)
|
|
1752
|
+
);
|
|
1753
|
+
if (direct) {
|
|
1754
|
+
return direct;
|
|
1755
|
+
}
|
|
1756
|
+
} catch {
|
|
1757
|
+
}
|
|
1758
|
+
const byGlobalId = readMetricNodeDoc(
|
|
1759
|
+
await ctx.db.query("epistemicNodes").withIndex("by_globalId", (q) => q.eq("globalId", candidate)).first()
|
|
1760
|
+
);
|
|
1761
|
+
if (byGlobalId) {
|
|
1762
|
+
return byGlobalId;
|
|
1763
|
+
}
|
|
1764
|
+
}
|
|
1765
|
+
return null;
|
|
1766
|
+
}
|
|
1401
1767
|
async function getEvidenceLinks(ctx, beliefNodeId) {
|
|
1402
|
-
const edges = await ctx
|
|
1403
|
-
"by_to_type",
|
|
1404
|
-
(q) => q.eq("toNodeId", beliefNodeId).eq("edgeType", "informs")
|
|
1405
|
-
).collect();
|
|
1768
|
+
const edges = await collectIncomingEdgeRows(ctx, beliefNodeId, "informs");
|
|
1406
1769
|
if (edges.length === 0) {
|
|
1407
1770
|
return [];
|
|
1408
1771
|
}
|
|
1409
|
-
const
|
|
1410
|
-
|
|
1411
|
-
const node =
|
|
1412
|
-
if (
|
|
1413
|
-
|
|
1772
|
+
const links = [];
|
|
1773
|
+
for (const edge of edges) {
|
|
1774
|
+
const node = await resolveEndpointNode(ctx, sourceEndpointRefs(edge));
|
|
1775
|
+
if (node?.nodeType !== "evidence" || node.status === "archived") {
|
|
1776
|
+
continue;
|
|
1414
1777
|
}
|
|
1415
|
-
|
|
1416
|
-
}
|
|
1778
|
+
links.push({ edge, node });
|
|
1779
|
+
}
|
|
1780
|
+
return links;
|
|
1417
1781
|
}
|
|
1418
1782
|
function getEvidenceTags(node) {
|
|
1419
1783
|
const metadata = node.metadata && typeof node.metadata === "object" ? node.metadata : null;
|
|
@@ -1439,7 +1803,8 @@ async function computeTaggedEvidenceCount(args) {
|
|
|
1439
1803
|
};
|
|
1440
1804
|
}
|
|
1441
1805
|
async function computeContradictionCounts(ctx, beliefNodeId) {
|
|
1442
|
-
const
|
|
1806
|
+
const contradictionDb = ctx.db;
|
|
1807
|
+
const contradictions = await contradictionDb.query("contradictions").withIndex("by_beliefId", (q) => q.eq("beliefId", beliefNodeId)).collect();
|
|
1443
1808
|
return contradictions.reduce(
|
|
1444
1809
|
(counts, contradiction) => {
|
|
1445
1810
|
const status = contradiction.resolutionStatus ?? contradiction.status ?? "unresolved";
|
|
@@ -1475,18 +1840,16 @@ async function computeEvidenceFreshness(ctx, beliefNodeId, now = Date.now()) {
|
|
|
1475
1840
|
};
|
|
1476
1841
|
}
|
|
1477
1842
|
async function computeDependentBeliefCount(ctx, beliefNodeId) {
|
|
1478
|
-
const incomingEdges = await ctx
|
|
1843
|
+
const incomingEdges = await collectIncomingEdgeRows(ctx, beliefNodeId);
|
|
1479
1844
|
const dependencyEdges = incomingEdges.filter(
|
|
1480
|
-
(edge) => DEPENDENT_EDGE_TYPES.has(edge.edgeType)
|
|
1845
|
+
(edge) => edge.edgeType ? DEPENDENT_EDGE_TYPES.has(edge.edgeType) : false
|
|
1481
1846
|
);
|
|
1482
1847
|
if (dependencyEdges.length === 0) {
|
|
1483
1848
|
return 0;
|
|
1484
1849
|
}
|
|
1485
|
-
const dependentBeliefs = await Promise.all(
|
|
1486
|
-
dependencyEdges.map((edge) => ctx.db.get(edge.fromNodeId))
|
|
1487
|
-
);
|
|
1488
1850
|
const uniqueBeliefIds = /* @__PURE__ */ new Set();
|
|
1489
|
-
for (const
|
|
1851
|
+
for (const edge of dependencyEdges) {
|
|
1852
|
+
const node = await resolveEndpointNode(ctx, sourceEndpointRefs(edge));
|
|
1490
1853
|
if (node && node.nodeType === "belief" && node.status !== "archived" && node.status !== "deleted") {
|
|
1491
1854
|
uniqueBeliefIds.add(String(node._id));
|
|
1492
1855
|
}
|
|
@@ -1496,7 +1859,10 @@ async function computeDependentBeliefCount(ctx, beliefNodeId) {
|
|
|
1496
1859
|
async function snapshotEvidentialMetric(args) {
|
|
1497
1860
|
switch (args.metric) {
|
|
1498
1861
|
case "evidence_count": {
|
|
1499
|
-
const count = await computeEvidenceCountMetric(
|
|
1862
|
+
const count = await computeEvidenceCountMetric(
|
|
1863
|
+
args.ctx,
|
|
1864
|
+
args.beliefNodeId
|
|
1865
|
+
);
|
|
1500
1866
|
return {
|
|
1501
1867
|
metric: args.metric,
|
|
1502
1868
|
value: count,
|
|
@@ -1504,7 +1870,10 @@ async function snapshotEvidentialMetric(args) {
|
|
|
1504
1870
|
};
|
|
1505
1871
|
}
|
|
1506
1872
|
case "contradiction_status": {
|
|
1507
|
-
const counts = await computeContradictionCounts(
|
|
1873
|
+
const counts = await computeContradictionCounts(
|
|
1874
|
+
args.ctx,
|
|
1875
|
+
args.beliefNodeId
|
|
1876
|
+
);
|
|
1508
1877
|
return {
|
|
1509
1878
|
metric: args.metric,
|
|
1510
1879
|
value: counts.activeCount,
|
|
@@ -1524,7 +1893,10 @@ async function snapshotEvidentialMetric(args) {
|
|
|
1524
1893
|
};
|
|
1525
1894
|
}
|
|
1526
1895
|
case "dependent_count": {
|
|
1527
|
-
const count = await computeDependentBeliefCount(
|
|
1896
|
+
const count = await computeDependentBeliefCount(
|
|
1897
|
+
args.ctx,
|
|
1898
|
+
args.beliefNodeId
|
|
1899
|
+
);
|
|
1528
1900
|
return {
|
|
1529
1901
|
metric: args.metric,
|
|
1530
1902
|
value: count,
|
|
@@ -1540,7 +1912,9 @@ async function snapshotEvidentialMetric(args) {
|
|
|
1540
1912
|
}
|
|
1541
1913
|
}
|
|
1542
1914
|
async function evaluateBuiltInEvidentialContract(args) {
|
|
1543
|
-
const config = parseEvidentialEvaluatorConfig(
|
|
1915
|
+
const config = parseEvidentialEvaluatorConfig(
|
|
1916
|
+
args.contract.condition.evaluatorConfig
|
|
1917
|
+
);
|
|
1544
1918
|
const snapshot = await snapshotEvidentialMetric({
|
|
1545
1919
|
ctx: args.ctx,
|
|
1546
1920
|
beliefNodeId: args.belief._id,
|
|
@@ -1548,7 +1922,10 @@ async function evaluateBuiltInEvidentialContract(args) {
|
|
|
1548
1922
|
now: args.now
|
|
1549
1923
|
});
|
|
1550
1924
|
const comparisonSatisfied = snapshot.value !== null && compareMetricValue(config.operator, snapshot.value, config.threshold);
|
|
1551
|
-
const result =
|
|
1925
|
+
const result = resolveComparisonResult(
|
|
1926
|
+
args.contract.direction,
|
|
1927
|
+
comparisonSatisfied
|
|
1928
|
+
);
|
|
1552
1929
|
return {
|
|
1553
1930
|
result,
|
|
1554
1931
|
rationale: buildEvidentialRationale({
|
|
@@ -1568,57 +1945,66 @@ async function evaluateBuiltInEvidentialContract(args) {
|
|
|
1568
1945
|
}
|
|
1569
1946
|
};
|
|
1570
1947
|
}
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
"
|
|
1577
|
-
"
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1948
|
+
function evaluateMetricCheckerContract(args) {
|
|
1949
|
+
return Promise.resolve().then(() => {
|
|
1950
|
+
const config = parseMetricCheckerConfig(
|
|
1951
|
+
args.contract.condition.evaluatorConfig
|
|
1952
|
+
);
|
|
1953
|
+
const input = getEvaluatorInputRecord(args.inputData, "metricData");
|
|
1954
|
+
const metric = typeof input.metric === "string" && input.metric.length > 0 ? input.metric : config.metric;
|
|
1955
|
+
const observedValue = pickFiniteNumber(input, [
|
|
1956
|
+
"observedValue",
|
|
1957
|
+
"currentValue",
|
|
1958
|
+
"metricValue",
|
|
1959
|
+
"value"
|
|
1960
|
+
]) ?? config.observedValue ?? config.currentValue ?? config.metricValue ?? null;
|
|
1961
|
+
if (observedValue === null) {
|
|
1962
|
+
return {
|
|
1963
|
+
result: "inconclusive",
|
|
1964
|
+
rationale: `metric_checker is awaiting data for ${metric ?? args.contract.condition.expression}.`,
|
|
1965
|
+
data: {
|
|
1966
|
+
metric,
|
|
1967
|
+
observedValue: null,
|
|
1968
|
+
operator: config.operator,
|
|
1969
|
+
threshold: config.threshold,
|
|
1970
|
+
unit: config.unit
|
|
1971
|
+
}
|
|
1972
|
+
};
|
|
1973
|
+
}
|
|
1974
|
+
const comparisonSatisfied = compareMetricValue(
|
|
1975
|
+
config.operator,
|
|
1976
|
+
observedValue,
|
|
1977
|
+
config.threshold
|
|
1978
|
+
);
|
|
1979
|
+
const result = resolveComparisonResult(
|
|
1980
|
+
args.contract.direction,
|
|
1981
|
+
comparisonSatisfied
|
|
1982
|
+
);
|
|
1582
1983
|
return {
|
|
1583
|
-
result
|
|
1584
|
-
rationale:
|
|
1984
|
+
result,
|
|
1985
|
+
rationale: buildComparisonRationale({
|
|
1986
|
+
label: metric ?? "metric",
|
|
1987
|
+
observedValue,
|
|
1988
|
+
operator: config.operator,
|
|
1989
|
+
threshold: config.threshold,
|
|
1990
|
+
comparisonSatisfied,
|
|
1991
|
+
result,
|
|
1992
|
+
unit: config.unit
|
|
1993
|
+
}),
|
|
1585
1994
|
data: {
|
|
1586
1995
|
metric,
|
|
1587
|
-
observedValue
|
|
1996
|
+
observedValue,
|
|
1588
1997
|
operator: config.operator,
|
|
1589
1998
|
threshold: config.threshold,
|
|
1590
1999
|
unit: config.unit
|
|
1591
2000
|
}
|
|
1592
2001
|
};
|
|
1593
|
-
}
|
|
1594
|
-
const comparisonSatisfied = compareMetricValue(
|
|
1595
|
-
config.operator,
|
|
1596
|
-
observedValue,
|
|
1597
|
-
config.threshold
|
|
1598
|
-
);
|
|
1599
|
-
const result = resolveComparisonResult(args.contract.direction, comparisonSatisfied);
|
|
1600
|
-
return {
|
|
1601
|
-
result,
|
|
1602
|
-
rationale: buildComparisonRationale({
|
|
1603
|
-
label: metric ?? "metric",
|
|
1604
|
-
observedValue,
|
|
1605
|
-
operator: config.operator,
|
|
1606
|
-
threshold: config.threshold,
|
|
1607
|
-
comparisonSatisfied,
|
|
1608
|
-
result,
|
|
1609
|
-
unit: config.unit
|
|
1610
|
-
}),
|
|
1611
|
-
data: {
|
|
1612
|
-
metric,
|
|
1613
|
-
observedValue,
|
|
1614
|
-
operator: config.operator,
|
|
1615
|
-
threshold: config.threshold,
|
|
1616
|
-
unit: config.unit
|
|
1617
|
-
}
|
|
1618
|
-
};
|
|
2002
|
+
});
|
|
1619
2003
|
}
|
|
1620
2004
|
async function evaluateReferenceCheckCounterContract(args) {
|
|
1621
|
-
const config = parseReferenceCheckCounterConfig(
|
|
2005
|
+
const config = parseReferenceCheckCounterConfig(
|
|
2006
|
+
args.contract.condition.evaluatorConfig
|
|
2007
|
+
);
|
|
1622
2008
|
const input = getEvaluatorInputRecord(args.inputData, "referenceCheckData");
|
|
1623
2009
|
const tag = typeof input.tag === "string" && input.tag.trim().length > 0 ? input.tag.trim() : config.tag;
|
|
1624
2010
|
const snapshot = await computeTaggedEvidenceCount({
|
|
@@ -1632,7 +2018,10 @@ async function evaluateReferenceCheckCounterContract(args) {
|
|
|
1632
2018
|
snapshot.count,
|
|
1633
2019
|
config.threshold
|
|
1634
2020
|
);
|
|
1635
|
-
const result = resolveComparisonResult(
|
|
2021
|
+
const result = resolveComparisonResult(
|
|
2022
|
+
args.contract.direction,
|
|
2023
|
+
comparisonSatisfied
|
|
2024
|
+
);
|
|
1636
2025
|
return {
|
|
1637
2026
|
result,
|
|
1638
2027
|
rationale: buildComparisonRationale({
|
|
@@ -1654,130 +2043,167 @@ async function evaluateReferenceCheckCounterContract(args) {
|
|
|
1654
2043
|
}
|
|
1655
2044
|
};
|
|
1656
2045
|
}
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
"temporal_deadline requires contract.deadline to be set to a finite timestamp."
|
|
1661
|
-
);
|
|
1662
|
-
}
|
|
1663
|
-
const config = parseTemporalDeadlineConfig(args.contract.condition.evaluatorConfig);
|
|
1664
|
-
const input = getEvaluatorInputRecord(args.inputData, "temporalData");
|
|
1665
|
-
const label = (typeof input.label === "string" && input.label.length > 0 ? input.label : config.label) ?? args.contract.title ?? args.contract.condition.expression;
|
|
1666
|
-
const completedAt = pickFiniteNumber(input, [
|
|
1667
|
-
"completedAt",
|
|
1668
|
-
"observedAt",
|
|
1669
|
-
"satisfiedAt",
|
|
1670
|
-
"achievedAt"
|
|
1671
|
-
]) ?? config.completedAt ?? config.observedAt ?? config.satisfiedAt ?? config.achievedAt;
|
|
1672
|
-
const completed = input.completed === true || config.completed === true || completedAt !== void 0;
|
|
1673
|
-
if (completed) {
|
|
1674
|
-
if (completedAt !== void 0 && completedAt > args.contract.deadline) {
|
|
1675
|
-
return {
|
|
1676
|
-
result: "expired",
|
|
1677
|
-
rationale: `${label} completed at ${completedAt}, after deadline ${args.contract.deadline}.`,
|
|
1678
|
-
data: {
|
|
1679
|
-
label,
|
|
1680
|
-
deadline: args.contract.deadline,
|
|
1681
|
-
completed: true,
|
|
1682
|
-
completedAt,
|
|
1683
|
-
missedDeadline: true,
|
|
1684
|
-
overdueByMs: completedAt - args.contract.deadline
|
|
1685
|
-
}
|
|
1686
|
-
};
|
|
1687
|
-
}
|
|
1688
|
-
const result = args.contract.direction === "falsifies" ? "disconfirmed" : "confirmed";
|
|
2046
|
+
function resolveCompletedTemporalDeadlineResult(args) {
|
|
2047
|
+
const { completedAt, context, deadline, label } = args;
|
|
2048
|
+
if (completedAt !== void 0 && completedAt > deadline) {
|
|
1689
2049
|
return {
|
|
1690
|
-
result,
|
|
1691
|
-
rationale: `${label} completed
|
|
2050
|
+
result: "expired",
|
|
2051
|
+
rationale: `${label} completed at ${completedAt}, after deadline ${deadline}.`,
|
|
1692
2052
|
data: {
|
|
1693
2053
|
label,
|
|
1694
|
-
deadline
|
|
2054
|
+
deadline,
|
|
1695
2055
|
completed: true,
|
|
1696
|
-
completedAt
|
|
1697
|
-
missedDeadline:
|
|
2056
|
+
completedAt,
|
|
2057
|
+
missedDeadline: true,
|
|
2058
|
+
overdueByMs: completedAt - deadline
|
|
1698
2059
|
}
|
|
1699
2060
|
};
|
|
1700
2061
|
}
|
|
1701
|
-
|
|
2062
|
+
const result = context.contract.direction === "falsifies" ? "disconfirmed" : "confirmed";
|
|
2063
|
+
return {
|
|
2064
|
+
result,
|
|
2065
|
+
rationale: `${label} completed before deadline ${deadline}.`,
|
|
2066
|
+
data: {
|
|
2067
|
+
label,
|
|
2068
|
+
deadline,
|
|
2069
|
+
completed: true,
|
|
2070
|
+
completedAt: completedAt ?? null,
|
|
2071
|
+
missedDeadline: false
|
|
2072
|
+
}
|
|
2073
|
+
};
|
|
2074
|
+
}
|
|
2075
|
+
function resolveOpenTemporalDeadlineResult(args) {
|
|
2076
|
+
const { context, deadline, label } = args;
|
|
2077
|
+
if (context.now > deadline) {
|
|
1702
2078
|
return {
|
|
1703
2079
|
result: "expired",
|
|
1704
|
-
rationale: `${label} missed deadline ${
|
|
2080
|
+
rationale: `${label} missed deadline ${deadline}; temporal contract expired.`,
|
|
1705
2081
|
data: {
|
|
1706
2082
|
label,
|
|
1707
|
-
deadline
|
|
2083
|
+
deadline,
|
|
1708
2084
|
completed: false,
|
|
1709
|
-
overdueByMs:
|
|
2085
|
+
overdueByMs: context.now - deadline
|
|
1710
2086
|
}
|
|
1711
2087
|
};
|
|
1712
2088
|
}
|
|
1713
2089
|
return {
|
|
1714
2090
|
result: "inconclusive",
|
|
1715
|
-
rationale: `${label} is still before deadline ${
|
|
2091
|
+
rationale: `${label} is still before deadline ${deadline}; awaiting outcome.`,
|
|
1716
2092
|
data: {
|
|
1717
2093
|
label,
|
|
1718
|
-
deadline
|
|
2094
|
+
deadline,
|
|
1719
2095
|
completed: false,
|
|
1720
|
-
timeRemainingMs:
|
|
2096
|
+
timeRemainingMs: deadline - context.now
|
|
1721
2097
|
}
|
|
1722
2098
|
};
|
|
1723
2099
|
}
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
2100
|
+
function evaluateTemporalDeadlineContract(args) {
|
|
2101
|
+
return Promise.resolve().then(() => {
|
|
2102
|
+
if (typeof args.contract.deadline !== "number" || !Number.isFinite(args.contract.deadline)) {
|
|
2103
|
+
throw new Error(
|
|
2104
|
+
"temporal_deadline requires contract.deadline to be set to a finite timestamp."
|
|
2105
|
+
);
|
|
2106
|
+
}
|
|
2107
|
+
const deadline = args.contract.deadline;
|
|
2108
|
+
const config = parseTemporalDeadlineConfig(
|
|
2109
|
+
args.contract.condition.evaluatorConfig
|
|
2110
|
+
);
|
|
2111
|
+
const input = getEvaluatorInputRecord(args.inputData, "temporalData");
|
|
2112
|
+
const label = (typeof input.label === "string" && input.label.length > 0 ? input.label : config.label) ?? args.contract.title ?? args.contract.condition.expression;
|
|
2113
|
+
const completedAt = pickFiniteNumber(input, [
|
|
2114
|
+
"completedAt",
|
|
2115
|
+
"observedAt",
|
|
2116
|
+
"satisfiedAt",
|
|
2117
|
+
"achievedAt"
|
|
2118
|
+
]) ?? config.completedAt ?? config.observedAt ?? config.satisfiedAt ?? config.achievedAt;
|
|
2119
|
+
const completed = input.completed === true || config.completed === true || completedAt !== void 0;
|
|
2120
|
+
if (completed) {
|
|
2121
|
+
return resolveCompletedTemporalDeadlineResult({
|
|
2122
|
+
completedAt,
|
|
2123
|
+
context: args,
|
|
2124
|
+
deadline,
|
|
2125
|
+
label
|
|
2126
|
+
});
|
|
2127
|
+
}
|
|
2128
|
+
return resolveOpenTemporalDeadlineResult({
|
|
2129
|
+
context: args,
|
|
2130
|
+
deadline,
|
|
2131
|
+
label
|
|
2132
|
+
});
|
|
2133
|
+
});
|
|
2134
|
+
}
|
|
2135
|
+
function evaluateMarketIndexComparatorContract(args) {
|
|
2136
|
+
return Promise.resolve().then(() => {
|
|
2137
|
+
const config = parseMarketIndexComparatorConfig(
|
|
2138
|
+
args.contract.condition.evaluatorConfig
|
|
2139
|
+
);
|
|
2140
|
+
const input = getEvaluatorInputRecord(args.inputData, "marketIndexData");
|
|
2141
|
+
const subject = typeof input.subject === "string" && input.subject.length > 0 ? input.subject : config.subject;
|
|
2142
|
+
const benchmark = typeof input.benchmark === "string" && input.benchmark.length > 0 ? input.benchmark : config.benchmark;
|
|
2143
|
+
const subjectValue = pickFiniteNumber(input, ["subjectValue", "primaryValue", "leftValue"]) ?? config.subjectValue ?? config.primaryValue ?? null;
|
|
2144
|
+
const benchmarkValue = pickFiniteNumber(input, [
|
|
2145
|
+
"benchmarkValue",
|
|
2146
|
+
"comparisonValue",
|
|
2147
|
+
"rightValue"
|
|
2148
|
+
]) ?? config.benchmarkValue ?? config.comparisonValue ?? null;
|
|
2149
|
+
if (subjectValue === null || benchmarkValue === null) {
|
|
2150
|
+
return {
|
|
2151
|
+
result: "inconclusive",
|
|
2152
|
+
rationale: "market_index_comparator is awaiting both subject and benchmark values.",
|
|
2153
|
+
data: {
|
|
2154
|
+
subject,
|
|
2155
|
+
subjectValue,
|
|
2156
|
+
benchmark,
|
|
2157
|
+
benchmarkValue,
|
|
2158
|
+
operator: config.operator,
|
|
2159
|
+
threshold: config.threshold
|
|
2160
|
+
}
|
|
2161
|
+
};
|
|
2162
|
+
}
|
|
2163
|
+
if (benchmarkValue === 0) {
|
|
2164
|
+
throw new Error(
|
|
2165
|
+
"market_index_comparator cannot compare against a zero benchmark value."
|
|
2166
|
+
);
|
|
2167
|
+
}
|
|
2168
|
+
const differentialPercent = (subjectValue - benchmarkValue) / Math.abs(benchmarkValue) * 100;
|
|
2169
|
+
const comparisonSatisfied = compareMetricValue(
|
|
2170
|
+
config.operator,
|
|
2171
|
+
differentialPercent,
|
|
2172
|
+
config.threshold
|
|
2173
|
+
);
|
|
2174
|
+
const result = resolveComparisonResult(
|
|
2175
|
+
args.contract.direction,
|
|
2176
|
+
comparisonSatisfied
|
|
2177
|
+
);
|
|
1732
2178
|
return {
|
|
1733
|
-
result
|
|
1734
|
-
rationale:
|
|
2179
|
+
result,
|
|
2180
|
+
rationale: buildComparisonRationale({
|
|
2181
|
+
label: `${subject ?? "subject"} vs ${benchmark ?? "benchmark"} differential`,
|
|
2182
|
+
observedValue: differentialPercent,
|
|
2183
|
+
operator: config.operator,
|
|
2184
|
+
threshold: config.threshold,
|
|
2185
|
+
comparisonSatisfied,
|
|
2186
|
+
result,
|
|
2187
|
+
unit: "%"
|
|
2188
|
+
}),
|
|
1735
2189
|
data: {
|
|
1736
2190
|
subject,
|
|
1737
2191
|
subjectValue,
|
|
1738
2192
|
benchmark,
|
|
1739
2193
|
benchmarkValue,
|
|
2194
|
+
differentialPercent,
|
|
1740
2195
|
operator: config.operator,
|
|
1741
2196
|
threshold: config.threshold
|
|
1742
2197
|
}
|
|
1743
2198
|
};
|
|
1744
|
-
}
|
|
1745
|
-
if (benchmarkValue === 0) {
|
|
1746
|
-
throw new Error(
|
|
1747
|
-
"market_index_comparator cannot compare against a zero benchmark value."
|
|
1748
|
-
);
|
|
1749
|
-
}
|
|
1750
|
-
const differentialPercent = (subjectValue - benchmarkValue) / Math.abs(benchmarkValue) * 100;
|
|
1751
|
-
const comparisonSatisfied = compareMetricValue(
|
|
1752
|
-
config.operator,
|
|
1753
|
-
differentialPercent,
|
|
1754
|
-
config.threshold
|
|
1755
|
-
);
|
|
1756
|
-
const result = resolveComparisonResult(args.contract.direction, comparisonSatisfied);
|
|
1757
|
-
return {
|
|
1758
|
-
result,
|
|
1759
|
-
rationale: buildComparisonRationale({
|
|
1760
|
-
label: `${subject ?? "subject"} vs ${benchmark ?? "benchmark"} differential`,
|
|
1761
|
-
observedValue: differentialPercent,
|
|
1762
|
-
operator: config.operator,
|
|
1763
|
-
threshold: config.threshold,
|
|
1764
|
-
comparisonSatisfied,
|
|
1765
|
-
result,
|
|
1766
|
-
unit: "%"
|
|
1767
|
-
}),
|
|
1768
|
-
data: {
|
|
1769
|
-
subject,
|
|
1770
|
-
subjectValue,
|
|
1771
|
-
benchmark,
|
|
1772
|
-
benchmarkValue,
|
|
1773
|
-
differentialPercent,
|
|
1774
|
-
operator: config.operator,
|
|
1775
|
-
threshold: config.threshold
|
|
1776
|
-
}
|
|
1777
|
-
};
|
|
2199
|
+
});
|
|
1778
2200
|
}
|
|
1779
2201
|
var METRIC_COMPARATOR_EVALUATOR_NAMES = {
|
|
1780
|
-
evidentialAliases: /* @__PURE__ */ new Set([
|
|
2202
|
+
evidentialAliases: /* @__PURE__ */ new Set([
|
|
2203
|
+
"evidential",
|
|
2204
|
+
"built_in_evidential",
|
|
2205
|
+
"builtin_evidential"
|
|
2206
|
+
]),
|
|
1781
2207
|
metricChecker: "metric_checker",
|
|
1782
2208
|
referenceCheckCounter: "reference_check_counter",
|
|
1783
2209
|
temporalDeadline: "temporal_deadline",
|
|
@@ -1785,6 +2211,8 @@ var METRIC_COMPARATOR_EVALUATOR_NAMES = {
|
|
|
1785
2211
|
};
|
|
1786
2212
|
|
|
1787
2213
|
// src/evaluators/shared.ts
|
|
2214
|
+
var WINDOWS_PATH_SEPARATORS = /\\/g;
|
|
2215
|
+
var LEADING_DOT_SLASH = /^\.\//;
|
|
1788
2216
|
function asArray(value) {
|
|
1789
2217
|
return Array.isArray(value) ? value : [];
|
|
1790
2218
|
}
|
|
@@ -1826,7 +2254,7 @@ function extractTextCandidates(value) {
|
|
|
1826
2254
|
return Array.from(new Set(candidates));
|
|
1827
2255
|
}
|
|
1828
2256
|
function normalizeFilePath(value) {
|
|
1829
|
-
return value.replace(
|
|
2257
|
+
return value.replace(WINDOWS_PATH_SEPARATORS, "/").replace(LEADING_DOT_SLASH, "");
|
|
1830
2258
|
}
|
|
1831
2259
|
function normalizeToolResultEnvelope(value) {
|
|
1832
2260
|
const record = asRecord(value);
|
|
@@ -1880,7 +2308,7 @@ function somePatternMatches(filePath, patterns) {
|
|
|
1880
2308
|
return patterns.some((pattern) => patternMatchesPath(filePath, pattern));
|
|
1881
2309
|
}
|
|
1882
2310
|
|
|
1883
|
-
// src/evaluators/
|
|
2311
|
+
// src/evaluators/lint-checker-evaluator.ts
|
|
1884
2312
|
function parseConfig(condition) {
|
|
1885
2313
|
const record = asRecord(condition.evaluatorConfig);
|
|
1886
2314
|
if (!record) {
|
|
@@ -1952,7 +2380,10 @@ var lintCheckerEvaluator = {
|
|
|
1952
2380
|
}
|
|
1953
2381
|
const envelope = normalizeToolResultEnvelope(args.resultData);
|
|
1954
2382
|
const exitCode = asNumber(envelope.exitCode);
|
|
1955
|
-
const matchedDiagnostics = getMatchedDiagnostics(
|
|
2383
|
+
const matchedDiagnostics = getMatchedDiagnostics(
|
|
2384
|
+
args.contract,
|
|
2385
|
+
args.resultData
|
|
2386
|
+
);
|
|
1956
2387
|
if (matchedDiagnostics.length === 0 && exitCode !== 0 && exitCode !== null) {
|
|
1957
2388
|
return {
|
|
1958
2389
|
result: "inconclusive",
|
|
@@ -1978,7 +2409,7 @@ var lintCheckerEvaluator = {
|
|
|
1978
2409
|
}
|
|
1979
2410
|
};
|
|
1980
2411
|
|
|
1981
|
-
// src/evaluators/
|
|
2412
|
+
// src/evaluators/sentry-checker-evaluator.ts
|
|
1982
2413
|
function parseConfig2(condition) {
|
|
1983
2414
|
const record = asRecord(condition.evaluatorConfig);
|
|
1984
2415
|
if (!record) {
|
|
@@ -2063,7 +2494,7 @@ var sentryCheckerEvaluator = {
|
|
|
2063
2494
|
}
|
|
2064
2495
|
};
|
|
2065
2496
|
|
|
2066
|
-
// src/evaluators/
|
|
2497
|
+
// src/evaluators/test-runner-evaluator.ts
|
|
2067
2498
|
function parseConfig3(condition) {
|
|
2068
2499
|
const record = asRecord(condition.evaluatorConfig);
|
|
2069
2500
|
if (!record) {
|
|
@@ -2209,7 +2640,7 @@ var testRunnerEvaluator = {
|
|
|
2209
2640
|
}
|
|
2210
2641
|
};
|
|
2211
2642
|
|
|
2212
|
-
// src/evaluators/
|
|
2643
|
+
// src/evaluators/tsc-checker-evaluator.ts
|
|
2213
2644
|
function parseConfig4(condition) {
|
|
2214
2645
|
const record = asRecord(condition.evaluatorConfig);
|
|
2215
2646
|
if (!record) {
|
|
@@ -2294,7 +2725,10 @@ var tscCheckerEvaluator = {
|
|
|
2294
2725
|
}
|
|
2295
2726
|
const envelope = normalizeToolResultEnvelope(args.resultData);
|
|
2296
2727
|
const exitCode = asNumber(envelope.exitCode);
|
|
2297
|
-
const matchedDiagnostics = getMatchedDiagnostics2(
|
|
2728
|
+
const matchedDiagnostics = getMatchedDiagnostics2(
|
|
2729
|
+
args.contract,
|
|
2730
|
+
args.resultData
|
|
2731
|
+
);
|
|
2298
2732
|
if (matchedDiagnostics.length === 0 && exitCode !== 0 && exitCode !== null) {
|
|
2299
2733
|
return {
|
|
2300
2734
|
result: "inconclusive",
|
|
@@ -2338,6 +2772,18 @@ var BUILT_IN_REFERENCE_CHECK_COUNTER2 = METRIC_COMPARATOR_EVALUATOR_NAMES.refere
|
|
|
2338
2772
|
var BUILT_IN_TEMPORAL_DEADLINE2 = METRIC_COMPARATOR_EVALUATOR_NAMES.temporalDeadline;
|
|
2339
2773
|
var BUILT_IN_MARKET_INDEX_COMPARATOR2 = METRIC_COMPARATOR_EVALUATOR_NAMES.marketIndexComparator;
|
|
2340
2774
|
var MAX_CONTRACT_EVALUATION_BATCH_SIZE = 50;
|
|
2775
|
+
function confidenceSeed(args) {
|
|
2776
|
+
if (typeof args.currentConfidence === "number") {
|
|
2777
|
+
return args.currentConfidence;
|
|
2778
|
+
}
|
|
2779
|
+
if (typeof args.beliefConfidence === "number") {
|
|
2780
|
+
return args.beliefConfidence;
|
|
2781
|
+
}
|
|
2782
|
+
return 0.5;
|
|
2783
|
+
}
|
|
2784
|
+
function contractDocId(contract) {
|
|
2785
|
+
return contract._id;
|
|
2786
|
+
}
|
|
2341
2787
|
function clearEpistemicEvaluators() {
|
|
2342
2788
|
evaluatorRegistry.clear();
|
|
2343
2789
|
ensureBuiltInEvaluators();
|
|
@@ -2430,7 +2876,10 @@ async function executeContractEvaluation(args) {
|
|
|
2430
2876
|
rationale: `No epistemic evaluator registered for "${args.contract.condition.evaluator}".`
|
|
2431
2877
|
};
|
|
2432
2878
|
}
|
|
2433
|
-
const confidenceBefore =
|
|
2879
|
+
const confidenceBefore = confidenceSeed({
|
|
2880
|
+
beliefConfidence: args.belief.confidence,
|
|
2881
|
+
currentConfidence: args.currentConfidence
|
|
2882
|
+
});
|
|
2434
2883
|
const modulationPlan = deriveContractModulationPlan({
|
|
2435
2884
|
currentConfidence: confidenceBefore,
|
|
2436
2885
|
modulation: args.contract.modulation,
|
|
@@ -2470,16 +2919,16 @@ async function executeContractEvaluation(args) {
|
|
|
2470
2919
|
modulationRationale: evaluation.rationale,
|
|
2471
2920
|
topicId: args.contract.topicId
|
|
2472
2921
|
});
|
|
2473
|
-
const nextStatus = deriveContractStatus(
|
|
2474
|
-
|
|
2475
|
-
args.contract.
|
|
2476
|
-
{
|
|
2477
|
-
status: nextStatus,
|
|
2478
|
-
lastEvaluatedAt: args.now,
|
|
2479
|
-
evaluationCount: (args.contract.evaluationCount ?? 0) + 1,
|
|
2480
|
-
updatedAt: args.now
|
|
2481
|
-
}
|
|
2922
|
+
const nextStatus = deriveContractStatus(
|
|
2923
|
+
evaluation.result,
|
|
2924
|
+
args.contract.status
|
|
2482
2925
|
);
|
|
2926
|
+
await args.ctx.db.patch(contractDocId(args.contract), {
|
|
2927
|
+
status: nextStatus,
|
|
2928
|
+
lastEvaluatedAt: args.now,
|
|
2929
|
+
evaluationCount: (args.contract.evaluationCount ?? 0) + 1,
|
|
2930
|
+
updatedAt: args.now
|
|
2931
|
+
});
|
|
2483
2932
|
return {
|
|
2484
2933
|
evaluationId,
|
|
2485
2934
|
result: evaluation.result,
|
|
@@ -2564,7 +3013,8 @@ async function evaluateContractsForTriggerBatch(args) {
|
|
|
2564
3013
|
};
|
|
2565
3014
|
}
|
|
2566
3015
|
async function loadContractsForBelief(args) {
|
|
2567
|
-
|
|
3016
|
+
const rows = await args.ctx.db.query("epistemicContracts").withIndex("by_belief", (q) => q.eq("beliefNodeId", args.beliefNodeId)).collect();
|
|
3017
|
+
return rows;
|
|
2568
3018
|
}
|
|
2569
3019
|
async function loadContractsForTrigger(args) {
|
|
2570
3020
|
const contracts = await loadContractsForBelief(args);
|