chainlesschain 0.162.149 → 0.162.150
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/package.json +1 -1
- package/src/assets/web-panel/assets/{AIOps-BJif14yR.js → AIOps-CBLvrjeG.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-CXek6gJY.js → ActionButton-DYv2GtE0.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-BgQhdAJi.js → Analytics-CL6PZ-Ww.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-DTYl5NtR.js → AppLayout-xuyHt4uA.js} +3 -3
- package/src/assets/web-panel/assets/{Audit-BzATQAeR.js → Audit-DOvSVycq.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-BzdPEQhL.js → Backup-DMhfTswr.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-BM0KVh8E.js → BaseInput-CQxDdm63.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-D7fHXHkz.js → Chat-BEeNhK2a.js} +5 -5
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-Wm34RR-b.js → ChatBubbleRenderer-8nul8eTq.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-CAiSQ9vO.js → Checkbox-CL04O-ER.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-Df40CrEe.js → Codegen-C50o-n7x.js} +1 -1
- package/src/assets/web-panel/assets/{Col-DIT2fNFU.js → Col-CH-bDkzs.js} +1 -1
- package/src/assets/web-panel/assets/{Community-CSTIbW2k.js → Community-DqAIMvSe.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-DtqXZZUi.js → Compact-C43fo_my.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-CUtzw6o7.js → Compliance-BERnMrdP.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-CezmlnmU.js → Cowork-Baw3w1gp.js} +4 -4
- package/src/assets/web-panel/assets/{Cron-P4BITarg.js → Cron-BEqAHF1-.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-BRRiYwvq.js → Crosschain-CvnmKwK4.js} +1 -1
- package/src/assets/web-panel/assets/{DID-L5ijB9i4.js → DID-iMPxgVdt.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-CFxro4ob.js → Dashboard--4SJX3YR.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-BmAFCQ71.js → Dropdown-BgLV6xgz.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-DJBCEuon.js → EmailListRenderer-Bvb8oUD8.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-z4oLq6eT.js → FamilyGuardDashboard-DpXPjJB5.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-DsVCpHMF.js → Federation-BbFfJ1Xi.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-DP3bP5th.js → FormItemContext-DeGq1B-q.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-BAXP2Gc6.js → GenericCardRenderer-CNW7s9zM.js} +1 -1
- package/src/assets/web-panel/assets/{Git-I3g_bAw9.js → Git-L1PjW-lT.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-jHS5-ioS.js → Governance-PK-X58to.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-CPL7sfx9.js → Inference-BePWEH-d.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-Jf236h4C.js → KnowledgeGraph-LF_sBvdL.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-Cm2tcSKg.js → Logs-BKkfk9hy.js} +2 -2
- package/src/assets/web-panel/assets/{Marketplace-CZK82rhi.js → Marketplace-BNMqUDla.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-CZCeji7a.js → McpTools-w4WPiyz2.js} +5 -5
- package/src/assets/web-panel/assets/{Memory-3l2KVS9k.js → Memory-DUKMVGNi.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-VYdpoLh6.js → MobileBridge-BWhiEyTJ.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-CiB9cmm1.js → MobileProjects-Ocf5JEkX.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-wCFZbBuL.js → Mtc-D2B6MMhU.js} +4 -4
- package/src/assets/web-panel/assets/{MtcAudit-1a3THIyG.js → MtcAudit-DdYjCq1O.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-DMzLB2hG.js → Multisig-Cb1hfuUZ.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-D9wZbf6l.js → NLProgramming-CTeImGp7.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-hrFe2ZM-.js → Notes-BjYNc7eQ.js} +4 -4
- package/src/assets/web-panel/assets/{NotificationSettings-CHGX5Jwm.js → NotificationSettings-Dn_NtRXQ.js} +1 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-DVYYIizh.js +1 -0
- package/src/assets/web-panel/assets/{Organization-By7FkhtY.js → Organization-Be2Kmr5j.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow--khGSzJn.js → Overflow-Cu_-qRlR.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-CAG9dH35.js → P2P-DD2HoGzE.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-B3SQZmK9.js → PdhVaultBrowser-BRI7DVth.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-D35ec6JA.js → Permissions-C9Srcs2M.js} +3 -3
- package/src/assets/web-panel/assets/{PersonalDataHub-CxBF7hW_.js → PersonalDataHub-CUqcMgo1.js} +3 -3
- package/src/assets/web-panel/assets/{Pipeline-s6EtOO1s.js → Pipeline-HBrQGLXt.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-BbJYmWmO.js → Privacy-D-B0vjwh.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-VGQq1jMT.js → ProjectInit-eTeLIu9e.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-B1ew3Teh.js → ProjectSettings-DrRqCsC6.js} +2 -2
- package/src/assets/web-panel/assets/Projects-1G9DNOhI.js +1 -0
- package/src/assets/web-panel/assets/{Providers-mrO47FIK.js → Providers-RkTZzpxP.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-IJF2mHyw.js → QrScannerModal-BSCUgsgC.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-CU0wN_Z0.js → QuickAsk-CHgyM3Bz.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-DhN37R6G.js → Recommend-0lry4OZq.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-D_xOX_hu.js → RemoteSession-Cn45UroZ.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-D_Ssv7uH.js → Reputation-Q-Zjb707.js} +1 -1
- package/src/assets/web-panel/assets/{Row-Kx5dKxX7.js → Row-BdM70oda.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-BlGwqZkY.js → RssFeed-DmOAKKap.js} +2 -2
- package/src/assets/web-panel/assets/{Search-hLFQzxpb.js → Search-Dwavbm07.js} +1 -1
- package/src/assets/web-panel/assets/{Security-DMlvsVt4.js → Security-DukXFCnk.js} +3 -3
- package/src/assets/web-panel/assets/{Services-Bd0Qsj2m.js → Services-BIlRnITu.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-DFclq9X3.js → Skeleton-YYVQdhhQ.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-BNtln2qY.js → Skills-B8_iYHz2.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-Dch5H19G.js → Sla-BdVrhT31.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-2UfQcU1g.js → SpeechSettings-CD3ggRx7.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-CD9YQr4i.js → SyncSettings-Bp02VZFH.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-BNu-7MzI.js → Tasks-DEVmCEsr.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-D1n9CaIR.js → Templates-B6czWc4N.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-DenL3iBW.js → Tenant-BCJLv17r.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-ZzU0Io1Y.js → Terminal-CD132d2Y.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-D87IfukO.js → TimelineRenderer-ZB-CvkZl.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-BkiZc8E3.js → Tokens-BnSY0S-s.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-BNRSytGN.js → Trigger-VZw9Oy2w.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-Bwbd4X2m.js → Trust-pZq7Hjd2.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-B8O2bs0o.js → UkeySign-DnQaqk4q.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-C2fL8zmH.js → VideoEditing-BEUfmvJV.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-BORYDdE1.js → Wallet-CoZKMXJ2.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-C0V5S2FM.js → WebAuthn-CBOGVx1I.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-2dR0fcHL.js → WorkflowEditor-huSKn7TT.js} +1 -1
- package/src/assets/web-panel/assets/{chat-BmuAFAn8.js → chat-A_3w6FBO.js} +1 -1
- package/src/assets/web-panel/assets/{colors-CN3smMcK.js → colors-D1Bem9Oy.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-DCnxb4kW.js → compact-item-CJYJj0oO.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-vlR43pHn.js → createContext-BkbFiKT4.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-WDr3_M_N.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-D04tHYFd.js → hasIn-CKvUafVY.js} +1 -1
- package/src/assets/web-panel/assets/{index-0DnaZGkC.js → index-AjrSPnvv.js} +1 -1
- package/src/assets/web-panel/assets/{index-BudvKQfG.js → index-B8i0lViZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-BeGDEXFs.js → index-B9Svn0zc.js} +1 -1
- package/src/assets/web-panel/assets/{index-D5LZVZ0L.js → index-BHdHSX06.js} +1 -1
- package/src/assets/web-panel/assets/{index-BTPEZTk1.js → index-BHdailyo.js} +1 -1
- package/src/assets/web-panel/assets/{index-DIpY0qM5.js → index-BJwlEnYo.js} +1 -1
- package/src/assets/web-panel/assets/{index-CsAsCPJ6.js → index-BOoAQjJz.js} +1 -1
- package/src/assets/web-panel/assets/{index-ljuBiQW9.js → index-BSgWxAOG.js} +1 -1
- package/src/assets/web-panel/assets/{index-hpvvtAZ3.js → index-BdutMsne.js} +1 -1
- package/src/assets/web-panel/assets/{index-_FIkN3jd.js → index-BiDWxzbn.js} +1 -1
- package/src/assets/web-panel/assets/{index-C-6NO5il.js → index-By5a0T_W.js} +1 -1
- package/src/assets/web-panel/assets/{index-B78xL3s2.js → index-C-WIY-FQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-ClhAHDK3.js → index-C37f6iey.js} +1 -1
- package/src/assets/web-panel/assets/{index-ToUh2b1-.js → index-C9bWmTcO.js} +1 -1
- package/src/assets/web-panel/assets/{index-D28DeAAB.js → index-CBaosWRO.js} +1 -1
- package/src/assets/web-panel/assets/{index-D8vwp4qp.js → index-CBlBVJ_m.js} +1 -1
- package/src/assets/web-panel/assets/{index-BqhASEL4.js → index-CD62EEGo.js} +1 -1
- package/src/assets/web-panel/assets/{index-DDwLgQY9.js → index-CUj-l7GM.js} +1 -1
- package/src/assets/web-panel/assets/{index-DbVsQBOH.js → index-CVS8Ymuq.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cr-A0FYJ.js → index-ChkXUj3f.js} +1 -1
- package/src/assets/web-panel/assets/{index-D65_XseV.js → index-Cj0OZ-37.js} +1 -1
- package/src/assets/web-panel/assets/{index-BXRg8GFQ.js → index-Co3OFL0t.js} +1 -1
- package/src/assets/web-panel/assets/{index-430S68MN.js → index-Crp8CbRg.js} +1 -1
- package/src/assets/web-panel/assets/{index-CngCC8hC.js → index-D22zNXiS.js} +1 -1
- package/src/assets/web-panel/assets/{index-HhNjnCfe.js → index-DTs_D1OL.js} +1 -1
- package/src/assets/web-panel/assets/{index-CP9m9Ggr.js → index-DfgCdFrN.js} +3 -3
- package/src/assets/web-panel/assets/{index-jzR7Ujuw.js → index-DjYrecNb.js} +1 -1
- package/src/assets/web-panel/assets/{index-CTOCnIQ7.js → index-DpW9cf3e.js} +1 -1
- package/src/assets/web-panel/assets/index-Dwix3p4g.js +1 -0
- package/src/assets/web-panel/assets/{index-D_n8_vfI.js → index-F--HuPG1.js} +1 -1
- package/src/assets/web-panel/assets/{index-BasvsWDM.js → index-Fuk6t_3K.js} +1 -1
- package/src/assets/web-panel/assets/{index-CnXebZLL.js → index-JEAGMii9.js} +1 -1
- package/src/assets/web-panel/assets/{index-DYAtmqiv.js → index-PF-mpv8K.js} +1 -1
- package/src/assets/web-panel/assets/index-SHaoZ0CA.js +1 -0
- package/src/assets/web-panel/assets/{index-DTWg-18U.js → index-b-sbVdjQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-C5Sxb1sE.js → index-pyvMVX8r.js} +1 -1
- package/src/assets/web-panel/assets/{index-TslMTwNy.js → index-qNTtOVi_.js} +1 -1
- package/src/assets/web-panel/assets/{index-DTtRscUa.js → index-tgO8iza6.js} +1 -1
- package/src/assets/web-panel/assets/{index-DbADHwhr.js → index-ttDQVhZy.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-C3wUb4je.js → initDefaultProps-DtrnfsZH.js} +1 -1
- package/src/assets/web-panel/assets/{motion-D-jYFUNA.js → motion-D4zqSaX3.js} +1 -1
- package/src/assets/web-panel/assets/{move-tqb8nwJ2.js → move-CGFGOUQj.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-DSOjMJMz.js → mtc-parser-DH2HvkJl.js} +1 -1
- package/src/assets/web-panel/assets/{omit-CJ7VimIW.js → omit-jJ2at5HX.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-qXiG1iT3.js → pickAttrs-CRyMT1Fv.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-CkGBcy1Z.js → placementArrow-DZ_CX0Pt.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-D3WvTlLO.js → responsiveObserve-wruHk-h5.js} +1 -1
- package/src/assets/web-panel/assets/{slide-BEE2ftge.js → slide-BGgx8q67.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-CsfBpxiG.js → statusUtils-Do5M7gKm.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-xPrIiJPI.js → styleChecker-CRa-GZpX.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-C5Yd-SCR.js → useFlexGapSupport-BxPcq6pj.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-D_MDS8HI.js → useFs-v5O2ZcJm.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-BqJh-usA.js → usePersonalDataHub--z2FU0Px.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-chm_p-gz.js → vnode-1emidVKd.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-3-YDNz0Z.js → zoom-CcJaRyHs.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/a2a.js +19 -4
- package/src/commands/activitypub.js +20 -3
- package/src/commands/agent.js +27 -5
- package/src/commands/audit.js +40 -24
- package/src/commands/codeintel.js +68 -0
- package/src/commands/collab.js +15 -2
- package/src/commands/compliance.js +5 -0
- package/src/commands/config.js +4 -1
- package/src/commands/dao.js +86 -14
- package/src/commands/dev.js +2 -0
- package/src/commands/did.js +7 -1
- package/src/commands/dlp.js +23 -1
- package/src/commands/economy.js +29 -3
- package/src/commands/eval.js +7 -0
- package/src/commands/evomap.js +26 -0
- package/src/commands/governance.js +17 -3
- package/src/commands/hardening.js +18 -0
- package/src/commands/incentive.js +5 -0
- package/src/commands/init.js +46 -2
- package/src/commands/kg.js +4 -0
- package/src/commands/loop.js +6 -1
- package/src/commands/lowcode.js +15 -2
- package/src/commands/marketplace.js +40 -6
- package/src/commands/matrix.js +20 -1
- package/src/commands/memory.js +4 -1
- package/src/commands/mtc.js +7 -1
- package/src/commands/nostr.js +31 -4
- package/src/commands/note.js +7 -4
- package/src/commands/plugin.js +125 -5
- package/src/commands/pqc.js +5 -0
- package/src/commands/reputation.js +10 -1
- package/src/commands/scim.js +6 -0
- package/src/commands/session.js +32 -10
- package/src/commands/siem.js +11 -0
- package/src/commands/sla.js +18 -3
- package/src/commands/social.js +38 -5
- package/src/commands/sso.js +10 -2
- package/src/commands/stress.js +23 -4
- package/src/commands/team.js +9 -2
- package/src/commands/tech.js +2 -0
- package/src/commands/tenant.js +10 -1
- package/src/commands/terraform.js +6 -0
- package/src/commands/update.js +1 -1
- package/src/commands/zkp.js +20 -0
- package/src/gateways/ws/message-dispatcher.js +5 -2
- package/src/gateways/ws/remote-session-protocol.js +103 -42
- package/src/harness/jsonl-session-store.js +12 -5
- package/src/harness/plugin-manager.js +16 -4
- package/src/harness/remote-command-ledger.js +46 -15
- package/src/harness/worktree-isolator.js +16 -6
- package/src/lib/__tests__/logger.test.js +5 -2
- package/src/lib/a2a-protocol.js +25 -1
- package/src/lib/activitypub-bridge.js +61 -0
- package/src/lib/agent-core.js +2 -0
- package/src/lib/agent-economy.js +262 -29
- package/src/lib/agent-network.js +7 -1
- package/src/lib/agent-team/team-runner.js +25 -9
- package/src/lib/agent-team/team-worktree.js +36 -4
- package/src/lib/async-hook-supervisor.cjs +102 -16
- package/src/lib/audit-logger.js +7 -6
- package/src/lib/autonomous-developer.js +60 -0
- package/src/lib/chat-core.js +17 -4
- package/src/lib/collaboration-governance.js +56 -0
- package/src/lib/community-governance.js +68 -0
- package/src/lib/compliance-manager.js +63 -0
- package/src/lib/cross-chain.js +5 -0
- package/src/lib/dao-governance.js +151 -2
- package/src/lib/did-manager.js +23 -10
- package/src/lib/dlp-engine.js +70 -0
- package/src/lib/eval/runner.js +89 -1
- package/src/lib/eval/tasks.js +170 -0
- package/src/lib/eval/trend.js +16 -1
- package/src/lib/evolution-system.js +92 -0
- package/src/lib/evomap-federation.js +55 -0
- package/src/lib/evomap-governance.js +94 -0
- package/src/lib/fatal-handler.js +17 -1
- package/src/lib/hardening-manager.js +73 -0
- package/src/lib/hierarchical-memory.js +14 -8
- package/src/lib/knowledge-exporter.js +8 -2
- package/src/lib/knowledge-graph.js +79 -0
- package/src/lib/llm-providers.js +23 -14
- package/src/lib/logger.js +4 -1
- package/src/lib/lsp/__tests__/benchmark.test.js +88 -0
- package/src/lib/lsp/__tests__/lsp-client.test.js +11 -0
- package/src/lib/lsp/__tests__/lsp-manager.test.js +69 -0
- package/src/lib/lsp/benchmark.js +257 -0
- package/src/lib/lsp/lsp-client.js +30 -9
- package/src/lib/lsp/lsp-manager.js +54 -2
- package/src/lib/matrix-bridge.js +84 -0
- package/src/lib/memory-manager.js +5 -3
- package/src/lib/nostr-bridge.js +53 -0
- package/src/lib/permission-engine.js +22 -4
- package/src/lib/plugin-runtime/__tests__/remote-source.test.js +256 -0
- package/src/lib/plugin-runtime/install.js +9 -1
- package/src/lib/plugin-runtime/policy.js +9 -1
- package/src/lib/plugin-runtime/remote-source.js +240 -0
- package/src/lib/pqc-manager.js +64 -0
- package/src/lib/reputation-optimizer.js +101 -0
- package/src/lib/sandbox-egress-proxy.js +159 -59
- package/src/lib/sandbox-fs-policy.js +112 -0
- package/src/lib/sandbox-network-policy.js +18 -1
- package/src/lib/sandbox-v2.js +14 -14
- package/src/lib/scim-manager.js +36 -0
- package/src/lib/session-manager.js +5 -2
- package/src/lib/settings-hooks.cjs +1 -0
- package/src/lib/siem-exporter.js +45 -0
- package/src/lib/skill-loader.js +20 -2
- package/src/lib/skill-marketplace.js +83 -0
- package/src/lib/sla-manager.js +88 -0
- package/src/lib/social-manager.js +74 -0
- package/src/lib/stress-tester.js +65 -0
- package/src/lib/tech-learning-engine.js +75 -0
- package/src/lib/tenant-saas.js +107 -0
- package/src/lib/terraform-manager.js +67 -0
- package/src/lib/token-incentive.js +180 -29
- package/src/lib/wallet-manager.js +81 -35
- package/src/lib/zkp-engine.js +87 -0
- package/src/repl/agent-repl.js +17 -2
- package/src/runtime/__tests__/auto-pin.test.js +104 -0
- package/src/runtime/agent-core.js +241 -68
- package/src/runtime/auto-pin.js +117 -0
- package/src/runtime/headless-runner.js +35 -0
- package/src/assets/web-panel/assets/OrderTableRenderer-CRIFE2Tj.js +0 -1
- package/src/assets/web-panel/assets/Projects-CGcNIs_g.js +0 -1
- package/src/assets/web-panel/assets/devWarning-DxwmsL4j.js +0 -1
- package/src/assets/web-panel/assets/index-Cg2ldRfU.js +0 -1
- package/src/assets/web-panel/assets/index-Dwzo-dtJ.js +0 -1
|
@@ -217,9 +217,10 @@ export class TeamRunner {
|
|
|
217
217
|
mailbox: this.mailbox,
|
|
218
218
|
budget: this.budget,
|
|
219
219
|
});
|
|
220
|
-
this.registry.complete(key, { holder, result });
|
|
221
|
-
// Fold usage/cost into the team budget
|
|
222
|
-
//
|
|
220
|
+
const done = this.registry.complete(key, { holder, result });
|
|
221
|
+
// Fold usage/cost into the team budget regardless — the task DID execute
|
|
222
|
+
// and consumed resources. `--exec` shell tasks carry no usage → only the
|
|
223
|
+
// task-count / wall-clock dimensions move.
|
|
223
224
|
if (this.budget) {
|
|
224
225
|
this.budget.record(
|
|
225
226
|
{
|
|
@@ -230,12 +231,27 @@ export class TeamRunner {
|
|
|
230
231
|
this._now(),
|
|
231
232
|
);
|
|
232
233
|
}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
234
|
+
if (done.ok) {
|
|
235
|
+
this._setState(holder, "completed-task");
|
|
236
|
+
this._emit("task:completed", {
|
|
237
|
+
key,
|
|
238
|
+
holder,
|
|
239
|
+
ms: this._now() - startedAt,
|
|
240
|
+
});
|
|
241
|
+
} else {
|
|
242
|
+
// The registry REJECTED the completion — the lease expired mid-run (the
|
|
243
|
+
// task outran its TTL without renewing), so a peer may already own it.
|
|
244
|
+
// Reporting `task:completed` + bumping the completed counter here would
|
|
245
|
+
// be a phantom success (the registry has no record of it, and the task
|
|
246
|
+
// will be reclaimed and re-run). Surface the discard honestly instead so
|
|
247
|
+
// the event stream and per-teammate stats stay truthful.
|
|
248
|
+
this._emit("task:completion-discarded", {
|
|
249
|
+
key,
|
|
250
|
+
holder,
|
|
251
|
+
reason: done.reason,
|
|
252
|
+
ms: this._now() - startedAt,
|
|
253
|
+
});
|
|
254
|
+
}
|
|
239
255
|
} catch (err) {
|
|
240
256
|
// A failed task still consumed a task-count slot (and any wall-clock) — fold
|
|
241
257
|
// it so a doomed retry loop can't dodge the budget.
|
|
@@ -96,6 +96,24 @@ export class TeamWorktreeCoordinator {
|
|
|
96
96
|
makeRunTask({ runInWorktree = null } = {}) {
|
|
97
97
|
return async ({ key, task, holder }) => {
|
|
98
98
|
const branch = this.branchFor(key);
|
|
99
|
+
// A retry (the prior attempt failed and TaskLeaseRegistry re-queued the
|
|
100
|
+
// task) would collide with its own leftover worktree: createWorktree
|
|
101
|
+
// derives a DETERMINISTIC path from the branch and throws "Worktree
|
|
102
|
+
// already exists" (and `worktree add -b` rejects the existing branch), so
|
|
103
|
+
// the retry can never recover — it just re-fails on the collision instead
|
|
104
|
+
// of the real task. Tear down the prior attempt's worktree + branch first
|
|
105
|
+
// so a retry starts clean.
|
|
106
|
+
const prior = this._created.get(key);
|
|
107
|
+
if (prior) {
|
|
108
|
+
try {
|
|
109
|
+
_deps.removeWorktree(this.repoDir, prior.path, {
|
|
110
|
+
deleteBranch: true,
|
|
111
|
+
});
|
|
112
|
+
} catch {
|
|
113
|
+
/* best-effort — a real problem will resurface in createWorktree */
|
|
114
|
+
}
|
|
115
|
+
this._created.delete(key);
|
|
116
|
+
}
|
|
99
117
|
const { path: worktreePath } = _deps.createWorktree(this.repoDir, branch);
|
|
100
118
|
this._created.set(key, { branch, path: worktreePath, committed: false });
|
|
101
119
|
if (typeof runInWorktree === "function") {
|
|
@@ -157,20 +175,34 @@ export class TeamWorktreeCoordinator {
|
|
|
157
175
|
const conflicts = preview?.conflicts || [];
|
|
158
176
|
let merged = false;
|
|
159
177
|
if (clean && merge) {
|
|
178
|
+
// mergeWorktree does NOT throw on a failed merge — it catches internally
|
|
179
|
+
// and RETURNS {success:false, conflicts?, message} (a conflict the clean
|
|
180
|
+
// preview didn't predict, or any non-conflict git failure). The old
|
|
181
|
+
// try/catch was dead for that path and set merged:true unconditionally,
|
|
182
|
+
// reporting a real merge failure as success with empty conflicts. Inspect
|
|
183
|
+
// the return value. (The try still catches assertSafeGitRef, the only
|
|
184
|
+
// throw path — a malformed branch ref.)
|
|
185
|
+
let mergeResult;
|
|
160
186
|
try {
|
|
161
|
-
_deps.mergeWorktree(this.repoDir, info.branch, {
|
|
187
|
+
mergeResult = _deps.mergeWorktree(this.repoDir, info.branch, {
|
|
162
188
|
message: `Merge team task ${key}`,
|
|
163
189
|
});
|
|
164
|
-
merged = true;
|
|
165
190
|
} catch (err) {
|
|
191
|
+
mergeResult = { success: false, message: err.message };
|
|
192
|
+
}
|
|
193
|
+
if (mergeResult?.success === true) {
|
|
194
|
+
merged = true;
|
|
195
|
+
} else {
|
|
166
196
|
results.push({
|
|
167
197
|
key,
|
|
168
198
|
branch: info.branch,
|
|
169
199
|
committed: true,
|
|
170
200
|
clean: false,
|
|
171
201
|
merged: false,
|
|
172
|
-
conflicts
|
|
173
|
-
|
|
202
|
+
conflicts: mergeResult?.conflicts?.length
|
|
203
|
+
? mergeResult.conflicts
|
|
204
|
+
: conflicts,
|
|
205
|
+
error: `merge failed: ${mergeResult?.message || "unknown error"}`,
|
|
174
206
|
});
|
|
175
207
|
continue;
|
|
176
208
|
}
|
|
@@ -23,9 +23,10 @@
|
|
|
23
23
|
* flight — a rapid PostToolUse hook can't stack N copies of itself;
|
|
24
24
|
* - a maxConcurrent cap — overflow is DROPPED with a recorded skip, never
|
|
25
25
|
* queued unbounded;
|
|
26
|
-
* - a per-hook timeout that kills the child
|
|
27
|
-
*
|
|
28
|
-
*
|
|
26
|
+
* - a per-hook timeout that TREE-kills the child (shell + the real command it
|
|
27
|
+
* spawned — a bare child.kill would orphan the grandchild);
|
|
28
|
+
* - tree-reaping of every child on stopAll() / process 'exit', so a session
|
|
29
|
+
* never leaves an orphan hook process.
|
|
29
30
|
*
|
|
30
31
|
* `_deps.spawn` / `_deps.now` are injected so the whole supervisor is unit-
|
|
31
32
|
* testable with fake child processes (no real shell).
|
|
@@ -37,6 +38,12 @@ const { tryParseDecision } = require("./hook-runner.cjs");
|
|
|
37
38
|
const DEFAULT_TIMEOUT_MS = 60000;
|
|
38
39
|
const MAX_TIMEOUT_MS = 600000;
|
|
39
40
|
const DEFAULT_MAX_CONCURRENT = 4;
|
|
41
|
+
// Ring cap on undrained records (parity with PluginMonitorSupervisor's
|
|
42
|
+
// OUTPUT_RING): drainResults()/drainRewakes() normally clear each turn, but a
|
|
43
|
+
// stalled/absent drain over a high-frequency hook would otherwise grow these
|
|
44
|
+
// arrays without bound. Keep only the most recent RESULT_RING; older records
|
|
45
|
+
// are dropped oldest-first.
|
|
46
|
+
const RESULT_RING = 500;
|
|
40
47
|
|
|
41
48
|
class AsyncHookSupervisor {
|
|
42
49
|
constructor(opts = {}) {
|
|
@@ -46,20 +53,87 @@ class AsyncHookSupervisor {
|
|
|
46
53
|
: DEFAULT_MAX_CONCURRENT;
|
|
47
54
|
this._deps = {
|
|
48
55
|
spawn: opts.spawn || cpDefault.spawn,
|
|
56
|
+
spawnSync: opts.spawnSync || cpDefault.spawnSync,
|
|
49
57
|
now: opts.now || (() => Date.now()),
|
|
50
58
|
};
|
|
51
59
|
this._running = new Map(); // key -> { child, timer }
|
|
52
60
|
this._results = []; // completed records awaiting drainResults()
|
|
53
61
|
this._rewakes = []; // failed asyncRewake records awaiting drainRewakes()
|
|
54
62
|
this._stopped = false;
|
|
63
|
+
// The exit reaper is installed LAZILY (on first spawn), not in the ctor:
|
|
64
|
+
// a supervisor that never dispatches a hook (or the many built in tests)
|
|
65
|
+
// must not leave a permanent `process.once('exit')` listener behind —
|
|
66
|
+
// that accumulates across sessions/instances into a MaxListenersExceeded
|
|
67
|
+
// leak. Mirrors PluginMonitorSupervisor._installExitHook.
|
|
55
68
|
this._exitHook = () => this.stopAll();
|
|
56
|
-
|
|
69
|
+
this._exitHookInstalled = false;
|
|
57
70
|
}
|
|
58
71
|
|
|
59
72
|
_key(hook) {
|
|
60
73
|
return `${hook.event || ""}::${hook.command}`;
|
|
61
74
|
}
|
|
62
75
|
|
|
76
|
+
/**
|
|
77
|
+
* Kill a hook child's WHOLE process tree. Hooks run with `shell: true`, so the
|
|
78
|
+
* real command is a grandchild of the shell — a plain `child.kill()` only
|
|
79
|
+
* signals the shell (POSIX: reparents + keeps the command running; Windows:
|
|
80
|
+
* killing cmd.exe never touches its children), orphaning the actual hook
|
|
81
|
+
* process. POSIX: the child is spawned detached (its own group), so a negative
|
|
82
|
+
* pid signals the whole group. Windows: `taskkill /T` walks the tree. Both are
|
|
83
|
+
* SYNCHRONOUS (spawnSync / process.kill) so this is safe inside stopAll() and
|
|
84
|
+
* the process 'exit' reaper, where async work would be cut off. A child with no
|
|
85
|
+
* real pid (the unit-test fakes) falls back to its own `.kill()`.
|
|
86
|
+
*/
|
|
87
|
+
_killChildTree(child, signal = "SIGTERM") {
|
|
88
|
+
if (!child) return;
|
|
89
|
+
const pid = child.pid;
|
|
90
|
+
if (typeof pid !== "number" || pid <= 0) {
|
|
91
|
+
try {
|
|
92
|
+
child.kill(signal);
|
|
93
|
+
} catch {
|
|
94
|
+
/* already gone / fake with no kill */
|
|
95
|
+
}
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
try {
|
|
99
|
+
if (process.platform === "win32") {
|
|
100
|
+
const r = this._deps.spawnSync(
|
|
101
|
+
"taskkill",
|
|
102
|
+
["/pid", String(pid), "/T", "/F"],
|
|
103
|
+
{ windowsHide: true },
|
|
104
|
+
);
|
|
105
|
+
// If taskkill couldn't launch, fall back to a direct kill.
|
|
106
|
+
if (r && r.error) child.kill(signal);
|
|
107
|
+
} else {
|
|
108
|
+
// Negative pid → the whole process group (requires the detached spawn).
|
|
109
|
+
try {
|
|
110
|
+
process.kill(-pid, signal);
|
|
111
|
+
} catch {
|
|
112
|
+
child.kill(signal);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
} catch {
|
|
116
|
+
try {
|
|
117
|
+
child.kill(signal);
|
|
118
|
+
} catch {
|
|
119
|
+
/* already gone */
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** Install the process-exit reaper exactly once, only when a child exists. */
|
|
125
|
+
_installExitHook() {
|
|
126
|
+
if (this._exitHookInstalled) return;
|
|
127
|
+
this._exitHookInstalled = true;
|
|
128
|
+
process.once("exit", this._exitHook);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/** Append a result record, bounded to the most recent RESULT_RING. */
|
|
132
|
+
_pushResult(rec) {
|
|
133
|
+
this._results.push(rec);
|
|
134
|
+
if (this._results.length > RESULT_RING) this._results.shift();
|
|
135
|
+
}
|
|
136
|
+
|
|
63
137
|
/**
|
|
64
138
|
* Dispatch a batch of async hooks fire-and-forget. Returns IMMEDIATELY with a
|
|
65
139
|
* per-hook disposition (`{command, dispatched, reason?}`) — it never awaits a
|
|
@@ -100,7 +174,7 @@ class AsyncHookSupervisor {
|
|
|
100
174
|
});
|
|
101
175
|
// Record the skip so the caller/agent can SEE that a hook was dropped
|
|
102
176
|
// (silent truncation would read as "the hook ran and said nothing").
|
|
103
|
-
this.
|
|
177
|
+
this._pushResult({
|
|
104
178
|
command: hook.command,
|
|
105
179
|
event: hook.event || null,
|
|
106
180
|
ok: false,
|
|
@@ -121,6 +195,9 @@ class AsyncHookSupervisor {
|
|
|
121
195
|
}
|
|
122
196
|
|
|
123
197
|
_spawnOne(hook, payload, opts) {
|
|
198
|
+
// A live child now exists — arm the exit reaper so a session never leaves
|
|
199
|
+
// an orphan hook process (installed once, only from here).
|
|
200
|
+
this._installExitHook();
|
|
124
201
|
const key = this._key(hook);
|
|
125
202
|
const started = this._deps.now();
|
|
126
203
|
const rawTimeout = Number(
|
|
@@ -136,6 +213,10 @@ class AsyncHookSupervisor {
|
|
|
136
213
|
child = this._deps.spawn(hook.command, {
|
|
137
214
|
cwd: opts.cwd || process.cwd(),
|
|
138
215
|
shell: true,
|
|
216
|
+
// POSIX: own process group so a timeout / stopAll can signal the whole
|
|
217
|
+
// tree (shell + the real hook command), not just the shell wrapper.
|
|
218
|
+
// No-op on Windows, where the tree is reaped via `taskkill /T` instead.
|
|
219
|
+
detached: process.platform !== "win32",
|
|
139
220
|
env: {
|
|
140
221
|
...process.env,
|
|
141
222
|
CLAUDE_HOOK_EVENT: hook.event || payload.hook_event_name || "",
|
|
@@ -158,6 +239,13 @@ class AsyncHookSupervisor {
|
|
|
158
239
|
this._running.set(key, rec);
|
|
159
240
|
|
|
160
241
|
try {
|
|
242
|
+
// `.end(data)` flushes ASYNCHRONOUSLY: if the hook exited before consuming
|
|
243
|
+
// stdin (a fast command), the write fails with an async EPIPE emitted as an
|
|
244
|
+
// 'error' event on the stream — NOT a sync throw this catch can see. With no
|
|
245
|
+
// listener that becomes an uncaught exception that crashes the process (seen
|
|
246
|
+
// on Linux CI). Attach a no-op error handler first so a closed-stdin write
|
|
247
|
+
// is swallowed as the non-fatal condition it is.
|
|
248
|
+
child.stdin?.on("error", () => {});
|
|
161
249
|
child.stdin?.end(JSON.stringify(payload));
|
|
162
250
|
} catch {
|
|
163
251
|
/* stdin may already be closed — non-fatal */
|
|
@@ -171,11 +259,9 @@ class AsyncHookSupervisor {
|
|
|
171
259
|
|
|
172
260
|
const timer = setTimeout(() => {
|
|
173
261
|
killedByTimeout = true;
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
/* already gone */
|
|
178
|
-
}
|
|
262
|
+
// Tree-kill: a hook that spawned a subprocess (e.g. `npm test`) must not
|
|
263
|
+
// leave that subprocess orphaned when it exceeds its timeout.
|
|
264
|
+
this._killChildTree(child, "SIGTERM");
|
|
179
265
|
}, timeout);
|
|
180
266
|
if (typeof timer.unref === "function") timer.unref();
|
|
181
267
|
rec.timer = timer;
|
|
@@ -240,11 +326,12 @@ class AsyncHookSupervisor {
|
|
|
240
326
|
ts: now,
|
|
241
327
|
ms: fields.started != null ? now - fields.started : 0,
|
|
242
328
|
};
|
|
243
|
-
this.
|
|
329
|
+
this._pushResult(rec);
|
|
244
330
|
// A rewake fires only for a hook that OPTED IN and finished in a failure
|
|
245
331
|
// state — a passing async check should not re-engage the agent.
|
|
246
332
|
if (hook.asyncRewake && !rec.ok) {
|
|
247
333
|
this._rewakes.push(rec);
|
|
334
|
+
if (this._rewakes.length > RESULT_RING) this._rewakes.shift();
|
|
248
335
|
}
|
|
249
336
|
}
|
|
250
337
|
|
|
@@ -283,11 +370,9 @@ class AsyncHookSupervisor {
|
|
|
283
370
|
} catch {
|
|
284
371
|
/* ignore */
|
|
285
372
|
}
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
/* already gone */
|
|
290
|
-
}
|
|
373
|
+
// Tree-kill (not a bare child.kill) so a session end / process exit never
|
|
374
|
+
// leaves an orphaned hook subprocess — the guarantee this class documents.
|
|
375
|
+
this._killChildTree(rec.child, "SIGTERM");
|
|
291
376
|
this._running.delete(key);
|
|
292
377
|
}
|
|
293
378
|
try {
|
|
@@ -295,6 +380,7 @@ class AsyncHookSupervisor {
|
|
|
295
380
|
} catch {
|
|
296
381
|
/* ignore */
|
|
297
382
|
}
|
|
383
|
+
this._exitHookInstalled = false;
|
|
298
384
|
}
|
|
299
385
|
}
|
|
300
386
|
|
package/src/lib/audit-logger.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import crypto from "crypto";
|
|
7
7
|
import { safeJsonParse } from "./safe-json.js";
|
|
8
|
+
import { escapeLike } from "./sql-like.js";
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Event types for audit logging.
|
|
@@ -183,13 +184,13 @@ export function queryLogs(db, filters = {}) {
|
|
|
183
184
|
}
|
|
184
185
|
|
|
185
186
|
if (filters.operation) {
|
|
186
|
-
sql += " AND operation LIKE ?";
|
|
187
|
-
params.push(`%${filters.operation}%`);
|
|
187
|
+
sql += " AND operation LIKE ? ESCAPE '\\'";
|
|
188
|
+
params.push(`%${escapeLike(filters.operation)}%`);
|
|
188
189
|
}
|
|
189
190
|
|
|
190
191
|
if (filters.actor) {
|
|
191
|
-
sql += " AND actor LIKE ?";
|
|
192
|
-
params.push(`%${filters.actor}%`);
|
|
192
|
+
sql += " AND actor LIKE ? ESCAPE '\\'";
|
|
193
|
+
params.push(`%${escapeLike(filters.actor)}%`);
|
|
193
194
|
}
|
|
194
195
|
|
|
195
196
|
if (filters.riskLevel) {
|
|
@@ -214,8 +215,8 @@ export function queryLogs(db, filters = {}) {
|
|
|
214
215
|
|
|
215
216
|
if (filters.search) {
|
|
216
217
|
// Search in operation field (primary search field for CLI)
|
|
217
|
-
sql += " AND operation LIKE ?";
|
|
218
|
-
params.push(`%${filters.search}%`);
|
|
218
|
+
sql += " AND operation LIKE ? ESCAPE '\\'";
|
|
219
|
+
params.push(`%${escapeLike(filters.search)}%`);
|
|
219
220
|
}
|
|
220
221
|
|
|
221
222
|
sql += " ORDER BY created_at DESC";
|
|
@@ -151,6 +151,66 @@ export function ensureAutonomousDevTables(db) {
|
|
|
151
151
|
);
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
+
/**
|
|
155
|
+
* Rehydrate _sessions/_adrs from the persisted dev_sessions/
|
|
156
|
+
* architecture_decisions tables. The `cc` CLI runs every command in a fresh
|
|
157
|
+
* process, so without this the Maps start empty and a session/ADR created in a
|
|
158
|
+
* prior invocation is invisible (`cc dev list`/`show`/`adrs` show nothing) and
|
|
159
|
+
* every mutation — recordADR, advancePhase, etc. — throws "Session not found"
|
|
160
|
+
* against the empty Map. Call after ensureAutonomousDevTables(db).
|
|
161
|
+
*/
|
|
162
|
+
export function loadFromDb(db) {
|
|
163
|
+
if (!db) return 0;
|
|
164
|
+
_sessions.clear();
|
|
165
|
+
_adrs.clear();
|
|
166
|
+
|
|
167
|
+
const parse = (v, fallback) => {
|
|
168
|
+
if (v == null) return fallback;
|
|
169
|
+
try {
|
|
170
|
+
return JSON.parse(v);
|
|
171
|
+
} catch {
|
|
172
|
+
return fallback;
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
const sessionRows = db.prepare(`SELECT * FROM dev_sessions`).all();
|
|
177
|
+
for (const row of sessionRows) {
|
|
178
|
+
_sessions.set(row.session_id, {
|
|
179
|
+
sessionId: row.session_id,
|
|
180
|
+
requirement: row.requirement,
|
|
181
|
+
currentPhase: row.current_phase,
|
|
182
|
+
status: row.status,
|
|
183
|
+
autonomyLevel: row.autonomy_level ?? 2,
|
|
184
|
+
codeChanges: parse(row.code_changes, []),
|
|
185
|
+
testResults: parse(row.test_results, null),
|
|
186
|
+
reviewFeedback: parse(row.review_feedback, null),
|
|
187
|
+
startedAt: row.started_at,
|
|
188
|
+
completedAt: row.completed_at ?? null,
|
|
189
|
+
createdBy: row.created_by ?? null,
|
|
190
|
+
updatedAt: row.updated_at,
|
|
191
|
+
_seq: ++_seq,
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const adrRows = db.prepare(`SELECT * FROM architecture_decisions`).all();
|
|
196
|
+
for (const row of adrRows) {
|
|
197
|
+
_adrs.set(row.adr_id, {
|
|
198
|
+
adrId: row.adr_id,
|
|
199
|
+
sessionId: row.session_id,
|
|
200
|
+
title: row.title,
|
|
201
|
+
context: row.context,
|
|
202
|
+
decision: row.decision,
|
|
203
|
+
consequences: row.consequences ?? "",
|
|
204
|
+
alternatives: parse(row.alternatives, []),
|
|
205
|
+
status: row.status,
|
|
206
|
+
createdAt: row.created_at,
|
|
207
|
+
_seq: ++_seq,
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return _sessions.size + _adrs.size;
|
|
212
|
+
}
|
|
213
|
+
|
|
154
214
|
/* ── Catalogs ──────────────────────────────────────────────── */
|
|
155
215
|
|
|
156
216
|
export function listAutonomyLevels() {
|
package/src/lib/chat-core.js
CHANGED
|
@@ -134,6 +134,11 @@ export async function streamOllama(
|
|
|
134
134
|
const reader = response.body.getReader();
|
|
135
135
|
const decoder = new TextDecoder();
|
|
136
136
|
let fullResponse = "";
|
|
137
|
+
// Buffer incomplete lines across reads: an NDJSON line can be split across two
|
|
138
|
+
// stream chunks (TCP doesn't align to '\n'), so parsing each chunk in
|
|
139
|
+
// isolation would drop the split line entirely (both halves fail JSON.parse).
|
|
140
|
+
// Keep the trailing partial for the next read — same pattern as streamAnthropic.
|
|
141
|
+
let buf = "";
|
|
137
142
|
|
|
138
143
|
try {
|
|
139
144
|
while (true) {
|
|
@@ -141,10 +146,12 @@ export async function streamOllama(
|
|
|
141
146
|
if (done) break;
|
|
142
147
|
guard.bump();
|
|
143
148
|
|
|
144
|
-
|
|
145
|
-
const lines =
|
|
149
|
+
buf += decoder.decode(value, { stream: true });
|
|
150
|
+
const lines = buf.split("\n");
|
|
151
|
+
buf = lines.pop() || "";
|
|
146
152
|
|
|
147
153
|
for (const line of lines) {
|
|
154
|
+
if (!line) continue;
|
|
148
155
|
try {
|
|
149
156
|
const json = JSON.parse(line);
|
|
150
157
|
if (json.message?.content) {
|
|
@@ -225,6 +232,11 @@ export async function streamOpenAI(
|
|
|
225
232
|
const reader = response.body.getReader();
|
|
226
233
|
const decoder = new TextDecoder();
|
|
227
234
|
let fullResponse = "";
|
|
235
|
+
// Buffer incomplete lines across reads: an SSE `data:` line can be split
|
|
236
|
+
// across two stream chunks, so parsing each chunk in isolation would drop the
|
|
237
|
+
// split line (both halves fail JSON.parse) — losing content and usage. Keep
|
|
238
|
+
// the trailing partial for the next read — same pattern as streamAnthropic.
|
|
239
|
+
let buf = "";
|
|
228
240
|
|
|
229
241
|
try {
|
|
230
242
|
while (true) {
|
|
@@ -232,8 +244,9 @@ export async function streamOpenAI(
|
|
|
232
244
|
if (done) break;
|
|
233
245
|
guard.bump();
|
|
234
246
|
|
|
235
|
-
|
|
236
|
-
const lines =
|
|
247
|
+
buf += decoder.decode(value, { stream: true });
|
|
248
|
+
const lines = buf.split("\n");
|
|
249
|
+
buf = lines.pop() || "";
|
|
237
250
|
|
|
238
251
|
for (const line of lines) {
|
|
239
252
|
if (line.startsWith("data: ")) {
|
|
@@ -129,6 +129,62 @@ export function ensureGovernanceTables(db) {
|
|
|
129
129
|
);
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
+
/**
|
|
133
|
+
* Rehydrate _decisions/_agentLevels from the persisted governance_decisions/
|
|
134
|
+
* autonomy_levels tables. The `cc` CLI runs every command in a fresh process, so
|
|
135
|
+
* without this the Maps start empty and a decision/level set in a prior
|
|
136
|
+
* invocation is invisible (`cc collab decisions`/`show`/`agents` show nothing),
|
|
137
|
+
* decision voting throws "not found", and setAutonomyLevel on a cold Map takes
|
|
138
|
+
* the INSERT branch on an already-persisted agent_id → PRIMARY KEY conflict.
|
|
139
|
+
* Call after ensureGovernanceTables(db).
|
|
140
|
+
*/
|
|
141
|
+
export function loadFromDb(db) {
|
|
142
|
+
if (!db) return 0;
|
|
143
|
+
_decisions.clear();
|
|
144
|
+
_agentLevels.clear();
|
|
145
|
+
|
|
146
|
+
const parse = (v, fallback) => {
|
|
147
|
+
if (v == null) return fallback;
|
|
148
|
+
try {
|
|
149
|
+
return JSON.parse(v);
|
|
150
|
+
} catch {
|
|
151
|
+
return fallback;
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
const decisionRows = db.prepare(`SELECT * FROM governance_decisions`).all();
|
|
156
|
+
for (const row of decisionRows) {
|
|
157
|
+
_decisions.set(row.decision_id, {
|
|
158
|
+
decisionId: row.decision_id,
|
|
159
|
+
type: row.type,
|
|
160
|
+
proposal: row.proposal,
|
|
161
|
+
status: row.status,
|
|
162
|
+
votes: parse(row.votes, {}),
|
|
163
|
+
resolution: row.resolution ?? null,
|
|
164
|
+
executedAt: row.executed_at ?? null,
|
|
165
|
+
createdAt: row.created_at,
|
|
166
|
+
updatedAt: row.updated_at,
|
|
167
|
+
_seq: ++_seq,
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const levelRows = db.prepare(`SELECT * FROM autonomy_levels`).all();
|
|
172
|
+
for (const row of levelRows) {
|
|
173
|
+
_agentLevels.set(row.agent_id, {
|
|
174
|
+
agentId: row.agent_id,
|
|
175
|
+
currentLevel: row.current_level,
|
|
176
|
+
permissions: parse(row.permissions, []),
|
|
177
|
+
adjustmentHistory: parse(row.adjustment_history, []),
|
|
178
|
+
lastReviewAt: row.last_review_at ?? null,
|
|
179
|
+
createdAt: row.created_at,
|
|
180
|
+
updatedAt: row.updated_at,
|
|
181
|
+
_seq: ++_seq,
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return _decisions.size + _agentLevels.size;
|
|
186
|
+
}
|
|
187
|
+
|
|
132
188
|
/* ── Catalogs ──────────────────────────────────────────────── */
|
|
133
189
|
|
|
134
190
|
export function listDecisionTypes() {
|
|
@@ -129,6 +129,74 @@ export function ensureGovernanceTables(db) {
|
|
|
129
129
|
);
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
+
/**
|
|
133
|
+
* Rehydrate _proposals/_votes/_proposalVotes from the persisted
|
|
134
|
+
* governance_proposals/governance_votes tables. The `cc` CLI runs every command
|
|
135
|
+
* in a fresh process, so without this the Maps start empty and a proposal/vote
|
|
136
|
+
* created in a prior invocation is invisible (`cc governance list`/`show`/
|
|
137
|
+
* `votes`/`tally`/`stats` show nothing) and activate/close/castVote throw
|
|
138
|
+
* "Proposal not found". Rebuilds the _proposalVotes proposalId→Set<voteId>
|
|
139
|
+
* index from the votes too. Call after ensureGovernanceTables(db).
|
|
140
|
+
*/
|
|
141
|
+
export function loadFromDb(db) {
|
|
142
|
+
if (!db) return 0;
|
|
143
|
+
_proposals.clear();
|
|
144
|
+
_votes.clear();
|
|
145
|
+
_proposalVotes.clear();
|
|
146
|
+
|
|
147
|
+
const parse = (v, fallback) => {
|
|
148
|
+
if (v == null) return fallback;
|
|
149
|
+
try {
|
|
150
|
+
return JSON.parse(v);
|
|
151
|
+
} catch {
|
|
152
|
+
return fallback;
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
const proposalRows = db.prepare(`SELECT * FROM governance_proposals`).all();
|
|
157
|
+
for (const row of proposalRows) {
|
|
158
|
+
_proposals.set(row.id, {
|
|
159
|
+
id: row.id,
|
|
160
|
+
title: row.title,
|
|
161
|
+
description: row.description ?? null,
|
|
162
|
+
type: row.type,
|
|
163
|
+
proposerDid: row.proposer_did ?? null,
|
|
164
|
+
status: row.status,
|
|
165
|
+
impactLevel: row.impact_level ?? null,
|
|
166
|
+
impactAnalysis: parse(row.impact_analysis, null),
|
|
167
|
+
voteYes: row.vote_yes ?? 0,
|
|
168
|
+
voteNo: row.vote_no ?? 0,
|
|
169
|
+
voteAbstain: row.vote_abstain ?? 0,
|
|
170
|
+
votingStartsAt: row.voting_starts_at ?? null,
|
|
171
|
+
votingEndsAt: row.voting_ends_at ?? null,
|
|
172
|
+
metadata: parse(row.metadata, null),
|
|
173
|
+
createdAt: row.created_at,
|
|
174
|
+
_seq: ++_seq,
|
|
175
|
+
});
|
|
176
|
+
_proposalVotes.set(row.id, new Set());
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const voteRows = db.prepare(`SELECT * FROM governance_votes`).all();
|
|
180
|
+
for (const row of voteRows) {
|
|
181
|
+
_votes.set(row.id, {
|
|
182
|
+
id: row.id,
|
|
183
|
+
proposalId: row.proposal_id,
|
|
184
|
+
voterDid: row.voter_did,
|
|
185
|
+
vote: row.vote,
|
|
186
|
+
reason: row.reason ?? null,
|
|
187
|
+
weight: row.weight ?? 1.0,
|
|
188
|
+
createdAt: row.created_at,
|
|
189
|
+
_seq: ++_seq,
|
|
190
|
+
});
|
|
191
|
+
if (!_proposalVotes.has(row.proposal_id)) {
|
|
192
|
+
_proposalVotes.set(row.proposal_id, new Set());
|
|
193
|
+
}
|
|
194
|
+
_proposalVotes.get(row.proposal_id).add(row.id);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return _proposals.size + _votes.size;
|
|
198
|
+
}
|
|
199
|
+
|
|
132
200
|
/* ── Catalogs ──────────────────────────────────────────────── */
|
|
133
201
|
|
|
134
202
|
export function listProposalTypes() {
|
|
@@ -723,6 +723,69 @@ export function _resetState() {
|
|
|
723
723
|
_reportRetentionMs = COMPLIANCE_DEFAULT_REPORT_RETENTION_MS;
|
|
724
724
|
}
|
|
725
725
|
|
|
726
|
+
/**
|
|
727
|
+
* Rehydrate the in-memory _evidence/_policies Maps from the persisted
|
|
728
|
+
* compliance_* tables. The CLI runs each `cc compliance` subcommand in a fresh
|
|
729
|
+
* node process, so both Maps start empty every invocation. collectEvidence/
|
|
730
|
+
* addPolicy dual-write (Map + INSERT into compliance_evidence/compliance_policies)
|
|
731
|
+
* but generateReport (summary path), scanCompliance and listPolicies read the
|
|
732
|
+
* Maps only — so a `report`/`scan` after `evidence` in a separate process saw 0
|
|
733
|
+
* evidence items and scored 0. (The `report --detailed` path already SELECTed via
|
|
734
|
+
* the command-layer _loadEvidenceFromDb/_loadPoliciesFromDb; this makes the
|
|
735
|
+
* summary/scan/policies paths consistent.) `_reports` is write-only (no read
|
|
736
|
+
* path) and is not rehydrated. Call after ensureComplianceTables(db).
|
|
737
|
+
*/
|
|
738
|
+
export function loadFromDb(db) {
|
|
739
|
+
if (!db) return 0;
|
|
740
|
+
ensureComplianceTables(db);
|
|
741
|
+
_evidence.clear();
|
|
742
|
+
_policies.clear();
|
|
743
|
+
|
|
744
|
+
for (const r of db
|
|
745
|
+
.prepare(
|
|
746
|
+
`SELECT id, framework, type, description, source, status, collected_at
|
|
747
|
+
FROM compliance_evidence ORDER BY collected_at ASC`,
|
|
748
|
+
)
|
|
749
|
+
.all()) {
|
|
750
|
+
_evidence.set(r.id, {
|
|
751
|
+
id: r.id,
|
|
752
|
+
framework: r.framework,
|
|
753
|
+
type: r.type,
|
|
754
|
+
description: r.description || "",
|
|
755
|
+
source: r.source,
|
|
756
|
+
status: r.status,
|
|
757
|
+
collectedAt: r.collected_at,
|
|
758
|
+
});
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
for (const r of db
|
|
762
|
+
.prepare(
|
|
763
|
+
`SELECT id, name, type, framework, rules, enabled, severity, created_at
|
|
764
|
+
FROM compliance_policies ORDER BY created_at ASC`,
|
|
765
|
+
)
|
|
766
|
+
.all()) {
|
|
767
|
+
// One corrupt rules cell must not sink the whole policy load.
|
|
768
|
+
let rules = {};
|
|
769
|
+
try {
|
|
770
|
+
rules = r.rules ? JSON.parse(r.rules) : {};
|
|
771
|
+
} catch {
|
|
772
|
+
rules = {};
|
|
773
|
+
}
|
|
774
|
+
_policies.set(r.id, {
|
|
775
|
+
id: r.id,
|
|
776
|
+
name: r.name,
|
|
777
|
+
type: r.type,
|
|
778
|
+
framework: r.framework,
|
|
779
|
+
rules,
|
|
780
|
+
enabled: !!r.enabled,
|
|
781
|
+
severity: r.severity,
|
|
782
|
+
createdAt: r.created_at,
|
|
783
|
+
});
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
return _evidence.size + _policies.size;
|
|
787
|
+
}
|
|
788
|
+
|
|
726
789
|
// =====================================================================
|
|
727
790
|
// compliance-manager V2 governance overlay (iter17)
|
|
728
791
|
// =====================================================================
|