chainlesschain 0.162.171 → 0.162.173
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/bin/chainlesschain.js +8 -0
- package/package.json +6 -1
- package/src/assets/web-panel/assets/{AIOps-Cf8yb18C.js → AIOps-228_yS1K.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-CsFT6FMt.js → ActionButton-qEKhWWk_.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-DQe_hXMA.js → Analytics-Drma7Pkx.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-Cl9Pp7jk.js → AppLayout-B-gexhEy.js} +4 -4
- package/src/assets/web-panel/assets/{Artifacts-CBEzLVjF.js → Artifacts-CWNSO5Af.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-BS2Un14C.js → Audit-DY3j9Ltk.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-DmcDH8OK.js → BackgroundAgents-Bz2pcyfS.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-DvzjTkkn.js → Backup-Bg5aAkWT.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-DnbpuyME.js → BaseInput-35_LrETp.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-BJRRCm2P.js → Chat-CWvrCIuL.js} +5 -5
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-Bgpxyqd_.js → ChatBubbleRenderer-7iAWWEmJ.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-DFOrWmvm.js → Checkbox-B4qv17qH.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-BIQ2kU6Q.js → Codegen-Co18wV4m.js} +1 -1
- package/src/assets/web-panel/assets/{Col-BI3R-N4I.js → Col-D0RjQKek.js} +1 -1
- package/src/assets/web-panel/assets/{Community-CPiAwsHT.js → Community-C5r80sMV.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-Bv4cslSK.js → Compact-Cnwsi_GQ.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-CSlDG1NZ.js → Compliance-EFmGHrSw.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-CFcRumXf.js → Cowork-7Ix8iqrx.js} +4 -4
- package/src/assets/web-panel/assets/{Cron-DKYKMmOn.js → Cron-Dpvn36K7.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-CxPMByp2.js → Crosschain-DgwE0dXI.js} +1 -1
- package/src/assets/web-panel/assets/{DID-DJqiYw1C.js → DID-79Xkd_Iy.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-D2dLMxqy.js → Dashboard-BX-kQk9j.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-BnJc384A.js → Dropdown-B2hIzIKh.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-DctFvm-J.js → EmailListRenderer-CwgczLkA.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-J_xg-Qop.js → FamilyGuardDashboard-D1dpW73p.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-BckL07Uw.js → Federation-CzGSfm-g.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-B8s5ccSO.js → FormItemContext-Bdgq6Ctr.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-hPMBK2No.js → GenericCardRenderer-BdiR-AVP.js} +1 -1
- package/src/assets/web-panel/assets/{Git-CfMpYLo7.js → Git-CyFl_ZOb.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-Bt3OcrC7.js → Governance-CIJfns5M.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-BlKc336N.js → Inference-U2SL3a9n.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-B6p7og2c.js → KnowledgeGraph-B8TRMic6.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-uv5Re6YR.js → Logs-CN3aA59h.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-CId5JWjX.js → MarkdownRenderer-Op_hHJCw.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-CfNbntHt.js → Marketplace-CIu4bo4n.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-YRXt74Yk.js → McpTools-dMtEtLGH.js} +5 -5
- package/src/assets/web-panel/assets/{Memory-BfQQs-Jd.js → Memory-B2a1qG3t.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-BuGC-4S2.js → MobileBridge-Ci8N7KT8.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-Czieqw1m.js → MobileProjects-CnJwGBSZ.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-DHWHOVCO.js → Mtc-B_yNoA93.js} +5 -5
- package/src/assets/web-panel/assets/{MtcAudit-DWSEbMW-.js → MtcAudit-DLYUJLFa.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-DrhEv1vq.js → Multisig-lGvE7Ulk.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-D8wKCu7E.js → NLProgramming-CSl7-p0U.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-AFeqq0I_.js → Notes-CRzhFyCr.js} +4 -4
- package/src/assets/web-panel/assets/{NotificationSettings-D6qenYUo.js → NotificationSettings-D8vIFpxx.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-CF0X4fyB.js → OrderTableRenderer-BK07A_0l.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-DdfbNqf6.js → Organization-5CnL1jaB.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-BFEvnLfd.js → Overflow-B4QvQ7ku.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-DtL6wbkz.js → P2P-IwrXGm2f.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-CQPriTud.js → PdhVaultBrowser-CNr6Ocb1.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-Bj25ANmR.js → Permissions-CcKqZlw6.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-BNj2Oux0.js → PersonalDataHub-zUZb-JzZ.js} +3 -3
- package/src/assets/web-panel/assets/{Pipeline-Dyj8UEaG.js → Pipeline-mMelf_X6.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-BBUrWRFz.js → Privacy-BaA6CMRz.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-BdX7uQn6.js → ProjectInit-CI8OJYpf.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-BghtW1zr.js → ProjectSettings-C6ZJ3hQv.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-9VTquZCz.js → Projects-BVljPeGz.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-D-0K_Eza.js → Providers-D_bjZHj6.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-DDaN30_D.js → QrScannerModal-TgVSKKTP.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-DfHlifOj.js → QuickAsk-CnnleZmK.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-CgLIvYE2.js → Recommend-zqJL4tgH.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-DpOPrwE4.js → RemoteSession-bBFpdwjH.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-wMexlbCE.js → Reputation-tKkKrza-.js} +1 -1
- package/src/assets/web-panel/assets/{Row-D9aD_nrc.js → Row-DgQaPsSR.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-Drg7l6zu.js → RssFeed-B3PJQQ_a.js} +3 -3
- package/src/assets/web-panel/assets/{Search-BKO1nrwN.js → Search-BX2HUESa.js} +1 -1
- package/src/assets/web-panel/assets/{Security-G3Kyk-TG.js → Security-aqzxU6JQ.js} +4 -4
- package/src/assets/web-panel/assets/{Services-xJReTOna.js → Services-BiehYAcJ.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-ldVDVTPG.js → Skeleton-aWL9v64n.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-emwNYV0j.js → Skills-DnLhre12.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-CZYwGp1K.js → Sla-C2ZJiegm.js} +1 -1
- package/src/assets/web-panel/assets/SpeechSettings-BpQdJ1IM.js +1 -0
- package/src/assets/web-panel/assets/{SyncSettings-Dcs5Hhj6.js → SyncSettings-C93cxqz8.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-CerFAo26.js → Tasks-oSM3jeQI.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-BdZUbOg3.js → Templates-DJa_a4iY.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-B4c_7Bsw.js → Tenant-B7p9ktEF.js} +1 -1
- package/src/assets/web-panel/assets/Terminal-aljUKGFD.js +3 -0
- package/src/assets/web-panel/assets/{TimelineRenderer-tc6sp0TV.js → TimelineRenderer-CDcFH-4e.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-Bw_vkMJq.js → Tokens-KISm6N5n.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-DkbJnpvz.js → Trigger-BBYrtPba.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-CIf9kqN1.js → Trust-BMuSnufM.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-Cjwllnea.js → UkeySign-BqZbe27i.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-kgfkY7AN.js → VideoEditing-C-21zOQc.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-CYWXt4u9.js → Wallet-EwfAuGhE.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-QgPwyWCO.js → WebAuthn-D__2NkcW.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-Co0lha18.js → WorkflowEditor-C7pTi9eg.js} +1 -1
- package/src/assets/web-panel/assets/{chat-CI__Ox-r.js → chat-DGJsLa46.js} +1 -1
- package/src/assets/web-panel/assets/{colors-Csv0eYYd.js → colors-DLGee_hV.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-e53UCdHy.js → compact-item-uXOmbkDm.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-BMPGRDhV.js → createContext-CsPfwwcp.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-CVrl2cXX.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-Dz68qIAq.js → hasIn-BHvO8oYD.js} +1 -1
- package/src/assets/web-panel/assets/{index-CoGSbW5J.js → index-477LYji2.js} +1 -1
- package/src/assets/web-panel/assets/{index-53ljQo_x.js → index-9F6z582g.js} +1 -1
- package/src/assets/web-panel/assets/{index-ajz0E0pK.js → index-B2NtdqkO.js} +1 -1
- package/src/assets/web-panel/assets/{index-ygfUVVFv.js → index-B5XTuu1V.js} +1 -1
- package/src/assets/web-panel/assets/{index-wcCouSNq.js → index-BDV08Lfd.js} +1 -1
- package/src/assets/web-panel/assets/{index-t6f80uqL.js → index-BOXMd0h7.js} +17 -17
- package/src/assets/web-panel/assets/index-BPY_5R3R.js +1 -0
- package/src/assets/web-panel/assets/{index-BHkDRNA5.js → index-BZa2DYkz.js} +1 -1
- package/src/assets/web-panel/assets/{index-DCl4Xb4N.js → index-Bb8I5bJW.js} +1 -1
- package/src/assets/web-panel/assets/{index-BW2dImbg.js → index-By5mviLz.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dk9Gi8xd.js → index-C0mLGe0N.js} +1 -1
- package/src/assets/web-panel/assets/{index-CXuON9OG.js → index-C0w_0UmL.js} +1 -1
- package/src/assets/web-panel/assets/{index-B1s1B8Iy.js → index-CN3eksmo.js} +1 -1
- package/src/assets/web-panel/assets/{index-DJqQL6so.js → index-CNCYZBCQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-BT3CV4Nh.js → index-Cc_spyrU.js} +1 -1
- package/src/assets/web-panel/assets/{index-CNtZMPKV.js → index-CeJ_IuUy.js} +1 -1
- package/src/assets/web-panel/assets/{index-C-NbcAbP.js → index-Ckb7veFD.js} +1 -1
- package/src/assets/web-panel/assets/{index-K5E_wjut.js → index-ClWReh9U.js} +1 -1
- package/src/assets/web-panel/assets/index-CrRvYSFJ.js +1 -0
- package/src/assets/web-panel/assets/{index-5iicv5af.js → index-D3UkkZps.js} +1 -1
- package/src/assets/web-panel/assets/{index-CrsoSnQF.js → index-D73CnO2G.js} +1 -1
- package/src/assets/web-panel/assets/{index-HbhQRrM2.js → index-D7EKxUXQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-DyqcHiL1.js → index-DA8wNocR.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dtjm1K1a.js → index-DEOm1Go8.js} +1 -1
- package/src/assets/web-panel/assets/{index--7tHEadk.js → index-DHMZKkRS.js} +1 -1
- package/src/assets/web-panel/assets/{index-DnXm3Qsh.js → index-DJBB-U5Z.js} +1 -1
- package/src/assets/web-panel/assets/{index-DVCd2aMX.js → index-DJkVI1UW.js} +1 -1
- package/src/assets/web-panel/assets/{index-CpTzqJ0Z.js → index-DbkMc0Qq.js} +1 -1
- package/src/assets/web-panel/assets/{index-DctYrVMq.js → index-DjX8mK9d.js} +1 -1
- package/src/assets/web-panel/assets/{index-_LmPlyeV.js → index-DmcFSHuA.js} +1 -1
- package/src/assets/web-panel/assets/{index-CvLBQk_M.js → index-DqNI4xlm.js} +1 -1
- package/src/assets/web-panel/assets/{index-C53o-MdJ.js → index-DvQrYrw_.js} +1 -1
- package/src/assets/web-panel/assets/{index-BOpz2qS1.js → index-Gqs5qts7.js} +1 -1
- package/src/assets/web-panel/assets/{index-N9DkR1i7.js → index-MAaNHDU0.js} +1 -1
- package/src/assets/web-panel/assets/{index-CYUxs6J1.js → index-YslvEzZs.js} +1 -1
- package/src/assets/web-panel/assets/{index-D0bg74e1.js → index-gTQZVYbs.js} +1 -1
- package/src/assets/web-panel/assets/{index-C5hLtxVz.js → index-hzI1TGEs.js} +1 -1
- package/src/assets/web-panel/assets/{index-B4lKPJy1.js → index-vWJiZGAS.js} +1 -1
- package/src/assets/web-panel/assets/{index-CyLUaP2i.js → index-wnZd4y25.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-DVCeQJrT.js → initDefaultProps-oK6Ac1vm.js} +1 -1
- package/src/assets/web-panel/assets/{motion-chBCR_8v.js → motion-BmETDqwI.js} +1 -1
- package/src/assets/web-panel/assets/{move-BziPlrh6.js → move-0DfUhr7q.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-Cenk0OD7.js → mtc-parser-BDG-x4aO.js} +1 -1
- package/src/assets/web-panel/assets/{omit-D-AiRsei.js → omit-C_n1NOjZ.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-CHw3Fvqt.js → pickAttrs-j5w-2Trf.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-g8I-rCad.js → placementArrow-DDVTNAah.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-BWffAr9k.js → responsiveObserve-DM30qzcv.js} +1 -1
- package/src/assets/web-panel/assets/{slide-BmUQqhkb.js → slide-BcVzNlnc.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-B89gCO-y.js → statusUtils-VQh4j7zt.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-x1bnCF73.js → styleChecker-DcHl95y_.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-B-k1_Ggw.js → useFlexGapSupport-C5bRw-Km.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-Bc3PUqQk.js → useFs-IcE9exrQ.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-D8qFDX1I.js → usePersonalDataHub-BGv3NgE4.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-UaL5-WGg.js → vnode-B9pXxNhd.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-Dv7bsbLs.js → zoom-Bba0fIkh.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/permissions.js +24 -1
- package/src/index.js +63 -845
- package/src/lib/agent-ipc-bus.js +331 -0
- package/src/lib/context-source-ledger.js +164 -0
- package/src/lib/execution-trace/index.js +10 -0
- package/src/lib/execution-trace/metrics-collector.js +218 -0
- package/src/lib/execution-trace/trace-context.js +182 -0
- package/src/lib/hook-manager.js +17 -0
- package/src/lib/hooks-v2-runtime.js +278 -0
- package/src/lib/metrics-collector.js +127 -0
- package/src/lib/observability/index.js +35 -0
- package/src/lib/observability/otlp-exporter.js +260 -0
- package/src/lib/otlp-exporter.js +45 -0
- package/src/lib/process-execution-broker/SPAWN_AUDIT_REPORT.md +117 -0
- package/src/lib/process-execution-broker/index.js +450 -0
- package/src/lib/process-execution-broker/patch-child-process.js +50 -0
- package/src/lib/process-execution-broker/spawn-audit.json +3814 -0
- package/src/lib/runtime-provenance-ledger.js +190 -0
- package/src/lib/session-hooks.js +41 -0
- package/src/program-base.js +4 -1
- package/src/repl/agent-repl.js +2 -0
- package/src/assets/web-panel/assets/SpeechSettings-CyaPrzOF.js +0 -1
- package/src/assets/web-panel/assets/Terminal-VVFLS3Ol.js +0 -3
- package/src/assets/web-panel/assets/devWarning-BIulobq7.js +0 -1
- package/src/assets/web-panel/assets/index-BGkiYnET.js +0 -1
- package/src/assets/web-panel/assets/index-Eyhrr_3u.js +0 -1
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MetricsCollector - CLI runtime metrics collection (M3)
|
|
3
|
+
*
|
|
4
|
+
* Collects counters, gauges, histograms for performance monitoring
|
|
5
|
+
* with OTLP export support (M8 integration)
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export class MetricsCollector {
|
|
9
|
+
constructor() {
|
|
10
|
+
this._counters = new Map();
|
|
11
|
+
this._gauges = new Map();
|
|
12
|
+
this._histograms = new Map();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Increment a counter metric
|
|
17
|
+
* @param {string} name - Metric name
|
|
18
|
+
* @param {number} value - Increment amount (default 1)
|
|
19
|
+
* @param {object} labels - Metric labels
|
|
20
|
+
*/
|
|
21
|
+
counter(name, value = 1, labels = {}) {
|
|
22
|
+
const key = this._key(name, labels);
|
|
23
|
+
if (!this._counters.has(key)) {
|
|
24
|
+
this._counters.set(key, { name, value: 0, labels });
|
|
25
|
+
}
|
|
26
|
+
this._counters.get(key).value += value;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Set a gauge metric
|
|
31
|
+
* @param {string} name - Metric name
|
|
32
|
+
* @param {number} value - Gauge value
|
|
33
|
+
* @param {object} labels - Metric labels
|
|
34
|
+
*/
|
|
35
|
+
gauge(name, value, labels = {}) {
|
|
36
|
+
const key = this._key(name, labels);
|
|
37
|
+
this._gauges.set(key, { name, value, labels, timestamp: Date.now() });
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Record a histogram observation
|
|
42
|
+
* @param {string} name - Metric name
|
|
43
|
+
* @param {number} value - Observed value
|
|
44
|
+
* @param {object} labels - Metric labels
|
|
45
|
+
*/
|
|
46
|
+
histogram(name, value, labels = {}) {
|
|
47
|
+
const key = this._key(name, labels);
|
|
48
|
+
if (!this._histograms.has(key)) {
|
|
49
|
+
this._histograms.set(key, {
|
|
50
|
+
name,
|
|
51
|
+
count: 0,
|
|
52
|
+
sum: 0,
|
|
53
|
+
min: Infinity,
|
|
54
|
+
max: -Infinity,
|
|
55
|
+
labels,
|
|
56
|
+
values: [],
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
const h = this._histograms.get(key);
|
|
60
|
+
h.count++;
|
|
61
|
+
h.sum += value;
|
|
62
|
+
h.min = Math.min(h.min, value);
|
|
63
|
+
h.max = Math.max(h.max, value);
|
|
64
|
+
// Keep last 1000 values for percentile calculation
|
|
65
|
+
if (h.values.length < 1000) {
|
|
66
|
+
h.values.push(value);
|
|
67
|
+
} else {
|
|
68
|
+
h.values[h.count % 1000] = value;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Time a function execution and record duration
|
|
74
|
+
* @param {string} name - Metric name
|
|
75
|
+
* @param {Function} fn - Function to time
|
|
76
|
+
* @param {object} labels - Metric labels
|
|
77
|
+
* @returns {*} Function result
|
|
78
|
+
*/
|
|
79
|
+
async timer(name, fn, labels = {}) {
|
|
80
|
+
const start = performance.now();
|
|
81
|
+
try {
|
|
82
|
+
return await fn();
|
|
83
|
+
} finally {
|
|
84
|
+
const duration = performance.now() - start;
|
|
85
|
+
this.histogram(name, duration, labels);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Get all collected metrics
|
|
91
|
+
* @returns {object} All metrics
|
|
92
|
+
*/
|
|
93
|
+
snapshot() {
|
|
94
|
+
return {
|
|
95
|
+
counters: Array.from(this._counters.values()),
|
|
96
|
+
gauges: Array.from(this._gauges.values()),
|
|
97
|
+
histograms: Array.from(this._histograms.values()).map((h) => ({
|
|
98
|
+
name: h.name,
|
|
99
|
+
count: h.count,
|
|
100
|
+
sum: h.sum,
|
|
101
|
+
min: h.min,
|
|
102
|
+
max: h.max,
|
|
103
|
+
avg: h.sum / h.count,
|
|
104
|
+
labels: h.labels,
|
|
105
|
+
})),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Reset all metrics
|
|
111
|
+
*/
|
|
112
|
+
reset() {
|
|
113
|
+
this._counters.clear();
|
|
114
|
+
this._gauges.clear();
|
|
115
|
+
this._histograms.clear();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
_key(name, labels) {
|
|
119
|
+
const labelStr = Object.entries(labels)
|
|
120
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
121
|
+
.map(([k, v]) => `${k}=${v}`)
|
|
122
|
+
.join(",");
|
|
123
|
+
return labelStr ? `${name}{${labelStr}}` : name;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export const metricsCollector = new MetricsCollector();
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Observability - 可观测性模块统一导出
|
|
3
|
+
* M3 阶段模块:包含分布式追踪 + 性能指标收集
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
traceContext,
|
|
8
|
+
TraceContext,
|
|
9
|
+
} from "../execution-trace/trace-context.js";
|
|
10
|
+
import {
|
|
11
|
+
metricsCollector,
|
|
12
|
+
MetricsCollector,
|
|
13
|
+
} from "../execution-trace/metrics-collector.js";
|
|
14
|
+
|
|
15
|
+
export { traceContext, TraceContext, metricsCollector, MetricsCollector };
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* 初始化可观测性模块
|
|
19
|
+
* @param {Object} [options={}]
|
|
20
|
+
* @param {boolean} [options.tracingEnabled=true] - 是否启用追踪
|
|
21
|
+
* @param {boolean} [options.metricsEnabled=true] - 是否启用指标收集
|
|
22
|
+
*/
|
|
23
|
+
export function initObservability(options = {}) {
|
|
24
|
+
const { tracingEnabled = true, metricsEnabled = true } = options;
|
|
25
|
+
|
|
26
|
+
// 可观测性模块初始化逻辑
|
|
27
|
+
return {
|
|
28
|
+
tracingEnabled,
|
|
29
|
+
metricsEnabled,
|
|
30
|
+
traceContext,
|
|
31
|
+
metricsCollector,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export * from "../execution-trace/index.js";
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OTLP Exporter — M8 Observability
|
|
3
|
+
* OpenTelemetry Protocol exporter for spans and metrics
|
|
4
|
+
* Sends to localhost:4318 by default, with batching and retry
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import http from "node:http";
|
|
8
|
+
import https from "node:https";
|
|
9
|
+
import { URL } from "node:url";
|
|
10
|
+
|
|
11
|
+
class OtlpExporter {
|
|
12
|
+
constructor(options = {}) {
|
|
13
|
+
this.endpoint =
|
|
14
|
+
options.endpoint ||
|
|
15
|
+
process.env.OTEL_EXPORTER_OTLP_ENDPOINT ||
|
|
16
|
+
"http://localhost:4318";
|
|
17
|
+
this.headers = options.headers || {};
|
|
18
|
+
this.serviceName =
|
|
19
|
+
options.serviceName ||
|
|
20
|
+
process.env.OTEL_SERVICE_NAME ||
|
|
21
|
+
"chainlesschain-cli";
|
|
22
|
+
this.batchSize = options.batchSize || 512;
|
|
23
|
+
this.flushIntervalMs = options.flushIntervalMs || 5000;
|
|
24
|
+
this._spanBuffer = [];
|
|
25
|
+
this._metricBuffer = [];
|
|
26
|
+
this._timer = null;
|
|
27
|
+
this._droppedSpans = 0;
|
|
28
|
+
this._droppedMetrics = 0;
|
|
29
|
+
this._failedExports = 0;
|
|
30
|
+
this._successfulExports = 0;
|
|
31
|
+
this._enabled = options.enabled !== false;
|
|
32
|
+
if (this._enabled) {
|
|
33
|
+
this._startFlushTimer();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
_startFlushTimer() {
|
|
38
|
+
if (this._timer) clearInterval(this._timer);
|
|
39
|
+
this._timer = setInterval(() => this.flush(), this.flushIntervalMs);
|
|
40
|
+
this._timer.unref?.();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
_getHttpModule(urlStr) {
|
|
44
|
+
return urlStr.startsWith("https:") ? https : http;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
_post(path, data, contentType) {
|
|
48
|
+
if (!this._enabled) return Promise.resolve();
|
|
49
|
+
return new Promise((resolve) => {
|
|
50
|
+
try {
|
|
51
|
+
const url = new URL(path, this.endpoint);
|
|
52
|
+
const mod = this._getHttpModule(url.protocol);
|
|
53
|
+
const payload = JSON.stringify(data);
|
|
54
|
+
const req = mod.request(
|
|
55
|
+
{
|
|
56
|
+
hostname: url.hostname,
|
|
57
|
+
port: url.port,
|
|
58
|
+
path: url.pathname + url.search,
|
|
59
|
+
method: "POST",
|
|
60
|
+
headers: {
|
|
61
|
+
"Content-Type": contentType,
|
|
62
|
+
"Content-Length": Buffer.byteLength(payload),
|
|
63
|
+
...this.headers,
|
|
64
|
+
},
|
|
65
|
+
timeout: 10000,
|
|
66
|
+
},
|
|
67
|
+
(res) => {
|
|
68
|
+
res.resume();
|
|
69
|
+
if (res.statusCode >= 200 && res.statusCode < 300) {
|
|
70
|
+
this._successfulExports++;
|
|
71
|
+
} else {
|
|
72
|
+
this._failedExports++;
|
|
73
|
+
}
|
|
74
|
+
resolve();
|
|
75
|
+
},
|
|
76
|
+
);
|
|
77
|
+
req.on("error", () => {
|
|
78
|
+
this._failedExports++;
|
|
79
|
+
resolve();
|
|
80
|
+
});
|
|
81
|
+
req.on("timeout", () => {
|
|
82
|
+
req.destroy();
|
|
83
|
+
this._failedExports++;
|
|
84
|
+
resolve();
|
|
85
|
+
});
|
|
86
|
+
req.write(payload);
|
|
87
|
+
req.end();
|
|
88
|
+
} catch {
|
|
89
|
+
resolve();
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
exportSpans(spans) {
|
|
95
|
+
if (!this._enabled) return;
|
|
96
|
+
for (const span of spans) {
|
|
97
|
+
if (this._spanBuffer.length >= this.batchSize) {
|
|
98
|
+
this._spanBuffer.shift();
|
|
99
|
+
this._droppedSpans++;
|
|
100
|
+
}
|
|
101
|
+
this._spanBuffer.push({
|
|
102
|
+
resourceSpans: [
|
|
103
|
+
{
|
|
104
|
+
resource: {
|
|
105
|
+
attributes: [
|
|
106
|
+
{
|
|
107
|
+
key: "service.name",
|
|
108
|
+
value: { stringValue: this.serviceName },
|
|
109
|
+
},
|
|
110
|
+
],
|
|
111
|
+
},
|
|
112
|
+
scopeSpans: [
|
|
113
|
+
{
|
|
114
|
+
scope: { name: span.component || "chainlesschain" },
|
|
115
|
+
spans: [this._toOtlpSpan(span)],
|
|
116
|
+
},
|
|
117
|
+
],
|
|
118
|
+
},
|
|
119
|
+
],
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
_toOtlpSpan(span) {
|
|
125
|
+
return {
|
|
126
|
+
traceId: span.traceId || "",
|
|
127
|
+
spanId: span.spanId || "",
|
|
128
|
+
parentSpanId: span.parentSpanId || "",
|
|
129
|
+
name: span.name || "unknown",
|
|
130
|
+
kind: this._toSpanKind(span.kind),
|
|
131
|
+
startTimeUnixNano: (span.startTime || Date.now()) * 1_000_000,
|
|
132
|
+
endTimeUnixNano: (span.endTime || Date.now()) * 1_000_000,
|
|
133
|
+
attributes: Object.entries(span.attributes || {}).map(([k, v]) => ({
|
|
134
|
+
key: k,
|
|
135
|
+
value: this._toAttrValue(v),
|
|
136
|
+
})),
|
|
137
|
+
status: { code: span.error ? 2 : 1, message: span.error?.message || "" },
|
|
138
|
+
events: (span.events || []).map((e) => ({
|
|
139
|
+
timeUnixNano: (e.time || Date.now()) * 1_000_000,
|
|
140
|
+
name: e.name,
|
|
141
|
+
attributes: Object.entries(e.attributes || {}).map(([k, v]) => ({
|
|
142
|
+
key: k,
|
|
143
|
+
value: this._toAttrValue(v),
|
|
144
|
+
})),
|
|
145
|
+
})),
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
_toSpanKind(kind) {
|
|
150
|
+
const map = { internal: 0, server: 1, client: 2, producer: 3, consumer: 4 };
|
|
151
|
+
return map[kind] ?? 0;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
_toAttrValue(v) {
|
|
155
|
+
if (typeof v === "string") return { stringValue: v };
|
|
156
|
+
if (typeof v === "number")
|
|
157
|
+
return Number.isInteger(v) ? { intValue: String(v) } : { doubleValue: v };
|
|
158
|
+
if (typeof v === "boolean") return { boolValue: v };
|
|
159
|
+
return { stringValue: String(v) };
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
exportMetrics(metrics) {
|
|
163
|
+
if (!this._enabled) return;
|
|
164
|
+
for (const metric of metrics) {
|
|
165
|
+
if (this._metricBuffer.length >= this.batchSize) {
|
|
166
|
+
this._metricBuffer.shift();
|
|
167
|
+
this._droppedMetrics++;
|
|
168
|
+
}
|
|
169
|
+
this._metricBuffer.push({
|
|
170
|
+
resourceMetrics: [
|
|
171
|
+
{
|
|
172
|
+
resource: {
|
|
173
|
+
attributes: [
|
|
174
|
+
{
|
|
175
|
+
key: "service.name",
|
|
176
|
+
value: { stringValue: this.serviceName },
|
|
177
|
+
},
|
|
178
|
+
],
|
|
179
|
+
},
|
|
180
|
+
scopeMetrics: [
|
|
181
|
+
{
|
|
182
|
+
scope: { name: metric.component || "chainlesschain" },
|
|
183
|
+
metrics: [this._toOtlpMetric(metric)],
|
|
184
|
+
},
|
|
185
|
+
],
|
|
186
|
+
},
|
|
187
|
+
],
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
_toOtlpMetric(metric) {
|
|
193
|
+
return {
|
|
194
|
+
name: metric.name,
|
|
195
|
+
description: metric.description || "",
|
|
196
|
+
unit: metric.unit || "1",
|
|
197
|
+
[metric.type === "histogram"
|
|
198
|
+
? "histogram"
|
|
199
|
+
: metric.type === "sum"
|
|
200
|
+
? "sum"
|
|
201
|
+
: "gauge"]: {
|
|
202
|
+
dataPoints: [
|
|
203
|
+
{
|
|
204
|
+
attributes: Object.entries(metric.attributes || {}).map(
|
|
205
|
+
([k, v]) => ({ key: k, value: this._toAttrValue(v) }),
|
|
206
|
+
),
|
|
207
|
+
timeUnixNano: Date.now() * 1_000_000,
|
|
208
|
+
...(metric.type === "histogram"
|
|
209
|
+
? {
|
|
210
|
+
count: metric.value?.count || 0,
|
|
211
|
+
sum: metric.value?.sum || 0,
|
|
212
|
+
bucketCounts: metric.value?.bucketCounts || [],
|
|
213
|
+
explicitBounds: metric.value?.explicitBounds || [],
|
|
214
|
+
}
|
|
215
|
+
: { asDouble: metric.value || 0 }),
|
|
216
|
+
},
|
|
217
|
+
],
|
|
218
|
+
aggregationTemporality: 1,
|
|
219
|
+
isMonotonic: metric.type === "sum",
|
|
220
|
+
},
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
async flush() {
|
|
225
|
+
if (!this._enabled) return;
|
|
226
|
+
const spans = this._spanBuffer.splice(0);
|
|
227
|
+
const metrics = this._metricBuffer.splice(0);
|
|
228
|
+
const promises = [];
|
|
229
|
+
for (const span of spans)
|
|
230
|
+
promises.push(this._post("/v1/traces", span, "application/json"));
|
|
231
|
+
for (const metric of metrics)
|
|
232
|
+
promises.push(this._post("/v1/metrics", metric, "application/json"));
|
|
233
|
+
await Promise.allSettled(promises);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
shutdown() {
|
|
237
|
+
if (this._timer) clearInterval(this._timer);
|
|
238
|
+
return this.flush();
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
getStats() {
|
|
242
|
+
return {
|
|
243
|
+
enabled: this._enabled,
|
|
244
|
+
bufferedSpans: this._spanBuffer.length,
|
|
245
|
+
bufferedMetrics: this._metricBuffer.length,
|
|
246
|
+
droppedSpans: this._droppedSpans,
|
|
247
|
+
droppedMetrics: this._droppedMetrics,
|
|
248
|
+
failedExports: this._failedExports,
|
|
249
|
+
successfulExports: this._successfulExports,
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
let _defaultExporter = null;
|
|
255
|
+
export function getDefaultOtlpExporter() {
|
|
256
|
+
if (!_defaultExporter) _defaultExporter = new OtlpExporter();
|
|
257
|
+
return _defaultExporter;
|
|
258
|
+
}
|
|
259
|
+
export { OtlpExporter };
|
|
260
|
+
export default OtlpExporter;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OTLP Exporter - Minimal OTLP/HTTP trace exporter for M6 observability
|
|
3
|
+
* Strictly bounded to observability layer only, no cross-layer calls
|
|
4
|
+
*/
|
|
5
|
+
export class OTLPTraceExporter {
|
|
6
|
+
constructor(options = {}) {
|
|
7
|
+
this.endpoint = options.endpoint || "http://localhost:4318/v1/traces";
|
|
8
|
+
this._queue = [];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export(span) {
|
|
12
|
+
const payload = {
|
|
13
|
+
resourceSpans: [{
|
|
14
|
+
resource: { attributes: [{ key: "service.name", value: { stringValue: "cc-cli" } }] },
|
|
15
|
+
scopeSpans: [{
|
|
16
|
+
spans: [{
|
|
17
|
+
traceId: span.traceId,
|
|
18
|
+
spanId: span.spanId,
|
|
19
|
+
name: span.name || "span",
|
|
20
|
+
kind: 1,
|
|
21
|
+
startTimeUnixNano: span.startTime ? BigInt(span.startTime * 1e6).toString() : BigInt(Date.now() * 1e6).toString(),
|
|
22
|
+
endTimeUnixNano: span.endTime ? BigInt(span.endTime * 1e6).toString() : undefined,
|
|
23
|
+
attributes: (span.metadata ? Object.entries(span.metadata).map(([k, v]) => ({ key: k, value: { stringValue: String(v) } })) : []),
|
|
24
|
+
}]
|
|
25
|
+
}]
|
|
26
|
+
}]
|
|
27
|
+
};
|
|
28
|
+
// Fire and forget, no blocking
|
|
29
|
+
fetch(this.endpoint, {
|
|
30
|
+
method: "POST",
|
|
31
|
+
headers: { "Content-Type": "application/json" },
|
|
32
|
+
body: JSON.stringify(payload),
|
|
33
|
+
}).catch(() => {});
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
let defaultExporter = null;
|
|
39
|
+
export function initOTLPExporter(endpoint) {
|
|
40
|
+
if (!defaultExporter && endpoint) {
|
|
41
|
+
defaultExporter = new OTLPTraceExporter({ endpoint: endpoint.endsWith("/v1/traces") ? endpoint : endpoint.replace(/\/?$/, "/v1/traces") });
|
|
42
|
+
globalThis.ccRuntime?.traceContext.onEnd((span) => defaultExporter.export(span));
|
|
43
|
+
}
|
|
44
|
+
return defaultExporter;
|
|
45
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# Process Execution Broker - Spawn/Exec Call Site Audit Report
|
|
2
|
+
|
|
3
|
+
> Audit Date: 2026-07-18
|
|
4
|
+
> Auditor: Agent
|
|
5
|
+
> Scope: `packages/cli/src`
|
|
6
|
+
|
|
7
|
+
## Executive Summary
|
|
8
|
+
|
|
9
|
+
Total direct `child_process` call sites identified: **~85+**
|
|
10
|
+
- `spawn`: ~40 call sites
|
|
11
|
+
- `spawnSync`: ~25 call sites
|
|
12
|
+
- `execSync`: ~15 call sites
|
|
13
|
+
- `execFileSync`: ~8 call sites
|
|
14
|
+
- `execFile`: ~2 call sites
|
|
15
|
+
- `fork`: ~1 call site
|
|
16
|
+
|
|
17
|
+
## Classification by Risk Category
|
|
18
|
+
|
|
19
|
+
### A. Agent Self-Spawn (HIGH PRIORITY - must route through Broker)
|
|
20
|
+
These are the primary surfaces where the agent spawns sub-agents or child cc processes:
|
|
21
|
+
|
|
22
|
+
| File | Function | Type | Purpose |
|
|
23
|
+
|------|----------|------|---------|
|
|
24
|
+
| `commands/agenda.js` | `defaultSpawnAgent()` | spawn | Wakeup/cron scheduled agent execution |
|
|
25
|
+
| `commands/background-session.js` | - | spawn | Background session agent |
|
|
26
|
+
| `commands/batch.js` | `spawnAgent()` | spawn + execFileSync | Batch agent execution |
|
|
27
|
+
| `commands/eval.js` | - | spawn + spawnSync | Eval child processes |
|
|
28
|
+
| `commands/loop.js` | `spawnIteration()` | spawn | Loop mode iteration self-spawn |
|
|
29
|
+
| `commands/routine.js` | - | spawn + execFile | Routine execution |
|
|
30
|
+
| `commands/team.js` | `spawnAgent()` | spawn | Team/cowork multi-agent |
|
|
31
|
+
| `gateways/ws/ws-server.js` | - | spawn | WebSocket gateway spawned CLI commands |
|
|
32
|
+
| `harness/background-task-manager.js` | - | fork | Background task forked workers |
|
|
33
|
+
| `lib/background-agent-supervisor.js` | - | spawn + spawnSync | Background agent supervision |
|
|
34
|
+
| `lib/agent-team/team-worktree.js` | - | spawn + execFileSync | Team worktree agent |
|
|
35
|
+
| `lib/claude-code-bridge.js` | - | spawn + execSync | Claude Code bridge execution |
|
|
36
|
+
| `lib/agent-sandbox.js` | - | spawnSync | Sandbox (docker/bwrap) execution |
|
|
37
|
+
|
|
38
|
+
### B. MCP Server Process (MEDIUM PRIORITY)
|
|
39
|
+
| File | Function | Type | Purpose |
|
|
40
|
+
|------|----------|------|---------|
|
|
41
|
+
| `harness/mcp-client.js` | - | spawn | MCP stdio server processes |
|
|
42
|
+
| `lib/lsp/lsp-client.js` | - | spawn | LSP server processes |
|
|
43
|
+
|
|
44
|
+
### C. Git Operations (SAFE - can keep direct)
|
|
45
|
+
| File | Type | Count |
|
|
46
|
+
|------|------|-------|
|
|
47
|
+
| `commands/review.js` | spawnSync | 2 |
|
|
48
|
+
| `commands/session.js` | execFileSync | 1 |
|
|
49
|
+
| `harness/worktree-isolator.js` | execSync | 3 |
|
|
50
|
+
| `lib/agent-worktree.js` | execFileSync/execSync | multiple |
|
|
51
|
+
| `lib/checkpoint-store.js` | spawnSync | multiple |
|
|
52
|
+
| `lib/cloud/bundle.js` | execFileSync | multiple |
|
|
53
|
+
| `lib/git-integration.js` | execSync/spawnSync | multiple |
|
|
54
|
+
|
|
55
|
+
### D. Package/System Management (SAFE - can keep direct)
|
|
56
|
+
| File | Type | Purpose |
|
|
57
|
+
|------|------|---------|
|
|
58
|
+
| `auth/npm-auth.js` | execSync | npm login/whoami |
|
|
59
|
+
| `commands/config.js` | execSync | Open editor |
|
|
60
|
+
| `commands/init.js` | execSync/spawnSync | Init tool probing |
|
|
61
|
+
| `commands/memory.js` | execSync | Open editor |
|
|
62
|
+
| `commands/update.js` | execSync | npm install -g |
|
|
63
|
+
| `lib/api-key-helper.js` | execSync | Credential helper |
|
|
64
|
+
| `lib/chrome-connector.js` | spawn | Chrome debugger |
|
|
65
|
+
| `lib/doctor-checkup.js` | execSync/spawnSync | Doctor checks |
|
|
66
|
+
| `lib/downloader.js` | execFileSync | Binary downloads |
|
|
67
|
+
| `lib/ensure-utf8.js` | execSync | Windows codepage |
|
|
68
|
+
| `lib/host-adb-bridge.js` | execFile | ADB bridge |
|
|
69
|
+
|
|
70
|
+
### E. Hook Execution (BROKER-AWARE already)
|
|
71
|
+
| File | Type | Purpose |
|
|
72
|
+
|------|------|---------|
|
|
73
|
+
| `lib/async-hook-supervisor.cjs` | spawn/spawnSync | Async hooks |
|
|
74
|
+
| `lib/hook-manager.js` | execSync | Legacy hook manager |
|
|
75
|
+
| `lib/hook-runner.cjs` | spawn/spawnSync | Hook runner |
|
|
76
|
+
|
|
77
|
+
### F. Evaluation/Benchmark (TEST only)
|
|
78
|
+
| File | Type | Purpose |
|
|
79
|
+
|------|------|---------|
|
|
80
|
+
| `lib/eval/tasks.js` | execFileSync | Eval task fixtures |
|
|
81
|
+
| `lib/lsp/benchmark.js` | execFileSync | LSP benchmarks |
|
|
82
|
+
| `lib/computer-use/control-backend.js` | spawnSync | Computer use |
|
|
83
|
+
|
|
84
|
+
### G. Execution Backend
|
|
85
|
+
| File | Type | Purpose |
|
|
86
|
+
|------|------|---------|
|
|
87
|
+
| `lib/execution-backend.js` | execSync | Shell/Docker/SSH backend |
|
|
88
|
+
|
|
89
|
+
### H. Background Task Worker
|
|
90
|
+
| File | Type | Purpose |
|
|
91
|
+
|------|------|---------|
|
|
92
|
+
| `harness/background-task-worker.js` | execSync | Worker task execution |
|
|
93
|
+
|
|
94
|
+
## Migration Plan
|
|
95
|
+
|
|
96
|
+
### Phase 1 (M1 Deliverable)
|
|
97
|
+
Create ProcessExecutionBroker with core interface, then migrate:
|
|
98
|
+
1. Category A (Agent Self-Spawn) - all HIGH priority sites
|
|
99
|
+
2. Instrument with audit events + logging
|
|
100
|
+
|
|
101
|
+
### Phase 2 (Post-M1)
|
|
102
|
+
1. Category B (MCP/LSP) - register server processes as supervised children
|
|
103
|
+
2. Keep Categories C/D as `bypassBroker: true` approved calls (with explicit allowlist)
|
|
104
|
+
|
|
105
|
+
### Phase 3 (M3 deliverable)
|
|
106
|
+
3. Route Category E hooks through Broker for unified supervision
|
|
107
|
+
|
|
108
|
+
## Bypass Allowlist (Initial)
|
|
109
|
+
The following patterns will be initially marked as `bypassBroker: true` with reason:
|
|
110
|
+
- All `git` command executions (known safe, no agent control over args)
|
|
111
|
+
- Editor opening (`$EDITOR`, `vim`, `nano`, etc.)
|
|
112
|
+
- Package manager operations (`npm`, `pip`)
|
|
113
|
+
- Chrome/ADB debug bridge connections
|
|
114
|
+
- Doctor/diagnostic probes
|
|
115
|
+
- Windows codepage setup (`chcp`)
|
|
116
|
+
- File downloads/extraction (unzip)
|
|
117
|
+
- Test fixtures and benchmarks (test-only code)
|