chainlesschain 0.166.21 → 0.166.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.
- package/README.md +67 -9
- package/package.json +4 -3
- package/src/assets/web-panel/assets/{AIOps-BjMnsUci.js → AIOps-DR-MWcZc.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-DdYFP03A.js → ActionButton-DT8B7sEb.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-Bb8TuuK_.js → Analytics-asjh3dQJ.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-Kn3TIOtk.js → AppLayout-DivQ491i.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-4IxpqI_b.js → Artifacts-DPH2uUmy.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-BOV2caqU.js → Audit-Bp2nLyc-.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-B86k-ay4.js → BackgroundAgents-CHS28khl.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-C5_ie1e3.js → Backup-CKeaFSfz.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-xpwg6QCW.js → BaseInput-CxwM9BAH.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-CVZOcZau.js → Chat-DYLDwaCv.js} +4 -4
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-D8fPYhUu.js → ChatBubbleRenderer-DdBJDBP0.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-MKTq3zdP.js → Checkbox-uYTWOB8j.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-JUk3wzep.js → Codegen-CvYa_dwT.js} +1 -1
- package/src/assets/web-panel/assets/{Col-JPvTA0kC.js → Col-CanMAX4m.js} +1 -1
- package/src/assets/web-panel/assets/{Community-Tqgl87NQ.js → Community-B4WaDtHw.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-BuAFYBmN.js → Compact-K93Uof_3.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-CXS9WIPZ.js → Compliance-CKeDLgUW.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-Ds2bFHrr.js → Cowork-P93grAeB.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-C_dV_OeW.js → Cron-BSHnMtDn.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-BsO6tIRo.js → Crosschain-epAOpUVJ.js} +1 -1
- package/src/assets/web-panel/assets/{DID-rNOFqBac.js → DID-ByjXfP7t.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-C2fcKKVY.js → Dashboard-QztTU8tb.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-Y7Ndr0X_.js → Dropdown-DhUc9yhN.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-DcP_uPmL.js → EmailListRenderer-C2sLhJJN.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-Cwn3gDzk.js → FamilyGuardDashboard-CdfbWNDn.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-ClQuOsqb.js → Federation-CcF_R7NW.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-DfwtmlcK.js → FormItemContext-Cm_X2IBk.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-zNZhtbC5.js → GenericCardRenderer-DUi4NWlb.js} +1 -1
- package/src/assets/web-panel/assets/{Git-BZmdW-G5.js → Git-4Sq5FjBt.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-CqBk4lEn.js → Governance-Dx2_v4V6.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-Dbmt3ZXk.js → Inference-7Vr1xekR.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-hMTH6qf3.js → KnowledgeGraph-Cnd2XOzf.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-CkiYgiW2.js → Logs-B66QPVf-.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-BL1FElXg.js → MarkdownRenderer-PLsEvhly.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-CbB6wfin.js → Marketplace-BMIK9BmC.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-BSwiFtte.js → McpTools-BDbyp3J_.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-B03PeHrz.js → Memory-CJdzfZGi.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-CRGrnd-X.js → MobileBridge-C2TH5Y3-.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-CE_5v2kO.js → MobileProjects-D1dYXkvV.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-Dp11QVx1.js → Mtc-B-4A1I1j.js} +4 -4
- package/src/assets/web-panel/assets/{MtcAudit-CYu-3JBu.js → MtcAudit-Bgcc9UOl.js} +5 -5
- package/src/assets/web-panel/assets/{Multisig-CGyJ0Xl3.js → Multisig-DqOe-etP.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-CoWi_ov1.js → NLProgramming-7VnhzE_6.js} +1 -1
- package/src/assets/web-panel/assets/Notes-BxawpeUQ.js +7 -0
- package/src/assets/web-panel/assets/{NotificationSettings-DX4I2b4W.js → NotificationSettings-Cr08G2aE.js} +1 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-Ce8bEGlK.js +1 -0
- package/src/assets/web-panel/assets/{Organization-oopLO_tk.js → Organization-BC7lveGv.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-BFVvjMyf.js → Overflow-CakOW-G0.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-CBy5t-Tk.js → P2P-Cf8CaOBZ.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser--YWJNsu6.js → PdhVaultBrowser-Dc7b98W9.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-C2dZ8scb.js → Permissions-DGJyMEfS.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-Bs3l7Hlx.js → PersonalDataHub-DNIwSdwu.js} +6 -6
- package/src/assets/web-panel/assets/{Pipeline-DEBWbZuD.js → Pipeline-5B1S12wa.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-CjHBb6NU.js → Privacy-CMB6Ke5t.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-D2WipUz5.js → ProjectInit-D5PqTFiT.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-B6WfnrGB.js → ProjectSettings-CbKNdSjV.js} +2 -2
- package/src/assets/web-panel/assets/Projects-ccXaHzYL.js +1 -0
- package/src/assets/web-panel/assets/{Providers-CCv5M_Dv.js → Providers-CJF5_-Gs.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-CGthxU54.js → QrScannerModal-CT6iEAdi.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-CnPmXPFb.js → QuickAsk-Ci0h9mJ_.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-Df_tGEa9.js → Recommend-Da5mobZu.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-Z58N0Loe.js → RemoteSession-BaCY8eey.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-CZTBQ2Vt.js → Reputation-CaITfTsI.js} +1 -1
- package/src/assets/web-panel/assets/{Row-CdK3YpCQ.js → Row-DtUDamyP.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-CFMVT5sb.js → RssFeed-DX27gFpg.js} +3 -3
- package/src/assets/web-panel/assets/{Search-DrF8RIvD.js → Search-DFL69osN.js} +1 -1
- package/src/assets/web-panel/assets/{Security-Ddk2f2DM.js → Security-BqGeoWv-.js} +3 -3
- package/src/assets/web-panel/assets/{Services-CCuK-VOo.js → Services-3z1WnEAc.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-DxCpHzeM.js → Skeleton-C_OJQQ9Z.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-t2oTDgcv.js → Skills-BY7aT6Mo.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-Df63M9_R.js → Sla-BZv7DSaD.js} +1 -1
- package/src/assets/web-panel/assets/SpeechSettings-6lJKLhCn.js +1 -0
- package/src/assets/web-panel/assets/{SyncSettings-COd_tgPp.js → SyncSettings-B6D7STlI.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-CzDCcrik.js → Tasks-Co_FCZAO.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-D-vfxTGA.js → Templates-CnY-9fgz.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-BlpT_Gxc.js → Tenant-B71yXfZ8.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-D5rq52Hg.js → Terminal-Dd_P7awo.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-DdoMndkK.js → TimelineRenderer-CvIEMyli.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-BhgBsI6g.js → Tokens-DknFBGOi.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-DwwzoikZ.js → Trigger-D_4nJONB.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-HkTpzXFb.js → Trust-BNl21fa7.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-D9nk6Ehe.js → UkeySign-CFrCI7uK.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-BKk0rfoy.js → VideoEditing-BVfY6JLg.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-IVWIU_Lq.js → Wallet-Cj9CAK0J.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-CFTCpfsG.js → WebAuthn-DcqZlzA3.js} +4 -4
- package/src/assets/web-panel/assets/{WorkflowEditor-Dnf4Obif.js → WorkflowEditor-Dfr_dMld.js} +1 -1
- package/src/assets/web-panel/assets/{chat-D2snERdj.js → chat-Yv6UF0AD.js} +1 -1
- package/src/assets/web-panel/assets/{colors-DKEjK1N1.js → colors-CDW_-1fs.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-BEDLwQdt.js → compact-item-BYOQvd-6.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-DA9iW1a0.js → createContext-BCGO0BiP.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-H-kXSuf-.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-5l2xEcY9.js → hasIn-DY-70cfQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-B7_W_rYd.js → index-366wfQBU.js} +1 -1
- package/src/assets/web-panel/assets/index-B0o4MeNK.js +1 -0
- package/src/assets/web-panel/assets/{index-CxEtQYdi.js → index-B9ZogJJM.js} +1 -1
- package/src/assets/web-panel/assets/{index-B00GeekA.js → index-B9m5QAMg.js} +1 -1
- package/src/assets/web-panel/assets/{index-C7sKbM5s.js → index-BBs2mv5M.js} +1 -1
- package/src/assets/web-panel/assets/{index-CX1x4AFn.js → index-BFv1hzF6.js} +1 -1
- package/src/assets/web-panel/assets/index-BVafOL_I.js +1 -0
- package/src/assets/web-panel/assets/{index-DU2TXJu-.js → index-BXlEx4UH.js} +1 -1
- package/src/assets/web-panel/assets/{index-e-e40id6.js → index-BayRTE5w.js} +1 -1
- package/src/assets/web-panel/assets/{index-DXet1xol.js → index-Bb9nyts1.js} +1 -1
- package/src/assets/web-panel/assets/{index-D7z4zB_a.js → index-Bf_Va0S-.js} +1 -1
- package/src/assets/web-panel/assets/{index-fccZmC_h.js → index-Br3wQLVY.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bqc8tdIF.js → index-BvK4fjkk.js} +1 -1
- package/src/assets/web-panel/assets/{index-BO9dQjpt.js → index-C40UdtlS.js} +1 -1
- package/src/assets/web-panel/assets/{index-Csfb-7hw.js → index-C4UJA2ju.js} +1 -1
- package/src/assets/web-panel/assets/{index-Td8ZwyoC.js → index-CB_Iw73G.js} +1 -1
- package/src/assets/web-panel/assets/{index-BZ5lY2zx.js → index-CCwWp3mT.js} +1 -1
- package/src/assets/web-panel/assets/{index-DpqtbXdE.js → index-CFa2fPCk.js} +1 -1
- package/src/assets/web-panel/assets/{index-NJieh3T1.js → index-CIyHxV4u.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dbkghqn_.js → index-CUP-A2_h.js} +1 -1
- package/src/assets/web-panel/assets/{index-DqwPFbOb.js → index-CUo27q9J.js} +3 -3
- package/src/assets/web-panel/assets/{index-B4QYBliR.js → index-CaT8trvf.js} +1 -1
- package/src/assets/web-panel/assets/{index-BgfImyZI.js → index-CnZNbcux.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dbd7eEex.js → index-Cy2NE6AO.js} +1 -1
- package/src/assets/web-panel/assets/{index-CbTPvp2_.js → index-CzeEEazr.js} +1 -1
- package/src/assets/web-panel/assets/{index-5pW4t1iD.js → index-D--TEyDj.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dg2a9owQ.js → index-DCtsjhhT.js} +1 -1
- package/src/assets/web-panel/assets/{index-B_eCoZgW.js → index-DLOf7BSz.js} +1 -1
- package/src/assets/web-panel/assets/{index-7P1b8HZo.js → index-DM5c4pc-.js} +1 -1
- package/src/assets/web-panel/assets/{index-CRPrHE7h.js → index-DRFC2Qt0.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bq5P3piS.js → index-DT_qVaaV.js} +1 -1
- package/src/assets/web-panel/assets/{index-CjWltbi_.js → index-DUDoRk9r.js} +1 -1
- package/src/assets/web-panel/assets/{index-CkMKuqUs.js → index-Dg-AQYDf.js} +1 -1
- package/src/assets/web-panel/assets/{index-DLoalqRX.js → index-DuIPq5MX.js} +1 -1
- package/src/assets/web-panel/assets/{index-CGlotREA.js → index-NYVBUAVN.js} +1 -1
- package/src/assets/web-panel/assets/{index-yYEQXYaU.js → index-NaCESahy.js} +1 -1
- package/src/assets/web-panel/assets/{index-CmruhzFi.js → index-RjIMPG0u.js} +1 -1
- package/src/assets/web-panel/assets/{index-fgYk0QXO.js → index-Y9akzgFO.js} +1 -1
- package/src/assets/web-panel/assets/{index-DvV03Ayk.js → index-hZ0Eyrrw.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-CPrcB1TC.js → initDefaultProps-CG99CcR4.js} +1 -1
- package/src/assets/web-panel/assets/{motion-BQ7mWRh_.js → motion-Z7MH0_0G.js} +1 -1
- package/src/assets/web-panel/assets/{move-CzOEq99p.js → move-BX67lOdq.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-BlQI5jrw.js → mtc-parser-CmAbG1fE.js} +1 -1
- package/src/assets/web-panel/assets/{omit-DlW4gxmv.js → omit-DiU5tI1_.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-BBYms5nP.js → pickAttrs-BGfvLrYL.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-az2MPJ_7.js → placementArrow-CggLEgaJ.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-D1-ibEol.js → responsiveObserve-t3nlghPZ.js} +1 -1
- package/src/assets/web-panel/assets/{slide-DHGqa4GA.js → slide-BkV4dL9s.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-CYGDo6lD.js → statusUtils-qec1PUoC.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-Cl2EM9K6.js → styleChecker-ChjX6T8D.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-DdYhzuv1.js → useFlexGapSupport-B1jLoZcM.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-DWumPuBW.js → useFs-C3X53s4E.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-DxAO-Aqi.js → usePersonalDataHub-DOvbbnkZ.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-CplsQf_N.js → vnode-Ie0TEVFT.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-Cw5HXNSG.js → zoom-CRUMVS8l.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-help-index.json +3 -3
- package/src/commands/agent.js +18 -1
- package/src/commands/evolution-benchmark.js +72 -0
- package/src/commands/evolution.js +2 -0
- package/src/commands/governed-skill-marketplace.js +142 -0
- package/src/commands/marketplace.js +4 -1
- package/src/commands/serve.js +41 -0
- package/src/commands/skill.js +3 -0
- package/src/data/changelog.json +39 -0
- package/src/gateways/ws/ws-agent-handler.js +59 -2
- package/src/gateways/ws/ws-server.js +2 -0
- package/src/harness/golden-transcript.js +1 -0
- package/src/harness/prompt-compressor.js +51 -5
- package/src/harness/provider-backed-compaction.js +28 -1
- package/src/harness/remote-session-registry.js +15 -3
- package/src/index.js +30 -4
- package/src/lazy-dispatch.js +15 -1
- package/src/lib/advisor-runtime.js +55 -2
- package/src/lib/app-server/cli-agent-kernel-adapter.js +4 -0
- package/src/lib/app-server/graph-runtime.js +32 -0
- package/src/lib/app-server/server.js +45 -1
- package/src/lib/app-server/websocket-transport.js +23 -0
- package/src/lib/autonomous-agent.js +63 -13
- package/src/lib/cowork/ab-comparator-cli.js +4 -3
- package/src/lib/cowork/debate-review-cli.js +4 -3
- package/src/lib/cowork/decision-kb-cli.js +5 -0
- package/src/lib/cowork-adapter.js +38 -16
- package/src/lib/evolution/agent-evolution-ingress.js +95 -15
- package/src/lib/evolution/agent-evolution-runtime-composition.js +82 -0
- package/src/lib/evolution/agent-evolution-session-lifecycle.js +46 -0
- package/src/lib/evolution/agent-model-projection.js +217 -0
- package/src/lib/evolution/bounded-descriptor-read.js +29 -0
- package/src/lib/evolution/controlled-skill-pilot-ledger-adapter.js +551 -0
- package/src/lib/evolution/controlled-skill-production-pilot.js +308 -18
- package/src/lib/evolution/evidence-backed-wiki-maintainer.js +10 -1
- package/src/lib/evolution/evidence-json-text.js +236 -0
- package/src/lib/evolution/evolution-artifact-ports.js +202 -21
- package/src/lib/evolution/evolution-deployment-loader.js +369 -0
- package/src/lib/evolution/evolution-eval-child-evidence-ledger-adapter.js +373 -0
- package/src/lib/evolution/evolution-eval-gate.js +14 -1
- package/src/lib/evolution/evolution-eval-process-supervisor-worker.mjs +14 -0
- package/src/lib/evolution/evolution-eval-process-supervisor.js +607 -0
- package/src/lib/evolution/evolution-evidence-artifact-adapter.js +14 -1
- package/src/lib/evolution/evolution-evidence-projector.js +240 -37
- package/src/lib/evolution/evolution-file-witness.js +153 -30
- package/src/lib/evolution/evolution-ledger-ports.js +1027 -66
- package/src/lib/evolution/evolution-ledger.js +66 -2
- package/src/lib/evolution/evolution-raw-crypto-shred.js +29 -15
- package/src/lib/evolution/evolution-raw-deletion-ledger-adapter.js +865 -0
- package/src/lib/evolution/evolution-release-train-domain-stages.js +769 -0
- package/src/lib/evolution/evolution-release-train-ledger-adapter.js +335 -0
- package/src/lib/evolution/evolution-release-train-stage-output-ledger-adapter.js +333 -0
- package/src/lib/evolution/evolution-release-train.js +586 -0
- package/src/lib/evolution/evolution-workbench-batch-executor.js +101 -144
- package/src/lib/evolution/evolution-workbench-control-ports.js +203 -0
- package/src/lib/evolution/evolution-workbench-file-resources.js +403 -0
- package/src/lib/evolution/evolution-workbench-projection.js +152 -25
- package/src/lib/evolution/evolution-workbench-registry-source.js +482 -0
- package/src/lib/evolution/evolution-workbench-review-ledger-adapter.js +823 -0
- package/src/lib/evolution/evolution-workbench-review-protocol.js +157 -0
- package/src/lib/evolution/evolution-workbench-rollback-authorization.js +57 -0
- package/src/lib/evolution/evolution-workbench-rollback-ledger-adapter.js +1016 -0
- package/src/lib/evolution/evolution-workbench-runtime.js +133 -0
- package/src/lib/evolution/evolution-workbench-version-control.js +70 -36
- package/src/lib/evolution/evolvable-artifact-ledger-adapter.js +736 -0
- package/src/lib/evolution/governed-knowledge-artifact-lifecycle.js +364 -0
- package/src/lib/evolution/governed-knowledge-candidate-rejection.js +343 -0
- package/src/lib/evolution/governed-knowledge-dependency-authority.js +227 -44
- package/src/lib/evolution/governed-knowledge-dependency-ledger-executor.js +95 -83
- package/src/lib/evolution/governed-knowledge-merge-ledger-executor.js +29 -2
- package/src/lib/evolution/governed-knowledge-merge-publisher-authority.js +31 -3
- package/src/lib/evolution/governed-knowledge-record.js +148 -0
- package/src/lib/evolution/governed-knowledge-revocation-record.js +135 -0
- package/src/lib/evolution/governed-knowledge-skill-rollback.js +475 -0
- package/src/lib/evolution/governed-knowledge-sync-ledger-adapter.js +92 -6
- package/src/lib/evolution/governed-knowledge-sync-merge-publisher.js +57 -4
- package/src/lib/evolution/governed-knowledge-sync.js +332 -99
- package/src/lib/evolution/governed-knowledge-wiki-tombstone.js +462 -0
- package/src/lib/evolution/governed-skill-marketplace-badge.js +208 -0
- package/src/lib/evolution/governed-skill-marketplace-candidate.js +330 -0
- package/src/lib/evolution/governed-skill-marketplace-cli-host.js +308 -0
- package/src/lib/evolution/governed-skill-marketplace-ledger-adapter.js +420 -0
- package/src/lib/evolution/governed-skill-marketplace.js +288 -5
- package/src/lib/evolution/governed-wiki-pruning-journal.js +302 -0
- package/src/lib/evolution/governed-wiki-pruning-ledger-adapter.js +459 -0
- package/src/lib/evolution/governed-wiki-pruning-maintenance.js +576 -0
- package/src/lib/evolution/governed-wiki-pruning-plan-authority.js +169 -0
- package/src/lib/evolution/governed-wiki-pruning-raw-shred.js +207 -0
- package/src/lib/evolution/governed-wiki-pruning-retrieval.js +587 -0
- package/src/lib/evolution/governed-wiki-pruning-runtime.js +153 -0
- package/src/lib/evolution/governed-wiki-pruning-skill-rollback.js +360 -0
- package/src/lib/evolution/governed-wiki-pruning.js +322 -143
- package/src/lib/evolution/independent-skill-revocation-source.js +231 -0
- package/src/lib/evolution/knowledge-wiki-source-admission.js +124 -0
- package/src/lib/evolution/knowledge-wiki-source-provenance.js +359 -0
- package/src/lib/evolution/progressive-canary-external-watchdog.js +578 -0
- package/src/lib/evolution/progressive-canary-traffic-worker.js +628 -0
- package/src/lib/evolution/progressive-canary-watchdog-file-store.js +285 -0
- package/src/lib/evolution/progressive-canary-watchdog-node-pki.js +265 -0
- package/src/lib/evolution/skill-candidate-registry.js +22 -0
- package/src/lib/evolution/skill-promotion-controller.js +25 -0
- package/src/lib/evolution/skill-promotion-review-ledger-adapter.js +100 -0
- package/src/lib/evolution/skill-registry-transition-ledger-adapter.js +131 -2
- package/src/lib/evolution/skill-release-registry.js +25 -4
- package/src/lib/evolution/skill-retrieval-revocation-authority.js +361 -0
- package/src/lib/evolution/skill-retrieval-revocation-ledger-adapter.js +346 -0
- package/src/lib/evolution/skill-revocation-propagation.js +467 -0
- package/src/lib/evolution/skill-target-matrix-eval.js +162 -11
- package/src/lib/evolution/skill-wiki-reconciliation.js +985 -0
- package/src/lib/evolution/skill-writer-inventory-manifest.js +15 -12
- package/src/lib/evolution/statistical-progressive-canary.js +845 -0
- package/src/lib/evolution/structured-memory-agent-control-plane.js +120 -0
- package/src/lib/evolution/structured-memory-authority-ledger-adapter.js +5 -1
- package/src/lib/evolution/structured-memory-promotion-receipt-writer.js +126 -0
- package/src/lib/evolution/wiki-informed-skill-proposer.js +127 -21
- package/src/lib/evolution/wiki-maintainer-ledger-adapter.js +760 -100
- package/src/lib/evolution/wiki-revision-protocol.js +120 -0
- package/src/lib/evolution/wiki-skill-proposal-ledger-adapter.js +307 -0
- package/src/lib/evolution/wiki-target-tombstone-revision.js +101 -0
- package/src/lib/evolution/wikiskill-benchmark-cli-host.js +178 -0
- package/src/lib/evolution/wikiskill-benchmark-execution-host.js +702 -0
- package/src/lib/evolution/wikiskill-benchmark-ledger-adapter.js +613 -0
- package/src/lib/evolution/wikiskill-benchmark.js +574 -0
- package/src/lib/goal-assess.js +17 -10
- package/src/lib/interactive-planner.js +9 -1
- package/src/lib/iteration-budget.js +16 -2
- package/src/lib/micro-compact.js +4 -1
- package/src/lib/model-failure-policy.js +21 -0
- package/src/lib/process-execution-broker/index.js +1 -0
- package/src/lib/process-execution-broker/windows-sandbox-helper.dll +0 -0
- package/src/lib/process-execution-broker/windows-sandbox-helper.exe +0 -0
- package/src/lib/process-execution-broker/windows-sandbox.cs +33 -15
- package/src/lib/read-file-page.js +191 -0
- package/src/lib/runnable-provider.js +2 -1
- package/src/lib/session-host-lease.js +11 -16
- package/src/lib/skill-retrieval-router.js +22 -1
- package/src/repl/agent-repl.js +127 -33
- package/src/runtime/agent-core.js +224 -80
- package/src/runtime/agent-runtime.js +43 -0
- package/src/runtime/coding-agent-contract-shared.cjs +7 -1
- package/src/runtime/fallback-model.js +143 -62
- package/src/runtime/headless-runner.js +54 -10
- package/src/runtime/headless-stream.js +53 -6
- package/src/runtime/runtime-factory.js +41 -2
- package/src/assets/web-panel/assets/Notes-CgU9DDo9.js +0 -7
- package/src/assets/web-panel/assets/OrderTableRenderer-CwHc15Zs.js +0 -1
- package/src/assets/web-panel/assets/Projects-FF_thRi6.js +0 -1
- package/src/assets/web-panel/assets/SpeechSettings-l7ox6KuX.js +0 -1
- package/src/assets/web-panel/assets/devWarning-DyhgpXPf.js +0 -1
- package/src/assets/web-panel/assets/index-Ck1jhFE0.js +0 -1
- package/src/assets/web-panel/assets/index-c8jJEHVs.js +0 -1
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { types as utilTypes } from "node:util";
|
|
3
|
+
import { verifyGovernedSkillMarketplaceCandidateBinding } from "./governed-skill-marketplace-candidate.js";
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
SKILL_REVOCATION_DEPENDENCY_REQUEST_SCHEMA,
|
|
7
|
+
SKILL_REVOCATION_DEPENDENCY_RESULT_SCHEMA,
|
|
8
|
+
digestSkillRevocationDependencyRequest,
|
|
9
|
+
} from "./skill-revocation-propagation.js";
|
|
3
10
|
|
|
4
11
|
export const GOVERNED_SKILL_MARKETPLACE_MANIFEST_SCHEMA =
|
|
5
12
|
"chainlesschain.governed-skill-marketplace-manifest/v1";
|
|
@@ -15,6 +22,61 @@ const STAGES = new Map([
|
|
|
15
22
|
["shadow", "canary"],
|
|
16
23
|
["canary", "active"],
|
|
17
24
|
]);
|
|
25
|
+
const MARKETPLACE_STATE_KEYS = new Set([
|
|
26
|
+
"candidateBinding",
|
|
27
|
+
"schema",
|
|
28
|
+
"tenantId",
|
|
29
|
+
"skillName",
|
|
30
|
+
"version",
|
|
31
|
+
"manifestDigest",
|
|
32
|
+
"packageDigest",
|
|
33
|
+
"adaptedOutputDigest",
|
|
34
|
+
"target",
|
|
35
|
+
"stage",
|
|
36
|
+
"previousStateDigest",
|
|
37
|
+
"revoked",
|
|
38
|
+
"transitionRequestDigest",
|
|
39
|
+
"transitionReceiptDigest",
|
|
40
|
+
"revocationReceiptDigest",
|
|
41
|
+
"revocationPropagationRequestDigest",
|
|
42
|
+
"revocationBaselineStateDigest",
|
|
43
|
+
"stateDigest",
|
|
44
|
+
]);
|
|
45
|
+
const MARKETPLACE_STATE_REQUIRED_KEYS = new Set([
|
|
46
|
+
"schema",
|
|
47
|
+
"tenantId",
|
|
48
|
+
"skillName",
|
|
49
|
+
"version",
|
|
50
|
+
"manifestDigest",
|
|
51
|
+
"packageDigest",
|
|
52
|
+
"adaptedOutputDigest",
|
|
53
|
+
"target",
|
|
54
|
+
"stage",
|
|
55
|
+
"previousStateDigest",
|
|
56
|
+
"revoked",
|
|
57
|
+
"stateDigest",
|
|
58
|
+
]);
|
|
59
|
+
const MARKETPLACE_TARGET_KEYS = new Set(["model", "os", "tool", "runtime"]);
|
|
60
|
+
const REVOCATION_DEPENDENCY_REQUEST_KEYS = new Set([
|
|
61
|
+
"schema",
|
|
62
|
+
"tenantId",
|
|
63
|
+
"streamId",
|
|
64
|
+
"operationId",
|
|
65
|
+
"transitionDigest",
|
|
66
|
+
"candidateId",
|
|
67
|
+
"skillName",
|
|
68
|
+
"occurredAt",
|
|
69
|
+
"sourceReceiptDigest",
|
|
70
|
+
"resolutionDigest",
|
|
71
|
+
"dependency",
|
|
72
|
+
"requestDigest",
|
|
73
|
+
]);
|
|
74
|
+
const REVOCATION_DEPENDENCY_KEYS = new Set([
|
|
75
|
+
"kind",
|
|
76
|
+
"ref",
|
|
77
|
+
"digest",
|
|
78
|
+
"disposition",
|
|
79
|
+
]);
|
|
18
80
|
|
|
19
81
|
function canonical(value) {
|
|
20
82
|
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
@@ -55,6 +117,24 @@ function record(value, label) {
|
|
|
55
117
|
return value;
|
|
56
118
|
}
|
|
57
119
|
|
|
120
|
+
function exact(value, keys, label) {
|
|
121
|
+
record(value, label);
|
|
122
|
+
const own = Reflect.ownKeys(value);
|
|
123
|
+
if (
|
|
124
|
+
own.length !== keys.size ||
|
|
125
|
+
own.some((key) => typeof key !== "string" || !keys.has(key))
|
|
126
|
+
) {
|
|
127
|
+
throw new TypeError(`${label} has an invalid shape`);
|
|
128
|
+
}
|
|
129
|
+
for (const key of own) {
|
|
130
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
131
|
+
if (!descriptor || !("value" in descriptor) || !descriptor.enumerable) {
|
|
132
|
+
throw new TypeError(`${label}.${String(key)} is not a data field`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return value;
|
|
136
|
+
}
|
|
137
|
+
|
|
58
138
|
function id(value, label) {
|
|
59
139
|
if (typeof value !== "string" || !ID.test(value))
|
|
60
140
|
throw new TypeError(`${label} is invalid`);
|
|
@@ -160,6 +240,76 @@ export function buildGovernedSkillMarketplaceManifest(input, signature) {
|
|
|
160
240
|
return freeze({ ...core, manifestDigest, signature });
|
|
161
241
|
}
|
|
162
242
|
|
|
243
|
+
export function digestGovernedSkillMarketplaceState(core) {
|
|
244
|
+
return hash(GOVERNED_SKILL_MARKETPLACE_STATE_SCHEMA, core);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
export function verifyGovernedSkillMarketplaceState(
|
|
248
|
+
input,
|
|
249
|
+
tenantId,
|
|
250
|
+
skillName,
|
|
251
|
+
) {
|
|
252
|
+
record(input, "marketplace state");
|
|
253
|
+
for (const key of Reflect.ownKeys(input)) {
|
|
254
|
+
const descriptor = Object.getOwnPropertyDescriptor(input, key);
|
|
255
|
+
if (!descriptor || !("value" in descriptor) || !descriptor.enumerable) {
|
|
256
|
+
throw new Error("marketplace state contains an unsafe field");
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
const ownKeys = Reflect.ownKeys(input);
|
|
260
|
+
if (
|
|
261
|
+
ownKeys.some(
|
|
262
|
+
(key) => typeof key !== "string" || !MARKETPLACE_STATE_KEYS.has(key),
|
|
263
|
+
) ||
|
|
264
|
+
[...MARKETPLACE_STATE_REQUIRED_KEYS].some(
|
|
265
|
+
(key) => !Object.hasOwn(input, key),
|
|
266
|
+
)
|
|
267
|
+
) {
|
|
268
|
+
throw new Error("marketplace state has an invalid shape");
|
|
269
|
+
}
|
|
270
|
+
exact(input.target, MARKETPLACE_TARGET_KEYS, "marketplace state target");
|
|
271
|
+
if (Object.hasOwn(input, "candidateBinding"))
|
|
272
|
+
verifyGovernedSkillMarketplaceCandidateBinding(
|
|
273
|
+
input.candidateBinding,
|
|
274
|
+
input,
|
|
275
|
+
);
|
|
276
|
+
const state = clone(input);
|
|
277
|
+
const core = clone(state);
|
|
278
|
+
delete core.stateDigest;
|
|
279
|
+
if (
|
|
280
|
+
state.schema !== GOVERNED_SKILL_MARKETPLACE_STATE_SCHEMA ||
|
|
281
|
+
state.tenantId !== tenantId ||
|
|
282
|
+
state.skillName !== skillName ||
|
|
283
|
+
!ID.test(state.version ?? "") ||
|
|
284
|
+
!["candidate", "shadow", "canary", "active", "rolled-back"].includes(
|
|
285
|
+
state.stage,
|
|
286
|
+
) ||
|
|
287
|
+
typeof state.revoked !== "boolean" ||
|
|
288
|
+
(state.previousStateDigest !== null &&
|
|
289
|
+
!DIGEST.test(state.previousStateDigest ?? "")) ||
|
|
290
|
+
!["model", "os", "tool", "runtime"].every((field) =>
|
|
291
|
+
ID.test(state.target[field] ?? ""),
|
|
292
|
+
) ||
|
|
293
|
+
[
|
|
294
|
+
"manifestDigest",
|
|
295
|
+
"packageDigest",
|
|
296
|
+
"adaptedOutputDigest",
|
|
297
|
+
"stateDigest",
|
|
298
|
+
...[
|
|
299
|
+
"transitionRequestDigest",
|
|
300
|
+
"transitionReceiptDigest",
|
|
301
|
+
"revocationReceiptDigest",
|
|
302
|
+
"revocationPropagationRequestDigest",
|
|
303
|
+
"revocationBaselineStateDigest",
|
|
304
|
+
].filter((field) => Object.hasOwn(state, field)),
|
|
305
|
+
].some((field) => !DIGEST.test(state[field] ?? "")) ||
|
|
306
|
+
state.stateDigest !== digestGovernedSkillMarketplaceState(core)
|
|
307
|
+
) {
|
|
308
|
+
throw new Error("marketplace state is unauthenticated or corrupt");
|
|
309
|
+
}
|
|
310
|
+
return freeze(state);
|
|
311
|
+
}
|
|
312
|
+
|
|
163
313
|
export class GovernedSkillMarketplace {
|
|
164
314
|
constructor({ tenantId, ports } = {}) {
|
|
165
315
|
this.tenantId = id(tenantId, "tenantId");
|
|
@@ -172,13 +322,18 @@ export class GovernedSkillMarketplace {
|
|
|
172
322
|
this._verifyRevocation = capture(ports, "verifyRevocation");
|
|
173
323
|
}
|
|
174
324
|
|
|
175
|
-
async
|
|
325
|
+
async verifyListing(input, target) {
|
|
176
326
|
const manifest = normalizeManifest(input, this.tenantId);
|
|
177
327
|
if ((await this._verifySignature({ manifest })) !== true)
|
|
178
328
|
throw new Error("marketplace manifest signature is invalid");
|
|
179
329
|
const cell = targetCell(manifest, target);
|
|
180
330
|
if (cell.safetyPassed !== true)
|
|
181
331
|
throw new Error("marketplace target safety gate failed");
|
|
332
|
+
return freeze({ manifest, target: clone(target), cell });
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
async inspect(input, target) {
|
|
336
|
+
const { manifest, cell } = await this.verifyListing(input, target);
|
|
182
337
|
const adapted = await this._adapt({
|
|
183
338
|
manifest,
|
|
184
339
|
target: clone(target),
|
|
@@ -202,7 +357,12 @@ export class GovernedSkillMarketplace {
|
|
|
202
357
|
});
|
|
203
358
|
}
|
|
204
359
|
|
|
205
|
-
async stage({
|
|
360
|
+
async stage({
|
|
361
|
+
manifest: input,
|
|
362
|
+
target,
|
|
363
|
+
expectedStateDigest = null,
|
|
364
|
+
candidateBinding = null,
|
|
365
|
+
} = {}) {
|
|
206
366
|
const inspected = await this.inspect(input, target);
|
|
207
367
|
const current = await this._load({
|
|
208
368
|
skillName: inspected.manifest.skillName,
|
|
@@ -222,6 +382,24 @@ export class GovernedSkillMarketplace {
|
|
|
222
382
|
previousStateDigest: expectedStateDigest,
|
|
223
383
|
revoked: false,
|
|
224
384
|
};
|
|
385
|
+
if (candidateBinding !== null) {
|
|
386
|
+
const binding = verifyGovernedSkillMarketplaceCandidateBinding(
|
|
387
|
+
candidateBinding,
|
|
388
|
+
state,
|
|
389
|
+
);
|
|
390
|
+
if (
|
|
391
|
+
binding.dependencyLockDigest !==
|
|
392
|
+
inspected.manifest.dependencyLockDigest ||
|
|
393
|
+
binding.targetMatrixRoot !== inspected.manifest.targetMatrixDigest ||
|
|
394
|
+
binding.sbomDigest !== inspected.manifest.sbomDigest ||
|
|
395
|
+
binding.permissionManifestDigest !==
|
|
396
|
+
inspected.manifest.permissionManifestDigest
|
|
397
|
+
)
|
|
398
|
+
throw new Error(
|
|
399
|
+
"marketplace candidate binding differs from the signed manifest",
|
|
400
|
+
);
|
|
401
|
+
state.candidateBinding = binding;
|
|
402
|
+
}
|
|
225
403
|
return this._persist(state, expectedStateDigest, "marketplace.staged");
|
|
226
404
|
}
|
|
227
405
|
|
|
@@ -350,7 +528,15 @@ export class GovernedSkillMarketplace {
|
|
|
350
528
|
);
|
|
351
529
|
}
|
|
352
530
|
|
|
353
|
-
async revoke({
|
|
531
|
+
async revoke({
|
|
532
|
+
skillName,
|
|
533
|
+
expectedStateDigest,
|
|
534
|
+
revocationReceipt,
|
|
535
|
+
propagationRequestDigest = null,
|
|
536
|
+
} = {}) {
|
|
537
|
+
if (propagationRequestDigest !== null) {
|
|
538
|
+
digest(propagationRequestDigest, "propagationRequestDigest");
|
|
539
|
+
}
|
|
354
540
|
const current = await this._exact(skillName, expectedStateDigest);
|
|
355
541
|
const verified = await this._verifyRevocation({
|
|
356
542
|
state: current,
|
|
@@ -393,6 +579,12 @@ export class GovernedSkillMarketplace {
|
|
|
393
579
|
stage: "rolled-back",
|
|
394
580
|
revoked: true,
|
|
395
581
|
revocationReceiptDigest: verified.receiptDigest,
|
|
582
|
+
...(propagationRequestDigest === null
|
|
583
|
+
? {}
|
|
584
|
+
: {
|
|
585
|
+
revocationPropagationRequestDigest: propagationRequestDigest,
|
|
586
|
+
revocationBaselineStateDigest: current.stateDigest,
|
|
587
|
+
}),
|
|
396
588
|
transitionRequestDigest: requestDigest,
|
|
397
589
|
transitionReceiptDigest: transition.receiptDigest,
|
|
398
590
|
},
|
|
@@ -401,10 +593,101 @@ export class GovernedSkillMarketplace {
|
|
|
401
593
|
);
|
|
402
594
|
}
|
|
403
595
|
|
|
596
|
+
async revokeMarketplaceBadge(request) {
|
|
597
|
+
exact(
|
|
598
|
+
request,
|
|
599
|
+
REVOCATION_DEPENDENCY_REQUEST_KEYS,
|
|
600
|
+
"marketplace revocation dependency request",
|
|
601
|
+
);
|
|
602
|
+
exact(
|
|
603
|
+
request.dependency,
|
|
604
|
+
REVOCATION_DEPENDENCY_KEYS,
|
|
605
|
+
"marketplace revocation dependency",
|
|
606
|
+
);
|
|
607
|
+
const expectedRef = `marketplace-state:${this.tenantId}:${request.skillName}`;
|
|
608
|
+
if (
|
|
609
|
+
request.schema !== SKILL_REVOCATION_DEPENDENCY_REQUEST_SCHEMA ||
|
|
610
|
+
request.tenantId !== this.tenantId ||
|
|
611
|
+
request.dependency.kind !== "marketplace-badge" ||
|
|
612
|
+
request.dependency.disposition !== "revoke" ||
|
|
613
|
+
request.dependency.ref !== expectedRef ||
|
|
614
|
+
request.requestDigest !==
|
|
615
|
+
digestSkillRevocationDependencyRequest(request) ||
|
|
616
|
+
!DIGEST.test(request.dependency.digest ?? "") ||
|
|
617
|
+
!DIGEST.test(request.transitionDigest ?? "") ||
|
|
618
|
+
!DIGEST.test(request.candidateId ?? "") ||
|
|
619
|
+
!DIGEST.test(request.sourceReceiptDigest ?? "") ||
|
|
620
|
+
!DIGEST.test(request.resolutionDigest ?? "")
|
|
621
|
+
) {
|
|
622
|
+
throw new Error("marketplace revocation dependency is not exactly bound");
|
|
623
|
+
}
|
|
624
|
+
id(request.skillName, "skillName");
|
|
625
|
+
id(request.streamId, "streamId");
|
|
626
|
+
id(request.operationId, "operationId");
|
|
627
|
+
if (new Date(request.occurredAt).toISOString() !== request.occurredAt) {
|
|
628
|
+
throw new Error("marketplace revocation timestamp is invalid");
|
|
629
|
+
}
|
|
630
|
+
let current = await this._verifiedState(request.skillName);
|
|
631
|
+
const expectedStateDigest = request.dependency.digest;
|
|
632
|
+
if (!(
|
|
633
|
+
current.revoked === true &&
|
|
634
|
+
current.stage === "rolled-back" &&
|
|
635
|
+
current.revocationBaselineStateDigest === expectedStateDigest &&
|
|
636
|
+
current.revocationPropagationRequestDigest === request.requestDigest
|
|
637
|
+
)) {
|
|
638
|
+
if (current.stateDigest !== expectedStateDigest) {
|
|
639
|
+
throw new Error("marketplace revocation dependency baseline changed");
|
|
640
|
+
}
|
|
641
|
+
try {
|
|
642
|
+
current = await this.revoke({
|
|
643
|
+
skillName: request.skillName,
|
|
644
|
+
expectedStateDigest,
|
|
645
|
+
revocationReceipt: request,
|
|
646
|
+
propagationRequestDigest: request.requestDigest,
|
|
647
|
+
});
|
|
648
|
+
} catch (cause) {
|
|
649
|
+
const recovered = await this._verifiedState(request.skillName);
|
|
650
|
+
if (
|
|
651
|
+
recovered.revoked !== true ||
|
|
652
|
+
recovered.stage !== "rolled-back" ||
|
|
653
|
+
recovered.revocationBaselineStateDigest !== expectedStateDigest ||
|
|
654
|
+
recovered.revocationPropagationRequestDigest !== request.requestDigest
|
|
655
|
+
) {
|
|
656
|
+
throw cause;
|
|
657
|
+
}
|
|
658
|
+
current = recovered;
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
return freeze({
|
|
662
|
+
schema: SKILL_REVOCATION_DEPENDENCY_RESULT_SCHEMA,
|
|
663
|
+
authenticated: true,
|
|
664
|
+
durable: true,
|
|
665
|
+
applied: true,
|
|
666
|
+
idempotent: true,
|
|
667
|
+
tenantId: this.tenantId,
|
|
668
|
+
operationId: request.operationId,
|
|
669
|
+
requestDigest: request.requestDigest,
|
|
670
|
+
dependencyKind: request.dependency.kind,
|
|
671
|
+
dependencyRef: request.dependency.ref,
|
|
672
|
+
dependencyDigest: request.dependency.digest,
|
|
673
|
+
disposition: request.dependency.disposition,
|
|
674
|
+
receiptDigest: current.stateDigest,
|
|
675
|
+
});
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
async _verifiedState(skillName) {
|
|
679
|
+
const current = await this._load({ skillName });
|
|
680
|
+
return verifyGovernedSkillMarketplaceState(
|
|
681
|
+
current,
|
|
682
|
+
this.tenantId,
|
|
683
|
+
skillName,
|
|
684
|
+
);
|
|
685
|
+
}
|
|
686
|
+
|
|
404
687
|
async _exact(skillName, expectedStateDigest) {
|
|
405
688
|
id(skillName, "skillName");
|
|
406
689
|
digest(expectedStateDigest, "expectedStateDigest");
|
|
407
|
-
const current = await this.
|
|
690
|
+
const current = await this._verifiedState(skillName);
|
|
408
691
|
if (!current || current.stateDigest !== expectedStateDigest)
|
|
409
692
|
throw new Error("marketplace state changed or is missing");
|
|
410
693
|
return current;
|
|
@@ -415,7 +698,7 @@ export class GovernedSkillMarketplace {
|
|
|
415
698
|
delete core.stateDigest;
|
|
416
699
|
const state = freeze({
|
|
417
700
|
...core,
|
|
418
|
-
stateDigest:
|
|
701
|
+
stateDigest: digestGovernedSkillMarketplaceState(core),
|
|
419
702
|
});
|
|
420
703
|
const result = await this._commit({ state, expectedStateDigest, event });
|
|
421
704
|
if (
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { types } from "node:util";
|
|
3
|
+
export const GOVERNED_WIKI_PRUNING_PLAN_SCHEMA =
|
|
4
|
+
"chainlesschain.governed-wiki-pruning-plan/v2";
|
|
5
|
+
export const GOVERNED_WIKI_PRUNING_POLICY_SCHEMA =
|
|
6
|
+
"chainlesschain.governed-wiki-pruning-policy/v1";
|
|
7
|
+
|
|
8
|
+
export const WIKI_PRUNING_JOURNAL_SCHEMA =
|
|
9
|
+
"chainlesschain.governed-wiki-pruning-journal/v1";
|
|
10
|
+
export const WIKI_PRUNING_JOURNAL_MAX_BYTES = 1024 * 1024;
|
|
11
|
+
const DIGEST = /^sha256:[a-f0-9]{64}$/u;
|
|
12
|
+
const PLAN_KEYS = [
|
|
13
|
+
"schema",
|
|
14
|
+
"tenantId",
|
|
15
|
+
"wikiStateDigest",
|
|
16
|
+
"policyDigest",
|
|
17
|
+
"effectiveAt",
|
|
18
|
+
"patternActions",
|
|
19
|
+
"retrievalRemovals",
|
|
20
|
+
"dependencyDispositions",
|
|
21
|
+
"deletions",
|
|
22
|
+
"auditPolicy",
|
|
23
|
+
"planDigest",
|
|
24
|
+
];
|
|
25
|
+
const JOURNAL_KEYS = [
|
|
26
|
+
"schema",
|
|
27
|
+
"tenantId",
|
|
28
|
+
"revision",
|
|
29
|
+
"previousJournalDigest",
|
|
30
|
+
"plan",
|
|
31
|
+
"phase",
|
|
32
|
+
"operationReceipts",
|
|
33
|
+
"journalDigest",
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
export function pruningCanonical(value) {
|
|
37
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
38
|
+
if (Array.isArray(value)) return `[${value.map(pruningCanonical).join(",")}]`;
|
|
39
|
+
return `{${Object.keys(value)
|
|
40
|
+
.sort()
|
|
41
|
+
.map((key) => `${JSON.stringify(key)}:${pruningCanonical(value[key])}`)
|
|
42
|
+
.join(",")}}`;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function pruningDigest(domain, value) {
|
|
46
|
+
return `sha256:${createHash("sha256").update(domain).update("\0").update(pruningCanonical(value)).digest("hex")}`;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function exact(value, keys, label) {
|
|
50
|
+
if (
|
|
51
|
+
!value ||
|
|
52
|
+
Array.isArray(value) ||
|
|
53
|
+
typeof value !== "object" ||
|
|
54
|
+
Object.keys(value).length !== keys.length ||
|
|
55
|
+
keys.some((key) => !Object.hasOwn(value, key))
|
|
56
|
+
)
|
|
57
|
+
throw new TypeError(`${label} fields are invalid`);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Capture before any await. Never invoke accessors, proxy traps or toJSON;
|
|
61
|
+
// bound traversal as well as the resulting canonical bytes.
|
|
62
|
+
function snapshot(input) {
|
|
63
|
+
let nodes = 0;
|
|
64
|
+
let textBytes = 0;
|
|
65
|
+
const seen = new WeakSet();
|
|
66
|
+
const copy = (value, depth = 0) => {
|
|
67
|
+
if (++nodes > 40_000 || depth > 24)
|
|
68
|
+
throw new TypeError("pruning journal graph exceeds its budget");
|
|
69
|
+
if (typeof value === "string") {
|
|
70
|
+
textBytes += Buffer.byteLength(value, "utf8");
|
|
71
|
+
if (textBytes > WIKI_PRUNING_JOURNAL_MAX_BYTES)
|
|
72
|
+
throw new TypeError("pruning journal text exceeds its budget");
|
|
73
|
+
return value;
|
|
74
|
+
}
|
|
75
|
+
if (
|
|
76
|
+
value === null ||
|
|
77
|
+
typeof value === "boolean" ||
|
|
78
|
+
(typeof value === "number" && Number.isFinite(value))
|
|
79
|
+
)
|
|
80
|
+
return value;
|
|
81
|
+
if (typeof value !== "object" || types.isProxy(value) || seen.has(value))
|
|
82
|
+
throw new TypeError("pruning journal requires acyclic plain data");
|
|
83
|
+
const array = Array.isArray(value);
|
|
84
|
+
if (
|
|
85
|
+
![array ? Array.prototype : Object.prototype, null].includes(
|
|
86
|
+
Object.getPrototypeOf(value),
|
|
87
|
+
)
|
|
88
|
+
)
|
|
89
|
+
throw new TypeError("pruning journal prototype is invalid");
|
|
90
|
+
seen.add(value);
|
|
91
|
+
const properties = Object.getOwnPropertyDescriptors(value);
|
|
92
|
+
const keys = Reflect.ownKeys(properties);
|
|
93
|
+
const length = array ? properties.length?.value : 0;
|
|
94
|
+
if (
|
|
95
|
+
array &&
|
|
96
|
+
(!Number.isSafeInteger(length) ||
|
|
97
|
+
length < 0 ||
|
|
98
|
+
length > 8192 ||
|
|
99
|
+
keys.length !== length + 1)
|
|
100
|
+
)
|
|
101
|
+
throw new TypeError("pruning journal array is invalid");
|
|
102
|
+
const result = array ? [] : {};
|
|
103
|
+
for (const key of keys) {
|
|
104
|
+
if (array && key === "length") continue;
|
|
105
|
+
const property = properties[key];
|
|
106
|
+
if (
|
|
107
|
+
typeof key !== "string" ||
|
|
108
|
+
!("value" in property) ||
|
|
109
|
+
!property.enumerable ||
|
|
110
|
+
(array && (!/^(0|[1-9][0-9]*)$/u.test(key) || Number(key) >= length))
|
|
111
|
+
)
|
|
112
|
+
throw new TypeError("pruning journal properties are unsafe");
|
|
113
|
+
textBytes += Buffer.byteLength(key, "utf8");
|
|
114
|
+
Object.defineProperty(result, key, {
|
|
115
|
+
value: copy(property.value, depth + 1),
|
|
116
|
+
enumerable: true,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
seen.delete(value);
|
|
120
|
+
return Object.freeze(result);
|
|
121
|
+
};
|
|
122
|
+
const result = copy(input);
|
|
123
|
+
if (
|
|
124
|
+
Buffer.byteLength(pruningCanonical(result), "utf8") >
|
|
125
|
+
WIKI_PRUNING_JOURNAL_MAX_BYTES
|
|
126
|
+
)
|
|
127
|
+
throw new TypeError("pruning journal exceeds its byte budget");
|
|
128
|
+
return result;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function verifyPruningJournalPlan(input, tenantId) {
|
|
132
|
+
const plan = snapshot(input);
|
|
133
|
+
exact(plan, PLAN_KEYS, "pruning plan");
|
|
134
|
+
if (typeof tenantId !== "string" || !tenantId.trim())
|
|
135
|
+
throw new TypeError("pruning plan tenant is invalid");
|
|
136
|
+
const { planDigest, ...core } = plan;
|
|
137
|
+
if (
|
|
138
|
+
plan.schema !== GOVERNED_WIKI_PRUNING_PLAN_SCHEMA ||
|
|
139
|
+
plan.tenantId !== tenantId ||
|
|
140
|
+
!DIGEST.test(plan.wikiStateDigest) ||
|
|
141
|
+
!DIGEST.test(plan.policyDigest) ||
|
|
142
|
+
!DIGEST.test(planDigest) ||
|
|
143
|
+
typeof plan.effectiveAt !== "string" ||
|
|
144
|
+
!Number.isFinite(Date.parse(plan.effectiveAt)) ||
|
|
145
|
+
pruningDigest(GOVERNED_WIKI_PRUNING_PLAN_SCHEMA, core) !== planDigest
|
|
146
|
+
)
|
|
147
|
+
throw new TypeError("pruning plan binding is invalid");
|
|
148
|
+
for (const key of [
|
|
149
|
+
"patternActions",
|
|
150
|
+
"retrievalRemovals",
|
|
151
|
+
"dependencyDispositions",
|
|
152
|
+
"deletions",
|
|
153
|
+
])
|
|
154
|
+
if (!Array.isArray(plan[key]) || plan[key].length > 4096)
|
|
155
|
+
throw new TypeError("pruning plan actions are invalid");
|
|
156
|
+
return plan;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export function capturePruningData(input) {
|
|
160
|
+
return snapshot(input);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export function pruningOperationCalls(plan) {
|
|
164
|
+
const steps = [
|
|
165
|
+
["dependency-dispositions", plan.dependencyDispositions],
|
|
166
|
+
["wiki-revision", plan.patternActions],
|
|
167
|
+
...plan.deletions.map((deletion) => ["crypto-shred", deletion]),
|
|
168
|
+
["retrieval-projection", { removals: plan.retrievalRemovals }],
|
|
169
|
+
];
|
|
170
|
+
return steps.map(([operation, payload]) => {
|
|
171
|
+
const request = snapshot({
|
|
172
|
+
tenantId: plan.tenantId,
|
|
173
|
+
planDigest: plan.planDigest,
|
|
174
|
+
wikiStateDigest: plan.wikiStateDigest,
|
|
175
|
+
operation,
|
|
176
|
+
payload,
|
|
177
|
+
});
|
|
178
|
+
return Object.freeze({
|
|
179
|
+
request,
|
|
180
|
+
requestDigest: pruningDigest(
|
|
181
|
+
"chainlesschain.governed-wiki-pruning-operation/v1",
|
|
182
|
+
request,
|
|
183
|
+
),
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export function verifyWikiPruningJournal(input, tenantId) {
|
|
189
|
+
const state = snapshot(input);
|
|
190
|
+
exact(state, JOURNAL_KEYS, "pruning journal");
|
|
191
|
+
const { journalDigest, ...core } = state;
|
|
192
|
+
if (
|
|
193
|
+
state.schema !== WIKI_PRUNING_JOURNAL_SCHEMA ||
|
|
194
|
+
state.tenantId !== tenantId ||
|
|
195
|
+
!Number.isSafeInteger(state.revision) ||
|
|
196
|
+
state.revision < 1 ||
|
|
197
|
+
(state.previousJournalDigest !== null &&
|
|
198
|
+
!DIGEST.test(state.previousJournalDigest)) ||
|
|
199
|
+
!DIGEST.test(journalDigest) ||
|
|
200
|
+
pruningDigest(WIKI_PRUNING_JOURNAL_SCHEMA, core) !== journalDigest
|
|
201
|
+
)
|
|
202
|
+
throw new TypeError("pruning journal binding is invalid");
|
|
203
|
+
const plan = verifyPruningJournalPlan(state.plan, tenantId);
|
|
204
|
+
const calls = pruningOperationCalls(plan);
|
|
205
|
+
if (
|
|
206
|
+
!Array.isArray(state.operationReceipts) ||
|
|
207
|
+
state.operationReceipts.length > calls.length ||
|
|
208
|
+
!["prepared", "running", "finalized"].includes(state.phase) ||
|
|
209
|
+
(state.phase === "prepared" && state.operationReceipts.length !== 0) ||
|
|
210
|
+
(state.phase === "running" && state.operationReceipts.length === 0) ||
|
|
211
|
+
(state.phase === "finalized" &&
|
|
212
|
+
state.operationReceipts.length !== calls.length)
|
|
213
|
+
)
|
|
214
|
+
throw new TypeError("pruning journal progress is invalid");
|
|
215
|
+
state.operationReceipts.forEach((receipt, index) => {
|
|
216
|
+
if (
|
|
217
|
+
receipt?.authenticated !== true ||
|
|
218
|
+
receipt.durable !== true ||
|
|
219
|
+
receipt.requestDigest !== calls[index].requestDigest ||
|
|
220
|
+
!DIGEST.test(receipt.receiptDigest)
|
|
221
|
+
)
|
|
222
|
+
throw new TypeError("pruning operation receipt is not exactly bound");
|
|
223
|
+
});
|
|
224
|
+
return state;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export function assertPruningJournalTransition(previous, next) {
|
|
228
|
+
if (
|
|
229
|
+
next.revision !== (previous?.revision ?? 0) + 1 ||
|
|
230
|
+
next.previousJournalDigest !== (previous?.journalDigest ?? null)
|
|
231
|
+
)
|
|
232
|
+
throw new Error("pruning journal does not extend its exact predecessor");
|
|
233
|
+
if (!previous || previous.plan.planDigest !== next.plan.planDigest) {
|
|
234
|
+
if (
|
|
235
|
+
(previous && previous.phase !== "finalized") ||
|
|
236
|
+
next.phase !== "prepared"
|
|
237
|
+
)
|
|
238
|
+
throw new Error("pruning journal cannot replace an unfinished plan");
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
if (
|
|
242
|
+
previous.phase === "finalized" ||
|
|
243
|
+
pruningCanonical(previous.plan) !== pruningCanonical(next.plan)
|
|
244
|
+
)
|
|
245
|
+
throw new Error("pruning journal plan cannot be rewritten or restarted");
|
|
246
|
+
const count = previous.operationReceipts.length;
|
|
247
|
+
if (
|
|
248
|
+
pruningCanonical(next.operationReceipts.slice(0, count)) !==
|
|
249
|
+
pruningCanonical(previous.operationReceipts) ||
|
|
250
|
+
(next.phase === "running" && next.operationReceipts.length !== count + 1) ||
|
|
251
|
+
(next.phase === "finalized" && next.operationReceipts.length !== count) ||
|
|
252
|
+
next.phase === "prepared"
|
|
253
|
+
)
|
|
254
|
+
throw new Error(
|
|
255
|
+
"pruning journal must retain receipts and advance one step at a time",
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
export function buildWikiPruningJournal({
|
|
260
|
+
plan: input,
|
|
261
|
+
previous = null,
|
|
262
|
+
receipt = null,
|
|
263
|
+
finalize = false,
|
|
264
|
+
}) {
|
|
265
|
+
if (typeof finalize !== "boolean")
|
|
266
|
+
throw new TypeError("pruning journal finalize flag is invalid");
|
|
267
|
+
const capturedPlan = snapshot(input);
|
|
268
|
+
const plan = verifyPruningJournalPlan(capturedPlan, capturedPlan.tenantId);
|
|
269
|
+
const capturedReceipt = receipt === null ? null : snapshot(receipt);
|
|
270
|
+
const prior =
|
|
271
|
+
previous === null
|
|
272
|
+
? null
|
|
273
|
+
: verifyWikiPruningJournal(previous, plan.tenantId);
|
|
274
|
+
const samePlan = prior?.plan.planDigest === plan.planDigest;
|
|
275
|
+
if (
|
|
276
|
+
(!samePlan && (receipt !== null || finalize)) ||
|
|
277
|
+
(receipt !== null && finalize)
|
|
278
|
+
)
|
|
279
|
+
throw new Error("pruning journal must prepare before progress");
|
|
280
|
+
const core = {
|
|
281
|
+
schema: WIKI_PRUNING_JOURNAL_SCHEMA,
|
|
282
|
+
tenantId: plan.tenantId,
|
|
283
|
+
revision: (prior?.revision ?? 0) + 1,
|
|
284
|
+
previousJournalDigest: prior?.journalDigest ?? null,
|
|
285
|
+
plan,
|
|
286
|
+
phase: !samePlan ? "prepared" : finalize ? "finalized" : "running",
|
|
287
|
+
operationReceipts: !samePlan
|
|
288
|
+
? []
|
|
289
|
+
: receipt === null
|
|
290
|
+
? prior.operationReceipts
|
|
291
|
+
: [...prior.operationReceipts, capturedReceipt],
|
|
292
|
+
};
|
|
293
|
+
const next = verifyWikiPruningJournal(
|
|
294
|
+
{
|
|
295
|
+
...core,
|
|
296
|
+
journalDigest: pruningDigest(WIKI_PRUNING_JOURNAL_SCHEMA, core),
|
|
297
|
+
},
|
|
298
|
+
plan.tenantId,
|
|
299
|
+
);
|
|
300
|
+
assertPruningJournalTransition(prior, next);
|
|
301
|
+
return next;
|
|
302
|
+
}
|