chainlesschain 0.166.22 → 0.166.25
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 +46 -3
- package/package.json +4 -3
- package/src/assets/web-panel/assets/{AIOps-oJ7USzMC.js → AIOps-RaxL_QQD.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-BlgnZe_C.js → ActionButton-DD3ieFO-.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-D2rRbTLu.js → Analytics-CATDJukS.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-FwS3f0B2.js → AppLayout-BHGsnRDS.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-iF-_08Hi.js → Artifacts-BL6NunjN.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-D24p0zQw.js → Audit-D0nEWfbA.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-Cg3mRVi9.js → BackgroundAgents-BAP1MUol.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-EOqht3H-.js → Backup-R4y2OeSi.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-9XWYq2hj.js → BaseInput-ByQZ2z6S.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-Dq5yardA.js → Chat-32uV--xF.js} +4 -4
- package/src/assets/web-panel/assets/ChatBubbleRenderer-t1enanwz.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-CuyCBoBf.js → Checkbox-D1CB-7bq.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-DjWtYHNe.js → Codegen-BPx3dQ2q.js} +1 -1
- package/src/assets/web-panel/assets/{Col-CrVr_iuG.js → Col-DkPTQ2Gl.js} +1 -1
- package/src/assets/web-panel/assets/{Community-C6QxpfGc.js → Community-ZriaxRlr.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-B-v5r6Pa.js → Compact-C_qJ0P7F.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-zNiLiFgD.js → Compliance-Bgoy-saS.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-D9K7lMOu.js → Cowork-B5i9y6XK.js} +2 -2
- package/src/assets/web-panel/assets/{Cron-DAjO36z4.js → Cron-D7vBJ5-J.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-Bxqn0aqB.js → Crosschain-D4kvoGI_.js} +1 -1
- package/src/assets/web-panel/assets/{DID-DfRmLUe-.js → DID-BLOeBd-r.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-Cz8KF3fr.js → Dashboard-mecJaonC.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-C4oVfkP0.js → Dropdown-GPKwaFer.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-ivyZKN8k.js → EmailListRenderer-BML9m7Dd.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-DoxY1CPW.js → FamilyGuardDashboard-DN5bAtJC.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-C93gZxnb.js → Federation-DmD6Gecd.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-D_lEjYJE.js → FormItemContext-6wwplN_K.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-BNFN9YjN.js → GenericCardRenderer-DUhpLkDL.js} +1 -1
- package/src/assets/web-panel/assets/{Git-mUu2HcLI.js → Git-eJfyXkwf.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-CNuosrge.js → Governance-swAUW59x.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-DwY5pbCB.js → Inference-CbdwJPDJ.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-aRUxhACD.js → KnowledgeGraph-UuYpg1nm.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-DFfsWYy_.js → Logs-CS0G057y.js} +2 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-BxIIB4k3.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-COI-ciM-.js → Marketplace-CZRjuvvI.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-BJJwaIpe.js → McpTools-BOJ9A_Rf.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-CDO6SGDZ.js → Memory-BnkrR-Ok.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-BlZ5tFf4.js → MobileBridge-Do4mPi13.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-DuoxbgWz.js → MobileProjects-2JxWa6-p.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-6ec9j70b.js → Mtc-CS_mnpGd.js} +2 -2
- package/src/assets/web-panel/assets/{MtcAudit-BuL7HkC7.js → MtcAudit-DZ4J_351.js} +5 -5
- package/src/assets/web-panel/assets/{Multisig-CJxR85lk.js → Multisig-Jh74zKXu.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-B71O1S4l.js → NLProgramming-_4n2BfnS.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-Bsw5zbpV.js → Notes-CtENcKHv.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-BnAhXuK_.js → NotificationSettings-dgDCvpK9.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-BJ0R5GGz.js → OrderTableRenderer-D5VxCrmG.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-B7wwNxoP.js → Organization-CpIF8Xkd.js} +2 -2
- package/src/assets/web-panel/assets/{Overflow-CfAGr0gM.js → Overflow-aHnBZaez.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-KhMg22Fz.js → P2P-8ppzog2V.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-NdAXI9ft.js → PdhVaultBrowser-D3p1BXkp.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-CIYjqyT7.js → Permissions-D7vflD5q.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-D2ht3P_R.js → PersonalDataHub-D2hY-Ek2.js} +4 -4
- package/src/assets/web-panel/assets/{Pipeline-i6flZW1m.js → Pipeline-qK2VqhJC.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-DE0lhYVc.js → Privacy-DHJr4uu0.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-BL3YbyxS.js → ProjectInit-DMBS6trm.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-CEtdg7ni.js → ProjectSettings-D3Ng74BT.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-CvtU5peJ.js → Projects-BfJFZiIW.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-DKt_Cg-j.js → Providers-DlNA95G0.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-DA61jNSx.js → QrScannerModal-CMOIYxIm.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-fS9ryUmq.js → QuickAsk-D6MyGp5I.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-CR9dZU5Y.js → Recommend-W6WcShtf.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-BV0BR2Dz.js → RemoteSession-Dm_MjlV_.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-BIeGUvYD.js → Reputation-Ctvij6eX.js} +1 -1
- package/src/assets/web-panel/assets/{Row-DHDT1aro.js → Row-DivbeDE-.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-Cq6YKb1h.js → RssFeed-D4famoAw.js} +3 -3
- package/src/assets/web-panel/assets/{Search-DEF6vsy6.js → Search-6gOAh3zG.js} +1 -1
- package/src/assets/web-panel/assets/{Security-CHtYiKY9.js → Security-DApb9kK8.js} +4 -4
- package/src/assets/web-panel/assets/{Services-u16lvBJN.js → Services-B8OomyE2.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-CGbizyDj.js → Skeleton-BTJ2g2E3.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-BZMQcAa7.js → Skills-NIRr4DD1.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-Bm-CycVi.js → Sla-BQHP_6px.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-BudpA5kr.js → SpeechSettings-BVQTDSVS.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-B8q1C1eC.js → SyncSettings-BOD4Mar6.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-SU1pBWc-.js → Tasks-Ciu7H2-y.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-CyOfJzmt.js → Templates-CtlwavRU.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-xqWSm2GP.js → Tenant-QLWYJdL6.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-D1Ttgjsi.js → Terminal-B3q10mjm.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-Da2lYs5D.js → TimelineRenderer-CqltBA_8.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-B34-SduO.js → Tokens-CJOKrj4y.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-C8zyYm4R.js → Trigger-CPMGgfdM.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-D1Pvqems.js → Trust-DiJms7Bl.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-Do3VVnAy.js → UkeySign-rakR8eel.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-Dz7egVIA.js → VideoEditing-DAWZUM5o.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-Dcuw-OxR.js → Wallet-DqUPnl7K.js} +3 -3
- package/src/assets/web-panel/assets/{WebAuthn-DPlw-QsB.js → WebAuthn-BnVUwvMm.js} +3 -3
- package/src/assets/web-panel/assets/{WorkflowEditor-h4OsnU5q.js → WorkflowEditor-B1CAwxgs.js} +1 -1
- package/src/assets/web-panel/assets/{chat-eO9wEwrW.js → chat-k2-0Jzfy.js} +1 -1
- package/src/assets/web-panel/assets/{colors-34lSmOXw.js → colors-BAu8xBmW.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-CK4kEWJ4.js → compact-item-DMlqcdfI.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-E0A57xed.js → createContext-BU9kfiSw.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-DuGrUMAS.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-BD9ZMGAl.js → hasIn-2vacgdcl.js} +1 -1
- package/src/assets/web-panel/assets/{index--N0u6kTG.js → index-B-C-Ruft.js} +1 -1
- package/src/assets/web-panel/assets/{index-DzXjP44T.js → index-B7wDjYUd.js} +1 -1
- package/src/assets/web-panel/assets/{index-CZBaqe3d.js → index-BMq0frKK.js} +1 -1
- package/src/assets/web-panel/assets/{index-DrOalGut.js → index-BUX4W-2v.js} +1 -1
- package/src/assets/web-panel/assets/{index-CT1_eRL-.js → index-BZz2eB33.js} +1 -1
- package/src/assets/web-panel/assets/{index-DrsDA_md.js → index-BblNQlaA.js} +1 -1
- package/src/assets/web-panel/assets/{index-DP-UZAQN.js → index-BdfKoqsK.js} +1 -1
- package/src/assets/web-panel/assets/{index-DiT_REby.js → index-Bf8YofPE.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cx3Jn1r0.js → index-Bn8tARil.js} +1 -1
- package/src/assets/web-panel/assets/{index-B0rkHxKK.js → index-Bpe2CJd-.js} +1 -1
- package/src/assets/web-panel/assets/{index-B_G_ElKO.js → index-BxctzdYQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-MIg5Z8qe.js → index-C24NoPpy.js} +1 -1
- package/src/assets/web-panel/assets/{index-BmNbU2Z6.js → index-C5C4kSi8.js} +1 -1
- package/src/assets/web-panel/assets/{index-BsGmo6v1.js → index-C6ICn9Y6.js} +1 -1
- package/src/assets/web-panel/assets/{index-CsrKJJcX.js → index-C8ldqZi6.js} +1 -1
- package/src/assets/web-panel/assets/{index-BbX_Dted.js → index-C9WsM29I.js} +1 -1
- package/src/assets/web-panel/assets/{index-Ch175NUw.js → index-CONPVaxw.js} +1 -1
- package/src/assets/web-panel/assets/{index-DONOUtlz.js → index-CPyYXKFB.js} +1 -1
- package/src/assets/web-panel/assets/{index-DFLE2qO9.js → index-CSvSf9px.js} +1 -1
- package/src/assets/web-panel/assets/{index-o8pYehRq.js → index-CXmpR6N3.js} +3 -3
- package/src/assets/web-panel/assets/{index-Cz3unNfL.js → index-Chybe7Ge.js} +1 -1
- package/src/assets/web-panel/assets/{index-yAGBu2E0.js → index-CyXmP3PW.js} +1 -1
- package/src/assets/web-panel/assets/{index-CuSau5ya.js → index-DCusBOqR.js} +1 -1
- package/src/assets/web-panel/assets/{index-DcE1BspQ.js → index-DH01oIaj.js} +1 -1
- package/src/assets/web-panel/assets/{index-DrSAAuJj.js → index-DHg3LMNP.js} +1 -1
- package/src/assets/web-panel/assets/{index-CZkFMeWL.js → index-DWLTSIka.js} +1 -1
- package/src/assets/web-panel/assets/{index-DvKcroix.js → index-DaUGdvtU.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bjs90Eh9.js → index-DcA-tEQd.js} +1 -1
- package/src/assets/web-panel/assets/{index-DGRxt5wj.js → index-DfWvcu4p.js} +1 -1
- package/src/assets/web-panel/assets/{index-DCn-ECvK.js → index-DmZNnZz7.js} +1 -1
- package/src/assets/web-panel/assets/index-DvFfMAux.js +1 -0
- package/src/assets/web-panel/assets/{index-8qMA1DWQ.js → index-JsyGqKmD.js} +1 -1
- package/src/assets/web-panel/assets/{index-D4bB_x_v.js → index-TtrpHmYx.js} +1 -1
- package/src/assets/web-panel/assets/{index-Brqc9Emx.js → index-Ygh0wmKz.js} +1 -1
- package/src/assets/web-panel/assets/{index-Da5fmOHB.js → index-dIYqw3f0.js} +1 -1
- package/src/assets/web-panel/assets/{index-DpfisY1g.js → index-hDHHJYno.js} +1 -1
- package/src/assets/web-panel/assets/index-n6p-1A77.js +1 -0
- package/src/assets/web-panel/assets/{index-DeXNCyQJ.js → index-oElehY4F.js} +1 -1
- package/src/assets/web-panel/assets/{index-DcbgVLOH.js → index-z4_YwZDW.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-DMTkAomF.js → initDefaultProps-B9OXWu2e.js} +1 -1
- package/src/assets/web-panel/assets/{motion-Cnti1F5g.js → motion-IQ47MCDQ.js} +1 -1
- package/src/assets/web-panel/assets/{move-CGxmHUga.js → move-CLCU4kjV.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-CuwwLoq7.js → mtc-parser-CXnVlSPq.js} +1 -1
- package/src/assets/web-panel/assets/{omit-BpdlTkPM.js → omit-BJjLXB0f.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-D7nWrThp.js → pickAttrs-BHdtvdy6.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-Bhx0TV8F.js → placementArrow-oq8X_Bwc.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-CZ1KesZh.js → responsiveObserve-DTD02LAO.js} +1 -1
- package/src/assets/web-panel/assets/{slide-CnldF8J6.js → slide-DbEeq8to.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-CZfo_GOA.js → statusUtils-Do2fy1CJ.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-B2QCcAv5.js → styleChecker-CFWD63T-.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-DzzjIS4J.js → useFlexGapSupport-BeozAWOo.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-B_atg9M0.js → useFs-0-rIgnBL.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-DhZs3QYN.js → usePersonalDataHub-CeiNoI31.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-DcePTYAm.js → vnode-Dj0ReRNg.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-BYmlnjRk.js → zoom-DD7MC4Dy.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-knowledge.js +40 -1
- 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 +21 -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/generated/cc-agent-protocol.schema.json +3 -1
- 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 +20 -2
- package/src/lazy-dispatch.js +6 -0
- 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 +94 -1
- package/src/lib/app-server/websocket-transport.js +15 -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 +437 -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 +32 -10
- package/src/lib/evolution/evidence-json-text.js +236 -0
- package/src/lib/evolution/evolution-artifact-ports.js +196 -21
- package/src/lib/evolution/evolution-deployment-loader.js +240 -2
- 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 +271 -37
- package/src/lib/evolution/evolution-file-witness.js +153 -30
- package/src/lib/evolution/evolution-ledger-ports.js +1219 -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-stage-output-ledger-adapter.js +333 -0
- package/src/lib/evolution/evolution-release-train.js +54 -6
- 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 +134 -26
- 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 +48 -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-inventory.js +392 -0
- package/src/lib/evolution/governed-knowledge-dependency-ledger-executor.js +217 -82
- package/src/lib/evolution/governed-knowledge-quarantine-release.js +1013 -0
- package/src/lib/evolution/governed-knowledge-record.js +148 -0
- package/src/lib/evolution/governed-knowledge-revocation-host.js +59 -0
- package/src/lib/evolution/governed-knowledge-revocation-record.js +135 -0
- package/src/lib/evolution/governed-knowledge-skill-rollback.js +510 -0
- package/src/lib/evolution/governed-knowledge-sync.js +181 -95
- package/src/lib/evolution/governed-knowledge-wiki-tombstone.js +516 -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 +283 -0
- package/src/lib/evolution/knowledge-wiki-source-provenance.js +360 -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 +43 -3
- 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 +168 -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 +8 -6
- package/src/lib/evolution/statistical-progressive-canary.js +165 -3
- 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 +822 -101
- 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 +109 -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 +80 -16
- 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-loop-guard.js +113 -0
- package/src/lib/read-file-page.js +191 -0
- package/src/lib/runnable-provider.js +2 -1
- package/src/lib/skill-retrieval-router.js +22 -1
- package/src/repl/agent-repl.js +133 -34
- package/src/runtime/agent-core.js +196 -74
- 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 +50 -6
- package/src/runtime/runtime-factory.js +41 -2
- package/src/assets/web-panel/assets/ChatBubbleRenderer-Ds3pA-ET.js +0 -1
- package/src/assets/web-panel/assets/MarkdownRenderer-DqTx7_u1.js +0 -1
- package/src/assets/web-panel/assets/devWarning-CF3xafX2.js +0 -1
- package/src/assets/web-panel/assets/index-C907rPwd.js +0 -1
- package/src/assets/web-panel/assets/index-wueRSK2d.js +0 -1
|
@@ -1,10 +1,15 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { resolveKnowledgeWikiSourceProvenance } from "./knowledge-wiki-source-provenance.js";
|
|
1
3
|
import {
|
|
4
|
+
EVOLUTION_ARTIFACT_MAX_CANONICAL_BYTES,
|
|
2
5
|
EVOLUTION_DURABLE_ARTIFACT_RECORD_SCHEMA,
|
|
3
6
|
isEvolutionLedgerArtifactResolver,
|
|
7
|
+
captureEvolutionLedgerBatchResolver,
|
|
4
8
|
} from "./evolution-artifact-ports.js";
|
|
5
9
|
import {
|
|
6
10
|
EVOLUTION_ARTIFACT_RESOLUTION_SCHEMA,
|
|
7
11
|
EVOLUTION_LEDGER_DOMAIN_EVENT_SCHEMA,
|
|
12
|
+
EVOLUTION_LEDGER_MAX_EVENTS,
|
|
8
13
|
} from "./evolution-ledger.js";
|
|
9
14
|
import {
|
|
10
15
|
WIKI_REVISION_SCHEMA,
|
|
@@ -15,13 +20,28 @@ import {
|
|
|
15
20
|
|
|
16
21
|
export const WIKI_LEDGER_EVENT_TYPE = "wiki.revision.committed";
|
|
17
22
|
export const WIKI_LEDGER_CONFLICT_CODE = "CC_EVOLUTION_WIKI_REVISION_CONFLICT";
|
|
18
|
-
|
|
23
|
+
import {
|
|
24
|
+
WIKI_LEDGER_CORRUPT_CODE,
|
|
25
|
+
verifyWikiRevision as verifyRevision,
|
|
26
|
+
verifyWikiRequestTransition as verifyRequestTransition,
|
|
27
|
+
} from "./wiki-revision-protocol.js";
|
|
28
|
+
export { WIKI_LEDGER_CORRUPT_CODE } from "./wiki-revision-protocol.js";
|
|
19
29
|
|
|
20
30
|
const DIGEST = /^sha256:[a-f0-9]{64}$/u;
|
|
21
31
|
const REVISION_ID = /^wiki:[a-f0-9]{64}$/u;
|
|
32
|
+
const READERS = new WeakMap();
|
|
33
|
+
|
|
34
|
+
function freeze(value) {
|
|
35
|
+
if (value && typeof value === "object" && !Object.isFrozen(value)) {
|
|
36
|
+
Object.freeze(value);
|
|
37
|
+
for (const child of Object.values(value)) freeze(child);
|
|
38
|
+
}
|
|
39
|
+
return value;
|
|
40
|
+
}
|
|
22
41
|
|
|
23
42
|
function requiredString(value, name) {
|
|
24
|
-
if (typeof value !== "string" || value.trim() === "")
|
|
43
|
+
if (typeof value !== "string" || value.trim() === "")
|
|
44
|
+
throw new TypeError(`${name} is required`);
|
|
25
45
|
return value;
|
|
26
46
|
}
|
|
27
47
|
|
|
@@ -33,39 +53,66 @@ function fail(code, message) {
|
|
|
33
53
|
|
|
34
54
|
function captureMethod(owner, name, label) {
|
|
35
55
|
const method = owner?.[name];
|
|
36
|
-
if (typeof method !== "function")
|
|
56
|
+
if (typeof method !== "function")
|
|
57
|
+
throw new TypeError(`${label}.${name} is required`);
|
|
37
58
|
return (...args) => Reflect.apply(method, owner, args);
|
|
38
59
|
}
|
|
39
60
|
|
|
40
61
|
function parseRecord(resolution, descriptor) {
|
|
41
|
-
if (
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
62
|
+
if (
|
|
63
|
+
resolution?.schema !== EVOLUTION_ARTIFACT_RESOLUTION_SCHEMA ||
|
|
64
|
+
resolution.authenticated !== true ||
|
|
65
|
+
resolution.found !== true ||
|
|
66
|
+
!DIGEST.test(resolution.digest ?? "") ||
|
|
67
|
+
!DIGEST.test(resolution.receiptDigest ?? "") ||
|
|
68
|
+
!Buffer.isBuffer(resolution.bytes) ||
|
|
69
|
+
resolution.bytes.length > EVOLUTION_ARTIFACT_MAX_CANONICAL_BYTES
|
|
70
|
+
) {
|
|
71
|
+
fail(
|
|
72
|
+
WIKI_LEDGER_CORRUPT_CODE,
|
|
73
|
+
"Wiki artifact resolution is not authenticated and complete",
|
|
74
|
+
);
|
|
45
75
|
}
|
|
46
76
|
let record;
|
|
47
77
|
try {
|
|
48
|
-
record = JSON.parse(
|
|
78
|
+
record = JSON.parse(
|
|
79
|
+
new TextDecoder("utf-8", { fatal: true }).decode(resolution.bytes),
|
|
80
|
+
);
|
|
49
81
|
} catch {
|
|
50
82
|
fail(WIKI_LEDGER_CORRUPT_CODE, "Wiki artifact is not canonical JSON");
|
|
51
83
|
}
|
|
52
84
|
const revision = record?.value;
|
|
53
|
-
if (
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
85
|
+
if (
|
|
86
|
+
record?.schema !== EVOLUTION_DURABLE_ARTIFACT_RECORD_SCHEMA ||
|
|
87
|
+
record.tenantId !== descriptor.artifactTenantId ||
|
|
88
|
+
record.audience !== descriptor.audience ||
|
|
89
|
+
record.purpose !== descriptor.purpose ||
|
|
90
|
+
record.retention !== "ledger" ||
|
|
91
|
+
record.type !== "wiki-revision" ||
|
|
92
|
+
revision?.schema !== WIKI_REVISION_SCHEMA ||
|
|
93
|
+
revision.tenantId !== descriptor.tenantId ||
|
|
94
|
+
revision.evolutionRunId !== descriptor.evolutionRunId ||
|
|
95
|
+
revision.state?.schema !== WIKI_STATE_SCHEMA ||
|
|
96
|
+
revision.state.tenantId !== descriptor.tenantId ||
|
|
97
|
+
revision.stateDigest !== digestWikiState(revision.state) ||
|
|
98
|
+
revision.state.revisionId !== revision.revisionId ||
|
|
99
|
+
!REVISION_ID.test(revision.revisionId ?? "")
|
|
100
|
+
) {
|
|
101
|
+
fail(
|
|
102
|
+
WIKI_LEDGER_CORRUPT_CODE,
|
|
103
|
+
"Wiki artifact record or revision binding is invalid",
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
return verifyRevision(revision, descriptor);
|
|
63
107
|
}
|
|
64
108
|
|
|
65
109
|
function normalizeDescriptor(input) {
|
|
66
110
|
return Object.freeze({
|
|
67
111
|
tenantId: requiredString(input?.tenantId, "tenantId"),
|
|
68
|
-
artifactTenantId: requiredString(
|
|
112
|
+
artifactTenantId: requiredString(
|
|
113
|
+
input?.artifactTenantId,
|
|
114
|
+
"artifactTenantId",
|
|
115
|
+
),
|
|
69
116
|
evolutionRunId: requiredString(input?.evolutionRunId, "evolutionRunId"),
|
|
70
117
|
audience: requiredString(input?.audience, "audience"),
|
|
71
118
|
purpose: requiredString(input?.purpose, "purpose"),
|
|
@@ -73,128 +120,802 @@ function normalizeDescriptor(input) {
|
|
|
73
120
|
}
|
|
74
121
|
|
|
75
122
|
export class WikiMaintainerLedgerAdapter {
|
|
76
|
-
|
|
123
|
+
#putCanonical;
|
|
124
|
+
#readLedger;
|
|
125
|
+
#verifyLedger;
|
|
126
|
+
#appendDomainEvent;
|
|
127
|
+
#resolveArtifact;
|
|
128
|
+
#resolveArtifactBatch;
|
|
129
|
+
|
|
130
|
+
constructor({
|
|
131
|
+
descriptor,
|
|
132
|
+
artifactPorts,
|
|
133
|
+
ledger,
|
|
134
|
+
ledgerArtifactResolver,
|
|
135
|
+
} = {}) {
|
|
77
136
|
this.descriptor = normalizeDescriptor(descriptor);
|
|
78
|
-
this
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
137
|
+
this.#putCanonical = captureMethod(
|
|
138
|
+
artifactPorts,
|
|
139
|
+
"putCanonical",
|
|
140
|
+
"artifactPorts",
|
|
141
|
+
);
|
|
142
|
+
this.#readLedger = captureMethod(ledger, "read", "ledger");
|
|
143
|
+
this.#verifyLedger = captureMethod(ledger, "verify", "ledger");
|
|
144
|
+
this.#appendDomainEvent = captureMethod(
|
|
145
|
+
ledger,
|
|
146
|
+
"appendDomainEvent",
|
|
147
|
+
"ledger",
|
|
148
|
+
);
|
|
82
149
|
if (!isEvolutionLedgerArtifactResolver(ledgerArtifactResolver)) {
|
|
83
|
-
throw new TypeError(
|
|
150
|
+
throw new TypeError(
|
|
151
|
+
"a branded EvolutionArtifactPorts ledger resolver is required",
|
|
152
|
+
);
|
|
84
153
|
}
|
|
85
|
-
this
|
|
154
|
+
this.#resolveArtifact = ledgerArtifactResolver;
|
|
155
|
+
this.#resolveArtifactBatch = captureEvolutionLedgerBatchResolver(
|
|
156
|
+
ledgerArtifactResolver,
|
|
157
|
+
);
|
|
86
158
|
Object.freeze(this);
|
|
159
|
+
READERS.set(
|
|
160
|
+
this,
|
|
161
|
+
Object.freeze({
|
|
162
|
+
descriptor: this.descriptor,
|
|
163
|
+
matchesLedger: (candidate) => candidate === ledger,
|
|
164
|
+
loadWiki: () => this.#loadWiki(),
|
|
165
|
+
readInventory: () => this.#readInventory(),
|
|
166
|
+
readRevision: (input) => this.#readRevision(input),
|
|
167
|
+
readKnowledgeProvenance: (input) =>
|
|
168
|
+
this.#readKnowledgeProvenance(input),
|
|
169
|
+
readStateRevision: (input) => this.#readStateRevision(input),
|
|
170
|
+
findStateRevision: (input) => this.#readStateRevision(input, false),
|
|
171
|
+
resolveHistory: (input) => this.#resolveHistory(input),
|
|
172
|
+
resolveAtCheckpoint: (input) => this.#resolveHistory(input, true),
|
|
173
|
+
}),
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
#history({
|
|
178
|
+
sourceDigest = null,
|
|
179
|
+
allowed = [],
|
|
180
|
+
checkpoint = null,
|
|
181
|
+
inventory = false,
|
|
182
|
+
revisionId = null,
|
|
183
|
+
stateRevisionDigest = null,
|
|
184
|
+
} = {}) {
|
|
185
|
+
// read() already authenticates its snapshot. Resolve against that snapshot's
|
|
186
|
+
// identity, then compare the entire event range with a fresh authority head.
|
|
187
|
+
// This avoids a redundant pre-read scan without caching authorization.
|
|
188
|
+
const events = this.#readLedger({ limit: EVOLUTION_LEDGER_MAX_EVENTS });
|
|
189
|
+
if (!Array.isArray(events) || events.length > EVOLUTION_LEDGER_MAX_EVENTS)
|
|
190
|
+
fail(
|
|
191
|
+
WIKI_LEDGER_CORRUPT_CODE,
|
|
192
|
+
"EvolutionLedger read did not return events",
|
|
193
|
+
);
|
|
194
|
+
const tail = events.at(-1);
|
|
195
|
+
if (checkpoint) {
|
|
196
|
+
const boundary = events[checkpoint.sequence - 1];
|
|
197
|
+
if (
|
|
198
|
+
!boundary ||
|
|
199
|
+
["epoch", "ledgerId", "identityDigest"].some(
|
|
200
|
+
(key) => checkpoint[key] !== boundary[key],
|
|
201
|
+
) ||
|
|
202
|
+
checkpoint.headDigest !== boundary.eventDigest
|
|
203
|
+
) {
|
|
204
|
+
fail(
|
|
205
|
+
WIKI_LEDGER_CONFLICT_CODE,
|
|
206
|
+
"Wiki checkpoint is not in this authenticated ledger",
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
if (
|
|
211
|
+
tail &&
|
|
212
|
+
(typeof tail.epoch !== "string" ||
|
|
213
|
+
typeof tail.ledgerId !== "string" ||
|
|
214
|
+
!DIGEST.test(tail.identityDigest ?? "") ||
|
|
215
|
+
!DIGEST.test(tail.eventDigest ?? "") ||
|
|
216
|
+
events.some(
|
|
217
|
+
(event, index) =>
|
|
218
|
+
event.sequence !== index + 1 ||
|
|
219
|
+
event.epoch !== tail.epoch ||
|
|
220
|
+
event.ledgerId !== tail.ledgerId ||
|
|
221
|
+
event.identityDigest !== tail.identityDigest,
|
|
222
|
+
))
|
|
223
|
+
) {
|
|
224
|
+
fail(
|
|
225
|
+
WIKI_LEDGER_CORRUPT_CODE,
|
|
226
|
+
"Wiki ledger read has incomplete sequence or identity bindings",
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
const matches = events.filter(
|
|
230
|
+
(event) =>
|
|
231
|
+
event.schema === EVOLUTION_LEDGER_DOMAIN_EVENT_SCHEMA &&
|
|
232
|
+
event.type === WIKI_LEDGER_EVENT_TYPE &&
|
|
233
|
+
event.tenantId === this.descriptor.tenantId &&
|
|
234
|
+
event.correlationId === this.descriptor.evolutionRunId,
|
|
235
|
+
);
|
|
236
|
+
const tenantWikiRunIds = [
|
|
237
|
+
...new Set(
|
|
238
|
+
events
|
|
239
|
+
.filter(
|
|
240
|
+
(event) =>
|
|
241
|
+
event.schema === EVOLUTION_LEDGER_DOMAIN_EVENT_SCHEMA &&
|
|
242
|
+
event.type === WIKI_LEDGER_EVENT_TYPE &&
|
|
243
|
+
event.tenantId === this.descriptor.tenantId,
|
|
244
|
+
)
|
|
245
|
+
.map((event) => requiredString(event.correlationId, "correlationId")),
|
|
246
|
+
),
|
|
247
|
+
].sort();
|
|
248
|
+
let state = createEmptyWikiState(this.descriptor.tenantId);
|
|
249
|
+
let viewState = state;
|
|
250
|
+
let latest = null;
|
|
251
|
+
let selectedRevision = null;
|
|
252
|
+
let source = sourceDigest === digestWikiState(state) ? state : null;
|
|
253
|
+
const successors = [];
|
|
254
|
+
const revisions = [];
|
|
255
|
+
let retainedBytes = 0;
|
|
256
|
+
let batch = [];
|
|
257
|
+
for (const [index, event] of matches.entries()) {
|
|
258
|
+
const previous = latest;
|
|
259
|
+
if (
|
|
260
|
+
!Number.isSafeInteger(event.sequence) ||
|
|
261
|
+
event.sequence <= (previous?.event.sequence ?? 0) ||
|
|
262
|
+
event.artifactTenantId !== this.descriptor.artifactTenantId ||
|
|
263
|
+
event.decision !== "committed" ||
|
|
264
|
+
event.skillName !== null ||
|
|
265
|
+
!Array.isArray(event.sourceRefs) ||
|
|
266
|
+
digestWikiState(event.sourceRefs) !==
|
|
267
|
+
digestWikiState(previous ? [previous.event.subjectRef] : [])
|
|
268
|
+
) {
|
|
269
|
+
fail(WIKI_LEDGER_CORRUPT_CODE, "Wiki ledger event lineage is invalid");
|
|
270
|
+
}
|
|
271
|
+
// Four revisions at most (4 MiB of payload), retained only while this
|
|
272
|
+
// synchronous chunk is checked. Full index readback and fresh authority
|
|
273
|
+
// remain inside each batch; no snapshot survives this history read.
|
|
274
|
+
if (index % 4 === 0)
|
|
275
|
+
batch = this.#resolveArtifactBatch(
|
|
276
|
+
matches.slice(index, index + 4).map((item) => ({
|
|
277
|
+
epoch: tail.epoch,
|
|
278
|
+
ledgerId: tail.ledgerId,
|
|
279
|
+
ref: item.subjectRef,
|
|
280
|
+
tenantId: this.descriptor.artifactTenantId,
|
|
281
|
+
})),
|
|
282
|
+
);
|
|
283
|
+
const revision = this.#resolveEvent(event, tail, batch[index % 4]);
|
|
284
|
+
const inView =
|
|
285
|
+
checkpoint === null || event.sequence <= checkpoint.sequence;
|
|
286
|
+
// Before durable maintenance requests, v1 genesis did not contain that
|
|
287
|
+
// map. Accept only the exact known legacy genesis, never an arbitrary
|
|
288
|
+
// caller-supplied predecessor or a modern revision with missing fields.
|
|
289
|
+
if (
|
|
290
|
+
!previous &&
|
|
291
|
+
!Object.hasOwn(revision, "maintenanceRequestId") &&
|
|
292
|
+
!Object.hasOwn(revision.state, "maintenanceRequests") &&
|
|
293
|
+
revision.priorStateDigest !== digestWikiState(state)
|
|
294
|
+
) {
|
|
295
|
+
const legacyGenesis = {
|
|
296
|
+
...createEmptyWikiState(this.descriptor.tenantId),
|
|
297
|
+
};
|
|
298
|
+
delete legacyGenesis.maintenanceRequests;
|
|
299
|
+
if (revision.priorStateDigest === digestWikiState(legacyGenesis)) {
|
|
300
|
+
state = freeze(legacyGenesis);
|
|
301
|
+
if (inView) {
|
|
302
|
+
viewState = state;
|
|
303
|
+
source = sourceDigest === revision.priorStateDigest ? state : null;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
if (
|
|
308
|
+
revision.revision !== state.revision + 1 ||
|
|
309
|
+
revision.priorStateDigest !== digestWikiState(state) ||
|
|
310
|
+
event.eventId !== `wiki.revision.${revision.revisionId.slice(5)}` ||
|
|
311
|
+
event.timestamp !== revision.effectiveAt
|
|
312
|
+
) {
|
|
313
|
+
fail(
|
|
314
|
+
WIKI_LEDGER_CORRUPT_CODE,
|
|
315
|
+
"Wiki revision does not extend its authenticated predecessor",
|
|
316
|
+
);
|
|
317
|
+
}
|
|
318
|
+
verifyRequestTransition(state, revision);
|
|
319
|
+
if (inventory) {
|
|
320
|
+
const wikiSourceRevisionIds = [
|
|
321
|
+
...new Set(
|
|
322
|
+
Object.values(revision.state.evidence)
|
|
323
|
+
.flatMap((entry) => [entry.ref, entry.artifactRef])
|
|
324
|
+
.filter(
|
|
325
|
+
(ref) =>
|
|
326
|
+
typeof ref === "string" &&
|
|
327
|
+
ref.startsWith(`wiki-source://${this.descriptor.tenantId}/wiki:`),
|
|
328
|
+
)
|
|
329
|
+
.map((ref) => ref.slice(ref.lastIndexOf("/") + 1)),
|
|
330
|
+
),
|
|
331
|
+
].sort();
|
|
332
|
+
revisions.push(
|
|
333
|
+
freeze({
|
|
334
|
+
revision: revision.revision,
|
|
335
|
+
revisionId: revision.revisionId,
|
|
336
|
+
priorStateDigest: revision.priorStateDigest,
|
|
337
|
+
stateDigest: revision.stateDigest,
|
|
338
|
+
artifactRef: event.subjectRef,
|
|
339
|
+
wikiSourceRevisionIds,
|
|
340
|
+
checkpoint: {
|
|
341
|
+
epoch: event.epoch,
|
|
342
|
+
ledgerId: event.ledgerId,
|
|
343
|
+
identityDigest: event.identityDigest,
|
|
344
|
+
sequence: event.sequence,
|
|
345
|
+
headDigest: event.eventDigest,
|
|
346
|
+
},
|
|
347
|
+
}),
|
|
348
|
+
);
|
|
349
|
+
}
|
|
350
|
+
if (
|
|
351
|
+
revision.revisionId === revisionId ||
|
|
352
|
+
revision.stateDigest === stateRevisionDigest
|
|
353
|
+
) {
|
|
354
|
+
if (selectedRevision)
|
|
355
|
+
fail(WIKI_LEDGER_CORRUPT_CODE, "Wiki revision identity is ambiguous");
|
|
356
|
+
selectedRevision = {
|
|
357
|
+
trusted: true,
|
|
358
|
+
state: revision.state,
|
|
359
|
+
stateDigest: revision.stateDigest,
|
|
360
|
+
revisionId: revision.revisionId,
|
|
361
|
+
checkpoint: {
|
|
362
|
+
epoch: event.epoch,
|
|
363
|
+
ledgerId: event.ledgerId,
|
|
364
|
+
identityDigest: event.identityDigest,
|
|
365
|
+
sequence: event.sequence,
|
|
366
|
+
headDigest: event.eventDigest,
|
|
367
|
+
},
|
|
368
|
+
artifactRef: event.subjectRef,
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
if (source && inView) {
|
|
372
|
+
if (
|
|
373
|
+
!revision.maintenanceRequestDigest ||
|
|
374
|
+
revision.maintenanceRequestDigest !== allowed[successors.length]
|
|
375
|
+
) {
|
|
376
|
+
fail(
|
|
377
|
+
WIKI_LEDGER_CONFLICT_CODE,
|
|
378
|
+
"Wiki has successors outside the authorized maintenance sequence",
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
retainedBytes += Buffer.byteLength(JSON.stringify(revision), "utf8");
|
|
382
|
+
if (retainedBytes > 8 * EVOLUTION_ARTIFACT_MAX_CANONICAL_BYTES) {
|
|
383
|
+
fail(
|
|
384
|
+
WIKI_LEDGER_CORRUPT_CODE,
|
|
385
|
+
"Wiki successor history exceeds its retained byte budget",
|
|
386
|
+
);
|
|
387
|
+
}
|
|
388
|
+
successors.push({
|
|
389
|
+
revision,
|
|
390
|
+
eventDigest: event.eventDigest,
|
|
391
|
+
artifactRef: event.subjectRef,
|
|
392
|
+
predecessorHead: {
|
|
393
|
+
epoch: event.epoch,
|
|
394
|
+
ledgerId: event.ledgerId,
|
|
395
|
+
identityDigest: event.identityDigest,
|
|
396
|
+
sequence: event.sequence - 1,
|
|
397
|
+
headDigest: event.prevDigest,
|
|
398
|
+
},
|
|
399
|
+
});
|
|
400
|
+
} else if (inView && sourceDigest === revision.stateDigest) {
|
|
401
|
+
source = revision.state;
|
|
402
|
+
}
|
|
403
|
+
if (inView) viewState = revision.state;
|
|
404
|
+
latest = { event, revision };
|
|
405
|
+
state = revision.state;
|
|
406
|
+
}
|
|
407
|
+
const head = this.#verifyLedger();
|
|
408
|
+
if (
|
|
409
|
+
head.sequence !== events.length ||
|
|
410
|
+
head.headDigest !== (tail?.eventDigest ?? null) ||
|
|
411
|
+
(tail &&
|
|
412
|
+
["identityDigest", "epoch", "ledgerId"].some(
|
|
413
|
+
(key) => tail[key] !== head[key],
|
|
414
|
+
))
|
|
415
|
+
) {
|
|
416
|
+
fail(
|
|
417
|
+
WIKI_LEDGER_CONFLICT_CODE,
|
|
418
|
+
"Wiki ledger changed while authenticating history",
|
|
419
|
+
);
|
|
420
|
+
}
|
|
421
|
+
return {
|
|
422
|
+
head,
|
|
423
|
+
latest,
|
|
424
|
+
state,
|
|
425
|
+
viewState,
|
|
426
|
+
source,
|
|
427
|
+
successors,
|
|
428
|
+
selectedRevision,
|
|
429
|
+
revisions,
|
|
430
|
+
tenantWikiRunIds,
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
#readInventory() {
|
|
435
|
+
const { head, revisions, tenantWikiRunIds } = this.#history({
|
|
436
|
+
inventory: true,
|
|
437
|
+
});
|
|
438
|
+
return freeze({
|
|
439
|
+
authenticated: true,
|
|
440
|
+
descriptor: this.descriptor,
|
|
441
|
+
ledgerHead: head,
|
|
442
|
+
revisions,
|
|
443
|
+
tenantWikiRunIds,
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
#readKnowledgeProvenance({
|
|
448
|
+
tenantId,
|
|
449
|
+
revisionId,
|
|
450
|
+
knowledgeId,
|
|
451
|
+
contentDigest,
|
|
452
|
+
} = {}) {
|
|
453
|
+
if (
|
|
454
|
+
tenantId !== this.descriptor.tenantId ||
|
|
455
|
+
!REVISION_ID.test(revisionId ?? "") ||
|
|
456
|
+
typeof knowledgeId !== "string" ||
|
|
457
|
+
!/^[A-Za-z0-9][A-Za-z0-9._:@/-]{0,255}$/u.test(knowledgeId) ||
|
|
458
|
+
!DIGEST.test(contentDigest ?? "")
|
|
459
|
+
)
|
|
460
|
+
throw new TypeError(
|
|
461
|
+
"Wiki Knowledge provenance requires exact source identities",
|
|
462
|
+
);
|
|
463
|
+
const events = this.#readLedger({ limit: EVOLUTION_LEDGER_MAX_EVENTS });
|
|
464
|
+
const tail = Array.isArray(events) ? events.at(-1) : null;
|
|
465
|
+
if (
|
|
466
|
+
!tail ||
|
|
467
|
+
events.length > EVOLUTION_LEDGER_MAX_EVENTS ||
|
|
468
|
+
events.some(
|
|
469
|
+
(event, index) =>
|
|
470
|
+
event.sequence !== index + 1 ||
|
|
471
|
+
["epoch", "ledgerId", "identityDigest"].some(
|
|
472
|
+
(key) => event[key] !== tail[key],
|
|
473
|
+
),
|
|
474
|
+
)
|
|
475
|
+
)
|
|
476
|
+
fail(
|
|
477
|
+
WIKI_LEDGER_CORRUPT_CODE,
|
|
478
|
+
"Wiki provenance event range is incomplete",
|
|
479
|
+
);
|
|
480
|
+
const selected = events.find(
|
|
481
|
+
(event) =>
|
|
482
|
+
event.eventId === `wiki.revision.${revisionId.slice(5)}` &&
|
|
483
|
+
event.tenantId === tenantId,
|
|
484
|
+
);
|
|
485
|
+
const sources = events.filter(
|
|
486
|
+
(event) =>
|
|
487
|
+
event.type === WIKI_LEDGER_EVENT_TYPE &&
|
|
488
|
+
event.tenantId === tenantId &&
|
|
489
|
+
event.sequence <= (selected?.sequence ?? 0),
|
|
490
|
+
);
|
|
491
|
+
const positions = new Map(
|
|
492
|
+
sources.map((event, index) => [event.sequence, index]),
|
|
493
|
+
);
|
|
494
|
+
// Same bounded four-subject read as normal Wiki history. Retain no proof
|
|
495
|
+
// across calls and never resolve a future revision as an earlier source.
|
|
496
|
+
let batchStart = -1;
|
|
497
|
+
let batch = [];
|
|
498
|
+
const proof = resolveKnowledgeWikiSourceProvenance({
|
|
499
|
+
events,
|
|
500
|
+
descriptor: this.descriptor,
|
|
501
|
+
revisionId,
|
|
502
|
+
knowledge: { knowledgeId, contentDigest },
|
|
503
|
+
resolveSubject: (event) => {
|
|
504
|
+
const position = positions.get(event.sequence);
|
|
505
|
+
const start = position - (position % 4);
|
|
506
|
+
if (start !== batchStart) {
|
|
507
|
+
batch = this.#resolveArtifactBatch(
|
|
508
|
+
sources.slice(start, start + 4).map((item) => ({
|
|
509
|
+
epoch: tail.epoch,
|
|
510
|
+
ledgerId: tail.ledgerId,
|
|
511
|
+
tenantId: this.descriptor.artifactTenantId,
|
|
512
|
+
ref: item.subjectRef,
|
|
513
|
+
})),
|
|
514
|
+
);
|
|
515
|
+
batchStart = start;
|
|
516
|
+
}
|
|
517
|
+
const resolution = batch[position - start];
|
|
518
|
+
if (
|
|
519
|
+
resolution?.schema !== EVOLUTION_ARTIFACT_RESOLUTION_SCHEMA ||
|
|
520
|
+
resolution.authenticated !== true ||
|
|
521
|
+
resolution.found !== true ||
|
|
522
|
+
resolution.ref !== event.subjectRef.ref ||
|
|
523
|
+
resolution.digest !== event.subjectRef.digest ||
|
|
524
|
+
!DIGEST.test(resolution.receiptDigest ?? "") ||
|
|
525
|
+
!Buffer.isBuffer(resolution.bytes) ||
|
|
526
|
+
resolution.bytes.length > EVOLUTION_ARTIFACT_MAX_CANONICAL_BYTES ||
|
|
527
|
+
`sha256:${createHash("sha256").update(resolution.bytes).digest("hex")}` !==
|
|
528
|
+
event.subjectRef.digest
|
|
529
|
+
)
|
|
530
|
+
fail(
|
|
531
|
+
WIKI_LEDGER_CORRUPT_CODE,
|
|
532
|
+
"Wiki provenance subject is not authenticated and exactly bound",
|
|
533
|
+
);
|
|
534
|
+
return resolution.bytes;
|
|
535
|
+
},
|
|
536
|
+
});
|
|
537
|
+
const head = this.#verifyLedger();
|
|
538
|
+
if (
|
|
539
|
+
head.sequence !== events.length ||
|
|
540
|
+
head.headDigest !== tail.eventDigest ||
|
|
541
|
+
["epoch", "ledgerId", "identityDigest"].some(
|
|
542
|
+
(key) => head[key] !== tail[key],
|
|
543
|
+
)
|
|
544
|
+
)
|
|
545
|
+
fail(
|
|
546
|
+
WIKI_LEDGER_CONFLICT_CODE,
|
|
547
|
+
"Wiki ledger changed while authenticating source provenance",
|
|
548
|
+
);
|
|
549
|
+
return freeze({
|
|
550
|
+
authenticated: true,
|
|
551
|
+
tenantId,
|
|
552
|
+
...proof,
|
|
553
|
+
ledgerHead: head,
|
|
554
|
+
});
|
|
87
555
|
}
|
|
88
556
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
557
|
+
// Immutable provenance, not an authorization to use an obsolete Wiki as current.
|
|
558
|
+
// Authenticate the full present history, retaining only the selected revision.
|
|
559
|
+
#readRevision({ tenantId, revisionId } = {}) {
|
|
560
|
+
if (
|
|
561
|
+
tenantId !== this.descriptor.tenantId ||
|
|
562
|
+
!REVISION_ID.test(revisionId ?? "")
|
|
563
|
+
)
|
|
564
|
+
throw new TypeError(
|
|
565
|
+
"Wiki provenance requires an exact tenant and revisionId",
|
|
566
|
+
);
|
|
567
|
+
const { head, selectedRevision } = this.#history({ revisionId });
|
|
568
|
+
if (!selectedRevision)
|
|
569
|
+
fail(
|
|
570
|
+
WIKI_LEDGER_CONFLICT_CODE,
|
|
571
|
+
"Wiki revision is not in authenticated history",
|
|
572
|
+
);
|
|
573
|
+
return freeze({
|
|
574
|
+
authenticated: true,
|
|
575
|
+
tenantId,
|
|
576
|
+
evolutionRunId: this.descriptor.evolutionRunId,
|
|
577
|
+
...selectedRevision,
|
|
578
|
+
ledgerHead: head,
|
|
579
|
+
});
|
|
95
580
|
}
|
|
96
581
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
582
|
+
// Content-addressed original state lookup, without authorizing intervening
|
|
583
|
+
// changes. Effect consumers still replay their exact permitted successors.
|
|
584
|
+
#readStateRevision({ tenantId, stateDigest } = {}, required = true) {
|
|
585
|
+
if (
|
|
586
|
+
tenantId !== this.descriptor.tenantId ||
|
|
587
|
+
!DIGEST.test(stateDigest ?? "")
|
|
588
|
+
)
|
|
589
|
+
throw new TypeError(
|
|
590
|
+
"Wiki source requires an exact tenant and state digest",
|
|
591
|
+
);
|
|
592
|
+
const { head, selectedRevision } = this.#history({
|
|
593
|
+
stateRevisionDigest: stateDigest,
|
|
594
|
+
});
|
|
595
|
+
// A scoped lookup may prove absence only after authenticating the complete
|
|
596
|
+
// run. Corrupt/missing bytes and concurrent ledger changes still throw.
|
|
597
|
+
if (!selectedRevision && !required) return null;
|
|
598
|
+
if (!selectedRevision)
|
|
599
|
+
fail(
|
|
600
|
+
WIKI_LEDGER_CONFLICT_CODE,
|
|
601
|
+
"Wiki state revision is not in authenticated history",
|
|
602
|
+
);
|
|
603
|
+
return freeze({
|
|
604
|
+
authenticated: true,
|
|
605
|
+
tenantId,
|
|
606
|
+
evolutionRunId: this.descriptor.evolutionRunId,
|
|
607
|
+
...selectedRevision,
|
|
608
|
+
ledgerHead: head,
|
|
104
609
|
});
|
|
105
|
-
|
|
106
|
-
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
#resolveEvent(event, authority, capturedResolution = null) {
|
|
613
|
+
const resolution =
|
|
614
|
+
capturedResolution ??
|
|
615
|
+
this.#resolveArtifact({
|
|
616
|
+
epoch: authority.epoch,
|
|
617
|
+
ledgerId: authority.ledgerId,
|
|
618
|
+
ref: event.subjectRef,
|
|
619
|
+
tenantId: this.descriptor.artifactTenantId,
|
|
620
|
+
});
|
|
621
|
+
if (
|
|
622
|
+
resolution?.ref !== event.subjectRef.ref ||
|
|
623
|
+
resolution.digest !== event.subjectRef.digest
|
|
624
|
+
) {
|
|
625
|
+
fail(
|
|
626
|
+
WIKI_LEDGER_CORRUPT_CODE,
|
|
627
|
+
"Wiki ledger event resolved a substituted artifact",
|
|
628
|
+
);
|
|
107
629
|
}
|
|
108
630
|
return parseRecord(resolution, this.descriptor);
|
|
109
631
|
}
|
|
110
632
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
633
|
+
loadWiki = () => this.#loadWiki();
|
|
634
|
+
|
|
635
|
+
#loadWiki() {
|
|
636
|
+
const { state } = this.#history();
|
|
637
|
+
return freeze({
|
|
638
|
+
trusted: true,
|
|
639
|
+
state,
|
|
640
|
+
stateDigest: digestWikiState(state),
|
|
641
|
+
});
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
resolveHistory(input) {
|
|
645
|
+
return this.#resolveHistory(input);
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
resolveAtCheckpoint(input) {
|
|
649
|
+
return this.#resolveHistory(input, true);
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
// Provenance only: callers must authorize the plan and independently check
|
|
653
|
+
// the successor's actual operation/state, not treat a request digest as an
|
|
654
|
+
// effect receipt. Allowed digests describe an ordered prefix, not a set.
|
|
655
|
+
#resolveHistory(
|
|
656
|
+
{
|
|
657
|
+
tenantId,
|
|
658
|
+
stateDigest,
|
|
659
|
+
allowedMaintenanceRequestDigests = [],
|
|
660
|
+
checkpoint = null,
|
|
661
|
+
} = {},
|
|
662
|
+
historical = false,
|
|
663
|
+
) {
|
|
664
|
+
if (historical) {
|
|
665
|
+
const fields = [
|
|
666
|
+
"epoch",
|
|
667
|
+
"ledgerId",
|
|
668
|
+
"identityDigest",
|
|
669
|
+
"sequence",
|
|
670
|
+
"headDigest",
|
|
671
|
+
];
|
|
672
|
+
if (
|
|
673
|
+
!checkpoint ||
|
|
674
|
+
typeof checkpoint !== "object" ||
|
|
675
|
+
Array.isArray(checkpoint) ||
|
|
676
|
+
Object.keys(checkpoint).length !== fields.length ||
|
|
677
|
+
fields.some((key) => !Object.hasOwn(checkpoint, key)) ||
|
|
678
|
+
typeof checkpoint.epoch !== "string" ||
|
|
679
|
+
typeof checkpoint.ledgerId !== "string" ||
|
|
680
|
+
!DIGEST.test(checkpoint.identityDigest ?? "") ||
|
|
681
|
+
!DIGEST.test(checkpoint.headDigest ?? "") ||
|
|
682
|
+
!Number.isSafeInteger(checkpoint.sequence) ||
|
|
683
|
+
checkpoint.sequence < 1 ||
|
|
684
|
+
checkpoint.sequence > EVOLUTION_LEDGER_MAX_EVENTS
|
|
685
|
+
) {
|
|
686
|
+
throw new TypeError(
|
|
687
|
+
"Wiki historical read requires an exact authenticated checkpoint",
|
|
688
|
+
);
|
|
689
|
+
}
|
|
690
|
+
checkpoint = Object.freeze({ ...checkpoint });
|
|
691
|
+
} else if (checkpoint !== null) {
|
|
692
|
+
throw new TypeError(
|
|
693
|
+
"current Wiki history cannot be downgraded to a checkpoint view",
|
|
694
|
+
);
|
|
695
|
+
}
|
|
696
|
+
if (
|
|
697
|
+
tenantId !== this.descriptor.tenantId ||
|
|
698
|
+
!DIGEST.test(stateDigest ?? "") ||
|
|
699
|
+
!Array.isArray(allowedMaintenanceRequestDigests) ||
|
|
700
|
+
allowedMaintenanceRequestDigests.length > 128
|
|
701
|
+
) {
|
|
702
|
+
throw new TypeError(
|
|
703
|
+
"Wiki history requires an exact tenant, baseline, and bounded request sequence",
|
|
704
|
+
);
|
|
705
|
+
}
|
|
706
|
+
const allowed = [];
|
|
707
|
+
const length = allowedMaintenanceRequestDigests.length;
|
|
708
|
+
for (let index = 0; index < length; index += 1) {
|
|
709
|
+
const value = allowedMaintenanceRequestDigests[index];
|
|
710
|
+
if (!DIGEST.test(value ?? "") || allowed.includes(value)) {
|
|
711
|
+
throw new TypeError(
|
|
712
|
+
"Wiki history request digests must be unique and dense",
|
|
713
|
+
);
|
|
117
714
|
}
|
|
715
|
+
allowed.push(value);
|
|
118
716
|
}
|
|
119
|
-
const
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
717
|
+
const { head, viewState, source, successors } = this.#history({
|
|
718
|
+
sourceDigest: stateDigest,
|
|
719
|
+
allowed,
|
|
720
|
+
checkpoint,
|
|
721
|
+
});
|
|
722
|
+
if (!source) {
|
|
723
|
+
fail(
|
|
724
|
+
WIKI_LEDGER_CONFLICT_CODE,
|
|
725
|
+
"Wiki baseline is not in authenticated history",
|
|
726
|
+
);
|
|
123
727
|
}
|
|
124
|
-
return {
|
|
728
|
+
return freeze({
|
|
729
|
+
authenticated: true,
|
|
730
|
+
tenantId,
|
|
731
|
+
evolutionRunId: this.descriptor.evolutionRunId,
|
|
732
|
+
source: { trusted: true, state: source, stateDigest },
|
|
733
|
+
current: {
|
|
734
|
+
trusted: true,
|
|
735
|
+
state: viewState,
|
|
736
|
+
stateDigest: digestWikiState(viewState),
|
|
737
|
+
},
|
|
738
|
+
successors,
|
|
739
|
+
ledgerHead: head,
|
|
740
|
+
scope: historical ? "checkpoint" : "current",
|
|
741
|
+
checkpoint,
|
|
742
|
+
});
|
|
125
743
|
}
|
|
126
744
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
745
|
+
commitRevision = ({
|
|
746
|
+
expectedStateDigest,
|
|
747
|
+
revision,
|
|
748
|
+
expectedLedgerHead,
|
|
749
|
+
} = {}) => {
|
|
750
|
+
const headKeys = [
|
|
751
|
+
"epoch",
|
|
752
|
+
"ledgerId",
|
|
753
|
+
"identityDigest",
|
|
754
|
+
"sequence",
|
|
755
|
+
"headDigest",
|
|
756
|
+
];
|
|
757
|
+
if (expectedLedgerHead !== undefined) {
|
|
758
|
+
if (
|
|
759
|
+
!expectedLedgerHead ||
|
|
760
|
+
typeof expectedLedgerHead !== "object" ||
|
|
761
|
+
Array.isArray(expectedLedgerHead) ||
|
|
762
|
+
Object.keys(expectedLedgerHead).length !== headKeys.length ||
|
|
763
|
+
headKeys.some((key) => !Object.hasOwn(expectedLedgerHead, key)) ||
|
|
764
|
+
typeof expectedLedgerHead.epoch !== "string" ||
|
|
765
|
+
typeof expectedLedgerHead.ledgerId !== "string" ||
|
|
766
|
+
!DIGEST.test(expectedLedgerHead.identityDigest ?? "") ||
|
|
767
|
+
!Number.isSafeInteger(expectedLedgerHead.sequence) ||
|
|
768
|
+
expectedLedgerHead.sequence < 0 ||
|
|
769
|
+
(expectedLedgerHead.sequence === 0
|
|
770
|
+
? expectedLedgerHead.headDigest !== null
|
|
771
|
+
: !DIGEST.test(expectedLedgerHead.headDigest ?? ""))
|
|
772
|
+
) {
|
|
773
|
+
throw new TypeError("Wiki expected ledger head is invalid");
|
|
774
|
+
}
|
|
775
|
+
expectedLedgerHead = Object.freeze({ ...expectedLedgerHead });
|
|
776
|
+
}
|
|
777
|
+
if (
|
|
778
|
+
!DIGEST.test(expectedStateDigest ?? "") ||
|
|
779
|
+
revision?.schema !== WIKI_REVISION_SCHEMA ||
|
|
780
|
+
revision.tenantId !== this.descriptor.tenantId ||
|
|
781
|
+
revision.evolutionRunId !== this.descriptor.evolutionRunId ||
|
|
782
|
+
revision.stateDigest !== digestWikiState(revision.state) ||
|
|
783
|
+
revision.state.revisionId !== revision.revisionId ||
|
|
784
|
+
!REVISION_ID.test(revision.revisionId ?? "")
|
|
785
|
+
) {
|
|
138
786
|
throw new TypeError("Wiki revision commit request is invalid");
|
|
139
787
|
}
|
|
140
|
-
|
|
141
|
-
|
|
788
|
+
// Own the revision before handing it to any persistence callback.
|
|
789
|
+
revision = freeze(
|
|
790
|
+
structuredClone(verifyRevision(revision, this.descriptor)),
|
|
791
|
+
);
|
|
792
|
+
const { head, latest, state: currentState } = this.#history();
|
|
793
|
+
if (
|
|
794
|
+
expectedLedgerHead &&
|
|
795
|
+
headKeys.some((key) => expectedLedgerHead[key] !== head[key])
|
|
796
|
+
) {
|
|
797
|
+
fail(
|
|
798
|
+
WIKI_LEDGER_CONFLICT_CODE,
|
|
799
|
+
"Wiki authorization ledger head changed before revision commit",
|
|
800
|
+
);
|
|
801
|
+
}
|
|
142
802
|
const currentDigest = digestWikiState(currentState);
|
|
143
803
|
if (currentDigest !== expectedStateDigest) {
|
|
144
|
-
if (
|
|
145
|
-
|
|
146
|
-
|
|
804
|
+
if (
|
|
805
|
+
latest?.revision.revisionId === revision.revisionId &&
|
|
806
|
+
currentDigest === revision.stateDigest
|
|
807
|
+
) {
|
|
808
|
+
return Object.freeze({
|
|
809
|
+
committed: true,
|
|
810
|
+
recovered: true,
|
|
811
|
+
revisionId: revision.revisionId,
|
|
812
|
+
stateDigest: revision.stateDigest,
|
|
813
|
+
evolutionRunId: this.descriptor.evolutionRunId,
|
|
814
|
+
});
|
|
147
815
|
}
|
|
148
|
-
fail(
|
|
816
|
+
fail(
|
|
817
|
+
WIKI_LEDGER_CONFLICT_CODE,
|
|
818
|
+
"Wiki state changed before revision commit",
|
|
819
|
+
);
|
|
149
820
|
}
|
|
150
|
-
if (
|
|
151
|
-
|
|
821
|
+
if (
|
|
822
|
+
revision.revision !== currentState.revision + 1 ||
|
|
823
|
+
revision.priorStateDigest !== currentDigest
|
|
824
|
+
) {
|
|
825
|
+
fail(
|
|
826
|
+
WIKI_LEDGER_CONFLICT_CODE,
|
|
827
|
+
"Wiki revision does not extend the current state",
|
|
828
|
+
);
|
|
152
829
|
}
|
|
153
|
-
|
|
154
|
-
const published = this
|
|
830
|
+
verifyRequestTransition(currentState, revision);
|
|
831
|
+
const published = this.#putCanonical("wiki-revision", revision, {
|
|
155
832
|
audience: this.descriptor.audience,
|
|
156
833
|
purpose: this.descriptor.purpose,
|
|
157
834
|
retention: "ledger",
|
|
158
835
|
});
|
|
159
|
-
if (
|
|
160
|
-
|
|
161
|
-
|
|
836
|
+
if (
|
|
837
|
+
!published?.ref ||
|
|
838
|
+
published.receipt?.persisted !== true ||
|
|
839
|
+
published.receipt?.readbackVerified !== true ||
|
|
840
|
+
published.receipt?.integrityVerified !== true ||
|
|
841
|
+
published.receipt?.retention !== "ledger"
|
|
842
|
+
) {
|
|
843
|
+
fail(
|
|
844
|
+
WIKI_LEDGER_CORRUPT_CODE,
|
|
845
|
+
"Wiki revision artifact was not durably read back",
|
|
846
|
+
);
|
|
162
847
|
}
|
|
163
848
|
const eventId = `wiki.revision.${revision.revisionId.slice("wiki:".length)}`;
|
|
164
|
-
const receipt = this
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
849
|
+
const receipt = this.#appendDomainEvent(
|
|
850
|
+
{
|
|
851
|
+
artifactTenantId: this.descriptor.artifactTenantId,
|
|
852
|
+
correlationId: this.descriptor.evolutionRunId,
|
|
853
|
+
decision: "committed",
|
|
854
|
+
eventId,
|
|
855
|
+
reason: `wiki revision ${revision.revision} committed`,
|
|
856
|
+
skillName: null,
|
|
857
|
+
sourceRefs: latest ? [latest.event.subjectRef] : [],
|
|
858
|
+
subjectRef: published.ref,
|
|
859
|
+
tenantId: this.descriptor.tenantId,
|
|
860
|
+
timestamp: revision.effectiveAt,
|
|
861
|
+
type: WIKI_LEDGER_EVENT_TYPE,
|
|
862
|
+
},
|
|
863
|
+
{ expectedHeadDigest: head.headDigest, expectedSequence: head.sequence },
|
|
864
|
+
);
|
|
865
|
+
if (
|
|
866
|
+
receipt?.authenticated !== true ||
|
|
867
|
+
receipt?.committed !== true ||
|
|
868
|
+
receipt?.durable !== true ||
|
|
869
|
+
receipt.eventId !== eventId ||
|
|
870
|
+
!DIGEST.test(receipt.receiptDigest ?? "")
|
|
871
|
+
) {
|
|
872
|
+
fail(
|
|
873
|
+
WIKI_LEDGER_CORRUPT_CODE,
|
|
874
|
+
"Wiki ledger did not confirm a durable authenticated append",
|
|
875
|
+
);
|
|
876
|
+
}
|
|
877
|
+
const stored = this.#history().latest;
|
|
878
|
+
if (
|
|
879
|
+
stored?.revision.revisionId !== revision.revisionId ||
|
|
880
|
+
stored.revision.stateDigest !== revision.stateDigest
|
|
881
|
+
) {
|
|
882
|
+
fail(
|
|
883
|
+
WIKI_LEDGER_CORRUPT_CODE,
|
|
884
|
+
"Wiki revision readback differs after ledger commit",
|
|
885
|
+
);
|
|
886
|
+
}
|
|
887
|
+
return Object.freeze({
|
|
888
|
+
committed: true,
|
|
889
|
+
recovered: false,
|
|
890
|
+
revisionId: revision.revisionId,
|
|
891
|
+
stateDigest: revision.stateDigest,
|
|
892
|
+
evolutionRunId: this.descriptor.evolutionRunId,
|
|
893
|
+
ledgerReceiptDigest: receipt.receiptDigest,
|
|
894
|
+
});
|
|
188
895
|
};
|
|
189
896
|
|
|
190
897
|
maintainerPorts({ resolveEvidence, derive } = {}) {
|
|
191
898
|
if (typeof resolveEvidence !== "function" || typeof derive !== "function") {
|
|
192
899
|
throw new TypeError("resolveEvidence and derive ports are required");
|
|
193
900
|
}
|
|
194
|
-
return Object.freeze({
|
|
901
|
+
return Object.freeze({
|
|
902
|
+
loadWiki: () => this.#loadWiki(),
|
|
903
|
+
commitRevision: this.commitRevision,
|
|
904
|
+
resolveEvidence,
|
|
905
|
+
derive,
|
|
906
|
+
});
|
|
195
907
|
}
|
|
196
908
|
}
|
|
197
909
|
|
|
910
|
+
export function captureWikiRevisionReader(adapter) {
|
|
911
|
+
const reader = READERS.get(adapter);
|
|
912
|
+
if (!reader)
|
|
913
|
+
throw new TypeError(
|
|
914
|
+
"a branded WikiMaintainerLedgerAdapter reader is required",
|
|
915
|
+
);
|
|
916
|
+
return reader;
|
|
917
|
+
}
|
|
918
|
+
|
|
198
919
|
export function createWikiMaintainerLedgerAdapter(options) {
|
|
199
920
|
return new WikiMaintainerLedgerAdapter(options);
|
|
200
921
|
}
|