@lucern/graph-primitives 1.0.50 → 1.0.52

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 (67) hide show
  1. package/dist/beliefDecay.js +34 -186
  2. package/dist/beliefEvidenceLinks.js +32 -187
  3. package/dist/contradictions.js +34 -187
  4. package/dist/entityLifecycle.js +88 -205
  5. package/dist/epistemicAnswers.js +35 -187
  6. package/dist/epistemicBeliefs.admin.js +34 -187
  7. package/dist/epistemicBeliefs.backfills.js +34 -188
  8. package/dist/epistemicBeliefs.confidence.d.ts +1 -1
  9. package/dist/epistemicBeliefs.confidence.js +32 -188
  10. package/dist/epistemicBeliefs.core.js +37 -187
  11. package/dist/epistemicBeliefs.d.ts +1 -1
  12. package/dist/epistemicBeliefs.helpers.d.ts +1 -1
  13. package/dist/epistemicBeliefs.helpers.js +34 -186
  14. package/dist/epistemicBeliefs.internal.js +37 -187
  15. package/dist/epistemicBeliefs.js +37 -187
  16. package/dist/epistemicBeliefs.lifecycle.js +32 -188
  17. package/dist/epistemicBeliefs.links.js +34 -188
  18. package/dist/epistemicContracts.evaluators.js +34 -188
  19. package/dist/epistemicContracts.handlers.js +34 -188
  20. package/dist/epistemicContracts.js +34 -188
  21. package/dist/epistemicEdges.d.ts +1 -1
  22. package/dist/epistemicEdges.helpers.d.ts +1 -1
  23. package/dist/epistemicEdges.js +32 -187
  24. package/dist/epistemicEdges.mutations.js +34 -186
  25. package/dist/epistemicEdges.queries.js +35 -188
  26. package/dist/epistemicEdges.types.d.ts +1 -1
  27. package/dist/epistemicEvidence.d.ts +1 -1
  28. package/dist/epistemicEvidence.js +37 -187
  29. package/dist/epistemicEvidenceHelpers.d.ts +1 -1
  30. package/dist/epistemicEvidenceHelpers.js +34 -186
  31. package/dist/epistemicEvidenceMutations.js +37 -187
  32. package/dist/epistemicEvidenceQueries.js +34 -186
  33. package/dist/epistemicHelpers.js +4 -1
  34. package/dist/epistemicInsert.js +4 -1
  35. package/dist/epistemicNodeCreation.js +4 -1
  36. package/dist/epistemicNodes.helpers.d.ts +1 -1
  37. package/dist/epistemicNodes.internal.js +35 -188
  38. package/dist/epistemicNodes.js +37 -188
  39. package/dist/epistemicNodes.mutations.js +35 -188
  40. package/dist/epistemicNodes.queries.js +35 -188
  41. package/dist/epistemicQuestions.conviction.js +34 -186
  42. package/dist/epistemicQuestions.create.js +37 -187
  43. package/dist/epistemicQuestions.d.ts +1 -1
  44. package/dist/epistemicQuestions.evidence.js +37 -187
  45. package/dist/epistemicQuestions.helpers.d.ts +1 -1
  46. package/dist/epistemicQuestions.helpers.js +34 -186
  47. package/dist/epistemicQuestions.js +37 -187
  48. package/dist/epistemicQuestions.lifecycle.js +34 -186
  49. package/dist/epistemicQuestions.queries.js +34 -186
  50. package/dist/epistemicQuestions.sprint.js +35 -188
  51. package/dist/epistemicQuestions.tail.js +37 -187
  52. package/dist/epistemicSources.js +35 -188
  53. package/dist/index.d.ts +1 -1
  54. package/dist/index.js +98 -213
  55. package/dist/proof-attestation.json +1 -1
  56. package/dist/questionEvidenceLinks.js +34 -187
  57. package/dist/scopeResolverCompat.d.ts +1 -1
  58. package/dist/scopeResolverCompat.js +32 -193
  59. package/dist/topicOntologyResolver.d.ts +3 -3
  60. package/dist/topicOntologyResolver.js +57 -18
  61. package/dist/{topicScope-DJVa0mLa.d.ts → topicScope-CL1IVOmv.d.ts} +2 -2
  62. package/dist/topicScope.d.ts +1 -1
  63. package/dist/topicScope.js +32 -193
  64. package/dist/workflowBridge.js +32 -193
  65. package/dist/workspaceIsolation.d.ts +1 -1
  66. package/dist/workspaceIsolation.js +32 -193
  67. package/package.json +4 -4
