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,313 @@
|
|
|
1
|
+
import structuredMemory from "@chainlesschain/session-core/structured-evolution-memory";
|
|
2
|
+
|
|
3
|
+
const { StructuredEvolutionMemory, createStructuredMemoryAuthorityReceipt } =
|
|
4
|
+
structuredMemory;
|
|
5
|
+
const DIGEST = /^sha256:[a-f0-9]{64}$/u;
|
|
6
|
+
const REVIEWERS = new WeakSet();
|
|
7
|
+
|
|
8
|
+
function requiredString(value, name) {
|
|
9
|
+
if (typeof value !== "string" || value.trim() === "") {
|
|
10
|
+
throw new TypeError(`${name} is required`);
|
|
11
|
+
}
|
|
12
|
+
return value;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function requiredDigest(value, name) {
|
|
16
|
+
if (!DIGEST.test(value || "")) {
|
|
17
|
+
throw new TypeError(`${name} must be sha256-bound`);
|
|
18
|
+
}
|
|
19
|
+
return value;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function strings(value, name, { allowEmpty = true } = {}) {
|
|
23
|
+
if (
|
|
24
|
+
!Array.isArray(value) ||
|
|
25
|
+
(!allowEmpty && value.length === 0) ||
|
|
26
|
+
value.length > 256 ||
|
|
27
|
+
value.some((item) => typeof item !== "string" || item.trim() === "")
|
|
28
|
+
) {
|
|
29
|
+
throw new TypeError(`${name} must be a bounded string list`);
|
|
30
|
+
}
|
|
31
|
+
return [...new Set(value)].sort();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function capture(owner, name) {
|
|
35
|
+
if (typeof owner?.[name] !== "function") {
|
|
36
|
+
throw new TypeError(`${name} port is required`);
|
|
37
|
+
}
|
|
38
|
+
return (...args) => Reflect.apply(owner[name], owner, args);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function descriptor(input) {
|
|
42
|
+
if (!["critic", "evaluator"].includes(input?.kind)) {
|
|
43
|
+
throw new TypeError("semantic reviewer kind is invalid");
|
|
44
|
+
}
|
|
45
|
+
for (const field of ["issuerRevision", "verifierRevision"]) {
|
|
46
|
+
if (!Number.isSafeInteger(input[field]) || input[field] < 1) {
|
|
47
|
+
throw new TypeError(`${field} must be a positive integer`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
const value = Object.freeze({
|
|
51
|
+
tenantId: requiredString(input.tenantId, "tenantId"),
|
|
52
|
+
kind: input.kind,
|
|
53
|
+
issuerId: requiredString(input.issuerId, "issuerId"),
|
|
54
|
+
issuerRevision: input.issuerRevision,
|
|
55
|
+
issuerHandlerDigest: requiredDigest(
|
|
56
|
+
input.issuerHandlerDigest,
|
|
57
|
+
"issuerHandlerDigest",
|
|
58
|
+
),
|
|
59
|
+
verifierId: requiredString(input.verifierId, "verifierId"),
|
|
60
|
+
verifierRevision: input.verifierRevision,
|
|
61
|
+
verifierHandlerDigest: requiredDigest(
|
|
62
|
+
input.verifierHandlerDigest,
|
|
63
|
+
"verifierHandlerDigest",
|
|
64
|
+
),
|
|
65
|
+
});
|
|
66
|
+
if (
|
|
67
|
+
value.issuerId === value.verifierId ||
|
|
68
|
+
value.issuerHandlerDigest === value.verifierHandlerDigest
|
|
69
|
+
) {
|
|
70
|
+
throw new Error(
|
|
71
|
+
"semantic review producer and verifier must be independent",
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
return value;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function normalizeRequest(input, tenantId) {
|
|
78
|
+
return Object.freeze({
|
|
79
|
+
tenantId,
|
|
80
|
+
memoryId: requiredString(input?.memoryId, "memoryId"),
|
|
81
|
+
layer:
|
|
82
|
+
input?.layer === "semantic"
|
|
83
|
+
? "semantic"
|
|
84
|
+
: (() => {
|
|
85
|
+
throw new TypeError("semantic layer is required");
|
|
86
|
+
})(),
|
|
87
|
+
action:
|
|
88
|
+
input?.action === "accept"
|
|
89
|
+
? "accept"
|
|
90
|
+
: (() => {
|
|
91
|
+
throw new TypeError("semantic accept action is required");
|
|
92
|
+
})(),
|
|
93
|
+
contentDigest: requiredDigest(input?.contentDigest, "contentDigest"),
|
|
94
|
+
artifactRef: requiredString(input?.artifactRef, "artifactRef"),
|
|
95
|
+
evidenceRefs: strings(input?.evidenceRefs, "evidenceRefs", {
|
|
96
|
+
allowEmpty: false,
|
|
97
|
+
}),
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function createStructuredMemorySemanticReviewer({
|
|
102
|
+
descriptor: input,
|
|
103
|
+
producer,
|
|
104
|
+
attestor,
|
|
105
|
+
verifier,
|
|
106
|
+
clock = () => new Date().toISOString(),
|
|
107
|
+
} = {}) {
|
|
108
|
+
const identity = descriptor(input);
|
|
109
|
+
const review = capture(producer, "review");
|
|
110
|
+
const attest = capture(attestor, "attest");
|
|
111
|
+
const verify = capture(verifier, "verify");
|
|
112
|
+
if (typeof clock !== "function")
|
|
113
|
+
throw new TypeError("clock must be a function");
|
|
114
|
+
const reviewer = Object.freeze({
|
|
115
|
+
identity,
|
|
116
|
+
async issue(requestInput) {
|
|
117
|
+
const request = normalizeRequest(requestInput, identity.tenantId);
|
|
118
|
+
const outcome = await review(request);
|
|
119
|
+
if (!outcome || !["accepted", "rejected"].includes(outcome.decision)) {
|
|
120
|
+
throw new Error(`${identity.kind} returned an invalid review decision`);
|
|
121
|
+
}
|
|
122
|
+
const reasonCodes = strings(outcome.reasonCodes || [], "reasonCodes");
|
|
123
|
+
if (outcome.decision !== "accepted") {
|
|
124
|
+
return Object.freeze({
|
|
125
|
+
accepted: false,
|
|
126
|
+
kind: identity.kind,
|
|
127
|
+
reasonCodes,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
const issuedAt = requiredString(clock(), "issuedAt");
|
|
131
|
+
if (!Number.isFinite(Date.parse(issuedAt))) {
|
|
132
|
+
throw new TypeError("issuedAt must be an ISO timestamp");
|
|
133
|
+
}
|
|
134
|
+
const receipt = createStructuredMemoryAuthorityReceipt({
|
|
135
|
+
...request,
|
|
136
|
+
kind: identity.kind,
|
|
137
|
+
decision: "accepted",
|
|
138
|
+
issuerId: identity.issuerId,
|
|
139
|
+
issuerRevision: identity.issuerRevision,
|
|
140
|
+
issuerHandlerDigest: identity.issuerHandlerDigest,
|
|
141
|
+
issuedAt,
|
|
142
|
+
});
|
|
143
|
+
const attestation = await attest({
|
|
144
|
+
purpose: `structured-memory-${identity.kind}-receipt`,
|
|
145
|
+
payloadDigest: receipt.receiptDigest,
|
|
146
|
+
receipt,
|
|
147
|
+
reasonCodes,
|
|
148
|
+
});
|
|
149
|
+
if (attestation === null || attestation === undefined) {
|
|
150
|
+
throw new Error(`${identity.kind} attestor returned no attestation`);
|
|
151
|
+
}
|
|
152
|
+
const signed = Object.freeze({ ...receipt, attestation });
|
|
153
|
+
if (
|
|
154
|
+
(await verify({
|
|
155
|
+
descriptor: identity,
|
|
156
|
+
request,
|
|
157
|
+
receipt: signed,
|
|
158
|
+
reasonCodes,
|
|
159
|
+
})) !== true
|
|
160
|
+
) {
|
|
161
|
+
throw new Error(`${identity.kind} receipt authentication failed`);
|
|
162
|
+
}
|
|
163
|
+
return Object.freeze({
|
|
164
|
+
accepted: true,
|
|
165
|
+
kind: identity.kind,
|
|
166
|
+
reasonCodes,
|
|
167
|
+
receipt: signed,
|
|
168
|
+
});
|
|
169
|
+
},
|
|
170
|
+
});
|
|
171
|
+
REVIEWERS.add(reviewer);
|
|
172
|
+
return reviewer;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function captureReviewer(value, kind, tenantId) {
|
|
176
|
+
if (
|
|
177
|
+
!REVIEWERS.has(value) ||
|
|
178
|
+
value.identity.kind !== kind ||
|
|
179
|
+
value.identity.tenantId !== tenantId
|
|
180
|
+
) {
|
|
181
|
+
throw new TypeError(`a branded tenant-scoped ${kind} reviewer is required`);
|
|
182
|
+
}
|
|
183
|
+
return Object.freeze({
|
|
184
|
+
identity: value.identity,
|
|
185
|
+
issue: capture(value, "issue"),
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export function createStructuredMemorySemanticReviewPipeline({
|
|
190
|
+
tenantId: tenantIdInput,
|
|
191
|
+
memory,
|
|
192
|
+
authorityStore,
|
|
193
|
+
critic,
|
|
194
|
+
evaluator,
|
|
195
|
+
proposerAuthority,
|
|
196
|
+
governorAuthority,
|
|
197
|
+
} = {}) {
|
|
198
|
+
const tenantId = requiredString(tenantIdInput, "tenantId");
|
|
199
|
+
if (
|
|
200
|
+
!(memory instanceof StructuredEvolutionMemory) ||
|
|
201
|
+
memory.tenantId !== tenantId
|
|
202
|
+
) {
|
|
203
|
+
throw new TypeError(
|
|
204
|
+
"a tenant-scoped StructuredEvolutionMemory is required",
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
const retainReceipt = capture(authorityStore, "retainReceipt");
|
|
208
|
+
const reviewers = Object.freeze({
|
|
209
|
+
critic: captureReviewer(critic, "critic", tenantId),
|
|
210
|
+
evaluator: captureReviewer(evaluator, "evaluator", tenantId),
|
|
211
|
+
});
|
|
212
|
+
const authorityIds = [
|
|
213
|
+
reviewers.critic.identity.issuerId,
|
|
214
|
+
reviewers.critic.identity.verifierId,
|
|
215
|
+
reviewers.evaluator.identity.issuerId,
|
|
216
|
+
reviewers.evaluator.identity.verifierId,
|
|
217
|
+
];
|
|
218
|
+
const handlerDigests = [
|
|
219
|
+
reviewers.critic.identity.issuerHandlerDigest,
|
|
220
|
+
reviewers.critic.identity.verifierHandlerDigest,
|
|
221
|
+
reviewers.evaluator.identity.issuerHandlerDigest,
|
|
222
|
+
reviewers.evaluator.identity.verifierHandlerDigest,
|
|
223
|
+
];
|
|
224
|
+
if (
|
|
225
|
+
new Set(authorityIds).size !== authorityIds.length ||
|
|
226
|
+
new Set(handlerDigests).size !== handlerDigests.length
|
|
227
|
+
) {
|
|
228
|
+
throw new Error("critic and evaluator authorities must be independent");
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return Object.freeze({
|
|
232
|
+
tenantId,
|
|
233
|
+
async propose(input = {}) {
|
|
234
|
+
return memory.append({
|
|
235
|
+
eventId: requiredString(input.eventId, "eventId"),
|
|
236
|
+
memoryId: requiredString(input.memoryId, "memoryId"),
|
|
237
|
+
layer: "semantic",
|
|
238
|
+
action: "propose",
|
|
239
|
+
authority: proposerAuthority,
|
|
240
|
+
automatic: input.automatic !== false,
|
|
241
|
+
contentDigest: requiredDigest(input.contentDigest, "contentDigest"),
|
|
242
|
+
artifactRef: requiredString(input.artifactRef, "artifactRef"),
|
|
243
|
+
evidenceRefs: strings(input.evidenceRefs, "evidenceRefs", {
|
|
244
|
+
allowEmpty: false,
|
|
245
|
+
}),
|
|
246
|
+
supersedes: strings(input.supersedes || [], "supersedes"),
|
|
247
|
+
timestamp: requiredString(input.timestamp, "timestamp"),
|
|
248
|
+
metadata: input.metadata || {},
|
|
249
|
+
});
|
|
250
|
+
},
|
|
251
|
+
async reviewAndAccept({
|
|
252
|
+
memoryId,
|
|
253
|
+
eventId,
|
|
254
|
+
timestamp,
|
|
255
|
+
metadata = {},
|
|
256
|
+
} = {}) {
|
|
257
|
+
const proposed =
|
|
258
|
+
memory.projection().memories[requiredString(memoryId, "memoryId")];
|
|
259
|
+
if (
|
|
260
|
+
!proposed ||
|
|
261
|
+
proposed.layer !== "semantic" ||
|
|
262
|
+
proposed.status !== "proposed"
|
|
263
|
+
) {
|
|
264
|
+
throw new Error("semantic memory is not awaiting review");
|
|
265
|
+
}
|
|
266
|
+
const request = {
|
|
267
|
+
tenantId,
|
|
268
|
+
memoryId: proposed.memoryId,
|
|
269
|
+
layer: "semantic",
|
|
270
|
+
action: "accept",
|
|
271
|
+
contentDigest: proposed.contentDigest,
|
|
272
|
+
artifactRef: proposed.artifactRef,
|
|
273
|
+
evidenceRefs: proposed.evidenceRefs,
|
|
274
|
+
};
|
|
275
|
+
const [criticResult, evaluatorResult] = await Promise.all([
|
|
276
|
+
reviewers.critic.issue(request),
|
|
277
|
+
reviewers.evaluator.issue(request),
|
|
278
|
+
]);
|
|
279
|
+
if (!criticResult.accepted || !evaluatorResult.accepted) {
|
|
280
|
+
throw new Error("semantic memory was rejected by independent review");
|
|
281
|
+
}
|
|
282
|
+
for (const result of [criticResult, evaluatorResult]) {
|
|
283
|
+
const retained = await retainReceipt(result.receipt);
|
|
284
|
+
if (
|
|
285
|
+
retained?.persisted !== true ||
|
|
286
|
+
retained.receiptDigest !== result.receipt.receiptDigest
|
|
287
|
+
) {
|
|
288
|
+
throw new Error(
|
|
289
|
+
`${result.kind} receipt was not durably acknowledged`,
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
return memory.append({
|
|
294
|
+
eventId: requiredString(eventId, "eventId"),
|
|
295
|
+
memoryId: proposed.memoryId,
|
|
296
|
+
layer: "semantic",
|
|
297
|
+
action: "accept",
|
|
298
|
+
authority: governorAuthority,
|
|
299
|
+
automatic: false,
|
|
300
|
+
contentDigest: proposed.contentDigest,
|
|
301
|
+
artifactRef: proposed.artifactRef,
|
|
302
|
+
evidenceRefs: proposed.evidenceRefs,
|
|
303
|
+
supersedes: proposed.supersedes,
|
|
304
|
+
receiptRefs: {
|
|
305
|
+
critic: criticResult.receipt.receiptDigest,
|
|
306
|
+
evaluator: evaluatorResult.receipt.receiptDigest,
|
|
307
|
+
},
|
|
308
|
+
timestamp: requiredString(timestamp, "timestamp"),
|
|
309
|
+
metadata,
|
|
310
|
+
});
|
|
311
|
+
},
|
|
312
|
+
});
|
|
313
|
+
}
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
|
|
3
|
+
export const WIKI_SKILL_PROPOSAL_SCHEMA =
|
|
4
|
+
"chainlesschain.wiki-informed-skill-proposal/v1";
|
|
5
|
+
export const WIKI_PROPOSAL_STATUS = Object.freeze({
|
|
6
|
+
PROPOSAL: "proposal",
|
|
7
|
+
NO_PROPOSAL: "no-proposal",
|
|
8
|
+
NEEDS_EVIDENCE: "needs-evidence",
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
const DIGEST = /^sha256:[a-f0-9]{64}$/u;
|
|
12
|
+
const SKILL_NAME = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/u;
|
|
13
|
+
const INITIAL_SOURCES = Object.freeze([
|
|
14
|
+
"wiki-index",
|
|
15
|
+
"skill-impact",
|
|
16
|
+
"active-skill",
|
|
17
|
+
"training-summary",
|
|
18
|
+
]);
|
|
19
|
+
const SELECTIVE_SOURCES = new Set(["pattern", "raw"]);
|
|
20
|
+
const SAFE_DIFF_ROOTS = new Set([
|
|
21
|
+
"SKILL.md",
|
|
22
|
+
"PURPOSE.md",
|
|
23
|
+
"assets",
|
|
24
|
+
"references",
|
|
25
|
+
"scripts",
|
|
26
|
+
]);
|
|
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)
|
|
32
|
+
.sort()
|
|
33
|
+
.map((key) => `${JSON.stringify(key)}:${canonical(value[key])}`)
|
|
34
|
+
.join(",")}}`;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function hash(value) {
|
|
38
|
+
return `sha256:${createHash("sha256").update(canonical(value)).digest("hex")}`;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function deepFreeze(value) {
|
|
42
|
+
if (value && typeof value === "object" && !Object.isFrozen(value)) {
|
|
43
|
+
Object.freeze(value);
|
|
44
|
+
for (const child of Object.values(value)) deepFreeze(child);
|
|
45
|
+
}
|
|
46
|
+
return value;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function requiredString(value, name) {
|
|
50
|
+
if (typeof value !== "string" || value.trim() === "") {
|
|
51
|
+
throw new TypeError(`${name} is required`);
|
|
52
|
+
}
|
|
53
|
+
return value;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function stringList(value, name, { allowEmpty = false, max = 64 } = {}) {
|
|
57
|
+
if (
|
|
58
|
+
!Array.isArray(value) ||
|
|
59
|
+
(!allowEmpty && value.length === 0) ||
|
|
60
|
+
value.length > max ||
|
|
61
|
+
value.some((item) => typeof item !== "string" || item.trim() === "") ||
|
|
62
|
+
new Set(value).size !== value.length
|
|
63
|
+
) {
|
|
64
|
+
throw new TypeError(`${name} must be a bounded unique string list`);
|
|
65
|
+
}
|
|
66
|
+
return [...value];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function verifyEnvelope(value, expectedKind) {
|
|
70
|
+
if (
|
|
71
|
+
!value ||
|
|
72
|
+
typeof value !== "object" ||
|
|
73
|
+
value.kind !== expectedKind ||
|
|
74
|
+
value.trusted !== true ||
|
|
75
|
+
typeof value.ref !== "string" ||
|
|
76
|
+
!DIGEST.test(value.digest ?? "") ||
|
|
77
|
+
value.digest !== hash(value.data)
|
|
78
|
+
) {
|
|
79
|
+
const error = new Error(`${expectedKind} evidence is not digest-bound and trusted`);
|
|
80
|
+
error.code = "WIKI_PROPOSAL_UNTRUSTED_EVIDENCE";
|
|
81
|
+
throw error;
|
|
82
|
+
}
|
|
83
|
+
return deepFreeze({
|
|
84
|
+
kind: value.kind,
|
|
85
|
+
ref: value.ref,
|
|
86
|
+
digest: value.digest,
|
|
87
|
+
data: structuredClone(value.data),
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function normalizeDescriptor(input) {
|
|
92
|
+
const descriptor = {
|
|
93
|
+
tenantId: requiredString(input?.tenantId, "tenantId"),
|
|
94
|
+
evolutionRunId: requiredString(input?.evolutionRunId, "evolutionRunId"),
|
|
95
|
+
targetSkillName: requiredString(input?.targetSkillName, "targetSkillName"),
|
|
96
|
+
wikiRevision: requiredString(input?.wikiRevision, "wikiRevision"),
|
|
97
|
+
proposerModel: requiredString(input?.proposerModel, "proposerModel"),
|
|
98
|
+
minEvidenceSamples: Math.max(1, Number(input?.minEvidenceSamples) || 1),
|
|
99
|
+
maxSelectiveEvidence: Math.min(
|
|
100
|
+
16,
|
|
101
|
+
Math.max(0, Number(input?.maxSelectiveEvidence) || 4),
|
|
102
|
+
),
|
|
103
|
+
};
|
|
104
|
+
if (!SKILL_NAME.test(descriptor.targetSkillName)) {
|
|
105
|
+
throw new TypeError("targetSkillName must be canonical kebab-case");
|
|
106
|
+
}
|
|
107
|
+
return deepFreeze(descriptor);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function validateDiff(diff) {
|
|
111
|
+
if (!Array.isArray(diff) || diff.length === 0 || diff.length > 128) {
|
|
112
|
+
throw new TypeError("machineDiff must contain 1..128 operations");
|
|
113
|
+
}
|
|
114
|
+
return diff.map((entry) => {
|
|
115
|
+
if (!entry || !["add", "replace", "remove"].includes(entry.op)) {
|
|
116
|
+
throw new TypeError("machineDiff operation is invalid");
|
|
117
|
+
}
|
|
118
|
+
const path = requiredString(entry.path, "machineDiff.path").replaceAll("\\", "/");
|
|
119
|
+
const parts = path.split("/");
|
|
120
|
+
if (
|
|
121
|
+
path.startsWith("/") ||
|
|
122
|
+
parts.includes("..") ||
|
|
123
|
+
!SAFE_DIFF_ROOTS.has(parts[0]) ||
|
|
124
|
+
/(^|\/)(active|\.chainlesschain)(\/|$)/u.test(path)
|
|
125
|
+
) {
|
|
126
|
+
const error = new Error("machineDiff escaped the single candidate Skill");
|
|
127
|
+
error.code = "WIKI_PROPOSAL_UNSAFE_DIFF";
|
|
128
|
+
throw error;
|
|
129
|
+
}
|
|
130
|
+
return {
|
|
131
|
+
op: entry.op,
|
|
132
|
+
path,
|
|
133
|
+
beforeDigest: entry.beforeDigest ?? null,
|
|
134
|
+
afterDigest: entry.afterDigest ?? null,
|
|
135
|
+
};
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function validateProposal(output, descriptor, evidence) {
|
|
140
|
+
if (output?.status !== WIKI_PROPOSAL_STATUS.PROPOSAL) {
|
|
141
|
+
throw new TypeError("proposal output status is invalid");
|
|
142
|
+
}
|
|
143
|
+
if (output.skillName !== descriptor.targetSkillName) {
|
|
144
|
+
const error = new Error("proposer attempted to change more than the fixed Skill");
|
|
145
|
+
error.code = "WIKI_PROPOSAL_MULTI_SKILL";
|
|
146
|
+
throw error;
|
|
147
|
+
}
|
|
148
|
+
const knownRefs = new Set(evidence.map((item) => item.ref));
|
|
149
|
+
const purpose = {
|
|
150
|
+
summary: requiredString(output.purpose?.summary, "purpose.summary"),
|
|
151
|
+
patternRefs: stringList(output.purpose?.patternRefs, "purpose.patternRefs"),
|
|
152
|
+
sourceEvidenceRefs: stringList(
|
|
153
|
+
output.purpose?.sourceEvidenceRefs,
|
|
154
|
+
"purpose.sourceEvidenceRefs",
|
|
155
|
+
),
|
|
156
|
+
};
|
|
157
|
+
for (const ref of [...purpose.patternRefs, ...purpose.sourceEvidenceRefs]) {
|
|
158
|
+
if (!knownRefs.has(ref)) {
|
|
159
|
+
const error = new Error("PURPOSE references evidence outside the resolved set");
|
|
160
|
+
error.code = "WIKI_PROPOSAL_UNKNOWN_LINEAGE";
|
|
161
|
+
throw error;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
const contextCost = {
|
|
165
|
+
maxTokens: Number(output.contextCost?.maxTokens),
|
|
166
|
+
maxBytes: Number(output.contextCost?.maxBytes),
|
|
167
|
+
};
|
|
168
|
+
if (
|
|
169
|
+
!Number.isInteger(contextCost.maxTokens) ||
|
|
170
|
+
contextCost.maxTokens <= 0 ||
|
|
171
|
+
!Number.isInteger(contextCost.maxBytes) ||
|
|
172
|
+
contextCost.maxBytes <= 0
|
|
173
|
+
) {
|
|
174
|
+
throw new TypeError("contextCost must provide positive maxTokens/maxBytes");
|
|
175
|
+
}
|
|
176
|
+
return deepFreeze({
|
|
177
|
+
schema: WIKI_SKILL_PROPOSAL_SCHEMA,
|
|
178
|
+
status: WIKI_PROPOSAL_STATUS.PROPOSAL,
|
|
179
|
+
tenantId: descriptor.tenantId,
|
|
180
|
+
evolutionRunId: descriptor.evolutionRunId,
|
|
181
|
+
skillName: descriptor.targetSkillName,
|
|
182
|
+
purpose,
|
|
183
|
+
applicableWhen: stringList(output.applicableWhen, "applicableWhen"),
|
|
184
|
+
notApplicableWhen: stringList(output.notApplicableWhen, "notApplicableWhen"),
|
|
185
|
+
failureCounterexamples: stringList(
|
|
186
|
+
output.failureCounterexamples,
|
|
187
|
+
"failureCounterexamples",
|
|
188
|
+
),
|
|
189
|
+
rollbackSteps: stringList(output.rollbackSteps, "rollbackSteps"),
|
|
190
|
+
validationMethods: stringList(output.validationMethods, "validationMethods"),
|
|
191
|
+
requestedCapabilities: stringList(
|
|
192
|
+
output.requestedCapabilities,
|
|
193
|
+
"requestedCapabilities",
|
|
194
|
+
{ allowEmpty: true },
|
|
195
|
+
),
|
|
196
|
+
targetRuntimes: stringList(output.targetRuntimes, "targetRuntimes"),
|
|
197
|
+
contextCost,
|
|
198
|
+
machineDiff: validateDiff(output.machineDiff),
|
|
199
|
+
sourceEvidenceRefs: evidence.map(({ ref, digest }) => ({ ref, digest })),
|
|
200
|
+
wikiRevision: descriptor.wikiRevision,
|
|
201
|
+
proposerModel: descriptor.proposerModel,
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function abstention(status, reason, evidence = []) {
|
|
206
|
+
return deepFreeze({
|
|
207
|
+
schema: WIKI_SKILL_PROPOSAL_SCHEMA,
|
|
208
|
+
status,
|
|
209
|
+
reason,
|
|
210
|
+
sourceEvidenceRefs: evidence.map(({ ref, digest }) => ({ ref, digest })),
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export class WikiInformedSkillProposer {
|
|
215
|
+
constructor({ descriptor, policy, ports } = {}) {
|
|
216
|
+
this.descriptor = normalizeDescriptor(descriptor);
|
|
217
|
+
if (policy?.proposerWikiRead !== true || policy?.executionAgentWikiRead === true) {
|
|
218
|
+
throw new Error("capability policy must isolate Wiki reads to the proposer");
|
|
219
|
+
}
|
|
220
|
+
if (typeof ports?.readInitial !== "function")
|
|
221
|
+
throw new TypeError("readInitial port is required");
|
|
222
|
+
if (typeof ports?.readSelective !== "function")
|
|
223
|
+
throw new TypeError("readSelective port is required");
|
|
224
|
+
if (typeof ports?.generate !== "function")
|
|
225
|
+
throw new TypeError("generate port is required");
|
|
226
|
+
if (typeof ports?.createCandidate !== "function")
|
|
227
|
+
throw new TypeError("createCandidate port is required");
|
|
228
|
+
this._ports = ports;
|
|
229
|
+
Object.freeze(this);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
async propose() {
|
|
233
|
+
const initial = [];
|
|
234
|
+
for (const kind of INITIAL_SOURCES) {
|
|
235
|
+
initial.push(verifyEnvelope(await this._ports.readInitial(kind), kind));
|
|
236
|
+
}
|
|
237
|
+
const wiki = initial.find((item) => item.kind === "wiki-index");
|
|
238
|
+
const training = initial.find((item) => item.kind === "training-summary");
|
|
239
|
+
if ((wiki.data?.contradictionRefs?.length ?? 0) > 0) {
|
|
240
|
+
return abstention(
|
|
241
|
+
WIKI_PROPOSAL_STATUS.NEEDS_EVIDENCE,
|
|
242
|
+
"wiki evidence is contradictory",
|
|
243
|
+
initial,
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
if (Number(training.data?.sampleCount) < this.descriptor.minEvidenceSamples) {
|
|
247
|
+
return abstention(
|
|
248
|
+
WIKI_PROPOSAL_STATUS.NEEDS_EVIDENCE,
|
|
249
|
+
"training evidence sample is insufficient",
|
|
250
|
+
initial,
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
let evidence = [...initial];
|
|
255
|
+
let output = await this._ports.generate({
|
|
256
|
+
descriptor: this.descriptor,
|
|
257
|
+
evidence: deepFreeze([...evidence]),
|
|
258
|
+
});
|
|
259
|
+
if (output?.status === WIKI_PROPOSAL_STATUS.NO_PROPOSAL) {
|
|
260
|
+
return abstention(output.status, requiredString(output.reason, "reason"), evidence);
|
|
261
|
+
}
|
|
262
|
+
if (output?.status === WIKI_PROPOSAL_STATUS.NEEDS_EVIDENCE) {
|
|
263
|
+
const requests = output.requests;
|
|
264
|
+
if (
|
|
265
|
+
!Array.isArray(requests) ||
|
|
266
|
+
requests.length === 0 ||
|
|
267
|
+
requests.length > this.descriptor.maxSelectiveEvidence
|
|
268
|
+
) {
|
|
269
|
+
return abstention(output.status, "selective evidence request is invalid", evidence);
|
|
270
|
+
}
|
|
271
|
+
for (const request of requests) {
|
|
272
|
+
if (!SELECTIVE_SOURCES.has(request?.kind)) {
|
|
273
|
+
return abstention(output.status, "requested evidence scope is not allowed", evidence);
|
|
274
|
+
}
|
|
275
|
+
evidence.push(
|
|
276
|
+
verifyEnvelope(
|
|
277
|
+
await this._ports.readSelective(request.kind, request.ref),
|
|
278
|
+
request.kind,
|
|
279
|
+
),
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
output = await this._ports.generate({
|
|
283
|
+
descriptor: this.descriptor,
|
|
284
|
+
evidence: deepFreeze([...evidence]),
|
|
285
|
+
});
|
|
286
|
+
if (output?.status !== WIKI_PROPOSAL_STATUS.PROPOSAL) {
|
|
287
|
+
return abstention(
|
|
288
|
+
output?.status === WIKI_PROPOSAL_STATUS.NO_PROPOSAL
|
|
289
|
+
? output.status
|
|
290
|
+
: WIKI_PROPOSAL_STATUS.NEEDS_EVIDENCE,
|
|
291
|
+
requiredString(output?.reason, "reason"),
|
|
292
|
+
evidence,
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
const proposal = validateProposal(output, this.descriptor, evidence);
|
|
298
|
+
const proposalDigest = hash(proposal);
|
|
299
|
+
const candidateInput = deepFreeze({
|
|
300
|
+
tenantId: proposal.tenantId,
|
|
301
|
+
skillName: proposal.skillName,
|
|
302
|
+
derivationMode: "wiki",
|
|
303
|
+
wikiRevision: proposal.wikiRevision,
|
|
304
|
+
proposerModel: proposal.proposerModel,
|
|
305
|
+
requestedCapabilities: proposal.requestedCapabilities,
|
|
306
|
+
sourceEvidenceRefs: proposal.sourceEvidenceRefs,
|
|
307
|
+
content: canonical(proposal),
|
|
308
|
+
});
|
|
309
|
+
const created = await this._ports.createCandidate(candidateInput);
|
|
310
|
+
const candidate = created?.candidate;
|
|
311
|
+
if (
|
|
312
|
+
typeof candidate?.candidateId !== "string" ||
|
|
313
|
+
typeof candidate?.contentDigest !== "string" ||
|
|
314
|
+
candidate.skillName !== proposal.skillName ||
|
|
315
|
+
candidate.content !== candidateInput.content ||
|
|
316
|
+
candidate.derivationMode !== "wiki" ||
|
|
317
|
+
candidate.wikiRevision !== proposal.wikiRevision ||
|
|
318
|
+
candidate.proposerModel !== proposal.proposerModel ||
|
|
319
|
+
canonical(candidate.requestedCapabilities) !==
|
|
320
|
+
canonical(proposal.requestedCapabilities) ||
|
|
321
|
+
canonical(candidate.targetRuntimes) !== canonical(proposal.targetRuntimes) ||
|
|
322
|
+
canonical(candidate.sourceEvidenceRefs) !==
|
|
323
|
+
canonical(proposal.sourceEvidenceRefs)
|
|
324
|
+
) {
|
|
325
|
+
const error = new Error(
|
|
326
|
+
"candidate sink did not return an exact immutable proposal binding",
|
|
327
|
+
);
|
|
328
|
+
error.code = "WIKI_PROPOSAL_CANDIDATE_UNCONFIRMED";
|
|
329
|
+
throw error;
|
|
330
|
+
}
|
|
331
|
+
return deepFreeze({
|
|
332
|
+
status: WIKI_PROPOSAL_STATUS.PROPOSAL,
|
|
333
|
+
proposal,
|
|
334
|
+
proposalDigest,
|
|
335
|
+
candidateId: candidate.candidateId,
|
|
336
|
+
contentDigest: candidate.contentDigest,
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
export function createWikiInformedSkillProposer(options) {
|
|
342
|
+
return new WikiInformedSkillProposer(options);
|
|
343
|
+
}
|