chainlesschain 0.166.16 → 0.166.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -10
- package/completions/_cc +1 -1
- package/completions/cc.bash +1 -1
- package/completions/cc.fish +1 -1
- package/completions/cc.ps1 +1 -1
- package/package.json +2 -2
- package/src/assets/web-panel/assets/{AIOps-CTxa2Wbq.js → AIOps-CQSBl3hY.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-DHrQyYhy.js → ActionButton-IQt-vRLt.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-DQiUqcNl.js → Analytics-DkHC8O7k.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-_Iz4r6wt.js → AppLayout-CSti2P2T.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-BNs63YHo.js → Artifacts-C57hxn3v.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-BgHIqRLn.js → Audit-DByLntcf.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-DUQ5axBB.js → BackgroundAgents-D1Bd2EOa.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-CJ51E9Vw.js → Backup-VstHzHng.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-o-5toA_R.js → BaseInput-CLhdexIf.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-Cu7a-x1L.js → Chat-BefC_JZS.js} +6 -6
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-BUyYkAXr.js → ChatBubbleRenderer-DbXMvgmn.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-DwdmZ71L.js → Checkbox-CEY982vx.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-BrH2eYiP.js → Codegen-Dcm_DTvJ.js} +1 -1
- package/src/assets/web-panel/assets/{Col-BVJQEP2j.js → Col-C8SSu4KA.js} +1 -1
- package/src/assets/web-panel/assets/{Community-FGO3vZPq.js → Community-BVV9vwRR.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-DYGAFVnT.js → Compact-B7c5Vo18.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-CRvc8Bdt.js → Compliance-Tq9jSZ5a.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-D6Ah2m7A.js → Cowork-BJUjT09Q.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-AXbU2ifR.js → Cron-CjV9PEaS.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-C5DXgEFd.js → Crosschain-Dl7ReL8F.js} +1 -1
- package/src/assets/web-panel/assets/{DID-Bxh9QV9v.js → DID-CG8PjWmM.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-B-ZHEta-.js → Dashboard-CDBM6wmF.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-66Ik1jqa.js → Dropdown-8_55bXTD.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-CCWk1BIM.js → EmailListRenderer-D3qOU1Cm.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard--9faIULK.js → FamilyGuardDashboard-Bv5oWMZF.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-CejW9CgX.js → Federation-hpZ1xkKd.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-acHgcXki.js → FormItemContext-BN7GT191.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-D2ghd_K4.js → GenericCardRenderer-PCRhfA7M.js} +1 -1
- package/src/assets/web-panel/assets/{Git-BOe1YJrV.js → Git-CIlP2vy7.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-BjgzJsof.js → Governance-81lgm7YL.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-CXCD5rnP.js → Inference-Cs24xMOV.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-CHA8QgJT.js → KnowledgeGraph-CrJLVCZo.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-DORPMcL6.js → Logs-DLyO8RKT.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-CPPHz01z.js → MarkdownRenderer-DBOqijrP.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-BCFlo1Yx.js → Marketplace-Dz7AbQZc.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-Dl_uZAKh.js → McpTools-BM0aFiWv.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-DupHamwz.js → Memory-C9SJzENX.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-BRSMPJxW.js → MobileBridge-BO2HnNRk.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-BHpuzsDl.js → MobileProjects-CK_jMz0l.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-Ch0jOQfZ.js → Mtc-CfhrJsdO.js} +2 -2
- package/src/assets/web-panel/assets/{MtcAudit-qzwQrDi7.js → MtcAudit-BE2ELxgI.js} +4 -4
- package/src/assets/web-panel/assets/{Multisig-B5wHzUcm.js → Multisig-CgR_E3Jd.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-Hy9uAiA0.js → NLProgramming-Cw9445_K.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-DkuchMC7.js → Notes-DZimkTrb.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-CYZhD7Pi.js → NotificationSettings-DxHVh4uT.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-DKOoqajt.js → OrderTableRenderer-Iy-pnX56.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-D9AXn6j8.js → Organization-pPXJtWo4.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-Bg15J6hX.js → Overflow-YamdTJwA.js} +1 -1
- package/src/assets/web-panel/assets/{P2P--B54HoQn.js → P2P-BvqP53x7.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-Cz9Kk2Nb.js → PdhVaultBrowser-Blz1Xn2n.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-DHx38eS1.js → Permissions-CgFRQqFJ.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-Dw8i2hAs.js → PersonalDataHub-CFeo3-6O.js} +4 -4
- package/src/assets/web-panel/assets/{Pipeline-B2o6Ur2G.js → Pipeline-BkaRojEK.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-8g-h2fnu.js → Privacy-BNZEx2Qp.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-DuVTcINx.js → ProjectInit-HUBOgEEK.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-C8njvdZX.js → ProjectSettings-CFMmhROS.js} +2 -2
- package/src/assets/web-panel/assets/Projects-Dc517BXp.js +1 -0
- package/src/assets/web-panel/assets/{Providers-wFqgod_W.js → Providers-DTLf8bgj.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-9NCXrpmA.js → QrScannerModal-BBNjPszk.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-WUTNvFkY.js → QuickAsk-DCsHvk3G.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-xT4nYmju.js → Recommend-Dpr5YSop.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-fak1PBGC.js → RemoteSession-DmKnvqGg.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-D1AkQvD-.js → Reputation-CSRfuurX.js} +1 -1
- package/src/assets/web-panel/assets/{Row-DVfm6xGt.js → Row-CDj3pQ_w.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-BDunoLSE.js → RssFeed-DI0a_kNq.js} +2 -2
- package/src/assets/web-panel/assets/{Search-OPycRoU3.js → Search-jAy7B2nU.js} +1 -1
- package/src/assets/web-panel/assets/{Security-C8-Fm3Dt.js → Security-CkHTqYhc.js} +4 -4
- package/src/assets/web-panel/assets/{Services-qM_sMpMl.js → Services-CP-0Nzga.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-D3HBJjVF.js → Skeleton-BkF5-p3n.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-jr67X-tP.js → Skills-BDu-utDE.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-CS3ggyCg.js → Sla-CQvq_2Qb.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-CTOCYxOi.js → SpeechSettings-T7Ap512g.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-D3s3cLT5.js → SyncSettings-Bt-PLvot.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-CdfoJ25m.js → Tasks-yLEcCogg.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-Drb4AI8X.js → Templates-ByN3fmbr.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-DzwR3Qkz.js → Tenant-DBI7hITH.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-D-ESq7xp.js → Terminal-B77_DlGX.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-BK-AUuws.js → TimelineRenderer-CsLTB_QO.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-xGTouuNp.js → Tokens-BV2N6cR8.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-BvZj-v2H.js → Trigger-CjXWGH3p.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-BLC9CGmc.js → Trust-uqXIq3WC.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-BSuCXpmE.js → UkeySign-D-6qu4vY.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-DT3A-_Ql.js → VideoEditing-CxGmx_2e.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-c1OXao85.js → Wallet-DSq7WlAg.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-CuA-F7KJ.js → WebAuthn-CDBiD57O.js} +2 -2
- package/src/assets/web-panel/assets/{WorkflowEditor-MANZrf82.js → WorkflowEditor-Z8f63TSb.js} +1 -1
- package/src/assets/web-panel/assets/{chat-D4Y4Ey0O.js → chat-B-UZFBjy.js} +1 -1
- package/src/assets/web-panel/assets/{colors-DDH06hKO.js → colors-CFk7K-7Q.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-Cym756Xj.js → compact-item-X0IVMvgi.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-By4Nb1k-.js → createContext-DWg4j2n6.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-B2IW1J_J.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-Ch7OY258.js → hasIn-CkVCwNNF.js} +1 -1
- package/src/assets/web-panel/assets/{index-D9le0-dc.js → index-5OcZHdzc.js} +1 -1
- package/src/assets/web-panel/assets/{index-CykROEJA.js → index-B273IY-E.js} +1 -1
- package/src/assets/web-panel/assets/{index-DjwgJ5Jd.js → index-B3-B3FWD.js} +1 -1
- package/src/assets/web-panel/assets/{index-CjNUTBwe.js → index-BB4KHHcv.js} +1 -1
- package/src/assets/web-panel/assets/index-BCp2ir-1.js +1 -0
- package/src/assets/web-panel/assets/{index-BFydNU6a.js → index-BG-GaZri.js} +1 -1
- package/src/assets/web-panel/assets/{index-mL3nOcH6.js → index-BPBia4b-.js} +1 -1
- package/src/assets/web-panel/assets/{index-XGeQMvWK.js → index-BipwEbTA.js} +1 -1
- package/src/assets/web-panel/assets/{index-D5sADPGY.js → index-BoskgPt9.js} +1 -1
- package/src/assets/web-panel/assets/{index-CV8qXTvb.js → index-Btqk6zWb.js} +1 -1
- package/src/assets/web-panel/assets/index-Bw4iuzRD.js +1 -0
- package/src/assets/web-panel/assets/{index-CJPks33Y.js → index-BzXjYUmd.js} +1 -1
- package/src/assets/web-panel/assets/{index-BBBUn5v7.js → index-C1ZAOJRW.js} +1 -1
- package/src/assets/web-panel/assets/{index-DiewptTL.js → index-CCLwoATF.js} +1 -1
- package/src/assets/web-panel/assets/{index-OU8DZ9BL.js → index-CDfSD07S.js} +1 -1
- package/src/assets/web-panel/assets/{index-DvnywwUj.js → index-CLlP1E4X.js} +1 -1
- package/src/assets/web-panel/assets/{index-CT-3FYwd.js → index-CMCEXBRh.js} +1 -1
- package/src/assets/web-panel/assets/{index-tZ5BUdad.js → index-CN8HZlLH.js} +1 -1
- package/src/assets/web-panel/assets/{index-DNlxihs8.js → index-CNKFsBlz.js} +1 -1
- package/src/assets/web-panel/assets/{index-CF3Lhyns.js → index-CUBkvFPH.js} +1 -1
- package/src/assets/web-panel/assets/{index-CV1UC4zo.js → index-Ca0mij1n.js} +1 -1
- package/src/assets/web-panel/assets/{index-DAkk1M7x.js → index-CbIAWbma.js} +1 -1
- package/src/assets/web-panel/assets/{index-DNEJzc0r.js → index-CbihMThv.js} +1 -1
- package/src/assets/web-panel/assets/{index-q-s04OKn.js → index-CvOa-IFV.js} +1 -1
- package/src/assets/web-panel/assets/{index-BZB9q-Lp.js → index-Cvwu_rA_.js} +1 -1
- package/src/assets/web-panel/assets/{index-oBsfUbyH.js → index-D-EJNxgR.js} +1 -1
- package/src/assets/web-panel/assets/{index-ZY2Qs_Sn.js → index-D8uEL8Uw.js} +1 -1
- package/src/assets/web-panel/assets/{index-DtGValNi.js → index-D92g4l3n.js} +1 -1
- package/src/assets/web-panel/assets/{index-CpudmDhf.js → index-DCqpl_E_.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bo20BfdS.js → index-DLSBks8h.js} +1 -1
- package/src/assets/web-panel/assets/{index-CUSUzaB8.js → index-Db_5xhrU.js} +1 -1
- package/src/assets/web-panel/assets/{index-CZn6dmZe.js → index-DcDggpWR.js} +1 -1
- package/src/assets/web-panel/assets/{index-CGsvEbbq.js → index-DeWKPQGs.js} +1 -1
- package/src/assets/web-panel/assets/{index-jx7kr6mB.js → index-DhVHoqGL.js} +3 -3
- package/src/assets/web-panel/assets/{index-BIrRX-ra.js → index-DyWlOuak.js} +1 -1
- package/src/assets/web-panel/assets/{index-6CpOV3Pn.js → index-LU54bChK.js} +1 -1
- package/src/assets/web-panel/assets/{index-6-2eYBXr.js → index-OjnAwUJo.js} +1 -1
- package/src/assets/web-panel/assets/{index-B51otVoZ.js → index-P83LDnCz.js} +1 -1
- package/src/assets/web-panel/assets/{index-ArMrnx0v.js → index-_-9k3Tna.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-DGcX9iPP.js → initDefaultProps-CFNgY8lJ.js} +1 -1
- package/src/assets/web-panel/assets/{motion-2SeL1D8A.js → motion-D-5RrDzn.js} +1 -1
- package/src/assets/web-panel/assets/{move-3cYbQCpS.js → move-DN-L0Bd-.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-IDdxfw0z.js → mtc-parser-6mgLSeCK.js} +1 -1
- package/src/assets/web-panel/assets/{omit-BNswdKO6.js → omit-ClWW8eTP.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-BwCnem2I.js → pickAttrs-Vystq3R8.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-B9PtZ5rq.js → placementArrow-D0H9hK4W.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-CPB6iSzV.js → responsiveObserve-B3iNRU-a.js} +1 -1
- package/src/assets/web-panel/assets/{slide-DZgyblZa.js → slide-CiMXe6am.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-D82IBdsx.js → statusUtils-CGDZJ1uT.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-qSHtosM-.js → styleChecker-D2zA6NkY.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-CmWO7h0I.js → useFlexGapSupport-C1sYU6QE.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-yLrs_ub4.js → useFs-BzUHSjg2.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-CJ1VW6rh.js → usePersonalDataHub-CxB5yZCq.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-CzY_moQ4.js → vnode-BfUfMwtc.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-DAa7rEY5.js → zoom-CFYmj1TO.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-help-index.json +2 -2
- package/src/command-manifest.json +2 -2
- package/src/commands/agent.js +80 -2
- package/src/commands/evolution.js +61 -42
- package/src/commands/learning.js +24 -8
- package/src/commands/serve.js +11 -2
- package/src/data/changelog.json +13 -0
- package/src/gateways/ws/session-protocol.js +1 -0
- package/src/gateways/ws/ws-agent-handler.js +70 -2
- package/src/gateways/ws/ws-server.js +8 -0
- package/src/lib/app-server/cli-agent-kernel-adapter.js +4 -0
- package/src/lib/app-server/graph-runtime.js +115 -8
- package/src/lib/app-server/server.js +21 -2
- package/src/lib/app-server/websocket-transport.js +2 -0
- package/src/lib/evolution/agent-evolution-ingress.js +300 -0
- package/src/lib/evolution/agent-evolution-runtime-composition-brand.js +22 -0
- package/src/lib/evolution/agent-evolution-runtime-composition.js +369 -0
- package/src/lib/evolution/bounded-skill-improvement-pilot.js +498 -0
- package/src/lib/evolution/evidence-backed-wiki-maintainer.js +752 -0
- package/src/lib/evolution/evolution-artifact-ports.js +48 -0
- package/src/lib/evolution/evolution-eval-gate.js +11 -4
- package/src/lib/evolution/evolution-evidence-artifact-adapter.js +499 -0
- package/src/lib/evolution/evolution-evidence-projector.js +61 -1
- package/src/lib/evolution/evolution-file-witness.js +601 -0
- package/src/lib/evolution/evolution-ledger-file-backend.js +176 -0
- package/src/lib/evolution/evolution-ledger-ports.js +353 -16
- package/src/lib/evolution/evolution-ledger.js +1355 -54
- package/src/lib/evolution/evolution-run-ledger-adapter.js +409 -0
- package/src/lib/evolution/evolution-run-runtime-adapter.js +5 -0
- package/src/lib/evolution/evolution-run-wiki-maintenance-source.js +300 -0
- package/src/lib/evolution/scheduled-batch-wiki-maintenance-source.js +368 -0
- package/src/lib/evolution/skill-candidate-registry.js +649 -0
- package/src/lib/evolution/skill-evaluated-promotion-durability.js +899 -0
- package/src/lib/evolution/skill-evaluated-promotion.js +481 -0
- package/src/lib/evolution/skill-promotion-controller.js +220 -37
- package/src/lib/evolution/skill-promotion-review-ledger-adapter.js +451 -0
- package/src/lib/evolution/skill-promotion-review.js +793 -0
- package/src/lib/evolution/skill-registry-transition-capability.js +55 -0
- package/src/lib/evolution/skill-registry-transition-ledger-adapter.js +1280 -0
- package/src/lib/evolution/skill-registry-transition-source.js +372 -0
- package/src/lib/evolution/skill-release-registry.js +2191 -11
- package/src/lib/evolution/skill-target-matrix-eval.js +133 -10
- package/src/lib/evolution/structured-memory-agent-control-plane.js +222 -0
- package/src/lib/evolution/structured-memory-authority-ledger-adapter.js +351 -0
- package/src/lib/evolution/structured-memory-ledger-adapter.js +220 -0
- package/src/lib/evolution/structured-memory-policy-receipt-writer.js +164 -0
- package/src/lib/evolution/structured-memory-post-compact-hook.js +87 -0
- package/src/lib/evolution/structured-memory-promotion-receipt-writer.js +221 -0
- package/src/lib/evolution/structured-memory-semantic-review-pipeline.js +313 -0
- package/src/lib/evolution/wiki-informed-skill-proposer.js +343 -0
- package/src/lib/evolution/wiki-maintainer-ledger-adapter.js +200 -0
- package/src/lib/evolution/wiki-maintenance-trigger-ledger-adapter.js +687 -0
- package/src/lib/evolution-system.js +65 -30
- package/src/lib/graph-kernel/evolution-run-runtime-adapter.js +5 -0
- package/src/lib/hooks-v2-runtime.js +20 -0
- package/src/lib/mcp-lifecycle-authority.js +21 -2
- package/src/lib/remote-approval-bridge.js +24 -0
- package/src/lib/scheduler-kernel/store.js +62 -14
- package/src/repl/agent-repl.js +45 -0
- package/src/runtime/agent-core.js +68 -0
- package/src/runtime/agent-runtime.js +114 -1
- package/src/runtime/headless-runner.js +19 -0
- package/src/runtime/headless-stream.js +43 -0
- package/src/runtime/runtime-factory.js +19 -1
- package/src/assets/web-panel/assets/Projects-Ca9BAfu7.js +0 -1
- package/src/assets/web-panel/assets/devWarning-KO3pAGeO.js +0 -1
- package/src/assets/web-panel/assets/index-Bh4Rgkg2.js +0 -1
- package/src/assets/web-panel/assets/index-Dox_coTY.js +0 -1
- package/src/lib/learning/learning-hooks.js +0 -123
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import structuredMemory from "@chainlesschain/session-core/structured-evolution-memory";
|
|
3
|
+
import {
|
|
4
|
+
EVOLUTION_DURABLE_ARTIFACT_RECORD_SCHEMA,
|
|
5
|
+
isEvolutionLedgerArtifactResolver,
|
|
6
|
+
} from "./evolution-artifact-ports.js";
|
|
7
|
+
import {
|
|
8
|
+
EVOLUTION_ARTIFACT_RESOLUTION_SCHEMA,
|
|
9
|
+
EVOLUTION_LEDGER_DOMAIN_EVENT_SCHEMA,
|
|
10
|
+
} from "./evolution-ledger.js";
|
|
11
|
+
|
|
12
|
+
const {
|
|
13
|
+
STRUCTURED_MEMORY_RECEIPT_SCHEMA,
|
|
14
|
+
STRUCTURED_MEMORY_RECEIPT_RESOLUTION_SCHEMA,
|
|
15
|
+
createStructuredMemoryAuthorityReceipt,
|
|
16
|
+
createStructuredMemoryReceiptProvider,
|
|
17
|
+
} = structuredMemory;
|
|
18
|
+
|
|
19
|
+
export const STRUCTURED_MEMORY_AUTHORITY_RECEIPT_EVENT_TYPE =
|
|
20
|
+
"memory.authority-receipt.persisted";
|
|
21
|
+
export const STRUCTURED_MEMORY_AUTHORITY_LEDGER_CORRUPT_CODE =
|
|
22
|
+
"CC_STRUCTURED_MEMORY_AUTHORITY_LEDGER_CORRUPT";
|
|
23
|
+
|
|
24
|
+
const ARTIFACT_TYPE = "structured-memory-authority-receipt";
|
|
25
|
+
const DIGEST = /^sha256:[a-f0-9]{64}$/u;
|
|
26
|
+
|
|
27
|
+
function canonical(value) {
|
|
28
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
29
|
+
if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`;
|
|
30
|
+
return `{${Object.keys(value)
|
|
31
|
+
.sort()
|
|
32
|
+
.map((key) => `${JSON.stringify(key)}:${canonical(value[key])}`)
|
|
33
|
+
.join(",")}}`;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function hash(value) {
|
|
37
|
+
return `sha256:${createHash("sha256").update(canonical(value)).digest("hex")}`;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function requiredString(value, name) {
|
|
41
|
+
if (typeof value !== "string" || value.trim() === "")
|
|
42
|
+
throw new TypeError(`${name} is required`);
|
|
43
|
+
return value;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function capture(owner, name) {
|
|
47
|
+
if (typeof owner?.[name] !== "function")
|
|
48
|
+
throw new TypeError(`${name} port is required`);
|
|
49
|
+
return (...args) => Reflect.apply(owner[name], owner, args);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function corrupt(message) {
|
|
53
|
+
const error = new Error(message);
|
|
54
|
+
error.code = STRUCTURED_MEMORY_AUTHORITY_LEDGER_CORRUPT_CODE;
|
|
55
|
+
throw error;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function normalizeDescriptor(input) {
|
|
59
|
+
if (
|
|
60
|
+
!Number.isSafeInteger(input?.authorityRevision) ||
|
|
61
|
+
input.authorityRevision <= 0
|
|
62
|
+
) {
|
|
63
|
+
throw new TypeError("authorityRevision must be a positive integer");
|
|
64
|
+
}
|
|
65
|
+
if (!DIGEST.test(input?.handlerDigest || ""))
|
|
66
|
+
throw new TypeError("handlerDigest must be sha256-bound");
|
|
67
|
+
return Object.freeze({
|
|
68
|
+
tenantId: requiredString(input.tenantId, "tenantId"),
|
|
69
|
+
artifactTenantId: requiredString(
|
|
70
|
+
input.artifactTenantId,
|
|
71
|
+
"artifactTenantId",
|
|
72
|
+
),
|
|
73
|
+
streamId: requiredString(input.streamId, "streamId"),
|
|
74
|
+
audience: requiredString(input.audience, "audience"),
|
|
75
|
+
purpose: requiredString(input.purpose, "purpose"),
|
|
76
|
+
authorityId: requiredString(input.authorityId, "authorityId"),
|
|
77
|
+
authorityRevision: input.authorityRevision,
|
|
78
|
+
handlerDigest: input.handlerDigest,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function validateCanonicalReceipt(receipt, tenantId) {
|
|
83
|
+
if (
|
|
84
|
+
receipt?.schema !== STRUCTURED_MEMORY_RECEIPT_SCHEMA ||
|
|
85
|
+
receipt.tenantId !== tenantId ||
|
|
86
|
+
!DIGEST.test(receipt.receiptDigest || "")
|
|
87
|
+
)
|
|
88
|
+
throw new TypeError("structured memory authority receipt is invalid");
|
|
89
|
+
const normalized = createStructuredMemoryAuthorityReceipt(receipt);
|
|
90
|
+
if (normalized.receiptDigest !== receipt.receiptDigest) {
|
|
91
|
+
corrupt("structured memory authority receipt digest is invalid");
|
|
92
|
+
}
|
|
93
|
+
return receipt;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function parseResolution(resolution, descriptor) {
|
|
97
|
+
if (
|
|
98
|
+
resolution?.schema !== EVOLUTION_ARTIFACT_RESOLUTION_SCHEMA ||
|
|
99
|
+
resolution.authenticated !== true ||
|
|
100
|
+
resolution.found !== true ||
|
|
101
|
+
!DIGEST.test(resolution.digest || "") ||
|
|
102
|
+
!DIGEST.test(resolution.receiptDigest || "") ||
|
|
103
|
+
!Buffer.isBuffer(resolution.bytes)
|
|
104
|
+
) {
|
|
105
|
+
corrupt(
|
|
106
|
+
"structured memory receipt artifact resolution is unauthenticated or incomplete",
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
let record;
|
|
110
|
+
try {
|
|
111
|
+
record = JSON.parse(resolution.bytes.toString("utf8"));
|
|
112
|
+
} catch {
|
|
113
|
+
corrupt("structured memory receipt artifact is not JSON");
|
|
114
|
+
}
|
|
115
|
+
if (
|
|
116
|
+
record?.schema !== EVOLUTION_DURABLE_ARTIFACT_RECORD_SCHEMA ||
|
|
117
|
+
record.tenantId !== descriptor.artifactTenantId ||
|
|
118
|
+
record.audience !== descriptor.audience ||
|
|
119
|
+
record.purpose !== descriptor.purpose ||
|
|
120
|
+
record.retention !== "ledger" ||
|
|
121
|
+
record.type !== ARTIFACT_TYPE
|
|
122
|
+
)
|
|
123
|
+
corrupt("structured memory receipt durable record binding is invalid");
|
|
124
|
+
return validateCanonicalReceipt(record.value, descriptor.tenantId);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export class StructuredMemoryAuthorityLedgerAdapter {
|
|
128
|
+
constructor({
|
|
129
|
+
descriptor: input,
|
|
130
|
+
artifactPorts,
|
|
131
|
+
ledger,
|
|
132
|
+
ledgerArtifactResolver,
|
|
133
|
+
receiptVerifier,
|
|
134
|
+
} = {}) {
|
|
135
|
+
this.descriptor = normalizeDescriptor(input);
|
|
136
|
+
this._put = capture(artifactPorts, "putCanonical");
|
|
137
|
+
this._read = capture(ledger, "read");
|
|
138
|
+
this._verifyLedger = capture(ledger, "verify");
|
|
139
|
+
this._append = capture(ledger, "appendDomainEvent");
|
|
140
|
+
this._verifyReceipt = capture(receiptVerifier, "verify");
|
|
141
|
+
if (!isEvolutionLedgerArtifactResolver(ledgerArtifactResolver)) {
|
|
142
|
+
throw new TypeError(
|
|
143
|
+
"a branded EvolutionArtifactPorts ledger resolver is required",
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
this._resolveArtifact = ledgerArtifactResolver;
|
|
147
|
+
Object.freeze(this);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
_events() {
|
|
151
|
+
const events = this._read();
|
|
152
|
+
if (!Array.isArray(events))
|
|
153
|
+
corrupt("EvolutionLedger did not return an event array");
|
|
154
|
+
return events.filter(
|
|
155
|
+
(event) =>
|
|
156
|
+
event.schema === EVOLUTION_LEDGER_DOMAIN_EVENT_SCHEMA &&
|
|
157
|
+
event.type === STRUCTURED_MEMORY_AUTHORITY_RECEIPT_EVENT_TYPE &&
|
|
158
|
+
event.tenantId === this.descriptor.tenantId &&
|
|
159
|
+
event.correlationId === this.descriptor.streamId,
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
_resolveEvent(event) {
|
|
164
|
+
const identity = this._verifyLedger();
|
|
165
|
+
const resolution = this._resolveArtifact({
|
|
166
|
+
epoch: identity.epoch,
|
|
167
|
+
ledgerId: identity.ledgerId,
|
|
168
|
+
ref: event.subjectRef,
|
|
169
|
+
tenantId: this.descriptor.artifactTenantId,
|
|
170
|
+
});
|
|
171
|
+
if (
|
|
172
|
+
resolution.ref !== event.subjectRef.ref ||
|
|
173
|
+
resolution.digest !== event.subjectRef.digest
|
|
174
|
+
) {
|
|
175
|
+
corrupt("structured memory receipt ledger subject was substituted");
|
|
176
|
+
}
|
|
177
|
+
return parseResolution(resolution, this.descriptor);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
async retainReceipt(receipt) {
|
|
181
|
+
validateCanonicalReceipt(receipt, this.descriptor.tenantId);
|
|
182
|
+
if (
|
|
183
|
+
(await this._verifyReceipt({
|
|
184
|
+
receipt,
|
|
185
|
+
source: "retain",
|
|
186
|
+
ledgerEvent: null,
|
|
187
|
+
})) !== true
|
|
188
|
+
) {
|
|
189
|
+
throw new Error(
|
|
190
|
+
"structured memory authority receipt authentication failed",
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
const eventId = `${STRUCTURED_MEMORY_AUTHORITY_RECEIPT_EVENT_TYPE}.${receipt.receiptDigest.slice(7)}`;
|
|
194
|
+
const matching = this._events().filter(
|
|
195
|
+
(event) => event.eventId === eventId,
|
|
196
|
+
);
|
|
197
|
+
if (matching.length > 1)
|
|
198
|
+
corrupt("structured memory receipt has duplicate ledger events");
|
|
199
|
+
if (matching.length === 1) {
|
|
200
|
+
if (canonical(this._resolveEvent(matching[0])) !== canonical(receipt)) {
|
|
201
|
+
corrupt("structured memory receipt id resolved substituted content");
|
|
202
|
+
}
|
|
203
|
+
return Object.freeze({
|
|
204
|
+
persisted: true,
|
|
205
|
+
recovered: true,
|
|
206
|
+
receiptDigest: receipt.receiptDigest,
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
const head = this._verifyLedger();
|
|
210
|
+
const published = this._put(ARTIFACT_TYPE, receipt, {
|
|
211
|
+
audience: this.descriptor.audience,
|
|
212
|
+
purpose: this.descriptor.purpose,
|
|
213
|
+
retention: "ledger",
|
|
214
|
+
});
|
|
215
|
+
if (
|
|
216
|
+
published?.receipt?.persisted !== true ||
|
|
217
|
+
published.receipt.readbackVerified !== true ||
|
|
218
|
+
published.receipt.integrityVerified !== true ||
|
|
219
|
+
published.receipt.retention !== "ledger"
|
|
220
|
+
) {
|
|
221
|
+
corrupt(
|
|
222
|
+
"structured memory receipt persistence was not durably confirmed",
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
const previous = this._events().at(-1);
|
|
226
|
+
const ledgerReceipt = this._append(
|
|
227
|
+
{
|
|
228
|
+
artifactTenantId: this.descriptor.artifactTenantId,
|
|
229
|
+
correlationId: this.descriptor.streamId,
|
|
230
|
+
decision: "committed",
|
|
231
|
+
eventId,
|
|
232
|
+
reason: `${receipt.kind} structured memory authority receipt committed`,
|
|
233
|
+
skillName: null,
|
|
234
|
+
sourceRefs: previous ? [previous.subjectRef] : [],
|
|
235
|
+
subjectRef: published.ref,
|
|
236
|
+
tenantId: this.descriptor.tenantId,
|
|
237
|
+
timestamp: receipt.issuedAt,
|
|
238
|
+
type: STRUCTURED_MEMORY_AUTHORITY_RECEIPT_EVENT_TYPE,
|
|
239
|
+
},
|
|
240
|
+
{ expectedHeadDigest: head.headDigest, expectedSequence: head.sequence },
|
|
241
|
+
);
|
|
242
|
+
if (
|
|
243
|
+
ledgerReceipt?.authenticated !== true ||
|
|
244
|
+
ledgerReceipt.committed !== true ||
|
|
245
|
+
ledgerReceipt.durable !== true ||
|
|
246
|
+
ledgerReceipt.eventId !== eventId ||
|
|
247
|
+
!DIGEST.test(ledgerReceipt.receiptDigest || "")
|
|
248
|
+
) {
|
|
249
|
+
corrupt(
|
|
250
|
+
"structured memory receipt ledger append was not durably confirmed",
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
return Object.freeze({
|
|
254
|
+
persisted: true,
|
|
255
|
+
receiptDigest: receipt.receiptDigest,
|
|
256
|
+
ledgerReceiptDigest: ledgerReceipt.receiptDigest,
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
async listReceipts(kind) {
|
|
261
|
+
if (!["critic", "evaluator", "promotion", "policy"].includes(kind)) {
|
|
262
|
+
throw new TypeError(
|
|
263
|
+
"a structured memory authority receipt kind is required",
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
const receipts = [];
|
|
267
|
+
const seen = new Set();
|
|
268
|
+
for (const event of this._events()) {
|
|
269
|
+
const receipt = this._resolveEvent(event);
|
|
270
|
+
if (receipt.kind !== kind) continue;
|
|
271
|
+
if (seen.has(receipt.receiptDigest)) {
|
|
272
|
+
corrupt("structured memory receipt digest is duplicated");
|
|
273
|
+
}
|
|
274
|
+
if (
|
|
275
|
+
(await this._verifyReceipt({
|
|
276
|
+
receipt,
|
|
277
|
+
source: "resolve",
|
|
278
|
+
ledgerEvent: event.eventDigest,
|
|
279
|
+
})) !== true
|
|
280
|
+
) {
|
|
281
|
+
throw new Error(
|
|
282
|
+
"structured memory authority receipt authentication failed",
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
seen.add(receipt.receiptDigest);
|
|
286
|
+
receipts.push(Object.freeze(structuredClone(receipt)));
|
|
287
|
+
}
|
|
288
|
+
return Object.freeze(receipts);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
createReceiptProvider() {
|
|
292
|
+
const providerDescriptor = {
|
|
293
|
+
tenantId: this.descriptor.tenantId,
|
|
294
|
+
authorityId: this.descriptor.authorityId,
|
|
295
|
+
authorityRevision: this.descriptor.authorityRevision,
|
|
296
|
+
handlerDigest: this.descriptor.handlerDigest,
|
|
297
|
+
};
|
|
298
|
+
return createStructuredMemoryReceiptProvider({
|
|
299
|
+
descriptor: providerDescriptor,
|
|
300
|
+
resolver: {
|
|
301
|
+
resolve: async (request) => {
|
|
302
|
+
const eventId = `${STRUCTURED_MEMORY_AUTHORITY_RECEIPT_EVENT_TYPE}.${request.receiptDigest.slice(7)}`;
|
|
303
|
+
const matches = this._events().filter(
|
|
304
|
+
(event) => event.eventId === eventId,
|
|
305
|
+
);
|
|
306
|
+
if (matches.length !== 1)
|
|
307
|
+
corrupt(
|
|
308
|
+
"structured memory receipt ledger resolution is missing or ambiguous",
|
|
309
|
+
);
|
|
310
|
+
const receipt = this._resolveEvent(matches[0]);
|
|
311
|
+
return Object.freeze({
|
|
312
|
+
schema: STRUCTURED_MEMORY_RECEIPT_RESOLUTION_SCHEMA,
|
|
313
|
+
authenticated: true,
|
|
314
|
+
...providerDescriptor,
|
|
315
|
+
kind: request.kind,
|
|
316
|
+
receiptDigest: request.receiptDigest,
|
|
317
|
+
receipt,
|
|
318
|
+
ledgerEventDigest: matches[0].eventDigest,
|
|
319
|
+
resolutionReceiptDigest: hash({
|
|
320
|
+
eventDigest: matches[0].eventDigest,
|
|
321
|
+
receiptDigest: request.receiptDigest,
|
|
322
|
+
subjectRef: matches[0].subjectRef,
|
|
323
|
+
}),
|
|
324
|
+
});
|
|
325
|
+
},
|
|
326
|
+
},
|
|
327
|
+
verifier: {
|
|
328
|
+
verify: async ({ request, resolution }) => {
|
|
329
|
+
const eventId = `${STRUCTURED_MEMORY_AUTHORITY_RECEIPT_EVENT_TYPE}.${request.receiptDigest.slice(7)}`;
|
|
330
|
+
const matches = this._events().filter(
|
|
331
|
+
(event) => event.eventId === eventId,
|
|
332
|
+
);
|
|
333
|
+
if (
|
|
334
|
+
matches.length !== 1 ||
|
|
335
|
+
resolution.ledgerEventDigest !== matches[0].eventDigest
|
|
336
|
+
)
|
|
337
|
+
return false;
|
|
338
|
+
return await this._verifyReceipt({
|
|
339
|
+
receipt: resolution.receipt,
|
|
340
|
+
source: "resolve",
|
|
341
|
+
ledgerEvent: resolution.ledgerEventDigest,
|
|
342
|
+
});
|
|
343
|
+
},
|
|
344
|
+
},
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
export function createStructuredMemoryAuthorityLedgerAdapter(options) {
|
|
350
|
+
return new StructuredMemoryAuthorityLedgerAdapter(options);
|
|
351
|
+
}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import structuredMemory from "@chainlesschain/session-core/structured-evolution-memory";
|
|
3
|
+
import {
|
|
4
|
+
EVOLUTION_DURABLE_ARTIFACT_RECORD_SCHEMA,
|
|
5
|
+
isEvolutionLedgerArtifactResolver,
|
|
6
|
+
} from "./evolution-artifact-ports.js";
|
|
7
|
+
import {
|
|
8
|
+
EVOLUTION_ARTIFACT_RESOLUTION_SCHEMA,
|
|
9
|
+
EVOLUTION_LEDGER_DOMAIN_EVENT_SCHEMA,
|
|
10
|
+
} from "./evolution-ledger.js";
|
|
11
|
+
|
|
12
|
+
const {
|
|
13
|
+
STRUCTURED_MEMORY_EVENT_SCHEMA,
|
|
14
|
+
STRUCTURED_MEMORY_SNAPSHOT_SCHEMA,
|
|
15
|
+
StructuredEvolutionMemory,
|
|
16
|
+
projectStructuredMemory,
|
|
17
|
+
isStructuredMemoryReceiptProvider,
|
|
18
|
+
isStructuredMemoryPostCompactVerifier,
|
|
19
|
+
} = structuredMemory;
|
|
20
|
+
|
|
21
|
+
export const STRUCTURED_MEMORY_LEDGER_EVENT_TYPE = "memory.event.persisted";
|
|
22
|
+
export const STRUCTURED_MEMORY_LEDGER_SNAPSHOT_TYPE = "memory.snapshot.persisted";
|
|
23
|
+
export const STRUCTURED_MEMORY_LEDGER_CORRUPT_CODE = "CC_STRUCTURED_MEMORY_LEDGER_CORRUPT";
|
|
24
|
+
export const STRUCTURED_MEMORY_LEDGER_CONFLICT_CODE = "CC_STRUCTURED_MEMORY_LEDGER_CONFLICT";
|
|
25
|
+
|
|
26
|
+
const DIGEST = /^sha256:[a-f0-9]{64}$/u;
|
|
27
|
+
|
|
28
|
+
function canonical(value) {
|
|
29
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
30
|
+
if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`;
|
|
31
|
+
return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${canonical(value[key])}`).join(",")}}`;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function hash(value) {
|
|
35
|
+
return `sha256:${createHash("sha256").update(canonical(value)).digest("hex")}`;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function requiredString(value, name) {
|
|
39
|
+
if (typeof value !== "string" || value.trim() === "") throw new TypeError(`${name} is required`);
|
|
40
|
+
return value;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function fail(message) {
|
|
44
|
+
const error = new Error(message);
|
|
45
|
+
error.code = STRUCTURED_MEMORY_LEDGER_CORRUPT_CODE;
|
|
46
|
+
throw error;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function conflict(message) {
|
|
50
|
+
const error = new Error(message);
|
|
51
|
+
error.code = STRUCTURED_MEMORY_LEDGER_CONFLICT_CODE;
|
|
52
|
+
throw error;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function capture(owner, name) {
|
|
56
|
+
if (typeof owner?.[name] !== "function") throw new TypeError(`${name} port is required`);
|
|
57
|
+
return (...args) => Reflect.apply(owner[name], owner, args);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function descriptor(input) {
|
|
61
|
+
return Object.freeze({
|
|
62
|
+
tenantId: requiredString(input?.tenantId, "tenantId"),
|
|
63
|
+
artifactTenantId: requiredString(input?.artifactTenantId, "artifactTenantId"),
|
|
64
|
+
streamId: requiredString(input?.streamId, "streamId"),
|
|
65
|
+
audience: requiredString(input?.audience, "audience"),
|
|
66
|
+
purpose: requiredString(input?.purpose, "purpose"),
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function parseResolution(resolution, expectedType, options) {
|
|
71
|
+
if (resolution?.schema !== EVOLUTION_ARTIFACT_RESOLUTION_SCHEMA || resolution.authenticated !== true ||
|
|
72
|
+
resolution.found !== true || !DIGEST.test(resolution.digest || "") ||
|
|
73
|
+
!DIGEST.test(resolution.receiptDigest || "") || !Buffer.isBuffer(resolution.bytes)) {
|
|
74
|
+
fail("structured memory artifact resolution is unauthenticated or incomplete");
|
|
75
|
+
}
|
|
76
|
+
let record;
|
|
77
|
+
try { record = JSON.parse(resolution.bytes.toString("utf8")); } catch { fail("structured memory artifact is not JSON"); }
|
|
78
|
+
if (record?.schema !== EVOLUTION_DURABLE_ARTIFACT_RECORD_SCHEMA || record.tenantId !== options.artifactTenantId ||
|
|
79
|
+
record.audience !== options.audience || record.purpose !== options.purpose || record.retention !== "ledger" ||
|
|
80
|
+
record.type !== expectedType) {
|
|
81
|
+
fail("structured memory durable record binding is invalid");
|
|
82
|
+
}
|
|
83
|
+
return record.value;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export class StructuredMemoryLedgerAdapter {
|
|
87
|
+
constructor({ descriptor: input, artifactPorts, ledger, ledgerArtifactResolver,
|
|
88
|
+
receiptProvider, postCompactVerifier, clock = Date.now } = {}) {
|
|
89
|
+
this.descriptor = descriptor(input);
|
|
90
|
+
this._put = capture(artifactPorts, "putCanonical");
|
|
91
|
+
this._read = capture(ledger, "read");
|
|
92
|
+
this._verify = capture(ledger, "verify");
|
|
93
|
+
this._append = capture(ledger, "appendDomainEvent");
|
|
94
|
+
if (typeof clock !== "function") throw new TypeError("clock must be a function");
|
|
95
|
+
this._clock = clock;
|
|
96
|
+
if (!isEvolutionLedgerArtifactResolver(ledgerArtifactResolver)) {
|
|
97
|
+
throw new TypeError("a branded EvolutionArtifactPorts ledger resolver is required");
|
|
98
|
+
}
|
|
99
|
+
if (!isStructuredMemoryReceiptProvider(receiptProvider) ||
|
|
100
|
+
receiptProvider.identity.tenantId !== this.descriptor.tenantId) {
|
|
101
|
+
throw new TypeError("a branded tenant-scoped structured memory receipt provider is required");
|
|
102
|
+
}
|
|
103
|
+
if (!isStructuredMemoryPostCompactVerifier(postCompactVerifier) ||
|
|
104
|
+
postCompactVerifier.identity.tenantId !== this.descriptor.tenantId) {
|
|
105
|
+
throw new TypeError("a branded tenant-scoped structured memory PostCompact verifier is required");
|
|
106
|
+
}
|
|
107
|
+
this._resolve = ledgerArtifactResolver;
|
|
108
|
+
this._receiptProvider = receiptProvider;
|
|
109
|
+
this._postCompactVerifier = postCompactVerifier;
|
|
110
|
+
Object.freeze(this);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
_events(type) {
|
|
114
|
+
const events = this._read();
|
|
115
|
+
if (!Array.isArray(events)) fail("EvolutionLedger did not return an event array");
|
|
116
|
+
return events.filter((event) => event.schema === EVOLUTION_LEDGER_DOMAIN_EVENT_SCHEMA && event.type === type &&
|
|
117
|
+
event.tenantId === this.descriptor.tenantId && event.correlationId === this.descriptor.streamId);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
_resolveEvent(event, artifactType) {
|
|
121
|
+
const identity = this._verify();
|
|
122
|
+
const resolution = this._resolve({ epoch: identity.epoch, ledgerId: identity.ledgerId,
|
|
123
|
+
ref: event.subjectRef, tenantId: this.descriptor.artifactTenantId });
|
|
124
|
+
if (resolution.ref !== event.subjectRef.ref || resolution.digest !== event.subjectRef.digest) {
|
|
125
|
+
fail("structured memory ledger subject was substituted");
|
|
126
|
+
}
|
|
127
|
+
return parseResolution(resolution, artifactType, this.descriptor);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
load() {
|
|
131
|
+
const events = this._events(STRUCTURED_MEMORY_LEDGER_EVENT_TYPE).map((entry) => this._resolveEvent(entry, "structured-memory-event"));
|
|
132
|
+
const projection = projectStructuredMemory(events, { tenantId: this.descriptor.tenantId });
|
|
133
|
+
const snapshots = this._events(STRUCTURED_MEMORY_LEDGER_SNAPSHOT_TYPE)
|
|
134
|
+
.map((entry) => this._resolveEvent(entry, "structured-memory-snapshot"))
|
|
135
|
+
.sort((left, right) => left.throughSequence - right.throughSequence);
|
|
136
|
+
const snapshot = snapshots.at(-1) ?? null;
|
|
137
|
+
if (snapshot && snapshot.throughSequence > projection.sequence) fail("structured memory snapshot is ahead of its event stream");
|
|
138
|
+
return Object.freeze({ events: Object.freeze(events), snapshot });
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
_persist(type, artifactType, value, logicalDigest, logicalId, timestamp, sourceRefs) {
|
|
142
|
+
const head = this._verify();
|
|
143
|
+
const published = this._put(artifactType, value, { audience: this.descriptor.audience,
|
|
144
|
+
purpose: this.descriptor.purpose, retention: "ledger" });
|
|
145
|
+
if (published?.receipt?.persisted !== true || published.receipt.readbackVerified !== true ||
|
|
146
|
+
published.receipt.integrityVerified !== true || published.receipt.retention !== "ledger") {
|
|
147
|
+
fail("structured memory artifact persistence was not durably confirmed");
|
|
148
|
+
}
|
|
149
|
+
const eventId = `${type}.${logicalDigest.slice("sha256:".length)}`;
|
|
150
|
+
const receipt = this._append({ artifactTenantId: this.descriptor.artifactTenantId,
|
|
151
|
+
correlationId: this.descriptor.streamId, decision: "committed", eventId,
|
|
152
|
+
reason: `${type} committed`, skillName: null, sourceRefs, subjectRef: published.ref,
|
|
153
|
+
tenantId: this.descriptor.tenantId, timestamp, type },
|
|
154
|
+
{ expectedHeadDigest: head.headDigest, expectedSequence: head.sequence });
|
|
155
|
+
if (receipt?.authenticated !== true || receipt.committed !== true || receipt.durable !== true ||
|
|
156
|
+
receipt.eventId !== eventId || !DIGEST.test(receipt.receiptDigest || "")) {
|
|
157
|
+
fail("structured memory ledger append was not durably confirmed");
|
|
158
|
+
}
|
|
159
|
+
return Object.freeze({ persisted: true, [logicalId]: logicalDigest, ledgerReceiptDigest: receipt.receiptDigest });
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
persistEvent = async (event) => {
|
|
163
|
+
if (event?.schema !== STRUCTURED_MEMORY_EVENT_SCHEMA || event.tenantId !== this.descriptor.tenantId) {
|
|
164
|
+
throw new TypeError("structured memory event persistence input is invalid");
|
|
165
|
+
}
|
|
166
|
+
const eventDigest = hash(event);
|
|
167
|
+
const existing = this._events(STRUCTURED_MEMORY_LEDGER_EVENT_TYPE);
|
|
168
|
+
const identical = existing.find((entry) => entry.eventId === `${STRUCTURED_MEMORY_LEDGER_EVENT_TYPE}.${eventDigest.slice(7)}`);
|
|
169
|
+
if (identical) {
|
|
170
|
+
if (canonical(this._resolveEvent(identical, "structured-memory-event")) !== canonical(event)) {
|
|
171
|
+
fail("structured memory event id resolved substituted content");
|
|
172
|
+
}
|
|
173
|
+
return Object.freeze({ persisted: true, eventId: event.eventId, eventDigest, recovered: true });
|
|
174
|
+
}
|
|
175
|
+
if (existing.length !== event.sequence - 1) conflict("structured memory stream changed before event commit");
|
|
176
|
+
if (existing.length > 0) {
|
|
177
|
+
const priorValue = this._resolveEvent(existing.at(-1), "structured-memory-event");
|
|
178
|
+
if (priorValue.sequence !== event.sequence - 1) fail("structured memory stream sequence is corrupt");
|
|
179
|
+
}
|
|
180
|
+
const prior = existing.at(-1);
|
|
181
|
+
const result = this._persist(STRUCTURED_MEMORY_LEDGER_EVENT_TYPE, "structured-memory-event", event,
|
|
182
|
+
eventDigest, "eventDigest", event.timestamp, prior ? [prior.subjectRef] : []);
|
|
183
|
+
return Object.freeze({ ...result, eventId: event.eventId });
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
persistSnapshot = async (snapshot) => {
|
|
187
|
+
if (snapshot?.schema !== STRUCTURED_MEMORY_SNAPSHOT_SCHEMA || snapshot.tenantId !== this.descriptor.tenantId ||
|
|
188
|
+
!DIGEST.test(snapshot.snapshotDigest || "")) throw new TypeError("structured memory snapshot input is invalid");
|
|
189
|
+
const existing = this._events(STRUCTURED_MEMORY_LEDGER_SNAPSHOT_TYPE);
|
|
190
|
+
const identical = existing.find((entry) => entry.eventId === `${STRUCTURED_MEMORY_LEDGER_SNAPSHOT_TYPE}.${snapshot.snapshotDigest.slice(7)}`);
|
|
191
|
+
if (identical) {
|
|
192
|
+
if (canonical(this._resolveEvent(identical, "structured-memory-snapshot")) !== canonical(snapshot)) {
|
|
193
|
+
fail("structured memory snapshot id resolved substituted content");
|
|
194
|
+
}
|
|
195
|
+
return Object.freeze({ persisted: true, snapshotDigest: snapshot.snapshotDigest, recovered: true });
|
|
196
|
+
}
|
|
197
|
+
const memoryEvents = this._events(STRUCTURED_MEMORY_LEDGER_EVENT_TYPE);
|
|
198
|
+
const projection = projectStructuredMemory(memoryEvents.map((entry) => this._resolveEvent(entry, "structured-memory-event")),
|
|
199
|
+
{ tenantId: this.descriptor.tenantId });
|
|
200
|
+
if (projection.sequence !== snapshot.throughSequence || projection.eventRoot !== snapshot.eventRoot ||
|
|
201
|
+
projection.projectionDigest !== snapshot.projectionDigest) {
|
|
202
|
+
conflict("structured memory changed before snapshot commit");
|
|
203
|
+
}
|
|
204
|
+
const sources = [memoryEvents.at(-1)?.subjectRef, existing.at(-1)?.subjectRef].filter(Boolean);
|
|
205
|
+
return this._persist(STRUCTURED_MEMORY_LEDGER_SNAPSHOT_TYPE, "structured-memory-snapshot", snapshot,
|
|
206
|
+
snapshot.snapshotDigest, "snapshotDigest", new Date(this._clock()).toISOString(), sources);
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
createMemory() {
|
|
210
|
+
const restored = this.load();
|
|
211
|
+
return new StructuredEvolutionMemory({ tenantId: this.descriptor.tenantId,
|
|
212
|
+
persistEvent: this.persistEvent, persistSnapshot: this.persistSnapshot,
|
|
213
|
+
postCompactVerifier: this._postCompactVerifier, receiptProvider: this._receiptProvider,
|
|
214
|
+
initialEvents: restored.events, initialSnapshot: restored.snapshot });
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export function createStructuredMemoryLedgerAdapter(options) {
|
|
219
|
+
return new StructuredMemoryLedgerAdapter(options);
|
|
220
|
+
}
|