chainlesschain 0.162.162 → 0.162.164
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 +3 -1
- package/src/assets/web-panel/assets/{AIOps-ClI2ALgv.js → AIOps-BqRkaHGb.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-BDjRcJaK.js → ActionButton-DWO7OZLC.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-DikSRsaT.js → Analytics-C5oaVezM.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-9mLhMFmz.js → AppLayout-CsUESDoZ.js} +3 -3
- package/src/assets/web-panel/assets/{Artifacts-BSr88BrH.js → Artifacts-Dragqu5k.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-CdvyimOF.js → Audit-CQsaHctY.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-D3_hCedh.js → BackgroundAgents-DdG1jNSM.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-Cyvv9RHf.js → Backup-DN6sjK4z.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-BZM14kt8.js → BaseInput-Cxm_ZTCl.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-DrQSokVz.js → Chat-DVXGmA56.js} +6 -6
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-HwJR-C6B.js → ChatBubbleRenderer-BdaCL_iE.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-bFLYeWMV.js → Checkbox-DEc4vD_A.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-7mN7xJXT.js → Codegen-CKiTcv36.js} +1 -1
- package/src/assets/web-panel/assets/{Col-DAB5ZWm7.js → Col-Br9UUNN0.js} +1 -1
- package/src/assets/web-panel/assets/{Community-B_1TymaK.js → Community-NeUH_70T.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-Bq1uSWLJ.js → Compact-BqR-z2Df.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-CyiE1jEe.js → Compliance-DcWB_SgZ.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-Cpk0D7vm.js → Cowork-BfhgcudF.js} +2 -2
- package/src/assets/web-panel/assets/{Cron-d_Lv3rdB.js → Cron-LaU29LgD.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-DMqhHjMR.js → Crosschain-B2ZB9uwW.js} +1 -1
- package/src/assets/web-panel/assets/{DID-Br-oPuBw.js → DID-BuHl38A2.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-CfLW_RaP.js → Dashboard-m627yqvZ.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-DZnTOExV.js → Dropdown-C7bxF8F5.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-DHIUHDv1.js → EmailListRenderer-DPLPQzLp.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-Bw3t3myu.js → FamilyGuardDashboard-cOiH6ike.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-D9cpQPAY.js → Federation-Bvkzg88z.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-Jdczr9Mr.js → FormItemContext-BTsiA7h_.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-BT8ZMpC5.js → GenericCardRenderer-BGnVE5qu.js} +1 -1
- package/src/assets/web-panel/assets/{Git-DjARip2b.js → Git-DS_j6r25.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-BgWbSRcj.js → Governance-CKRG3Rsl.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-CfouJciM.js → Inference-DW8INoNQ.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-50l7mrAr.js → KnowledgeGraph-BhEYeFhC.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-rq50H84B.js → Logs-wqi0uxuR.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-DUPIEdQH.js → MarkdownRenderer-DS8dE8ty.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-BYgPDmHU.js → Marketplace-CMlTuPLT.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-5DVgcFdx.js → McpTools-CSx4m5JJ.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-B70LPk7f.js → Memory-vnQCUy-_.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-De8ssA5Y.js → MobileBridge-BV2NA742.js} +1 -1
- package/src/assets/web-panel/assets/MobileProjects-Bw0k8e1B.js +1 -0
- package/src/assets/web-panel/assets/{Mtc-RJsOTsIA.js → Mtc-CzK_FPB1.js} +2 -2
- package/src/assets/web-panel/assets/{MtcAudit-Crh-6BEK.js → MtcAudit-Cb7G9oL3.js} +5 -5
- package/src/assets/web-panel/assets/{Multisig-wuoR5l3x.js → Multisig-qJxlUyzr.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-U2Mji4fZ.js → NLProgramming-DqaBJ7Te.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-CdTZAyDH.js → Notes-CwhTJkRi.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-C-FucWE7.js → NotificationSettings-YDs4Fal4.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-DCYFTeaI.js → OrderTableRenderer-CvEALpq7.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-an3OF85L.js → Organization-CEmQm9n8.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-C-1vmYFe.js → Overflow-zby_P_LA.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-Cwh47xKg.js → P2P-DsmDNFNT.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-Dm38GT0k.js → PdhVaultBrowser-FWwFlZGF.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-DS2Y8awD.js → Permissions-DuzQ6me5.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-BQNziA0I.js → PersonalDataHub-DZbeN613.js} +3 -3
- package/src/assets/web-panel/assets/{Pipeline-DF85L1ue.js → Pipeline-CoNSVAUS.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-BuLornF-.js → Privacy-OYJEAaMC.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-C3Y31IwX.js → ProjectInit-CWIapV--.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-BCPiI8aD.js → ProjectSettings-CX8xMxZn.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-BZ6s4k6g.js → Projects-BLCN8YyY.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-D3Wp022X.js → Providers-BV_sxp75.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-CUJfQkH4.js → QrScannerModal-BTnRrHRp.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-UAc0EO8l.js → QuickAsk-D1KZg018.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-BaxKupcs.js → Recommend-COm5cuNg.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-C75NNnXZ.js → RemoteSession-0saWEkYI.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-BVXynZAk.js → Reputation-Dr7iKLS2.js} +1 -1
- package/src/assets/web-panel/assets/{Row-C5MRZ0bi.js → Row-C1vpPBcr.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-DAKkEYka.js → RssFeed-CxlWrtNj.js} +3 -3
- package/src/assets/web-panel/assets/{Search-DvWv9YOA.js → Search-BT2V8dPN.js} +1 -1
- package/src/assets/web-panel/assets/{Security-B5peafW1.js → Security-bm9V3c5k.js} +4 -4
- package/src/assets/web-panel/assets/{Services-UQmvPEaG.js → Services-CocH1yyX.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-C3bhWpuF.js → Skeleton-DHItlMdd.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-DfkKf9_H.js → Skills-C59sLc4w.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-DqMSjlBM.js → Sla-Crj4BMc8.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-C-WbxWUX.js → SpeechSettings-DX4KFceY.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-CYuHZ4N2.js → SyncSettings-BD_iwQLr.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-CyeAyB9d.js → Tasks-BmCTzYsH.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-BTCeQnpq.js → Templates-BGUaxZYl.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-BifQuA9Y.js → Tenant-BS0tJx2O.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-Bx_9Bocf.js → Terminal--tHSAsld.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-BX0RFCOm.js → TimelineRenderer-D9-MFxS4.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-CGHrCmUS.js → Tokens-CiCB485f.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-DlqaY4SO.js → Trigger-SmCFuW_l.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-DfOmj-ay.js → Trust-DkK3Rqe0.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-B72jH5fE.js → UkeySign-CDM4LGdB.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-BT-63fqv.js → VideoEditing-IDB7DJXt.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-Dsul3sHr.js → Wallet-Bikj5cmt.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-Izkwwdgy.js → WebAuthn-C9abWlAw.js} +2 -2
- package/src/assets/web-panel/assets/{WorkflowEditor-D3FHSiH1.js → WorkflowEditor-DrbRKVky.js} +1 -1
- package/src/assets/web-panel/assets/{chat-CmVz5z3U.js → chat-CccCSDQf.js} +1 -1
- package/src/assets/web-panel/assets/{colors-CuLgyJBp.js → colors-CXObXLhb.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-Ml1YkXpw.js → compact-item-B5kfYAxC.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-BvjJ48bs.js → createContext-DmiPBfip.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-CvKrADNa.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-DVC0157C.js → hasIn-Q6lYteAc.js} +1 -1
- package/src/assets/web-panel/assets/{index-C229ABfy.js → index-25Wlqps4.js} +1 -1
- package/src/assets/web-panel/assets/{index-Ck_52dz_.js → index-33U29UNV.js} +1 -1
- package/src/assets/web-panel/assets/{index-QXzlT9KD.js → index-4oXBDczR.js} +1 -1
- package/src/assets/web-panel/assets/{index-4SBta3d7.js → index-BGYXvMc5.js} +1 -1
- package/src/assets/web-panel/assets/{index-B0S8NzO6.js → index-BJCCa0s_.js} +1 -1
- package/src/assets/web-panel/assets/{index-DJyN28Et.js → index-BJJ5DhKI.js} +1 -1
- package/src/assets/web-panel/assets/{index-DC_OI9H2.js → index-BLOzViJ6.js} +1 -1
- package/src/assets/web-panel/assets/{index-C_XuRgGn.js → index-BRrbUMoG.js} +1 -1
- package/src/assets/web-panel/assets/{index-wvb_FtaV.js → index-BUFpT17Q.js} +1 -1
- package/src/assets/web-panel/assets/{index-KMqhcF7l.js → index-BkRDiqGc.js} +1 -1
- package/src/assets/web-panel/assets/{index-vG4XSJ1d.js → index-BsfvW6my.js} +1 -1
- package/src/assets/web-panel/assets/{index-DYXHFr4r.js → index-By-kfPED.js} +1 -1
- package/src/assets/web-panel/assets/{index-DuGszaWY.js → index-BzFTcQsc.js} +1 -1
- package/src/assets/web-panel/assets/{index-CXkJH-lK.js → index-C2FXdboq.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dt5KMjwJ.js → index-C5XOlTHN.js} +1 -1
- package/src/assets/web-panel/assets/{index-4wcgvPoF.js → index-CLhBDS2w.js} +1 -1
- package/src/assets/web-panel/assets/{index-C_H_S-DY.js → index-CMq7UeoT.js} +1 -1
- package/src/assets/web-panel/assets/{index-BydjdZnl.js → index-CVMTWNKl.js} +1 -1
- package/src/assets/web-panel/assets/{index-BjHBpRYZ.js → index-Caghi-yL.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bzr0rB5T.js → index-CdB6FuSH.js} +1 -1
- package/src/assets/web-panel/assets/{index-BbPtzB8M.js → index-CoK8-kWQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-BUt8kTIB.js → index-CsO3GUAY.js} +1 -1
- package/src/assets/web-panel/assets/{index-C_vRgTl9.js → index-CwZBa20Z.js} +1 -1
- package/src/assets/web-panel/assets/{index-DukDVXCv.js → index-D-kASucw.js} +1 -1
- package/src/assets/web-panel/assets/{index-BbepULSc.js → index-D8eBw7vW.js} +1 -1
- package/src/assets/web-panel/assets/{index-BfuKP4qe.js → index-D9wgifk4.js} +1 -1
- package/src/assets/web-panel/assets/{index-BiC6dQZG.js → index-DAYCTc07.js} +1 -1
- package/src/assets/web-panel/assets/{index-CmFNvNLZ.js → index-DF6Q8l2h.js} +1 -1
- package/src/assets/web-panel/assets/index-DTdFUWc_.js +1 -0
- package/src/assets/web-panel/assets/{index-KjgKdZe-.js → index-DgTLApS9.js} +1 -1
- package/src/assets/web-panel/assets/{index-BpFJHiTv.js → index-DgxVJ8pg.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cw0Rjy87.js → index-DlJvIqoR.js} +1 -1
- package/src/assets/web-panel/assets/{index-CFYVQMvu.js → index-Dw4eHfsG.js} +1 -1
- package/src/assets/web-panel/assets/{index-CudmwNBV.js → index-Rh-ytwow.js} +3 -3
- package/src/assets/web-panel/assets/{index-DDGaOWBV.js → index-StAEt2pq.js} +1 -1
- package/src/assets/web-panel/assets/{index-D3lD5qap.js → index-bzfw951k.js} +1 -1
- package/src/assets/web-panel/assets/{index-BzG-x9p4.js → index-fSUMbMvv.js} +1 -1
- package/src/assets/web-panel/assets/{index-B_EvG_GW.js → index-tFHy5Wol.js} +1 -1
- package/src/assets/web-panel/assets/index-zQ0M_kz-.js +1 -0
- package/src/assets/web-panel/assets/{initDefaultProps-BDgd2YZ8.js → initDefaultProps-BNq7X72N.js} +1 -1
- package/src/assets/web-panel/assets/{motion-ErtrXdYe.js → motion-DOf9viTc.js} +1 -1
- package/src/assets/web-panel/assets/{move-_GPPNCgs.js → move-CRHTcW4x.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-DRLL-8V2.js → mtc-parser-Cyoozgm2.js} +1 -1
- package/src/assets/web-panel/assets/{omit-p86sl023.js → omit-6-TjFNru.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-BTu7cMLH.js → pickAttrs-DlUmO1zi.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-BEKz6Isr.js → placementArrow-CFOL8mIR.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-Ck42c9MP.js → responsiveObserve-BtaFK5zd.js} +1 -1
- package/src/assets/web-panel/assets/{slide-1CEvuPsB.js → slide-BIbc2bur.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-BDfdx1GJ.js → statusUtils-BXX9d6-w.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-B4K46m5w.js → styleChecker-BGv10Bpn.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-DoIVpJNq.js → useFlexGapSupport-bKnKT8tw.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-DdAWi-ln.js → useFs-FY4IL4jn.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-iUu6k8dx.js → usePersonalDataHub-Bwl9TEgu.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-DZz4R6Tw.js → vnode-BM3OHxAT.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-DXlf9sA3.js → zoom-D1fbFiHB.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/agenda.js +320 -32
- package/src/commands/agent.js +105 -11
- package/src/commands/context.js +125 -14
- package/src/commands/doctor.js +85 -1
- package/src/commands/hook.js +181 -7
- package/src/commands/plugin.js +456 -1
- package/src/commands/review.js +363 -2
- package/src/commands/session.js +191 -0
- package/src/commands/team.js +19 -1
- package/src/data/changelog.json +10 -4
- package/src/gateways/ws/remote-session-protocol.js +39 -0
- package/src/gateways/ws/session-protocol.js +55 -2
- package/src/gateways/ws/ws-agent-handler.js +50 -0
- package/src/harness/jsonl-session-store.js +60 -0
- package/src/harness/worktree-isolator.js +140 -5
- package/src/lib/agent-schedule-store.js +318 -10
- package/src/lib/agent-team/team-worktree.js +37 -2
- package/src/lib/agent-tool-admission.js +125 -0
- package/src/lib/app-preview.js +360 -0
- package/src/lib/async-hook-supervisor.cjs +54 -0
- package/src/lib/capability-manifest.js +319 -0
- package/src/lib/capability-negotiation.js +23 -12
- package/src/lib/channels/channel-manager.js +54 -2
- package/src/lib/cli-context-engineering.js +9 -2
- package/src/lib/context-breakdown.js +116 -0
- package/src/lib/diagnostic-bundle.js +230 -0
- package/src/lib/doctor-checkup.js +275 -4
- package/src/lib/execution-location.js +286 -0
- package/src/lib/headless-manifest.js +13 -40
- package/src/lib/hook-event-log.cjs +193 -0
- package/src/lib/hook-stats-store.cjs +197 -0
- package/src/lib/idempotency.js +109 -0
- package/src/lib/interaction-adapter.js +34 -4
- package/src/lib/json-schema-output.js +46 -12
- package/src/lib/json-schema-validate.js +143 -3
- package/src/lib/jsonl-session-store.js +1 -0
- package/src/lib/lsp/__tests__/lsp-manager.test.js +58 -0
- package/src/lib/lsp/lsp-manager.js +56 -0
- package/src/lib/monitor-event.js +290 -0
- package/src/lib/operation-fingerprint.js +217 -0
- package/src/lib/plugin-runtime/bin.js +37 -0
- package/src/lib/plugin-runtime/capabilities.js +19 -0
- package/src/lib/plugin-runtime/capability-consent.js +203 -0
- package/src/lib/plugin-runtime/hooks.js +37 -0
- package/src/lib/plugin-runtime/lsp.js +38 -0
- package/src/lib/plugin-runtime/mcp.js +40 -0
- package/src/lib/plugin-runtime/monitors.js +37 -0
- package/src/lib/plugin-runtime/plugin-options.js +151 -0
- package/src/lib/plugin-runtime/policy.js +62 -0
- package/src/lib/plugin-runtime/scopes.js +20 -4
- package/src/lib/pr-automation-policy.js +224 -0
- package/src/lib/project-instructions.js +128 -0
- package/src/lib/remote-approval-bridge.js +66 -13
- package/src/lib/repl-goal.js +132 -0
- package/src/lib/repl-rewind.js +153 -0
- package/src/lib/review-comment-anchor.js +241 -0
- package/src/lib/review-pipeline.js +46 -7
- package/src/lib/runtime-checkup.js +221 -0
- package/src/lib/schedule-planner.js +17 -1
- package/src/lib/secret-scan.js +409 -0
- package/src/lib/session-branch.js +0 -0
- package/src/lib/settings-hook-events.cjs +13 -0
- package/src/lib/settings-loader.cjs +42 -0
- package/src/lib/side-effect-ledger-store.js +88 -0
- package/src/lib/side-effect-ledger.js +401 -0
- package/src/lib/skill-loader.js +32 -0
- package/src/lib/skill-path-scope.js +63 -0
- package/src/lib/sub-agent-context.js +110 -9
- package/src/lib/sub-agent-registry.js +19 -0
- package/src/lib/subagent-inheritance.js +112 -0
- package/src/lib/telemetry/span-recorder.js +17 -4
- package/src/lib/terminal-context.js +195 -0
- package/src/lib/turn-binding-store.js +119 -0
- package/src/lib/unattended-action-policy.js +182 -0
- package/src/lib/worktree-cleanup-safety.js +138 -0
- package/src/lib/worktree-isolator.js +8 -0
- package/src/lib/worktree-sparse.js +131 -0
- package/src/repl/agent-repl.js +280 -30
- package/src/repl/permission-tier.js +28 -0
- package/src/runtime/agent-core.js +565 -21
- package/src/runtime/coding-agent-contract-shared.cjs +60 -1
- package/src/runtime/diagnostics.js +60 -0
- package/src/runtime/headless-runner.js +393 -1
- package/src/runtime/headless-stream.js +60 -1
- package/src/assets/web-panel/assets/MobileProjects-D10VISps.js +0 -1
- package/src/assets/web-panel/assets/devWarning-DhiGrbsh.js +0 -1
- package/src/assets/web-panel/assets/index-B7a1TrU6.js +0 -1
- package/src/assets/web-panel/assets/index-C2B1KRja.js +0 -1
|
@@ -12,8 +12,16 @@
|
|
|
12
12
|
* verifier verdicts, confidence-filter, rank, and render the structured report.
|
|
13
13
|
* The fan-out of finder/verifier AGENTS is orchestration the command layer adds;
|
|
14
14
|
* everything here is deterministic and testable without an LLM.
|
|
15
|
+
*
|
|
16
|
+
* P1-1 wiring (行评论锚定): when the caller supplies the reviewed file contents,
|
|
17
|
+
* each finding's output carries a re-anchorable comment ANCHOR (file + base hash
|
|
18
|
+
* + line + anchored line text + context) via [[review-comment-anchor.js]] instead
|
|
19
|
+
* of only a bare `line` coordinate — so a downstream IDE Diff Review can relocate
|
|
20
|
+
* or stale the comment after the agent edits the file, never reusing a dead line.
|
|
15
21
|
*/
|
|
16
22
|
|
|
23
|
+
import { makeCommentAnchor } from "./review-comment-anchor.js";
|
|
24
|
+
|
|
17
25
|
/** The finder dimensions a full review fans out across. */
|
|
18
26
|
export const REVIEW_DIMENSIONS = Object.freeze([
|
|
19
27
|
"correctness",
|
|
@@ -184,16 +192,44 @@ export function rankFindings(findings) {
|
|
|
184
192
|
);
|
|
185
193
|
}
|
|
186
194
|
|
|
187
|
-
|
|
188
|
-
|
|
195
|
+
/** Look a path's content up from a Map or plain object, or return undefined. */
|
|
196
|
+
function lookupContent(fileContents, filePath) {
|
|
197
|
+
if (!fileContents) return undefined;
|
|
198
|
+
if (typeof fileContents.get === "function") return fileContents.get(filePath);
|
|
199
|
+
return fileContents[filePath];
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function toOutputFinding(f, fileContents) {
|
|
203
|
+
const line = Number.isFinite(Number(f.line))
|
|
204
|
+
? Math.floor(Number(f.line))
|
|
205
|
+
: null;
|
|
206
|
+
const failureScenario = String(f.failureScenario || f.failure_scenario || "");
|
|
207
|
+
const out = {
|
|
189
208
|
path: String(f.path || ""),
|
|
190
|
-
line
|
|
209
|
+
line,
|
|
191
210
|
category: f.category || (f.categories && f.categories[0]) || "correctness",
|
|
192
211
|
severity: normalizeSeverity(f.severity),
|
|
193
|
-
failure_scenario:
|
|
212
|
+
failure_scenario: failureScenario,
|
|
194
213
|
evidence: String(f.evidence || ""),
|
|
195
214
|
confidence: clampConfidence(f.confidence),
|
|
196
215
|
};
|
|
216
|
+
// P1-1: anchor the comment to the CODE it addresses, not to a coordinate, so
|
|
217
|
+
// an IDE diff review can relocate/stale it after edits (never reuse a dead
|
|
218
|
+
// line). Only when the caller supplied this file's content AND we have a
|
|
219
|
+
// valid 1-based line to anchor.
|
|
220
|
+
if (line != null && line >= 1) {
|
|
221
|
+
const content = lookupContent(fileContents, out.path);
|
|
222
|
+
if (typeof content === "string") {
|
|
223
|
+
out.anchor = makeCommentAnchor({
|
|
224
|
+
file: out.path,
|
|
225
|
+
content,
|
|
226
|
+
line,
|
|
227
|
+
comment: failureScenario || out.evidence,
|
|
228
|
+
id: `${out.path}:${line}:${out.category}`,
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
return out;
|
|
197
233
|
}
|
|
198
234
|
|
|
199
235
|
/**
|
|
@@ -202,17 +238,20 @@ function toOutputFinding(f) {
|
|
|
202
238
|
* evidence output) plus severity/category rollups.
|
|
203
239
|
*
|
|
204
240
|
* @param {Array} rawFindings findings from all finders
|
|
205
|
-
* @param {object} [opts] { verdicts, minConfidence }
|
|
241
|
+
* @param {object} [opts] { verdicts, minConfidence, fileContents }
|
|
242
|
+
* fileContents — optional Map/object of `path → current file content`. When a
|
|
243
|
+
* finding's file is present, its output gains a re-anchorable `anchor` (P1-1);
|
|
244
|
+
* omit it and the output is byte-identical to before.
|
|
206
245
|
*/
|
|
207
246
|
export function buildReviewReport(
|
|
208
247
|
rawFindings,
|
|
209
|
-
{ verdicts = {}, minConfidence = 0 } = {},
|
|
248
|
+
{ verdicts = {}, minConfidence = 0, fileContents = null } = {},
|
|
210
249
|
) {
|
|
211
250
|
const deduped = dedupeFindings(rawFindings);
|
|
212
251
|
const verified = applyVerdicts(deduped, verdicts);
|
|
213
252
|
const filtered = filterByConfidence(verified, { minConfidence });
|
|
214
253
|
const ranked = rankFindings(filtered);
|
|
215
|
-
const findings = ranked.map(toOutputFinding);
|
|
254
|
+
const findings = ranked.map((f) => toOutputFinding(f, fileContents));
|
|
216
255
|
|
|
217
256
|
const bySeverity = { Critical: 0, High: 0, Medium: 0, Low: 0, Note: 0 };
|
|
218
257
|
const byCategory = {};
|
|
@@ -216,6 +216,227 @@ export function checkHooks(hooks = [], t) {
|
|
|
216
216
|
return out;
|
|
217
217
|
}
|
|
218
218
|
|
|
219
|
+
/**
|
|
220
|
+
* STATICALLY validate a settings.json `hooks` block for reliably-detectable
|
|
221
|
+
* breakage — a hook that will silently NEVER fire (unknown event name, an
|
|
222
|
+
* uncompilable `/…/` regex matcher, a missing command) or is misconfigured (a
|
|
223
|
+
* non-positive / over-cap timeout). This is the config subset a doctor can
|
|
224
|
+
* catch without running anything; RUNTIME health (slow / circuit-broken hooks)
|
|
225
|
+
* needs live per-process stats and is handled by `checkHooks`, not here.
|
|
226
|
+
*
|
|
227
|
+
* @param {object} hooksBlock raw `.hooks` object from settings.json
|
|
228
|
+
* @param {object} [opts] { validEvents: Set<string>|string[], maxTimeoutSec }
|
|
229
|
+
*/
|
|
230
|
+
export function checkHookConfig(
|
|
231
|
+
hooksBlock,
|
|
232
|
+
{ validEvents, maxTimeoutSec = 600 } = {},
|
|
233
|
+
) {
|
|
234
|
+
const out = [];
|
|
235
|
+
if (!hooksBlock || typeof hooksBlock !== "object") return out;
|
|
236
|
+
const known =
|
|
237
|
+
validEvents instanceof Set ? validEvents : new Set(validEvents || []);
|
|
238
|
+
|
|
239
|
+
for (const [event, groups] of Object.entries(hooksBlock)) {
|
|
240
|
+
// An event key the loader doesn't understand → every hook under it is dead
|
|
241
|
+
// (silently never fires). This is the highest-value static catch.
|
|
242
|
+
if (known.size && !known.has(event)) {
|
|
243
|
+
out.push(
|
|
244
|
+
finding(
|
|
245
|
+
"hook-unknown-event",
|
|
246
|
+
"hooks",
|
|
247
|
+
"warn",
|
|
248
|
+
`Hook event "${event}" is not recognized — its hooks never fire`,
|
|
249
|
+
"fix the event name in settings.json hooks",
|
|
250
|
+
{ ref: event },
|
|
251
|
+
),
|
|
252
|
+
);
|
|
253
|
+
continue;
|
|
254
|
+
}
|
|
255
|
+
if (!Array.isArray(groups)) {
|
|
256
|
+
out.push(
|
|
257
|
+
finding(
|
|
258
|
+
"hook-malformed",
|
|
259
|
+
"hooks",
|
|
260
|
+
"warn",
|
|
261
|
+
`Hook event "${event}" is not an array`,
|
|
262
|
+
"settings.json hooks[<event>] must be an array",
|
|
263
|
+
{ ref: event },
|
|
264
|
+
),
|
|
265
|
+
);
|
|
266
|
+
continue;
|
|
267
|
+
}
|
|
268
|
+
groups.forEach((g, gi) => {
|
|
269
|
+
const at = `${event}[${gi}]`;
|
|
270
|
+
// A `/body/flags` regex matcher that won't compile silently never matches.
|
|
271
|
+
if (g && typeof g.matcher === "string" && g.matcher.startsWith("/")) {
|
|
272
|
+
const m = g.matcher.match(/^\/(.*)\/([a-z]*)$/);
|
|
273
|
+
try {
|
|
274
|
+
new RegExp(m ? m[1] : g.matcher.slice(1), m ? m[2] : "");
|
|
275
|
+
} catch {
|
|
276
|
+
out.push(
|
|
277
|
+
finding(
|
|
278
|
+
"hook-bad-matcher",
|
|
279
|
+
"hooks",
|
|
280
|
+
"warn",
|
|
281
|
+
`Hook ${at} matcher ${g.matcher} is not a valid regex — it never matches`,
|
|
282
|
+
"fix the regex matcher",
|
|
283
|
+
{ ref: at },
|
|
284
|
+
),
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
const cmds = g && Array.isArray(g.hooks) ? g.hooks : null;
|
|
289
|
+
if (!cmds) {
|
|
290
|
+
out.push(
|
|
291
|
+
finding(
|
|
292
|
+
"hook-malformed",
|
|
293
|
+
"hooks",
|
|
294
|
+
"warn",
|
|
295
|
+
`Hook ${at} has no hooks array`,
|
|
296
|
+
"each hook group needs a hooks:[] array",
|
|
297
|
+
{ ref: at },
|
|
298
|
+
),
|
|
299
|
+
);
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
cmds.forEach((h, hi) => {
|
|
303
|
+
const hAt = `${at}.hooks[${hi}]`;
|
|
304
|
+
if (!h || typeof h.command !== "string" || !h.command.trim()) {
|
|
305
|
+
out.push(
|
|
306
|
+
finding(
|
|
307
|
+
"hook-no-command",
|
|
308
|
+
"hooks",
|
|
309
|
+
"warn",
|
|
310
|
+
`Hook ${hAt} has no command — it does nothing`,
|
|
311
|
+
"add a command string or remove the entry",
|
|
312
|
+
{ ref: hAt },
|
|
313
|
+
),
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
if (h && h.timeout != null) {
|
|
317
|
+
const t = Number(h.timeout);
|
|
318
|
+
if (!Number.isFinite(t) || t <= 0) {
|
|
319
|
+
out.push(
|
|
320
|
+
finding(
|
|
321
|
+
"hook-bad-timeout",
|
|
322
|
+
"hooks",
|
|
323
|
+
"info",
|
|
324
|
+
`Hook ${hAt} timeout ${h.timeout} is not a positive number`,
|
|
325
|
+
"timeout is in seconds; use a positive value",
|
|
326
|
+
{ ref: hAt },
|
|
327
|
+
),
|
|
328
|
+
);
|
|
329
|
+
} else if (t > maxTimeoutSec) {
|
|
330
|
+
out.push(
|
|
331
|
+
finding(
|
|
332
|
+
"hook-bad-timeout",
|
|
333
|
+
"hooks",
|
|
334
|
+
"info",
|
|
335
|
+
`Hook ${hAt} timeout ${t}s exceeds the ${maxTimeoutSec}s cap (clamped)`,
|
|
336
|
+
"lower the timeout",
|
|
337
|
+
{ ref: hAt },
|
|
338
|
+
),
|
|
339
|
+
);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
return out;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Sandbox real-capability / silent-degradation (P2 doctor "沙箱真实能力和静默
|
|
350
|
+
* 降级"). Given a probed snapshot, flag the dangerous case: a sandbox is
|
|
351
|
+
* CONFIGURED but its engine is unavailable AND `failIfUnavailable` is off — so
|
|
352
|
+
* tool subprocesses run with NO isolation and nothing warns (you think you're
|
|
353
|
+
* sandboxed but you're not). Strict-but-unavailable is a warn (fail-closed: the
|
|
354
|
+
* agent refuses to start, so it's not silent). Available → an info confirming
|
|
355
|
+
* the true isolation level.
|
|
356
|
+
*
|
|
357
|
+
* @param {object} snapshot { configured, engine, available, reason,
|
|
358
|
+
* failIfUnavailable, isolationLevel }
|
|
359
|
+
*/
|
|
360
|
+
export function checkSandbox(snapshot = {}) {
|
|
361
|
+
const out = [];
|
|
362
|
+
if (!snapshot || !snapshot.configured) return out;
|
|
363
|
+
const engine = snapshot.engine || "sandbox";
|
|
364
|
+
const why = snapshot.reason ? `: ${snapshot.reason}` : "";
|
|
365
|
+
if (snapshot.available) {
|
|
366
|
+
out.push(
|
|
367
|
+
finding(
|
|
368
|
+
"sandbox-active",
|
|
369
|
+
"sandbox",
|
|
370
|
+
"info",
|
|
371
|
+
`Sandbox ${engine} available (isolation: ${snapshot.isolationLevel || "unknown"})`,
|
|
372
|
+
"",
|
|
373
|
+
{ ref: engine },
|
|
374
|
+
),
|
|
375
|
+
);
|
|
376
|
+
return out;
|
|
377
|
+
}
|
|
378
|
+
if (snapshot.failIfUnavailable) {
|
|
379
|
+
out.push(
|
|
380
|
+
finding(
|
|
381
|
+
"sandbox-strict-unavailable",
|
|
382
|
+
"sandbox",
|
|
383
|
+
"warn",
|
|
384
|
+
`Sandbox ${engine} is configured (strict) but unavailable${why} — the agent refuses to start until it's installed`,
|
|
385
|
+
`install ${engine} or unset sandbox.failIfUnavailable`,
|
|
386
|
+
{ ref: engine },
|
|
387
|
+
),
|
|
388
|
+
);
|
|
389
|
+
} else {
|
|
390
|
+
out.push(
|
|
391
|
+
finding(
|
|
392
|
+
"sandbox-silent-degrade",
|
|
393
|
+
"sandbox",
|
|
394
|
+
"error",
|
|
395
|
+
`Sandbox ${engine} is configured but unavailable${why} — commands run WITHOUT isolation and won't warn`,
|
|
396
|
+
`install ${engine}, or set sandbox.failIfUnavailable:true to fail closed`,
|
|
397
|
+
{ ref: engine },
|
|
398
|
+
),
|
|
399
|
+
);
|
|
400
|
+
}
|
|
401
|
+
return out;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Skill ids defined MORE THAN ONCE across (or within) layers (P2 doctor "重复
|
|
406
|
+
* Skill"). The loader's loadAll() silently keeps only the highest-priority copy
|
|
407
|
+
* per id (Map.set overwrite), so a user never learns their custom skill shadowed
|
|
408
|
+
* — or was shadowed by — another. Given the full, un-deduped per-layer entry
|
|
409
|
+
* list, flag every id with more than one definition.
|
|
410
|
+
*
|
|
411
|
+
* @param {Array<{id:string, layer:string}>} entries
|
|
412
|
+
*/
|
|
413
|
+
export function checkDuplicateSkills(entries = []) {
|
|
414
|
+
const byId = new Map(); // id → layer[]
|
|
415
|
+
for (const e of entries) {
|
|
416
|
+
if (!e || !e.id) continue;
|
|
417
|
+
const arr = byId.get(e.id) || [];
|
|
418
|
+
arr.push(e.layer || "?");
|
|
419
|
+
byId.set(e.id, arr);
|
|
420
|
+
}
|
|
421
|
+
const out = [];
|
|
422
|
+
for (const [id, layers] of byId) {
|
|
423
|
+
if (layers.length > 1) {
|
|
424
|
+
const uniq = [...new Set(layers)];
|
|
425
|
+
out.push(
|
|
426
|
+
finding(
|
|
427
|
+
"skill-duplicate",
|
|
428
|
+
"skills",
|
|
429
|
+
"warn",
|
|
430
|
+
`Skill "${id}" has ${layers.length} definitions (${uniq.join(", ")}) — only the highest-priority copy loads`,
|
|
431
|
+
"rename or remove the redundant skill copy",
|
|
432
|
+
{ ref: id, layers: uniq },
|
|
433
|
+
),
|
|
434
|
+
);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
return out;
|
|
438
|
+
}
|
|
439
|
+
|
|
219
440
|
/** Plugins / LSP servers reported unhealthy or dead. */
|
|
220
441
|
export function checkPluginsAndLsp(plugins = []) {
|
|
221
442
|
const out = [];
|
|
@@ -52,11 +52,27 @@ export function baseFireAt(entry) {
|
|
|
52
52
|
return Number.isFinite(n) ? n : null;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
/**
|
|
56
|
+
* The jitter window that governs an entry: a PER-ENTRY `entry.jitterMs` (a
|
|
57
|
+
* finite, non-negative number stored at create time) is authoritative and wins
|
|
58
|
+
* over the caller's `jitterMs` fallback; an entry without its own field falls
|
|
59
|
+
* back to the passed global. This lets each scheduled task carry its own spread
|
|
60
|
+
* — one noisy cron can jitter without perturbing the rest — while still honoring
|
|
61
|
+
* a daemon-wide default for entries that predate per-entry jitter.
|
|
62
|
+
*/
|
|
63
|
+
export function resolveEntryJitterMs(entry, jitterMs = 0) {
|
|
64
|
+
const per = Number(entry?.jitterMs);
|
|
65
|
+
if (Number.isFinite(per) && per >= 0) return per;
|
|
66
|
+
return Number(jitterMs) || 0;
|
|
67
|
+
}
|
|
68
|
+
|
|
55
69
|
/** Base fire time with the entry's deterministic jitter applied. */
|
|
56
70
|
export function effectiveFireAt(entry, jitterMs = 0) {
|
|
57
71
|
const base = baseFireAt(entry);
|
|
58
72
|
if (base == null) return null;
|
|
59
|
-
return
|
|
73
|
+
return (
|
|
74
|
+
base + jitterOffsetMs(entry?.id, resolveEntryJitterMs(entry, jitterMs))
|
|
75
|
+
);
|
|
60
76
|
}
|
|
61
77
|
|
|
62
78
|
/** Is an entry still pending/active (not in a terminal state)? */
|