@lucern/graph-primitives 1.0.23 → 1.0.24

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/beliefDecay.js +3 -0
  2. package/dist/beliefDecay.js.map +1 -1
  3. package/dist/beliefEvidenceLinks.js +15 -3
  4. package/dist/beliefEvidenceLinks.js.map +1 -1
  5. package/dist/beliefEvidenceLinks.operational.js +12 -3
  6. package/dist/beliefEvidenceLinks.operational.js.map +1 -1
  7. package/dist/entityCanonicalMatch.d.ts +40 -0
  8. package/dist/entityCanonicalMatch.js +33 -0
  9. package/dist/entityCanonicalMatch.js.map +1 -0
  10. package/dist/entityLifecycle.js +62 -37
  11. package/dist/entityLifecycle.js.map +1 -1
  12. package/dist/epistemicAnswers.js.map +1 -1
  13. package/dist/epistemicBeliefs.admin.js +17 -6
  14. package/dist/epistemicBeliefs.admin.js.map +1 -1
  15. package/dist/epistemicBeliefs.backfills.js +13 -2
  16. package/dist/epistemicBeliefs.backfills.js.map +1 -1
  17. package/dist/epistemicBeliefs.confidence.js +17 -6
  18. package/dist/epistemicBeliefs.confidence.js.map +1 -1
  19. package/dist/epistemicBeliefs.core.js +32 -9
  20. package/dist/epistemicBeliefs.core.js.map +1 -1
  21. package/dist/epistemicBeliefs.forkEvidence.js +13 -2
  22. package/dist/epistemicBeliefs.forkEvidence.js.map +1 -1
  23. package/dist/epistemicBeliefs.helpers.d.ts +16 -1
  24. package/dist/epistemicBeliefs.helpers.js +20 -6
  25. package/dist/epistemicBeliefs.helpers.js.map +1 -1
  26. package/dist/epistemicBeliefs.internal.js +28 -5
  27. package/dist/epistemicBeliefs.internal.js.map +1 -1
  28. package/dist/epistemicBeliefs.js +32 -9
  29. package/dist/epistemicBeliefs.js.map +1 -1
  30. package/dist/epistemicBeliefs.lifecycle.js +17 -6
  31. package/dist/epistemicBeliefs.lifecycle.js.map +1 -1
  32. package/dist/epistemicBeliefs.links.js +29 -9
  33. package/dist/epistemicBeliefs.links.js.map +1 -1
  34. package/dist/epistemicBeliefs.topicAnchor.js +12 -3
  35. package/dist/epistemicBeliefs.topicAnchor.js.map +1 -1
  36. package/dist/epistemicContracts.evaluators.js +17 -6
  37. package/dist/epistemicContracts.evaluators.js.map +1 -1
  38. package/dist/epistemicContracts.handlers.js +17 -6
  39. package/dist/epistemicContracts.handlers.js.map +1 -1
  40. package/dist/epistemicContracts.js +17 -6
  41. package/dist/epistemicContracts.js.map +1 -1
  42. package/dist/epistemicEdges.handlers.js +12 -3
  43. package/dist/epistemicEdges.handlers.js.map +1 -1
  44. package/dist/epistemicEdges.helpers.d.ts +2 -2
  45. package/dist/epistemicEdges.js +15 -3
  46. package/dist/epistemicEdges.js.map +1 -1
  47. package/dist/epistemicEdges.mutations.js +3 -0
  48. package/dist/epistemicEdges.mutations.js.map +1 -1
  49. package/dist/epistemicEvidence.js +15 -3
  50. package/dist/epistemicEvidence.js.map +1 -1
  51. package/dist/epistemicEvidenceHelpers.js +3 -0
  52. package/dist/epistemicEvidenceHelpers.js.map +1 -1
  53. package/dist/epistemicEvidenceMutations.js +15 -3
  54. package/dist/epistemicEvidenceMutations.js.map +1 -1
  55. package/dist/epistemicEvidenceQueries.js +3 -0
  56. package/dist/epistemicEvidenceQueries.js.map +1 -1
  57. package/dist/epistemicHelpers.js.map +1 -1
  58. package/dist/epistemicInsert.js +12 -3
  59. package/dist/epistemicInsert.js.map +1 -1
  60. package/dist/epistemicNodeCreation.js.map +1 -1
  61. package/dist/epistemicNodes.internal.js.map +1 -1
  62. package/dist/epistemicNodes.js.map +1 -1
  63. package/dist/epistemicNodes.mutations.js.map +1 -1
  64. package/dist/epistemicNodes.validators.d.ts +2 -2
  65. package/dist/epistemicQuestions.conviction.js +3 -0
  66. package/dist/epistemicQuestions.conviction.js.map +1 -1
  67. package/dist/epistemicQuestions.create.js +3 -0
  68. package/dist/epistemicQuestions.create.js.map +1 -1
  69. package/dist/epistemicQuestions.evidence.js +3 -0
  70. package/dist/epistemicQuestions.evidence.js.map +1 -1
  71. package/dist/epistemicQuestions.helpers.js +3 -0
  72. package/dist/epistemicQuestions.helpers.js.map +1 -1
  73. package/dist/epistemicQuestions.js +3 -0
  74. package/dist/epistemicQuestions.js.map +1 -1
  75. package/dist/epistemicQuestions.lifecycle.js +3 -0
  76. package/dist/epistemicQuestions.lifecycle.js.map +1 -1
  77. package/dist/epistemicQuestions.queries.js +3 -0
  78. package/dist/epistemicQuestions.queries.js.map +1 -1
  79. package/dist/epistemicQuestions.tail.js +3 -0
  80. package/dist/epistemicQuestions.tail.js.map +1 -1
  81. package/dist/epistemicSources.js.map +1 -1
  82. package/dist/index.js +78 -42
  83. package/dist/index.js.map +1 -1
  84. package/dist/proof-attestation.json +1 -1
  85. package/dist/questionEvidenceLinks.js +3 -0
  86. package/dist/questionEvidenceLinks.js.map +1 -1
  87. package/dist/resolvers.js +3 -0
  88. package/dist/resolvers.js.map +1 -1
  89. package/dist/topicProjectOverlay.d.ts +4 -0
  90. package/dist/topicProjectOverlay.js +3 -0
  91. package/dist/topicProjectOverlay.js.map +1 -1
  92. package/package.json +4 -4
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/convex.ts","../src/debug.ts","../src/embeddingTrigger.ts","../src/topicScope.ts","../src/workspaceIsolation.ts","../src/epistemicInsert.ts","../src/epistemicSources.ts"],"names":["normalizeScopeValue","v","nextMetadata","title"],"mappings":";;;;;;;;;AAaO,IAAM,GAAA,GAAM,MAAA;AACO,iBAAA;AACnB,IAAM,QAAA,GAAW,MAAA;AAyGjB,IAAM,QAAA,GACX,eAAA;AACK,IAAM,KAAA,GAAQ,YAAA;;;ACpHrB,SAAS,4BAAA,GAAwC;AAC/C,EAAA,MAAM,GAAA,GAAO,WAA8C,OAAA,EAAS,GAAA;AACpE,EAAA,OACE,GAAA,EAAK,4BAAA,KAAiC,GAAA,IACtC,GAAA,EAAK,kBAAA,KAAuB,GAAA;AAEhC;AAsBO,SAAS,2BAAA,CACd,SACA,OAAA,EACM;AACN,EAAA,IAAI,CAAC,8BAA6B,EAAG;AACnC,IAAA;AAAA,EACF;AACA,EAAA,OAAA,CAAQ,KAAA,CAAM,OAAA,EAAS,OAAA,IAAW,EAAE,CAAA;AACtC;;;ACbA,eAAsB,4BACpB,IAAA,EACe;AACf,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,CAAK,IAAI,SAAA,CAAU,QAAA;AAAA,MACvB,CAAA;AAAA,MACA,iDAAA;AAAA,MACA;AAAA,QACE,QAAQ,IAAA,CAAK,MAAA;AAAA,QACb,WAAW,IAAA,CAAK,SAAA,GAAY,MAAA,CAAO,IAAA,CAAK,SAAS,CAAA,GAAI,KAAA,CAAA;AAAA,QACrD,SAAS,IAAA,CAAK,OAAA,GAAU,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA,GAAI,KAAA,CAAA;AAAA,QAC/C,WAAW,IAAA,CAAK,SAAA;AAAA,QAChB,UAAU,IAAA,CAAK,QAAA;AAAA,QACf,IAAA,EAAM,IAAA,CAAK,IAAA,CAAK,KAAA,CAAM,GAAG,GAAM,CAAA;AAAA,QAC/B,WAAW,IAAA,CAAK,SAAA;AAAA,QAChB,YAAY,IAAA,CAAK;AAAA;AACnB,KACF;AAAA,EACF,SAAS,KAAA,EAAO;AACd,IAAA,2BAAA;AAAA,MACE,4DAAA;AAAA,MACA;AAAA,QACE,KAAA;AAAA,QACA,MAAA,EAAQ,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA;AAAA,QAC1B,UAAU,IAAA,CAAK;AAAA;AACjB,KACF;AAAA,EAEF;AACF;ACpDA,IAAM,kBAAA,GAAqB,qBAAA;AA6C3B,eAAe,2BAAA,CACb,KACA,GAAA,EACmC;AACnC,EAAA,IAAI,CAAC,GAAA,EAAK,EAAA,IAAM,OAAO,GAAA,CAAI,EAAA,CAAG,UAAU,UAAA,EAAY;AAClD,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,IAAI,IAAA,GAAiC,IAAA;AAGrC,EAAA,IAAI;AACF,IAAA,MAAM,aAAc,MAAM,GAAA,CAAI,EAAA,CAC3B,KAAA,CAAM,gBAAgB,CAAA,CACtB,SAAA,CAAU,aAAA,EAAe,CAAC,MAAW,CAAA,CAAE,EAAA,CAAG,YAAY,GAAG,CAAC,EAC1D,KAAA,EAAM;AACT,IAAA,IAAI,UAAA,IAAc,UAAA,CAAW,QAAA,KAAa,OAAA,EAAS;AACjD,MAAA,IAAA,GAAO,UAAA;AAAA,IACT;AAAA,EACF,SAAS,KAAA,EAAO;AACd,IAAA,2BAAA;AAAA,MACE,yDAAA;AAAA,MACA,EAAE,OAAO,GAAA;AAAI,KACf;AAAA,EACF;AAEA,EAAA,IAAI,CAAC,IAAA,EAAM;AACT,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,WACJ,mBAAA,CAAoB,IAAA,CAAK,OAAO,CAAA,IAAK,mBAAA,CAAoB,KAAK,QAAQ,CAAA;AACxE,EAAA,IAAI,CAAC,QAAA,EAAU;AACb,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,QAAA;AAAA,IACT,SAAA,EAAW,kBAAkB,IAA2B,CAAA;AAAA,IACxD,MAAA,EAAQ;AAAA,GACV;AACF;AAOA,SAAS,kBACP,KAAA,EACoB;AACpB,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA;AAAA,EACF;AACA,EAAA,MAAM,qBAAA,GAAwB,mBAAA,CAAoB,KAAA,CAAM,kBAAkB,CAAC,CAAA;AAC3E,EAAA,IAAI,qBAAA,EAAuB;AACzB,IAAA,OAAO,qBAAA;AAAA,EACT;AACA,EAAA,MAAM,QAAA,GAAY,KAAA,CAAM,QAAA,IAAY,EAAC;AACrC,EAAA,MAAM,SAAA,GACH,SAAS,kBAAkB,CAAA,IAC3B,SAAS,eAAA,IACT,QAAA,CAAS,aACT,QAAA,CAAS,cAAA;AACZ,EAAA,OAAO,YAAa,SAAA,GAAuB,MAAA;AAC7C;AAEA,SAAS,oBAAoB,KAAA,EAAoC;AAC/D,EAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,IAAA;AAAA,EACF;AACA,EAAA,MAAM,UAAA,GAAa,MAAM,IAAA,EAAK;AAC9B,EAAA,OAAO,UAAA,CAAW,MAAA,GAAS,CAAA,GAAI,UAAA,GAAa,MAAA;AAC9C;AAEA,SAAS,iBAAiB,UAAA,EAA8C;AACtE,EAAA,OAAO,CAAC,GAAG,UAAU,EAAE,IAAA,CAAK,CAAC,GAAG,CAAA,KAAM;AACpC,IAAA,MAAM,MAAA,GAAS,EAAE,KAAA,IAAS,IAAA;AAC1B,IAAA,MAAM,MAAA,GAAS,EAAE,KAAA,IAAS,IAAA;AAC1B,IAAA,IAAI,WAAW,MAAA,EAAQ;AACrB,MAAA,OAAO,MAAA,GAAS,MAAA;AAAA,IAClB;AACA,IAAA,MAAM,QAAA,GAAW,CAAA,CAAE,SAAA,IAAa,MAAA,CAAO,gBAAA;AACvC,IAAA,MAAM,QAAA,GAAW,CAAA,CAAE,SAAA,IAAa,MAAA,CAAO,gBAAA;AACvC,IAAA,IAAI,aAAa,QAAA,EAAU;AACzB,MAAA,OAAO,QAAA,GAAW,QAAA;AAAA,IACpB;AACA,IAAA,OAAO,MAAA,CAAO,CAAA,CAAE,IAAA,IAAQ,EAAE,CAAA,CAAE,cAAc,MAAA,CAAO,CAAA,CAAE,IAAA,IAAQ,EAAE,CAAC,CAAA;AAAA,EAChE,CAAC,EAAE,CAAC,CAAA;AACN;AAEA,eAAe,sBAAA,CACb,KACA,OAAA,EACqB;AACrB,EAAA,IAAI;AACF,IAAA,OAAQ,MAAM,GAAA,CAAI,EAAA,CACf,KAAA,CAAM,QAAQ,CAAA,CACd,SAAA;AAAA,MAAU,wBAAA;AAAA,MAA0B,CAAC,CAAA,KACpC,CAAA,CAAE,EAAA,CAAG,oBAAoB,OAAO;AAAA,MAEjC,OAAA,EAAQ;AAAA,EACb,SAAS,KAAA,EAAO;AACd,IAAA,2BAAA;AAAA,MACE,sDAAA;AAAA,MACA;AAAA,QACE,KAAA;AAAA,QACA;AAAA;AACF,KACF;AAIA,IAAA,MAAM,SAAU,MAAM,GAAA,CAAI,GAAG,KAAA,CAAM,QAAQ,EAAE,OAAA,EAAQ;AACrD,IAAA,OAAO,MAAA,CAAO,MAAA,CAAO,CAAC,KAAA,KAAU;AAC9B,MAAA,MAAM,kBAAA,GAAqB,mBAAA,CAAoB,KAAA,CAAM,QAAQ,CAAA;AAC7D,MAAA,MAAM,eAAA,GAAkB,kBAAkB,KAAK,CAAA;AAC/C,MAAA,OACE,OAAO,KAAA,CAAM,GAAG,MAAM,OAAA,IACtB,kBAAA,KAAuB,WACvB,eAAA,KAAoB,OAAA;AAAA,IAExB,CAAC,CAAA;AAAA,EACH;AACF;AAEA,eAAe,uBAAA,CACb,KACA,OAAA,EAC0B;AAC1B,EAAA,IAAI,OAAO,GAAA,CAAI,QAAA,KAAa,UAAA,EAAY;AACtC,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,IAAI;AACF,IAAA,OAAS,MAAM,GAAA,CAAI,QAAA,CAAS,GAAA,CAAO,OAAO,GAAA,EAAY;AAAA,MACpD,EAAA,EAAI;AAAA,KACL,CAAA,IAAM,IAAA;AAAA,EACT,SAAS,KAAA,EAAO;AACd,IAAA,2BAAA;AAAA,MACE,oDAAA;AAAA,MACA;AAAA,QACE,KAAA;AAAA,QACA;AAAA;AACF,KACF;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAEA,eAAe,gCAAA,CACb,KACA,aAAA,EAC0B;AAC1B,EAAA,IAAI,OAAO,GAAA,CAAI,QAAA,KAAa,UAAA,EAAY;AACtC,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,IAAI;AACF,IAAA,OAAS,MAAM,GAAA,CAAI,QAAA,CAAS,GAAA,CAAO,OAAO,kBAAA,EAA2B;AAAA,MACnE,SAAA,EAAW;AAAA,KACZ,CAAA,IAAM,IAAA;AAAA,EACT,SAAS,KAAA,EAAO;AACd,IAAA,2BAAA;AAAA,MACE,sDAAA;AAAA,MACA;AAAA,QACE,KAAA;AAAA,QACA;AAAA;AACF,KACF;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAwBA,eAAe,8BAAA,CACb,KACA,KAAA,EACsD;AACtD,EAAA,MAAM,SAAA,GAAY,EAAA;AAClB,EAAA,IAAI,QAAA,GAAW,mBAAA,CAAoB,KAAA,CAAM,QAAQ,CAAA;AACjD,EAAA,IAAI,WAAA,GAAc,mBAAA,CAAoB,KAAA,CAAM,WAAW,CAAA;AAEvD,EAAA,IAAI,YAAY,WAAA,EAAa;AAC3B,IAAA,OAAO,EAAE,UAAU,WAAA,EAAY;AAAA,EACjC;AAEA,EAAA,IAAI,OAAA,GAA2B,KAAA;AAC/B,EAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,SAAA,IAAa,OAAA,EAAS,eAAe,CAAA,EAAA,EAAK;AAC5D,IAAA,OAAA,GAAW,MAAM,GAAA,CAAI,EAAA,CAAG,GAAA,CAAI,QAAQ,aAAa,CAAA;AACjD,IAAA,IAAI,CAAC,OAAA,EAAS;AAEd,IAAA,IAAI,CAAC,QAAA,EAAU;AACb,MAAA,QAAA,GAAW,mBAAA,CAAoB,QAAQ,QAAQ,CAAA;AAAA,IACjD;AACA,IAAA,IAAI,CAAC,WAAA,EAAa;AAChB,MAAA,WAAA,GAAc,mBAAA,CAAoB,QAAQ,WAAW,CAAA;AAAA,IACvD;AACA,IAAA,IAAI,YAAY,WAAA,EAAa;AAAA,EAC/B;AAEA,EAAA,OAAO,EAAE,UAAU,WAAA,EAAY;AACjC;AAEA,eAAsB,wBAAA,CACpB,KACA,IAAA,EAC4B;AAC5B,EAAA,IAAI,KAAK,OAAA,EAAS;AAEhB,IAAA,IAAI,KAAA,GAAyB,IAAA;AAC7B,IAAA,IAAI;AACF,MAAA,KAAA,GAAS,MAAM,IAAI,EAAA,CAAG,GAAA;AAAA,QACpB,IAAA,CAAK;AAAA,OACP;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,2BAAA;AAAA,QACE,gDAAA;AAAA,QACA;AAAA,UACE,KAAA;AAAA,UACA,SAAS,IAAA,CAAK;AAAA;AAChB,OACF;AAAA,IAEF;AACA,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,KAAA,GAAQ,MAAM,uBAAA,CAAwB,GAAA,EAAK,MAAA,CAAO,IAAA,CAAK,OAAO,CAAC,CAAA;AAAA,IACjE;AACA,IAAA,IAAI,CAAC,KAAA,EAAO;AAEV,MAAA,KAAA,GACE,gBAAA;AAAA,QACE,MAAM,sBAAA,CAAuB,GAAA,EAAK,MAAA,CAAO,IAAA,CAAK,OAAO,CAAC;AAAA,OACxD,IAAK,IAAA;AAAA,IACT;AACA,IAAA,IAAI,CAAC,KAAA,EAAO;AAGV,MAAA,MAAM,YAAY,MAAM,2BAAA;AAAA,QACtB,GAAA;AAAA,QACA,MAAA,CAAO,KAAK,OAAO;AAAA,OACrB;AACA,MAAA,IAAI,SAAA,EAAW;AACb,QAAA,OAAO,SAAA;AAAA,MACT;AACA,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,iBAAA,EAAoB,OAAO,IAAA,CAAK,OAAO,CAAC,CAAA,CAAE,CAAA;AAAA,IAC5D;AACA,IAAA,MAAM,SAAA,GAAY,MAAM,8BAAA,CAA+B,GAAA,EAAK,KAAK,CAAA;AACjE,IAAA,MAAM,MAAA,GAAS,kBAAkB,KAAK,CAAA;AACtC,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,OAAO;AAAA,QACL,SAAS,KAAA,CAAM,GAAA;AAAA,QACf,SAAA,EAAW,MAAA;AAAA,QACX,UAAU,SAAA,CAAU,QAAA;AAAA,QACpB,aAAa,SAAA,CAAU,WAAA;AAAA,QACvB,MAAA,EAAQ;AAAA,OACV;AAAA,IACF;AACA,IAAA,OAAO;AAAA,MACL,SAAS,KAAA,CAAM,GAAA;AAAA,MACf,UAAU,SAAA,CAAU,QAAA;AAAA,MACpB,aAAa,SAAA,CAAU,WAAA;AAAA,MACvB,MAAA,EAAQ;AAAA,KACV;AAAA,EACF;AAEA,EAAA,IAAI,KAAK,SAAA,EAAW;AAClB,IAAA,IAAI,WAAA,GAA+B,IAAA;AACnC,IAAA,IAAI;AACF,MAAA,WAAA,GAAe,MAAM,IAAI,EAAA,CAAG,GAAA;AAAA,QAC1B,IAAA,CAAK;AAAA,OACP;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,2BAAA;AAAA,QACE,kDAAA;AAAA,QACA;AAAA,UACE,KAAA;AAAA,UACA,WAAW,IAAA,CAAK;AAAA;AAClB,OACF;AAAA,IAEF;AAEA,IAAA,IAAI,WAAA,EAAa;AACf,MAAA,MAAM,SAAA,GAAY,MAAM,8BAAA,CAA+B,GAAA,EAAK,WAAW,CAAA;AACvE,MAAA,MAAM,MAAA,GAAS,kBAAkB,WAAW,CAAA;AAC5C,MAAA,OAAO;AAAA,QACL,SAAS,WAAA,CAAY,GAAA;AAAA,QACrB,SAAA,EAAW,UAAU,IAAA,CAAK,SAAA;AAAA,QAC1B,UAAU,SAAA,CAAU,QAAA;AAAA,QACpB,aAAa,SAAA,CAAU,WAAA;AAAA,QACvB,MAAA,EAAQ;AAAA,OACV;AAAA,IACF;AAEA,IAAA,WAAA,GAAc,MAAM,gCAAA,CAAiC,GAAA,EAAK,IAAA,CAAK,SAAS,CAAA;AACxE,IAAA,IAAI,WAAA,EAAa;AACf,MAAA,MAAM,SAAA,GAAY,MAAM,8BAAA,CAA+B,GAAA,EAAK,WAAW,CAAA;AACvE,MAAA,MAAM,MAAA,GAAS,kBAAkB,WAAW,CAAA;AAC5C,MAAA,OAAO;AAAA,QACL,SAAS,WAAA,CAAY,GAAA;AAAA,QACrB,SAAA,EAAW,UAAU,IAAA,CAAK,SAAA;AAAA,QAC1B,UAAU,SAAA,CAAU,QAAA;AAAA,QACpB,aAAa,SAAA,CAAU,WAAA;AAAA,QACvB,MAAA,EAAQ;AAAA,OACV;AAAA,IACF;AAEA,IAAA,MAAM,MAAA,GAAS,MAAM,sBAAA,CAAuB,GAAA,EAAK,KAAK,SAAS,CAAA;AAC/D,IAAA,MAAM,OAAA,GAAU,iBAAiB,MAAM,CAAA;AACvC,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,MAAM,SAAA,GAAY,MAAM,8BAAA,CAA+B,GAAA,EAAK,OAAO,CAAA;AACnE,MAAA,OAAO;AAAA,QACL,SAAS,OAAA,CAAQ,GAAA;AAAA,QACjB,WAAW,IAAA,CAAK,SAAA;AAAA,QAChB,UAAU,SAAA,CAAU,QAAA;AAAA,QACpB,aAAa,SAAA,CAAU,WAAA;AAAA,QACvB,MAAA,EAAQ;AAAA,OACV;AAAA,IACF;AAEA,IAAA,MAAM,YAAY,MAAM,2BAAA;AAAA,MACtB,GAAA;AAAA,MACA,MAAA,CAAO,KAAK,SAAS;AAAA,KACvB;AACA,IAAA,IAAI,SAAA,EAAW;AACb,MAAA,OAAO;AAAA,QACL,GAAG,SAAA;AAAA,QACH,SAAA,EAAW,SAAA,CAAU,SAAA,IAAa,MAAA,CAAO,KAAK,SAAS;AAAA,OACzD;AAAA,IACF;AAEA,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,qBAAA,EAAwB,MAAA,CAAO,IAAA,CAAK,SAAS,CAAC,CAAA,qBAAA;AAAA,KAChD;AAAA,EACF;AAEA,EAAA,MAAM,IAAI,KAAA;AAAA,IACR;AAAA,GACF;AACF;CAGiC;AAAA,EAC/B,SAAA,EAAW,CAAA,CAAE,QAAA,CAAS,CAAA,CAAE,QAAQ,CAAA;AAAA,EAChC,OAAA,EAAS,CAAA,CAAE,QAAA,CAAS,CAAA,CAAE,QAAQ;AAChC;AC/XO,SAASA,qBAAoB,KAAA,EAAoC;AACtE,EAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,IAAA;AAAA,EACF;AACA,EAAA,MAAM,UAAA,GAAa,MAAM,IAAA,EAAK;AAC9B,EAAA,OAAO,UAAA,CAAW,MAAA,GAAS,CAAA,GAAI,UAAA,GAAa,MAAA;AAC9C;AAEA,SAAS,6BAA6B,IAAA,EAK5B;AACR,EAAA,MAAM,KAAA,GAAQ,IAAI,KAAA,CAAM,IAAA,CAAK,OAAO,CAAA;AACpC,EAAA,KAAA,CAAM,MAAA,GAAS,GAAA;AACf,EAAA,KAAA,CAAM,IAAA,GAAO,qBAAA;AACb,EAAA,KAAA,CAAM,gBAAgB,IAAA,CAAK,aAAA;AAC3B,EAAA,KAAA,CAAM,aAAa,IAAA,CAAK,UAAA;AACxB,EAAA,KAAA,CAAM,UAAU,IAAA,CAAK,OAAA;AACrB,EAAA,MAAM,KAAA;AACR;AAEO,SAAS,wCAAwC,IAAA,EAI/C;AACP,EAAA,MAAM,KAAA,GAAQ,WAAW,IAAA,CAAK,QAAQ,IAClC,mBAAA,CAAoB,IAAA,CAAK,QAAQ,CAAA,GACjC,MAAA;AACJ,EAAA,IAAI,UAAU,aAAA,EAAe;AAC3B,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,WAAA,GAAcA,oBAAAA,CAAoB,IAAA,CAAK,KAAA,CAAM,WAAW,CAAA;AAC9D,EAAA,IAAI,WAAA,EAAa;AACf,IAAA;AAAA,EACF;AAEA,EAAA,4BAAA,CAA6B;AAAA,IAC3B,OAAA,EACE,6FAAA;AAAA,IACF,aAAA,EAAe,8CAAA;AAAA,IACf,UAAA,EACE,kGAAA;AAAA,IACF,OAAA,EAAS;AAAA,MACP,cAAc,IAAA,CAAK,YAAA;AAAA,MACnB,UAAU,IAAA,CAAK,QAAA;AAAA,MACf,OAAA,EAAS,KAAK,KAAA,CAAM,OAAA;AAAA,MACpB,SAAA,EAAW,KAAK,KAAA,CAAM;AAAA;AACxB,GACD,CAAA;AACH;ACzEA,eAAsB,mBAAA,CACpB,KACA,GAAA,EAC+B;AAC/B,EAAA,oBAAA,CAAqB,gBAAA,EAAkB,IAAI,QAAQ,CAAA;AACnD,EAAA,OAAO,GAAA,CAAI,EAAA,CAAG,MAAA,CAAO,gBAAA,EAAkB,GAAG,CAAA;AAC5C;;;ACgBA,SAAS,2BAA2B,IAAA,EAO1B;AACR,EAAA,MAAM,KAAA,GAAQ,IAAI,KAAA,CAAM,IAAA,CAAK,OAAO,CAAA;AACpC,EAAA,KAAA,CAAM,SAAS,IAAA,CAAK,MAAA;AACpB,EAAA,KAAA,CAAM,OAAO,IAAA,CAAK,IAAA;AAClB,EAAA,KAAA,CAAM,gBAAgB,IAAA,CAAK,aAAA;AAC3B,EAAA,KAAA,CAAM,aAAa,IAAA,CAAK,UAAA;AACxB,EAAA,KAAA,CAAM,UAAU,IAAA,CAAK,OAAA;AACrB,EAAA,MAAM,KAAA;AACR;AAEA,SAAS,gBAAgB,KAAA,EAAoC;AAC3D,EAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,MAAM,UAAA,GAAa,MAAM,IAAA,EAAK;AAC9B,EAAA,OAAO,UAAA,CAAW,MAAA,GAAS,CAAA,GAAI,UAAA,GAAa,MAAA;AAC9C;AAEA,SAAS,gBAAgB,KAAA,EAAoC;AAC3D,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA,IAAY,OAAO,QAAA,CAAS,KAAK,IAAI,KAAA,GAAQ,MAAA;AACvE;AAEA,SAAS,SAAS,KAAA,EAAyC;AACzD,EAAA,OAAO,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,IAAY,CAAC,MAAM,OAAA,CAAQ,KAAK,CAAA,GAC5D,KAAA,GACD,EAAC;AACP;AAEA,SAAS,kBACP,QAAA,EACyB;AACzB,EAAA,MAAM,MAAA,GAAS,SAAS,QAAQ,CAAA;AAChC,EAAA,MAAM,EAAE,GAAA,EAAK,WAAA,EAAa,YAAY,WAAA,EAAa,GAAG,MAAK,GAAI,MAAA;AAC/D,EAAA,OAAO,IAAA;AACT;AAEA,SAAS,0BAA0B,QAAA,EAA0B;AAC3D,EAAA,MAAM,UAAU,CAAA,OAAA,EAAU,QAAA,CAAS,IAAA,EAAK,CAAE,aAAa,CAAA,CAAA;AACvD,EAAA,IAAI,IAAA,GAAO,IAAA;AACX,EAAA,KAAA,IAAS,QAAQ,CAAA,EAAG,KAAA,GAAQ,OAAA,CAAQ,MAAA,EAAQ,SAAS,CAAA,EAAG;AACtD,IAAA,IAAA,GAAA,CAAQ,IAAA,IAAQ,CAAA,IAAK,IAAA,GAAO,OAAA,CAAQ,WAAW,KAAK,CAAA;AACpD,IAAA,IAAA,IAAQ,IAAA;AAAA,EACV;AACA,EAAA,OAAO,IAAA,CAAK,IAAI,IAAI,CAAA,CAAE,SAAS,EAAE,CAAA,CAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAA;AACpD;AAEO,SAAS,mBAAmB,GAAA,EAAqB;AACtD,EAAA,MAAM,OAAA,GAAU,gBAAgB,GAAG,CAAA;AACnC,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,0BAAA,CAA2B;AAAA,MACzB,OAAA,EAAS,yBAAA;AAAA,MACT,MAAA,EAAQ,GAAA;AAAA,MACR,IAAA,EAAM,iBAAA;AAAA,MACN,aAAA,EAAe,kBAAA;AAAA,MACf,UAAA,EAAY;AAAA,KACb,CAAA;AAAA,EACH;AAEA,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI;AACF,IAAA,MAAA,GAAS,IAAI,IAAI,OAAO,CAAA;AAAA,EAC1B,CAAA,CAAA,MAAQ;AACN,IAAA,0BAAA,CAA2B;AAAA,MACzB,OAAA,EAAS,gBAAgB,OAAO,CAAA,CAAA;AAAA,MAChC,MAAA,EAAQ,GAAA;AAAA,MACR,IAAA,EAAM,iBAAA;AAAA,MACN,aAAA,EAAe,kBAAA;AAAA,MACf,UAAA,EAAY,yDAAA;AAAA,MACZ,OAAA,EAAS,EAAE,GAAA,EAAK,OAAA;AAAQ,KACzB,CAAA;AAAA,EACH;AAEA,EAAA,MAAM,QAAA,GAAW,MAAA,CAAO,QAAA,CAAS,WAAA,EAAY;AAC7C,EAAA,MAAM,QAAA,GAAW,MAAA,CAAO,QAAA,CAAS,WAAA,EAAY;AAC7C,EAAA,MAAM,OAAO,MAAA,CAAO,IAAA,GAAO,CAAA,CAAA,EAAI,MAAA,CAAO,IAAI,CAAA,CAAA,GAAK,EAAA;AAC/C,EAAA,MAAM,QAAA,GACJ,OAAO,QAAA,KAAa,GAAA,GAChB,KACA,MAAA,CAAO,QAAA,CAAS,OAAA,CAAQ,MAAA,EAAQ,EAAE,CAAA;AAExC,EAAA,MAAM,gBAAgB,CAAC,GAAG,OAAO,YAAA,CAAa,OAAA,EAAS,CAAA,CAAE,IAAA;AAAA,IAAK,CAAC,CAAC,IAAA,EAAM,MAAM,CAAA,EAAG,CAAC,IAAA,EAAM,MAAM,CAAA,KAC1F,IAAA,KAAS,OAAO,MAAA,CAAO,aAAA,CAAc,MAAM,CAAA,GAAI,IAAA,CAAK,cAAc,IAAI;AAAA,GACxE;AACA,EAAA,MAAM,MAAA,GAAS,IAAI,eAAA,EAAgB;AACnC,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,CAAA,IAAK,aAAA,EAAe;AACxC,IAAA,MAAA,CAAO,MAAA,CAAO,KAAK,KAAK,CAAA;AAAA,EAC1B;AACA,EAAA,MAAM,MAAA,GAAS,OAAO,QAAA,EAAS;AAE/B,EAAA,OAAO,CAAA,EAAG,QAAQ,CAAA,EAAA,EAAK,QAAQ,GAAG,IAAI,CAAA,EAAG,QAAQ,CAAA,EAC/C,OAAO,MAAA,GAAS,CAAA,GAAI,CAAA,CAAA,EAAI,MAAM,KAAK,EACrC,CAAA,CAAA;AACF;AAEA,eAAe,oBAAA,CACb,KACA,IAAA,EACA;AACA,EAAA,MAAM,cAAc,MAAM,GAAA,CAAI,EAAA,CAC3B,KAAA,CAAM,gBAAgB,CAAA,CACtB,SAAA;AAAA,IAAU,aAAA;AAAA,IAAe,CAAC,CAAA,KACzB,CAAA,CAAE,EAAA,CAAG,YAAY,QAAQ;AAAA,IAE1B,OAAA,EAAQ;AAEX,EAAA,IAAI,QAAA,GAAyC,IAAA;AAC7C,EAAA,IAAI,QAAA,GAAyC,IAAA;AAE7C,EAAA,KAAA,MAAW,QAAQ,WAAA,EAAwC;AACzD,IAAA,MAAM,QAAA,GAAW,QAAA,CAAS,IAAA,CAAK,QAAQ,CAAA;AACvC,IAAA,IACE,IAAA,CAAK,iBACL,eAAA,CAAgB,QAAA,CAAS,GAAG,CAAA,KAAM,IAAA,CAAK,aAAA,IACvC,CAAC,QAAA,EACD;AACA,MAAA,QAAA,GAAW,IAAA;AAAA,IACb;AACA,IAAA,IAAI,IAAA,CAAK,OAAO,eAAA,CAAgB,QAAA,CAAS,UAAU,CAAA,KAAM,IAAA,CAAK,GAAA,IAAO,CAAC,QAAA,EAAU;AAC9E,MAAA,QAAA,GAAW,IAAA;AAAA,IACb;AACA,IAAA,IAAI,QAAA,KAAa,CAAC,IAAA,CAAK,GAAA,IAAO,QAAA,CAAA,EAAW;AACvC,MAAA;AAAA,IACF;AAAA,EACF;AAEA,EAAA,IAAI,QAAA,IAAY,YAAY,MAAA,CAAO,QAAA,CAAS,GAAG,CAAA,KAAM,MAAA,CAAO,QAAA,CAAS,GAAG,CAAA,EAAG;AACzE,IAAA,0BAAA,CAA2B;AAAA,MACzB,OAAA,EAAS,0EAAA;AAAA,MACT,MAAA,EAAQ,GAAA;AAAA,MACR,IAAA,EAAM,sBAAA;AAAA,MACN,aAAA,EAAe,+BAAA;AAAA,MACf,UAAA,EACE,oHAAA;AAAA,MACF,OAAA,EAAS;AAAA,QACP,WAAA,EAAa,MAAA,CAAO,QAAA,CAAS,GAAG,CAAA;AAAA,QAChC,WAAA,EAAa,MAAA,CAAO,QAAA,CAAS,GAAG;AAAA;AAClC,KACD,CAAA;AAAA,EACH;AAEA,EAAA,OAAO,QAAA,IAAY,QAAA;AACrB;AAEA,SAAS,oBAAoB,IAAA,EAO1B;AACD,EAAA,MAAM,gBAAA,GAAmB,IAAA,CAAK,gBAAA,IAAoB,EAAC;AACnD,EAAA,MAAM,YAAA,GAAwC;AAAA,IAC5C,GAAG,gBAAA;AAAA,IACH,MAAM,IAAA,CAAK,IAAA;AAAA,IACX,GAAG,IAAA,CAAK;AAAA,GACV;AAEA,EAAA,IAAI,IAAA,CAAK,eAAe,MAAA,EAAW;AACjC,IAAA,YAAA,CAAa,aAAa,IAAA,CAAK,UAAA;AAAA,EACjC;AACA,EAAA,IAAI,CAAC,OAAO,SAAA,CAAU,cAAA,CAAe,KAAK,gBAAA,EAAkB,KAAK,CAAA,IAAK,IAAA,CAAK,aAAA,EAAe;AACxF,IAAA,YAAA,CAAa,MAAM,IAAA,CAAK,aAAA;AAAA,EAC1B,WAAW,MAAA,CAAO,SAAA,CAAU,eAAe,IAAA,CAAK,gBAAA,EAAkB,KAAK,CAAA,EAAG;AACxE,IAAA,YAAA,CAAa,MAAM,gBAAA,CAAiB,GAAA;AAAA,EACtC;AACA,EAAA,IAAI,CAAC,OAAO,SAAA,CAAU,cAAA,CAAe,KAAK,gBAAA,EAAkB,YAAY,CAAA,IAAK,IAAA,CAAK,GAAA,EAAK;AACrF,IAAA,YAAA,CAAa,aAAa,IAAA,CAAK,GAAA;AAAA,EACjC,WAAW,MAAA,CAAO,SAAA,CAAU,eAAe,IAAA,CAAK,gBAAA,EAAkB,YAAY,CAAA,EAAG;AAC/E,IAAA,YAAA,CAAa,aAAa,gBAAA,CAAiB,UAAA;AAAA,EAC7C;AAEA,EAAA,OAAO,YAAA;AACT;AAEA,SAAS,oBAAoB,IAAA,EAK1B;AACD,EAAA,MAAM,KAAA,GAAQ;AAAA,IACZ,eAAA,CAAgB,KAAK,KAAK,CAAA;AAAA,IAC1B,eAAA,CAAgB,KAAK,GAAG,CAAA;AAAA,IACxB,IAAA,CAAK,IAAA;AAAA,IACL,eAAA,CAAgB,IAAA,CAAK,QAAA,CAAS,iBAAiB;AAAA,IAC/C,MAAA,CAAO,CAAC,KAAA,KAA2B,OAAA,CAAQ,KAAK,CAAC,CAAA;AACnD,EAAA,OAAO,KAAA,CAAM,KAAK,IAAI,CAAA;AACxB;AAEO,IAAM,eAAe,QAAA,CAAS;AAAA,EACnC,IAAA,EAAM;AAAA,IACJ,GAAA,EAAKC,CAAAA,CAAE,QAAA,CAASA,CAAAA,CAAE,QAAQ,CAAA;AAAA,IAC1B,GAAA,EAAKA,CAAAA,CAAE,QAAA,CAASA,CAAAA,CAAE,QAAQ,CAAA;AAAA,IAC1B,IAAA,EAAMA,EAAE,MAAA,EAAO;AAAA,IACf,KAAA,EAAOA,CAAAA,CAAE,QAAA,CAASA,CAAAA,CAAE,QAAQ,CAAA;AAAA,IAC5B,UAAA,EAAYA,CAAAA,CAAE,QAAA,CAASA,CAAAA,CAAE,QAAQ,CAAA;AAAA,IACjC,QAAA,EAAUA,CAAAA,CAAE,QAAA,CAASA,CAAAA,CAAE,KAAK,CAAA;AAAA,IAC5B,OAAA,EAASA,CAAAA,CAAE,QAAA,CAASA,CAAAA,CAAE,QAAQ,CAAA;AAAA,IAC9B,MAAA,EAAQA,EAAE,MAAA;AAAO,GACnB;AAAA,EACA,OAAA,EAAS,gBAAA;AAAA,EACT,OAAA,EAAS,OAAO,GAAA,EAAK,IAAA,KAAS;AAC5B,IAAA,MAAM,SAAA,GAAY,eAAA,CAAgB,IAAA,CAAK,GAAG,CAAA;AAC1C,IAAA,MAAM,aAAA,GAAgB,SAAA,GAAY,kBAAA,CAAmB,SAAS,CAAA,GAAI,MAAA;AAClE,IAAA,MAAM,GAAA,GAAM,eAAA,CAAgB,IAAA,CAAK,GAAG,CAAA;AAEpC,IAAA,IAAI,CAAC,aAAA,IAAiB,CAAC,GAAA,EAAK;AAC1B,MAAA,0BAAA,CAA2B;AAAA,QACzB,OAAA,EAAS,gDAAA;AAAA,QACT,MAAA,EAAQ,GAAA;AAAA,QACR,IAAA,EAAM,iBAAA;AAAA,QACN,aAAA,EAAe,0BAAA;AAAA,QACf,UAAA,EAAY;AAAA,OACb,CAAA;AAAA,IACH;AAEA,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,IAAA,MAAM,aAAA,GAAgB,iBAAA,CAAkB,IAAA,CAAK,QAAQ,CAAA;AACrD,IAAA,MAAM,WAAW,MAAM,oBAAA,CAAqB,KAAK,EAAE,aAAA,EAAe,KAAK,CAAA;AAEvE,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,IAAI,QAAA,CAAS,OAAA,IAAW,CAAE,MAAM,gBAAA,CAAiB,GAAA,EAAK,MAAA,CAAO,QAAA,CAAS,OAAO,CAAA,EAAG,IAAA,CAAK,MAAM,CAAA,EAAI;AAC7F,QAAA,0BAAA,CAA2B;AAAA,UACzB,OAAA,EAAS,yCAAA;AAAA,UACT,MAAA,EAAQ,GAAA;AAAA,UACR,IAAA,EAAM,WAAA;AAAA,UACN,aAAA,EAAe,uBAAA;AAAA,UACf,UAAA,EAAY,qDAAA;AAAA,UACZ,OAAA,EAAS,EAAE,OAAA,EAAS,QAAA,CAAS,OAAA;AAAQ,SACtC,CAAA;AAAA,MACH;AAEA,MAAA,MAAM,gBAAA,GAAmB,QAAA,CAAS,QAAA,CAAS,QAAQ,CAAA;AACnD,MAAA,MAAM,WAAA,GAAc,eAAA,CAAgB,gBAAA,CAAiB,UAAU,CAAA;AAC/D,MAAA,IAAI,GAAA,IAAO,WAAA,IAAe,WAAA,KAAgB,GAAA,EAAK;AAC7C,QAAA,0BAAA,CAA2B;AAAA,UACzB,OAAA,EAAS,0DAAA;AAAA,UACT,MAAA,EAAQ,GAAA;AAAA,UACR,IAAA,EAAM,sBAAA;AAAA,UACN,aAAA,EAAe,+BAAA;AAAA,UACf,UAAA,EACE,6FAAA;AAAA,UACF,OAAA,EAAS;AAAA,YACP,QAAA,EAAU,MAAA,CAAO,QAAA,CAAS,GAAG,CAAA;AAAA,YAC7B,KAAK,gBAAA,CAAiB,GAAA;AAAA,YACtB,WAAA;AAAA,YACA,WAAA,EAAa;AAAA;AACf,SACD,CAAA;AAAA,MACH;AAEA,MAAA,MAAMC,gBAAe,mBAAA,CAAoB;AAAA,QACvC,gBAAA;AAAA,QACA,MAAM,IAAA,CAAK,IAAA;AAAA,QACX,UAAA,EAAY,eAAA,CAAgB,IAAA,CAAK,UAAU,CAAA;AAAA,QAC3C,QAAA,EAAU;AAAA,OACX,CAAA;AAED,MAAA,MAAM,KAAA,GAAiC;AAAA,QACrC,QAAA,EAAUA,aAAAA;AAAA,QACV,SAAA,EAAW;AAAA,OACb;AACA,MAAA,MAAMC,MAAAA,GAAQ,eAAA,CAAgB,IAAA,CAAK,KAAK,CAAA;AACxC,MAAA,IAAIA,MAAAA,EAAO;AACT,QAAA,KAAA,CAAM,KAAA,GAAQA,MAAAA;AACd,QAAA,KAAA,CAAM,aAAA,GAAgBA,MAAAA;AAAA,MACxB;AAEA,MAAA,MAAM,GAAA,CAAI,EAAA,CAAG,KAAA,CAAM,QAAA,CAAS,KAAK,KAAK,CAAA;AAEtC,MAAA,MAAM,IAAI,SAAA,CAAU,QAAA,CAAS,CAAA,EAAG,QAAA,CAAS,UAAU,eAAA,EAAiB;AAAA,QAClE,QAAQ,QAAA,CAAS,GAAA;AAAA,QACjB,SAAA,EAAW;AAAA,OACZ,CAAA;AAED,MAAA,MAAM,GAAA,CAAI,EAAA,CAAG,MAAA,CAAO,gBAAA,EAAkB;AAAA,QACpC,UAAA,EAAY,QAAA;AAAA,QACZ,UAAU,QAAA,CAAS,GAAA;AAAA,QACnB,UAAA,EAAY,yBAAA;AAAA,QACZ,SAAA,EAAW,GAAA;AAAA,QACX,WAAW,IAAA,CAAK,MAAA;AAAA,QAChB,OAAA,EAAS,KAAA;AAAA,QACT,SAAS,QAAA,CAAS,OAAA,GAAU,MAAA,CAAO,QAAA,CAAS,OAAO,CAAA,GAAI,MAAA;AAAA,QACvD,aAAA,EAAe;AAAA,UACb,OAAO,QAAA,CAAS,KAAA;AAAA,UAChB,QAAA,EAAU;AAAA,SACZ;AAAA,QACA,QAAA,EAAU;AAAA,UACR,KAAA,EAAOA,UAAS,QAAA,CAAS,KAAA;AAAA,UACzB,QAAA,EAAUD;AAAA;AACZ,OACM,CAAA;AAER,MAAA,OAAQ,MAAM,GAAA,CAAI,EAAA,CAAG,GAAA,CAAI,QAAA,CAAS,GAAG,CAAA,IAAM,QAAA;AAAA,IAC7C;AAEA,IAAA,IAAI,CAAC,eAAA,CAAgB,IAAA,CAAK,OAAO,CAAA,EAAG;AAClC,MAAA,0BAAA,CAA2B;AAAA,QACzB,OAAA,EAAS,iDAAA;AAAA,QACT,MAAA,EAAQ,GAAA;AAAA,QACR,IAAA,EAAM,iBAAA;AAAA,QACN,aAAA,EAAe,yBAAA;AAAA,QACf,UAAA,EAAY;AAAA,OACb,CAAA;AAAA,IACH;AAEA,IAAA,MAAM,KAAA,GAAQ,MAAM,wBAAA,CAAyB,GAAA,EAAK;AAAA,MAChD,SAAS,IAAA,CAAK;AAAA,KACf,CAAA;AACD,IAAA,uCAAA,CAAwC;AAAA,MACtC,KAAA;AAAA,MACA,QAAA,EAAU,QAAA;AAAA,MACV,YAAA,EAAc;AAAA,KACf,CAAA;AACD,IAAA,IAAI,MAAM,SAAA,EAAW;AACnB,MAAA,MAAM,oBAAA,CAAqB,GAAA,EAAK,KAAA,CAAM,SAAA,EAAW,KAAK,MAAM,CAAA;AAAA,IAC9D;AAEA,IAAA,MAAM,WAAW,gBAAA,EAAiB;AAClC,IAAA,MAAM,KAAA,GAAQ,eAAA,CAAgB,IAAA,CAAK,KAAK,CAAA;AACxC,IAAA,MAAM,eAAe,mBAAA,CAAoB;AAAA,MACvC,aAAA;AAAA,MACA,GAAA;AAAA,MACA,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,UAAA,EAAY,eAAA,CAAgB,IAAA,CAAK,UAAU,CAAA;AAAA,MAC3C,QAAA,EAAU;AAAA,KACX,CAAA;AACD,IAAA,MAAM,MAAA,GAAS,MAAM,mBAAA,CAAoB,GAAA,EAAK;AAAA,MAC5C,QAAA;AAAA,MACA,SAAS,KAAA,CAAM,OAAA;AAAA,MACf,WAAW,KAAA,CAAM,SAAA;AAAA,MACjB,UAAU,KAAA,CAAM,QAAA;AAAA,MAChB,aAAa,KAAA,CAAM,WAAA;AAAA,MACnB,QAAA,EAAU,QAAA;AAAA,MACV,cAAA,EAAgB,IAAA;AAAA,MAChB,aAAA,EAAe,SAAS,aAAA,IAAiB,QAAA;AAAA,MACzC,WAAA,EAAa,GAAA,IAAO,yBAAA,CAA0B,aAAA,IAAiB,SAAS,QAAQ,CAAA;AAAA,MAChF,GAAI,KAAA,GAAQ,EAAE,KAAA,KAAU,EAAC;AAAA,MACzB,MAAA,EAAQ,QAAA;AAAA,MACR,SAAA,EAAW,GAAA;AAAA,MACX,SAAA,EAAW,GAAA;AAAA,MACX,WAAW,IAAA,CAAK,MAAA;AAAA,MAChB,QAAA,EAAU;AAAA,KACX,CAAA;AAED,IAAA,MAAM,IAAI,SAAA,CAAU,QAAA,CAAS,CAAA,EAAG,QAAA,CAAS,UAAU,eAAA,EAAiB;AAAA,MAClE,MAAA;AAAA,MACA,SAAA,EAAW;AAAA,KACZ,CAAA;AAED,IAAA,MAAM,2BAAA,CAA4B;AAAA,MAChC,GAAA;AAAA,MACA,MAAA;AAAA,MACA,WAAW,KAAA,CAAM,SAAA;AAAA,MACjB,SAAS,KAAA,CAAM,OAAA;AAAA,MACf,WAAW,IAAA,CAAK,MAAA;AAAA,MAChB,QAAA,EAAU,QAAA;AAAA,MACV,MAAM,mBAAA,CAAoB;AAAA,QACxB,KAAA;AAAA,QACA,GAAA,EAAK,aAAA;AAAA,QACL,MAAM,IAAA,CAAK,IAAA;AAAA,QACX,QAAA,EAAU;AAAA,OACX;AAAA,KACF,CAAA;AAED,IAAA,MAAM,GAAA,CAAI,EAAA,CAAG,MAAA,CAAO,gBAAA,EAAkB;AAAA,MACpC,UAAA,EAAY,QAAA;AAAA,MACZ,QAAA,EAAU,MAAA;AAAA,MACV,UAAA,EAAY,gBAAA;AAAA,MACZ,SAAA,EAAW,GAAA;AAAA,MACX,WAAW,IAAA,CAAK,MAAA;AAAA,MAChB,OAAA,EAAS,KAAA;AAAA,MACT,SAAS,KAAA,CAAM,OAAA,GAAU,MAAA,CAAO,KAAA,CAAM,OAAO,CAAA,GAAI,MAAA;AAAA,MACjD,aAAA,EAAe,IAAA;AAAA,MACf,QAAA,EAAU;AAAA,QACR,KAAA;AAAA,QACA,GAAA,EAAK,aAAA;AAAA,QACL,UAAA,EAAY,GAAA;AAAA,QACZ,MAAM,IAAA,CAAK;AAAA;AACb,KACM,CAAA;AAER,IAAA,OAAO,MAAM,GAAA,CAAI,EAAA,CAAG,GAAA,CAAI,MAAM,CAAA;AAAA,EAChC;AACF,CAAC;AAEM,IAAM,UAAU,KAAA,CAAM;AAAA,EAC3B,IAAA,EAAM;AAAA,IACJ,QAAQD,CAAAA,CAAE,QAAA,CAASA,CAAAA,CAAE,EAAA,CAAG,gBAAgB,CAAC,CAAA;AAAA,IACzC,QAAA,EAAUA,CAAAA,CAAE,QAAA,CAASA,CAAAA,CAAE,QAAQ;AAAA,GACjC;AAAA,EACA,OAAA,EAAS,gBAAA;AAAA,EACT,OAAA,EAAS,OAAO,GAAA,EAAK,IAAA,KAAS;AAC5B,IAAA,MAAM,EAAA,GACJ,IAAA,CAAK,MAAA,IAAW,IAAA,CAAK,QAAA;AACvB,IAAA,IAAI,CAAC,EAAA,EAAI;AACP,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,MAAM,IAAA,GAAQ,MAAM,GAAA,CAAI,EAAA,CAAG,GAAA;AAAA,MACzB;AAAA,KACF;AACA,IAAA,IAAI,CAAC,IAAA,IAAQ,IAAA,CAAK,QAAA,KAAa,QAAA,EAAU;AACvC,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AACF,CAAC;AAEM,IAAM,YAAY,KAAA,CAAM;AAAA,EAC7B,IAAA,EAAM;AAAA,IACJ,GAAA,EAAKA,EAAE,MAAA;AAAO,GAChB;AAAA,EACA,OAAA,EAAS,gBAAA;AAAA,EACT,OAAA,EAAS,OAAO,GAAA,EAAK,IAAA,KAAS;AAC5B,IAAA,MAAM,aAAA,GAAgB,kBAAA,CAAmB,IAAA,CAAK,GAAG,CAAA;AACjD,IAAA,MAAM,OAAO,MAAM,oBAAA,CAAqB,GAAA,EAAK,EAAE,eAAe,CAAA;AAC9D,IAAA,OAAO,IAAA,IAAQ,IAAA,CAAK,QAAA,KAAa,QAAA,GAAW,IAAA,GAAO,IAAA;AAAA,EACrD;AACF,CAAC;AAEM,IAAM,YAAY,KAAA,CAAM;AAAA,EAC7B,IAAA,EAAM;AAAA,IACJ,GAAA,EAAKA,EAAE,MAAA;AAAO,GAChB;AAAA,EACA,OAAA,EAAS,gBAAA;AAAA,EACT,OAAA,EAAS,OAAO,GAAA,EAAK,IAAA,KAAS;AAC5B,IAAA,MAAM,GAAA,GAAM,eAAA,CAAgB,IAAA,CAAK,GAAG,CAAA;AACpC,IAAA,IAAI,CAAC,GAAA,EAAK;AACR,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,MAAM,OAAO,MAAM,oBAAA,CAAqB,GAAA,EAAK,EAAE,KAAK,CAAA;AACpD,IAAA,OAAO,IAAA,IAAQ,IAAA,CAAK,QAAA,KAAa,QAAA,GAAW,IAAA,GAAO,IAAA;AAAA,EACrD;AACF,CAAC","file":"epistemicSources.js","sourcesContent":["import {\n actionGeneric,\n anyApi,\n componentsGeneric,\n httpActionGeneric,\n internalActionGeneric,\n internalMutationGeneric,\n internalQueryGeneric,\n mutationGeneric,\n queryGeneric,\n} from \"convex/server\";\nimport type { GenericId } from \"convex/values\";\n\nexport const api = anyApi as any;\nexport const components = componentsGeneric() as any;\nexport const internal = anyApi as any;\n\nexport type TableNames = string;\nexport type Id<TableName extends TableNames = string> = GenericId<TableName>;\nexport type Doc<TableName extends TableNames = string> = any;\nexport type DataModel = any;\ntype IndexRangeBuilder = {\n field(fieldName: string): string;\n eq(fieldName: string, value: unknown): IndexRangeBuilder;\n gt(fieldName: string, value: unknown): IndexRangeBuilder;\n gte(fieldName: string, value: unknown): IndexRangeBuilder;\n lt(fieldName: string, value: unknown): IndexRangeBuilder;\n lte(fieldName: string, value: unknown): IndexRangeBuilder;\n};\ntype FilterBuilder = {\n eq(left: unknown, right: unknown): unknown;\n neq(left: unknown, right: unknown): unknown;\n gt(left: unknown, right: unknown): unknown;\n gte(left: unknown, right: unknown): unknown;\n lt(left: unknown, right: unknown): unknown;\n lte(left: unknown, right: unknown): unknown;\n and(...clauses: unknown[]): unknown;\n or(...clauses: unknown[]): unknown;\n field(fieldName: string): unknown;\n};\ntype QueryInitializer<TableName extends TableNames> = {\n withIndex(\n indexName: string,\n range?: (q: any) => unknown\n ): QueryInitializer<TableName>;\n filter(predicate: (q: any) => unknown): QueryInitializer<TableName>;\n order(direction: \"asc\" | \"desc\"): QueryInitializer<TableName>;\n collect(): Promise<Doc<TableName>[]>;\n take(limit: number): Promise<Doc<TableName>[]>;\n first(): Promise<Doc<TableName> | null>;\n unique(): Promise<Doc<TableName> | null>;\n};\nexport type DatabaseReader = {\n get<TableName extends TableNames>(\n id: Id<TableName>\n ): Promise<Doc<TableName> | null>;\n query<TableName extends TableNames>(\n tableName: TableName\n ): QueryInitializer<TableName>;\n normalizeId?<TableName extends TableNames>(\n tableName: TableName,\n id: string\n ): Id<TableName> | null;\n};\nexport type DatabaseWriter = DatabaseReader & {\n insert<TableName extends TableNames>(\n tableName: TableName,\n value: Record<string, unknown>\n ): Promise<Id<TableName>>;\n patch<TableName extends TableNames>(\n id: Id<TableName>,\n value: Record<string, unknown>\n ): Promise<void>;\n replace<TableName extends TableNames>(\n id: Id<TableName>,\n value: Record<string, unknown>\n ): Promise<void>;\n delete<TableName extends TableNames>(id: Id<TableName>): Promise<void>;\n};\ntype Scheduler = {\n runAfter(delayMs: number, functionReference: unknown, args?: unknown): Promise<void>;\n};\ntype AuthReader = {\n getUserIdentity(): Promise<unknown>;\n};\ntype RuntimeInvoker = {\n runQuery(functionReference: unknown, args?: unknown): Promise<any>;\n runMutation(functionReference: unknown, args?: unknown): Promise<any>;\n runAction(functionReference: unknown, args?: unknown): Promise<any>;\n};\nexport type QueryCtx = RuntimeInvoker & {\n auth: AuthReader;\n db: DatabaseReader;\n scheduler: Scheduler;\n};\nexport type MutationCtx = RuntimeInvoker & {\n auth: AuthReader;\n db: DatabaseWriter;\n scheduler: Scheduler;\n};\nexport type ActionCtx = RuntimeInvoker & {\n auth: AuthReader;\n scheduler: Scheduler;\n};\n\ntype ConvexFunctionBuilder<Ctx> = <\n Definition extends { handler?: (ctx: Ctx, args: any) => any },\n>(\n definition: Definition\n) => any;\n\nexport const action = actionGeneric as unknown as ConvexFunctionBuilder<ActionCtx>;\nexport const httpAction =\n httpActionGeneric as unknown as ConvexFunctionBuilder<ActionCtx>;\nexport const internalAction =\n internalActionGeneric as unknown as ConvexFunctionBuilder<ActionCtx>;\nexport const internalMutation =\n internalMutationGeneric as unknown as ConvexFunctionBuilder<MutationCtx>;\nexport const internalQuery =\n internalQueryGeneric as unknown as ConvexFunctionBuilder<QueryCtx>;\nexport const mutation =\n mutationGeneric as unknown as ConvexFunctionBuilder<MutationCtx>;\nexport const query = queryGeneric as unknown as ConvexFunctionBuilder<QueryCtx>;\n","type GraphPrimitiveDebugEnvironment = {\n process?: {\n env?: Record<string, string | undefined>;\n };\n};\n\nfunction isGraphPrimitiveDebugEnabled(): boolean {\n const env = (globalThis as GraphPrimitiveDebugEnvironment).process?.env;\n return (\n env?.LUCERN_COMPAT_FALLBACK_DEBUG === \"1\" ||\n env?.LUCERN_GRAPH_DEBUG === \"1\"\n );\n}\n\nexport function formatGraphPrimitiveError(error: unknown): string {\n if (error instanceof Error) {\n return `${error.name}: ${error.message}`;\n }\n if (typeof error === \"string\") {\n return error;\n }\n if (error === null) {\n return \"null\";\n }\n if (error === undefined) {\n return \"undefined\";\n }\n try {\n return JSON.stringify(error);\n } catch {\n return Object.prototype.toString.call(error);\n }\n}\n\nexport function debugGraphPrimitiveFallback(\n message: string,\n context?: Record<string, unknown>\n): void {\n if (!isGraphPrimitiveDebugEnabled()) {\n return;\n }\n console.debug(message, context ?? {});\n}\n","/**\n * Shared helper to schedule embedding generation after epistemic node creation.\n *\n * Best-effort — failures are silently caught. The embedding generation action\n * is a public action in convex/embeddingActions.ts that calls Pinecone.\n */\n\nimport type { Id } from \"./convex\";\nimport { debugGraphPrimitiveFallback } from \"./debug\";\n\ninterface EmbeddingTriggerArgs {\n ctx: any;\n nodeId: Id<\"epistemicNodes\">;\n projectId?: string | null;\n topicId?: string | null;\n createdBy: string;\n nodeType:\n | \"belief\"\n | \"question\"\n | \"evidence\"\n | \"answer\"\n | \"synthesis\"\n | \"theme\"\n | \"source\";\n text: string;\n hasAnswer?: boolean;\n confidence?: number;\n}\n\nexport async function scheduleEmbeddingGeneration(\n args: EmbeddingTriggerArgs,\n): Promise<void> {\n try {\n await args.ctx.scheduler.runAfter(\n 0,\n \"embeddingActions:generateEpistemicNodeEmbedding\" as any,\n {\n nodeId: args.nodeId,\n projectId: args.projectId ? String(args.projectId) : undefined,\n topicId: args.topicId ? String(args.topicId) : undefined,\n createdBy: args.createdBy,\n nodeType: args.nodeType,\n text: args.text.slice(0, 20_000),\n hasAnswer: args.hasAnswer,\n confidence: args.confidence,\n },\n );\n } catch (error) {\n debugGraphPrimitiveFallback(\n \"[embeddingTrigger] Failed to schedule embedding generation\",\n {\n error,\n nodeId: String(args.nodeId),\n nodeType: args.nodeType,\n },\n );\n // Embedding generation is best-effort — never block node creation\n }\n}\n","/** Topic-scope resolution helpers for graph-primitive operations. */\nimport { v } from \"convex/values\";\nimport { api as appApi } from \"./convex\";\nimport type { Id } from \"./convex\";\nimport { debugGraphPrimitiveFallback } from \"./debug\";\n\nconst LEGACY_SCOPE_FIELD = \"graphScope\" + \"ProjectId\";\n\ntype TopicDoc = Record<string, unknown> & {\n _id: Id<\"topics\">;\n globalId?: string;\n name?: string;\n depth?: number;\n createdAt?: number;\n parentTopicId?: Id<\"topics\">;\n tenantId?: string;\n workspaceId?: string;\n metadata?: Record<string, unknown>;\n};\n\nexport type TopicProjectScope = {\n topicId: Id<\"topics\">;\n projectId?: string;\n tenantId?: string;\n workspaceId?: string;\n source:\n | \"topic\"\n | \"project_mapped_topic\"\n | \"topic_inferred\"\n | \"topic_node\";\n};\n\n/**\n * RR.5 (legacy topics-table retirement) — graph-primitives mirror of the\n * kernel's epistemicNodes-first topic-scope fallback. Kept in lockstep with\n * `packages/reasoning-kernel/src/adapters/lib/topicScope.ts`\n * (`tests/unit/convex/topic-scope-fallbacks.test.ts` asserts parity).\n *\n * Resolves a topic that exists only as `epistemicNodes(nodeType=\"topic\")` —\n * the write-of-record — when no legacy `topics` row backs the ref, returning the\n * node's `topicId` self-key so scoped beliefs/evidence/questions stay reachable.\n * See the kernel module for the full silent-empty-result rationale.\n */\ntype TopicNodeScopeDoc = {\n _id: string | Id<\"epistemicNodes\">;\n globalId?: string;\n nodeType?: string;\n topicId?: string;\n metadata?: Record<string, unknown>;\n};\n\nasync function resolveTopicNodeScopeOrNull(\n ctx: any,\n ref: string,\n): Promise<TopicProjectScope | null> {\n if (!ctx?.db || typeof ctx.db.query !== \"function\") {\n return null;\n }\n\n let node: TopicNodeScopeDoc | null = null;\n\n // 1. The ref IS the topic node's UUIDv7 globalId.\n try {\n const byGlobalId = (await ctx.db\n .query(\"epistemicNodes\")\n .withIndex(\"by_globalId\", (q: any) => q.eq(\"globalId\", ref))\n .first()) as TopicNodeScopeDoc | null;\n if (byGlobalId && byGlobalId.nodeType === \"topic\") {\n node = byGlobalId;\n }\n } catch (error) {\n debugGraphPrimitiveFallback(\n \"[topicScope] topic-node scope lookup by globalId failed\",\n { error, ref },\n );\n }\n\n if (!node) {\n return null;\n }\n\n const scopeKey =\n normalizeScopeValue(node.topicId) ?? normalizeScopeValue(node.globalId);\n if (!scopeKey) {\n return null;\n }\n\n return {\n topicId: scopeKey as Id<\"topics\">,\n projectId: asMappedProjectId(node as unknown as TopicDoc),\n source: \"topic_node\",\n };\n}\n\ntype MaterializedTopicNodeDoc = {\n _id: string | Id<\"epistemicNodes\">;\n metadata?: Record<string, unknown>;\n};\n\nfunction asMappedProjectId(\n topic: TopicDoc | null | undefined,\n): string | undefined {\n if (!topic) {\n return;\n }\n const directLegacyProjectId = normalizeScopeValue(topic[LEGACY_SCOPE_FIELD]);\n if (directLegacyProjectId) {\n return directLegacyProjectId;\n }\n const metadata = (topic.metadata || {}) as Record<string, unknown>;\n const candidate =\n (metadata[LEGACY_SCOPE_FIELD] as string | undefined) ||\n (metadata.legacyProjectId as string | undefined) ||\n (metadata.projectId as string | undefined) ||\n (metadata.scopeProjectId as string | undefined);\n return candidate ? (candidate as string) : undefined;\n}\n\nfunction normalizeScopeValue(value: unknown): string | undefined {\n if (typeof value !== \"string\") {\n return;\n }\n const normalized = value.trim();\n return normalized.length > 0 ? normalized : undefined;\n}\n\nfunction pickPrimaryTopic(candidates: TopicDoc[]): TopicDoc | undefined {\n return [...candidates].sort((a, b) => {\n const depthA = a.depth ?? 9999;\n const depthB = b.depth ?? 9999;\n if (depthA !== depthB) {\n return depthA - depthB;\n }\n const createdA = a.createdAt ?? Number.MAX_SAFE_INTEGER;\n const createdB = b.createdAt ?? Number.MAX_SAFE_INTEGER;\n if (createdA !== createdB) {\n return createdA - createdB;\n }\n return String(a.name || \"\").localeCompare(String(b.name || \"\"));\n })[0];\n}\n\nasync function findTopicsByScopeAlias(\n ctx: any,\n scopeId: string,\n): Promise<TopicDoc[]> {\n try {\n return (await ctx.db\n .query(\"topics\")\n .withIndex(\"by_graph_scope_project\", (q: any) =>\n q.eq(LEGACY_SCOPE_FIELD, scopeId),\n )\n .collect()) as TopicDoc[];\n } catch (error) {\n debugGraphPrimitiveFallback(\n \"[topicScope] Failed to resolve scope alias via index\",\n {\n error,\n scopeId,\n },\n );\n // Older Lucern dev deployments can lag index backfills while still carrying\n // the underlying topics table. Scan and filter so scope resolution keeps\n // working during the rollout.\n const topics = (await ctx.db.query(\"topics\").collect()) as TopicDoc[];\n return topics.filter((topic) => {\n const normalizedGlobalId = normalizeScopeValue(topic.globalId);\n const mappedProjectId = asMappedProjectId(topic);\n return (\n String(topic._id) === scopeId ||\n normalizedGlobalId === scopeId ||\n mappedProjectId === scopeId\n );\n });\n }\n}\n\nasync function tryResolveHostTopicById(\n ctx: any,\n topicId: string,\n): Promise<TopicDoc | null> {\n if (typeof ctx.runQuery !== \"function\") {\n return null;\n }\n try {\n return ((await ctx.runQuery(appApi.topics.get as any, {\n id: topicId,\n })) ?? null) as TopicDoc | null;\n } catch (error) {\n debugGraphPrimitiveFallback(\n \"[topicScope] Failed to resolve topic by host query\",\n {\n error,\n topicId,\n },\n );\n return null;\n }\n}\n\nasync function tryResolveHostTopicByLegacyScope(\n ctx: any,\n legacyScopeId: string,\n): Promise<TopicDoc | null> {\n if (typeof ctx.runQuery !== \"function\") {\n return null;\n }\n try {\n return ((await ctx.runQuery(appApi.topics.getByLegacyScopeId as any, {\n projectId: legacyScopeId,\n })) ?? null) as TopicDoc | null;\n } catch (error) {\n debugGraphPrimitiveFallback(\n \"[topicScope] Failed to resolve topic by legacy scope\",\n {\n error,\n legacyScopeId,\n },\n );\n return null;\n }\n}\n\nexport function readMaterializedTopicTableId(\n topicNode: MaterializedTopicNodeDoc | null | undefined,\n): string | undefined {\n if (!topicNode) {\n return;\n }\n\n const metadata = (topicNode.metadata || {}) as Record<string, unknown>;\n const topicTableId =\n (metadata.topicTableId as string | undefined) ||\n (metadata.topicId as string | undefined);\n\n return typeof topicTableId === \"string\" && topicTableId.trim().length > 0\n ? topicTableId.trim()\n : undefined;\n}\n\n/**\n * Walk the topic parent chain to find inherited workspaceId and tenantId.\n * Mirrors the pattern used by resolveTopicOntology for ontologyId inheritance.\n * Max depth: 10 (defensive limit against pathological nesting).\n */\nasync function resolveInheritedWorkspaceScope(\n ctx: any,\n topic: TopicDoc,\n): Promise<{ tenantId?: string; workspaceId?: string }> {\n const MAX_DEPTH = 10;\n let tenantId = normalizeScopeValue(topic.tenantId);\n let workspaceId = normalizeScopeValue(topic.workspaceId);\n\n if (tenantId && workspaceId) {\n return { tenantId, workspaceId };\n }\n\n let current: TopicDoc | null = topic;\n for (let i = 0; i < MAX_DEPTH && current?.parentTopicId; i++) {\n current = (await ctx.db.get(current.parentTopicId)) as TopicDoc | null;\n if (!current) break;\n\n if (!tenantId) {\n tenantId = normalizeScopeValue(current.tenantId);\n }\n if (!workspaceId) {\n workspaceId = normalizeScopeValue(current.workspaceId);\n }\n if (tenantId && workspaceId) break;\n }\n\n return { tenantId, workspaceId };\n}\n\nexport async function resolveTopicProjectScope(\n ctx: any,\n args: { topicId?: Id<\"topics\"> | string; projectId?: string },\n): Promise<TopicProjectScope> {\n if (args.topicId) {\n // Try direct lookup, fall back to the legacy mapped-project bridge\n let topic: TopicDoc | null = null;\n try {\n topic = (await ctx.db.get(\n args.topicId as Id<\"topics\">,\n )) as TopicDoc | null;\n } catch (error) {\n debugGraphPrimitiveFallback(\n \"[topicScope] Failed to load topic by direct id\",\n {\n error,\n topicId: args.topicId,\n },\n );\n // Not a valid topics table ID\n }\n if (!topic) {\n topic = await tryResolveHostTopicById(ctx, String(args.topicId));\n }\n if (!topic) {\n // Try as legacy projectId / globalId via the mapped-project bridge.\n topic =\n pickPrimaryTopic(\n await findTopicsByScopeAlias(ctx, String(args.topicId)),\n ) ?? null;\n }\n if (!topic) {\n // RR.5: no legacy topics row — resolve the canonical topic node store\n // before throwing (silent-empty-result fix).\n const nodeScope = await resolveTopicNodeScopeOrNull(\n ctx,\n String(args.topicId),\n );\n if (nodeScope) {\n return nodeScope;\n }\n throw new Error(`Topic not found: ${String(args.topicId)}`);\n }\n const inherited = await resolveInheritedWorkspaceScope(ctx, topic);\n const mapped = asMappedProjectId(topic);\n if (mapped) {\n return {\n topicId: topic._id,\n projectId: mapped,\n tenantId: inherited.tenantId,\n workspaceId: inherited.workspaceId,\n source: \"topic\",\n };\n }\n return {\n topicId: topic._id,\n tenantId: inherited.tenantId,\n workspaceId: inherited.workspaceId,\n source: \"topic\",\n };\n }\n\n if (args.projectId) {\n let directTopic: TopicDoc | null = null;\n try {\n directTopic = (await ctx.db.get(\n args.projectId as Id<\"topics\">,\n )) as TopicDoc | null;\n } catch (error) {\n debugGraphPrimitiveFallback(\n \"[topicScope] Failed to load direct project topic\",\n {\n error,\n projectId: args.projectId,\n },\n );\n // Not a valid topics table ID, continue to legacy graph-scope lookup.\n }\n\n if (directTopic) {\n const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);\n const mapped = asMappedProjectId(directTopic);\n return {\n topicId: directTopic._id,\n projectId: mapped ?? args.projectId,\n tenantId: inherited.tenantId,\n workspaceId: inherited.workspaceId,\n source: \"topic_inferred\",\n };\n }\n\n directTopic = await tryResolveHostTopicByLegacyScope(ctx, args.projectId);\n if (directTopic) {\n const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);\n const mapped = asMappedProjectId(directTopic);\n return {\n topicId: directTopic._id,\n projectId: mapped ?? args.projectId,\n tenantId: inherited.tenantId,\n workspaceId: inherited.workspaceId,\n source: \"topic_inferred\",\n };\n }\n\n const topics = await findTopicsByScopeAlias(ctx, args.projectId);\n const primary = pickPrimaryTopic(topics);\n if (primary) {\n const inherited = await resolveInheritedWorkspaceScope(ctx, primary);\n return {\n topicId: primary._id,\n projectId: args.projectId,\n tenantId: inherited.tenantId,\n workspaceId: inherited.workspaceId,\n source: \"project_mapped_topic\",\n };\n }\n // RR.5: try the canonical topic node store before failing.\n const nodeScope = await resolveTopicNodeScopeOrNull(\n ctx,\n String(args.projectId),\n );\n if (nodeScope) {\n return {\n ...nodeScope,\n projectId: nodeScope.projectId ?? String(args.projectId),\n };\n }\n\n throw new Error(\n `Legacy project scope ${String(args.projectId)} has no mapped topic.`,\n );\n }\n\n throw new Error(\n \"Missing scope: provide topicId (preferred) or legacy projectId alias.\",\n );\n}\n\n/** Shared scope args for graph-primitive functions. topicId is canonical; projectId is a legacy alias. */\nexport const optionalScopeArgs = {\n projectId: v.optional(v.string()),\n topicId: v.optional(v.string()),\n} as const;\n","import {\n getLayerForNodeType,\n isNodeType,\n} from \"@lucern/contracts/schema-helpers/spine/tables/epistemicNodes\";\nimport {\n resolveTopicProjectScope,\n type TopicProjectScope,\n} from \"./topicScope\";\n\ntype StructuredInvariantError = Error & {\n status: number;\n code: string;\n invariantCode?: string;\n suggestion?: string;\n details?: unknown;\n};\n\ntype ScopeLike = {\n tenantId?: unknown;\n workspaceId?: unknown;\n epistemicLayer?: unknown;\n nodeType?: unknown;\n topicId?: unknown;\n projectId?: unknown;\n publicationStatus?: unknown;\n};\n\nexport type RuntimePackMutationContext = {\n toolName?: string;\n packKey?: string;\n packInstallScope?: \"tenant\" | \"workspace\";\n};\n\nexport function normalizeScopeValue(value: unknown): string | undefined {\n if (typeof value !== \"string\") {\n return;\n }\n const normalized = value.trim();\n return normalized.length > 0 ? normalized : undefined;\n}\n\nfunction throwWorkspaceIsolationError(args: {\n message: string;\n invariantCode: string;\n suggestion: string;\n details?: unknown;\n}): never {\n const error = new Error(args.message) as StructuredInvariantError;\n error.status = 409;\n error.code = \"INVARIANT_VIOLATION\";\n error.invariantCode = args.invariantCode;\n error.suggestion = args.suggestion;\n error.details = args.details;\n throw error;\n}\n\nexport function assertWorkspaceScopedEpistemicNodeScope(args: {\n scope: TopicProjectScope;\n nodeType: string;\n mutationName: string;\n}): void {\n const layer = isNodeType(args.nodeType)\n ? getLayerForNodeType(args.nodeType)\n : undefined;\n if (layer === \"ontological\") {\n return;\n }\n\n const workspaceId = normalizeScopeValue(args.scope.workspaceId);\n if (workspaceId) {\n return;\n }\n\n throwWorkspaceIsolationError({\n message:\n \"Workspace-scoped reasoning isolation requires workspaceId on non-ontological node creation.\",\n invariantCode: \"workspace.scope_required_for_epistemic_nodes\",\n suggestion:\n \"Resolve the topic/project scope through a workspace-bound topic before creating epistemic nodes.\",\n details: {\n mutationName: args.mutationName,\n nodeType: args.nodeType,\n topicId: args.scope.topicId,\n projectId: args.scope.projectId,\n },\n });\n}\n\nexport function nodeMatchesWorkspaceReasoningScope(\n node: ScopeLike | null | undefined,\n scope: Pick<TopicProjectScope, \"tenantId\" | \"workspaceId\">\n): boolean {\n if (!node) {\n return false;\n }\n\n const scopeTenantId = normalizeScopeValue(scope.tenantId);\n const scopeWorkspaceId = normalizeScopeValue(scope.workspaceId);\n const nodeTenantId = normalizeScopeValue(node.tenantId);\n const nodeWorkspaceId = normalizeScopeValue(node.workspaceId);\n const epistemicLayer =\n typeof node.epistemicLayer === \"string\" ? node.epistemicLayer : undefined;\n\n if (\n scopeTenantId &&\n nodeTenantId &&\n scopeTenantId !== nodeTenantId\n ) {\n return false;\n }\n\n // Ontological entities are tenant-global (no workspace required)\n if (epistemicLayer === \"ontological\" && nodeWorkspaceId === undefined) {\n return true;\n }\n\n // Published nodes are visible at tenant scope — the microservice API surface.\n // The node stays in its workspace, but tenant-scope queries can see it.\n if (!scopeWorkspaceId && node.publicationStatus === \"published\") {\n return true;\n }\n\n if (!scopeWorkspaceId) {\n return nodeWorkspaceId === undefined;\n }\n\n return scopeWorkspaceId === nodeWorkspaceId;\n}\n\nexport function edgeMatchesWorkspaceReasoningScope(\n edge: ScopeLike | null | undefined,\n scope: Pick<TopicProjectScope, \"tenantId\" | \"workspaceId\">\n): boolean {\n if (!edge) {\n return false;\n }\n\n const scopeTenantId = normalizeScopeValue(scope.tenantId);\n const scopeWorkspaceId = normalizeScopeValue(scope.workspaceId);\n const edgeTenantId = normalizeScopeValue(edge.tenantId);\n const edgeWorkspaceId = normalizeScopeValue(edge.workspaceId);\n\n if (\n scopeTenantId &&\n edgeTenantId &&\n scopeTenantId !== edgeTenantId\n ) {\n return false;\n }\n\n if (!scopeWorkspaceId) {\n return edgeWorkspaceId === undefined;\n }\n\n return scopeWorkspaceId === edgeWorkspaceId;\n}\n\nexport async function resolveNodeScopeForWorkspaceIsolation(\n ctx: any,\n node: ScopeLike | null | undefined\n): Promise<{\n tenantId?: string;\n workspaceId?: string;\n epistemicLayer?: string;\n nodeType?: string;\n}> {\n const epistemicLayer =\n typeof node?.epistemicLayer === \"string\" ? node.epistemicLayer : undefined;\n const resolved = {\n tenantId: normalizeScopeValue(node?.tenantId),\n workspaceId: normalizeScopeValue(node?.workspaceId),\n epistemicLayer,\n nodeType: typeof node?.nodeType === \"string\" ? node.nodeType : undefined,\n };\n\n if (!node) {\n return resolved;\n }\n\n if (resolved.epistemicLayer === \"ontological\") {\n return resolved;\n }\n\n if (resolved.tenantId || resolved.workspaceId) {\n return resolved;\n }\n\n if (node.topicId) {\n const topicScope = await resolveTopicProjectScope(ctx, {\n topicId: node.topicId as any,\n });\n return {\n ...resolved,\n tenantId: topicScope.tenantId,\n workspaceId: topicScope.workspaceId,\n };\n }\n\n if (node.projectId) {\n const topicScope = await resolveTopicProjectScope(ctx, {\n projectId: String(node.projectId),\n });\n return {\n ...resolved,\n tenantId: topicScope.tenantId,\n workspaceId: topicScope.workspaceId,\n };\n }\n\n return resolved;\n}\n\nexport function resolveRuntimePackMutationContext(args: {\n runtimeToolName?: string;\n runtimePackKey?: string;\n runtimePackInstallScope?: \"tenant\" | \"workspace\";\n}): RuntimePackMutationContext | undefined {\n if (\n !args.runtimeToolName &&\n !args.runtimePackKey &&\n !args.runtimePackInstallScope\n ) {\n return;\n }\n\n return {\n toolName: args.runtimeToolName,\n packKey: args.runtimePackKey,\n packInstallScope: args.runtimePackInstallScope,\n };\n}\n\nexport function assertTenantPackWorkspaceMutationAllowed(args: {\n runtime?: RuntimePackMutationContext;\n target: ScopeLike;\n mutationName: string;\n}): void {\n if (\n !args.runtime?.packKey ||\n args.runtime.packInstallScope !== \"tenant\"\n ) {\n return;\n }\n\n const targetWorkspaceId = normalizeScopeValue(args.target.workspaceId);\n const targetLayer =\n typeof args.target.epistemicLayer === \"string\"\n ? args.target.epistemicLayer\n : undefined;\n\n if (!targetWorkspaceId || targetLayer === \"ontological\") {\n return;\n }\n\n throwWorkspaceIsolationError({\n message:\n `Tenant-scoped pack \"${args.runtime.packKey}\" cannot mutate workspace-scoped reasoning state.`,\n invariantCode: \"workspace.tenant_pack_reasoning_write_forbidden\",\n suggestion:\n \"Use a workspace-scoped pack for workspace-local graph mutations, or route the change through tenant-global canonical entity flows.\",\n details: {\n mutationName: args.mutationName,\n toolName: args.runtime.toolName,\n packKey: args.runtime.packKey,\n targetWorkspaceId,\n targetNodeType: args.target.nodeType,\n targetLayer,\n },\n });\n}\n","import type { WithoutSystemFields } from \"convex/server\";\nimport {\n assertUuidV7Identity,\n assertStorageEdgeVocabulary,\n assertCanonicalEdgeEndpoint,\n} from \"@lucern/contracts/ids\";\nimport {\n assertEdgePolicyAllowed,\n edgePolicyManifest,\n type EpistemicNodeType,\n} from \"@lucern/contracts\";\nimport type { Doc, Id, MutationCtx } from \"./convex\";\n\nexport async function insertEpistemicNode(\n ctx: MutationCtx,\n doc: WithoutSystemFields<Doc<\"epistemicNodes\">>,\n): Promise<Id<\"epistemicNodes\">> {\n assertUuidV7Identity(\"epistemicNodes\", doc.globalId);\n return ctx.db.insert(\"epistemicNodes\", doc);\n}\n\nexport async function insertEpistemicEdge(\n ctx: MutationCtx,\n doc: WithoutSystemFields<Doc<\"epistemicEdges\">>,\n): Promise<Id<\"epistemicEdges\">> {\n assertUuidV7Identity(\"epistemicEdges\", doc.globalId);\n\n // R1.1a — STORAGE-VOCABULARY MEMBERSHIP\n assertStorageEdgeVocabulary(doc.edgeType);\n\n // R1.1b — ENDPOINT PRESENCE\n if (!doc.fromNodeId || typeof doc.fromNodeId !== \"string\") {\n throw new Error(\n \"edge_endpoint_missing: epistemicEdges insert requires a non-empty fromNodeId\"\n );\n }\n if (!doc.toNodeId || typeof doc.toNodeId !== \"string\") {\n throw new Error(\n \"edge_endpoint_missing: epistemicEdges insert requires a non-empty toNodeId\"\n );\n }\n\n // C2-RR.4 Defect E — ENDPOINT CANONICAL IDENTITY. Edge endpoints must be the\n // UUIDv7 globalIds of the connected nodes, never Convex doc ids or legacy\n // topic ids. This refuses the mixed _id/globalId endpoint writes at the floor.\n assertCanonicalEdgeEndpoint(\"fromNodeId\", doc.fromNodeId);\n assertCanonicalEdgeEndpoint(\"toNodeId\", doc.toNodeId);\n\n // R1.1c — FULL POLICY ASSERT (when nodeTypes are present and edgeType is in public manifest)\n if (doc.fromNodeType && doc.toNodeType && doc.edgeType !== \"extracted_from\") {\n assertEdgePolicyAllowed(\n edgePolicyManifest,\n doc.edgeType,\n {\n kind: \"epistemic_node\",\n nodeId: doc.fromNodeId,\n nodeType: doc.fromNodeType as EpistemicNodeType,\n },\n {\n kind: \"epistemic_node\",\n nodeId: doc.toNodeId,\n nodeType: doc.toNodeType as EpistemicNodeType,\n }\n );\n }\n\n return ctx.db.insert(\"epistemicEdges\", doc);\n}\n","/**\n * Epistemic Sources API\n *\n * Invariants:\n * - Invariant 7: evidence is context-bound. Sources carry topic, author, and capture time.\n * - Invariant 8: no retroactive reinterpretation. Source identity fields stay immutable.\n * - Invariant 14: no silent state transitions. Every create/update is audited.\n * - Invariant 15: retrieval respects boundaries. Sources live at L1 terminal leaves.\n */\n\nimport { v } from \"convex/values\";\nimport {\n checkScopeAccess,\n requireProjectAccess,\n} from \"@lucern/access-control/access\";\nimport { permissiveReturn } from \"@lucern/contracts/schema-helpers/validators\";\nimport type { Doc, Id } from \"./convex\";\nimport { internal, mutation, query } from \"./convex\";\nimport { scheduleEmbeddingGeneration } from \"./embeddingTrigger\";\nimport { generateGlobalId } from \"./globalId\";\nimport {\n type EpistemicDbReader,\n} from \"./epistemicQuestions.helpers\";\nimport { resolveTopicProjectScope } from \"./topicScope\";\nimport { assertWorkspaceScopedEpistemicNodeScope } from \"./workspaceIsolation\";\nimport { insertEpistemicNode } from \"./epistemicInsert.js\";\n\ntype StructuredSourceError = Error & {\n status: number;\n code: string;\n invariantCode?: string;\n suggestion?: string;\n details?: unknown;\n};\n\nfunction throwStructuredSourceError(args: {\n message: string;\n status: number;\n code: string;\n invariantCode?: string;\n suggestion?: string;\n details?: unknown;\n}): never {\n const error = new Error(args.message) as StructuredSourceError;\n error.status = args.status;\n error.code = args.code;\n error.invariantCode = args.invariantCode;\n error.suggestion = args.suggestion;\n error.details = args.details;\n throw error;\n}\n\nfunction normalizeString(value: unknown): string | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n const normalized = value.trim();\n return normalized.length > 0 ? normalized : undefined;\n}\n\nfunction normalizeNumber(value: unknown): number | undefined {\n return typeof value === \"number\" && Number.isFinite(value) ? value : undefined;\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {};\n}\n\nfunction normalizeMetadata(\n metadata: unknown\n): Record<string, unknown> {\n const record = asRecord(metadata);\n const { url: _ignoredUrl, contentSha: _ignoredSha, ...rest } = record;\n return rest;\n}\n\nfunction generateSourceContentHash(identity: string): string {\n const content = `source:${identity.trim().toLowerCase()}`;\n let hash = 5381;\n for (let index = 0; index < content.length; index += 1) {\n hash = (hash << 5) + hash + content.charCodeAt(index);\n hash &= hash;\n }\n return Math.abs(hash).toString(16).padStart(8, \"0\");\n}\n\nexport function normalizeSourceUrl(url: string): string {\n const trimmed = normalizeString(url);\n if (!trimmed) {\n throwStructuredSourceError({\n message: \"Source URL is required.\",\n status: 400,\n code: \"INVALID_REQUEST\",\n invariantCode: \"source.url.valid\",\n suggestion: \"Provide an absolute URL with a valid protocol and host.\",\n });\n }\n\n let parsed: URL;\n try {\n parsed = new URL(trimmed);\n } catch {\n throwStructuredSourceError({\n message: `Invalid URL: ${trimmed}`,\n status: 400,\n code: \"INVALID_REQUEST\",\n invariantCode: \"source.url.valid\",\n suggestion: \"Provide an absolute URL with a valid protocol and host.\",\n details: { url: trimmed },\n });\n }\n\n const protocol = parsed.protocol.toLowerCase();\n const hostname = parsed.hostname.toLowerCase();\n const port = parsed.port ? `:${parsed.port}` : \"\";\n const pathname =\n parsed.pathname === \"/\"\n ? \"\"\n : parsed.pathname.replace(/\\/+$/, \"\");\n\n const sortedEntries = [...parsed.searchParams.entries()].sort(([aKey, aValue], [bKey, bValue]) =>\n aKey === bKey ? aValue.localeCompare(bValue) : aKey.localeCompare(bKey)\n );\n const params = new URLSearchParams();\n for (const [key, value] of sortedEntries) {\n params.append(key, value);\n }\n const search = params.toString();\n\n return `${protocol}//${hostname}${port}${pathname}${\n search.length > 0 ? `?${search}` : \"\"\n }`;\n}\n\nasync function findSourceByIdentity(\n ctx: { db: EpistemicDbReader },\n args: { normalizedUrl?: string; sha?: string },\n) {\n const sourceNodes = await ctx.db\n .query(\"epistemicNodes\")\n .withIndex(\"by_nodeType\", (q) =>\n q.eq(\"nodeType\", \"source\"),\n )\n .collect();\n\n let urlMatch: Doc<\"epistemicNodes\"> | null = null;\n let shaMatch: Doc<\"epistemicNodes\"> | null = null;\n\n for (const node of sourceNodes as Doc<\"epistemicNodes\">[]) {\n const metadata = asRecord(node.metadata);\n if (\n args.normalizedUrl &&\n normalizeString(metadata.url) === args.normalizedUrl &&\n !urlMatch\n ) {\n urlMatch = node;\n }\n if (args.sha && normalizeString(metadata.contentSha) === args.sha && !shaMatch) {\n shaMatch = node;\n }\n if (urlMatch && (!args.sha || shaMatch)) {\n break;\n }\n }\n\n if (urlMatch && shaMatch && String(urlMatch._id) !== String(shaMatch._id)) {\n throwStructuredSourceError({\n message: \"Source identity conflict: URL and SHA resolve to different source nodes.\",\n status: 409,\n code: \"CONTENT_SHA_MISMATCH\",\n invariantCode: \"source.content_hash_immutable\",\n suggestion:\n \"Same source identity resolves to different records. Create a new source with a distinct URL or use fork semantics.\",\n details: {\n urlSourceId: String(urlMatch._id),\n shaSourceId: String(shaMatch._id),\n },\n });\n }\n\n return urlMatch ?? shaMatch;\n}\n\nfunction buildSourceMetadata(args: {\n existingMetadata?: Record<string, unknown>;\n normalizedUrl?: string;\n sha?: string;\n kind: string;\n capturedAt?: number;\n metadata?: Record<string, unknown>;\n}) {\n const existingMetadata = args.existingMetadata ?? {};\n const nextMetadata: Record<string, unknown> = {\n ...existingMetadata,\n kind: args.kind,\n ...args.metadata,\n };\n\n if (args.capturedAt !== undefined) {\n nextMetadata.capturedAt = args.capturedAt;\n }\n if (!Object.prototype.hasOwnProperty.call(existingMetadata, \"url\") && args.normalizedUrl) {\n nextMetadata.url = args.normalizedUrl;\n } else if (Object.prototype.hasOwnProperty.call(existingMetadata, \"url\")) {\n nextMetadata.url = existingMetadata.url;\n }\n if (!Object.prototype.hasOwnProperty.call(existingMetadata, \"contentSha\") && args.sha) {\n nextMetadata.contentSha = args.sha;\n } else if (Object.prototype.hasOwnProperty.call(existingMetadata, \"contentSha\")) {\n nextMetadata.contentSha = existingMetadata.contentSha;\n }\n\n return nextMetadata;\n}\n\nfunction sourceEmbeddingText(args: {\n title?: string;\n url?: string;\n kind: string;\n metadata: Record<string, unknown>;\n}) {\n const lines = [\n normalizeString(args.title),\n normalizeString(args.url),\n args.kind,\n normalizeString(args.metadata.sourceDescription),\n ].filter((value): value is string => Boolean(value));\n return lines.join(\"\\n\");\n}\n\nexport const upsertSource = mutation({\n args: {\n url: v.optional(v.string()),\n sha: v.optional(v.string()),\n kind: v.string(),\n title: v.optional(v.string()),\n capturedAt: v.optional(v.number()),\n metadata: v.optional(v.any()),\n topicId: v.optional(v.string()),\n userId: v.string(),\n },\n returns: permissiveReturn,\n handler: async (ctx, args) => {\n const sourceUrl = normalizeString(args.url);\n const normalizedUrl = sourceUrl ? normalizeSourceUrl(sourceUrl) : undefined;\n const sha = normalizeString(args.sha);\n\n if (!normalizedUrl && !sha) {\n throwStructuredSourceError({\n message: \"Source identity requires a URL or content SHA.\",\n status: 400,\n code: \"INVALID_REQUEST\",\n invariantCode: \"source.identity.required\",\n suggestion: \"Provide url or sha.\",\n });\n }\n\n const now = Date.now();\n const metadataPatch = normalizeMetadata(args.metadata);\n const existing = await findSourceByIdentity(ctx, { normalizedUrl, sha });\n\n if (existing) {\n if (existing.topicId && !(await checkScopeAccess(ctx, String(existing.topicId), args.userId))) {\n throwStructuredSourceError({\n message: \"Access denied to existing source scope.\",\n status: 403,\n code: \"FORBIDDEN\",\n invariantCode: \"policy.scope_required\",\n suggestion: \"Request access to the source topic scope and retry.\",\n details: { topicId: existing.topicId },\n });\n }\n\n const existingMetadata = asRecord(existing.metadata);\n const existingSha = normalizeString(existingMetadata.contentSha);\n if (sha && existingSha && existingSha !== sha) {\n throwStructuredSourceError({\n message: \"Same URL cannot be reused with a different content hash.\",\n status: 409,\n code: \"CONTENT_SHA_MISMATCH\",\n invariantCode: \"source.content_hash_immutable\",\n suggestion:\n \"Same URL, different content. Create a new source with a distinct URL or use fork semantics.\",\n details: {\n sourceId: String(existing._id),\n url: existingMetadata.url,\n existingSha,\n receivedSha: sha,\n },\n });\n }\n\n const nextMetadata = buildSourceMetadata({\n existingMetadata,\n kind: args.kind,\n capturedAt: normalizeNumber(args.capturedAt),\n metadata: metadataPatch,\n });\n\n const patch: Record<string, unknown> = {\n metadata: nextMetadata,\n updatedAt: now,\n };\n const title = normalizeString(args.title);\n if (title) {\n patch.title = title;\n patch.canonicalText = title;\n }\n\n await ctx.db.patch(existing._id, patch);\n\n await ctx.scheduler.runAfter(0, internal.neo4jSync.syncNodeToNeo4j, {\n nodeId: existing._id,\n operation: \"upsert\",\n });\n\n await ctx.db.insert(\"epistemicAudit\", {\n entityType: \"source\" as any,\n entityId: existing._id,\n changeType: \"source_metadata_updated\" as any,\n changedAt: now,\n changedBy: args.userId,\n isAgent: false,\n topicId: existing.topicId ? String(existing.topicId) : undefined,\n previousState: {\n title: existing.title,\n metadata: existingMetadata,\n },\n newState: {\n title: title ?? existing.title,\n metadata: nextMetadata,\n },\n } as any);\n\n return (await ctx.db.get(existing._id)) ?? existing;\n }\n\n if (!normalizeString(args.topicId)) {\n throwStructuredSourceError({\n message: \"topicId is required when creating a new source.\",\n status: 400,\n code: \"INVALID_REQUEST\",\n invariantCode: \"source.context_required\",\n suggestion: \"Provide topicId when creating a new source node.\",\n });\n }\n\n const scope = await resolveTopicProjectScope(ctx, {\n topicId: args.topicId,\n });\n assertWorkspaceScopedEpistemicNodeScope({\n scope,\n nodeType: \"source\",\n mutationName: \"epistemicSources.upsertSource\",\n });\n if (scope.projectId) {\n await requireProjectAccess(ctx, scope.projectId, args.userId);\n }\n\n const globalId = generateGlobalId();\n const title = normalizeString(args.title);\n const nextMetadata = buildSourceMetadata({\n normalizedUrl,\n sha,\n kind: args.kind,\n capturedAt: normalizeNumber(args.capturedAt),\n metadata: metadataPatch,\n });\n const nodeId = await insertEpistemicNode(ctx, {\n globalId,\n topicId: scope.topicId,\n projectId: scope.projectId,\n tenantId: scope.tenantId,\n workspaceId: scope.workspaceId,\n nodeType: \"source\",\n epistemicLayer: \"L1\",\n canonicalText: title ?? normalizedUrl ?? \"source\",\n contentHash: sha ?? generateSourceContentHash(normalizedUrl ?? title ?? \"source\"),\n ...(title ? { title } : {}),\n status: \"active\",\n createdAt: now,\n updatedAt: now,\n createdBy: args.userId,\n metadata: nextMetadata,\n });\n\n await ctx.scheduler.runAfter(0, internal.neo4jSync.syncNodeToNeo4j, {\n nodeId,\n operation: \"upsert\",\n });\n\n await scheduleEmbeddingGeneration({\n ctx,\n nodeId,\n projectId: scope.projectId,\n topicId: scope.topicId,\n createdBy: args.userId,\n nodeType: \"source\",\n text: sourceEmbeddingText({\n title,\n url: normalizedUrl,\n kind: args.kind,\n metadata: nextMetadata,\n }),\n });\n\n await ctx.db.insert(\"epistemicAudit\", {\n entityType: \"source\" as any,\n entityId: nodeId,\n changeType: \"source_created\" as any,\n changedAt: now,\n changedBy: args.userId,\n isAgent: false,\n topicId: scope.topicId ? String(scope.topicId) : undefined,\n previousState: null,\n newState: {\n title,\n url: normalizedUrl,\n contentSha: sha,\n kind: args.kind,\n },\n } as any);\n\n return await ctx.db.get(nodeId);\n },\n});\n\nexport const getById = query({\n args: {\n nodeId: v.optional(v.id(\"epistemicNodes\")),\n sourceId: v.optional(v.string()),\n },\n returns: permissiveReturn,\n handler: async (ctx, args) => {\n const id: Id<\"epistemicNodes\"> | undefined =\n args.nodeId ?? (args.sourceId as Id<\"epistemicNodes\"> | undefined);\n if (!id) {\n return null;\n }\n const node = (await ctx.db.get(\n id as Id<\"epistemicNodes\">\n )) as Doc<\"epistemicNodes\"> | null;\n if (!node || node.nodeType !== \"source\") {\n return null;\n }\n return node;\n },\n});\n\nexport const findByUrl = query({\n args: {\n url: v.string(),\n },\n returns: permissiveReturn,\n handler: async (ctx, args) => {\n const normalizedUrl = normalizeSourceUrl(args.url);\n const node = await findSourceByIdentity(ctx, { normalizedUrl });\n return node && node.nodeType === \"source\" ? node : null;\n },\n});\n\nexport const findBySha = query({\n args: {\n sha: v.string(),\n },\n returns: permissiveReturn,\n handler: async (ctx, args) => {\n const sha = normalizeString(args.sha);\n if (!sha) {\n return null;\n }\n const node = await findSourceByIdentity(ctx, { sha });\n return node && node.nodeType === \"source\" ? node : null;\n },\n});\n"]}
1
+ {"version":3,"sources":["../src/convex.ts","../src/debug.ts","../src/embeddingTrigger.ts","../src/topicScope.ts","../src/workspaceIsolation.ts","../src/epistemicInsert.ts","../src/epistemicSources.ts"],"names":["normalizeScopeValue","v","nextMetadata","title"],"mappings":"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","file":"epistemicSources.js","sourcesContent":["import {\n actionGeneric,\n anyApi,\n componentsGeneric,\n httpActionGeneric,\n internalActionGeneric,\n internalMutationGeneric,\n internalQueryGeneric,\n mutationGeneric,\n queryGeneric,\n} from \"convex/server\";\nimport type { GenericId } from \"convex/values\";\n\nexport const api = anyApi as any;\nexport const components = componentsGeneric() as any;\nexport const internal = anyApi as any;\n\nexport type TableNames = string;\nexport type Id<TableName extends TableNames = string> = GenericId<TableName>;\nexport type Doc<TableName extends TableNames = string> = any;\nexport type DataModel = any;\ntype IndexRangeBuilder = {\n field(fieldName: string): string;\n eq(fieldName: string, value: unknown): IndexRangeBuilder;\n gt(fieldName: string, value: unknown): IndexRangeBuilder;\n gte(fieldName: string, value: unknown): IndexRangeBuilder;\n lt(fieldName: string, value: unknown): IndexRangeBuilder;\n lte(fieldName: string, value: unknown): IndexRangeBuilder;\n};\ntype FilterBuilder = {\n eq(left: unknown, right: unknown): unknown;\n neq(left: unknown, right: unknown): unknown;\n gt(left: unknown, right: unknown): unknown;\n gte(left: unknown, right: unknown): unknown;\n lt(left: unknown, right: unknown): unknown;\n lte(left: unknown, right: unknown): unknown;\n and(...clauses: unknown[]): unknown;\n or(...clauses: unknown[]): unknown;\n field(fieldName: string): unknown;\n};\ntype QueryInitializer<TableName extends TableNames> = {\n withIndex(\n indexName: string,\n range?: (q: any) => unknown\n ): QueryInitializer<TableName>;\n filter(predicate: (q: any) => unknown): QueryInitializer<TableName>;\n order(direction: \"asc\" | \"desc\"): QueryInitializer<TableName>;\n collect(): Promise<Doc<TableName>[]>;\n take(limit: number): Promise<Doc<TableName>[]>;\n first(): Promise<Doc<TableName> | null>;\n unique(): Promise<Doc<TableName> | null>;\n};\nexport type DatabaseReader = {\n get<TableName extends TableNames>(\n id: Id<TableName>\n ): Promise<Doc<TableName> | null>;\n query<TableName extends TableNames>(\n tableName: TableName\n ): QueryInitializer<TableName>;\n normalizeId?<TableName extends TableNames>(\n tableName: TableName,\n id: string\n ): Id<TableName> | null;\n};\nexport type DatabaseWriter = DatabaseReader & {\n insert<TableName extends TableNames>(\n tableName: TableName,\n value: Record<string, unknown>\n ): Promise<Id<TableName>>;\n patch<TableName extends TableNames>(\n id: Id<TableName>,\n value: Record<string, unknown>\n ): Promise<void>;\n replace<TableName extends TableNames>(\n id: Id<TableName>,\n value: Record<string, unknown>\n ): Promise<void>;\n delete<TableName extends TableNames>(id: Id<TableName>): Promise<void>;\n};\ntype Scheduler = {\n runAfter(delayMs: number, functionReference: unknown, args?: unknown): Promise<void>;\n};\ntype AuthReader = {\n getUserIdentity(): Promise<unknown>;\n};\ntype RuntimeInvoker = {\n runQuery(functionReference: unknown, args?: unknown): Promise<any>;\n runMutation(functionReference: unknown, args?: unknown): Promise<any>;\n runAction(functionReference: unknown, args?: unknown): Promise<any>;\n};\nexport type QueryCtx = RuntimeInvoker & {\n auth: AuthReader;\n db: DatabaseReader;\n scheduler: Scheduler;\n};\nexport type MutationCtx = RuntimeInvoker & {\n auth: AuthReader;\n db: DatabaseWriter;\n scheduler: Scheduler;\n};\nexport type ActionCtx = RuntimeInvoker & {\n auth: AuthReader;\n scheduler: Scheduler;\n};\n\ntype ConvexFunctionBuilder<Ctx> = <\n Definition extends { handler?: (ctx: Ctx, args: any) => any },\n>(\n definition: Definition\n) => any;\n\nexport const action = actionGeneric as unknown as ConvexFunctionBuilder<ActionCtx>;\nexport const httpAction =\n httpActionGeneric as unknown as ConvexFunctionBuilder<ActionCtx>;\nexport const internalAction =\n internalActionGeneric as unknown as ConvexFunctionBuilder<ActionCtx>;\nexport const internalMutation =\n internalMutationGeneric as unknown as ConvexFunctionBuilder<MutationCtx>;\nexport const internalQuery =\n internalQueryGeneric as unknown as ConvexFunctionBuilder<QueryCtx>;\nexport const mutation =\n mutationGeneric as unknown as ConvexFunctionBuilder<MutationCtx>;\nexport const query = queryGeneric as unknown as ConvexFunctionBuilder<QueryCtx>;\n","type GraphPrimitiveDebugEnvironment = {\n process?: {\n env?: Record<string, string | undefined>;\n };\n};\n\nfunction isGraphPrimitiveDebugEnabled(): boolean {\n const env = (globalThis as GraphPrimitiveDebugEnvironment).process?.env;\n return (\n env?.LUCERN_COMPAT_FALLBACK_DEBUG === \"1\" ||\n env?.LUCERN_GRAPH_DEBUG === \"1\"\n );\n}\n\nexport function formatGraphPrimitiveError(error: unknown): string {\n if (error instanceof Error) {\n return `${error.name}: ${error.message}`;\n }\n if (typeof error === \"string\") {\n return error;\n }\n if (error === null) {\n return \"null\";\n }\n if (error === undefined) {\n return \"undefined\";\n }\n try {\n return JSON.stringify(error);\n } catch {\n return Object.prototype.toString.call(error);\n }\n}\n\nexport function debugGraphPrimitiveFallback(\n message: string,\n context?: Record<string, unknown>\n): void {\n if (!isGraphPrimitiveDebugEnabled()) {\n return;\n }\n console.debug(message, context ?? {});\n}\n","/**\n * Shared helper to schedule embedding generation after epistemic node creation.\n *\n * Best-effort — failures are silently caught. The embedding generation action\n * is a public action in convex/embeddingActions.ts that calls Pinecone.\n */\n\nimport type { Id } from \"./convex\";\nimport { debugGraphPrimitiveFallback } from \"./debug\";\n\ninterface EmbeddingTriggerArgs {\n ctx: any;\n nodeId: Id<\"epistemicNodes\">;\n projectId?: string | null;\n topicId?: string | null;\n createdBy: string;\n nodeType:\n | \"belief\"\n | \"question\"\n | \"evidence\"\n | \"answer\"\n | \"synthesis\"\n | \"theme\"\n | \"source\";\n text: string;\n hasAnswer?: boolean;\n confidence?: number;\n}\n\nexport async function scheduleEmbeddingGeneration(\n args: EmbeddingTriggerArgs,\n): Promise<void> {\n try {\n await args.ctx.scheduler.runAfter(\n 0,\n \"embeddingActions:generateEpistemicNodeEmbedding\" as any,\n {\n nodeId: args.nodeId,\n projectId: args.projectId ? String(args.projectId) : undefined,\n topicId: args.topicId ? String(args.topicId) : undefined,\n createdBy: args.createdBy,\n nodeType: args.nodeType,\n text: args.text.slice(0, 20_000),\n hasAnswer: args.hasAnswer,\n confidence: args.confidence,\n },\n );\n } catch (error) {\n debugGraphPrimitiveFallback(\n \"[embeddingTrigger] Failed to schedule embedding generation\",\n {\n error,\n nodeId: String(args.nodeId),\n nodeType: args.nodeType,\n },\n );\n // Embedding generation is best-effort — never block node creation\n }\n}\n","/** Topic-scope resolution helpers for graph-primitive operations. */\nimport { v } from \"convex/values\";\nimport { api as appApi } from \"./convex\";\nimport type { Id } from \"./convex\";\nimport { debugGraphPrimitiveFallback } from \"./debug\";\n\nconst LEGACY_SCOPE_FIELD = \"graphScope\" + \"ProjectId\";\n\ntype TopicDoc = Record<string, unknown> & {\n _id: Id<\"topics\">;\n globalId?: string;\n name?: string;\n depth?: number;\n createdAt?: number;\n parentTopicId?: Id<\"topics\">;\n tenantId?: string;\n workspaceId?: string;\n metadata?: Record<string, unknown>;\n};\n\nexport type TopicProjectScope = {\n topicId: Id<\"topics\">;\n projectId?: string;\n tenantId?: string;\n workspaceId?: string;\n source:\n | \"topic\"\n | \"project_mapped_topic\"\n | \"topic_inferred\"\n | \"topic_node\";\n};\n\n/**\n * RR.5 (legacy topics-table retirement) — graph-primitives mirror of the\n * kernel's epistemicNodes-first topic-scope fallback. Kept in lockstep with\n * `packages/reasoning-kernel/src/adapters/lib/topicScope.ts`\n * (`tests/unit/convex/topic-scope-fallbacks.test.ts` asserts parity).\n *\n * Resolves a topic that exists only as `epistemicNodes(nodeType=\"topic\")` —\n * the write-of-record — when no legacy `topics` row backs the ref, returning the\n * node's `topicId` self-key so scoped beliefs/evidence/questions stay reachable.\n * See the kernel module for the full silent-empty-result rationale.\n */\ntype TopicNodeScopeDoc = {\n _id: string | Id<\"epistemicNodes\">;\n globalId?: string;\n nodeType?: string;\n topicId?: string;\n metadata?: Record<string, unknown>;\n};\n\nasync function resolveTopicNodeScopeOrNull(\n ctx: any,\n ref: string,\n): Promise<TopicProjectScope | null> {\n if (!ctx?.db || typeof ctx.db.query !== \"function\") {\n return null;\n }\n\n let node: TopicNodeScopeDoc | null = null;\n\n // 1. The ref IS the topic node's UUIDv7 globalId.\n try {\n const byGlobalId = (await ctx.db\n .query(\"epistemicNodes\")\n .withIndex(\"by_globalId\", (q: any) => q.eq(\"globalId\", ref))\n .first()) as TopicNodeScopeDoc | null;\n if (byGlobalId && byGlobalId.nodeType === \"topic\") {\n node = byGlobalId;\n }\n } catch (error) {\n debugGraphPrimitiveFallback(\n \"[topicScope] topic-node scope lookup by globalId failed\",\n { error, ref },\n );\n }\n\n if (!node) {\n return null;\n }\n\n const scopeKey =\n normalizeScopeValue(node.topicId) ?? normalizeScopeValue(node.globalId);\n if (!scopeKey) {\n return null;\n }\n\n return {\n topicId: scopeKey as Id<\"topics\">,\n projectId: asMappedProjectId(node as unknown as TopicDoc),\n source: \"topic_node\",\n };\n}\n\ntype MaterializedTopicNodeDoc = {\n _id: string | Id<\"epistemicNodes\">;\n metadata?: Record<string, unknown>;\n};\n\nfunction asMappedProjectId(\n topic: TopicDoc | null | undefined,\n): string | undefined {\n if (!topic) {\n return;\n }\n const directLegacyProjectId = normalizeScopeValue(topic[LEGACY_SCOPE_FIELD]);\n if (directLegacyProjectId) {\n return directLegacyProjectId;\n }\n const metadata = (topic.metadata || {}) as Record<string, unknown>;\n const candidate =\n (metadata[LEGACY_SCOPE_FIELD] as string | undefined) ||\n (metadata.legacyProjectId as string | undefined) ||\n (metadata.projectId as string | undefined) ||\n (metadata.scopeProjectId as string | undefined);\n return candidate ? (candidate as string) : undefined;\n}\n\nfunction normalizeScopeValue(value: unknown): string | undefined {\n if (typeof value !== \"string\") {\n return;\n }\n const normalized = value.trim();\n return normalized.length > 0 ? normalized : undefined;\n}\n\nfunction pickPrimaryTopic(candidates: TopicDoc[]): TopicDoc | undefined {\n return [...candidates].sort((a, b) => {\n const depthA = a.depth ?? 9999;\n const depthB = b.depth ?? 9999;\n if (depthA !== depthB) {\n return depthA - depthB;\n }\n const createdA = a.createdAt ?? Number.MAX_SAFE_INTEGER;\n const createdB = b.createdAt ?? Number.MAX_SAFE_INTEGER;\n if (createdA !== createdB) {\n return createdA - createdB;\n }\n return String(a.name || \"\").localeCompare(String(b.name || \"\"));\n })[0];\n}\n\nasync function findTopicsByScopeAlias(\n ctx: any,\n scopeId: string,\n): Promise<TopicDoc[]> {\n try {\n return (await ctx.db\n .query(\"topics\")\n .withIndex(\"by_graph_scope_project\", (q: any) =>\n q.eq(LEGACY_SCOPE_FIELD, scopeId),\n )\n .collect()) as TopicDoc[];\n } catch (error) {\n debugGraphPrimitiveFallback(\n \"[topicScope] Failed to resolve scope alias via index\",\n {\n error,\n scopeId,\n },\n );\n // Older Lucern dev deployments can lag index backfills while still carrying\n // the underlying topics table. Scan and filter so scope resolution keeps\n // working during the rollout.\n const topics = (await ctx.db.query(\"topics\").collect()) as TopicDoc[];\n return topics.filter((topic) => {\n const normalizedGlobalId = normalizeScopeValue(topic.globalId);\n const mappedProjectId = asMappedProjectId(topic);\n return (\n String(topic._id) === scopeId ||\n normalizedGlobalId === scopeId ||\n mappedProjectId === scopeId\n );\n });\n }\n}\n\nasync function tryResolveHostTopicById(\n ctx: any,\n topicId: string,\n): Promise<TopicDoc | null> {\n if (typeof ctx.runQuery !== \"function\") {\n return null;\n }\n try {\n return ((await ctx.runQuery(appApi.topics.get as any, {\n id: topicId,\n })) ?? null) as TopicDoc | null;\n } catch (error) {\n debugGraphPrimitiveFallback(\n \"[topicScope] Failed to resolve topic by host query\",\n {\n error,\n topicId,\n },\n );\n return null;\n }\n}\n\nasync function tryResolveHostTopicByLegacyScope(\n ctx: any,\n legacyScopeId: string,\n): Promise<TopicDoc | null> {\n if (typeof ctx.runQuery !== \"function\") {\n return null;\n }\n try {\n return ((await ctx.runQuery(appApi.topics.getByLegacyScopeId as any, {\n projectId: legacyScopeId,\n })) ?? null) as TopicDoc | null;\n } catch (error) {\n debugGraphPrimitiveFallback(\n \"[topicScope] Failed to resolve topic by legacy scope\",\n {\n error,\n legacyScopeId,\n },\n );\n return null;\n }\n}\n\nexport function readMaterializedTopicTableId(\n topicNode: MaterializedTopicNodeDoc | null | undefined,\n): string | undefined {\n if (!topicNode) {\n return;\n }\n\n const metadata = (topicNode.metadata || {}) as Record<string, unknown>;\n const topicTableId =\n (metadata.topicTableId as string | undefined) ||\n (metadata.topicId as string | undefined);\n\n return typeof topicTableId === \"string\" && topicTableId.trim().length > 0\n ? topicTableId.trim()\n : undefined;\n}\n\n/**\n * Walk the topic parent chain to find inherited workspaceId and tenantId.\n * Mirrors the pattern used by resolveTopicOntology for ontologyId inheritance.\n * Max depth: 10 (defensive limit against pathological nesting).\n */\nasync function resolveInheritedWorkspaceScope(\n ctx: any,\n topic: TopicDoc,\n): Promise<{ tenantId?: string; workspaceId?: string }> {\n const MAX_DEPTH = 10;\n let tenantId = normalizeScopeValue(topic.tenantId);\n let workspaceId = normalizeScopeValue(topic.workspaceId);\n\n if (tenantId && workspaceId) {\n return { tenantId, workspaceId };\n }\n\n let current: TopicDoc | null = topic;\n for (let i = 0; i < MAX_DEPTH && current?.parentTopicId; i++) {\n current = (await ctx.db.get(current.parentTopicId)) as TopicDoc | null;\n if (!current) break;\n\n if (!tenantId) {\n tenantId = normalizeScopeValue(current.tenantId);\n }\n if (!workspaceId) {\n workspaceId = normalizeScopeValue(current.workspaceId);\n }\n if (tenantId && workspaceId) break;\n }\n\n return { tenantId, workspaceId };\n}\n\nexport async function resolveTopicProjectScope(\n ctx: any,\n args: { topicId?: Id<\"topics\"> | string; projectId?: string },\n): Promise<TopicProjectScope> {\n if (args.topicId) {\n // Try direct lookup, fall back to the legacy mapped-project bridge\n let topic: TopicDoc | null = null;\n try {\n topic = (await ctx.db.get(\n args.topicId as Id<\"topics\">,\n )) as TopicDoc | null;\n } catch (error) {\n debugGraphPrimitiveFallback(\n \"[topicScope] Failed to load topic by direct id\",\n {\n error,\n topicId: args.topicId,\n },\n );\n // Not a valid topics table ID\n }\n if (!topic) {\n topic = await tryResolveHostTopicById(ctx, String(args.topicId));\n }\n if (!topic) {\n // Try as legacy projectId / globalId via the mapped-project bridge.\n topic =\n pickPrimaryTopic(\n await findTopicsByScopeAlias(ctx, String(args.topicId)),\n ) ?? null;\n }\n if (!topic) {\n // RR.5: no legacy topics row — resolve the canonical topic node store\n // before throwing (silent-empty-result fix).\n const nodeScope = await resolveTopicNodeScopeOrNull(\n ctx,\n String(args.topicId),\n );\n if (nodeScope) {\n return nodeScope;\n }\n throw new Error(`Topic not found: ${String(args.topicId)}`);\n }\n const inherited = await resolveInheritedWorkspaceScope(ctx, topic);\n const mapped = asMappedProjectId(topic);\n if (mapped) {\n return {\n topicId: topic._id,\n projectId: mapped,\n tenantId: inherited.tenantId,\n workspaceId: inherited.workspaceId,\n source: \"topic\",\n };\n }\n return {\n topicId: topic._id,\n tenantId: inherited.tenantId,\n workspaceId: inherited.workspaceId,\n source: \"topic\",\n };\n }\n\n if (args.projectId) {\n let directTopic: TopicDoc | null = null;\n try {\n directTopic = (await ctx.db.get(\n args.projectId as Id<\"topics\">,\n )) as TopicDoc | null;\n } catch (error) {\n debugGraphPrimitiveFallback(\n \"[topicScope] Failed to load direct project topic\",\n {\n error,\n projectId: args.projectId,\n },\n );\n // Not a valid topics table ID, continue to legacy graph-scope lookup.\n }\n\n if (directTopic) {\n const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);\n const mapped = asMappedProjectId(directTopic);\n return {\n topicId: directTopic._id,\n projectId: mapped ?? args.projectId,\n tenantId: inherited.tenantId,\n workspaceId: inherited.workspaceId,\n source: \"topic_inferred\",\n };\n }\n\n directTopic = await tryResolveHostTopicByLegacyScope(ctx, args.projectId);\n if (directTopic) {\n const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);\n const mapped = asMappedProjectId(directTopic);\n return {\n topicId: directTopic._id,\n projectId: mapped ?? args.projectId,\n tenantId: inherited.tenantId,\n workspaceId: inherited.workspaceId,\n source: \"topic_inferred\",\n };\n }\n\n const topics = await findTopicsByScopeAlias(ctx, args.projectId);\n const primary = pickPrimaryTopic(topics);\n if (primary) {\n const inherited = await resolveInheritedWorkspaceScope(ctx, primary);\n return {\n topicId: primary._id,\n projectId: args.projectId,\n tenantId: inherited.tenantId,\n workspaceId: inherited.workspaceId,\n source: \"project_mapped_topic\",\n };\n }\n // RR.5: try the canonical topic node store before failing.\n const nodeScope = await resolveTopicNodeScopeOrNull(\n ctx,\n String(args.projectId),\n );\n if (nodeScope) {\n return {\n ...nodeScope,\n projectId: nodeScope.projectId ?? String(args.projectId),\n };\n }\n\n throw new Error(\n `Legacy project scope ${String(args.projectId)} has no mapped topic.`,\n );\n }\n\n throw new Error(\n \"Missing scope: provide topicId (preferred) or legacy projectId alias.\",\n );\n}\n\n/** Shared scope args for graph-primitive functions. topicId is canonical; projectId is a legacy alias. */\nexport const optionalScopeArgs = {\n projectId: v.optional(v.string()),\n topicId: v.optional(v.string()),\n} as const;\n","import {\n getLayerForNodeType,\n isNodeType,\n} from \"@lucern/contracts/schema-helpers/spine/tables/epistemicNodes\";\nimport {\n resolveTopicProjectScope,\n type TopicProjectScope,\n} from \"./topicScope\";\n\ntype StructuredInvariantError = Error & {\n status: number;\n code: string;\n invariantCode?: string;\n suggestion?: string;\n details?: unknown;\n};\n\ntype ScopeLike = {\n tenantId?: unknown;\n workspaceId?: unknown;\n epistemicLayer?: unknown;\n nodeType?: unknown;\n topicId?: unknown;\n projectId?: unknown;\n publicationStatus?: unknown;\n};\n\nexport type RuntimePackMutationContext = {\n toolName?: string;\n packKey?: string;\n packInstallScope?: \"tenant\" | \"workspace\";\n};\n\nexport function normalizeScopeValue(value: unknown): string | undefined {\n if (typeof value !== \"string\") {\n return;\n }\n const normalized = value.trim();\n return normalized.length > 0 ? normalized : undefined;\n}\n\nfunction throwWorkspaceIsolationError(args: {\n message: string;\n invariantCode: string;\n suggestion: string;\n details?: unknown;\n}): never {\n const error = new Error(args.message) as StructuredInvariantError;\n error.status = 409;\n error.code = \"INVARIANT_VIOLATION\";\n error.invariantCode = args.invariantCode;\n error.suggestion = args.suggestion;\n error.details = args.details;\n throw error;\n}\n\nexport function assertWorkspaceScopedEpistemicNodeScope(args: {\n scope: TopicProjectScope;\n nodeType: string;\n mutationName: string;\n}): void {\n const layer = isNodeType(args.nodeType)\n ? getLayerForNodeType(args.nodeType)\n : undefined;\n if (layer === \"ontological\") {\n return;\n }\n\n const workspaceId = normalizeScopeValue(args.scope.workspaceId);\n if (workspaceId) {\n return;\n }\n\n throwWorkspaceIsolationError({\n message:\n \"Workspace-scoped reasoning isolation requires workspaceId on non-ontological node creation.\",\n invariantCode: \"workspace.scope_required_for_epistemic_nodes\",\n suggestion:\n \"Resolve the topic/project scope through a workspace-bound topic before creating epistemic nodes.\",\n details: {\n mutationName: args.mutationName,\n nodeType: args.nodeType,\n topicId: args.scope.topicId,\n projectId: args.scope.projectId,\n },\n });\n}\n\nexport function nodeMatchesWorkspaceReasoningScope(\n node: ScopeLike | null | undefined,\n scope: Pick<TopicProjectScope, \"tenantId\" | \"workspaceId\">\n): boolean {\n if (!node) {\n return false;\n }\n\n const scopeTenantId = normalizeScopeValue(scope.tenantId);\n const scopeWorkspaceId = normalizeScopeValue(scope.workspaceId);\n const nodeTenantId = normalizeScopeValue(node.tenantId);\n const nodeWorkspaceId = normalizeScopeValue(node.workspaceId);\n const epistemicLayer =\n typeof node.epistemicLayer === \"string\" ? node.epistemicLayer : undefined;\n\n if (\n scopeTenantId &&\n nodeTenantId &&\n scopeTenantId !== nodeTenantId\n ) {\n return false;\n }\n\n // Ontological entities are tenant-global (no workspace required)\n if (epistemicLayer === \"ontological\" && nodeWorkspaceId === undefined) {\n return true;\n }\n\n // Published nodes are visible at tenant scope — the microservice API surface.\n // The node stays in its workspace, but tenant-scope queries can see it.\n if (!scopeWorkspaceId && node.publicationStatus === \"published\") {\n return true;\n }\n\n if (!scopeWorkspaceId) {\n return nodeWorkspaceId === undefined;\n }\n\n return scopeWorkspaceId === nodeWorkspaceId;\n}\n\nexport function edgeMatchesWorkspaceReasoningScope(\n edge: ScopeLike | null | undefined,\n scope: Pick<TopicProjectScope, \"tenantId\" | \"workspaceId\">\n): boolean {\n if (!edge) {\n return false;\n }\n\n const scopeTenantId = normalizeScopeValue(scope.tenantId);\n const scopeWorkspaceId = normalizeScopeValue(scope.workspaceId);\n const edgeTenantId = normalizeScopeValue(edge.tenantId);\n const edgeWorkspaceId = normalizeScopeValue(edge.workspaceId);\n\n if (\n scopeTenantId &&\n edgeTenantId &&\n scopeTenantId !== edgeTenantId\n ) {\n return false;\n }\n\n if (!scopeWorkspaceId) {\n return edgeWorkspaceId === undefined;\n }\n\n return scopeWorkspaceId === edgeWorkspaceId;\n}\n\nexport async function resolveNodeScopeForWorkspaceIsolation(\n ctx: any,\n node: ScopeLike | null | undefined\n): Promise<{\n tenantId?: string;\n workspaceId?: string;\n epistemicLayer?: string;\n nodeType?: string;\n}> {\n const epistemicLayer =\n typeof node?.epistemicLayer === \"string\" ? node.epistemicLayer : undefined;\n const resolved = {\n tenantId: normalizeScopeValue(node?.tenantId),\n workspaceId: normalizeScopeValue(node?.workspaceId),\n epistemicLayer,\n nodeType: typeof node?.nodeType === \"string\" ? node.nodeType : undefined,\n };\n\n if (!node) {\n return resolved;\n }\n\n if (resolved.epistemicLayer === \"ontological\") {\n return resolved;\n }\n\n if (resolved.tenantId || resolved.workspaceId) {\n return resolved;\n }\n\n if (node.topicId) {\n const topicScope = await resolveTopicProjectScope(ctx, {\n topicId: node.topicId as any,\n });\n return {\n ...resolved,\n tenantId: topicScope.tenantId,\n workspaceId: topicScope.workspaceId,\n };\n }\n\n if (node.projectId) {\n const topicScope = await resolveTopicProjectScope(ctx, {\n projectId: String(node.projectId),\n });\n return {\n ...resolved,\n tenantId: topicScope.tenantId,\n workspaceId: topicScope.workspaceId,\n };\n }\n\n return resolved;\n}\n\nexport function resolveRuntimePackMutationContext(args: {\n runtimeToolName?: string;\n runtimePackKey?: string;\n runtimePackInstallScope?: \"tenant\" | \"workspace\";\n}): RuntimePackMutationContext | undefined {\n if (\n !args.runtimeToolName &&\n !args.runtimePackKey &&\n !args.runtimePackInstallScope\n ) {\n return;\n }\n\n return {\n toolName: args.runtimeToolName,\n packKey: args.runtimePackKey,\n packInstallScope: args.runtimePackInstallScope,\n };\n}\n\nexport function assertTenantPackWorkspaceMutationAllowed(args: {\n runtime?: RuntimePackMutationContext;\n target: ScopeLike;\n mutationName: string;\n}): void {\n if (\n !args.runtime?.packKey ||\n args.runtime.packInstallScope !== \"tenant\"\n ) {\n return;\n }\n\n const targetWorkspaceId = normalizeScopeValue(args.target.workspaceId);\n const targetLayer =\n typeof args.target.epistemicLayer === \"string\"\n ? args.target.epistemicLayer\n : undefined;\n\n if (!targetWorkspaceId || targetLayer === \"ontological\") {\n return;\n }\n\n throwWorkspaceIsolationError({\n message:\n `Tenant-scoped pack \"${args.runtime.packKey}\" cannot mutate workspace-scoped reasoning state.`,\n invariantCode: \"workspace.tenant_pack_reasoning_write_forbidden\",\n suggestion:\n \"Use a workspace-scoped pack for workspace-local graph mutations, or route the change through tenant-global canonical entity flows.\",\n details: {\n mutationName: args.mutationName,\n toolName: args.runtime.toolName,\n packKey: args.runtime.packKey,\n targetWorkspaceId,\n targetNodeType: args.target.nodeType,\n targetLayer,\n },\n });\n}\n","import type { WithoutSystemFields } from \"convex/server\";\nimport {\n assertUuidV7Identity,\n assertStorageEdgeVocabulary,\n assertUuidShapedEdgeEndpoint,\n} from \"@lucern/contracts/ids\";\nimport {\n assertEdgePolicyAllowed,\n edgePolicyManifest,\n type EpistemicNodeType,\n} from \"@lucern/contracts\";\nimport type { Doc, Id, MutationCtx } from \"./convex\";\n\nexport async function insertEpistemicNode(\n ctx: MutationCtx,\n doc: WithoutSystemFields<Doc<\"epistemicNodes\">>,\n): Promise<Id<\"epistemicNodes\">> {\n assertUuidV7Identity(\"epistemicNodes\", doc.globalId);\n return ctx.db.insert(\"epistemicNodes\", doc);\n}\n\n/**\n * C2-RR.4b — REFERENTIAL edge-endpoint canonicality (amends RR.4's FORMAT guard).\n *\n * Proves an endpoint is the `globalId` of an EXISTING `epistemicNodes` row, not\n * that it has a v7 shape. Refuses doc-ids and fabricated/unknown endpoints while\n * keeping legacy v4-`globalId` nodes (the established prod corpus) linkable.\n * SHAPE pre-filter accepts both v4 and v7; the indexed `by_globalId` lookup is\n * the referential authority (no full scan). v7-format stays enforced only at new\n * identity minting (`assertUuidV7Identity`). See c2-rr4b-endpoint-referential.\n */\nasync function assertExistingNodeEndpoint(\n ctx: MutationCtx,\n endpointRole: \"fromNodeId\" | \"toNodeId\",\n endpoint: string,\n): Promise<void> {\n assertUuidShapedEdgeEndpoint(endpointRole, endpoint);\n const node = await ctx.db\n .query(\"epistemicNodes\")\n .withIndex(\"by_globalId\", (q: any) => q.eq(\"globalId\", endpoint))\n .first();\n if (!node) {\n throw new Error(\n `edge_endpoint_not_canonical: epistemicEdges insert requires ${endpointRole} to be the globalId of an existing epistemicNodes row, received ${endpoint} (no node with that globalId)`,\n );\n }\n}\n\nexport async function insertEpistemicEdge(\n ctx: MutationCtx,\n doc: WithoutSystemFields<Doc<\"epistemicEdges\">>,\n): Promise<Id<\"epistemicEdges\">> {\n assertUuidV7Identity(\"epistemicEdges\", doc.globalId);\n\n // R1.1a — STORAGE-VOCABULARY MEMBERSHIP\n assertStorageEdgeVocabulary(doc.edgeType);\n\n // R1.1b — ENDPOINT PRESENCE\n if (!doc.fromNodeId || typeof doc.fromNodeId !== \"string\") {\n throw new Error(\n \"edge_endpoint_missing: epistemicEdges insert requires a non-empty fromNodeId\"\n );\n }\n if (!doc.toNodeId || typeof doc.toNodeId !== \"string\") {\n throw new Error(\n \"edge_endpoint_missing: epistemicEdges insert requires a non-empty toNodeId\"\n );\n }\n\n // C2-RR.4b Defect E (REFERENTIAL) — ENDPOINT CANONICAL IDENTITY. Edge\n // endpoints must each be the globalId of an EXISTING epistemicNodes row,\n // never a Convex doc id, a legacy topic id, or a fabricated/unknown uuid.\n // This refuses the mixed _id/globalId endpoint writes at the floor while\n // keeping legacy v4-globalId nodes linkable (RR.4b prod-incident cure).\n await assertExistingNodeEndpoint(ctx, \"fromNodeId\", doc.fromNodeId);\n await assertExistingNodeEndpoint(ctx, \"toNodeId\", doc.toNodeId);\n\n // R1.1c — FULL POLICY ASSERT (when nodeTypes are present and edgeType is in public manifest)\n if (doc.fromNodeType && doc.toNodeType && doc.edgeType !== \"extracted_from\") {\n assertEdgePolicyAllowed(\n edgePolicyManifest,\n doc.edgeType,\n {\n kind: \"epistemic_node\",\n nodeId: doc.fromNodeId,\n nodeType: doc.fromNodeType as EpistemicNodeType,\n },\n {\n kind: \"epistemic_node\",\n nodeId: doc.toNodeId,\n nodeType: doc.toNodeType as EpistemicNodeType,\n }\n );\n }\n\n return ctx.db.insert(\"epistemicEdges\", doc);\n}\n","/**\n * Epistemic Sources API\n *\n * Invariants:\n * - Invariant 7: evidence is context-bound. Sources carry topic, author, and capture time.\n * - Invariant 8: no retroactive reinterpretation. Source identity fields stay immutable.\n * - Invariant 14: no silent state transitions. Every create/update is audited.\n * - Invariant 15: retrieval respects boundaries. Sources live at L1 terminal leaves.\n */\n\nimport { v } from \"convex/values\";\nimport {\n checkScopeAccess,\n requireProjectAccess,\n} from \"@lucern/access-control/access\";\nimport { permissiveReturn } from \"@lucern/contracts/schema-helpers/validators\";\nimport type { Doc, Id } from \"./convex\";\nimport { internal, mutation, query } from \"./convex\";\nimport { scheduleEmbeddingGeneration } from \"./embeddingTrigger\";\nimport { generateGlobalId } from \"./globalId\";\nimport {\n type EpistemicDbReader,\n} from \"./epistemicQuestions.helpers\";\nimport { resolveTopicProjectScope } from \"./topicScope\";\nimport { assertWorkspaceScopedEpistemicNodeScope } from \"./workspaceIsolation\";\nimport { insertEpistemicNode } from \"./epistemicInsert.js\";\n\ntype StructuredSourceError = Error & {\n status: number;\n code: string;\n invariantCode?: string;\n suggestion?: string;\n details?: unknown;\n};\n\nfunction throwStructuredSourceError(args: {\n message: string;\n status: number;\n code: string;\n invariantCode?: string;\n suggestion?: string;\n details?: unknown;\n}): never {\n const error = new Error(args.message) as StructuredSourceError;\n error.status = args.status;\n error.code = args.code;\n error.invariantCode = args.invariantCode;\n error.suggestion = args.suggestion;\n error.details = args.details;\n throw error;\n}\n\nfunction normalizeString(value: unknown): string | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n const normalized = value.trim();\n return normalized.length > 0 ? normalized : undefined;\n}\n\nfunction normalizeNumber(value: unknown): number | undefined {\n return typeof value === \"number\" && Number.isFinite(value) ? value : undefined;\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {};\n}\n\nfunction normalizeMetadata(\n metadata: unknown\n): Record<string, unknown> {\n const record = asRecord(metadata);\n const { url: _ignoredUrl, contentSha: _ignoredSha, ...rest } = record;\n return rest;\n}\n\nfunction generateSourceContentHash(identity: string): string {\n const content = `source:${identity.trim().toLowerCase()}`;\n let hash = 5381;\n for (let index = 0; index < content.length; index += 1) {\n hash = (hash << 5) + hash + content.charCodeAt(index);\n hash &= hash;\n }\n return Math.abs(hash).toString(16).padStart(8, \"0\");\n}\n\nexport function normalizeSourceUrl(url: string): string {\n const trimmed = normalizeString(url);\n if (!trimmed) {\n throwStructuredSourceError({\n message: \"Source URL is required.\",\n status: 400,\n code: \"INVALID_REQUEST\",\n invariantCode: \"source.url.valid\",\n suggestion: \"Provide an absolute URL with a valid protocol and host.\",\n });\n }\n\n let parsed: URL;\n try {\n parsed = new URL(trimmed);\n } catch {\n throwStructuredSourceError({\n message: `Invalid URL: ${trimmed}`,\n status: 400,\n code: \"INVALID_REQUEST\",\n invariantCode: \"source.url.valid\",\n suggestion: \"Provide an absolute URL with a valid protocol and host.\",\n details: { url: trimmed },\n });\n }\n\n const protocol = parsed.protocol.toLowerCase();\n const hostname = parsed.hostname.toLowerCase();\n const port = parsed.port ? `:${parsed.port}` : \"\";\n const pathname =\n parsed.pathname === \"/\"\n ? \"\"\n : parsed.pathname.replace(/\\/+$/, \"\");\n\n const sortedEntries = [...parsed.searchParams.entries()].sort(([aKey, aValue], [bKey, bValue]) =>\n aKey === bKey ? aValue.localeCompare(bValue) : aKey.localeCompare(bKey)\n );\n const params = new URLSearchParams();\n for (const [key, value] of sortedEntries) {\n params.append(key, value);\n }\n const search = params.toString();\n\n return `${protocol}//${hostname}${port}${pathname}${\n search.length > 0 ? `?${search}` : \"\"\n }`;\n}\n\nasync function findSourceByIdentity(\n ctx: { db: EpistemicDbReader },\n args: { normalizedUrl?: string; sha?: string },\n) {\n const sourceNodes = await ctx.db\n .query(\"epistemicNodes\")\n .withIndex(\"by_nodeType\", (q) =>\n q.eq(\"nodeType\", \"source\"),\n )\n .collect();\n\n let urlMatch: Doc<\"epistemicNodes\"> | null = null;\n let shaMatch: Doc<\"epistemicNodes\"> | null = null;\n\n for (const node of sourceNodes as Doc<\"epistemicNodes\">[]) {\n const metadata = asRecord(node.metadata);\n if (\n args.normalizedUrl &&\n normalizeString(metadata.url) === args.normalizedUrl &&\n !urlMatch\n ) {\n urlMatch = node;\n }\n if (args.sha && normalizeString(metadata.contentSha) === args.sha && !shaMatch) {\n shaMatch = node;\n }\n if (urlMatch && (!args.sha || shaMatch)) {\n break;\n }\n }\n\n if (urlMatch && shaMatch && String(urlMatch._id) !== String(shaMatch._id)) {\n throwStructuredSourceError({\n message: \"Source identity conflict: URL and SHA resolve to different source nodes.\",\n status: 409,\n code: \"CONTENT_SHA_MISMATCH\",\n invariantCode: \"source.content_hash_immutable\",\n suggestion:\n \"Same source identity resolves to different records. Create a new source with a distinct URL or use fork semantics.\",\n details: {\n urlSourceId: String(urlMatch._id),\n shaSourceId: String(shaMatch._id),\n },\n });\n }\n\n return urlMatch ?? shaMatch;\n}\n\nfunction buildSourceMetadata(args: {\n existingMetadata?: Record<string, unknown>;\n normalizedUrl?: string;\n sha?: string;\n kind: string;\n capturedAt?: number;\n metadata?: Record<string, unknown>;\n}) {\n const existingMetadata = args.existingMetadata ?? {};\n const nextMetadata: Record<string, unknown> = {\n ...existingMetadata,\n kind: args.kind,\n ...args.metadata,\n };\n\n if (args.capturedAt !== undefined) {\n nextMetadata.capturedAt = args.capturedAt;\n }\n if (!Object.prototype.hasOwnProperty.call(existingMetadata, \"url\") && args.normalizedUrl) {\n nextMetadata.url = args.normalizedUrl;\n } else if (Object.prototype.hasOwnProperty.call(existingMetadata, \"url\")) {\n nextMetadata.url = existingMetadata.url;\n }\n if (!Object.prototype.hasOwnProperty.call(existingMetadata, \"contentSha\") && args.sha) {\n nextMetadata.contentSha = args.sha;\n } else if (Object.prototype.hasOwnProperty.call(existingMetadata, \"contentSha\")) {\n nextMetadata.contentSha = existingMetadata.contentSha;\n }\n\n return nextMetadata;\n}\n\nfunction sourceEmbeddingText(args: {\n title?: string;\n url?: string;\n kind: string;\n metadata: Record<string, unknown>;\n}) {\n const lines = [\n normalizeString(args.title),\n normalizeString(args.url),\n args.kind,\n normalizeString(args.metadata.sourceDescription),\n ].filter((value): value is string => Boolean(value));\n return lines.join(\"\\n\");\n}\n\nexport const upsertSource = mutation({\n args: {\n url: v.optional(v.string()),\n sha: v.optional(v.string()),\n kind: v.string(),\n title: v.optional(v.string()),\n capturedAt: v.optional(v.number()),\n metadata: v.optional(v.any()),\n topicId: v.optional(v.string()),\n userId: v.string(),\n },\n returns: permissiveReturn,\n handler: async (ctx, args) => {\n const sourceUrl = normalizeString(args.url);\n const normalizedUrl = sourceUrl ? normalizeSourceUrl(sourceUrl) : undefined;\n const sha = normalizeString(args.sha);\n\n if (!normalizedUrl && !sha) {\n throwStructuredSourceError({\n message: \"Source identity requires a URL or content SHA.\",\n status: 400,\n code: \"INVALID_REQUEST\",\n invariantCode: \"source.identity.required\",\n suggestion: \"Provide url or sha.\",\n });\n }\n\n const now = Date.now();\n const metadataPatch = normalizeMetadata(args.metadata);\n const existing = await findSourceByIdentity(ctx, { normalizedUrl, sha });\n\n if (existing) {\n if (existing.topicId && !(await checkScopeAccess(ctx, String(existing.topicId), args.userId))) {\n throwStructuredSourceError({\n message: \"Access denied to existing source scope.\",\n status: 403,\n code: \"FORBIDDEN\",\n invariantCode: \"policy.scope_required\",\n suggestion: \"Request access to the source topic scope and retry.\",\n details: { topicId: existing.topicId },\n });\n }\n\n const existingMetadata = asRecord(existing.metadata);\n const existingSha = normalizeString(existingMetadata.contentSha);\n if (sha && existingSha && existingSha !== sha) {\n throwStructuredSourceError({\n message: \"Same URL cannot be reused with a different content hash.\",\n status: 409,\n code: \"CONTENT_SHA_MISMATCH\",\n invariantCode: \"source.content_hash_immutable\",\n suggestion:\n \"Same URL, different content. Create a new source with a distinct URL or use fork semantics.\",\n details: {\n sourceId: String(existing._id),\n url: existingMetadata.url,\n existingSha,\n receivedSha: sha,\n },\n });\n }\n\n const nextMetadata = buildSourceMetadata({\n existingMetadata,\n kind: args.kind,\n capturedAt: normalizeNumber(args.capturedAt),\n metadata: metadataPatch,\n });\n\n const patch: Record<string, unknown> = {\n metadata: nextMetadata,\n updatedAt: now,\n };\n const title = normalizeString(args.title);\n if (title) {\n patch.title = title;\n patch.canonicalText = title;\n }\n\n await ctx.db.patch(existing._id, patch);\n\n await ctx.scheduler.runAfter(0, internal.neo4jSync.syncNodeToNeo4j, {\n nodeId: existing._id,\n operation: \"upsert\",\n });\n\n await ctx.db.insert(\"epistemicAudit\", {\n entityType: \"source\" as any,\n entityId: existing._id,\n changeType: \"source_metadata_updated\" as any,\n changedAt: now,\n changedBy: args.userId,\n isAgent: false,\n topicId: existing.topicId ? String(existing.topicId) : undefined,\n previousState: {\n title: existing.title,\n metadata: existingMetadata,\n },\n newState: {\n title: title ?? existing.title,\n metadata: nextMetadata,\n },\n } as any);\n\n return (await ctx.db.get(existing._id)) ?? existing;\n }\n\n if (!normalizeString(args.topicId)) {\n throwStructuredSourceError({\n message: \"topicId is required when creating a new source.\",\n status: 400,\n code: \"INVALID_REQUEST\",\n invariantCode: \"source.context_required\",\n suggestion: \"Provide topicId when creating a new source node.\",\n });\n }\n\n const scope = await resolveTopicProjectScope(ctx, {\n topicId: args.topicId,\n });\n assertWorkspaceScopedEpistemicNodeScope({\n scope,\n nodeType: \"source\",\n mutationName: \"epistemicSources.upsertSource\",\n });\n if (scope.projectId) {\n await requireProjectAccess(ctx, scope.projectId, args.userId);\n }\n\n const globalId = generateGlobalId();\n const title = normalizeString(args.title);\n const nextMetadata = buildSourceMetadata({\n normalizedUrl,\n sha,\n kind: args.kind,\n capturedAt: normalizeNumber(args.capturedAt),\n metadata: metadataPatch,\n });\n const nodeId = await insertEpistemicNode(ctx, {\n globalId,\n topicId: scope.topicId,\n projectId: scope.projectId,\n tenantId: scope.tenantId,\n workspaceId: scope.workspaceId,\n nodeType: \"source\",\n epistemicLayer: \"L1\",\n canonicalText: title ?? normalizedUrl ?? \"source\",\n contentHash: sha ?? generateSourceContentHash(normalizedUrl ?? title ?? \"source\"),\n ...(title ? { title } : {}),\n status: \"active\",\n createdAt: now,\n updatedAt: now,\n createdBy: args.userId,\n metadata: nextMetadata,\n });\n\n await ctx.scheduler.runAfter(0, internal.neo4jSync.syncNodeToNeo4j, {\n nodeId,\n operation: \"upsert\",\n });\n\n await scheduleEmbeddingGeneration({\n ctx,\n nodeId,\n projectId: scope.projectId,\n topicId: scope.topicId,\n createdBy: args.userId,\n nodeType: \"source\",\n text: sourceEmbeddingText({\n title,\n url: normalizedUrl,\n kind: args.kind,\n metadata: nextMetadata,\n }),\n });\n\n await ctx.db.insert(\"epistemicAudit\", {\n entityType: \"source\" as any,\n entityId: nodeId,\n changeType: \"source_created\" as any,\n changedAt: now,\n changedBy: args.userId,\n isAgent: false,\n topicId: scope.topicId ? String(scope.topicId) : undefined,\n previousState: null,\n newState: {\n title,\n url: normalizedUrl,\n contentSha: sha,\n kind: args.kind,\n },\n } as any);\n\n return await ctx.db.get(nodeId);\n },\n});\n\nexport const getById = query({\n args: {\n nodeId: v.optional(v.id(\"epistemicNodes\")),\n sourceId: v.optional(v.string()),\n },\n returns: permissiveReturn,\n handler: async (ctx, args) => {\n const id: Id<\"epistemicNodes\"> | undefined =\n args.nodeId ?? (args.sourceId as Id<\"epistemicNodes\"> | undefined);\n if (!id) {\n return null;\n }\n const node = (await ctx.db.get(\n id as Id<\"epistemicNodes\">\n )) as Doc<\"epistemicNodes\"> | null;\n if (!node || node.nodeType !== \"source\") {\n return null;\n }\n return node;\n },\n});\n\nexport const findByUrl = query({\n args: {\n url: v.string(),\n },\n returns: permissiveReturn,\n handler: async (ctx, args) => {\n const normalizedUrl = normalizeSourceUrl(args.url);\n const node = await findSourceByIdentity(ctx, { normalizedUrl });\n return node && node.nodeType === \"source\" ? node : null;\n },\n});\n\nexport const findBySha = query({\n args: {\n sha: v.string(),\n },\n returns: permissiveReturn,\n handler: async (ctx, args) => {\n const sha = normalizeString(args.sha);\n if (!sha) {\n return null;\n }\n const node = await findSourceByIdentity(ctx, { sha });\n return node && node.nodeType === \"source\" ? node : null;\n },\n});\n"]}
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { normalizeTupleContradictionPolicy, mkOpinion, createInheritedContractRecord, confidenceFromSL, getRescoringSchedule, conditionalDeduction, project, dampedDependencyCascade, hasProjectedOpinionChanged, detectTupleContradiction, evaluateTupleContradictionTransition, readOpinionFromRecord, trustDiscount, applyNegativeSupport, cumulativeFusion, applyNegativeEvidence, computeEffectiveDecay, computeDeadlineUrgency, computeBaseDecay, bayesianUpdate, DECAY_TIERS, DEADLINE_URGENCY, parseEvidentialEvaluatorConfig, compareMetricValue, buildEvidentialRationale, parseMetricCheckerConfig, getEvaluatorInputRecord, pickFiniteNumber, resolveComparisonResult, buildComparisonRationale, parseReferenceCheckCounterConfig, parseTemporalDeadlineConfig, parseMarketIndexComparatorConfig } from '@lucern/confidence';
2
- import { v } from 'convex/values';
2
+ import { v, ConvexError } from 'convex/values';
3
3
  import { checkScopeAccess, getAccessibleProjectIds, checkProjectAccess, requireProjectAccess } from '@lucern/access-control/access';