@@ -3,6 +3,7 @@ import { permissiveReturn } from '@lucern/contracts/schema-helpers/validators';
3
3
  import { v } from 'convex/values';
4
4
  import { unsafeConvexAnyApi } from '@lucern/contracts/convex/unsafeAnyApi';
5
5
  import { componentsGeneric, mutationGeneric } from 'convex/server';
6
+ import { isUuidV7 } from '@lucern/contracts/ids';
6
7
 
7
8
  // src/epistemicEdges.mutations.ts
8
9
  var unsafeApi = unsafeConvexAnyApi(
@@ -1076,6 +1077,8 @@ function resolveGraphPrimitivesAppResolvers(_ctx) {
1076
1077
  ...resolverOverrides
1077
1078
  };
1078
1079
  }
1080
+
1081
+ // src/topicScope.ts
1079
1082
  var LEGACY_SCOPE_FIELD2 = "graphScopeProjectId";
1080
1083
  async function resolveTopicNodeScopeOrNull(ctx, ref) {
1081
1084
  if (!ctx?.db || typeof ctx.db.query !== "function") {
@@ -1096,16 +1099,36 @@ async function resolveTopicNodeScopeOrNull(ctx, ref) {
1096
1099
  if (!node) {
1097
1100
  return null;
1098
1101
  }
1099
- const scopeKey = normalizeScopeValue(node.topicId) ?? normalizeScopeValue(node.globalId);
1102
+ const scopeKey = canonicalTopicGlobalId(node);
1100
1103
  if (!scopeKey) {
1101
- return null;
1104
+ throw new Error(
1105
+ `topic.uuidv7_identity_required: topic node ${ref} is missing a UUIDv7 globalId.`
1106
+ );
1102
1107
  }
1108
+ const metadata = node.metadata ?? {};
1103
1109
  return {
1104
1110
  topicId: scopeKey,
1105
1111
  projectId: asMappedProjectId(node),
1106
- source: "topic_node"
1112
+ source: "topic_node",
1113
+ tenantId: normalizeScopeValue(node.tenantId) ?? normalizeScopeValue(metadata.tenantId),
1114
+ workspaceId: normalizeScopeValue(node.workspaceId) ?? normalizeScopeValue(metadata.workspaceId)
1107
1115
  };
1108
1116
  }
1117
+ function canonicalTopicGlobalId(node) {
1118
+ const globalId = normalizeScopeValue(node.globalId);
1119
+ if (globalId && isUuidV7(globalId)) {
1120
+ return globalId;
1121
+ }
1122
+ const topicId = normalizeScopeValue(node.topicId);
1123
+ return topicId && isUuidV7(topicId) ? topicId : null;
1124
+ }
1125
+ function requireUuidV7TopicScope(field, value) {
1126
+ if (!isUuidV7(value)) {
1127
+ throw new Error(
1128
+ `topic.uuidv7_required: ${field} must be a UUIDv7 public topic identifier.`
1129
+ );
1130
+ }
1131
+ }
1109
1132
  function asMappedProjectId(topic) {
1110
1133
  if (!topic) {
1111
1134
  return;
@@ -1127,200 +1150,25 @@ function normalizeScopeValue(value) {
1127
1150
  const normalized = value.trim();
1128
1151
  return normalized.length > 0 ? normalized : void 0;
1129
1152
  }
1130
- function pickPrimaryTopic(candidates) {
1131
- return [...candidates].sort((a, b) => {
1132
- const depthA = a.depth ?? 9999;
1133
- const depthB = b.depth ?? 9999;
1134
- if (depthA !== depthB) {
1135
- return depthA - depthB;
1136
- }
1137
- const createdA = a.createdAt ?? Number.MAX_SAFE_INTEGER;
1138
- const createdB = b.createdAt ?? Number.MAX_SAFE_INTEGER;
1139
- if (createdA !== createdB) {
1140
- return createdA - createdB;
1141
- }
1142
- return String(a.name || "").localeCompare(String(b.name || ""));
1143
- })[0];
1144
- }
1145
- async function findTopicsByScopeAlias(ctx, scopeId) {
1146
- const query = ctx.db.query("topics");
1147
- try {
1148
- return await query.withIndex(
1149
- "by_graph_scope_project",
1150
- (q) => q.eq(LEGACY_SCOPE_FIELD2, scopeId)
1151
- ).collect();
1152
- } catch (error) {
1153
- debugGraphPrimitiveFallback(
1154
- "[topicScope] Failed to resolve scope alias via index",
1155
- {
1156
- error,
1157
- scopeId
1158
- }
1159
- );
1160
- const topics = await query.collect();
1161
- return topics.filter((topic) => {
1162
- const normalizedGlobalId = normalizeScopeValue(topic.globalId);
1163
- const mappedProjectId = asMappedProjectId(topic);
1164
- return String(topic._id) === scopeId || normalizedGlobalId === scopeId || mappedProjectId === scopeId;
1165
- });
1166
- }
1167
- }
1168
- async function tryResolveHostTopicById(ctx, topicId) {
1169
- if (typeof ctx.runQuery !== "function") {
1170
- return null;
1171
- }
1172
- try {
1173
- return await ctx.runQuery(api.topics.get, {
1174
- id: topicId
1175
- }) ?? null;
1176
- } catch (error) {
1177
- debugGraphPrimitiveFallback(
1178
- "[topicScope] Failed to resolve topic by host query",
1179
- {
1180
- error,
1181
- topicId
1182
- }
1183
- );
1184
- return null;
1185
- }
1186
- }
1187
- async function tryResolveHostTopicByLegacyScope(ctx, legacyScopeId) {
1188
- if (typeof ctx.runQuery !== "function") {
1189
- return null;
1190
- }
1191
- try {
1192
- return await ctx.runQuery(api.topics.getByLegacyScopeId, {
1193
- projectId: legacyScopeId
1194
- }) ?? null;
1195
- } catch (error) {
1196
- debugGraphPrimitiveFallback(
1197
- "[topicScope] Failed to resolve topic by legacy scope",
1198
- {
1199
- error,
1200
- legacyScopeId
1201
- }
1202
- );
1203
- return null;
1204
- }
1205
- }
1206
- async function resolveInheritedWorkspaceScope(ctx, topic) {
1207
- const MAX_DEPTH = 10;
1208
- let tenantId = normalizeScopeValue(topic.tenantId);
1209
- let workspaceId = normalizeScopeValue(topic.workspaceId);
1210
- if (tenantId && workspaceId) {
1211
- return { tenantId, workspaceId };
1212
- }
1213
- let current = topic;
1214
- for (let i = 0; i < MAX_DEPTH && current?.parentTopicId; i++) {
1215
- current = await ctx.db.get(current.parentTopicId);
1216
- if (!current) {
1217
- break;
1218
- }
1219
- if (!tenantId) {
1220
- tenantId = normalizeScopeValue(current.tenantId);
1221
- }
1222
- if (!workspaceId) {
1223
- workspaceId = normalizeScopeValue(current.workspaceId);
1224
- }
1225
- if (tenantId && workspaceId) {
1226
- break;
1227
- }
1228
- }
1229
- return { tenantId, workspaceId };
1230
- }
1231
1153
  async function resolveTopicProjectScope(ctx, args) {
1232
1154
  if (args.topicId) {
1233
1155
  return await resolveScopeFromTopicId(ctx, args.topicId);
1234
1156
  }
1235
1157
  if (args.projectId) {
1236
- return await resolveScopeFromLegacyProjectId(ctx, args.projectId);
1158
+ throw new Error(
1159
+ "topic.uuidv7_required: projectId scope aliases are retired; pass topicId as the UUIDv7 topic globalId."
1160
+ );
1237
1161
  }
1238
- throw new Error(
1239
- "Missing scope: provide topicId (preferred) or legacy projectId alias."
1240
- );
1162
+ throw new Error("topic.uuidv7_required: Missing scope: provide topicId.");
1241
1163
  }
1242
1164
  async function resolveScopeFromTopicId(ctx, topicId) {
1243
- const topic = await resolveTopicDocFromTopicId(ctx, topicId);
1244
- if (topic) {
1245
- return await buildTopicScope(ctx, topic, "topic");
1246
- }
1247
- const nodeScope = await resolveTopicNodeScopeOrNull(ctx, String(topicId));
1165
+ const topicGlobalId = String(topicId);
1166
+ requireUuidV7TopicScope("topicId", topicGlobalId);
1167
+ const nodeScope = await resolveTopicNodeScopeOrNull(ctx, topicGlobalId);
1248
1168
  if (nodeScope) {
1249
1169
  return nodeScope;
1250
1170
  }
1251
- throw new Error(`Topic not found: ${String(topicId)}`);
1252
- }
1253
- async function resolveTopicDocFromTopicId(ctx, topicId) {
1254
- const direct = await tryReadTopicDoc(ctx, topicId, {
1255
- failureLog: "[topicScope] Failed to load topic by direct id",
1256
- idLogKey: "topicId"
1257
- });
1258
- if (direct) {
1259
- return direct;
1260
- }
1261
- const hostTopic = await tryResolveHostTopicById(ctx, String(topicId));
1262
- if (hostTopic) {
1263
- return hostTopic;
1264
- }
1265
- return pickPrimaryTopic(await findTopicsByScopeAlias(ctx, String(topicId))) ?? null;
1266
- }
1267
- async function resolveScopeFromLegacyProjectId(ctx, legacyProjectId) {
1268
- const directTopic = await resolveDirectLegacyProjectTopic(
1269
- ctx,
1270
- legacyProjectId
1271
- );
1272
- if (directTopic) {
1273
- return await buildTopicScope(ctx, directTopic, "topic_inferred", {
1274
- fallbackProjectId: legacyProjectId
1275
- });
1276
- }
1277
- const primary = pickPrimaryTopic(
1278
- await findTopicsByScopeAlias(ctx, legacyProjectId)
1279
- );
1280
- if (primary) {
1281
- return await buildTopicScope(ctx, primary, "project_mapped_topic", {
1282
- fallbackProjectId: legacyProjectId
1283
- });
1284
- }
1285
- const nodeScope = await resolveTopicNodeScopeOrNull(ctx, legacyProjectId);
1286
- if (nodeScope) {
1287
- return {
1288
- ...nodeScope,
1289
- projectId: nodeScope.projectId ?? legacyProjectId
1290
- };
1291
- }
1292
- throw new Error(
1293
- `Legacy project scope ${legacyProjectId} has no mapped topic.`
1294
- );
1295
- }
1296
- async function resolveDirectLegacyProjectTopic(ctx, legacyProjectId) {
1297
- const directTopic = await tryReadTopicDoc(ctx, legacyProjectId, {
1298
- failureLog: "[topicScope] Failed to load direct project topic",
1299
- idLogKey: "projectId"
1300
- });
1301
- return directTopic ?? tryResolveHostTopicByLegacyScope(ctx, legacyProjectId);
1302
- }
1303
- async function tryReadTopicDoc(ctx, id, log) {
1304
- try {
1305
- return await ctx.db.get(id);
1306
- } catch (error) {
1307
- debugGraphPrimitiveFallback(log.failureLog, {
1308
- error,
1309
- [log.idLogKey]: id
1310
- });
1311
- return null;
1312
- }
1313
- }
1314
- async function buildTopicScope(ctx, topic, source, options = {}) {
1315
- const inherited = await resolveInheritedWorkspaceScope(ctx, topic);
1316
- const mapped = asMappedProjectId(topic);
1317
- return {
1318
- topicId: topic._id,
1319
- ...mapped || options.fallbackProjectId ? { projectId: mapped ?? options.fallbackProjectId } : {},
1320
- tenantId: inherited.tenantId,
1321
- workspaceId: inherited.workspaceId,
1322
- source
1323
- };
1171
+ throw new Error(`Topic not found: ${topicGlobalId}`);
1324
1172
  }
1325
1173
  var optionalScopeArgs = {
1326
1174
  projectId: v.optional(v.string()),
@@ -3,12 +3,12 @@ import { permissiveReturn } from '@lucern/contracts/schema-helpers/validators';
3
3
  import { v } from 'convex/values';
4
4
  import { unsafeConvexAnyApi } from '@lucern/contracts/convex/unsafeAnyApi';
5
5
  import { componentsGeneric, queryGeneric } from 'convex/server';
6
+ import { isUuidV7 } from '@lucern/contracts/ids';
6
7
 
7
8
  // src/epistemicEdges.queries.ts
8
- var unsafeApi = unsafeConvexAnyApi(
9
+ unsafeConvexAnyApi(
9
10
  "graph-primitives top-level module bundle lacks a committed Convex _generated/api surface"
10
11
  );
11
- var api = unsafeApi;
12
12
  componentsGeneric();
13
13
  var query = queryGeneric;
14
14
 
@@ -275,6 +275,8 @@ async function collectScopedEdges(ctx, scope, scanLimit) {
275
275
  }
276
276
  return deduped;
277
277
  }
278
+
279
+ // src/topicScope.ts
278
280
  var LEGACY_SCOPE_FIELD = "graphScopeProjectId";
279
281
  async function resolveTopicNodeScopeOrNull(ctx, ref) {
280
282
  if (!ctx?.db || typeof ctx.db.query !== "function") {
@@ -295,16 +297,36 @@ async function resolveTopicNodeScopeOrNull(ctx, ref) {
295
297
  if (!node) {
296
298
  return null;
297
299
  }
298
- const scopeKey = normalizeScopeValue(node.topicId) ?? normalizeScopeValue(node.globalId);
300
+ const scopeKey = canonicalTopicGlobalId(node);
299
301
  if (!scopeKey) {
300
- return null;
302
+ throw new Error(
303
+ `topic.uuidv7_identity_required: topic node ${ref} is missing a UUIDv7 globalId.`
304
+ );
301
305
  }
306
+ const metadata = node.metadata ?? {};
302
307
  return {
303
308
  topicId: scopeKey,
304
309
  projectId: asMappedProjectId(node),
305
- source: "topic_node"
310
+ source: "topic_node",
311
+ tenantId: normalizeScopeValue(node.tenantId) ?? normalizeScopeValue(metadata.tenantId),
312
+ workspaceId: normalizeScopeValue(node.workspaceId) ?? normalizeScopeValue(metadata.workspaceId)
306
313
  };
307
314
  }
315
+ function canonicalTopicGlobalId(node) {
316
+ const globalId = normalizeScopeValue(node.globalId);
317
+ if (globalId && isUuidV7(globalId)) {
318
+ return globalId;
319
+ }
320
+ const topicId = normalizeScopeValue(node.topicId);
321
+ return topicId && isUuidV7(topicId) ? topicId : null;
322
+ }
323
+ function requireUuidV7TopicScope(field, value) {
324
+ if (!isUuidV7(value)) {
325
+ throw new Error(
326
+ `topic.uuidv7_required: ${field} must be a UUIDv7 public topic identifier.`
327
+ );
328
+ }
329
+ }
308
330
  function asMappedProjectId(topic) {
309
331
  if (!topic) {
310
332
  return;
@@ -326,200 +348,25 @@ function normalizeScopeValue(value) {
326
348
  const normalized = value.trim();
327
349
  return normalized.length > 0 ? normalized : void 0;
328
350
  }
329
- function pickPrimaryTopic(candidates) {
330
- return [...candidates].sort((a, b) => {
331
- const depthA = a.depth ?? 9999;
332
- const depthB = b.depth ?? 9999;
333
- if (depthA !== depthB) {
334
- return depthA - depthB;
335
- }
336
- const createdA = a.createdAt ?? Number.MAX_SAFE_INTEGER;
337
- const createdB = b.createdAt ?? Number.MAX_SAFE_INTEGER;
338
- if (createdA !== createdB) {
339
- return createdA - createdB;
340
- }
341
- return String(a.name || "").localeCompare(String(b.name || ""));
342
- })[0];
343
- }
344
- async function findTopicsByScopeAlias(ctx, scopeId) {
345
- const query2 = ctx.db.query("topics");
346
- try {
347
- return await query2.withIndex(
348
- "by_graph_scope_project",
349
- (q) => q.eq(LEGACY_SCOPE_FIELD, scopeId)
350
- ).collect();
351
- } catch (error) {
352
- debugGraphPrimitiveFallback(
353
- "[topicScope] Failed to resolve scope alias via index",
354
- {
355
- error,
356
- scopeId
357
- }
358
- );
359
- const topics = await query2.collect();
360
- return topics.filter((topic) => {
361
- const normalizedGlobalId = normalizeScopeValue(topic.globalId);
362
- const mappedProjectId = asMappedProjectId(topic);
363
- return String(topic._id) === scopeId || normalizedGlobalId === scopeId || mappedProjectId === scopeId;
364
- });
365
- }
366
- }
367
- async function tryResolveHostTopicById(ctx, topicId) {
368
- if (typeof ctx.runQuery !== "function") {
369
- return null;
370
- }
371
- try {
372
- return await ctx.runQuery(api.topics.get, {
373
- id: topicId
374
- }) ?? null;
375
- } catch (error) {
376
- debugGraphPrimitiveFallback(
377
- "[topicScope] Failed to resolve topic by host query",
378
- {
379
- error,
380
- topicId
381
- }
382
- );
383
- return null;
384
- }
385
- }
386
- async function tryResolveHostTopicByLegacyScope(ctx, legacyScopeId) {
387
- if (typeof ctx.runQuery !== "function") {
388
- return null;
389
- }
390
- try {
391
- return await ctx.runQuery(api.topics.getByLegacyScopeId, {
392
- projectId: legacyScopeId
393
- }) ?? null;
394
- } catch (error) {
395
- debugGraphPrimitiveFallback(
396
- "[topicScope] Failed to resolve topic by legacy scope",
397
- {
398
- error,
399
- legacyScopeId
400
- }
401
- );
402
- return null;
403
- }
404
- }
405
- async function resolveInheritedWorkspaceScope(ctx, topic) {
406
- const MAX_DEPTH = 10;
407
- let tenantId = normalizeScopeValue(topic.tenantId);
408
- let workspaceId = normalizeScopeValue(topic.workspaceId);
409
- if (tenantId && workspaceId) {
410
- return { tenantId, workspaceId };
411
- }
412
- let current = topic;
413
- for (let i = 0; i < MAX_DEPTH && current?.parentTopicId; i++) {
414
- current = await ctx.db.get(current.parentTopicId);
415
- if (!current) {
416
- break;
417
- }
418
- if (!tenantId) {
419
- tenantId = normalizeScopeValue(current.tenantId);
420
- }
421
- if (!workspaceId) {
422
- workspaceId = normalizeScopeValue(current.workspaceId);
423
- }
424
- if (tenantId && workspaceId) {
425
- break;
426
- }
427
- }
428
- return { tenantId, workspaceId };
429
- }
430
351
  async function resolveTopicProjectScope(ctx, args) {
431
352
  if (args.topicId) {
432
353
  return await resolveScopeFromTopicId(ctx, args.topicId);
433
354
  }
434
355
  if (args.projectId) {
435
- return await resolveScopeFromLegacyProjectId(ctx, args.projectId);
356
+ throw new Error(
357
+ "topic.uuidv7_required: projectId scope aliases are retired; pass topicId as the UUIDv7 topic globalId."
358
+ );
436
359
  }
437
- throw new Error(
438
- "Missing scope: provide topicId (preferred) or legacy projectId alias."
439
- );
360
+ throw new Error("topic.uuidv7_required: Missing scope: provide topicId.");
440
361
  }
441
362
  async function resolveScopeFromTopicId(ctx, topicId) {
442
- const topic = await resolveTopicDocFromTopicId(ctx, topicId);
443
- if (topic) {
444
- return await buildTopicScope(ctx, topic, "topic");
445
- }
446
- const nodeScope = await resolveTopicNodeScopeOrNull(ctx, String(topicId));
363
+ const topicGlobalId = String(topicId);
364
+ requireUuidV7TopicScope("topicId", topicGlobalId);
365
+ const nodeScope = await resolveTopicNodeScopeOrNull(ctx, topicGlobalId);
447
366
  if (nodeScope) {
448
367
  return nodeScope;
449
368
  }
450
- throw new Error(`Topic not found: ${String(topicId)}`);
451
- }
452
- async function resolveTopicDocFromTopicId(ctx, topicId) {
453
- const direct = await tryReadTopicDoc(ctx, topicId, {
454
- failureLog: "[topicScope] Failed to load topic by direct id",
455
- idLogKey: "topicId"
456
- });
457
- if (direct) {
458
- return direct;
459
- }
460
- const hostTopic = await tryResolveHostTopicById(ctx, String(topicId));
461
- if (hostTopic) {
462
- return hostTopic;
463
- }
464
- return pickPrimaryTopic(await findTopicsByScopeAlias(ctx, String(topicId))) ?? null;
465
- }
466
- async function resolveScopeFromLegacyProjectId(ctx, legacyProjectId) {
467
- const directTopic = await resolveDirectLegacyProjectTopic(
468
- ctx,
469
- legacyProjectId
470
- );
471
- if (directTopic) {
472
- return await buildTopicScope(ctx, directTopic, "topic_inferred", {
473
- fallbackProjectId: legacyProjectId
474
- });
475
- }
476
- const primary = pickPrimaryTopic(
477
- await findTopicsByScopeAlias(ctx, legacyProjectId)
478
- );
479
- if (primary) {
480
- return await buildTopicScope(ctx, primary, "project_mapped_topic", {
481
- fallbackProjectId: legacyProjectId
482
- });
483
- }
484
- const nodeScope = await resolveTopicNodeScopeOrNull(ctx, legacyProjectId);
485
- if (nodeScope) {
486
- return {
487
- ...nodeScope,
488
- projectId: nodeScope.projectId ?? legacyProjectId
489
- };
490
- }
491
- throw new Error(
492
- `Legacy project scope ${legacyProjectId} has no mapped topic.`
493
- );
494
- }
495
- async function resolveDirectLegacyProjectTopic(ctx, legacyProjectId) {
496
- const directTopic = await tryReadTopicDoc(ctx, legacyProjectId, {
497
- failureLog: "[topicScope] Failed to load direct project topic",
498
- idLogKey: "projectId"
499
- });
500
- return directTopic ?? tryResolveHostTopicByLegacyScope(ctx, legacyProjectId);
501
- }
502
- async function tryReadTopicDoc(ctx, id, log) {
503
- try {
504
- return await ctx.db.get(id);
505
- } catch (error) {
506
- debugGraphPrimitiveFallback(log.failureLog, {
507
- error,
508
- [log.idLogKey]: id
509
- });
510
- return null;
511
- }
512
- }
513
- async function buildTopicScope(ctx, topic, source, options = {}) {
514
- const inherited = await resolveInheritedWorkspaceScope(ctx, topic);
515
- const mapped = asMappedProjectId(topic);
516
- return {
517
- topicId: topic._id,
518
- ...mapped || options.fallbackProjectId ? { projectId: mapped ?? options.fallbackProjectId } : {},
519
- tenantId: inherited.tenantId,
520
- workspaceId: inherited.workspaceId,
521
- source
522
- };
369
+ throw new Error(`Topic not found: ${topicGlobalId}`);
523
370
  }
524
371
  var optionalScopeArgs = {
525
372
  projectId: v.optional(v.string()),
@@ -1,5 +1,5 @@
1
1
  import { Id } from './convex.js';
2
- import { r as resolveTopicProjectScope } from './topicScope-DJVa0mLa.js';
2
+ import { r as resolveTopicProjectScope } from './topicScope-CL1IVOmv.js';
3
3
  import '@lucern/access-control/convex';
4
4
  import '@lucern/contracts/convex/unsafeAnyApi';
5
5
  import 'convex/values';
@@ -2,7 +2,7 @@ export { flattenEvidenceNode, resolveEvidenceLinkedWorktreeId } from './epistemi
2
2
  export { create, createAndLink, flagAsIncorrect, internalCreate, remove, update, updateStatus, updateVerificationStatus } from './epistemicEvidenceMutations.js';
3
3
  export { getById, getByProject, getByProjectSystem, getByTopic, getEvidenceBalance, getForBelief, internalGetByProject, internalGetByTopic } from './epistemicEvidenceQueries.js';
4
4
  import '@lucern/access-control/convex.js';
5
- import './topicScope-DJVa0mLa.js';
5
+ import './topicScope-CL1IVOmv.js';
6
6
  import 'convex/values';
7
7
  import './convex.js';
8
8
  import '@lucern/access-control/convex';