@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.
Files changed (92) hide show
  1. package/dist/beliefEvidenceLinks.js +144 -99
  2. package/dist/beliefEvidenceLinks.js.map +1 -1
  3. package/dist/beliefEvidenceLinks.operational.d.ts +29 -0
  4. package/dist/beliefEvidenceLinks.operational.js +157 -0
  5. package/dist/beliefEvidenceLinks.operational.js.map +1 -0
  6. package/dist/{beliefLifecycle-y8WLXqQj.d.ts → beliefLifecycle-CXwdDw5e.d.ts} +7 -4
  7. package/dist/beliefLifecycle.d.ts +1 -1
  8. package/dist/beliefLifecycle.js +75 -18
  9. package/dist/beliefLifecycle.js.map +1 -1
  10. package/dist/entityLifecycle.js +1 -12
  11. package/dist/entityLifecycle.js.map +1 -1
  12. package/dist/epistemicAnswers.js +1 -12
  13. package/dist/epistemicAnswers.js.map +1 -1
  14. package/dist/epistemicBeliefs.admin.js.map +1 -1
  15. package/dist/epistemicBeliefs.backfills.d.ts +1 -1
  16. package/dist/epistemicBeliefs.backfills.js +63 -35
  17. package/dist/epistemicBeliefs.backfills.js.map +1 -1
  18. package/dist/epistemicBeliefs.confidence.d.ts +1 -1
  19. package/dist/epistemicBeliefs.confidence.js +70 -41
  20. package/dist/epistemicBeliefs.confidence.js.map +1 -1
  21. package/dist/epistemicBeliefs.core.js +946 -566
  22. package/dist/epistemicBeliefs.core.js.map +1 -1
  23. package/dist/epistemicBeliefs.d.ts +2 -2
  24. package/dist/epistemicBeliefs.forkEvidence.d.ts +18 -0
  25. package/dist/epistemicBeliefs.forkEvidence.js +121 -0
  26. package/dist/epistemicBeliefs.forkEvidence.js.map +1 -0
  27. package/dist/epistemicBeliefs.helpers.d.ts +2 -2
  28. package/dist/epistemicBeliefs.helpers.js +60 -32
  29. package/dist/epistemicBeliefs.helpers.js.map +1 -1
  30. package/dist/epistemicBeliefs.internal.js +175 -51
  31. package/dist/epistemicBeliefs.internal.js.map +1 -1
  32. package/dist/epistemicBeliefs.js +437 -84
  33. package/dist/epistemicBeliefs.js.map +1 -1
  34. package/dist/epistemicBeliefs.lifecycle.d.ts +2 -2
  35. package/dist/epistemicBeliefs.lifecycle.js +75 -47
  36. package/dist/epistemicBeliefs.lifecycle.js.map +1 -1
  37. package/dist/epistemicBeliefs.links.js +47 -13
  38. package/dist/epistemicBeliefs.links.js.map +1 -1
  39. package/dist/epistemicBeliefs.topicAnchor.d.ts +29 -0
  40. package/dist/epistemicBeliefs.topicAnchor.js +105 -0
  41. package/dist/epistemicBeliefs.topicAnchor.js.map +1 -0
  42. package/dist/epistemicContracts.evaluators.js +71 -42
  43. package/dist/epistemicContracts.evaluators.js.map +1 -1
  44. package/dist/epistemicContracts.handlers.js +72 -54
  45. package/dist/epistemicContracts.handlers.js.map +1 -1
  46. package/dist/epistemicContracts.js +72 -54
  47. package/dist/epistemicContracts.js.map +1 -1
  48. package/dist/epistemicContracts.metrics.js +1 -1
  49. package/dist/epistemicContracts.metrics.js.map +1 -1
  50. package/dist/epistemicContracts.types.d.ts +1 -1
  51. package/dist/epistemicEdgeCreation.js +1 -12
  52. package/dist/epistemicEdgeCreation.js.map +1 -1
  53. package/dist/epistemicEdges.helpers.d.ts +1 -1
  54. package/dist/epistemicEvidence.js +173 -93
  55. package/dist/epistemicEvidence.js.map +1 -1
  56. package/dist/epistemicEvidenceMutations.js +173 -93
  57. package/dist/epistemicEvidenceMutations.js.map +1 -1
  58. package/dist/epistemicHelpers.js +1 -12
  59. package/dist/epistemicHelpers.js.map +1 -1
  60. package/dist/epistemicNodeCreation.js +1 -10
  61. package/dist/epistemicNodeCreation.js.map +1 -1
  62. package/dist/epistemicNodes.internal.js.map +1 -1
  63. package/dist/epistemicNodes.js +2 -2
  64. package/dist/epistemicNodes.js.map +1 -1
  65. package/dist/epistemicNodes.mutations.js +2 -2
  66. package/dist/epistemicNodes.mutations.js.map +1 -1
  67. package/dist/epistemicQuestions.create.js +1 -12
  68. package/dist/epistemicQuestions.create.js.map +1 -1
  69. package/dist/epistemicQuestions.evidence.js +1 -12
  70. package/dist/epistemicQuestions.evidence.js.map +1 -1
  71. package/dist/epistemicQuestions.js +1 -12
  72. package/dist/epistemicQuestions.js.map +1 -1
  73. package/dist/epistemicQuestions.tail.js +1 -12
  74. package/dist/epistemicQuestions.tail.js.map +1 -1
  75. package/dist/epistemicSources.js +1 -12
  76. package/dist/epistemicSources.js.map +1 -1
  77. package/dist/evaluators/index.js +1 -1
  78. package/dist/evaluators/index.js.map +1 -1
  79. package/dist/globalId-4y9SPpC_.d.ts +10 -0
  80. package/dist/globalId.d.ts +1 -1
  81. package/dist/globalId.js +1 -13
  82. package/dist/globalId.js.map +1 -1
  83. package/dist/helpers.js +1 -12
  84. package/dist/helpers.js.map +1 -1
  85. package/dist/index.d.ts +4 -3
  86. package/dist/index.js +771 -247
  87. package/dist/index.js.map +1 -1
  88. package/dist/invariantEnforcement.js +2 -2
  89. package/dist/invariantEnforcement.js.map +1 -1
  90. package/dist/proof-attestation.json +3 -3
  91. package/package.json +4 -4
  92. package/dist/globalId-DKh9d_uD.d.ts +0 -20
