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
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { types as utilTypes } from "node:util";
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
SKILL_REVOCATION_DEPENDENCY_REQUEST_SCHEMA,
|
|
6
|
+
SKILL_REVOCATION_DEPENDENCY_RESULT_SCHEMA,
|
|
7
|
+
digestSkillRevocationDependencyRequest,
|
|
8
|
+
} from "./skill-revocation-propagation.js";
|
|
9
|
+
|
|
10
|
+
export const SKILL_RETRIEVAL_REVOCATION_STATE_SCHEMA =
|
|
11
|
+
"chainlesschain.skill-retrieval-revocation-state/v1";
|
|
12
|
+
export const SKILL_RETRIEVAL_REVOCATION_READER_SCHEMA =
|
|
13
|
+
"chainlesschain.skill-retrieval-revocation-reader/v1";
|
|
14
|
+
export const MAX_SKILL_RETRIEVAL_INVALIDATIONS = 10_000;
|
|
15
|
+
|
|
16
|
+
const DIGEST = /^sha256:[a-f0-9]{64}$/u;
|
|
17
|
+
const ID = /^[A-Za-z0-9][A-Za-z0-9._:@/-]{0,255}$/u;
|
|
18
|
+
const REQUEST_KEYS = new Set([
|
|
19
|
+
"schema",
|
|
20
|
+
"tenantId",
|
|
21
|
+
"streamId",
|
|
22
|
+
"operationId",
|
|
23
|
+
"transitionDigest",
|
|
24
|
+
"candidateId",
|
|
25
|
+
"skillName",
|
|
26
|
+
"occurredAt",
|
|
27
|
+
"sourceReceiptDigest",
|
|
28
|
+
"resolutionDigest",
|
|
29
|
+
"dependency",
|
|
30
|
+
"requestDigest",
|
|
31
|
+
]);
|
|
32
|
+
const DEPENDENCY_KEYS = new Set(["kind", "ref", "digest", "disposition"]);
|
|
33
|
+
const STATE_KEYS = new Set([
|
|
34
|
+
"schema",
|
|
35
|
+
"tenantId",
|
|
36
|
+
"revision",
|
|
37
|
+
"invalidations",
|
|
38
|
+
"stateDigest",
|
|
39
|
+
]);
|
|
40
|
+
const INVALIDATION_KEYS = new Set([
|
|
41
|
+
"skillName",
|
|
42
|
+
"contentDigest",
|
|
43
|
+
"transitionDigest",
|
|
44
|
+
"sourceReceiptDigest",
|
|
45
|
+
"propagationRequestDigest",
|
|
46
|
+
"invalidatedAt",
|
|
47
|
+
]);
|
|
48
|
+
const LOAD_KEYS = new Set([
|
|
49
|
+
"authenticated",
|
|
50
|
+
"durable",
|
|
51
|
+
"found",
|
|
52
|
+
"state",
|
|
53
|
+
"receiptDigest",
|
|
54
|
+
]);
|
|
55
|
+
const COMMIT_KEYS = new Set([
|
|
56
|
+
"authenticated",
|
|
57
|
+
"durable",
|
|
58
|
+
"committed",
|
|
59
|
+
"stateDigest",
|
|
60
|
+
"receiptDigest",
|
|
61
|
+
]);
|
|
62
|
+
const readerBrand = new WeakSet();
|
|
63
|
+
|
|
64
|
+
function canonical(value) {
|
|
65
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
66
|
+
if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`;
|
|
67
|
+
return `{${Object.keys(value)
|
|
68
|
+
.sort()
|
|
69
|
+
.map((key) => `${JSON.stringify(key)}:${canonical(value[key])}`)
|
|
70
|
+
.join(",")}}`;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function hash(value) {
|
|
74
|
+
return `sha256:${createHash("sha256").update(canonical(value)).digest("hex")}`;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function freeze(value, seen = new WeakSet()) {
|
|
78
|
+
if (!value || typeof value !== "object" || seen.has(value)) return value;
|
|
79
|
+
seen.add(value);
|
|
80
|
+
for (const child of Object.values(value)) freeze(child, seen);
|
|
81
|
+
return Object.freeze(value);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function exact(value, keys, label) {
|
|
85
|
+
if (
|
|
86
|
+
!value ||
|
|
87
|
+
typeof value !== "object" ||
|
|
88
|
+
Array.isArray(value) ||
|
|
89
|
+
utilTypes.isProxy(value) ||
|
|
90
|
+
![Object.prototype, null].includes(Object.getPrototypeOf(value))
|
|
91
|
+
) {
|
|
92
|
+
throw new TypeError(`${label} must be a plain record`);
|
|
93
|
+
}
|
|
94
|
+
const own = Reflect.ownKeys(value);
|
|
95
|
+
if (
|
|
96
|
+
own.length !== keys.size ||
|
|
97
|
+
own.some((key) => typeof key !== "string" || !keys.has(key))
|
|
98
|
+
) {
|
|
99
|
+
throw new TypeError(`${label} must contain exactly the supported fields`);
|
|
100
|
+
}
|
|
101
|
+
for (const key of own) {
|
|
102
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
103
|
+
if (!descriptor || !("value" in descriptor) || !descriptor.enumerable) {
|
|
104
|
+
throw new TypeError(`${label}.${String(key)} is unsafe`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function id(value, label) {
|
|
110
|
+
if (!ID.test(value ?? "")) throw new TypeError(`${label} is invalid`);
|
|
111
|
+
return value;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function digest(value, label) {
|
|
115
|
+
if (!DIGEST.test(value ?? "")) throw new TypeError(`${label} is invalid`);
|
|
116
|
+
return value;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function timestamp(value, label) {
|
|
120
|
+
if (typeof value !== "string" || new Date(value).toISOString() !== value) {
|
|
121
|
+
throw new TypeError(`${label} is invalid`);
|
|
122
|
+
}
|
|
123
|
+
return value;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export function digestSkillRetrievalRevocationState(core) {
|
|
127
|
+
return hash({ domain: SKILL_RETRIEVAL_REVOCATION_STATE_SCHEMA, ...core });
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export function verifySkillRetrievalRevocationState(value, tenantId) {
|
|
131
|
+
exact(value, STATE_KEYS, "retrieval revocation state");
|
|
132
|
+
if (
|
|
133
|
+
value.schema !== SKILL_RETRIEVAL_REVOCATION_STATE_SCHEMA ||
|
|
134
|
+
value.tenantId !== tenantId ||
|
|
135
|
+
!Number.isSafeInteger(value.revision) ||
|
|
136
|
+
value.revision < 1
|
|
137
|
+
) {
|
|
138
|
+
throw new Error("Retrieval revocation state authority is invalid");
|
|
139
|
+
}
|
|
140
|
+
exact(
|
|
141
|
+
value.invalidations,
|
|
142
|
+
new Set(Object.keys(value.invalidations)),
|
|
143
|
+
"invalidations",
|
|
144
|
+
);
|
|
145
|
+
const entries = Object.entries(value.invalidations);
|
|
146
|
+
if (entries.length > MAX_SKILL_RETRIEVAL_INVALIDATIONS) {
|
|
147
|
+
throw new Error("Retrieval revocation capacity exceeded");
|
|
148
|
+
}
|
|
149
|
+
for (const [contentDigest, entry] of entries) {
|
|
150
|
+
digest(contentDigest, "invalidation content digest");
|
|
151
|
+
exact(entry, INVALIDATION_KEYS, "retrieval invalidation");
|
|
152
|
+
id(entry.skillName, "invalidation skillName");
|
|
153
|
+
if (entry.contentDigest !== contentDigest) {
|
|
154
|
+
throw new Error("Retrieval invalidation key is not digest-bound");
|
|
155
|
+
}
|
|
156
|
+
digest(entry.transitionDigest, "invalidation transitionDigest");
|
|
157
|
+
digest(entry.sourceReceiptDigest, "invalidation sourceReceiptDigest");
|
|
158
|
+
digest(entry.propagationRequestDigest, "invalidation requestDigest");
|
|
159
|
+
timestamp(entry.invalidatedAt, "invalidation invalidatedAt");
|
|
160
|
+
}
|
|
161
|
+
const core = {
|
|
162
|
+
schema: value.schema,
|
|
163
|
+
tenantId: value.tenantId,
|
|
164
|
+
revision: value.revision,
|
|
165
|
+
invalidations: value.invalidations,
|
|
166
|
+
};
|
|
167
|
+
if (value.stateDigest !== digestSkillRetrievalRevocationState(core)) {
|
|
168
|
+
throw new Error("Retrieval revocation state digest is invalid");
|
|
169
|
+
}
|
|
170
|
+
return freeze(structuredClone(value));
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function normalizeRequest(request, tenantId) {
|
|
174
|
+
exact(request, REQUEST_KEYS, "retrieval invalidation request");
|
|
175
|
+
exact(
|
|
176
|
+
request.dependency,
|
|
177
|
+
DEPENDENCY_KEYS,
|
|
178
|
+
"retrieval invalidation dependency",
|
|
179
|
+
);
|
|
180
|
+
id(request.skillName, "request.skillName");
|
|
181
|
+
id(request.streamId, "request.streamId");
|
|
182
|
+
id(request.operationId, "request.operationId");
|
|
183
|
+
const expectedRef = `skill-content:${tenantId}:${request.skillName}`;
|
|
184
|
+
if (
|
|
185
|
+
request.schema !== SKILL_REVOCATION_DEPENDENCY_REQUEST_SCHEMA ||
|
|
186
|
+
request.tenantId !== tenantId ||
|
|
187
|
+
request.dependency.kind !== "retrieval-index" ||
|
|
188
|
+
request.dependency.disposition !== "invalidate" ||
|
|
189
|
+
request.dependency.ref !== expectedRef ||
|
|
190
|
+
request.requestDigest !== digestSkillRevocationDependencyRequest(request)
|
|
191
|
+
) {
|
|
192
|
+
throw new Error("Retrieval invalidation request is not exactly bound");
|
|
193
|
+
}
|
|
194
|
+
digest(request.dependency.digest, "request.dependency.digest");
|
|
195
|
+
digest(request.transitionDigest, "request.transitionDigest");
|
|
196
|
+
digest(request.candidateId, "request.candidateId");
|
|
197
|
+
digest(request.sourceReceiptDigest, "request.sourceReceiptDigest");
|
|
198
|
+
digest(request.resolutionDigest, "request.resolutionDigest");
|
|
199
|
+
timestamp(request.occurredAt, "request.occurredAt");
|
|
200
|
+
return request;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function matches(entry, request) {
|
|
204
|
+
return (
|
|
205
|
+
entry?.skillName === request.skillName &&
|
|
206
|
+
entry.contentDigest === request.dependency.digest &&
|
|
207
|
+
entry.transitionDigest === request.transitionDigest &&
|
|
208
|
+
entry.sourceReceiptDigest === request.sourceReceiptDigest &&
|
|
209
|
+
entry.propagationRequestDigest === request.requestDigest &&
|
|
210
|
+
entry.invalidatedAt === request.occurredAt
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export async function openSkillRetrievalRevocationAuthority({
|
|
215
|
+
tenantId,
|
|
216
|
+
ports,
|
|
217
|
+
} = {}) {
|
|
218
|
+
id(tenantId, "tenantId");
|
|
219
|
+
if (
|
|
220
|
+
!ports ||
|
|
221
|
+
typeof ports.load !== "function" ||
|
|
222
|
+
typeof ports.commit !== "function"
|
|
223
|
+
) {
|
|
224
|
+
throw new TypeError("Retrieval revocation persistence ports are required");
|
|
225
|
+
}
|
|
226
|
+
const load = ports.load.bind(ports);
|
|
227
|
+
const commit = ports.commit.bind(ports);
|
|
228
|
+
let state = null;
|
|
229
|
+
|
|
230
|
+
async function reload() {
|
|
231
|
+
const loaded = await load({ tenantId });
|
|
232
|
+
exact(loaded, LOAD_KEYS, "retrieval revocation load receipt");
|
|
233
|
+
if (
|
|
234
|
+
loaded.authenticated !== true ||
|
|
235
|
+
loaded.durable !== true ||
|
|
236
|
+
typeof loaded.found !== "boolean" ||
|
|
237
|
+
!DIGEST.test(loaded.receiptDigest ?? "") ||
|
|
238
|
+
(loaded.found ? loaded.state === null : loaded.state !== null)
|
|
239
|
+
) {
|
|
240
|
+
throw new Error("Retrieval revocation load is not authoritative");
|
|
241
|
+
}
|
|
242
|
+
state = loaded.found
|
|
243
|
+
? verifySkillRetrievalRevocationState(loaded.state, tenantId)
|
|
244
|
+
: null;
|
|
245
|
+
return state;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
await reload();
|
|
249
|
+
const reader = {
|
|
250
|
+
schema: SKILL_RETRIEVAL_REVOCATION_READER_SCHEMA,
|
|
251
|
+
tenantId,
|
|
252
|
+
inspect({ skillName, contentDigest } = {}) {
|
|
253
|
+
id(skillName, "skillName");
|
|
254
|
+
digest(contentDigest, "contentDigest");
|
|
255
|
+
const entry = state?.invalidations[contentDigest] ?? null;
|
|
256
|
+
if (entry !== null && entry.skillName !== skillName) {
|
|
257
|
+
throw new Error("Retrieval invalidation crossed its skill identity");
|
|
258
|
+
}
|
|
259
|
+
return freeze({
|
|
260
|
+
invalidated: entry !== null,
|
|
261
|
+
tenantId,
|
|
262
|
+
skillName,
|
|
263
|
+
contentDigest,
|
|
264
|
+
stateDigest: state?.stateDigest ?? null,
|
|
265
|
+
receiptDigest: entry?.propagationRequestDigest ?? null,
|
|
266
|
+
});
|
|
267
|
+
},
|
|
268
|
+
async invalidateRetrieval(input) {
|
|
269
|
+
const request = normalizeRequest(input, tenantId);
|
|
270
|
+
const contentDigest = request.dependency.digest;
|
|
271
|
+
if (matches(state?.invalidations[contentDigest], request)) {
|
|
272
|
+
return result(request, state.stateDigest);
|
|
273
|
+
}
|
|
274
|
+
if (state?.invalidations[contentDigest]) {
|
|
275
|
+
throw new Error(
|
|
276
|
+
"Retrieval content digest has a conflicting invalidation",
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
if (
|
|
280
|
+
Object.keys(state?.invalidations ?? {}).length >=
|
|
281
|
+
MAX_SKILL_RETRIEVAL_INVALIDATIONS
|
|
282
|
+
) {
|
|
283
|
+
throw new Error("Retrieval revocation capacity exceeded");
|
|
284
|
+
}
|
|
285
|
+
const core = {
|
|
286
|
+
schema: SKILL_RETRIEVAL_REVOCATION_STATE_SCHEMA,
|
|
287
|
+
tenantId,
|
|
288
|
+
revision: (state?.revision ?? 0) + 1,
|
|
289
|
+
invalidations: {
|
|
290
|
+
...(state?.invalidations ?? {}),
|
|
291
|
+
[contentDigest]: {
|
|
292
|
+
skillName: request.skillName,
|
|
293
|
+
contentDigest,
|
|
294
|
+
transitionDigest: request.transitionDigest,
|
|
295
|
+
sourceReceiptDigest: request.sourceReceiptDigest,
|
|
296
|
+
propagationRequestDigest: request.requestDigest,
|
|
297
|
+
invalidatedAt: request.occurredAt,
|
|
298
|
+
},
|
|
299
|
+
},
|
|
300
|
+
};
|
|
301
|
+
const next = freeze({
|
|
302
|
+
...core,
|
|
303
|
+
stateDigest: digestSkillRetrievalRevocationState(core),
|
|
304
|
+
});
|
|
305
|
+
try {
|
|
306
|
+
const receipt = await commit({
|
|
307
|
+
state: next,
|
|
308
|
+
expectedStateDigest: state?.stateDigest ?? null,
|
|
309
|
+
});
|
|
310
|
+
exact(receipt, COMMIT_KEYS, "retrieval revocation commit receipt");
|
|
311
|
+
if (
|
|
312
|
+
receipt.authenticated !== true ||
|
|
313
|
+
receipt.durable !== true ||
|
|
314
|
+
receipt.committed !== true ||
|
|
315
|
+
receipt.stateDigest !== next.stateDigest ||
|
|
316
|
+
!DIGEST.test(receipt.receiptDigest ?? "")
|
|
317
|
+
) {
|
|
318
|
+
throw new Error("Retrieval invalidation commit is not authoritative");
|
|
319
|
+
}
|
|
320
|
+
state = next;
|
|
321
|
+
} catch (cause) {
|
|
322
|
+
await reload();
|
|
323
|
+
if (!matches(state?.invalidations[contentDigest], request)) throw cause;
|
|
324
|
+
}
|
|
325
|
+
return result(request, state.stateDigest);
|
|
326
|
+
},
|
|
327
|
+
};
|
|
328
|
+
readerBrand.add(reader);
|
|
329
|
+
return Object.freeze(reader);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
function result(request, receiptDigest) {
|
|
333
|
+
return freeze({
|
|
334
|
+
schema: SKILL_REVOCATION_DEPENDENCY_RESULT_SCHEMA,
|
|
335
|
+
authenticated: true,
|
|
336
|
+
durable: true,
|
|
337
|
+
applied: true,
|
|
338
|
+
idempotent: true,
|
|
339
|
+
tenantId: request.tenantId,
|
|
340
|
+
operationId: request.operationId,
|
|
341
|
+
requestDigest: request.requestDigest,
|
|
342
|
+
dependencyKind: request.dependency.kind,
|
|
343
|
+
dependencyRef: request.dependency.ref,
|
|
344
|
+
dependencyDigest: request.dependency.digest,
|
|
345
|
+
disposition: request.dependency.disposition,
|
|
346
|
+
receiptDigest,
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
export function captureSkillRetrievalRevocationReader(reader) {
|
|
351
|
+
if (
|
|
352
|
+
!readerBrand.has(reader) ||
|
|
353
|
+
reader.schema !== SKILL_RETRIEVAL_REVOCATION_READER_SCHEMA ||
|
|
354
|
+
typeof reader.inspect !== "function"
|
|
355
|
+
) {
|
|
356
|
+
throw new TypeError(
|
|
357
|
+
"A branded Skill retrieval revocation reader is required",
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
return reader;
|
|
361
|
+
}
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
EVOLUTION_DURABLE_ARTIFACT_RECORD_SCHEMA,
|
|
5
|
+
isEvolutionLedgerArtifactResolver,
|
|
6
|
+
} from "./evolution-artifact-ports.js";
|
|
7
|
+
import {
|
|
8
|
+
EVOLUTION_ARTIFACT_RESOLUTION_SCHEMA,
|
|
9
|
+
EVOLUTION_LEDGER_DOMAIN_EVENT_SCHEMA,
|
|
10
|
+
} from "./evolution-ledger.js";
|
|
11
|
+
import { verifySkillRetrievalRevocationState } from "./skill-retrieval-revocation-authority.js";
|
|
12
|
+
|
|
13
|
+
export const SKILL_RETRIEVAL_REVOCATION_LEDGER_EVENT_TYPE =
|
|
14
|
+
"skill.retrieval-revocation.state-committed";
|
|
15
|
+
export const SKILL_RETRIEVAL_REVOCATION_LEDGER_RESOLUTION_SCHEMA =
|
|
16
|
+
"chainlesschain.skill-retrieval-revocation-ledger-resolution/v1";
|
|
17
|
+
export const SKILL_RETRIEVAL_REVOCATION_LEDGER_CORRUPT_CODE =
|
|
18
|
+
"CC_SKILL_RETRIEVAL_REVOCATION_LEDGER_CORRUPT";
|
|
19
|
+
export const SKILL_RETRIEVAL_REVOCATION_LEDGER_CONFLICT_CODE =
|
|
20
|
+
"CC_SKILL_RETRIEVAL_REVOCATION_LEDGER_CONFLICT";
|
|
21
|
+
|
|
22
|
+
const ARTIFACT_TYPE = "skill-retrieval-revocation-state";
|
|
23
|
+
const DIGEST = /^sha256:[a-f0-9]{64}$/u;
|
|
24
|
+
|
|
25
|
+
function canonical(value) {
|
|
26
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
27
|
+
if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`;
|
|
28
|
+
return `{${Object.keys(value)
|
|
29
|
+
.sort()
|
|
30
|
+
.map((key) => `${JSON.stringify(key)}:${canonical(value[key])}`)
|
|
31
|
+
.join(",")}}`;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function hash(domain, value) {
|
|
35
|
+
return `sha256:${createHash("sha256")
|
|
36
|
+
.update(domain)
|
|
37
|
+
.update("\0")
|
|
38
|
+
.update(canonical(value))
|
|
39
|
+
.digest("hex")}`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function string(value, label) {
|
|
43
|
+
if (typeof value !== "string" || value.trim() === "") {
|
|
44
|
+
throw new TypeError(`${label} is required`);
|
|
45
|
+
}
|
|
46
|
+
return value;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function digest(value, label, { nullable = false } = {}) {
|
|
50
|
+
if (nullable && value === null) return null;
|
|
51
|
+
if (!DIGEST.test(value ?? "")) throw new TypeError(`${label} is invalid`);
|
|
52
|
+
return value;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function capture(owner, method, label = method) {
|
|
56
|
+
if (typeof owner?.[method] !== "function") {
|
|
57
|
+
throw new TypeError(`${label} port is required`);
|
|
58
|
+
}
|
|
59
|
+
return (...args) => Reflect.apply(owner[method], owner, args);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function fail(code, message, options) {
|
|
63
|
+
const error = new Error(message, options);
|
|
64
|
+
error.code = code;
|
|
65
|
+
throw error;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function corrupt(message, options) {
|
|
69
|
+
fail(SKILL_RETRIEVAL_REVOCATION_LEDGER_CORRUPT_CODE, message, options);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function conflict(message) {
|
|
73
|
+
fail(SKILL_RETRIEVAL_REVOCATION_LEDGER_CONFLICT_CODE, message);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function normalizeDescriptor(input) {
|
|
77
|
+
return Object.freeze({
|
|
78
|
+
tenantId: string(input?.tenantId, "tenantId"),
|
|
79
|
+
artifactTenantId: string(input?.artifactTenantId, "artifactTenantId"),
|
|
80
|
+
streamId: string(input?.streamId, "streamId"),
|
|
81
|
+
audience: string(input?.audience, "audience"),
|
|
82
|
+
purpose: string(input?.purpose, "purpose"),
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function normalizeState(input, tenantId) {
|
|
87
|
+
return verifySkillRetrievalRevocationState(input, tenantId);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function assertStateExtends(previous, next) {
|
|
91
|
+
if (!previous) return;
|
|
92
|
+
const priorEntries = Object.entries(previous.invalidations);
|
|
93
|
+
if (Object.keys(next.invalidations).length < priorEntries.length) {
|
|
94
|
+
corrupt("retrieval revocation history removed an invalidation");
|
|
95
|
+
}
|
|
96
|
+
for (const [contentDigest, invalidation] of priorEntries) {
|
|
97
|
+
if (
|
|
98
|
+
canonical(next.invalidations[contentDigest]) !== canonical(invalidation)
|
|
99
|
+
) {
|
|
100
|
+
corrupt("retrieval revocation history replaced an invalidation");
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function parseState(resolution, descriptor) {
|
|
106
|
+
if (
|
|
107
|
+
resolution?.schema !== EVOLUTION_ARTIFACT_RESOLUTION_SCHEMA ||
|
|
108
|
+
resolution.authenticated !== true ||
|
|
109
|
+
resolution.found !== true ||
|
|
110
|
+
!DIGEST.test(resolution.digest ?? "") ||
|
|
111
|
+
!DIGEST.test(resolution.receiptDigest ?? "") ||
|
|
112
|
+
!Buffer.isBuffer(resolution.bytes)
|
|
113
|
+
) {
|
|
114
|
+
corrupt("retrieval revocation artifact resolution is incomplete");
|
|
115
|
+
}
|
|
116
|
+
let record;
|
|
117
|
+
try {
|
|
118
|
+
record = JSON.parse(resolution.bytes.toString("utf8"));
|
|
119
|
+
} catch {
|
|
120
|
+
corrupt("retrieval revocation artifact is not JSON");
|
|
121
|
+
}
|
|
122
|
+
if (
|
|
123
|
+
record?.schema !== EVOLUTION_DURABLE_ARTIFACT_RECORD_SCHEMA ||
|
|
124
|
+
record.tenantId !== descriptor.artifactTenantId ||
|
|
125
|
+
record.audience !== descriptor.audience ||
|
|
126
|
+
record.purpose !== descriptor.purpose ||
|
|
127
|
+
record.retention !== "ledger" ||
|
|
128
|
+
record.type !== ARTIFACT_TYPE
|
|
129
|
+
) {
|
|
130
|
+
corrupt("retrieval revocation durable artifact binding is invalid");
|
|
131
|
+
}
|
|
132
|
+
try {
|
|
133
|
+
return normalizeState(record.value, descriptor.tenantId);
|
|
134
|
+
} catch (cause) {
|
|
135
|
+
corrupt("retrieval revocation state artifact is invalid", { cause });
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export class SkillRetrievalRevocationLedgerAdapter {
|
|
140
|
+
constructor({
|
|
141
|
+
descriptor: input,
|
|
142
|
+
artifactPorts,
|
|
143
|
+
ledger,
|
|
144
|
+
ledgerArtifactResolver,
|
|
145
|
+
now = Date.now,
|
|
146
|
+
} = {}) {
|
|
147
|
+
this.descriptor = normalizeDescriptor(input);
|
|
148
|
+
this._put = capture(artifactPorts, "putCanonical");
|
|
149
|
+
this._read = capture(ledger, "read");
|
|
150
|
+
this._verifyLedger = capture(ledger, "verify");
|
|
151
|
+
this._append = capture(ledger, "appendDomainEvent");
|
|
152
|
+
if (!isEvolutionLedgerArtifactResolver(ledgerArtifactResolver)) {
|
|
153
|
+
throw new TypeError(
|
|
154
|
+
"a branded EvolutionArtifactPorts ledger resolver is required",
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
if (typeof now !== "function")
|
|
158
|
+
throw new TypeError("now must be a function");
|
|
159
|
+
this._resolveArtifact = ledgerArtifactResolver;
|
|
160
|
+
this._now = now;
|
|
161
|
+
Object.freeze(this);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
_events() {
|
|
165
|
+
const events = this._read();
|
|
166
|
+
if (!Array.isArray(events)) {
|
|
167
|
+
corrupt("EvolutionLedger did not return an event array");
|
|
168
|
+
}
|
|
169
|
+
return events.filter(
|
|
170
|
+
(event) =>
|
|
171
|
+
event.schema === EVOLUTION_LEDGER_DOMAIN_EVENT_SCHEMA &&
|
|
172
|
+
event.type === SKILL_RETRIEVAL_REVOCATION_LEDGER_EVENT_TYPE &&
|
|
173
|
+
event.tenantId === this.descriptor.tenantId &&
|
|
174
|
+
event.correlationId === this.descriptor.streamId,
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
_resolveEvent(event, previous = null) {
|
|
179
|
+
if (
|
|
180
|
+
event.artifactTenantId !== this.descriptor.artifactTenantId ||
|
|
181
|
+
event.decision !== "committed" ||
|
|
182
|
+
event.skillName !== null ||
|
|
183
|
+
!Array.isArray(event.sourceRefs) ||
|
|
184
|
+
event.sourceRefs.length !== (previous ? 1 : 0) ||
|
|
185
|
+
(previous &&
|
|
186
|
+
canonical(event.sourceRefs[0]) !== canonical(previous.subjectRef))
|
|
187
|
+
) {
|
|
188
|
+
corrupt("retrieval revocation ledger lineage is invalid");
|
|
189
|
+
}
|
|
190
|
+
const identity = this._verifyLedger();
|
|
191
|
+
const resolution = this._resolveArtifact({
|
|
192
|
+
epoch: identity.epoch,
|
|
193
|
+
ledgerId: identity.ledgerId,
|
|
194
|
+
ref: event.subjectRef,
|
|
195
|
+
tenantId: this.descriptor.artifactTenantId,
|
|
196
|
+
});
|
|
197
|
+
if (
|
|
198
|
+
resolution.ref !== event.subjectRef.ref ||
|
|
199
|
+
resolution.digest !== event.subjectRef.digest
|
|
200
|
+
) {
|
|
201
|
+
corrupt("retrieval revocation ledger subject was substituted");
|
|
202
|
+
}
|
|
203
|
+
const state = parseState(resolution, this.descriptor);
|
|
204
|
+
if (
|
|
205
|
+
event.eventId !==
|
|
206
|
+
`${SKILL_RETRIEVAL_REVOCATION_LEDGER_EVENT_TYPE}.${state.stateDigest.slice(7)}`
|
|
207
|
+
) {
|
|
208
|
+
corrupt("retrieval revocation event identity is invalid");
|
|
209
|
+
}
|
|
210
|
+
return state;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
_history() {
|
|
214
|
+
const events = this._events();
|
|
215
|
+
const history = [];
|
|
216
|
+
for (const [index, event] of events.entries()) {
|
|
217
|
+
const previous = events[index - 1] ?? null;
|
|
218
|
+
const state = this._resolveEvent(event, previous);
|
|
219
|
+
if (
|
|
220
|
+
state.revision !== index + 1 ||
|
|
221
|
+
(index > 0 && state.revision !== history[index - 1].state.revision + 1)
|
|
222
|
+
) {
|
|
223
|
+
corrupt("retrieval revocation state sequence is invalid");
|
|
224
|
+
}
|
|
225
|
+
assertStateExtends(history[index - 1]?.state ?? null, state);
|
|
226
|
+
history.push(Object.freeze({ event, state }));
|
|
227
|
+
}
|
|
228
|
+
return history;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
_resolution(state) {
|
|
232
|
+
const core = {
|
|
233
|
+
schema: SKILL_RETRIEVAL_REVOCATION_LEDGER_RESOLUTION_SCHEMA,
|
|
234
|
+
tenantId: this.descriptor.tenantId,
|
|
235
|
+
streamId: this.descriptor.streamId,
|
|
236
|
+
found: state !== null,
|
|
237
|
+
stateDigest: state?.stateDigest ?? null,
|
|
238
|
+
};
|
|
239
|
+
return Object.freeze({
|
|
240
|
+
authenticated: true,
|
|
241
|
+
durable: true,
|
|
242
|
+
found: state !== null,
|
|
243
|
+
state,
|
|
244
|
+
receiptDigest: hash(
|
|
245
|
+
SKILL_RETRIEVAL_REVOCATION_LEDGER_RESOLUTION_SCHEMA,
|
|
246
|
+
core,
|
|
247
|
+
),
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
load = ({ tenantId } = {}) => {
|
|
252
|
+
if (tenantId !== this.descriptor.tenantId) {
|
|
253
|
+
throw new TypeError("retrieval revocation load tenant is invalid");
|
|
254
|
+
}
|
|
255
|
+
return this._resolution(this._history().at(-1)?.state ?? null);
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
commit = ({ state: input, expectedStateDigest } = {}) => {
|
|
259
|
+
const state = normalizeState(input, this.descriptor.tenantId);
|
|
260
|
+
const expected = digest(expectedStateDigest, "expectedStateDigest", {
|
|
261
|
+
nullable: true,
|
|
262
|
+
});
|
|
263
|
+
const history = this._history();
|
|
264
|
+
const latest = history.at(-1) ?? null;
|
|
265
|
+
const currentDigest = latest?.state.stateDigest ?? null;
|
|
266
|
+
if (currentDigest !== expected) {
|
|
267
|
+
if (currentDigest === state.stateDigest) {
|
|
268
|
+
return Object.freeze({
|
|
269
|
+
authenticated: true,
|
|
270
|
+
durable: true,
|
|
271
|
+
committed: true,
|
|
272
|
+
stateDigest: state.stateDigest,
|
|
273
|
+
receiptDigest: latest.event.eventDigest,
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
conflict("retrieval revocation state changed before commit");
|
|
277
|
+
}
|
|
278
|
+
if (state.revision !== history.length + 1) {
|
|
279
|
+
conflict("retrieval revocation state revision does not extend history");
|
|
280
|
+
}
|
|
281
|
+
assertStateExtends(latest?.state ?? null, state);
|
|
282
|
+
const nowMs = Number(this._now());
|
|
283
|
+
if (!Number.isFinite(nowMs)) {
|
|
284
|
+
throw new TypeError("retrieval revocation ledger clock is invalid");
|
|
285
|
+
}
|
|
286
|
+
const head = this._verifyLedger();
|
|
287
|
+
const published = this._put(ARTIFACT_TYPE, state, {
|
|
288
|
+
audience: this.descriptor.audience,
|
|
289
|
+
purpose: this.descriptor.purpose,
|
|
290
|
+
retention: "ledger",
|
|
291
|
+
});
|
|
292
|
+
if (
|
|
293
|
+
published?.receipt?.persisted !== true ||
|
|
294
|
+
published.receipt.readbackVerified !== true ||
|
|
295
|
+
published.receipt.integrityVerified !== true ||
|
|
296
|
+
published.receipt.retention !== "ledger"
|
|
297
|
+
) {
|
|
298
|
+
corrupt("retrieval revocation state persistence was not confirmed");
|
|
299
|
+
}
|
|
300
|
+
const eventId = `${SKILL_RETRIEVAL_REVOCATION_LEDGER_EVENT_TYPE}.${state.stateDigest.slice(7)}`;
|
|
301
|
+
const receipt = this._append(
|
|
302
|
+
{
|
|
303
|
+
artifactTenantId: this.descriptor.artifactTenantId,
|
|
304
|
+
correlationId: this.descriptor.streamId,
|
|
305
|
+
decision: "committed",
|
|
306
|
+
eventId,
|
|
307
|
+
reason: `retrieval revocation state ${state.revision} committed`,
|
|
308
|
+
skillName: null,
|
|
309
|
+
sourceRefs: latest ? [latest.event.subjectRef] : [],
|
|
310
|
+
subjectRef: published.ref,
|
|
311
|
+
tenantId: this.descriptor.tenantId,
|
|
312
|
+
timestamp: new Date(nowMs).toISOString(),
|
|
313
|
+
type: SKILL_RETRIEVAL_REVOCATION_LEDGER_EVENT_TYPE,
|
|
314
|
+
},
|
|
315
|
+
{ expectedHeadDigest: head.headDigest, expectedSequence: head.sequence },
|
|
316
|
+
);
|
|
317
|
+
if (
|
|
318
|
+
receipt?.authenticated !== true ||
|
|
319
|
+
receipt.committed !== true ||
|
|
320
|
+
receipt.durable !== true ||
|
|
321
|
+
receipt.eventId !== eventId ||
|
|
322
|
+
!DIGEST.test(receipt.eventDigest ?? "")
|
|
323
|
+
) {
|
|
324
|
+
corrupt("retrieval revocation ledger append was not confirmed");
|
|
325
|
+
}
|
|
326
|
+
const recovered = this._history().at(-1);
|
|
327
|
+
if (recovered?.state.stateDigest !== state.stateDigest) {
|
|
328
|
+
corrupt("retrieval revocation state readback differs after commit");
|
|
329
|
+
}
|
|
330
|
+
return Object.freeze({
|
|
331
|
+
authenticated: true,
|
|
332
|
+
durable: true,
|
|
333
|
+
committed: true,
|
|
334
|
+
stateDigest: state.stateDigest,
|
|
335
|
+
receiptDigest: receipt.eventDigest,
|
|
336
|
+
});
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
persistencePorts() {
|
|
340
|
+
return Object.freeze({ load: this.load, commit: this.commit });
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
export function createSkillRetrievalRevocationLedgerAdapter(options) {
|
|
345
|
+
return new SkillRetrievalRevocationLedgerAdapter(options);
|
|
346
|
+
}
|