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,985 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { types as utilTypes } from "node:util";
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
EvidenceBackedWikiMaintainer,
|
|
6
|
+
WIKI_EVIDENCE_SCHEMA,
|
|
7
|
+
WIKI_MAINTENANCE_REQUEST_SCHEMA,
|
|
8
|
+
} from "./evidence-backed-wiki-maintainer.js";
|
|
9
|
+
|
|
10
|
+
export const SKILL_WIKI_TRANSITION_SCHEMA =
|
|
11
|
+
"chainlesschain.skill-wiki-transition/v1";
|
|
12
|
+
export const SKILL_WIKI_REVIEW_DECISION_SCHEMA =
|
|
13
|
+
"chainlesschain.skill-wiki-review-decision/v1";
|
|
14
|
+
export const SKILL_WIKI_PILOT_OUTCOME_SCHEMA =
|
|
15
|
+
"chainlesschain.skill-wiki-pilot-outcome/v1";
|
|
16
|
+
export const SKILL_WIKI_REVOCATION_OUTCOME_SCHEMA =
|
|
17
|
+
"chainlesschain.skill-wiki-revocation-outcome/v1";
|
|
18
|
+
export const SKILL_WIKI_IMPACT_RESOLUTION_SCHEMA =
|
|
19
|
+
"chainlesschain.skill-wiki-impact-resolution/v1";
|
|
20
|
+
export const SKILL_WIKI_EVIDENCE_RETENTION_SCHEMA =
|
|
21
|
+
"chainlesschain.skill-wiki-evidence-retention/v1";
|
|
22
|
+
export const SKILL_WIKI_RECONCILIATION_CHECKPOINT_SCHEMA =
|
|
23
|
+
"chainlesschain.skill-wiki-reconciliation-checkpoint/v1";
|
|
24
|
+
export const SKILL_WIKI_RECONCILIATION_ERROR_CODE =
|
|
25
|
+
"CC_SKILL_WIKI_RECONCILIATION_INVALID";
|
|
26
|
+
|
|
27
|
+
const SOURCES = new WeakSet();
|
|
28
|
+
const DIGEST = /^sha256:[a-f0-9]{64}$/u;
|
|
29
|
+
const WIKI_REVISION_ID = /^wiki:[a-f0-9]{64}$/u;
|
|
30
|
+
const SKILL_NAME = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/u;
|
|
31
|
+
const TRANSITION_KEYS = new Set([
|
|
32
|
+
"schema",
|
|
33
|
+
"authenticated",
|
|
34
|
+
"durable",
|
|
35
|
+
"tenantId",
|
|
36
|
+
"streamId",
|
|
37
|
+
"sequence",
|
|
38
|
+
"candidateId",
|
|
39
|
+
"skillName",
|
|
40
|
+
"activeReleaseDigest",
|
|
41
|
+
"stateDigest",
|
|
42
|
+
"settlementDigest",
|
|
43
|
+
"occurredAt",
|
|
44
|
+
"wikiRevision",
|
|
45
|
+
"sourceEvidenceRefs",
|
|
46
|
+
"sourceReceiptDigest",
|
|
47
|
+
]);
|
|
48
|
+
const REVIEW_KEYS = new Set([
|
|
49
|
+
"schema",
|
|
50
|
+
"authenticated",
|
|
51
|
+
"durable",
|
|
52
|
+
"tenantId",
|
|
53
|
+
"streamId",
|
|
54
|
+
"sequence",
|
|
55
|
+
"candidateId",
|
|
56
|
+
"skillName",
|
|
57
|
+
"decision",
|
|
58
|
+
"reason",
|
|
59
|
+
"occurredAt",
|
|
60
|
+
"packetDigest",
|
|
61
|
+
"decisionReceiptDigest",
|
|
62
|
+
"sourceEvidenceRefs",
|
|
63
|
+
"sourceReceiptDigest",
|
|
64
|
+
]);
|
|
65
|
+
const PILOT_KEYS = new Set([
|
|
66
|
+
"schema",
|
|
67
|
+
"authenticated",
|
|
68
|
+
"durable",
|
|
69
|
+
"tenantId",
|
|
70
|
+
"streamId",
|
|
71
|
+
"sequence",
|
|
72
|
+
"pilotId",
|
|
73
|
+
"descriptorDigest",
|
|
74
|
+
"candidateId",
|
|
75
|
+
"skillName",
|
|
76
|
+
"outcome",
|
|
77
|
+
"reason",
|
|
78
|
+
"occurredAt",
|
|
79
|
+
"activeStateDigest",
|
|
80
|
+
"evidenceReceiptDigests",
|
|
81
|
+
"sourceReceiptDigest",
|
|
82
|
+
]);
|
|
83
|
+
const REVOCATION_KEYS = new Set([
|
|
84
|
+
"schema",
|
|
85
|
+
"authenticated",
|
|
86
|
+
"durable",
|
|
87
|
+
"tenantId",
|
|
88
|
+
"streamId",
|
|
89
|
+
"sequence",
|
|
90
|
+
"revocationId",
|
|
91
|
+
"candidateId",
|
|
92
|
+
"skillName",
|
|
93
|
+
"outcome",
|
|
94
|
+
"reason",
|
|
95
|
+
"occurredAt",
|
|
96
|
+
"activeStateDigest",
|
|
97
|
+
"evidenceReceiptDigests",
|
|
98
|
+
"sourceReceiptDigest",
|
|
99
|
+
]);
|
|
100
|
+
const IMPACT_KEYS = new Set([
|
|
101
|
+
"schema",
|
|
102
|
+
"authenticated",
|
|
103
|
+
"durable",
|
|
104
|
+
"tenantId",
|
|
105
|
+
"transitionDigest",
|
|
106
|
+
"candidateId",
|
|
107
|
+
"skillName",
|
|
108
|
+
"wikiRevision",
|
|
109
|
+
"patternRefs",
|
|
110
|
+
"reason",
|
|
111
|
+
"receiptDigest",
|
|
112
|
+
]);
|
|
113
|
+
const CHECKPOINT_KEYS = new Set([
|
|
114
|
+
"schema",
|
|
115
|
+
"authenticated",
|
|
116
|
+
"durable",
|
|
117
|
+
"tenantId",
|
|
118
|
+
"streamId",
|
|
119
|
+
"cursor",
|
|
120
|
+
"lastTransitionDigest",
|
|
121
|
+
"lastWikiRevisionId",
|
|
122
|
+
"checkpointDigest",
|
|
123
|
+
]);
|
|
124
|
+
const RETENTION_KEYS = new Set([
|
|
125
|
+
"schema",
|
|
126
|
+
"authenticated",
|
|
127
|
+
"durable",
|
|
128
|
+
"tenantId",
|
|
129
|
+
"ref",
|
|
130
|
+
"envelopeDigest",
|
|
131
|
+
"receiptDigest",
|
|
132
|
+
]);
|
|
133
|
+
const CHECKPOINT_RECEIPT_KEYS = new Set([
|
|
134
|
+
"authenticated",
|
|
135
|
+
"durable",
|
|
136
|
+
"committed",
|
|
137
|
+
"checkpointDigest",
|
|
138
|
+
]);
|
|
139
|
+
|
|
140
|
+
function canonical(value) {
|
|
141
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
142
|
+
if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`;
|
|
143
|
+
return `{${Object.keys(value)
|
|
144
|
+
.sort()
|
|
145
|
+
.map((key) => `${JSON.stringify(key)}:${canonical(value[key])}`)
|
|
146
|
+
.join(",")}}`;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function hash(value) {
|
|
150
|
+
return `sha256:${createHash("sha256").update(canonical(value)).digest("hex")}`;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function freeze(value, seen = new WeakSet()) {
|
|
154
|
+
if (!value || typeof value !== "object" || seen.has(value)) return value;
|
|
155
|
+
seen.add(value);
|
|
156
|
+
Object.freeze(value);
|
|
157
|
+
for (const child of Object.values(value)) freeze(child, seen);
|
|
158
|
+
return value;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function fail(message, options) {
|
|
162
|
+
const error = new Error(message, options);
|
|
163
|
+
error.code = SKILL_WIKI_RECONCILIATION_ERROR_CODE;
|
|
164
|
+
throw error;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function exact(value, keys, label) {
|
|
168
|
+
if (
|
|
169
|
+
!value ||
|
|
170
|
+
typeof value !== "object" ||
|
|
171
|
+
Array.isArray(value) ||
|
|
172
|
+
utilTypes.isProxy(value) ||
|
|
173
|
+
![Object.prototype, null].includes(Object.getPrototypeOf(value))
|
|
174
|
+
) {
|
|
175
|
+
fail(`${label} must be a plain record`);
|
|
176
|
+
}
|
|
177
|
+
const own = Reflect.ownKeys(value);
|
|
178
|
+
if (
|
|
179
|
+
own.length !== keys.size ||
|
|
180
|
+
own.some((key) => typeof key !== "string" || !keys.has(key))
|
|
181
|
+
) {
|
|
182
|
+
fail(`${label} must contain exactly the supported fields`);
|
|
183
|
+
}
|
|
184
|
+
for (const key of own) {
|
|
185
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
186
|
+
if (!descriptor || !("value" in descriptor) || !descriptor.enumerable) {
|
|
187
|
+
fail(`${label}.${String(key)} must be an enumerable data field`);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function string(value, label, maximum = 512) {
|
|
193
|
+
if (
|
|
194
|
+
typeof value !== "string" ||
|
|
195
|
+
value.trim() !== value ||
|
|
196
|
+
value === "" ||
|
|
197
|
+
Buffer.byteLength(value, "utf8") > maximum
|
|
198
|
+
) {
|
|
199
|
+
fail(`${label} is invalid`);
|
|
200
|
+
}
|
|
201
|
+
return value;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function digest(value, label) {
|
|
205
|
+
if (!DIGEST.test(value ?? "")) fail(`${label} must be sha256-bound`);
|
|
206
|
+
return value;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function timestamp(value, label) {
|
|
210
|
+
string(value, label, 64);
|
|
211
|
+
const parsed = new Date(value);
|
|
212
|
+
if (!Number.isFinite(parsed.getTime()) || parsed.toISOString() !== value) {
|
|
213
|
+
fail(`${label} must be a canonical timestamp`);
|
|
214
|
+
}
|
|
215
|
+
return value;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function sequence(value, label, { allowZero = false } = {}) {
|
|
219
|
+
if (!Number.isSafeInteger(value) || value < (allowZero ? 0 : 1)) {
|
|
220
|
+
fail(`${label} must be a safe sequence`);
|
|
221
|
+
}
|
|
222
|
+
return value;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function references(value, label, { allowEmpty = true } = {}) {
|
|
226
|
+
if (
|
|
227
|
+
!Array.isArray(value) ||
|
|
228
|
+
utilTypes.isProxy(value) ||
|
|
229
|
+
value.length > 128 ||
|
|
230
|
+
(!allowEmpty && value.length === 0)
|
|
231
|
+
) {
|
|
232
|
+
fail(`${label} must be a bounded reference list`);
|
|
233
|
+
}
|
|
234
|
+
const normalized = value.map((entry, index) => {
|
|
235
|
+
exact(entry, new Set(["ref", "digest"]), `${label}[${index}]`);
|
|
236
|
+
return {
|
|
237
|
+
ref: string(entry.ref, `${label}[${index}].ref`),
|
|
238
|
+
digest: digest(entry.digest, `${label}[${index}].digest`),
|
|
239
|
+
};
|
|
240
|
+
});
|
|
241
|
+
if (
|
|
242
|
+
new Set(normalized.map((entry) => entry.ref)).size !== normalized.length
|
|
243
|
+
) {
|
|
244
|
+
fail(`${label} contains duplicate refs`);
|
|
245
|
+
}
|
|
246
|
+
return normalized.sort((left, right) => left.ref.localeCompare(right.ref));
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function normalizeTransition(input, tenantId, streamId) {
|
|
250
|
+
exact(input, TRANSITION_KEYS, "skill Wiki transition");
|
|
251
|
+
const wikiRevision =
|
|
252
|
+
input.wikiRevision === null
|
|
253
|
+
? null
|
|
254
|
+
: string(input.wikiRevision, "transition.wikiRevision");
|
|
255
|
+
const core = {
|
|
256
|
+
schema: SKILL_WIKI_TRANSITION_SCHEMA,
|
|
257
|
+
tenantId,
|
|
258
|
+
streamId,
|
|
259
|
+
sequence: sequence(input.sequence, "transition.sequence"),
|
|
260
|
+
candidateId: digest(input.candidateId, "transition.candidateId"),
|
|
261
|
+
skillName: string(input.skillName, "transition.skillName", 128),
|
|
262
|
+
activeReleaseDigest: digest(
|
|
263
|
+
input.activeReleaseDigest,
|
|
264
|
+
"transition.activeReleaseDigest",
|
|
265
|
+
),
|
|
266
|
+
stateDigest: digest(input.stateDigest, "transition.stateDigest"),
|
|
267
|
+
settlementDigest: digest(
|
|
268
|
+
input.settlementDigest,
|
|
269
|
+
"transition.settlementDigest",
|
|
270
|
+
),
|
|
271
|
+
occurredAt: timestamp(input.occurredAt, "transition.occurredAt"),
|
|
272
|
+
wikiRevision,
|
|
273
|
+
sourceEvidenceRefs: references(
|
|
274
|
+
input.sourceEvidenceRefs,
|
|
275
|
+
"transition.sourceEvidenceRefs",
|
|
276
|
+
{ allowEmpty: false },
|
|
277
|
+
),
|
|
278
|
+
sourceReceiptDigest: digest(
|
|
279
|
+
input.sourceReceiptDigest,
|
|
280
|
+
"transition.sourceReceiptDigest",
|
|
281
|
+
),
|
|
282
|
+
};
|
|
283
|
+
if (
|
|
284
|
+
input.schema !== SKILL_WIKI_TRANSITION_SCHEMA ||
|
|
285
|
+
input.authenticated !== true ||
|
|
286
|
+
input.durable !== true ||
|
|
287
|
+
input.tenantId !== tenantId ||
|
|
288
|
+
input.streamId !== streamId ||
|
|
289
|
+
!SKILL_NAME.test(core.skillName)
|
|
290
|
+
) {
|
|
291
|
+
fail("skill Wiki transition is not durably tenant-bound");
|
|
292
|
+
}
|
|
293
|
+
return freeze({
|
|
294
|
+
...core,
|
|
295
|
+
authenticated: true,
|
|
296
|
+
durable: true,
|
|
297
|
+
transitionDigest: hash(core),
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
function capture(owner, method, label) {
|
|
302
|
+
if (
|
|
303
|
+
!owner ||
|
|
304
|
+
typeof owner !== "object" ||
|
|
305
|
+
utilTypes.isProxy(owner) ||
|
|
306
|
+
typeof owner[method] !== "function" ||
|
|
307
|
+
utilTypes.isProxy(owner[method])
|
|
308
|
+
) {
|
|
309
|
+
throw new TypeError(`${label}.${method} is required`);
|
|
310
|
+
}
|
|
311
|
+
return owner[method].bind(owner);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
export function createSkillWikiReconciliationSource({
|
|
315
|
+
tenantId: tenantInput,
|
|
316
|
+
streamId: streamInput,
|
|
317
|
+
readTransitions,
|
|
318
|
+
} = {}) {
|
|
319
|
+
const tenantId = string(tenantInput, "tenantId", 256);
|
|
320
|
+
const streamId = string(streamInput, "streamId", 256);
|
|
321
|
+
if (
|
|
322
|
+
typeof readTransitions !== "function" ||
|
|
323
|
+
utilTypes.isProxy(readTransitions)
|
|
324
|
+
) {
|
|
325
|
+
throw new TypeError("readTransitions is required");
|
|
326
|
+
}
|
|
327
|
+
const read = readTransitions;
|
|
328
|
+
const source = {
|
|
329
|
+
tenantId,
|
|
330
|
+
streamId,
|
|
331
|
+
list({ afterSequence = 0, limit = 64 } = {}) {
|
|
332
|
+
const cursor = sequence(afterSequence, "afterSequence", {
|
|
333
|
+
allowZero: true,
|
|
334
|
+
});
|
|
335
|
+
if (!Number.isSafeInteger(limit) || limit < 1 || limit > 256) {
|
|
336
|
+
fail("limit must be between 1 and 256");
|
|
337
|
+
}
|
|
338
|
+
const raw = read();
|
|
339
|
+
if (!Array.isArray(raw) || raw.length > 100_000) {
|
|
340
|
+
fail("transition source did not return a bounded list");
|
|
341
|
+
}
|
|
342
|
+
const all = raw
|
|
343
|
+
.map((entry) => normalizeTransition(entry, tenantId, streamId))
|
|
344
|
+
.sort((left, right) => left.sequence - right.sequence);
|
|
345
|
+
for (let index = 1; index < all.length; index += 1) {
|
|
346
|
+
if (all[index - 1].sequence >= all[index].sequence) {
|
|
347
|
+
fail("transition source sequences must be unique and increasing");
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
return freeze(
|
|
351
|
+
all.filter((entry) => entry.sequence > cursor).slice(0, limit),
|
|
352
|
+
);
|
|
353
|
+
},
|
|
354
|
+
};
|
|
355
|
+
SOURCES.add(source);
|
|
356
|
+
return freeze(source);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
function normalizeReviewDecision(input, tenantId, streamId) {
|
|
360
|
+
exact(input, REVIEW_KEYS, "skill Wiki review decision");
|
|
361
|
+
const core = {
|
|
362
|
+
schema: SKILL_WIKI_REVIEW_DECISION_SCHEMA,
|
|
363
|
+
tenantId,
|
|
364
|
+
streamId,
|
|
365
|
+
sequence: sequence(input.sequence, "review.sequence"),
|
|
366
|
+
candidateId: digest(input.candidateId, "review.candidateId"),
|
|
367
|
+
skillName: string(input.skillName, "review.skillName", 128),
|
|
368
|
+
decision: input.decision,
|
|
369
|
+
reason: string(input.reason, "review.reason", 1024),
|
|
370
|
+
occurredAt: timestamp(input.occurredAt, "review.occurredAt"),
|
|
371
|
+
packetDigest: digest(input.packetDigest, "review.packetDigest"),
|
|
372
|
+
decisionReceiptDigest: digest(
|
|
373
|
+
input.decisionReceiptDigest,
|
|
374
|
+
"review.decisionReceiptDigest",
|
|
375
|
+
),
|
|
376
|
+
sourceEvidenceRefs: references(
|
|
377
|
+
input.sourceEvidenceRefs,
|
|
378
|
+
"review.sourceEvidenceRefs",
|
|
379
|
+
{ allowEmpty: false },
|
|
380
|
+
),
|
|
381
|
+
sourceReceiptDigest: digest(
|
|
382
|
+
input.sourceReceiptDigest,
|
|
383
|
+
"review.sourceReceiptDigest",
|
|
384
|
+
),
|
|
385
|
+
};
|
|
386
|
+
if (
|
|
387
|
+
input.schema !== SKILL_WIKI_REVIEW_DECISION_SCHEMA ||
|
|
388
|
+
input.authenticated !== true ||
|
|
389
|
+
input.durable !== true ||
|
|
390
|
+
input.tenantId !== tenantId ||
|
|
391
|
+
input.streamId !== streamId ||
|
|
392
|
+
input.decision !== "rejected" ||
|
|
393
|
+
!SKILL_NAME.test(core.skillName)
|
|
394
|
+
) {
|
|
395
|
+
fail("skill Wiki review decision is not durably tenant-bound");
|
|
396
|
+
}
|
|
397
|
+
return freeze({
|
|
398
|
+
...core,
|
|
399
|
+
authenticated: true,
|
|
400
|
+
durable: true,
|
|
401
|
+
wikiRevision: null,
|
|
402
|
+
transitionDigest: hash(core),
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
export function createSkillWikiReviewReconciliationSource({
|
|
407
|
+
tenantId: tenantInput,
|
|
408
|
+
streamId: streamInput,
|
|
409
|
+
readReviewDecisions,
|
|
410
|
+
} = {}) {
|
|
411
|
+
const tenantId = string(tenantInput, "tenantId", 256);
|
|
412
|
+
const streamId = string(streamInput, "streamId", 256);
|
|
413
|
+
if (
|
|
414
|
+
typeof readReviewDecisions !== "function" ||
|
|
415
|
+
utilTypes.isProxy(readReviewDecisions)
|
|
416
|
+
) {
|
|
417
|
+
throw new TypeError("readReviewDecisions is required");
|
|
418
|
+
}
|
|
419
|
+
const source = {
|
|
420
|
+
tenantId,
|
|
421
|
+
streamId,
|
|
422
|
+
async list({ afterSequence = 0, limit = 64 } = {}) {
|
|
423
|
+
const cursor = sequence(afterSequence, "afterSequence", {
|
|
424
|
+
allowZero: true,
|
|
425
|
+
});
|
|
426
|
+
if (!Number.isSafeInteger(limit) || limit < 1 || limit > 256) {
|
|
427
|
+
fail("limit must be between 1 and 256");
|
|
428
|
+
}
|
|
429
|
+
const raw = await readReviewDecisions();
|
|
430
|
+
if (
|
|
431
|
+
!Array.isArray(raw) ||
|
|
432
|
+
utilTypes.isProxy(raw) ||
|
|
433
|
+
raw.length > 100_000
|
|
434
|
+
) {
|
|
435
|
+
fail("review source did not return a bounded list");
|
|
436
|
+
}
|
|
437
|
+
const all = raw
|
|
438
|
+
.map((entry) => normalizeReviewDecision(entry, tenantId, streamId))
|
|
439
|
+
.sort((left, right) => left.sequence - right.sequence);
|
|
440
|
+
for (let index = 1; index < all.length; index += 1) {
|
|
441
|
+
if (all[index - 1].sequence >= all[index].sequence) {
|
|
442
|
+
fail("review source sequences must be unique and increasing");
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
return freeze(
|
|
446
|
+
all.filter((entry) => entry.sequence > cursor).slice(0, limit),
|
|
447
|
+
);
|
|
448
|
+
},
|
|
449
|
+
};
|
|
450
|
+
SOURCES.add(source);
|
|
451
|
+
return freeze(source);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
function normalizePilotOutcome(input, tenantId, streamId) {
|
|
455
|
+
exact(input, PILOT_KEYS, "skill Wiki Pilot outcome");
|
|
456
|
+
if (
|
|
457
|
+
!Array.isArray(input.evidenceReceiptDigests) ||
|
|
458
|
+
utilTypes.isProxy(input.evidenceReceiptDigests) ||
|
|
459
|
+
input.evidenceReceiptDigests.length > 128
|
|
460
|
+
) {
|
|
461
|
+
fail("Pilot evidence receipts must be bounded");
|
|
462
|
+
}
|
|
463
|
+
const evidenceReceiptDigests = [
|
|
464
|
+
...new Set(
|
|
465
|
+
input.evidenceReceiptDigests.map((value) =>
|
|
466
|
+
digest(value, "Pilot evidence receipt"),
|
|
467
|
+
),
|
|
468
|
+
),
|
|
469
|
+
].sort();
|
|
470
|
+
if (evidenceReceiptDigests.length !== input.evidenceReceiptDigests.length) {
|
|
471
|
+
fail("Pilot evidence receipts must be unique");
|
|
472
|
+
}
|
|
473
|
+
const core = {
|
|
474
|
+
schema: SKILL_WIKI_PILOT_OUTCOME_SCHEMA,
|
|
475
|
+
tenantId,
|
|
476
|
+
streamId,
|
|
477
|
+
sequence: sequence(input.sequence, "Pilot outcome sequence"),
|
|
478
|
+
pilotId: string(input.pilotId, "Pilot outcome pilotId", 256),
|
|
479
|
+
descriptorDigest: digest(
|
|
480
|
+
input.descriptorDigest,
|
|
481
|
+
"Pilot outcome descriptorDigest",
|
|
482
|
+
),
|
|
483
|
+
candidateId: digest(input.candidateId, "Pilot outcome candidateId"),
|
|
484
|
+
skillName: string(input.skillName, "Pilot outcome skillName", 128),
|
|
485
|
+
outcome: input.outcome,
|
|
486
|
+
reason: string(input.reason, "Pilot outcome reason", 1024),
|
|
487
|
+
occurredAt: timestamp(input.occurredAt, "Pilot outcome occurredAt"),
|
|
488
|
+
activeStateDigest: digest(
|
|
489
|
+
input.activeStateDigest,
|
|
490
|
+
"Pilot outcome activeStateDigest",
|
|
491
|
+
),
|
|
492
|
+
evidenceReceiptDigests,
|
|
493
|
+
sourceReceiptDigest: digest(
|
|
494
|
+
input.sourceReceiptDigest,
|
|
495
|
+
"Pilot outcome sourceReceiptDigest",
|
|
496
|
+
),
|
|
497
|
+
};
|
|
498
|
+
if (
|
|
499
|
+
input.schema !== SKILL_WIKI_PILOT_OUTCOME_SCHEMA ||
|
|
500
|
+
input.authenticated !== true ||
|
|
501
|
+
input.durable !== true ||
|
|
502
|
+
input.tenantId !== tenantId ||
|
|
503
|
+
input.streamId !== streamId ||
|
|
504
|
+
!["stable", "rollback"].includes(input.outcome) ||
|
|
505
|
+
!SKILL_NAME.test(core.skillName)
|
|
506
|
+
) {
|
|
507
|
+
fail("skill Wiki Pilot outcome is not durably tenant-bound");
|
|
508
|
+
}
|
|
509
|
+
return freeze({
|
|
510
|
+
...core,
|
|
511
|
+
authenticated: true,
|
|
512
|
+
durable: true,
|
|
513
|
+
wikiRevision: null,
|
|
514
|
+
transitionDigest: hash(core),
|
|
515
|
+
});
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
export function createSkillWikiPilotReconciliationSource({
|
|
519
|
+
tenantId: tenantInput,
|
|
520
|
+
streamId: streamInput,
|
|
521
|
+
readPilotOutcomes,
|
|
522
|
+
} = {}) {
|
|
523
|
+
const tenantId = string(tenantInput, "tenantId", 256);
|
|
524
|
+
const streamId = string(streamInput, "streamId", 256);
|
|
525
|
+
if (
|
|
526
|
+
typeof readPilotOutcomes !== "function" ||
|
|
527
|
+
utilTypes.isProxy(readPilotOutcomes)
|
|
528
|
+
) {
|
|
529
|
+
throw new TypeError("readPilotOutcomes is required");
|
|
530
|
+
}
|
|
531
|
+
const source = {
|
|
532
|
+
tenantId,
|
|
533
|
+
streamId,
|
|
534
|
+
async list({ afterSequence = 0, limit = 64 } = {}) {
|
|
535
|
+
const cursor = sequence(afterSequence, "afterSequence", {
|
|
536
|
+
allowZero: true,
|
|
537
|
+
});
|
|
538
|
+
if (!Number.isSafeInteger(limit) || limit < 1 || limit > 256) {
|
|
539
|
+
fail("limit must be between 1 and 256");
|
|
540
|
+
}
|
|
541
|
+
const raw = await readPilotOutcomes();
|
|
542
|
+
if (
|
|
543
|
+
!Array.isArray(raw) ||
|
|
544
|
+
utilTypes.isProxy(raw) ||
|
|
545
|
+
raw.length > 10_000
|
|
546
|
+
) {
|
|
547
|
+
fail("Pilot outcome source did not return a bounded list");
|
|
548
|
+
}
|
|
549
|
+
const all = raw
|
|
550
|
+
.map((entry) => normalizePilotOutcome(entry, tenantId, streamId))
|
|
551
|
+
.sort((left, right) => left.sequence - right.sequence);
|
|
552
|
+
for (let index = 1; index < all.length; index += 1) {
|
|
553
|
+
if (all[index - 1].sequence >= all[index].sequence) {
|
|
554
|
+
fail("Pilot outcome sequences must be unique and increasing");
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
return freeze(
|
|
558
|
+
all.filter((entry) => entry.sequence > cursor).slice(0, limit),
|
|
559
|
+
);
|
|
560
|
+
},
|
|
561
|
+
};
|
|
562
|
+
SOURCES.add(source);
|
|
563
|
+
return freeze(source);
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
function normalizeRevocationOutcome(input, tenantId, streamId) {
|
|
567
|
+
exact(input, REVOCATION_KEYS, "skill Wiki revocation outcome");
|
|
568
|
+
if (
|
|
569
|
+
!Array.isArray(input.evidenceReceiptDigests) ||
|
|
570
|
+
utilTypes.isProxy(input.evidenceReceiptDigests) ||
|
|
571
|
+
input.evidenceReceiptDigests.length < 1 ||
|
|
572
|
+
input.evidenceReceiptDigests.length > 128
|
|
573
|
+
) {
|
|
574
|
+
fail("revocation evidence receipts must be a bounded non-empty list");
|
|
575
|
+
}
|
|
576
|
+
const evidenceReceiptDigests = [
|
|
577
|
+
...new Set(
|
|
578
|
+
input.evidenceReceiptDigests.map((value) =>
|
|
579
|
+
digest(value, "revocation evidence receipt"),
|
|
580
|
+
),
|
|
581
|
+
),
|
|
582
|
+
].sort();
|
|
583
|
+
if (evidenceReceiptDigests.length !== input.evidenceReceiptDigests.length) {
|
|
584
|
+
fail("revocation evidence receipts must be unique");
|
|
585
|
+
}
|
|
586
|
+
const core = {
|
|
587
|
+
schema: SKILL_WIKI_REVOCATION_OUTCOME_SCHEMA,
|
|
588
|
+
tenantId,
|
|
589
|
+
streamId,
|
|
590
|
+
sequence: sequence(input.sequence, "revocation outcome sequence"),
|
|
591
|
+
revocationId: string(
|
|
592
|
+
input.revocationId,
|
|
593
|
+
"revocation outcome revocationId",
|
|
594
|
+
256,
|
|
595
|
+
),
|
|
596
|
+
candidateId: digest(input.candidateId, "revocation outcome candidateId"),
|
|
597
|
+
skillName: string(input.skillName, "revocation outcome skillName", 128),
|
|
598
|
+
outcome: input.outcome,
|
|
599
|
+
reason: string(input.reason, "revocation outcome reason", 1024),
|
|
600
|
+
occurredAt: timestamp(input.occurredAt, "revocation outcome occurredAt"),
|
|
601
|
+
activeStateDigest: digest(
|
|
602
|
+
input.activeStateDigest,
|
|
603
|
+
"revocation outcome activeStateDigest",
|
|
604
|
+
),
|
|
605
|
+
evidenceReceiptDigests,
|
|
606
|
+
sourceReceiptDigest: digest(
|
|
607
|
+
input.sourceReceiptDigest,
|
|
608
|
+
"revocation outcome sourceReceiptDigest",
|
|
609
|
+
),
|
|
610
|
+
};
|
|
611
|
+
if (
|
|
612
|
+
input.schema !== SKILL_WIKI_REVOCATION_OUTCOME_SCHEMA ||
|
|
613
|
+
input.authenticated !== true ||
|
|
614
|
+
input.durable !== true ||
|
|
615
|
+
input.tenantId !== tenantId ||
|
|
616
|
+
input.streamId !== streamId ||
|
|
617
|
+
input.outcome !== "revoke" ||
|
|
618
|
+
!SKILL_NAME.test(core.skillName)
|
|
619
|
+
) {
|
|
620
|
+
fail("skill Wiki revocation outcome is not durably tenant-bound");
|
|
621
|
+
}
|
|
622
|
+
return freeze({
|
|
623
|
+
...core,
|
|
624
|
+
authenticated: true,
|
|
625
|
+
durable: true,
|
|
626
|
+
wikiRevision: null,
|
|
627
|
+
transitionDigest: hash(core),
|
|
628
|
+
});
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
export function createSkillWikiRevocationReconciliationSource({
|
|
632
|
+
tenantId: tenantInput,
|
|
633
|
+
streamId: streamInput,
|
|
634
|
+
readRevocations,
|
|
635
|
+
} = {}) {
|
|
636
|
+
const tenantId = string(tenantInput, "tenantId", 256);
|
|
637
|
+
const streamId = string(streamInput, "streamId", 256);
|
|
638
|
+
if (
|
|
639
|
+
typeof readRevocations !== "function" ||
|
|
640
|
+
utilTypes.isProxy(readRevocations)
|
|
641
|
+
) {
|
|
642
|
+
throw new TypeError("readRevocations is required");
|
|
643
|
+
}
|
|
644
|
+
const source = {
|
|
645
|
+
tenantId,
|
|
646
|
+
streamId,
|
|
647
|
+
async list({ afterSequence = 0, limit = 64 } = {}) {
|
|
648
|
+
const cursor = sequence(afterSequence, "afterSequence", {
|
|
649
|
+
allowZero: true,
|
|
650
|
+
});
|
|
651
|
+
if (!Number.isSafeInteger(limit) || limit < 1 || limit > 256) {
|
|
652
|
+
fail("limit must be between 1 and 256");
|
|
653
|
+
}
|
|
654
|
+
const raw = await readRevocations();
|
|
655
|
+
if (
|
|
656
|
+
!Array.isArray(raw) ||
|
|
657
|
+
utilTypes.isProxy(raw) ||
|
|
658
|
+
raw.length > 10_000
|
|
659
|
+
) {
|
|
660
|
+
fail("revocation source did not return a bounded list");
|
|
661
|
+
}
|
|
662
|
+
const all = raw
|
|
663
|
+
.map((entry) => normalizeRevocationOutcome(entry, tenantId, streamId))
|
|
664
|
+
.sort((left, right) => left.sequence - right.sequence);
|
|
665
|
+
for (let index = 1; index < all.length; index += 1) {
|
|
666
|
+
if (all[index - 1].sequence >= all[index].sequence) {
|
|
667
|
+
fail("revocation outcome sequences must be unique and increasing");
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
return freeze(
|
|
671
|
+
all.filter((entry) => entry.sequence > cursor).slice(0, limit),
|
|
672
|
+
);
|
|
673
|
+
},
|
|
674
|
+
};
|
|
675
|
+
SOURCES.add(source);
|
|
676
|
+
return freeze(source);
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
export function captureSkillWikiReconciliationSource(source) {
|
|
680
|
+
if (!SOURCES.has(source)) {
|
|
681
|
+
throw new TypeError(
|
|
682
|
+
"a branded skill Wiki reconciliation source is required",
|
|
683
|
+
);
|
|
684
|
+
}
|
|
685
|
+
return freeze({
|
|
686
|
+
tenantId: source.tenantId,
|
|
687
|
+
streamId: source.streamId,
|
|
688
|
+
list: source.list.bind(source),
|
|
689
|
+
});
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
function normalizeImpact(value, transition, tenantId) {
|
|
693
|
+
exact(value, IMPACT_KEYS, "skill Wiki impact resolution");
|
|
694
|
+
if (
|
|
695
|
+
value.schema !== SKILL_WIKI_IMPACT_RESOLUTION_SCHEMA ||
|
|
696
|
+
value.authenticated !== true ||
|
|
697
|
+
value.durable !== true ||
|
|
698
|
+
value.tenantId !== tenantId ||
|
|
699
|
+
value.transitionDigest !== transition.transitionDigest ||
|
|
700
|
+
value.candidateId !== transition.candidateId ||
|
|
701
|
+
value.skillName !== transition.skillName ||
|
|
702
|
+
value.wikiRevision !== transition.wikiRevision
|
|
703
|
+
) {
|
|
704
|
+
fail("skill Wiki impact resolution is not bound to the transition");
|
|
705
|
+
}
|
|
706
|
+
if (
|
|
707
|
+
!Array.isArray(value.patternRefs) ||
|
|
708
|
+
utilTypes.isProxy(value.patternRefs) ||
|
|
709
|
+
value.patternRefs.length > 128
|
|
710
|
+
) {
|
|
711
|
+
fail("impact patternRefs must be bounded");
|
|
712
|
+
}
|
|
713
|
+
const patternRefs = [
|
|
714
|
+
...new Set(value.patternRefs.map((ref) => string(ref, "patternRef", 128))),
|
|
715
|
+
].sort();
|
|
716
|
+
if (patternRefs.length !== value.patternRefs.length) {
|
|
717
|
+
fail("impact patternRefs must be unique");
|
|
718
|
+
}
|
|
719
|
+
if (transition.wikiRevision !== null && patternRefs.length === 0) {
|
|
720
|
+
fail("a Wiki-derived transition must resolve at least one pattern");
|
|
721
|
+
}
|
|
722
|
+
return freeze({
|
|
723
|
+
patternRefs,
|
|
724
|
+
reason: string(value.reason, "impact.reason", 1024),
|
|
725
|
+
receiptDigest: digest(value.receiptDigest, "impact.receiptDigest"),
|
|
726
|
+
});
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
function checkpointCore(
|
|
730
|
+
tenantId,
|
|
731
|
+
streamId,
|
|
732
|
+
cursor,
|
|
733
|
+
transitionDigest,
|
|
734
|
+
revisionId,
|
|
735
|
+
) {
|
|
736
|
+
return {
|
|
737
|
+
schema: SKILL_WIKI_RECONCILIATION_CHECKPOINT_SCHEMA,
|
|
738
|
+
tenantId,
|
|
739
|
+
streamId,
|
|
740
|
+
cursor,
|
|
741
|
+
lastTransitionDigest: transitionDigest,
|
|
742
|
+
lastWikiRevisionId: revisionId,
|
|
743
|
+
};
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
function normalizeCheckpoint(value, tenantId, streamId) {
|
|
747
|
+
if (value == null) return null;
|
|
748
|
+
exact(value, CHECKPOINT_KEYS, "skill Wiki reconciliation checkpoint");
|
|
749
|
+
const core = checkpointCore(
|
|
750
|
+
tenantId,
|
|
751
|
+
streamId,
|
|
752
|
+
sequence(value.cursor, "checkpoint.cursor"),
|
|
753
|
+
digest(value.lastTransitionDigest, "checkpoint.lastTransitionDigest"),
|
|
754
|
+
string(value.lastWikiRevisionId, "checkpoint.lastWikiRevisionId"),
|
|
755
|
+
);
|
|
756
|
+
if (
|
|
757
|
+
value.schema !== core.schema ||
|
|
758
|
+
value.authenticated !== true ||
|
|
759
|
+
value.durable !== true ||
|
|
760
|
+
value.tenantId !== tenantId ||
|
|
761
|
+
value.streamId !== streamId ||
|
|
762
|
+
value.checkpointDigest !== hash(core)
|
|
763
|
+
) {
|
|
764
|
+
fail("checkpoint is not durably tenant-bound");
|
|
765
|
+
}
|
|
766
|
+
return freeze({ ...core, checkpointDigest: value.checkpointDigest });
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
export class SkillWikiReconciler {
|
|
770
|
+
constructor({ source, maintainer, ports, crashHook = null } = {}) {
|
|
771
|
+
this.source = captureSkillWikiReconciliationSource(source);
|
|
772
|
+
if (!(maintainer instanceof EvidenceBackedWikiMaintainer)) {
|
|
773
|
+
throw new TypeError("EvidenceBackedWikiMaintainer is required");
|
|
774
|
+
}
|
|
775
|
+
if (maintainer.descriptor.tenantId !== this.source.tenantId) {
|
|
776
|
+
throw new TypeError("Wiki maintainer belongs to another tenant");
|
|
777
|
+
}
|
|
778
|
+
this._maintain = maintainer.maintain.bind(maintainer);
|
|
779
|
+
this._resolveImpact = capture(ports, "resolveImpact", "ports");
|
|
780
|
+
this._retainEvidence = capture(ports, "retainEvidence", "ports");
|
|
781
|
+
this._loadCheckpoint = capture(ports, "loadCheckpoint", "ports");
|
|
782
|
+
this._commitCheckpoint = capture(ports, "commitCheckpoint", "ports");
|
|
783
|
+
if (crashHook !== null && typeof crashHook !== "function") {
|
|
784
|
+
throw new TypeError("crashHook must be a function or null");
|
|
785
|
+
}
|
|
786
|
+
this._crashHook = crashHook;
|
|
787
|
+
Object.freeze(this);
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
async _checkpoint() {
|
|
791
|
+
return normalizeCheckpoint(
|
|
792
|
+
await this._loadCheckpoint({
|
|
793
|
+
tenantId: this.source.tenantId,
|
|
794
|
+
streamId: this.source.streamId,
|
|
795
|
+
}),
|
|
796
|
+
this.source.tenantId,
|
|
797
|
+
this.source.streamId,
|
|
798
|
+
);
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
async _commit(next, previous) {
|
|
802
|
+
try {
|
|
803
|
+
const receipt = await this._commitCheckpoint({
|
|
804
|
+
checkpoint: next,
|
|
805
|
+
expectedCheckpointDigest: previous?.checkpointDigest ?? null,
|
|
806
|
+
});
|
|
807
|
+
exact(receipt, CHECKPOINT_RECEIPT_KEYS, "checkpoint commit receipt");
|
|
808
|
+
if (
|
|
809
|
+
receipt?.authenticated !== true ||
|
|
810
|
+
receipt?.durable !== true ||
|
|
811
|
+
receipt?.committed !== true ||
|
|
812
|
+
receipt?.checkpointDigest !== next.checkpointDigest
|
|
813
|
+
) {
|
|
814
|
+
fail("checkpoint commit was not durably acknowledged");
|
|
815
|
+
}
|
|
816
|
+
} catch (cause) {
|
|
817
|
+
const recovered = await this._checkpoint();
|
|
818
|
+
if (recovered?.checkpointDigest !== next.checkpointDigest) {
|
|
819
|
+
fail("checkpoint commit could not be recovered", { cause });
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
async reconcile({ limit = 64 } = {}) {
|
|
825
|
+
let checkpoint = await this._checkpoint();
|
|
826
|
+
const transitions = await this.source.list({
|
|
827
|
+
afterSequence: checkpoint?.cursor ?? 0,
|
|
828
|
+
limit,
|
|
829
|
+
});
|
|
830
|
+
const results = [];
|
|
831
|
+
for (const transition of transitions) {
|
|
832
|
+
const impact = normalizeImpact(
|
|
833
|
+
await this._resolveImpact(transition),
|
|
834
|
+
transition,
|
|
835
|
+
this.source.tenantId,
|
|
836
|
+
);
|
|
837
|
+
const pilot = transition.schema === SKILL_WIKI_PILOT_OUTCOME_SCHEMA;
|
|
838
|
+
const revocation =
|
|
839
|
+
transition.schema === SKILL_WIKI_REVOCATION_OUTCOME_SCHEMA;
|
|
840
|
+
const rejected =
|
|
841
|
+
transition.schema === SKILL_WIKI_REVIEW_DECISION_SCHEMA ||
|
|
842
|
+
(pilot && transition.outcome === "rollback") ||
|
|
843
|
+
revocation;
|
|
844
|
+
const decision = {
|
|
845
|
+
candidateId: transition.candidateId,
|
|
846
|
+
skillName: transition.skillName,
|
|
847
|
+
outcome: rejected ? "rejected" : "accepted",
|
|
848
|
+
patternRefs: impact.patternRefs,
|
|
849
|
+
reason:
|
|
850
|
+
pilot || revocation || rejected ? transition.reason : impact.reason,
|
|
851
|
+
};
|
|
852
|
+
const sourceDigest =
|
|
853
|
+
pilot || revocation
|
|
854
|
+
? transition.sourceReceiptDigest
|
|
855
|
+
: rejected
|
|
856
|
+
? transition.decisionReceiptDigest
|
|
857
|
+
: transition.settlementDigest;
|
|
858
|
+
const evidenceCore = {
|
|
859
|
+
schema: WIKI_EVIDENCE_SCHEMA,
|
|
860
|
+
tenantId: this.source.tenantId,
|
|
861
|
+
ref: `wiki-evidence://skill-decision/${sourceDigest.slice(7)}`,
|
|
862
|
+
sourceDigest,
|
|
863
|
+
projectionDigest: hash({ transition, impact }),
|
|
864
|
+
artifactRef: pilot
|
|
865
|
+
? `skill-pilot://${this.source.tenantId}/${transition.pilotId}/${transition.sequence}`
|
|
866
|
+
: revocation
|
|
867
|
+
? `skill-revocation://${this.source.tenantId}/${transition.revocationId}/${transition.sequence}`
|
|
868
|
+
: rejected
|
|
869
|
+
? `skill-review://${this.source.tenantId}/${transition.decisionReceiptDigest.slice(7)}`
|
|
870
|
+
: `skill-release://${this.source.tenantId}/${transition.activeReleaseDigest.slice(7)}`,
|
|
871
|
+
trustedProjection: true,
|
|
872
|
+
trustDomain: `skill-registry:${this.source.streamId}`,
|
|
873
|
+
kind: "proposal-decision",
|
|
874
|
+
status: "active",
|
|
875
|
+
observedAt: transition.occurredAt,
|
|
876
|
+
expiresAt: null,
|
|
877
|
+
data: {
|
|
878
|
+
decisionDigest: hash(decision),
|
|
879
|
+
decision,
|
|
880
|
+
transitionDigest: transition.transitionDigest,
|
|
881
|
+
sourceDecisionDigest: sourceDigest,
|
|
882
|
+
impactReceiptDigest: impact.receiptDigest,
|
|
883
|
+
wikiRevision: transition.wikiRevision,
|
|
884
|
+
...(pilot
|
|
885
|
+
? {
|
|
886
|
+
pilotId: transition.pilotId,
|
|
887
|
+
pilotOutcome: transition.outcome,
|
|
888
|
+
descriptorDigest: transition.descriptorDigest,
|
|
889
|
+
activeStateDigest: transition.activeStateDigest,
|
|
890
|
+
evidenceReceiptDigests: transition.evidenceReceiptDigests,
|
|
891
|
+
}
|
|
892
|
+
: revocation
|
|
893
|
+
? {
|
|
894
|
+
revocationId: transition.revocationId,
|
|
895
|
+
revocationOutcome: transition.outcome,
|
|
896
|
+
activeStateDigest: transition.activeStateDigest,
|
|
897
|
+
evidenceReceiptDigests: transition.evidenceReceiptDigests,
|
|
898
|
+
}
|
|
899
|
+
: rejected
|
|
900
|
+
? { packetDigest: transition.packetDigest }
|
|
901
|
+
: {
|
|
902
|
+
settlementDigest: transition.settlementDigest,
|
|
903
|
+
activeReleaseDigest: transition.activeReleaseDigest,
|
|
904
|
+
stateDigest: transition.stateDigest,
|
|
905
|
+
}),
|
|
906
|
+
},
|
|
907
|
+
};
|
|
908
|
+
const evidence = freeze({
|
|
909
|
+
...evidenceCore,
|
|
910
|
+
envelopeDigest: hash(evidenceCore),
|
|
911
|
+
});
|
|
912
|
+
const retained = await this._retainEvidence(evidence);
|
|
913
|
+
exact(retained, RETENTION_KEYS, "evidence retention receipt");
|
|
914
|
+
if (
|
|
915
|
+
retained?.schema !== SKILL_WIKI_EVIDENCE_RETENTION_SCHEMA ||
|
|
916
|
+
retained.authenticated !== true ||
|
|
917
|
+
retained.durable !== true ||
|
|
918
|
+
retained.tenantId !== this.source.tenantId ||
|
|
919
|
+
retained.ref !== evidence.ref ||
|
|
920
|
+
retained.envelopeDigest !== evidence.envelopeDigest ||
|
|
921
|
+
!DIGEST.test(retained.receiptDigest ?? "")
|
|
922
|
+
) {
|
|
923
|
+
fail("proposal-decision evidence was not durably retained");
|
|
924
|
+
}
|
|
925
|
+
const requestDigest = hash({
|
|
926
|
+
transitionDigest: transition.transitionDigest,
|
|
927
|
+
evidenceRef: evidence.ref,
|
|
928
|
+
decision,
|
|
929
|
+
});
|
|
930
|
+
const maintenanceRequest = freeze({
|
|
931
|
+
schema: WIKI_MAINTENANCE_REQUEST_SCHEMA,
|
|
932
|
+
tenantId: this.source.tenantId,
|
|
933
|
+
requestId: `wiki-maintenance:${requestDigest.slice(7)}`,
|
|
934
|
+
requestDigest,
|
|
935
|
+
});
|
|
936
|
+
const maintained = await this._maintain({
|
|
937
|
+
evidenceRefs: [evidence.ref],
|
|
938
|
+
effectiveAt: transition.occurredAt,
|
|
939
|
+
maintenanceRequest,
|
|
940
|
+
});
|
|
941
|
+
if (
|
|
942
|
+
!WIKI_REVISION_ID.test(maintained?.revisionId ?? "") ||
|
|
943
|
+
!DIGEST.test(maintained.stateDigest ?? "")
|
|
944
|
+
) {
|
|
945
|
+
fail("Wiki maintenance did not return a committed revision");
|
|
946
|
+
}
|
|
947
|
+
if (this._crashHook) {
|
|
948
|
+
await this._crashHook(
|
|
949
|
+
"after-wiki-commit",
|
|
950
|
+
freeze({ transition, maintained }),
|
|
951
|
+
);
|
|
952
|
+
}
|
|
953
|
+
const core = checkpointCore(
|
|
954
|
+
this.source.tenantId,
|
|
955
|
+
this.source.streamId,
|
|
956
|
+
transition.sequence,
|
|
957
|
+
transition.transitionDigest,
|
|
958
|
+
maintained.revisionId,
|
|
959
|
+
);
|
|
960
|
+
const next = freeze({
|
|
961
|
+
...core,
|
|
962
|
+
authenticated: true,
|
|
963
|
+
durable: true,
|
|
964
|
+
checkpointDigest: hash(core),
|
|
965
|
+
});
|
|
966
|
+
await this._commit(next, checkpoint);
|
|
967
|
+
checkpoint = next;
|
|
968
|
+
results.push({
|
|
969
|
+
sequence: transition.sequence,
|
|
970
|
+
transitionDigest: transition.transitionDigest,
|
|
971
|
+
revisionId: maintained.revisionId,
|
|
972
|
+
recovered: maintained.recovered === true,
|
|
973
|
+
});
|
|
974
|
+
}
|
|
975
|
+
return freeze({
|
|
976
|
+
processed: results.length,
|
|
977
|
+
cursor: checkpoint?.cursor ?? 0,
|
|
978
|
+
results,
|
|
979
|
+
});
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
export function createSkillWikiReconciler(options) {
|
|
984
|
+
return new SkillWikiReconciler(options);
|
|
985
|
+
}
|