@@ -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 } from '@lucern/contracts/ids';
10
11
  import { listAudienceRegistryRows } from '@lucern/access-control/audienceRegistry';
11
12
 
12
13
  // src/epistemicBeliefs.helpers.ts
@@ -15,18 +16,32 @@ import { listAudienceRegistryRows } from '@lucern/access-control/audienceRegistr
15
16
  var BELIEF_STATUS_VALUES = [
16
17
  "assumption",
17
18
  "hypothesis",
18
- "belief",
19
- "fact"
20
- ];
21
- var RESOLVED_PREDICTION_OUTCOMES = [
22
- "confirmed",
23
- "disconfirmed",
24
- "partial",
25
- "expired"
19
+ "active",
20
+ "superseded",
21
+ "resolved_true",
22
+ "resolved_false"
26
23
  ];
27
24
  function isBeliefLifecycleStatus(value) {
28
25
  return typeof value === "string" && BELIEF_STATUS_VALUES.includes(value);
29
26
  }
27
+ function normalizeLegacyBeliefStatus(value) {
28
+ if (isBeliefLifecycleStatus(value)) {
29
+ return value;
30
+ }
31
+ if (value === "belief" || value === "established" || value === "emerging") {
32
+ return "active";
33
+ }
34
+ if (value === "fact" || value === "confirmed") {
35
+ return "resolved_true";
36
+ }
37
+ if (value === "disconfirmed" || value === "expired") {
38
+ return "resolved_false";
39
+ }
40
+ if (value === "deprecated") {
41
+ return "superseded";
42
+ }
43
+ return null;
44
+ }
30
45
  function normalizeBeliefConfidence(confidence) {
31
46
  if (typeof confidence !== "number" || !Number.isFinite(confidence)) {
32
47
  return null;
@@ -46,47 +61,61 @@ function isResolvedByConfidence(confidence) {
46
61
  }
47
62
  return normalized <= 0 || normalized >= 1;
48
63
  }
49
- function hasResolvedPredictionOutcome(predictionMeta) {
64
+ function getPredictionMetaFromMetadata(metadata) {
65
+ return metadata?.predictionMeta;
66
+ }
67
+ function resolvedPredictionStatus(predictionMeta) {
50
68
  if (!predictionMeta || typeof predictionMeta !== "object") {
51
- return false;
69
+ return null;
52
70
  }
53
71
  const outcome = predictionMeta.outcome;
54
- return typeof outcome === "string" && RESOLVED_PREDICTION_OUTCOMES.includes(outcome);
55
- }
56
- function getPredictionMetaFromMetadata(metadata) {
57
- return metadata?.predictionMeta;
72
+ if (outcome === "confirmed") {
73
+ return "resolved_true";
74
+ }
75
+ if (outcome === "disconfirmed" || outcome === "expired") {
76
+ return "resolved_false";
77
+ }
78
+ return null;
58
79
  }
59
- function shouldTreatBeliefAsFact(opts) {
80
+ function shouldTreatBeliefAsResolved(opts) {
60
81
  if (isResolvedByConfidence(opts.confidence)) {
61
- return true;
82
+ const normalized = normalizeBeliefConfidence(opts.confidence);
83
+ return normalized === 0 ? "resolved_false" : "resolved_true";
62
84
  }
63
- if (hasResolvedPredictionOutcome(opts.predictionMeta)) {
64
- return true;
85
+ const directPredictionStatus = resolvedPredictionStatus(opts.predictionMeta);
86
+ if (directPredictionStatus) {
87
+ return directPredictionStatus;
65
88
  }
66
- if (hasResolvedPredictionOutcome(getPredictionMetaFromMetadata(opts.metadata))) {
67
- return true;
89
+ const metadataPredictionStatus = resolvedPredictionStatus(
90
+ getPredictionMetaFromMetadata(opts.metadata)
91
+ );
92
+ if (metadataPredictionStatus) {
93
+ return metadataPredictionStatus;
68
94
  }
69
- return false;
95
+ return null;
70
96
  }
71
97
  function resolveBeliefLifecycleStatus(opts) {
72
- if (shouldTreatBeliefAsFact(opts)) {
73
- return "fact";
98
+ const resolvedStatus = shouldTreatBeliefAsResolved(opts);
99
+ if (resolvedStatus) {
100
+ return resolvedStatus;
74
101
  }
75
102
  const direct = opts.beliefStatus;
76
- if (isBeliefLifecycleStatus(direct)) {
103
+ const normalizedDirect = normalizeLegacyBeliefStatus(direct);
104
+ if (normalizedDirect) {
77
105
  const normalized = normalizeBeliefConfidence(opts.confidence);
78
- if (normalized !== null && isPreValidationBeliefStatus(direct)) {
79
- return "belief";
106
+ if (normalized !== null && isPreValidationBeliefStatus(normalizedDirect)) {
107
+ return "active";
80
108
  }
81
- return direct;
109
+ return normalizedDirect;
82
110
  }
83
111
  const metaStatus = opts.metadata?.beliefStatus;
84
- if (isBeliefLifecycleStatus(metaStatus)) {
112
+ const normalizedMetaStatus = normalizeLegacyBeliefStatus(metaStatus);
113
+ if (normalizedMetaStatus) {
85
114
  const normalized = normalizeBeliefConfidence(opts.confidence);
86
- if (normalized !== null && isPreValidationBeliefStatus(metaStatus)) {
87
- return "belief";
115
+ if (normalized !== null && isPreValidationBeliefStatus(normalizedMetaStatus)) {
116
+ return "active";
88
117
  }
89
- return metaStatus;
118
+ return normalizedMetaStatus;
90
119
  }
91
120
  return "assumption";
92
121
  }
@@ -94,13 +123,14 @@ function isPreValidationBeliefStatus(status) {
94
123
  return status === "assumption" || status === "hypothesis";
95
124
  }
96
125
  function promoteBeliefStatusAfterScoring(status, opts) {
97
- if (shouldTreatBeliefAsFact({ ...opts })) {
98
- return "fact";
126
+ const resolvedStatus = shouldTreatBeliefAsResolved({ ...opts });
127
+ if (resolvedStatus) {
128
+ return resolvedStatus;
99
129
  }
100
130
  if (isPreValidationBeliefStatus(status)) {
101
- return "belief";
131
+ return "active";
102
132
  }
103
- return status === "fact" ? "fact" : "belief";
133
+ return status;
104
134
  }
105
135
  var api = anyApi;
106
136
  componentsGeneric();
@@ -870,7 +900,7 @@ function buildBeliefConfidenceRow(args) {
870
900
  disbelief: args.disbelief,
871
901
  uncertainty: args.uncertainty,
872
902
  baseRate: args.baseRate,
873
- slOperator: args.slOperator ?? "manual_assessment",
903
+ slOperator: args.slOperator ?? "prior_seed",
874
904
  trigger: args.trigger,
875
905
  ...args.rationale ? { rationale: args.rationale } : {},
876
906
  assessedBy: args.assessedBy,
@@ -1609,17 +1639,17 @@ async function applyBeliefConfidenceChange(ctx, args) {
1609
1639
  status: 404,
1610
1640
  code: "NOT_FOUND",
1611
1641
  invariantCode: "belief.exists",
1612
- suggestion: "Verify nodeId points to an existing node before modulating confidence.",
1642
+ suggestion: "Verify nodeId points to an existing node before appending SL scoring.",
1613
1643
  details: { nodeId: args.nodeId }
1614
1644
  });
1615
1645
  }
1616
1646
  if (node.nodeType !== "belief") {
1617
1647
  throwStructuredMutationError({
1618
- message: `modulateConfidence 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.`,
1648
+ 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.`,
1619
1649
  status: 400,
1620
1650
  code: "INVALID_ARGUMENT",
1621
1651
  invariantCode: "entity.no_confidence",
1622
- suggestion: "Use entityLifecycle.updateEntityAttributes for entity mutations. modulateConfidence is for belief nodes only.",
1652
+ suggestion: "Use entityLifecycle.updateEntityAttributes for entity mutations. appendSlScoring is for belief nodes only.",
1623
1653
  details: { nodeId: args.nodeId, nodeType: node.nodeType }
1624
1654
  });
1625
1655
  }
@@ -1629,7 +1659,7 @@ async function applyBeliefConfidenceChange(ctx, args) {
1629
1659
  status: 400,
1630
1660
  code: "MISSING_SCOPE",
1631
1661
  invariantCode: "belief.project_required",
1632
- suggestion: "Belief must have a projectId to modulate confidence.",
1662
+ suggestion: "Belief must have a projectId before SL scoring can be appended.",
1633
1663
  details: { nodeId: args.nodeId }
1634
1664
  });
1635
1665
  }
@@ -1652,7 +1682,7 @@ async function applyBeliefConfidenceChange(ctx, args) {
1652
1682
  status: 409,
1653
1683
  code: "CONFLICT",
1654
1684
  invariantCode: "belief.confidence_append_only",
1655
- suggestion: "Complete a worktree linked to this belief before recording confidence modulation.",
1685
+ suggestion: "Complete a worktree linked to this belief before recording SL scoring.",
1656
1686
  details: { nodeId: args.nodeId }
1657
1687
  });
1658
1688
  }
@@ -1907,6 +1937,199 @@ var propagateConfidenceChange = internalMutation({
1907
1937
  }
1908
1938
  });
1909
1939
 
1940
+ // src/epistemicBeliefs.forkEvidence.ts
1941
+ function normalizeForkTriggerRelation(value) {
1942
+ if (value === "supports" || value === "supporting") {
1943
+ return "supports";
1944
+ }
1945
+ if (value === "contradicts" || value === "contradicting") {
1946
+ return "contradicts";
1947
+ }
1948
+ return null;
1949
+ }
1950
+ async function resolveForkTriggerEvidence(ctx, args) {
1951
+ const evidence = await ctx.db.get(args.triggeringEvidenceId);
1952
+ if (!evidence || evidence.nodeType !== "evidence") {
1953
+ throwStructuredMutationError({
1954
+ message: "Fork requires an existing evidence node.",
1955
+ status: 400,
1956
+ code: "INVALID_ARGUMENT",
1957
+ invariantCode: "belief.fork_requires_evidence",
1958
+ suggestion: "Create or link evidence first, then fork with triggeringEvidenceId.",
1959
+ details: { triggeringEvidenceId: args.triggeringEvidenceId }
1960
+ });
1961
+ }
1962
+ if (evidence.topicId && evidence.topicId !== args.parent.topicId) {
1963
+ throwStructuredMutationError({
1964
+ message: "Fork evidence belongs to a different topic scope.",
1965
+ status: 400,
1966
+ code: "INVALID_ARGUMENT",
1967
+ invariantCode: "belief.fork_evidence_scope",
1968
+ suggestion: "Use evidence from the same topic/workspace scope as the parent belief.",
1969
+ details: {
1970
+ parentNodeId: args.parentNodeId,
1971
+ triggeringEvidenceId: args.triggeringEvidenceId
1972
+ }
1973
+ });
1974
+ }
1975
+ const evidenceMetadata = evidence.metadata && typeof evidence.metadata === "object" ? evidence.metadata : {};
1976
+ const parentRefs = new Set(
1977
+ [
1978
+ String(args.parentNodeId),
1979
+ String(args.parent.globalId ?? ""),
1980
+ String(args.parent._id)
1981
+ ].filter(Boolean)
1982
+ );
1983
+ const evidenceRefs = new Set(
1984
+ [
1985
+ String(args.triggeringEvidenceId),
1986
+ String(evidence.globalId ?? ""),
1987
+ String(evidence._id)
1988
+ ].filter(Boolean)
1989
+ );
1990
+ let relation = null;
1991
+ const linkedBeliefNodeId = String(
1992
+ evidenceMetadata.linkedBeliefNodeId ?? ""
1993
+ );
1994
+ if (linkedBeliefNodeId && parentRefs.has(linkedBeliefNodeId)) {
1995
+ relation = normalizeForkTriggerRelation(evidenceMetadata.evidenceRelation);
1996
+ }
1997
+ if (!relation) {
1998
+ for (const parentRef of parentRefs) {
1999
+ const links = await ctx.db.query("beliefEvidenceLinks").withIndex("by_beliefId", (q) => q.eq("beliefId", parentRef)).collect();
2000
+ const matched = links.find((link) => evidenceRefs.has(String(link.insightId)));
2001
+ if (matched) {
2002
+ relation = normalizeForkTriggerRelation(matched.relation);
2003
+ break;
2004
+ }
2005
+ }
2006
+ }
2007
+ if (!relation) {
2008
+ throwStructuredMutationError({
2009
+ message: "Fork evidence must already be attached to the parent belief through an SL evidence relation.",
2010
+ status: 409,
2011
+ code: "CONFLICT",
2012
+ invariantCode: "belief.fork_requires_attached_evidence",
2013
+ suggestion: "Attach the evidence to the parent belief as supports or contradicts before forking.",
2014
+ details: {
2015
+ parentNodeId: args.parentNodeId,
2016
+ triggeringEvidenceId: args.triggeringEvidenceId
2017
+ }
2018
+ });
2019
+ }
2020
+ if (args.forkMode === "supersede" && relation !== "contradicts") {
2021
+ throwStructuredMutationError({
2022
+ message: "Superseding fork requires contradicting evidence against the parent belief.",
2023
+ status: 409,
2024
+ code: "CONFLICT",
2025
+ invariantCode: "belief.supersede_requires_contradiction",
2026
+ suggestion: "Use forkMode='branch' for a non-replacing fork, or attach contradicting evidence before superseding.",
2027
+ details: {
2028
+ parentNodeId: args.parentNodeId,
2029
+ triggeringEvidenceId: args.triggeringEvidenceId,
2030
+ relation
2031
+ }
2032
+ });
2033
+ }
2034
+ return { evidenceNodeId: args.triggeringEvidenceId, relation };
2035
+ }
2036
+
2037
+ // src/epistemicBeliefs.topicAnchor.ts
2038
+ function cleanString(value) {
2039
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
2040
+ }
2041
+ function topicNodeCandidates(topicRef) {
2042
+ const normalized = topicRef.trim();
2043
+ if (!normalized) {
2044
+ return [];
2045
+ }
2046
+ const candidates = [normalized];
2047
+ if (normalized.startsWith("top_")) {
2048
+ candidates.push(normalized.slice(4));
2049
+ }
2050
+ return [...new Set(candidates)];
2051
+ }
2052
+ function readTopicNodeRef(args) {
2053
+ return cleanString(args.topicGlobalId) ?? cleanString(args.topicNodeId) ?? cleanString(args.topicId);
2054
+ }
2055
+ async function resolveRequiredTopicAnchor(ctx, topicRef) {
2056
+ for (const candidate of topicNodeCandidates(topicRef)) {
2057
+ try {
2058
+ const direct = await ctx.db.get(candidate);
2059
+ if (direct?.nodeType === "topic" && cleanString(direct.globalId)) {
2060
+ return direct;
2061
+ }
2062
+ } catch (_) {
2063
+ }
2064
+ const byGlobalId = await ctx.db.query("epistemicNodes").withIndex("by_globalId", (q) => q.eq("globalId", candidate)).first();
2065
+ if (byGlobalId?.nodeType === "topic" && cleanString(byGlobalId.globalId)) {
2066
+ return byGlobalId;
2067
+ }
2068
+ }
2069
+ throw new Error(
2070
+ "Belief creation requires topicGlobalId or topicNodeId for a topic node in epistemicNodes. Legacy topics-table IDs are not valid belief anchors."
2071
+ );
2072
+ }
2073
+ function scopeFromTopicAnchor(topicNode) {
2074
+ return {
2075
+ topicId: topicNode.globalId,
2076
+ projectId: cleanString(topicNode.projectId),
2077
+ tenantId: cleanString(topicNode.tenantId),
2078
+ workspaceId: cleanString(topicNode.workspaceId),
2079
+ source: "topic"
2080
+ };
2081
+ }
2082
+ async function createRequiredBeliefTopicEdge(ctx, args) {
2083
+ const topicGlobalId = args.topicNode.globalId;
2084
+ const edgeGlobalId = `edge:${args.beliefGlobalId}:${topicGlobalId}:scoped_by`;
2085
+ const now = Date.now();
2086
+ const existing = await ctx.db.query("epistemicEdges").withIndex("by_globalId", (q) => q.eq("globalId", edgeGlobalId)).first();
2087
+ if (!existing) {
2088
+ await ctx.db.insert("epistemicEdges", {
2089
+ globalId: edgeGlobalId,
2090
+ fromNodeId: String(args.beliefNodeId),
2091
+ toNodeId: String(args.topicNode._id),
2092
+ sourceGlobalId: args.beliefGlobalId,
2093
+ targetGlobalId: topicGlobalId,
2094
+ edgeType: "scoped_by",
2095
+ weight: 1,
2096
+ confidence: 1,
2097
+ context: "Belief creation topic anchor invariant.",
2098
+ reasoningMethod: "implicit",
2099
+ derivationType: "topic_scope_invariant",
2100
+ metadata: { invariant: "belief.topic_edge_required" },
2101
+ createdBy: args.createdBy,
2102
+ createdAt: now,
2103
+ updatedAt: now,
2104
+ projectId: cleanString(args.topicNode.projectId),
2105
+ topicId: topicGlobalId,
2106
+ tenantId: cleanString(args.topicNode.tenantId),
2107
+ workspaceId: cleanString(args.topicNode.workspaceId),
2108
+ fromNodeType: "belief",
2109
+ toNodeType: "topic",
2110
+ fromLayer: "L3",
2111
+ toLayer: args.topicNode.epistemicLayer ?? "ontological"
2112
+ });
2113
+ }
2114
+ await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {
2115
+ globalId: edgeGlobalId,
2116
+ fromGlobalId: args.beliefGlobalId,
2117
+ toGlobalId: topicGlobalId,
2118
+ edgeType: "scoped_by",
2119
+ weight: 1,
2120
+ confidence: 1,
2121
+ context: "Belief creation topic anchor invariant.",
2122
+ projectId: cleanString(args.topicNode.projectId),
2123
+ topicId: topicGlobalId,
2124
+ createdBy: args.createdBy,
2125
+ fromNodeType: "belief",
2126
+ toNodeType: "topic",
2127
+ fromLayer: "L3",
2128
+ toLayer: args.topicNode.epistemicLayer ?? "ontological",
2129
+ metadata: { invariant: "belief.topic_edge_required" }
2130
+ });
2131
+ }
2132
+
1910
2133
  // src/embeddingTrigger.ts
1911
2134
  async function scheduleEmbeddingGeneration(args) {
1912
2135
  try {
@@ -1936,22 +2159,12 @@ async function scheduleEmbeddingGeneration(args) {
1936
2159
  }
1937
2160
  }
1938
2161
 
1939
- // src/globalId.ts
1940
- function generateGlobalId() {
1941
- const bytes = new Uint8Array(16);
1942
- crypto.getRandomValues(bytes);
1943
- bytes[6] = bytes[6] & 15 | 64;
1944
- bytes[8] = bytes[8] & 63 | 128;
1945
- const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join(
1946
- ""
1947
- );
1948
- return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
1949
- }
1950
-
1951
2162
  // src/epistemicBeliefs.core.ts
1952
2163
  var create = mutation({
1953
2164
  args: {
1954
2165
  ...optionalBeliefScopeArgs,
2166
+ topicNodeId: v.optional(v.string()),
2167
+ topicGlobalId: v.optional(v.string()),
1955
2168
  formulation: v.string(),
1956
2169
  beliefType: v.optional(v.string()),
1957
2170
  rationale: v.optional(v.string()),
@@ -1996,20 +2209,32 @@ var create = mutation({
1996
2209
  returns: permissiveReturn,
1997
2210
  handler: async (ctx, args) => {
1998
2211
  const authenticatedUserId = await requireAuthenticatedUserId(ctx);
1999
- const scope = await resolveTopicProjectScope(ctx, {
2000
- topicId: args.topicId,
2001
- projectId: args.projectId
2002
- });
2212
+ const topicRef = readTopicNodeRef(args);
2213
+ if (!topicRef) {
2214
+ throwStructuredMutationError({
2215
+ message: "Belief creation requires an explicit topic epistemic node.",
2216
+ status: 400,
2217
+ code: "INVALID_ARGUMENT",
2218
+ invariantCode: "belief.topic_node_required",
2219
+ suggestion: "Pass topicGlobalId or topicNodeId for a topic in epistemicNodes before creating a belief.",
2220
+ details: {
2221
+ topicId: args.topicId,
2222
+ topicNodeId: args.topicNodeId,
2223
+ topicGlobalId: args.topicGlobalId
2224
+ }
2225
+ });
2226
+ }
2227
+ const topicNode = await resolveRequiredTopicAnchor(ctx, topicRef);
2228
+ const scope = scopeFromTopicAnchor(topicNode);
2003
2229
  assertWorkspaceScopedEpistemicNodeScope({
2004
2230
  scope,
2005
2231
  nodeType: "belief",
2006
2232
  mutationName: "epistemicBeliefs.create"
2007
2233
  });
2008
- const topic = await ctx.db.get(scope.topicId);
2009
2234
  const normalizedBeliefType = await assertSchemaEnumValue(ctx, {
2010
2235
  category: "belief_type",
2011
2236
  value: args.beliefType,
2012
- tenantId: topic?.tenantId,
2237
+ tenantId: scope.tenantId,
2013
2238
  context: "epistemicBeliefs.create"
2014
2239
  });
2015
2240
  if (scope.projectId) {
@@ -2042,7 +2267,7 @@ var create = mutation({
2042
2267
  title: args.formulation.slice(0, 100) + (args.formulation.length > 100 ? "..." : ""),
2043
2268
  metadata: {
2044
2269
  pillar,
2045
- // No confidenceLevel — only set after worktree completion via modulateConfidence()
2270
+ // No confidenceLevel — only set after evidence-backed SL scoring.
2046
2271
  status: "active",
2047
2272
  worktreeId: args.worktreeId,
2048
2273
  beliefStatus: initialBeliefStatus,
@@ -2086,9 +2311,15 @@ var create = mutation({
2086
2311
  rationale: "LKC-2 mandatory prior: seeded vacuous opinion at belief creation.",
2087
2312
  assessedBy: authenticatedUserId,
2088
2313
  assessedAt: now,
2089
- slOperator: "manual_assessment"
2314
+ slOperator: "prior_seed"
2090
2315
  })
2091
2316
  );
2317
+ await createRequiredBeliefTopicEdge(ctx, {
2318
+ beliefNodeId: nodeId,
2319
+ beliefGlobalId,
2320
+ topicNode,
2321
+ createdBy: authenticatedUserId
2322
+ });
2092
2323
  await ctx.scheduler.runAfter(0, internal.neo4jSync.syncNodeToNeo4j, {
2093
2324
  nodeId,
2094
2325
  operation: "upsert"
@@ -2425,9 +2656,10 @@ var forkBelief = mutation({
2425
2656
  v.literal("refinement"),
2426
2657
  v.literal("contradiction_response"),
2427
2658
  v.literal("scope_change"),
2428
- v.literal("confidence_collapse"),
2429
- v.literal("manual")
2659
+ v.literal("confidence_collapse")
2430
2660
  ),
2661
+ forkMode: v.optional(v.union(v.literal("supersede"), v.literal("branch"))),
2662
+ triggeringEvidenceId: v.id("epistemicNodes"),
2431
2663
  rationale: v.optional(v.string()),
2432
2664
  userId: v.string()
2433
2665
  },
@@ -2470,6 +2702,33 @@ var forkBelief = mutation({
2470
2702
  await requireProjectWriteAccess(ctx, parent.projectId, authenticatedUserId);
2471
2703
  const metadata = parent.metadata;
2472
2704
  const forkBeliefStatus = "hypothesis";
2705
+ const forkMode = args.forkMode ?? "supersede";
2706
+ const triggerEvidence = await resolveForkTriggerEvidence(ctx, {
2707
+ parentNodeId: args.parentNodeId,
2708
+ parent,
2709
+ triggeringEvidenceId: args.triggeringEvidenceId,
2710
+ forkMode
2711
+ });
2712
+ const parentLifecycleStatus = resolveBeliefLifecycleStatus({
2713
+ beliefStatus: parent.beliefStatus,
2714
+ confidence: parent.confidence,
2715
+ predictionMeta: parent.predictionMeta,
2716
+ metadata
2717
+ });
2718
+ if (forkMode === "supersede" && parentLifecycleStatus !== "active") {
2719
+ throwStructuredMutationError({
2720
+ message: "Superseding fork requires an active parent belief. Attach evidence first so the lifecycle can promote deterministically.",
2721
+ status: 409,
2722
+ code: "CONFLICT",
2723
+ invariantCode: "belief.supersede_requires_active_parent",
2724
+ suggestion: "Attach the contradicting evidence to the parent belief, let the evidence path promote it to active, then supersede.",
2725
+ details: {
2726
+ parentNodeId: args.parentNodeId,
2727
+ parentLifecycleStatus,
2728
+ triggeringEvidenceId: args.triggeringEvidenceId
2729
+ }
2730
+ });
2731
+ }
2473
2732
  const newBeliefGlobalId = generateGlobalId();
2474
2733
  const newNodeId = await ctx.db.insert("epistemicNodes", {
2475
2734
  globalId: newBeliefGlobalId,
@@ -2483,6 +2742,9 @@ var forkBelief = mutation({
2483
2742
  ...metadata,
2484
2743
  forkedFrom: args.parentNodeId,
2485
2744
  forkReason: args.forkReason,
2745
+ forkMode,
2746
+ triggeringEvidenceId: args.triggeringEvidenceId,
2747
+ triggeringEvidenceRelation: triggerEvidence.relation,
2486
2748
  forkTimestamp: now,
2487
2749
  forkedBy: authenticatedUserId,
2488
2750
  status: "active",
@@ -2501,6 +2763,27 @@ var forkBelief = mutation({
2501
2763
  createdAt: now,
2502
2764
  updatedAt: now
2503
2765
  });
2766
+ if (forkMode === "supersede") {
2767
+ await ctx.db.patch(args.parentNodeId, {
2768
+ status: "superseded",
2769
+ beliefStatus: "superseded",
2770
+ epistemicStatus: "superseded",
2771
+ supersededBy: newNodeId,
2772
+ updatedAt: now,
2773
+ metadata: {
2774
+ ...metadata ?? {},
2775
+ status: "superseded",
2776
+ beliefStatus: "superseded",
2777
+ epistemicStatus: "superseded",
2778
+ supersededBy: String(newNodeId),
2779
+ supersededByEvidenceId: String(triggerEvidence.evidenceNodeId)
2780
+ }
2781
+ });
2782
+ await ctx.scheduler.runAfter(0, internal.neo4jSync.syncNodeToNeo4j, {
2783
+ nodeId: args.parentNodeId,
2784
+ operation: "upsert"
2785
+ });
2786
+ }
2504
2787
  const inheritedContracts = await ctx.db.query("epistemicContracts").withIndex(
2505
2788
  "by_belief",
2506
2789
  (q) => q.eq("beliefNodeId", args.parentNodeId)
@@ -2527,12 +2810,17 @@ var forkBelief = mutation({
2527
2810
  globalId: generateGlobalId(),
2528
2811
  fromGlobalId: newBeliefGlobalId,
2529
2812
  toGlobalId: parent.globalId,
2530
- edgeType: "supersedes",
2531
- context: `Fork reason: ${args.forkReason}`,
2813
+ edgeType: forkMode === "supersede" ? "supersedes" : "derived_from",
2814
+ context: `Fork reason: ${args.forkReason}; triggering evidence: ${triggerEvidence.evidenceNodeId}`,
2532
2815
  createdBy: authenticatedUserId,
2533
2816
  topicId: parent.projectId ? String(parent.projectId) : void 0,
2534
2817
  fromNodeType: "belief",
2535
- toNodeType: "belief"
2818
+ toNodeType: "belief",
2819
+ metadata: {
2820
+ forkMode,
2821
+ triggeringEvidenceId: String(triggerEvidence.evidenceNodeId),
2822
+ triggeringEvidenceRelation: triggerEvidence.relation
2823
+ }
2536
2824
  });
2537
2825
  await scheduleEmbeddingGeneration({
2538
2826
  ctx,
@@ -2557,6 +2845,9 @@ var forkBelief = mutation({
2557
2845
  newState: {
2558
2846
  formulation: args.newFormulation,
2559
2847
  forkReason: args.forkReason,
2848
+ forkMode,
2849
+ triggeringEvidenceId: String(triggerEvidence.evidenceNodeId),
2850
+ triggeringEvidenceRelation: triggerEvidence.relation,
2560
2851
  tupleContradicted: false
2561
2852
  },
2562
2853
  projectId: parent.projectId,
@@ -2591,10 +2882,17 @@ var forkBelief = mutation({
2591
2882
  projectId: parent.projectId,
2592
2883
  topicId: parent.topicId
2593
2884
  });
2594
- return { newNodeId, parentNodeId: args.parentNodeId };
2885
+ return {
2886
+ newNodeId,
2887
+ parentNodeId: args.parentNodeId,
2888
+ forkMode,
2889
+ forkReason: args.forkReason,
2890
+ triggeringEvidenceId: triggerEvidence.evidenceNodeId,
2891
+ triggeringEvidenceRelation: triggerEvidence.relation
2892
+ };
2595
2893
  }
2596
2894
  });
2597
- var modulateConfidence = mutation({
2895
+ var appendSlScoring = mutation({
2598
2896
  args: {
2599
2897
  nodeId: v.id("epistemicNodes"),
2600
2898
  // SL opinion — the ONLY confidence input (EK-7)
@@ -2611,8 +2909,6 @@ var modulateConfidence = mutation({
2611
2909
  v.literal("evidence_removed"),
2612
2910
  v.literal("contradiction_detected"),
2613
2911
  v.literal("contradiction_resolved"),
2614
- v.literal("manual"),
2615
- v.literal("decay"),
2616
2912
  v.literal("agent_assessment"),
2617
2913
  v.literal("worktree_outcome"),
2618
2914
  v.literal("worktree_completed"),
@@ -2624,7 +2920,7 @@ var modulateConfidence = mutation({
2624
2920
  ),
2625
2921
  rationale: v.optional(v.string()),
2626
2922
  userId: v.string(),
2627
- // SL operator provenance (optional — defaults to manual_assessment)
2923
+ // SL operator provenance (optional — defaults inside the SL scorer)
2628
2924
  slOperator: v.optional(
2629
2925
  v.union(
2630
2926
  v.literal("cumulative_fusion"),
@@ -2634,7 +2930,8 @@ var modulateConfidence = mutation({
2634
2930
  v.literal("dependency_cascade"),
2635
2931
  v.literal("negation"),
2636
2932
  v.literal("constraint_fusion"),
2637
- v.literal("manual_assessment")
2933
+ v.literal("no_op"),
2934
+ v.literal("prior_seed")
2638
2935
  )
2639
2936
  ),
2640
2937
  triggeringEvidenceId: v.optional(v.id("epistemicNodes")),
@@ -2997,6 +3294,12 @@ async function getQuestionsAnsweredByEvidence(ctx, evidenceId) {
2997
3294
  }
2998
3295
 
2999
3296
  // src/epistemicBeliefs.links.ts
3297
+ function assertSignedImpactScore(value, context) {
3298
+ if (typeof value !== "number" || !Number.isFinite(value) || value === 0 || value < -1 || value > 1) {
3299
+ throw new Error(`${context} requires explicit nonzero weight in [-1, 1]`);
3300
+ }
3301
+ return value;
3302
+ }
3000
3303
  var updatePillar = mutation({
3001
3304
  args: {
3002
3305
  nodeId: v.id("epistemicNodes"),
@@ -3176,6 +3479,7 @@ var linkEvidence = mutation({
3176
3479
  beliefNodeId: v.id("epistemicNodes"),
3177
3480
  insightId: insightIdUnion,
3178
3481
  type: v.union(v.literal("supporting"), v.literal("contradicting")),
3482
+ weight: v.number(),
3179
3483
  rationale: v.optional(v.string()),
3180
3484
  userId: v.string()
3181
3485
  },
@@ -3199,16 +3503,54 @@ var linkEvidence = mutation({
3199
3503
  }
3200
3504
  const evidenceNodeId = insight._id;
3201
3505
  const evidenceGlobalId = insight.globalId;
3506
+ const weight = assertSignedImpactScore(args.weight, "Evidence link");
3507
+ if (args.type === "supporting" && weight < 0) {
3508
+ throw new Error("Supporting evidence links require positive weight");
3509
+ }
3510
+ if (args.type === "contradicting" && weight > 0) {
3511
+ throw new Error("Contradicting evidence links require negative weight");
3512
+ }
3513
+ const confidence = Math.abs(weight);
3202
3514
  const edgeType = "informs";
3203
- const weight = args.type === "supporting" ? 1 : -1;
3204
3515
  const logicalRole = evidenceNodeId ? await computeLogicalRole(ctx, evidenceNodeId, args.beliefNodeId) : "contributory";
3205
3516
  const edgeGlobalId = generateGlobalId();
3517
+ await ctx.db.insert("epistemicEdges", {
3518
+ globalId: edgeGlobalId,
3519
+ fromNodeId: evidenceNodeId,
3520
+ toNodeId: args.beliefNodeId,
3521
+ sourceGlobalId: evidenceGlobalId,
3522
+ targetGlobalId: belief.globalId,
3523
+ edgeType,
3524
+ weight,
3525
+ confidence,
3526
+ context: args.rationale || `${args.type} evidence`,
3527
+ reasoningMethod: "testimonial",
3528
+ logicalRole,
3529
+ temporalClass: "structural",
3530
+ derivationType: "evidence_sl_scoring",
3531
+ metadata: {
3532
+ relation: args.type,
3533
+ confidence,
3534
+ impactScore: weight,
3535
+ invariant: "evidence.belief_impact_required"
3536
+ },
3537
+ createdBy: authenticatedUserId,
3538
+ createdAt: Date.now(),
3539
+ updatedAt: Date.now(),
3540
+ topicId: belief.topicId ? String(belief.topicId) : void 0,
3541
+ projectId: belief.projectId ? String(belief.projectId) : void 0,
3542
+ fromNodeType: "evidence",
3543
+ toNodeType: "belief",
3544
+ fromLayer: "L2",
3545
+ toLayer: "L3"
3546
+ });
3206
3547
  await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {
3207
3548
  globalId: edgeGlobalId,
3208
3549
  fromGlobalId: evidenceGlobalId,
3209
3550
  toGlobalId: belief.globalId,
3210
3551
  edgeType,
3211
3552
  weight,
3553
+ confidence,
3212
3554
  context: args.rationale || `${args.type} evidence`,
3213
3555
  createdBy: authenticatedUserId,
3214
3556
  topicId: belief.projectId ? String(belief.projectId) : void 0,
@@ -3839,6 +4181,8 @@ var internalGetById = internalQuery({
3839
4181
  var internalCreate = internalMutation({
3840
4182
  args: {
3841
4183
  ...optionalBeliefScopeArgs,
4184
+ topicNodeId: v.optional(v.string()),
4185
+ topicGlobalId: v.optional(v.string()),
3842
4186
  formulation: v.string(),
3843
4187
  baseRate: v.optional(v.number()),
3844
4188
  confidence: v.optional(
@@ -3877,10 +4221,14 @@ var internalCreate = internalMutation({
3877
4221
  handler: async (ctx, args) => {
3878
4222
  const now = Date.now();
3879
4223
  const baseRate = assertBaseRateInRange(args.baseRate ?? 0.5);
3880
- const scope = await resolveTopicProjectScope(ctx, {
3881
- topicId: args.topicId,
3882
- projectId: args.projectId
3883
- });
4224
+ const topicRef = readTopicNodeRef(args);
4225
+ if (!topicRef) {
4226
+ throw new Error(
4227
+ "Belief creation requires topicGlobalId or topicNodeId for a topic node in epistemicNodes."
4228
+ );
4229
+ }
4230
+ const topicNode = await resolveRequiredTopicAnchor(ctx, topicRef);
4231
+ const scope = scopeFromTopicAnchor(topicNode);
3884
4232
  assertWorkspaceScopedEpistemicNodeScope({
3885
4233
  scope,
3886
4234
  nodeType: "belief",
@@ -3896,11 +4244,10 @@ var internalCreate = internalMutation({
3896
4244
  },
3897
4245
  mutationName: "epistemicBeliefs.internalCreate"
3898
4246
  });
3899
- const topic = await ctx.db.get(scope.topicId);
3900
4247
  const normalizedBeliefType = await assertSchemaEnumValue(ctx, {
3901
4248
  category: "belief_type",
3902
4249
  value: args.beliefType,
3903
- tenantId: topic?.tenantId,
4250
+ tenantId: scope.tenantId,
3904
4251
  context: "epistemicBeliefs.internalCreate"
3905
4252
  });
3906
4253
  const globalId = generateGlobalId();
@@ -3964,9 +4311,15 @@ var internalCreate = internalMutation({
3964
4311
  rationale: "LKC-2 mandatory prior: seeded vacuous opinion at belief creation.",
3965
4312
  assessedBy: args.userId,
3966
4313
  assessedAt: now,
3967
- slOperator: "manual_assessment"
4314
+ slOperator: "prior_seed"
3968
4315
  })
3969
4316
  );
4317
+ await createRequiredBeliefTopicEdge(ctx, {
4318
+ beliefNodeId: nodeId,
4319
+ beliefGlobalId: globalId,
4320
+ topicNode,
4321
+ createdBy: args.userId
4322
+ });
3970
4323
  await ctx.scheduler.runAfter(0, internal.neo4jSync.syncNodeToNeo4j, {
3971
4324
  nodeId,
3972
4325
  operation: "upsert"
@@ -4140,7 +4493,7 @@ var backfillSyntheticOpinionHistory = internalMutation({
4140
4493
  rationale: "LK-6 backfill: synthesized t0 from node-level opinion fields (no prior beliefConfidence row found).",
4141
4494
  assessedAt: readFiniteNumber(node.createdAt) ?? readFiniteNumber(node.updatedAt) ?? Date.now(),
4142
4495
  assessedBy: "system:lk-6-backfill",
4143
- slOperator: "manual_assessment"
4496
+ slOperator: "prior_seed"
4144
4497
  })
4145
4498
  );
4146
4499
  beliefsWithHistory.add(String(node._id));
@@ -4246,7 +4599,7 @@ var backfillMandatoryPriors = internalMutation({
4246
4599
  rationale: "LKC-2 backfill: inserted missing initial vacuous opinion with neutral prior.",
4247
4600
  assessedAt: readFiniteNumber(node.createdAt) ?? readFiniteNumber(node.updatedAt) ?? Date.now(),
4248
4601
  assessedBy: "system:lkc-2-prior-backfill",
4249
- slOperator: "manual_assessment"
4602
+ slOperator: "prior_seed"
4250
4603
  })
4251
4604
  );
4252
4605
  insertedInitialRows++;
@@ -4354,7 +4707,7 @@ var backfillScoredBeliefEdges = internalMutation({
4354
4707
  const scoredBeliefs = allBeliefs.filter((belief) => {
4355
4708
  const metadata = belief.metadata || {};
4356
4709
  const lifecycle = resolveBeliefStatus(belief, metadata);
4357
- return lifecycle === "belief" || lifecycle === "fact";
4710
+ return lifecycle === "active" || lifecycle === "resolved_true";
4358
4711
  });
4359
4712
  const themeNodes = await ctx.db.query("epistemicNodes").withIndex(
4360
4713
  "by_topic",
@@ -4540,6 +4893,6 @@ var reassignBeliefsTopic = mutation({
4540
4893
  }
4541
4894
  });
4542
4895
 
4543
- export { applyBeliefConfidenceChange, archive, backfillBeliefSprintIds, backfillMandatoryPriors, backfillScoredBeliefEdges, backfillSyntheticOpinionHistory, backfillTwoAxisConfidence, batchUpdateCriticality, create, deleteRelationship, flattenBeliefNode, forkBelief, getBeliefClusterPositions, getByCriticality, getById, getByIds, getByPillar, getByProject, getByProjectSystem, getByTopic, getByWorktree, getConfidenceHistory, getCountByStatus, getLineage, getRecentConfidenceChanges, getRelationships, getUnanalyzed, getWithEvidence, getWorktreeCluster, internalCreate, internalGetActive, internalGetById, internalGetByProject, internalGetByTopic, linkBeliefs, linkEvidence, modulateConfidence, propagateConfidenceChange, reassignBeliefsTopic, refineBelief, resolveBeliefWorktreeId, unlinkEvidence, updateCriticality, updatePillar, updateRationale, updateStatus, updateStatusInternal };
4896
+ export { appendSlScoring, applyBeliefConfidenceChange, archive, backfillBeliefSprintIds, backfillMandatoryPriors, backfillScoredBeliefEdges, backfillSyntheticOpinionHistory, backfillTwoAxisConfidence, batchUpdateCriticality, create, deleteRelationship, flattenBeliefNode, forkBelief, getBeliefClusterPositions, getByCriticality, getById, getByIds, getByPillar, getByProject, getByProjectSystem, getByTopic, getByWorktree, getConfidenceHistory, getCountByStatus, getLineage, getRecentConfidenceChanges, getRelationships, getUnanalyzed, getWithEvidence, getWorktreeCluster, internalCreate, internalGetActive, internalGetById, internalGetByProject, internalGetByTopic, linkBeliefs, linkEvidence, propagateConfidenceChange, reassignBeliefsTopic, refineBelief, resolveBeliefWorktreeId, unlinkEvidence, updateCriticality, updatePillar, updateRationale, updateStatus, updateStatusInternal };
4544
4897
  //# sourceMappingURL=epistemicBeliefs.js.map
4545
4898
  //# sourceMappingURL=epistemicBeliefs.js.map