4
4
  import { canAudienceClassAccess, normalizeAudienceKey, classFromAudienceKey } from '@lucern/access-control/audience';
5
5
  import { getCurrentUserId } from '@lucern/access-control/auth';
@@ -7,7 +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, assertUuidV7Identity, generateUuidV7, assertStorageEdgeVocabulary, assertCanonicalEdgeEndpoint, isUuidV7 } from '@lucern/contracts/ids';
10
+ import { generateGlobalId, assertUuidV7Identity, generateUuidV7, assertStorageEdgeVocabulary, assertUuidShapedEdgeEndpoint, isUuidV7 } from '@lucern/contracts/ids';
11
11
  import { assertEdgePolicyAllowed, edgePolicyManifest } from '@lucern/contracts';
12
12
  import { listAudienceRegistryRows } from '@lucern/access-control/audienceRegistry';
13
13
  import { scoreEntityTypeMatch, scoreEntityConnection, rankEntityTypeMatches, rankEntityConnections } from '@lucern/contracts/v1/ontologies/v1';
@@ -1092,6 +1092,9 @@ function materializeTopicProjectOverlay(topic, idMode = "legacy") {
1092
1092
  type: mapProjectType(topic, metadata),
1093
1093
  description: readNonEmptyString(topic.description),
1094
1094
  ownerId: readNonEmptyString(metadata.ownerId) || readNonEmptyString(topic.createdBy) || "system",
1095
+ // FR.7 creator-grant: surface the principal-shaped owner field (column-first,
1096
+ // metadata fallback for legacy rows that recorded it in metadata).
1097
+ ownerPrincipalId: readNonEmptyString(topic.ownerPrincipalId) || readNonEmptyString(metadata.ownerPrincipalId),
1095
1098
  sharedWith: readStringArray(metadata.sharedWith),
1096
1099
  visibility,
1097
1100
  tenantId: readNonEmptyString(topic.tenantId) || readNonEmptyString(metadata.tenantId),
@@ -1738,7 +1741,18 @@ var DEFAULT_CONFIDENCE_POLICY = {
1738
1741
  tupleContradiction: normalizeTupleContradictionPolicy()
1739
1742
  };
1740
1743
  function throwStructuredMutationError(args) {
1741
- const error = new Error(args.message);
1744
+ const data = {
1745
+ structuredMutationError: true,
1746
+ message: args.message,
1747
+ status: args.status,
1748
+ code: args.code,
1749
+ invariantCode: args.invariantCode,
1750
+ suggestion: args.suggestion,
1751
+ details: args.details
1752
+ };
1753
+ const error = new ConvexError(
1754
+ data
1755
+ );
1742
1756
  error.status = args.status;
1743
1757
  error.code = args.code;
1744
1758
  error.invariantCode = args.invariantCode;
@@ -2087,12 +2101,12 @@ async function requireProjectWriteAccess(ctx, projectId, userId) {
2087
2101
  );
2088
2102
  if (!hasAccess) {
2089
2103
  throwStructuredMutationError({
2090
- message: "Project access required.",
2104
+ message: `Project write access denied for topic ${projectId}.`,
2091
2105
  status: 403,
2092
- code: "FORBIDDEN",
2106
+ code: "PROJECT_ACCESS_DENIED",
2093
2107
  invariantCode: "policy.scope_required",
2094
- suggestion: "Request write access for the project and retry.",
2095
- details: { projectId, userId }
2108
+ suggestion: "The acting principal lacks project-write access to this topic. Request a topic grant (or, if the principal created this topic, run the creator-grant backfill) and retry.",
2109
+ details: { topicId: projectId, principalId: userId }
2096
2110
  });
2097
2111
  }
2098
2112
  }
@@ -2639,6 +2653,15 @@ async function insertEpistemicNode(ctx, doc) {
2639
2653
  assertUuidV7Identity("epistemicNodes", doc.globalId);
2640
2654
  return ctx.db.insert("epistemicNodes", doc);
2641
2655
  }
2656
+ async function assertExistingNodeEndpoint(ctx, endpointRole, endpoint) {
2657
+ assertUuidShapedEdgeEndpoint(endpointRole, endpoint);
2658
+ const node = await ctx.db.query("epistemicNodes").withIndex("by_globalId", (q) => q.eq("globalId", endpoint)).first();
2659
+ if (!node) {
2660
+ throw new Error(
2661
+ `edge_endpoint_not_canonical: epistemicEdges insert requires ${endpointRole} to be the globalId of an existing epistemicNodes row, received ${endpoint} (no node with that globalId)`
2662
+ );
2663
+ }
2664
+ }
2642
2665
  async function insertEpistemicEdge(ctx, doc) {
2643
2666
  assertUuidV7Identity("epistemicEdges", doc.globalId);
2644
2667
  assertStorageEdgeVocabulary(doc.edgeType);
@@ -2652,8 +2675,8 @@ async function insertEpistemicEdge(ctx, doc) {
2652
2675
  "edge_endpoint_missing: epistemicEdges insert requires a non-empty toNodeId"
2653
2676
  );
2654
2677
  }
2655
- assertCanonicalEdgeEndpoint("fromNodeId", doc.fromNodeId);
2656
- assertCanonicalEdgeEndpoint("toNodeId", doc.toNodeId);
2678
+ await assertExistingNodeEndpoint(ctx, "fromNodeId", doc.fromNodeId);
2679
+ await assertExistingNodeEndpoint(ctx, "toNodeId", doc.toNodeId);
2657
2680
  if (doc.fromNodeType && doc.toNodeType && doc.edgeType !== "extracted_from") {
2658
2681
  assertEdgePolicyAllowed(
2659
2682
  edgePolicyManifest,
@@ -8633,6 +8656,36 @@ async function isRegisteredEntityType(ctx, nodeType, tenantId) {
8633
8656
  return schema !== null;
8634
8657
  }
8635
8658
 
8659
+ // src/entityCanonicalMatch.ts
8660
+ function normalizeCanonicalEntityText(value) {
8661
+ return value.trim().toLowerCase().replace(/\s+/g, " ");
8662
+ }
8663
+ function buildEntityTitle(canonicalText) {
8664
+ return canonicalText.slice(0, 100) + (canonicalText.length > 100 ? "..." : "");
8665
+ }
8666
+ function matchesCanonicalEntityRecord(node, args) {
8667
+ if (node.epistemicLayer !== "ontological") {
8668
+ return false;
8669
+ }
8670
+ if (node.workspaceId !== void 0) {
8671
+ return false;
8672
+ }
8673
+ if (args.nodeType && node.nodeType !== args.nodeType) {
8674
+ return false;
8675
+ }
8676
+ if (args.contentHash && node.contentHash !== args.contentHash) {
8677
+ return false;
8678
+ }
8679
+ const rowTenantId = typeof node.tenantId === "string" && node.tenantId.trim().length > 0 ? node.tenantId.trim() : void 0;
8680
+ if (rowTenantId !== args.tenantId) {
8681
+ return false;
8682
+ }
8683
+ if (args.includeArchived) {
8684
+ return node.status !== "deleted";
8685
+ }
8686
+ return node.status === "active";
8687
+ }
8688
+
8636
8689
  // src/topicOntologyResolver.ts
8637
8690
  var MAX_RESOLUTION_DEPTH = 10;
8638
8691
  async function resolveTopicOntologyInternal(ctx, topicId) {
@@ -8699,7 +8752,18 @@ async function validateEntityTypeForTopic(ctx, topicId, nodeType) {
8699
8752
 
8700
8753
  // src/entityLifecycle.ts
8701
8754
  function throwStructuredMutationError2(args) {
8702
- const error = new Error(args.message);
8755
+ const data = {
8756
+ structuredMutationError: true,
8757
+ message: args.message,
8758
+ status: args.status,
8759
+ code: args.code,
8760
+ invariantCode: args.invariantCode,
8761
+ suggestion: args.suggestion,
8762
+ details: args.details
8763
+ };
8764
+ const error = new ConvexError(
8765
+ data
8766
+ );
8703
8767
  error.status = args.status;
8704
8768
  error.code = args.code;
8705
8769
  error.invariantCode = args.invariantCode;
@@ -8724,12 +8788,12 @@ async function requireProjectWriteAccess3(ctx, projectId, userId) {
8724
8788
  const hasAccess = await checkProjectAccess(ctx, projectId, userId);
8725
8789
  if (!hasAccess) {
8726
8790
  throwStructuredMutationError2({
8727
- message: "Project access required.",
8791
+ message: `Project write access denied for topic ${projectId}.`,
8728
8792
  status: 403,
8729
- code: "FORBIDDEN",
8793
+ code: "PROJECT_ACCESS_DENIED",
8730
8794
  invariantCode: "policy.scope_required",
8731
- suggestion: "Request write access for the project and retry.",
8732
- details: { projectId, userId }
8795
+ suggestion: "The acting principal lacks project-write access to this topic. Request a topic grant (or, if the principal created this topic, run the creator-grant backfill) and retry.",
8796
+ details: { topicId: projectId, principalId: userId }
8733
8797
  });
8734
8798
  }
8735
8799
  }
@@ -8753,12 +8817,6 @@ var ONTOLOGICAL_NODE_TYPE_SET = new Set(ONTOLOGICAL_NODE_TYPES);
8753
8817
  var isOntologicalNodeType = ONTOLOGICAL_NODE_TYPE_SET.has.bind(
8754
8818
  ONTOLOGICAL_NODE_TYPE_SET
8755
8819
  );
8756
- function normalizeCanonicalEntityText(value) {
8757
- return value.trim().toLowerCase().replace(/\s+/g, " ");
8758
- }
8759
- function buildEntityTitle(canonicalText) {
8760
- return canonicalText.slice(0, 100) + (canonicalText.length > 100 ? "..." : "");
8761
- }
8762
8820
  async function resolveCanonicalEntityScope(ctx, args) {
8763
8821
  const scope = await resolveTopicProjectScope(ctx, args);
8764
8822
  const topic = scope.topicId ? await ctx.db.get(scope.topicId) ?? null : null;
@@ -8774,28 +8832,6 @@ async function resolveCanonicalEntityScope(ctx, args) {
8774
8832
  project: project3
8775
8833
  };
8776
8834
  }
8777
- function matchesCanonicalEntityRecord(node, args) {
8778
- if (node.epistemicLayer !== "ontological") {
8779
- return false;
8780
- }
8781
- if (node.workspaceId !== void 0) {
8782
- return false;
8783
- }
8784
- if (args.nodeType && node.nodeType !== args.nodeType) {
8785
- return false;
8786
- }
8787
- if (args.contentHash && node.contentHash !== args.contentHash) {
8788
- return false;
8789
- }
8790
- const rowTenantId = typeof node.tenantId === "string" && node.tenantId.trim().length > 0 ? node.tenantId.trim() : void 0;
8791
- if (rowTenantId !== args.tenantId) {
8792
- return false;
8793
- }
8794
- if (args.includeArchived) {
8795
- return node.status !== "deleted";
8796
- }
8797
- return node.status === "active";
8798
- }
8799
8835
  async function findExistingCanonicalEntity(ctx, args) {
8800
8836
  const contentHash = generateContentHash3(args.nodeType, args.canonicalText);
8801
8837
  const candidates = await ctx.db.query("epistemicNodes").withIndex(