@lucern/graph-primitives 1.0.16 → 1.0.18
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/beliefEvidenceLinks.js +144 -99
- package/dist/beliefEvidenceLinks.js.map +1 -1
- package/dist/beliefEvidenceLinks.operational.d.ts +29 -0
- package/dist/beliefEvidenceLinks.operational.js +157 -0
- package/dist/beliefEvidenceLinks.operational.js.map +1 -0
- package/dist/{beliefLifecycle-y8WLXqQj.d.ts → beliefLifecycle-CXwdDw5e.d.ts} +7 -4
- package/dist/beliefLifecycle.d.ts +1 -1
- package/dist/beliefLifecycle.js +75 -18
- package/dist/beliefLifecycle.js.map +1 -1
- package/dist/entityLifecycle.js +1 -12
- package/dist/entityLifecycle.js.map +1 -1
- package/dist/epistemicAnswers.js +1 -12
- package/dist/epistemicAnswers.js.map +1 -1
- package/dist/epistemicBeliefs.admin.js.map +1 -1
- package/dist/epistemicBeliefs.backfills.d.ts +1 -1
- package/dist/epistemicBeliefs.backfills.js +63 -35
- package/dist/epistemicBeliefs.backfills.js.map +1 -1
- package/dist/epistemicBeliefs.confidence.d.ts +1 -1
- package/dist/epistemicBeliefs.confidence.js +70 -41
- package/dist/epistemicBeliefs.confidence.js.map +1 -1
- package/dist/epistemicBeliefs.core.js +946 -566
- package/dist/epistemicBeliefs.core.js.map +1 -1
- package/dist/epistemicBeliefs.d.ts +2 -2
- package/dist/epistemicBeliefs.forkEvidence.d.ts +18 -0
- package/dist/epistemicBeliefs.forkEvidence.js +121 -0
- package/dist/epistemicBeliefs.forkEvidence.js.map +1 -0
- package/dist/epistemicBeliefs.helpers.d.ts +2 -2
- package/dist/epistemicBeliefs.helpers.js +60 -32
- package/dist/epistemicBeliefs.helpers.js.map +1 -1
- package/dist/epistemicBeliefs.internal.js +175 -51
- package/dist/epistemicBeliefs.internal.js.map +1 -1
- package/dist/epistemicBeliefs.js +437 -84
- package/dist/epistemicBeliefs.js.map +1 -1
- package/dist/epistemicBeliefs.lifecycle.d.ts +2 -2
- package/dist/epistemicBeliefs.lifecycle.js +75 -47
- package/dist/epistemicBeliefs.lifecycle.js.map +1 -1
- package/dist/epistemicBeliefs.links.js +47 -13
- package/dist/epistemicBeliefs.links.js.map +1 -1
- package/dist/epistemicBeliefs.topicAnchor.d.ts +29 -0
- package/dist/epistemicBeliefs.topicAnchor.js +105 -0
- package/dist/epistemicBeliefs.topicAnchor.js.map +1 -0
- package/dist/epistemicContracts.evaluators.js +71 -42
- package/dist/epistemicContracts.evaluators.js.map +1 -1
- package/dist/epistemicContracts.handlers.js +72 -54
- package/dist/epistemicContracts.handlers.js.map +1 -1
- package/dist/epistemicContracts.js +72 -54
- package/dist/epistemicContracts.js.map +1 -1
- package/dist/epistemicContracts.metrics.js +1 -1
- package/dist/epistemicContracts.metrics.js.map +1 -1
- package/dist/epistemicContracts.types.d.ts +1 -1
- package/dist/epistemicEdgeCreation.js +1 -12
- package/dist/epistemicEdgeCreation.js.map +1 -1
- package/dist/epistemicEdges.helpers.d.ts +1 -1
- package/dist/epistemicEvidence.js +173 -93
- package/dist/epistemicEvidence.js.map +1 -1
- package/dist/epistemicEvidenceMutations.js +173 -93
- package/dist/epistemicEvidenceMutations.js.map +1 -1
- package/dist/epistemicHelpers.js +1 -12
- package/dist/epistemicHelpers.js.map +1 -1
- package/dist/epistemicNodeCreation.js +1 -10
- package/dist/epistemicNodeCreation.js.map +1 -1
- package/dist/epistemicNodes.internal.js.map +1 -1
- package/dist/epistemicNodes.js +2 -2
- package/dist/epistemicNodes.js.map +1 -1
- package/dist/epistemicNodes.mutations.js +2 -2
- package/dist/epistemicNodes.mutations.js.map +1 -1
- package/dist/epistemicQuestions.create.js +1 -12
- package/dist/epistemicQuestions.create.js.map +1 -1
- package/dist/epistemicQuestions.evidence.js +1 -12
- package/dist/epistemicQuestions.evidence.js.map +1 -1
- package/dist/epistemicQuestions.js +1 -12
- package/dist/epistemicQuestions.js.map +1 -1
- package/dist/epistemicQuestions.tail.js +1 -12
- package/dist/epistemicQuestions.tail.js.map +1 -1
- package/dist/epistemicSources.js +1 -12
- package/dist/epistemicSources.js.map +1 -1
- package/dist/evaluators/index.js +1 -1
- package/dist/evaluators/index.js.map +1 -1
- package/dist/globalId-4y9SPpC_.d.ts +10 -0
- package/dist/globalId.d.ts +1 -1
- package/dist/globalId.js +1 -13
- package/dist/globalId.js.map +1 -1
- package/dist/helpers.js +1 -12
- package/dist/helpers.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.js +771 -247
- package/dist/index.js.map +1 -1
- package/dist/invariantEnforcement.js +2 -2
- package/dist/invariantEnforcement.js.map +1 -1
- package/dist/proof-attestation.json +3 -3
- package/package.json +4 -4
- package/dist/globalId-DKh9d_uD.d.ts +0 -20
package/dist/index.js
CHANGED
|
@@ -7,6 +7,7 @@ import { componentsGeneric, anyApi, internalMutationGeneric, mutationGeneric, qu
|
|
|
7
7
|
import { isNodeType, getLayerForNodeType } from '@lucern/contracts/schema-helpers/spine/tables/epistemicNodes';
|
|
8
8
|
import { permissiveReturn } from '@lucern/contracts/schema-helpers/validators';
|
|
9
9
|
import { assertSchemaEnumValue } from '@lucern/contracts/schema-helpers/enumValidation';
|
|
10
|
+
import { generateGlobalId, isUuidV7, generateUuidV7 } from '@lucern/contracts/ids';
|
|
10
11
|
import { listAudienceRegistryRows } from '@lucern/access-control/audienceRegistry';
|
|
11
12
|
import { scoreEntityTypeMatch, scoreEntityConnection, rankEntityTypeMatches, rankEntityConnections } from '@lucern/contracts/v1/ontologies/v1';
|
|
12
13
|
import { wordTokenize, wordOverlapScore, tokenizeSearchText, tokenOverlapScore, stemToken, scoreLexicalSignals, scoreLexicalSignal, rerankLexicalWindow, rankWindowScore, prepareLexicalQuery, jaccardSimilarity, bigramTokenize } from '@lucern/contracts/text-matching.contract';
|
|
@@ -689,6 +690,7 @@ __export(beliefLifecycle_exports, {
|
|
|
689
690
|
isPreValidationBeliefStatus: () => isPreValidationBeliefStatus,
|
|
690
691
|
isPropagationEligibleBeliefStatus: () => isPropagationEligibleBeliefStatus,
|
|
691
692
|
isResolvedByConfidence: () => isResolvedByConfidence,
|
|
693
|
+
promoteBeliefStatusAfterEvidence: () => promoteBeliefStatusAfterEvidence,
|
|
692
694
|
promoteBeliefStatusAfterScoring: () => promoteBeliefStatusAfterScoring,
|
|
693
695
|
resolveBeliefLifecycleStatus: () => resolveBeliefLifecycleStatus,
|
|
694
696
|
shouldTreatBeliefAsFact: () => shouldTreatBeliefAsFact
|
|
@@ -696,8 +698,10 @@ __export(beliefLifecycle_exports, {
|
|
|
696
698
|
var BELIEF_STATUS_VALUES = [
|
|
697
699
|
"assumption",
|
|
698
700
|
"hypothesis",
|
|
699
|
-
"
|
|
700
|
-
"
|
|
701
|
+
"active",
|
|
702
|
+
"superseded",
|
|
703
|
+
"resolved_true",
|
|
704
|
+
"resolved_false"
|
|
701
705
|
];
|
|
702
706
|
var RESOLVED_PREDICTION_OUTCOMES = [
|
|
703
707
|
"confirmed",
|
|
@@ -708,6 +712,24 @@ var RESOLVED_PREDICTION_OUTCOMES = [
|
|
|
708
712
|
function isBeliefLifecycleStatus(value) {
|
|
709
713
|
return typeof value === "string" && BELIEF_STATUS_VALUES.includes(value);
|
|
710
714
|
}
|
|
715
|
+
function normalizeLegacyBeliefStatus(value) {
|
|
716
|
+
if (isBeliefLifecycleStatus(value)) {
|
|
717
|
+
return value;
|
|
718
|
+
}
|
|
719
|
+
if (value === "belief" || value === "established" || value === "emerging") {
|
|
720
|
+
return "active";
|
|
721
|
+
}
|
|
722
|
+
if (value === "fact" || value === "confirmed") {
|
|
723
|
+
return "resolved_true";
|
|
724
|
+
}
|
|
725
|
+
if (value === "disconfirmed" || value === "expired") {
|
|
726
|
+
return "resolved_false";
|
|
727
|
+
}
|
|
728
|
+
if (value === "deprecated") {
|
|
729
|
+
return "superseded";
|
|
730
|
+
}
|
|
731
|
+
return null;
|
|
732
|
+
}
|
|
711
733
|
function normalizeBeliefConfidence(confidence) {
|
|
712
734
|
if (typeof confidence !== "number" || !Number.isFinite(confidence)) {
|
|
713
735
|
return null;
|
|
@@ -749,25 +771,58 @@ function shouldTreatBeliefAsFact(opts) {
|
|
|
749
771
|
}
|
|
750
772
|
return false;
|
|
751
773
|
}
|
|
774
|
+
function resolvedPredictionStatus(predictionMeta) {
|
|
775
|
+
if (!predictionMeta || typeof predictionMeta !== "object") {
|
|
776
|
+
return null;
|
|
777
|
+
}
|
|
778
|
+
const outcome = predictionMeta.outcome;
|
|
779
|
+
if (outcome === "confirmed") {
|
|
780
|
+
return "resolved_true";
|
|
781
|
+
}
|
|
782
|
+
if (outcome === "disconfirmed" || outcome === "expired") {
|
|
783
|
+
return "resolved_false";
|
|
784
|
+
}
|
|
785
|
+
return null;
|
|
786
|
+
}
|
|
787
|
+
function shouldTreatBeliefAsResolved(opts) {
|
|
788
|
+
if (isResolvedByConfidence(opts.confidence)) {
|
|
789
|
+
const normalized = normalizeBeliefConfidence(opts.confidence);
|
|
790
|
+
return normalized === 0 ? "resolved_false" : "resolved_true";
|
|
791
|
+
}
|
|
792
|
+
const directPredictionStatus = resolvedPredictionStatus(opts.predictionMeta);
|
|
793
|
+
if (directPredictionStatus) {
|
|
794
|
+
return directPredictionStatus;
|
|
795
|
+
}
|
|
796
|
+
const metadataPredictionStatus = resolvedPredictionStatus(
|
|
797
|
+
getPredictionMetaFromMetadata(opts.metadata)
|
|
798
|
+
);
|
|
799
|
+
if (metadataPredictionStatus) {
|
|
800
|
+
return metadataPredictionStatus;
|
|
801
|
+
}
|
|
802
|
+
return null;
|
|
803
|
+
}
|
|
752
804
|
function resolveBeliefLifecycleStatus(opts) {
|
|
753
|
-
|
|
754
|
-
|
|
805
|
+
const resolvedStatus = shouldTreatBeliefAsResolved(opts);
|
|
806
|
+
if (resolvedStatus) {
|
|
807
|
+
return resolvedStatus;
|
|
755
808
|
}
|
|
756
809
|
const direct = opts.beliefStatus;
|
|
757
|
-
|
|
810
|
+
const normalizedDirect = normalizeLegacyBeliefStatus(direct);
|
|
811
|
+
if (normalizedDirect) {
|
|
758
812
|
const normalized = normalizeBeliefConfidence(opts.confidence);
|
|
759
|
-
if (normalized !== null && isPreValidationBeliefStatus(
|
|
760
|
-
return "
|
|
813
|
+
if (normalized !== null && isPreValidationBeliefStatus(normalizedDirect)) {
|
|
814
|
+
return "active";
|
|
761
815
|
}
|
|
762
|
-
return
|
|
816
|
+
return normalizedDirect;
|
|
763
817
|
}
|
|
764
818
|
const metaStatus = opts.metadata?.beliefStatus;
|
|
765
|
-
|
|
819
|
+
const normalizedMetaStatus = normalizeLegacyBeliefStatus(metaStatus);
|
|
820
|
+
if (normalizedMetaStatus) {
|
|
766
821
|
const normalized = normalizeBeliefConfidence(opts.confidence);
|
|
767
|
-
if (normalized !== null && isPreValidationBeliefStatus(
|
|
768
|
-
return "
|
|
822
|
+
if (normalized !== null && isPreValidationBeliefStatus(normalizedMetaStatus)) {
|
|
823
|
+
return "active";
|
|
769
824
|
}
|
|
770
|
-
return
|
|
825
|
+
return normalizedMetaStatus;
|
|
771
826
|
}
|
|
772
827
|
return "assumption";
|
|
773
828
|
}
|
|
@@ -775,16 +830,20 @@ function isPreValidationBeliefStatus(status) {
|
|
|
775
830
|
return status === "assumption" || status === "hypothesis";
|
|
776
831
|
}
|
|
777
832
|
function isPropagationEligibleBeliefStatus(status) {
|
|
778
|
-
return status === "
|
|
833
|
+
return status === "active" || status === "resolved_true";
|
|
779
834
|
}
|
|
780
835
|
function promoteBeliefStatusAfterScoring(status, opts) {
|
|
781
|
-
|
|
782
|
-
|
|
836
|
+
const resolvedStatus = shouldTreatBeliefAsResolved({ ...opts });
|
|
837
|
+
if (resolvedStatus) {
|
|
838
|
+
return resolvedStatus;
|
|
783
839
|
}
|
|
784
840
|
if (isPreValidationBeliefStatus(status)) {
|
|
785
|
-
return "
|
|
841
|
+
return "active";
|
|
786
842
|
}
|
|
787
|
-
return status
|
|
843
|
+
return status;
|
|
844
|
+
}
|
|
845
|
+
function promoteBeliefStatusAfterEvidence(status) {
|
|
846
|
+
return isPreValidationBeliefStatus(status) ? "active" : status;
|
|
788
847
|
}
|
|
789
848
|
var api = anyApi;
|
|
790
849
|
componentsGeneric();
|
|
@@ -1607,7 +1666,7 @@ function buildBeliefConfidenceRow(args) {
|
|
|
1607
1666
|
disbelief: args.disbelief,
|
|
1608
1667
|
uncertainty: args.uncertainty,
|
|
1609
1668
|
baseRate: args.baseRate,
|
|
1610
|
-
slOperator: args.slOperator ?? "
|
|
1669
|
+
slOperator: args.slOperator ?? "prior_seed",
|
|
1611
1670
|
trigger: args.trigger,
|
|
1612
1671
|
...args.rationale ? { rationale: args.rationale } : {},
|
|
1613
1672
|
assessedBy: args.assessedBy,
|
|
@@ -2061,17 +2120,17 @@ async function applyBeliefConfidenceChange(ctx, args) {
|
|
|
2061
2120
|
status: 404,
|
|
2062
2121
|
code: "NOT_FOUND",
|
|
2063
2122
|
invariantCode: "belief.exists",
|
|
2064
|
-
suggestion: "Verify nodeId points to an existing node before
|
|
2123
|
+
suggestion: "Verify nodeId points to an existing node before appending SL scoring.",
|
|
2065
2124
|
details: { nodeId: args.nodeId }
|
|
2066
2125
|
});
|
|
2067
2126
|
}
|
|
2068
2127
|
if (node.nodeType !== "belief") {
|
|
2069
2128
|
throwStructuredMutationError({
|
|
2070
|
-
message: `
|
|
2129
|
+
message: `appendSlScoring only applies to belief nodes. Received nodeType "${node.nodeType}". Entity nodes (company, person, investor, etc.) do not have confidence \u2014 use entityLifecycle.updateEntityAttributes for mutable entity data.`,
|
|
2071
2130
|
status: 400,
|
|
2072
2131
|
code: "INVALID_ARGUMENT",
|
|
2073
2132
|
invariantCode: "entity.no_confidence",
|
|
2074
|
-
suggestion: "Use entityLifecycle.updateEntityAttributes for entity mutations.
|
|
2133
|
+
suggestion: "Use entityLifecycle.updateEntityAttributes for entity mutations. appendSlScoring is for belief nodes only.",
|
|
2075
2134
|
details: { nodeId: args.nodeId, nodeType: node.nodeType }
|
|
2076
2135
|
});
|
|
2077
2136
|
}
|
|
@@ -2081,7 +2140,7 @@ async function applyBeliefConfidenceChange(ctx, args) {
|
|
|
2081
2140
|
status: 400,
|
|
2082
2141
|
code: "MISSING_SCOPE",
|
|
2083
2142
|
invariantCode: "belief.project_required",
|
|
2084
|
-
suggestion: "Belief must have a projectId
|
|
2143
|
+
suggestion: "Belief must have a projectId before SL scoring can be appended.",
|
|
2085
2144
|
details: { nodeId: args.nodeId }
|
|
2086
2145
|
});
|
|
2087
2146
|
}
|
|
@@ -2104,7 +2163,7 @@ async function applyBeliefConfidenceChange(ctx, args) {
|
|
|
2104
2163
|
status: 409,
|
|
2105
2164
|
code: "CONFLICT",
|
|
2106
2165
|
invariantCode: "belief.confidence_append_only",
|
|
2107
|
-
suggestion: "Complete a worktree linked to this belief before recording
|
|
2166
|
+
suggestion: "Complete a worktree linked to this belief before recording SL scoring.",
|
|
2108
2167
|
details: { nodeId: args.nodeId }
|
|
2109
2168
|
});
|
|
2110
2169
|
}
|
|
@@ -2359,6 +2418,199 @@ var propagateConfidenceChange = internalMutation({
|
|
|
2359
2418
|
}
|
|
2360
2419
|
});
|
|
2361
2420
|
|
|
2421
|
+
// src/epistemicBeliefs.forkEvidence.ts
|
|
2422
|
+
function normalizeForkTriggerRelation(value) {
|
|
2423
|
+
if (value === "supports" || value === "supporting") {
|
|
2424
|
+
return "supports";
|
|
2425
|
+
}
|
|
2426
|
+
if (value === "contradicts" || value === "contradicting") {
|
|
2427
|
+
return "contradicts";
|
|
2428
|
+
}
|
|
2429
|
+
return null;
|
|
2430
|
+
}
|
|
2431
|
+
async function resolveForkTriggerEvidence(ctx, args) {
|
|
2432
|
+
const evidence = await ctx.db.get(args.triggeringEvidenceId);
|
|
2433
|
+
if (!evidence || evidence.nodeType !== "evidence") {
|
|
2434
|
+
throwStructuredMutationError({
|
|
2435
|
+
message: "Fork requires an existing evidence node.",
|
|
2436
|
+
status: 400,
|
|
2437
|
+
code: "INVALID_ARGUMENT",
|
|
2438
|
+
invariantCode: "belief.fork_requires_evidence",
|
|
2439
|
+
suggestion: "Create or link evidence first, then fork with triggeringEvidenceId.",
|
|
2440
|
+
details: { triggeringEvidenceId: args.triggeringEvidenceId }
|
|
2441
|
+
});
|
|
2442
|
+
}
|
|
2443
|
+
if (evidence.topicId && evidence.topicId !== args.parent.topicId) {
|
|
2444
|
+
throwStructuredMutationError({
|
|
2445
|
+
message: "Fork evidence belongs to a different topic scope.",
|
|
2446
|
+
status: 400,
|
|
2447
|
+
code: "INVALID_ARGUMENT",
|
|
2448
|
+
invariantCode: "belief.fork_evidence_scope",
|
|
2449
|
+
suggestion: "Use evidence from the same topic/workspace scope as the parent belief.",
|
|
2450
|
+
details: {
|
|
2451
|
+
parentNodeId: args.parentNodeId,
|
|
2452
|
+
triggeringEvidenceId: args.triggeringEvidenceId
|
|
2453
|
+
}
|
|
2454
|
+
});
|
|
2455
|
+
}
|
|
2456
|
+
const evidenceMetadata = evidence.metadata && typeof evidence.metadata === "object" ? evidence.metadata : {};
|
|
2457
|
+
const parentRefs = new Set(
|
|
2458
|
+
[
|
|
2459
|
+
String(args.parentNodeId),
|
|
2460
|
+
String(args.parent.globalId ?? ""),
|
|
2461
|
+
String(args.parent._id)
|
|
2462
|
+
].filter(Boolean)
|
|
2463
|
+
);
|
|
2464
|
+
const evidenceRefs = new Set(
|
|
2465
|
+
[
|
|
2466
|
+
String(args.triggeringEvidenceId),
|
|
2467
|
+
String(evidence.globalId ?? ""),
|
|
2468
|
+
String(evidence._id)
|
|
2469
|
+
].filter(Boolean)
|
|
2470
|
+
);
|
|
2471
|
+
let relation = null;
|
|
2472
|
+
const linkedBeliefNodeId = String(
|
|
2473
|
+
evidenceMetadata.linkedBeliefNodeId ?? ""
|
|
2474
|
+
);
|
|
2475
|
+
if (linkedBeliefNodeId && parentRefs.has(linkedBeliefNodeId)) {
|
|
2476
|
+
relation = normalizeForkTriggerRelation(evidenceMetadata.evidenceRelation);
|
|
2477
|
+
}
|
|
2478
|
+
if (!relation) {
|
|
2479
|
+
for (const parentRef of parentRefs) {
|
|
2480
|
+
const links = await ctx.db.query("beliefEvidenceLinks").withIndex("by_beliefId", (q) => q.eq("beliefId", parentRef)).collect();
|
|
2481
|
+
const matched = links.find((link) => evidenceRefs.has(String(link.insightId)));
|
|
2482
|
+
if (matched) {
|
|
2483
|
+
relation = normalizeForkTriggerRelation(matched.relation);
|
|
2484
|
+
break;
|
|
2485
|
+
}
|
|
2486
|
+
}
|
|
2487
|
+
}
|
|
2488
|
+
if (!relation) {
|
|
2489
|
+
throwStructuredMutationError({
|
|
2490
|
+
message: "Fork evidence must already be attached to the parent belief through an SL evidence relation.",
|
|
2491
|
+
status: 409,
|
|
2492
|
+
code: "CONFLICT",
|
|
2493
|
+
invariantCode: "belief.fork_requires_attached_evidence",
|
|
2494
|
+
suggestion: "Attach the evidence to the parent belief as supports or contradicts before forking.",
|
|
2495
|
+
details: {
|
|
2496
|
+
parentNodeId: args.parentNodeId,
|
|
2497
|
+
triggeringEvidenceId: args.triggeringEvidenceId
|
|
2498
|
+
}
|
|
2499
|
+
});
|
|
2500
|
+
}
|
|
2501
|
+
if (args.forkMode === "supersede" && relation !== "contradicts") {
|
|
2502
|
+
throwStructuredMutationError({
|
|
2503
|
+
message: "Superseding fork requires contradicting evidence against the parent belief.",
|
|
2504
|
+
status: 409,
|
|
2505
|
+
code: "CONFLICT",
|
|
2506
|
+
invariantCode: "belief.supersede_requires_contradiction",
|
|
2507
|
+
suggestion: "Use forkMode='branch' for a non-replacing fork, or attach contradicting evidence before superseding.",
|
|
2508
|
+
details: {
|
|
2509
|
+
parentNodeId: args.parentNodeId,
|
|
2510
|
+
triggeringEvidenceId: args.triggeringEvidenceId,
|
|
2511
|
+
relation
|
|
2512
|
+
}
|
|
2513
|
+
});
|
|
2514
|
+
}
|
|
2515
|
+
return { evidenceNodeId: args.triggeringEvidenceId, relation };
|
|
2516
|
+
}
|
|
2517
|
+
|
|
2518
|
+
// src/epistemicBeliefs.topicAnchor.ts
|
|
2519
|
+
function cleanString(value) {
|
|
2520
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
2521
|
+
}
|
|
2522
|
+
function topicNodeCandidates(topicRef) {
|
|
2523
|
+
const normalized = topicRef.trim();
|
|
2524
|
+
if (!normalized) {
|
|
2525
|
+
return [];
|
|
2526
|
+
}
|
|
2527
|
+
const candidates = [normalized];
|
|
2528
|
+
if (normalized.startsWith("top_")) {
|
|
2529
|
+
candidates.push(normalized.slice(4));
|
|
2530
|
+
}
|
|
2531
|
+
return [...new Set(candidates)];
|
|
2532
|
+
}
|
|
2533
|
+
function readTopicNodeRef(args) {
|
|
2534
|
+
return cleanString(args.topicGlobalId) ?? cleanString(args.topicNodeId) ?? cleanString(args.topicId);
|
|
2535
|
+
}
|
|
2536
|
+
async function resolveRequiredTopicAnchor(ctx, topicRef) {
|
|
2537
|
+
for (const candidate of topicNodeCandidates(topicRef)) {
|
|
2538
|
+
try {
|
|
2539
|
+
const direct = await ctx.db.get(candidate);
|
|
2540
|
+
if (direct?.nodeType === "topic" && cleanString(direct.globalId)) {
|
|
2541
|
+
return direct;
|
|
2542
|
+
}
|
|
2543
|
+
} catch (_) {
|
|
2544
|
+
}
|
|
2545
|
+
const byGlobalId = await ctx.db.query("epistemicNodes").withIndex("by_globalId", (q) => q.eq("globalId", candidate)).first();
|
|
2546
|
+
if (byGlobalId?.nodeType === "topic" && cleanString(byGlobalId.globalId)) {
|
|
2547
|
+
return byGlobalId;
|
|
2548
|
+
}
|
|
2549
|
+
}
|
|
2550
|
+
throw new Error(
|
|
2551
|
+
"Belief creation requires topicGlobalId or topicNodeId for a topic node in epistemicNodes. Legacy topics-table IDs are not valid belief anchors."
|
|
2552
|
+
);
|
|
2553
|
+
}
|
|
2554
|
+
function scopeFromTopicAnchor(topicNode) {
|
|
2555
|
+
return {
|
|
2556
|
+
topicId: topicNode.globalId,
|
|
2557
|
+
projectId: cleanString(topicNode.projectId),
|
|
2558
|
+
tenantId: cleanString(topicNode.tenantId),
|
|
2559
|
+
workspaceId: cleanString(topicNode.workspaceId),
|
|
2560
|
+
source: "topic"
|
|
2561
|
+
};
|
|
2562
|
+
}
|
|
2563
|
+
async function createRequiredBeliefTopicEdge(ctx, args) {
|
|
2564
|
+
const topicGlobalId = args.topicNode.globalId;
|
|
2565
|
+
const edgeGlobalId = `edge:${args.beliefGlobalId}:${topicGlobalId}:scoped_by`;
|
|
2566
|
+
const now = Date.now();
|
|
2567
|
+
const existing = await ctx.db.query("epistemicEdges").withIndex("by_globalId", (q) => q.eq("globalId", edgeGlobalId)).first();
|
|
2568
|
+
if (!existing) {
|
|
2569
|
+
await ctx.db.insert("epistemicEdges", {
|
|
2570
|
+
globalId: edgeGlobalId,
|
|
2571
|
+
fromNodeId: String(args.beliefNodeId),
|
|
2572
|
+
toNodeId: String(args.topicNode._id),
|
|
2573
|
+
sourceGlobalId: args.beliefGlobalId,
|
|
2574
|
+
targetGlobalId: topicGlobalId,
|
|
2575
|
+
edgeType: "scoped_by",
|
|
2576
|
+
weight: 1,
|
|
2577
|
+
confidence: 1,
|
|
2578
|
+
context: "Belief creation topic anchor invariant.",
|
|
2579
|
+
reasoningMethod: "implicit",
|
|
2580
|
+
derivationType: "topic_scope_invariant",
|
|
2581
|
+
metadata: { invariant: "belief.topic_edge_required" },
|
|
2582
|
+
createdBy: args.createdBy,
|
|
2583
|
+
createdAt: now,
|
|
2584
|
+
updatedAt: now,
|
|
2585
|
+
projectId: cleanString(args.topicNode.projectId),
|
|
2586
|
+
topicId: topicGlobalId,
|
|
2587
|
+
tenantId: cleanString(args.topicNode.tenantId),
|
|
2588
|
+
workspaceId: cleanString(args.topicNode.workspaceId),
|
|
2589
|
+
fromNodeType: "belief",
|
|
2590
|
+
toNodeType: "topic",
|
|
2591
|
+
fromLayer: "L3",
|
|
2592
|
+
toLayer: args.topicNode.epistemicLayer ?? "ontological"
|
|
2593
|
+
});
|
|
2594
|
+
}
|
|
2595
|
+
await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {
|
|
2596
|
+
globalId: edgeGlobalId,
|
|
2597
|
+
fromGlobalId: args.beliefGlobalId,
|
|
2598
|
+
toGlobalId: topicGlobalId,
|
|
2599
|
+
edgeType: "scoped_by",
|
|
2600
|
+
weight: 1,
|
|
2601
|
+
confidence: 1,
|
|
2602
|
+
context: "Belief creation topic anchor invariant.",
|
|
2603
|
+
projectId: cleanString(args.topicNode.projectId),
|
|
2604
|
+
topicId: topicGlobalId,
|
|
2605
|
+
createdBy: args.createdBy,
|
|
2606
|
+
fromNodeType: "belief",
|
|
2607
|
+
toNodeType: "topic",
|
|
2608
|
+
fromLayer: "L3",
|
|
2609
|
+
toLayer: args.topicNode.epistemicLayer ?? "ontological",
|
|
2610
|
+
metadata: { invariant: "belief.topic_edge_required" }
|
|
2611
|
+
});
|
|
2612
|
+
}
|
|
2613
|
+
|
|
2362
2614
|
// src/embeddingTrigger.ts
|
|
2363
2615
|
async function scheduleEmbeddingGeneration(args) {
|
|
2364
2616
|
try {
|
|
@@ -2391,23 +2643,17 @@ async function scheduleEmbeddingGeneration(args) {
|
|
|
2391
2643
|
// src/globalId.ts
|
|
2392
2644
|
var globalId_exports = {};
|
|
2393
2645
|
__export(globalId_exports, {
|
|
2394
|
-
generateGlobalId: () => generateGlobalId
|
|
2646
|
+
generateGlobalId: () => generateGlobalId,
|
|
2647
|
+
generateUuidV7: () => generateUuidV7,
|
|
2648
|
+
isUuidV7: () => isUuidV7
|
|
2395
2649
|
});
|
|
2396
|
-
function generateGlobalId() {
|
|
2397
|
-
const bytes = new Uint8Array(16);
|
|
2398
|
-
crypto.getRandomValues(bytes);
|
|
2399
|
-
bytes[6] = bytes[6] & 15 | 64;
|
|
2400
|
-
bytes[8] = bytes[8] & 63 | 128;
|
|
2401
|
-
const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join(
|
|
2402
|
-
""
|
|
2403
|
-
);
|
|
2404
|
-
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
2405
|
-
}
|
|
2406
2650
|
|
|
2407
2651
|
// src/epistemicBeliefs.core.ts
|
|
2408
2652
|
var create = mutation({
|
|
2409
2653
|
args: {
|
|
2410
2654
|
...optionalBeliefScopeArgs,
|
|
2655
|
+
topicNodeId: v.optional(v.string()),
|
|
2656
|
+
topicGlobalId: v.optional(v.string()),
|
|
2411
2657
|
formulation: v.string(),
|
|
2412
2658
|
beliefType: v.optional(v.string()),
|
|
2413
2659
|
rationale: v.optional(v.string()),
|
|
@@ -2452,20 +2698,32 @@ var create = mutation({
|
|
|
2452
2698
|
returns: permissiveReturn,
|
|
2453
2699
|
handler: async (ctx, args) => {
|
|
2454
2700
|
const authenticatedUserId = await requireAuthenticatedUserId(ctx);
|
|
2455
|
-
const
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2701
|
+
const topicRef = readTopicNodeRef(args);
|
|
2702
|
+
if (!topicRef) {
|
|
2703
|
+
throwStructuredMutationError({
|
|
2704
|
+
message: "Belief creation requires an explicit topic epistemic node.",
|
|
2705
|
+
status: 400,
|
|
2706
|
+
code: "INVALID_ARGUMENT",
|
|
2707
|
+
invariantCode: "belief.topic_node_required",
|
|
2708
|
+
suggestion: "Pass topicGlobalId or topicNodeId for a topic in epistemicNodes before creating a belief.",
|
|
2709
|
+
details: {
|
|
2710
|
+
topicId: args.topicId,
|
|
2711
|
+
topicNodeId: args.topicNodeId,
|
|
2712
|
+
topicGlobalId: args.topicGlobalId
|
|
2713
|
+
}
|
|
2714
|
+
});
|
|
2715
|
+
}
|
|
2716
|
+
const topicNode = await resolveRequiredTopicAnchor(ctx, topicRef);
|
|
2717
|
+
const scope = scopeFromTopicAnchor(topicNode);
|
|
2459
2718
|
assertWorkspaceScopedEpistemicNodeScope({
|
|
2460
2719
|
scope,
|
|
2461
2720
|
nodeType: "belief",
|
|
2462
2721
|
mutationName: "epistemicBeliefs.create"
|
|
2463
2722
|
});
|
|
2464
|
-
const topic = await ctx.db.get(scope.topicId);
|
|
2465
2723
|
const normalizedBeliefType = await assertSchemaEnumValue(ctx, {
|
|
2466
2724
|
category: "belief_type",
|
|
2467
2725
|
value: args.beliefType,
|
|
2468
|
-
tenantId:
|
|
2726
|
+
tenantId: scope.tenantId,
|
|
2469
2727
|
context: "epistemicBeliefs.create"
|
|
2470
2728
|
});
|
|
2471
2729
|
if (scope.projectId) {
|
|
@@ -2498,7 +2756,7 @@ var create = mutation({
|
|
|
2498
2756
|
title: args.formulation.slice(0, 100) + (args.formulation.length > 100 ? "..." : ""),
|
|
2499
2757
|
metadata: {
|
|
2500
2758
|
pillar,
|
|
2501
|
-
// No confidenceLevel — only set after
|
|
2759
|
+
// No confidenceLevel — only set after evidence-backed SL scoring.
|
|
2502
2760
|
status: "active",
|
|
2503
2761
|
worktreeId: args.worktreeId,
|
|
2504
2762
|
beliefStatus: initialBeliefStatus,
|
|
@@ -2542,9 +2800,15 @@ var create = mutation({
|
|
|
2542
2800
|
rationale: "LKC-2 mandatory prior: seeded vacuous opinion at belief creation.",
|
|
2543
2801
|
assessedBy: authenticatedUserId,
|
|
2544
2802
|
assessedAt: now,
|
|
2545
|
-
slOperator: "
|
|
2803
|
+
slOperator: "prior_seed"
|
|
2546
2804
|
})
|
|
2547
2805
|
);
|
|
2806
|
+
await createRequiredBeliefTopicEdge(ctx, {
|
|
2807
|
+
beliefNodeId: nodeId,
|
|
2808
|
+
beliefGlobalId,
|
|
2809
|
+
topicNode,
|
|
2810
|
+
createdBy: authenticatedUserId
|
|
2811
|
+
});
|
|
2548
2812
|
await ctx.scheduler.runAfter(0, internal.neo4jSync.syncNodeToNeo4j, {
|
|
2549
2813
|
nodeId,
|
|
2550
2814
|
operation: "upsert"
|
|
@@ -2881,9 +3145,10 @@ var forkBelief = mutation({
|
|
|
2881
3145
|
v.literal("refinement"),
|
|
2882
3146
|
v.literal("contradiction_response"),
|
|
2883
3147
|
v.literal("scope_change"),
|
|
2884
|
-
v.literal("confidence_collapse")
|
|
2885
|
-
v.literal("manual")
|
|
3148
|
+
v.literal("confidence_collapse")
|
|
2886
3149
|
),
|
|
3150
|
+
forkMode: v.optional(v.union(v.literal("supersede"), v.literal("branch"))),
|
|
3151
|
+
triggeringEvidenceId: v.id("epistemicNodes"),
|
|
2887
3152
|
rationale: v.optional(v.string()),
|
|
2888
3153
|
userId: v.string()
|
|
2889
3154
|
},
|
|
@@ -2926,6 +3191,33 @@ var forkBelief = mutation({
|
|
|
2926
3191
|
await requireProjectWriteAccess(ctx, parent.projectId, authenticatedUserId);
|
|
2927
3192
|
const metadata = parent.metadata;
|
|
2928
3193
|
const forkBeliefStatus = "hypothesis";
|
|
3194
|
+
const forkMode = args.forkMode ?? "supersede";
|
|
3195
|
+
const triggerEvidence = await resolveForkTriggerEvidence(ctx, {
|
|
3196
|
+
parentNodeId: args.parentNodeId,
|
|
3197
|
+
parent,
|
|
3198
|
+
triggeringEvidenceId: args.triggeringEvidenceId,
|
|
3199
|
+
forkMode
|
|
3200
|
+
});
|
|
3201
|
+
const parentLifecycleStatus = resolveBeliefLifecycleStatus({
|
|
3202
|
+
beliefStatus: parent.beliefStatus,
|
|
3203
|
+
confidence: parent.confidence,
|
|
3204
|
+
predictionMeta: parent.predictionMeta,
|
|
3205
|
+
metadata
|
|
3206
|
+
});
|
|
3207
|
+
if (forkMode === "supersede" && parentLifecycleStatus !== "active") {
|
|
3208
|
+
throwStructuredMutationError({
|
|
3209
|
+
message: "Superseding fork requires an active parent belief. Attach evidence first so the lifecycle can promote deterministically.",
|
|
3210
|
+
status: 409,
|
|
3211
|
+
code: "CONFLICT",
|
|
3212
|
+
invariantCode: "belief.supersede_requires_active_parent",
|
|
3213
|
+
suggestion: "Attach the contradicting evidence to the parent belief, let the evidence path promote it to active, then supersede.",
|
|
3214
|
+
details: {
|
|
3215
|
+
parentNodeId: args.parentNodeId,
|
|
3216
|
+
parentLifecycleStatus,
|
|
3217
|
+
triggeringEvidenceId: args.triggeringEvidenceId
|
|
3218
|
+
}
|
|
3219
|
+
});
|
|
3220
|
+
}
|
|
2929
3221
|
const newBeliefGlobalId = generateGlobalId();
|
|
2930
3222
|
const newNodeId = await ctx.db.insert("epistemicNodes", {
|
|
2931
3223
|
globalId: newBeliefGlobalId,
|
|
@@ -2939,6 +3231,9 @@ var forkBelief = mutation({
|
|
|
2939
3231
|
...metadata,
|
|
2940
3232
|
forkedFrom: args.parentNodeId,
|
|
2941
3233
|
forkReason: args.forkReason,
|
|
3234
|
+
forkMode,
|
|
3235
|
+
triggeringEvidenceId: args.triggeringEvidenceId,
|
|
3236
|
+
triggeringEvidenceRelation: triggerEvidence.relation,
|
|
2942
3237
|
forkTimestamp: now,
|
|
2943
3238
|
forkedBy: authenticatedUserId,
|
|
2944
3239
|
status: "active",
|
|
@@ -2957,6 +3252,27 @@ var forkBelief = mutation({
|
|
|
2957
3252
|
createdAt: now,
|
|
2958
3253
|
updatedAt: now
|
|
2959
3254
|
});
|
|
3255
|
+
if (forkMode === "supersede") {
|
|
3256
|
+
await ctx.db.patch(args.parentNodeId, {
|
|
3257
|
+
status: "superseded",
|
|
3258
|
+
beliefStatus: "superseded",
|
|
3259
|
+
epistemicStatus: "superseded",
|
|
3260
|
+
supersededBy: newNodeId,
|
|
3261
|
+
updatedAt: now,
|
|
3262
|
+
metadata: {
|
|
3263
|
+
...metadata ?? {},
|
|
3264
|
+
status: "superseded",
|
|
3265
|
+
beliefStatus: "superseded",
|
|
3266
|
+
epistemicStatus: "superseded",
|
|
3267
|
+
supersededBy: String(newNodeId),
|
|
3268
|
+
supersededByEvidenceId: String(triggerEvidence.evidenceNodeId)
|
|
3269
|
+
}
|
|
3270
|
+
});
|
|
3271
|
+
await ctx.scheduler.runAfter(0, internal.neo4jSync.syncNodeToNeo4j, {
|
|
3272
|
+
nodeId: args.parentNodeId,
|
|
3273
|
+
operation: "upsert"
|
|
3274
|
+
});
|
|
3275
|
+
}
|
|
2960
3276
|
const inheritedContracts = await ctx.db.query("epistemicContracts").withIndex(
|
|
2961
3277
|
"by_belief",
|
|
2962
3278
|
(q) => q.eq("beliefNodeId", args.parentNodeId)
|
|
@@ -2983,12 +3299,17 @@ var forkBelief = mutation({
|
|
|
2983
3299
|
globalId: generateGlobalId(),
|
|
2984
3300
|
fromGlobalId: newBeliefGlobalId,
|
|
2985
3301
|
toGlobalId: parent.globalId,
|
|
2986
|
-
edgeType: "supersedes",
|
|
2987
|
-
context: `Fork reason: ${args.forkReason}`,
|
|
3302
|
+
edgeType: forkMode === "supersede" ? "supersedes" : "derived_from",
|
|
3303
|
+
context: `Fork reason: ${args.forkReason}; triggering evidence: ${triggerEvidence.evidenceNodeId}`,
|
|
2988
3304
|
createdBy: authenticatedUserId,
|
|
2989
3305
|
topicId: parent.projectId ? String(parent.projectId) : void 0,
|
|
2990
3306
|
fromNodeType: "belief",
|
|
2991
|
-
toNodeType: "belief"
|
|
3307
|
+
toNodeType: "belief",
|
|
3308
|
+
metadata: {
|
|
3309
|
+
forkMode,
|
|
3310
|
+
triggeringEvidenceId: String(triggerEvidence.evidenceNodeId),
|
|
3311
|
+
triggeringEvidenceRelation: triggerEvidence.relation
|
|
3312
|
+
}
|
|
2992
3313
|
});
|
|
2993
3314
|
await scheduleEmbeddingGeneration({
|
|
2994
3315
|
ctx,
|
|
@@ -3013,6 +3334,9 @@ var forkBelief = mutation({
|
|
|
3013
3334
|
newState: {
|
|
3014
3335
|
formulation: args.newFormulation,
|
|
3015
3336
|
forkReason: args.forkReason,
|
|
3337
|
+
forkMode,
|
|
3338
|
+
triggeringEvidenceId: String(triggerEvidence.evidenceNodeId),
|
|
3339
|
+
triggeringEvidenceRelation: triggerEvidence.relation,
|
|
3016
3340
|
tupleContradicted: false
|
|
3017
3341
|
},
|
|
3018
3342
|
projectId: parent.projectId,
|
|
@@ -3047,10 +3371,17 @@ var forkBelief = mutation({
|
|
|
3047
3371
|
projectId: parent.projectId,
|
|
3048
3372
|
topicId: parent.topicId
|
|
3049
3373
|
});
|
|
3050
|
-
return {
|
|
3374
|
+
return {
|
|
3375
|
+
newNodeId,
|
|
3376
|
+
parentNodeId: args.parentNodeId,
|
|
3377
|
+
forkMode,
|
|
3378
|
+
forkReason: args.forkReason,
|
|
3379
|
+
triggeringEvidenceId: triggerEvidence.evidenceNodeId,
|
|
3380
|
+
triggeringEvidenceRelation: triggerEvidence.relation
|
|
3381
|
+
};
|
|
3051
3382
|
}
|
|
3052
3383
|
});
|
|
3053
|
-
var
|
|
3384
|
+
var appendSlScoring = mutation({
|
|
3054
3385
|
args: {
|
|
3055
3386
|
nodeId: v.id("epistemicNodes"),
|
|
3056
3387
|
// SL opinion — the ONLY confidence input (EK-7)
|
|
@@ -3067,8 +3398,6 @@ var modulateConfidence = mutation({
|
|
|
3067
3398
|
v.literal("evidence_removed"),
|
|
3068
3399
|
v.literal("contradiction_detected"),
|
|
3069
3400
|
v.literal("contradiction_resolved"),
|
|
3070
|
-
v.literal("manual"),
|
|
3071
|
-
v.literal("decay"),
|
|
3072
3401
|
v.literal("agent_assessment"),
|
|
3073
3402
|
v.literal("worktree_outcome"),
|
|
3074
3403
|
v.literal("worktree_completed"),
|
|
@@ -3080,7 +3409,7 @@ var modulateConfidence = mutation({
|
|
|
3080
3409
|
),
|
|
3081
3410
|
rationale: v.optional(v.string()),
|
|
3082
3411
|
userId: v.string(),
|
|
3083
|
-
// SL operator provenance (optional — defaults
|
|
3412
|
+
// SL operator provenance (optional — defaults inside the SL scorer)
|
|
3084
3413
|
slOperator: v.optional(
|
|
3085
3414
|
v.union(
|
|
3086
3415
|
v.literal("cumulative_fusion"),
|
|
@@ -3090,7 +3419,8 @@ var modulateConfidence = mutation({
|
|
|
3090
3419
|
v.literal("dependency_cascade"),
|
|
3091
3420
|
v.literal("negation"),
|
|
3092
3421
|
v.literal("constraint_fusion"),
|
|
3093
|
-
v.literal("
|
|
3422
|
+
v.literal("no_op"),
|
|
3423
|
+
v.literal("prior_seed")
|
|
3094
3424
|
)
|
|
3095
3425
|
),
|
|
3096
3426
|
triggeringEvidenceId: v.optional(v.id("epistemicNodes")),
|
|
@@ -3457,6 +3787,12 @@ async function getQuestionsAnsweredByEvidence(ctx, evidenceId) {
|
|
|
3457
3787
|
}
|
|
3458
3788
|
|
|
3459
3789
|
// src/epistemicBeliefs.links.ts
|
|
3790
|
+
function assertSignedImpactScore(value, context) {
|
|
3791
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value === 0 || value < -1 || value > 1) {
|
|
3792
|
+
throw new Error(`${context} requires explicit nonzero weight in [-1, 1]`);
|
|
3793
|
+
}
|
|
3794
|
+
return value;
|
|
3795
|
+
}
|
|
3460
3796
|
var updatePillar = mutation({
|
|
3461
3797
|
args: {
|
|
3462
3798
|
nodeId: v.id("epistemicNodes"),
|
|
@@ -3636,6 +3972,7 @@ var linkEvidence = mutation({
|
|
|
3636
3972
|
beliefNodeId: v.id("epistemicNodes"),
|
|
3637
3973
|
insightId: insightIdUnion,
|
|
3638
3974
|
type: v.union(v.literal("supporting"), v.literal("contradicting")),
|
|
3975
|
+
weight: v.number(),
|
|
3639
3976
|
rationale: v.optional(v.string()),
|
|
3640
3977
|
userId: v.string()
|
|
3641
3978
|
},
|
|
@@ -3659,16 +3996,54 @@ var linkEvidence = mutation({
|
|
|
3659
3996
|
}
|
|
3660
3997
|
const evidenceNodeId = insight._id;
|
|
3661
3998
|
const evidenceGlobalId = insight.globalId;
|
|
3999
|
+
const weight = assertSignedImpactScore(args.weight, "Evidence link");
|
|
4000
|
+
if (args.type === "supporting" && weight < 0) {
|
|
4001
|
+
throw new Error("Supporting evidence links require positive weight");
|
|
4002
|
+
}
|
|
4003
|
+
if (args.type === "contradicting" && weight > 0) {
|
|
4004
|
+
throw new Error("Contradicting evidence links require negative weight");
|
|
4005
|
+
}
|
|
4006
|
+
const confidence = Math.abs(weight);
|
|
3662
4007
|
const edgeType = "informs";
|
|
3663
|
-
const weight = args.type === "supporting" ? 1 : -1;
|
|
3664
4008
|
const logicalRole = evidenceNodeId ? await computeLogicalRole(ctx, evidenceNodeId, args.beliefNodeId) : "contributory";
|
|
3665
4009
|
const edgeGlobalId = generateGlobalId();
|
|
4010
|
+
await ctx.db.insert("epistemicEdges", {
|
|
4011
|
+
globalId: edgeGlobalId,
|
|
4012
|
+
fromNodeId: evidenceNodeId,
|
|
4013
|
+
toNodeId: args.beliefNodeId,
|
|
4014
|
+
sourceGlobalId: evidenceGlobalId,
|
|
4015
|
+
targetGlobalId: belief.globalId,
|
|
4016
|
+
edgeType,
|
|
4017
|
+
weight,
|
|
4018
|
+
confidence,
|
|
4019
|
+
context: args.rationale || `${args.type} evidence`,
|
|
4020
|
+
reasoningMethod: "testimonial",
|
|
4021
|
+
logicalRole,
|
|
4022
|
+
temporalClass: "structural",
|
|
4023
|
+
derivationType: "evidence_sl_scoring",
|
|
4024
|
+
metadata: {
|
|
4025
|
+
relation: args.type,
|
|
4026
|
+
confidence,
|
|
4027
|
+
impactScore: weight,
|
|
4028
|
+
invariant: "evidence.belief_impact_required"
|
|
4029
|
+
},
|
|
4030
|
+
createdBy: authenticatedUserId,
|
|
4031
|
+
createdAt: Date.now(),
|
|
4032
|
+
updatedAt: Date.now(),
|
|
4033
|
+
topicId: belief.topicId ? String(belief.topicId) : void 0,
|
|
4034
|
+
projectId: belief.projectId ? String(belief.projectId) : void 0,
|
|
4035
|
+
fromNodeType: "evidence",
|
|
4036
|
+
toNodeType: "belief",
|
|
4037
|
+
fromLayer: "L2",
|
|
4038
|
+
toLayer: "L3"
|
|
4039
|
+
});
|
|
3666
4040
|
await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {
|
|
3667
4041
|
globalId: edgeGlobalId,
|
|
3668
4042
|
fromGlobalId: evidenceGlobalId,
|
|
3669
4043
|
toGlobalId: belief.globalId,
|
|
3670
4044
|
edgeType,
|
|
3671
4045
|
weight,
|
|
4046
|
+
confidence,
|
|
3672
4047
|
context: args.rationale || `${args.type} evidence`,
|
|
3673
4048
|
createdBy: authenticatedUserId,
|
|
3674
4049
|
topicId: belief.projectId ? String(belief.projectId) : void 0,
|
|
@@ -4299,6 +4674,8 @@ var internalGetById = internalQuery({
|
|
|
4299
4674
|
var internalCreate = internalMutation({
|
|
4300
4675
|
args: {
|
|
4301
4676
|
...optionalBeliefScopeArgs,
|
|
4677
|
+
topicNodeId: v.optional(v.string()),
|
|
4678
|
+
topicGlobalId: v.optional(v.string()),
|
|
4302
4679
|
formulation: v.string(),
|
|
4303
4680
|
baseRate: v.optional(v.number()),
|
|
4304
4681
|
confidence: v.optional(
|
|
@@ -4337,10 +4714,14 @@ var internalCreate = internalMutation({
|
|
|
4337
4714
|
handler: async (ctx, args) => {
|
|
4338
4715
|
const now = Date.now();
|
|
4339
4716
|
const baseRate = assertBaseRateInRange(args.baseRate ?? 0.5);
|
|
4340
|
-
const
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
|
|
4717
|
+
const topicRef = readTopicNodeRef(args);
|
|
4718
|
+
if (!topicRef) {
|
|
4719
|
+
throw new Error(
|
|
4720
|
+
"Belief creation requires topicGlobalId or topicNodeId for a topic node in epistemicNodes."
|
|
4721
|
+
);
|
|
4722
|
+
}
|
|
4723
|
+
const topicNode = await resolveRequiredTopicAnchor(ctx, topicRef);
|
|
4724
|
+
const scope = scopeFromTopicAnchor(topicNode);
|
|
4344
4725
|
assertWorkspaceScopedEpistemicNodeScope({
|
|
4345
4726
|
scope,
|
|
4346
4727
|
nodeType: "belief",
|
|
@@ -4356,11 +4737,10 @@ var internalCreate = internalMutation({
|
|
|
4356
4737
|
},
|
|
4357
4738
|
mutationName: "epistemicBeliefs.internalCreate"
|
|
4358
4739
|
});
|
|
4359
|
-
const topic = await ctx.db.get(scope.topicId);
|
|
4360
4740
|
const normalizedBeliefType = await assertSchemaEnumValue(ctx, {
|
|
4361
4741
|
category: "belief_type",
|
|
4362
4742
|
value: args.beliefType,
|
|
4363
|
-
tenantId:
|
|
4743
|
+
tenantId: scope.tenantId,
|
|
4364
4744
|
context: "epistemicBeliefs.internalCreate"
|
|
4365
4745
|
});
|
|
4366
4746
|
const globalId = generateGlobalId();
|
|
@@ -4424,9 +4804,15 @@ var internalCreate = internalMutation({
|
|
|
4424
4804
|
rationale: "LKC-2 mandatory prior: seeded vacuous opinion at belief creation.",
|
|
4425
4805
|
assessedBy: args.userId,
|
|
4426
4806
|
assessedAt: now,
|
|
4427
|
-
slOperator: "
|
|
4807
|
+
slOperator: "prior_seed"
|
|
4428
4808
|
})
|
|
4429
4809
|
);
|
|
4810
|
+
await createRequiredBeliefTopicEdge(ctx, {
|
|
4811
|
+
beliefNodeId: nodeId,
|
|
4812
|
+
beliefGlobalId: globalId,
|
|
4813
|
+
topicNode,
|
|
4814
|
+
createdBy: args.userId
|
|
4815
|
+
});
|
|
4430
4816
|
await ctx.scheduler.runAfter(0, internal.neo4jSync.syncNodeToNeo4j, {
|
|
4431
4817
|
nodeId,
|
|
4432
4818
|
operation: "upsert"
|
|
@@ -4600,7 +4986,7 @@ var backfillSyntheticOpinionHistory = internalMutation({
|
|
|
4600
4986
|
rationale: "LK-6 backfill: synthesized t0 from node-level opinion fields (no prior beliefConfidence row found).",
|
|
4601
4987
|
assessedAt: readFiniteNumber(node.createdAt) ?? readFiniteNumber(node.updatedAt) ?? Date.now(),
|
|
4602
4988
|
assessedBy: "system:lk-6-backfill",
|
|
4603
|
-
slOperator: "
|
|
4989
|
+
slOperator: "prior_seed"
|
|
4604
4990
|
})
|
|
4605
4991
|
);
|
|
4606
4992
|
beliefsWithHistory.add(String(node._id));
|
|
@@ -4706,7 +5092,7 @@ var backfillMandatoryPriors = internalMutation({
|
|
|
4706
5092
|
rationale: "LKC-2 backfill: inserted missing initial vacuous opinion with neutral prior.",
|
|
4707
5093
|
assessedAt: readFiniteNumber(node.createdAt) ?? readFiniteNumber(node.updatedAt) ?? Date.now(),
|
|
4708
5094
|
assessedBy: "system:lkc-2-prior-backfill",
|
|
4709
|
-
slOperator: "
|
|
5095
|
+
slOperator: "prior_seed"
|
|
4710
5096
|
})
|
|
4711
5097
|
);
|
|
4712
5098
|
insertedInitialRows++;
|
|
@@ -4814,7 +5200,7 @@ var backfillScoredBeliefEdges = internalMutation({
|
|
|
4814
5200
|
const scoredBeliefs = allBeliefs.filter((belief) => {
|
|
4815
5201
|
const metadata = belief.metadata || {};
|
|
4816
5202
|
const lifecycle = resolveBeliefStatus(belief, metadata);
|
|
4817
|
-
return lifecycle === "
|
|
5203
|
+
return lifecycle === "active" || lifecycle === "resolved_true";
|
|
4818
5204
|
});
|
|
4819
5205
|
const themeNodes = await ctx.db.query("epistemicNodes").withIndex(
|
|
4820
5206
|
"by_topic",
|
|
@@ -6300,85 +6686,32 @@ async function resolveScopeSoft(ctx, args) {
|
|
|
6300
6686
|
...projectId ? { projectId } : {}
|
|
6301
6687
|
};
|
|
6302
6688
|
}
|
|
6303
|
-
|
|
6304
|
-
|
|
6305
|
-
|
|
6306
|
-
|
|
6307
|
-
|
|
6308
|
-
v.literal("dismissed")
|
|
6309
|
-
);
|
|
6310
|
-
var matcherMetadataValidator = v.object({
|
|
6311
|
-
surface: v.string(),
|
|
6312
|
-
matcherFamily: v.optional(v.string()),
|
|
6313
|
-
matcherKey: v.optional(v.string()),
|
|
6314
|
-
matcherVersion: v.optional(v.string()),
|
|
6315
|
-
reviewStatus: v.optional(
|
|
6316
|
-
v.union(
|
|
6317
|
-
v.literal("pending"),
|
|
6318
|
-
v.literal("accepted"),
|
|
6319
|
-
v.literal("rejected"),
|
|
6320
|
-
v.literal("auto_accepted"),
|
|
6321
|
-
v.literal("superseded")
|
|
6322
|
-
)
|
|
6323
|
-
),
|
|
6324
|
-
configSnapshot: v.optional(v.any()),
|
|
6325
|
-
signalSnapshot: v.optional(v.any()),
|
|
6326
|
-
outcomeMetadata: v.optional(v.any())
|
|
6327
|
-
});
|
|
6328
|
-
async function markProjectGraphDirty(ctx, projectId) {
|
|
6329
|
-
if (!projectId) {
|
|
6330
|
-
return;
|
|
6689
|
+
|
|
6690
|
+
// src/beliefEvidenceLinks.operational.ts
|
|
6691
|
+
function assertEvidenceImpact(args) {
|
|
6692
|
+
if (!Number.isFinite(args.weight) || args.weight === 0 || args.weight < -1 || args.weight > 1) {
|
|
6693
|
+
throw new Error("Belief evidence links require explicit nonzero weight in [-1, 1]");
|
|
6331
6694
|
}
|
|
6332
|
-
|
|
6333
|
-
|
|
6334
|
-
|
|
6335
|
-
|
|
6336
|
-
|
|
6337
|
-
}
|
|
6338
|
-
);
|
|
6339
|
-
await resolveGraphPrimitivesAppResolvers().patchProject(ctx, projectId, {
|
|
6340
|
-
lastActivityAt: Date.now()
|
|
6341
|
-
});
|
|
6342
|
-
}
|
|
6343
|
-
async function recordMatcherDecision(ctx, args) {
|
|
6344
|
-
if (!args.matcherMetadata) {
|
|
6345
|
-
return;
|
|
6695
|
+
if (args.relation === "supports" && args.weight < 0) {
|
|
6696
|
+
throw new Error("Supporting evidence links require positive weight");
|
|
6697
|
+
}
|
|
6698
|
+
if (args.relation === "contradicts" && args.weight > 0) {
|
|
6699
|
+
throw new Error("Contradicting evidence links require negative weight");
|
|
6346
6700
|
}
|
|
6347
|
-
await ctx.runMutation("matcherFeedback:recordDecision", {
|
|
6348
|
-
projectId: args.beliefNode.projectId,
|
|
6349
|
-
topicId: args.beliefNode.topicId,
|
|
6350
|
-
surface: args.matcherMetadata.surface,
|
|
6351
|
-
matcherFamily: args.matcherMetadata.matcherFamily,
|
|
6352
|
-
matcherKey: args.matcherMetadata.matcherKey,
|
|
6353
|
-
matcherVersion: args.matcherMetadata.matcherVersion,
|
|
6354
|
-
sourceEntityId: String(args.insightId),
|
|
6355
|
-
targetEntityId: String(args.beliefId),
|
|
6356
|
-
suggestionTable: "beliefEvidenceLinks",
|
|
6357
|
-
suggestionId: args.linkId,
|
|
6358
|
-
reviewStatus: deriveMatcherReviewStatus({
|
|
6359
|
-
explicitReviewStatus: args.matcherMetadata.reviewStatus,
|
|
6360
|
-
linkStatus: args.linkStatus
|
|
6361
|
-
}),
|
|
6362
|
-
reviewedBy: args.reviewedBy,
|
|
6363
|
-
decisionReason: args.decisionReason,
|
|
6364
|
-
configSnapshot: args.matcherMetadata.configSnapshot,
|
|
6365
|
-
signalSnapshot: args.matcherMetadata.signalSnapshot,
|
|
6366
|
-
outcomeMetadata: args.matcherMetadata.outcomeMetadata
|
|
6367
|
-
});
|
|
6368
6701
|
}
|
|
6369
6702
|
async function applyOperationalLinkEffects(ctx, args) {
|
|
6703
|
+
assertEvidenceImpact({ relation: args.relation, weight: args.weight });
|
|
6704
|
+
const confidence = Math.abs(args.weight);
|
|
6370
6705
|
const currentSupporting = args.beliefNode.supportingInsightIds ?? [];
|
|
6371
6706
|
const currentContradicting = args.beliefNode.contradictingInsightIds ?? [];
|
|
6372
|
-
if (args.relation === "supports") {
|
|
6373
|
-
|
|
6374
|
-
|
|
6375
|
-
|
|
6376
|
-
|
|
6377
|
-
|
|
6378
|
-
|
|
6379
|
-
|
|
6380
|
-
}
|
|
6381
|
-
} else if (!currentContradicting.includes(args.insightId)) {
|
|
6707
|
+
if (args.relation === "supports" && !currentSupporting.includes(args.insightId)) {
|
|
6708
|
+
await ctx.db.patch(args.beliefId, {
|
|
6709
|
+
supportingInsightIds: [...currentSupporting, args.insightId],
|
|
6710
|
+
contradictingInsightIds: currentContradicting.filter(
|
|
6711
|
+
(id) => id !== args.insightId
|
|
6712
|
+
)
|
|
6713
|
+
});
|
|
6714
|
+
} else if (args.relation === "contradicts" && !currentContradicting.includes(args.insightId)) {
|
|
6382
6715
|
await ctx.db.patch(args.beliefId, {
|
|
6383
6716
|
contradictingInsightIds: [...currentContradicting, args.insightId],
|
|
6384
6717
|
supportingInsightIds: currentSupporting.filter(
|
|
@@ -6389,7 +6722,7 @@ async function applyOperationalLinkEffects(ctx, args) {
|
|
|
6389
6722
|
try {
|
|
6390
6723
|
const beliefSpineNode = await ctx.db.get(args.beliefId);
|
|
6391
6724
|
const evidenceSpineNode = await ctx.db.get(args.insightId);
|
|
6392
|
-
if (beliefSpineNode
|
|
6725
|
+
if (beliefSpineNode?.nodeType === "belief" && evidenceSpineNode?.nodeType === "evidence") {
|
|
6393
6726
|
const existingEdges = await ctx.db.query("epistemicEdges").withIndex(
|
|
6394
6727
|
"by_from_to",
|
|
6395
6728
|
(q) => q.eq("fromNodeId", evidenceSpineNode._id).eq("toNodeId", beliefSpineNode._id)
|
|
@@ -6402,16 +6735,44 @@ async function applyOperationalLinkEffects(ctx, args) {
|
|
|
6402
6735
|
await ctx.db.delete(edge._id);
|
|
6403
6736
|
}
|
|
6404
6737
|
}
|
|
6405
|
-
const weight = args.relation === "supports" ? args.confidence ?? 0.7 : -(args.confidence ?? 0.7);
|
|
6406
6738
|
const globalId = `edge-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;
|
|
6739
|
+
const context = args.rationale || `Linked as ${args.relation}`;
|
|
6740
|
+
await ctx.db.insert("epistemicEdges", {
|
|
6741
|
+
globalId,
|
|
6742
|
+
fromNodeId: evidenceSpineNode._id,
|
|
6743
|
+
toNodeId: beliefSpineNode._id,
|
|
6744
|
+
sourceGlobalId: evidenceSpineNode.globalId,
|
|
6745
|
+
targetGlobalId: beliefSpineNode.globalId,
|
|
6746
|
+
edgeType: "informs",
|
|
6747
|
+
weight: args.weight,
|
|
6748
|
+
confidence,
|
|
6749
|
+
context,
|
|
6750
|
+
reasoningMethod: "testimonial",
|
|
6751
|
+
derivationType: "evidence_sl_scoring",
|
|
6752
|
+
metadata: {
|
|
6753
|
+
relation: args.relation,
|
|
6754
|
+
confidence,
|
|
6755
|
+
impactScore: args.weight,
|
|
6756
|
+
invariant: "evidence.belief_impact_required"
|
|
6757
|
+
},
|
|
6758
|
+
createdBy: args.createdBy,
|
|
6759
|
+
createdAt: Date.now(),
|
|
6760
|
+
updatedAt: Date.now(),
|
|
6761
|
+
projectId: args.beliefNode.projectId,
|
|
6762
|
+
topicId: args.beliefNode.topicId ? String(args.beliefNode.topicId) : void 0,
|
|
6763
|
+
fromNodeType: "evidence",
|
|
6764
|
+
toNodeType: "belief",
|
|
6765
|
+
fromLayer: "L2",
|
|
6766
|
+
toLayer: "L3"
|
|
6767
|
+
});
|
|
6407
6768
|
await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {
|
|
6408
6769
|
globalId,
|
|
6409
6770
|
fromGlobalId: evidenceSpineNode.globalId,
|
|
6410
6771
|
toGlobalId: beliefSpineNode.globalId,
|
|
6411
6772
|
edgeType: "informs",
|
|
6412
|
-
weight,
|
|
6413
|
-
confidence
|
|
6414
|
-
context
|
|
6773
|
+
weight: args.weight,
|
|
6774
|
+
confidence,
|
|
6775
|
+
context,
|
|
6415
6776
|
projectId: args.beliefNode.projectId ? String(args.beliefNode.projectId) : void 0,
|
|
6416
6777
|
createdBy: args.createdBy,
|
|
6417
6778
|
fromNodeType: "evidence",
|
|
@@ -6424,17 +6785,13 @@ async function applyOperationalLinkEffects(ctx, args) {
|
|
|
6424
6785
|
console.error("[EpistemicSpine] Failed to create informs edge:", e);
|
|
6425
6786
|
}
|
|
6426
6787
|
if (args.beliefNode.projectId) {
|
|
6427
|
-
await ctx.scheduler.runAfter(
|
|
6428
|
-
|
|
6429
|
-
|
|
6430
|
-
|
|
6431
|
-
|
|
6432
|
-
|
|
6433
|
-
|
|
6434
|
-
projectId: args.beliefNode.projectId,
|
|
6435
|
-
userId: args.createdBy
|
|
6436
|
-
}
|
|
6437
|
-
);
|
|
6788
|
+
await ctx.scheduler.runAfter(0, "verificationActions:deepVerifyEvidence", {
|
|
6789
|
+
insightId: args.insightId,
|
|
6790
|
+
targetType: "belief",
|
|
6791
|
+
targetId: args.beliefId,
|
|
6792
|
+
projectId: args.beliefNode.projectId,
|
|
6793
|
+
userId: args.createdBy
|
|
6794
|
+
});
|
|
6438
6795
|
}
|
|
6439
6796
|
}
|
|
6440
6797
|
async function removeOperationalLinkEffects(ctx, args) {
|
|
@@ -6459,7 +6816,7 @@ async function removeOperationalLinkEffects(ctx, args) {
|
|
|
6459
6816
|
try {
|
|
6460
6817
|
const beliefSpineNode = await ctx.db.get(args.beliefId);
|
|
6461
6818
|
const evidenceSpineNode = await ctx.db.get(args.insightId);
|
|
6462
|
-
if (beliefSpineNode
|
|
6819
|
+
if (beliefSpineNode?.nodeType === "belief" && evidenceSpineNode?.nodeType === "evidence") {
|
|
6463
6820
|
const edges2 = await ctx.db.query("epistemicEdges").withIndex(
|
|
6464
6821
|
"by_from_to",
|
|
6465
6822
|
(q) => q.eq("fromNodeId", evidenceSpineNode._id).eq("toNodeId", beliefSpineNode._id)
|
|
@@ -6477,11 +6834,80 @@ async function removeOperationalLinkEffects(ctx, args) {
|
|
|
6477
6834
|
console.error("[EpistemicSpine] Failed to remove informs edge:", e);
|
|
6478
6835
|
}
|
|
6479
6836
|
}
|
|
6837
|
+
|
|
6838
|
+
// src/beliefEvidenceLinks.ts
|
|
6839
|
+
var beliefIdUnion = v.id("epistemicNodes");
|
|
6840
|
+
var insightIdUnion2 = v.id("epistemicNodes");
|
|
6841
|
+
var suggestionStatusValidator = v.union(
|
|
6842
|
+
v.literal("suggested"),
|
|
6843
|
+
v.literal("approved"),
|
|
6844
|
+
v.literal("dismissed")
|
|
6845
|
+
);
|
|
6846
|
+
var matcherMetadataValidator = v.object({
|
|
6847
|
+
surface: v.string(),
|
|
6848
|
+
matcherFamily: v.optional(v.string()),
|
|
6849
|
+
matcherKey: v.optional(v.string()),
|
|
6850
|
+
matcherVersion: v.optional(v.string()),
|
|
6851
|
+
reviewStatus: v.optional(
|
|
6852
|
+
v.union(
|
|
6853
|
+
v.literal("pending"),
|
|
6854
|
+
v.literal("accepted"),
|
|
6855
|
+
v.literal("rejected"),
|
|
6856
|
+
v.literal("auto_accepted"),
|
|
6857
|
+
v.literal("superseded")
|
|
6858
|
+
)
|
|
6859
|
+
),
|
|
6860
|
+
configSnapshot: v.optional(v.any()),
|
|
6861
|
+
signalSnapshot: v.optional(v.any()),
|
|
6862
|
+
outcomeMetadata: v.optional(v.any())
|
|
6863
|
+
});
|
|
6864
|
+
async function markProjectGraphDirty(ctx, projectId) {
|
|
6865
|
+
if (!projectId) {
|
|
6866
|
+
return;
|
|
6867
|
+
}
|
|
6868
|
+
await ctx.scheduler.runAfter(
|
|
6869
|
+
0,
|
|
6870
|
+
internal.graphAnalysisCache.markCacheStaleInternal,
|
|
6871
|
+
{
|
|
6872
|
+
projectId
|
|
6873
|
+
}
|
|
6874
|
+
);
|
|
6875
|
+
await resolveGraphPrimitivesAppResolvers().patchProject(ctx, projectId, {
|
|
6876
|
+
lastActivityAt: Date.now()
|
|
6877
|
+
});
|
|
6878
|
+
}
|
|
6879
|
+
async function recordMatcherDecision(ctx, args) {
|
|
6880
|
+
if (!args.matcherMetadata) {
|
|
6881
|
+
return;
|
|
6882
|
+
}
|
|
6883
|
+
await ctx.runMutation("matcherFeedback:recordDecision", {
|
|
6884
|
+
projectId: args.beliefNode.projectId,
|
|
6885
|
+
topicId: args.beliefNode.topicId,
|
|
6886
|
+
surface: args.matcherMetadata.surface,
|
|
6887
|
+
matcherFamily: args.matcherMetadata.matcherFamily,
|
|
6888
|
+
matcherKey: args.matcherMetadata.matcherKey,
|
|
6889
|
+
matcherVersion: args.matcherMetadata.matcherVersion,
|
|
6890
|
+
sourceEntityId: String(args.insightId),
|
|
6891
|
+
targetEntityId: String(args.beliefId),
|
|
6892
|
+
suggestionTable: "beliefEvidenceLinks",
|
|
6893
|
+
suggestionId: args.linkId,
|
|
6894
|
+
reviewStatus: deriveMatcherReviewStatus({
|
|
6895
|
+
explicitReviewStatus: args.matcherMetadata.reviewStatus,
|
|
6896
|
+
linkStatus: args.linkStatus
|
|
6897
|
+
}),
|
|
6898
|
+
reviewedBy: args.reviewedBy,
|
|
6899
|
+
decisionReason: args.decisionReason,
|
|
6900
|
+
configSnapshot: args.matcherMetadata.configSnapshot,
|
|
6901
|
+
signalSnapshot: args.matcherMetadata.signalSnapshot,
|
|
6902
|
+
outcomeMetadata: args.matcherMetadata.outcomeMetadata
|
|
6903
|
+
});
|
|
6904
|
+
}
|
|
6480
6905
|
var create2 = mutation({
|
|
6481
6906
|
args: {
|
|
6482
6907
|
beliefId: beliefIdUnion,
|
|
6483
6908
|
insightId: insightIdUnion2,
|
|
6484
6909
|
relation: v.union(v.literal("supports"), v.literal("contradicts")),
|
|
6910
|
+
weight: v.number(),
|
|
6485
6911
|
confidence: v.optional(v.number()),
|
|
6486
6912
|
rationale: v.optional(v.string()),
|
|
6487
6913
|
status: v.optional(suggestionStatusValidator),
|
|
@@ -6500,6 +6926,16 @@ var create2 = mutation({
|
|
|
6500
6926
|
if (!insightNode) {
|
|
6501
6927
|
throw new Error("Evidence node not found");
|
|
6502
6928
|
}
|
|
6929
|
+
if (!Number.isFinite(args.weight) || args.weight === 0 || args.weight < -1 || args.weight > 1) {
|
|
6930
|
+
throw new Error("Belief evidence links require explicit nonzero weight in [-1, 1]");
|
|
6931
|
+
}
|
|
6932
|
+
if (args.relation === "supports" && args.weight < 0) {
|
|
6933
|
+
throw new Error("Supporting evidence links require positive weight");
|
|
6934
|
+
}
|
|
6935
|
+
if (args.relation === "contradicts" && args.weight > 0) {
|
|
6936
|
+
throw new Error("Contradicting evidence links require negative weight");
|
|
6937
|
+
}
|
|
6938
|
+
const relationConfidence = Math.abs(args.weight);
|
|
6503
6939
|
if (beliefNode.projectId) {
|
|
6504
6940
|
const hasAccess = await checkProjectAccess(
|
|
6505
6941
|
ctx,
|
|
@@ -6524,7 +6960,7 @@ var create2 = mutation({
|
|
|
6524
6960
|
);
|
|
6525
6961
|
await ctx.db.patch(duplicate._id, {
|
|
6526
6962
|
relation: args.relation,
|
|
6527
|
-
confidence:
|
|
6963
|
+
confidence: relationConfidence,
|
|
6528
6964
|
rationale: args.rationale,
|
|
6529
6965
|
status: nextStatus
|
|
6530
6966
|
});
|
|
@@ -6536,7 +6972,7 @@ var create2 = mutation({
|
|
|
6536
6972
|
beliefId: resolvedBeliefId,
|
|
6537
6973
|
insightId: resolvedInsightId,
|
|
6538
6974
|
relation: args.relation,
|
|
6539
|
-
|
|
6975
|
+
weight: args.weight,
|
|
6540
6976
|
rationale: args.rationale,
|
|
6541
6977
|
createdBy: args.createdBy
|
|
6542
6978
|
});
|
|
@@ -6552,15 +6988,12 @@ var create2 = mutation({
|
|
|
6552
6988
|
await markProjectGraphDirty(ctx, beliefNode.projectId);
|
|
6553
6989
|
return duplicate._id;
|
|
6554
6990
|
}
|
|
6555
|
-
if (args.confidence !== void 0 && (args.confidence < 0 || args.confidence > 1)) {
|
|
6556
|
-
throw new Error("Confidence must be between 0 and 1");
|
|
6557
|
-
}
|
|
6558
6991
|
const now = Date.now();
|
|
6559
6992
|
const linkId = await ctx.db.insert("beliefEvidenceLinks", {
|
|
6560
6993
|
beliefId: args.beliefId,
|
|
6561
6994
|
insightId: args.insightId,
|
|
6562
6995
|
relation: args.relation,
|
|
6563
|
-
confidence:
|
|
6996
|
+
confidence: relationConfidence,
|
|
6564
6997
|
rationale: args.rationale,
|
|
6565
6998
|
status: args.status,
|
|
6566
6999
|
createdBy: args.createdBy,
|
|
@@ -6580,7 +7013,7 @@ var create2 = mutation({
|
|
|
6580
7013
|
beliefId: resolvedBeliefId,
|
|
6581
7014
|
insightId: resolvedInsightId,
|
|
6582
7015
|
relation: args.relation,
|
|
6583
|
-
|
|
7016
|
+
weight: args.weight,
|
|
6584
7017
|
rationale: args.rationale,
|
|
6585
7018
|
createdBy: args.createdBy
|
|
6586
7019
|
});
|
|
@@ -6688,7 +7121,7 @@ var reviewSuggestion = mutation({
|
|
|
6688
7121
|
beliefId: link.beliefId,
|
|
6689
7122
|
insightId: link.insightId,
|
|
6690
7123
|
relation: link.relation,
|
|
6691
|
-
confidence: link.confidence,
|
|
7124
|
+
weight: link.relation === "supports" ? Math.abs(link.confidence ?? 0) : -Math.abs(link.confidence ?? 0),
|
|
6692
7125
|
rationale: link.rationale,
|
|
6693
7126
|
createdBy: args.userId
|
|
6694
7127
|
});
|
|
@@ -8937,7 +9370,7 @@ async function evaluateBuiltInEvidentialContract(args) {
|
|
|
8937
9370
|
observedValue: snapshot.value,
|
|
8938
9371
|
operator: config.operator,
|
|
8939
9372
|
threshold: config.threshold,
|
|
8940
|
-
action: config.action ?? "
|
|
9373
|
+
action: config.action ?? "append_sl_scoring",
|
|
8941
9374
|
actionParams: config.actionParams
|
|
8942
9375
|
}
|
|
8943
9376
|
};
|
|
@@ -11707,6 +12140,91 @@ function formatEvidenceNode(n) {
|
|
|
11707
12140
|
updatedAt: n.updatedAt
|
|
11708
12141
|
};
|
|
11709
12142
|
}
|
|
12143
|
+
function assertSignedImpactScore2(value, context) {
|
|
12144
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value === 0 || value < -1 || value > 1) {
|
|
12145
|
+
throw new Error(`${context} requires explicit nonzero weight in [-1, 1]`);
|
|
12146
|
+
}
|
|
12147
|
+
return value;
|
|
12148
|
+
}
|
|
12149
|
+
function normalizeEvidenceRelation(relation, weight, context) {
|
|
12150
|
+
if (relation === "supports" || relation === "contradicts") {
|
|
12151
|
+
if (relation === "supports" && weight < 0) {
|
|
12152
|
+
throw new Error(`${context} supports relation requires positive weight`);
|
|
12153
|
+
}
|
|
12154
|
+
if (relation === "contradicts" && weight > 0) {
|
|
12155
|
+
throw new Error(`${context} contradicts relation requires negative weight`);
|
|
12156
|
+
}
|
|
12157
|
+
return relation;
|
|
12158
|
+
}
|
|
12159
|
+
return weight < 0 ? "contradicts" : "supports";
|
|
12160
|
+
}
|
|
12161
|
+
async function createEvidenceBeliefEdge(ctx, args) {
|
|
12162
|
+
const edgeGlobalId = crypto.randomUUID();
|
|
12163
|
+
const confidence = Math.abs(args.weight);
|
|
12164
|
+
const existingEdges = await ctx.db.query("epistemicEdges").withIndex(
|
|
12165
|
+
"by_from_to",
|
|
12166
|
+
(q) => q.eq("fromNodeId", args.evidenceNodeId).eq("toNodeId", args.beliefNodeId)
|
|
12167
|
+
).collect();
|
|
12168
|
+
const existing = existingEdges.find((edge) => edge.edgeType === "informs");
|
|
12169
|
+
const edgeDoc = {
|
|
12170
|
+
globalId: edgeGlobalId,
|
|
12171
|
+
fromNodeId: args.evidenceNodeId,
|
|
12172
|
+
toNodeId: args.beliefNodeId,
|
|
12173
|
+
sourceGlobalId: args.evidenceGlobalId,
|
|
12174
|
+
targetGlobalId: args.beliefGlobalId,
|
|
12175
|
+
edgeType: "informs",
|
|
12176
|
+
weight: args.weight,
|
|
12177
|
+
confidence,
|
|
12178
|
+
context: args.rationale,
|
|
12179
|
+
reasoningMethod: "testimonial",
|
|
12180
|
+
derivationType: "evidence_sl_scoring",
|
|
12181
|
+
metadata: {
|
|
12182
|
+
relation: args.relation,
|
|
12183
|
+
confidence,
|
|
12184
|
+
impactScore: args.weight,
|
|
12185
|
+
invariant: "evidence.belief_impact_required"
|
|
12186
|
+
},
|
|
12187
|
+
createdBy: args.userId,
|
|
12188
|
+
createdAt: Date.now(),
|
|
12189
|
+
updatedAt: Date.now(),
|
|
12190
|
+
topicId: args.topicId,
|
|
12191
|
+
projectId: args.projectId,
|
|
12192
|
+
fromNodeType: "evidence",
|
|
12193
|
+
toNodeType: "belief",
|
|
12194
|
+
fromLayer: "L2",
|
|
12195
|
+
toLayer: "L3"
|
|
12196
|
+
};
|
|
12197
|
+
if (existing) {
|
|
12198
|
+
await ctx.db.patch(existing._id, {
|
|
12199
|
+
...edgeDoc,
|
|
12200
|
+
globalId: existing.globalId,
|
|
12201
|
+
createdAt: existing.createdAt ?? edgeDoc.createdAt
|
|
12202
|
+
});
|
|
12203
|
+
} else {
|
|
12204
|
+
await ctx.db.insert("epistemicEdges", edgeDoc);
|
|
12205
|
+
}
|
|
12206
|
+
await ctx.scheduler.runAfter(5e3, internal.neo4jEdgeAPI.createEdge, {
|
|
12207
|
+
globalId: existing?.globalId ?? edgeGlobalId,
|
|
12208
|
+
fromGlobalId: args.evidenceGlobalId,
|
|
12209
|
+
toGlobalId: args.beliefGlobalId,
|
|
12210
|
+
edgeType: "informs",
|
|
12211
|
+
weight: args.weight,
|
|
12212
|
+
confidence,
|
|
12213
|
+
createdBy: args.userId,
|
|
12214
|
+
topicId: args.projectId ?? args.topicId,
|
|
12215
|
+
fromNodeType: "evidence",
|
|
12216
|
+
toNodeType: "belief",
|
|
12217
|
+
fromLayer: "L2",
|
|
12218
|
+
toLayer: "L3",
|
|
12219
|
+
metadata: {
|
|
12220
|
+
relation: args.relation,
|
|
12221
|
+
confidence,
|
|
12222
|
+
impactScore: args.weight,
|
|
12223
|
+
invariant: "evidence.belief_impact_required"
|
|
12224
|
+
}
|
|
12225
|
+
});
|
|
12226
|
+
return existing?.globalId ?? edgeGlobalId;
|
|
12227
|
+
}
|
|
11710
12228
|
var create6 = mutation({
|
|
11711
12229
|
args: {
|
|
11712
12230
|
...optionalEvidenceScopeArgs,
|
|
@@ -11727,11 +12245,12 @@ var create6 = mutation({
|
|
|
11727
12245
|
informationAsymmetry: v.optional(v.string()),
|
|
11728
12246
|
sourceDescription: v.optional(v.string()),
|
|
11729
12247
|
metadata: v.optional(v.any()),
|
|
11730
|
-
//
|
|
11731
|
-
linkedBeliefNodeId: v.
|
|
12248
|
+
// Required belief impact link.
|
|
12249
|
+
linkedBeliefNodeId: v.id("epistemicNodes"),
|
|
11732
12250
|
evidenceRelation: v.optional(
|
|
11733
12251
|
v.union(v.literal("supports"), v.literal("contradicts"))
|
|
11734
12252
|
),
|
|
12253
|
+
weight: v.number(),
|
|
11735
12254
|
confidence: v.optional(v.number())
|
|
11736
12255
|
},
|
|
11737
12256
|
returns: permissiveReturn,
|
|
@@ -11753,6 +12272,16 @@ var create6 = mutation({
|
|
|
11753
12272
|
const contentHash = generateContentHash5(args.text);
|
|
11754
12273
|
const kind = normalizeKind(args.kind);
|
|
11755
12274
|
const sourceType = normalizeSourceType(args.sourceType);
|
|
12275
|
+
const weight = assertSignedImpactScore2(args.weight, "Evidence creation");
|
|
12276
|
+
const evidenceRelation = normalizeEvidenceRelation(
|
|
12277
|
+
args.evidenceRelation,
|
|
12278
|
+
weight,
|
|
12279
|
+
"Evidence creation"
|
|
12280
|
+
);
|
|
12281
|
+
const linkedBeliefNode = await ctx.db.get(args.linkedBeliefNodeId);
|
|
12282
|
+
if (!linkedBeliefNode || linkedBeliefNode.nodeType !== "belief") {
|
|
12283
|
+
throw new Error("Evidence creation requires a linked belief node");
|
|
12284
|
+
}
|
|
11756
12285
|
const additionalMetadata = args.metadata && typeof args.metadata === "object" ? args.metadata : {};
|
|
11757
12286
|
const nodeId = await ctx.db.insert("epistemicNodes", {
|
|
11758
12287
|
globalId,
|
|
@@ -11780,8 +12309,10 @@ var create6 = mutation({
|
|
|
11780
12309
|
sourceQuestionId: args.sourceQuestionId,
|
|
11781
12310
|
rationale: args.rationale,
|
|
11782
12311
|
linkedBeliefNodeId: args.linkedBeliefNodeId,
|
|
11783
|
-
evidenceRelation
|
|
11784
|
-
confidence:
|
|
12312
|
+
evidenceRelation,
|
|
12313
|
+
confidence: Math.abs(weight),
|
|
12314
|
+
weight,
|
|
12315
|
+
impactScore: weight,
|
|
11785
12316
|
methodology: args.methodology,
|
|
11786
12317
|
informationAsymmetry: args.informationAsymmetry,
|
|
11787
12318
|
sourceDescription: args.sourceDescription,
|
|
@@ -11801,29 +12332,18 @@ var create6 = mutation({
|
|
|
11801
12332
|
nodeType: "evidence",
|
|
11802
12333
|
text: args.text
|
|
11803
12334
|
});
|
|
11804
|
-
|
|
11805
|
-
|
|
11806
|
-
|
|
11807
|
-
|
|
11808
|
-
|
|
11809
|
-
|
|
11810
|
-
|
|
11811
|
-
|
|
11812
|
-
|
|
11813
|
-
|
|
11814
|
-
|
|
11815
|
-
|
|
11816
|
-
fromNodeType: "evidence",
|
|
11817
|
-
toNodeType: "belief",
|
|
11818
|
-
fromLayer: "L2",
|
|
11819
|
-
toLayer: "L3",
|
|
11820
|
-
metadata: {
|
|
11821
|
-
relation: args.evidenceRelation,
|
|
11822
|
-
confidence: args.confidence
|
|
11823
|
-
}
|
|
11824
|
-
});
|
|
11825
|
-
}
|
|
11826
|
-
}
|
|
12335
|
+
await createEvidenceBeliefEdge(ctx, {
|
|
12336
|
+
evidenceNodeId: nodeId,
|
|
12337
|
+
evidenceGlobalId: globalId,
|
|
12338
|
+
beliefNodeId: args.linkedBeliefNodeId,
|
|
12339
|
+
beliefGlobalId: linkedBeliefNode.globalId,
|
|
12340
|
+
relation: evidenceRelation,
|
|
12341
|
+
weight,
|
|
12342
|
+
userId: args.userId,
|
|
12343
|
+
topicId: scope.topicId ? String(scope.topicId) : void 0,
|
|
12344
|
+
projectId: scope.projectId ? String(scope.projectId) : void 0,
|
|
12345
|
+
rationale: args.rationale
|
|
12346
|
+
});
|
|
11827
12347
|
await ctx.db.insert("epistemicAudit", {
|
|
11828
12348
|
entityType: "evidence",
|
|
11829
12349
|
entityId: nodeId,
|
|
@@ -11838,7 +12358,8 @@ var create6 = mutation({
|
|
|
11838
12358
|
kind,
|
|
11839
12359
|
sourceType,
|
|
11840
12360
|
linkedBeliefNodeId: args.linkedBeliefNodeId,
|
|
11841
|
-
evidenceRelation
|
|
12361
|
+
evidenceRelation,
|
|
12362
|
+
weight
|
|
11842
12363
|
}
|
|
11843
12364
|
});
|
|
11844
12365
|
if (scope.projectId || scope.topicId) {
|
|
@@ -11881,6 +12402,7 @@ var createAndLink = mutation({
|
|
|
11881
12402
|
userId: v.string(),
|
|
11882
12403
|
beliefNodeId: v.id("epistemicNodes"),
|
|
11883
12404
|
relation: v.union(v.literal("supports"), v.literal("contradicts")),
|
|
12405
|
+
weight: v.number(),
|
|
11884
12406
|
confidence: v.optional(v.number())
|
|
11885
12407
|
},
|
|
11886
12408
|
returns: permissiveReturn,
|
|
@@ -11895,7 +12417,17 @@ var createAndLink = mutation({
|
|
|
11895
12417
|
const contentHash = generateContentHash5(args.text);
|
|
11896
12418
|
const kind = normalizeKind(args.kind);
|
|
11897
12419
|
const sourceType = normalizeSourceType(args.sourceType);
|
|
11898
|
-
const
|
|
12420
|
+
const weight = assertSignedImpactScore2(args.weight, "Evidence createAndLink");
|
|
12421
|
+
const relation = normalizeEvidenceRelation(
|
|
12422
|
+
args.relation,
|
|
12423
|
+
weight,
|
|
12424
|
+
"Evidence createAndLink"
|
|
12425
|
+
);
|
|
12426
|
+
const confidence = Math.abs(weight);
|
|
12427
|
+
const beliefNode = await ctx.db.get(args.beliefNodeId);
|
|
12428
|
+
if (!beliefNode || beliefNode.nodeType !== "belief") {
|
|
12429
|
+
throw new Error("Belief node not found for edge creation");
|
|
12430
|
+
}
|
|
11899
12431
|
const nodeId = await ctx.db.insert("epistemicNodes", {
|
|
11900
12432
|
globalId,
|
|
11901
12433
|
topicId: scope.topicId,
|
|
@@ -11915,36 +12447,26 @@ var createAndLink = mutation({
|
|
|
11915
12447
|
kind,
|
|
11916
12448
|
tags: args.tags || [],
|
|
11917
12449
|
linkedBeliefNodeId: args.beliefNodeId,
|
|
11918
|
-
evidenceRelation:
|
|
11919
|
-
confidence
|
|
12450
|
+
evidenceRelation: relation,
|
|
12451
|
+
confidence,
|
|
12452
|
+
weight,
|
|
12453
|
+
impactScore: weight
|
|
11920
12454
|
}
|
|
11921
12455
|
});
|
|
11922
12456
|
await ctx.scheduler.runAfter(0, internal.neo4jSync.syncNodeToNeo4j, {
|
|
11923
12457
|
nodeId,
|
|
11924
12458
|
operation: "upsert"
|
|
11925
12459
|
});
|
|
11926
|
-
const
|
|
11927
|
-
|
|
11928
|
-
|
|
11929
|
-
|
|
11930
|
-
|
|
11931
|
-
|
|
11932
|
-
await ctx.scheduler.runAfter(5e3, internal.neo4jEdgeAPI.createEdge, {
|
|
11933
|
-
globalId: edgeGlobalId,
|
|
11934
|
-
fromGlobalId: globalId,
|
|
11935
|
-
toGlobalId: beliefNode.globalId,
|
|
11936
|
-
edgeType: "informs",
|
|
12460
|
+
const edgeGlobalId = await createEvidenceBeliefEdge(ctx, {
|
|
12461
|
+
evidenceNodeId: nodeId,
|
|
12462
|
+
evidenceGlobalId: globalId,
|
|
12463
|
+
beliefNodeId: args.beliefNodeId,
|
|
12464
|
+
beliefGlobalId: beliefNode.globalId,
|
|
12465
|
+
relation,
|
|
11937
12466
|
weight,
|
|
11938
|
-
|
|
11939
|
-
topicId: scope.
|
|
11940
|
-
|
|
11941
|
-
toNodeType: "belief",
|
|
11942
|
-
fromLayer: "L2",
|
|
11943
|
-
toLayer: "L3",
|
|
11944
|
-
metadata: {
|
|
11945
|
-
relation: args.relation,
|
|
11946
|
-
confidence
|
|
11947
|
-
}
|
|
12467
|
+
userId: args.userId,
|
|
12468
|
+
topicId: scope.topicId ? String(scope.topicId) : void 0,
|
|
12469
|
+
projectId: scope.projectId ? String(scope.projectId) : void 0
|
|
11948
12470
|
});
|
|
11949
12471
|
await markProjectGraphDirty2(ctx, scope.projectId, String(scope.topicId));
|
|
11950
12472
|
return { nodeId, edgeGlobalId };
|
|
@@ -12005,8 +12527,9 @@ var internalCreate2 = internalMutation({
|
|
|
12005
12527
|
sourceQuestionId: v.optional(v.string()),
|
|
12006
12528
|
userId: v.string(),
|
|
12007
12529
|
rationale: v.string(),
|
|
12008
|
-
linkedBeliefNodeId: v.
|
|
12530
|
+
linkedBeliefNodeId: v.id("epistemicNodes"),
|
|
12009
12531
|
evidenceRelation: v.optional(v.string()),
|
|
12532
|
+
weight: v.number(),
|
|
12010
12533
|
confidence: v.optional(v.number()),
|
|
12011
12534
|
metadata: v.optional(v.any()),
|
|
12012
12535
|
runtimeToolName: v.optional(v.string()),
|
|
@@ -12041,6 +12564,16 @@ var internalCreate2 = internalMutation({
|
|
|
12041
12564
|
const contentHash = generateContentHash5(args.text);
|
|
12042
12565
|
const kind = normalizeKind(args.kind);
|
|
12043
12566
|
const sourceType = normalizeSourceType(args.sourceType);
|
|
12567
|
+
const weight = assertSignedImpactScore2(args.weight, "Internal evidence creation");
|
|
12568
|
+
const evidenceRelation = normalizeEvidenceRelation(
|
|
12569
|
+
args.evidenceRelation,
|
|
12570
|
+
weight,
|
|
12571
|
+
"Internal evidence creation"
|
|
12572
|
+
);
|
|
12573
|
+
const linkedBeliefNode = await ctx.db.get(args.linkedBeliefNodeId);
|
|
12574
|
+
if (!linkedBeliefNode || linkedBeliefNode.nodeType !== "belief") {
|
|
12575
|
+
throw new Error("Internal evidence creation requires a linked belief node");
|
|
12576
|
+
}
|
|
12044
12577
|
const additionalMetadata = args.metadata && typeof args.metadata === "object" ? args.metadata : {};
|
|
12045
12578
|
const nodeId = await ctx.db.insert("epistemicNodes", {
|
|
12046
12579
|
globalId,
|
|
@@ -12068,8 +12601,10 @@ var internalCreate2 = internalMutation({
|
|
|
12068
12601
|
sourceQuestionId: args.sourceQuestionId,
|
|
12069
12602
|
rationale: args.rationale,
|
|
12070
12603
|
linkedBeliefNodeId: args.linkedBeliefNodeId,
|
|
12071
|
-
evidenceRelation
|
|
12072
|
-
confidence:
|
|
12604
|
+
evidenceRelation,
|
|
12605
|
+
confidence: Math.abs(weight),
|
|
12606
|
+
weight,
|
|
12607
|
+
impactScore: weight,
|
|
12073
12608
|
...additionalMetadata
|
|
12074
12609
|
}
|
|
12075
12610
|
});
|
|
@@ -12089,8 +12624,9 @@ var internalCreate2 = internalMutation({
|
|
|
12089
12624
|
externalSourceType: args.externalSourceType,
|
|
12090
12625
|
sourceUrl: args.sourceUrl,
|
|
12091
12626
|
linkedBeliefNodeId: args.linkedBeliefNodeId,
|
|
12092
|
-
evidenceRelation
|
|
12093
|
-
confidence:
|
|
12627
|
+
evidenceRelation,
|
|
12628
|
+
confidence: Math.abs(weight),
|
|
12629
|
+
weight
|
|
12094
12630
|
},
|
|
12095
12631
|
triggeringAction: "epistemicEvidence.internalCreate"
|
|
12096
12632
|
});
|
|
@@ -12098,30 +12634,18 @@ var internalCreate2 = internalMutation({
|
|
|
12098
12634
|
nodeId,
|
|
12099
12635
|
operation: "upsert"
|
|
12100
12636
|
});
|
|
12101
|
-
|
|
12102
|
-
|
|
12103
|
-
|
|
12104
|
-
|
|
12105
|
-
|
|
12106
|
-
|
|
12107
|
-
|
|
12108
|
-
|
|
12109
|
-
|
|
12110
|
-
|
|
12111
|
-
|
|
12112
|
-
|
|
12113
|
-
topicId: scope.projectId ? String(scope.projectId) : void 0,
|
|
12114
|
-
fromNodeType: "evidence",
|
|
12115
|
-
toNodeType: "belief",
|
|
12116
|
-
fromLayer: "L2",
|
|
12117
|
-
toLayer: "L3",
|
|
12118
|
-
metadata: {
|
|
12119
|
-
relation: args.evidenceRelation,
|
|
12120
|
-
confidence
|
|
12121
|
-
}
|
|
12122
|
-
});
|
|
12123
|
-
}
|
|
12124
|
-
}
|
|
12637
|
+
await createEvidenceBeliefEdge(ctx, {
|
|
12638
|
+
evidenceNodeId: nodeId,
|
|
12639
|
+
evidenceGlobalId: globalId,
|
|
12640
|
+
beliefNodeId: args.linkedBeliefNodeId,
|
|
12641
|
+
beliefGlobalId: linkedBeliefNode.globalId,
|
|
12642
|
+
relation: evidenceRelation,
|
|
12643
|
+
weight,
|
|
12644
|
+
userId: args.userId,
|
|
12645
|
+
topicId: scope.topicId ? String(scope.topicId) : void 0,
|
|
12646
|
+
projectId: scope.projectId ? String(scope.projectId) : void 0,
|
|
12647
|
+
rationale: args.rationale
|
|
12648
|
+
});
|
|
12125
12649
|
if (scope.projectId || scope.topicId) {
|
|
12126
12650
|
await ctx.scheduler.runAfter(
|
|
12127
12651
|
0,
|
|
@@ -13412,7 +13936,7 @@ function assertBeliefNodeGenericUpdateAllowed(args) {
|
|
|
13412
13936
|
throwInvariantError({
|
|
13413
13937
|
message: "Belief confidence is append-only. Generic node updates cannot set confidence directly.",
|
|
13414
13938
|
invariantCode: "belief.confidence_append_only",
|
|
13415
|
-
suggestion: "Use epistemicBeliefs.
|
|
13939
|
+
suggestion: "Use epistemicBeliefs.appendSlScoring() so the beliefConfidence ledger and audit trail are updated together.",
|
|
13416
13940
|
details: { mutationName: args.mutationName, nodeId: args.node._id }
|
|
13417
13941
|
});
|
|
13418
13942
|
}
|
|
@@ -13464,7 +13988,7 @@ function assertBeliefNodeVerifyAllowed(args) {
|
|
|
13464
13988
|
throwInvariantError({
|
|
13465
13989
|
message: "Belief verification cannot set confidence directly. Confidence changes must stay append-only.",
|
|
13466
13990
|
invariantCode: "belief.confidence_append_only",
|
|
13467
|
-
suggestion: "Call epistemicBeliefs.
|
|
13991
|
+
suggestion: "Call epistemicBeliefs.appendSlScoring() after verification so the confidence history is preserved.",
|
|
13468
13992
|
details: { mutationName: args.mutationName, nodeId: args.node._id }
|
|
13469
13993
|
});
|
|
13470
13994
|
}
|
|
@@ -18904,7 +19428,7 @@ var epistemicBeliefs = {
|
|
|
18904
19428
|
internalGetByTopic,
|
|
18905
19429
|
linkBeliefs,
|
|
18906
19430
|
linkEvidence,
|
|
18907
|
-
|
|
19431
|
+
appendSlScoring,
|
|
18908
19432
|
propagateConfidenceChange,
|
|
18909
19433
|
reassignBeliefsTopic,
|
|
18910
19434
|
refineBelief,
|