@herbertgao/pi-extensions 2026.10.0 → 2026.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -12
- package/THIRD_PARTY_NOTICES.md +3 -3
- package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail-audit.md +2 -2
- package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail-debt.md +2 -2
- package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail-gain.md +1 -1
- package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail-help.md +1 -1
- package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail-review.md +2 -2
- package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail.md +1 -1
- package/node_modules/@dietrichgebert/ponytail/.opencode/plugins/index.js +4 -0
- package/node_modules/@dietrichgebert/ponytail/.opencode/plugins/ponytail-frontmatter.cjs +43 -3
- package/node_modules/@dietrichgebert/ponytail/.opencode/plugins/ponytail.mjs +142 -59
- package/node_modules/@dietrichgebert/ponytail/.qoder/rules/ponytail.md +21 -21
- package/node_modules/@dietrichgebert/ponytail/.qoder-plugin/plugin.json +1 -1
- package/node_modules/@dietrichgebert/ponytail/AGENTS.md +21 -21
- package/node_modules/@dietrichgebert/ponytail/README.md +52 -242
- package/node_modules/@dietrichgebert/ponytail/hooks/claude-codex-hooks.json +3 -3
- package/node_modules/@dietrichgebert/ponytail/hooks/copilot-hooks.json +4 -4
- package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-activate.js +70 -16
- package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-config.js +8 -7
- package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-instructions.js +30 -30
- package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-map.js +103 -0
- package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-mode-tracker.js +46 -23
- package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-runtime.js +39 -7
- package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-subagent.js +20 -3
- package/node_modules/@dietrichgebert/ponytail/hooks/qoder-hooks.json +3 -3
- package/node_modules/@dietrichgebert/ponytail/package.json +3 -3
- package/node_modules/@dietrichgebert/ponytail/pi-extension/index.js +47 -17
- package/node_modules/@dietrichgebert/ponytail/scripts/uninstall.js +21 -7
- package/node_modules/@dietrichgebert/ponytail/skills/plugin.json +5 -0
- package/node_modules/@dietrichgebert/ponytail/skills/ponytail/SKILL.md +33 -101
- package/node_modules/@dietrichgebert/ponytail/skills/ponytail-audit/SKILL.md +89 -27
- package/node_modules/@dietrichgebert/ponytail/skills/ponytail-debt/SKILL.md +13 -12
- package/node_modules/@dietrichgebert/ponytail/skills/ponytail-gain/SKILL.md +21 -18
- package/node_modules/@dietrichgebert/ponytail/skills/ponytail-help/SKILL.md +12 -13
- package/node_modules/@dietrichgebert/ponytail/skills/ponytail-review/SKILL.md +96 -52
- package/node_modules/@herbertgao/pi-agency/LICENSE +21 -0
- package/node_modules/@herbertgao/pi-agency/README.md +40 -0
- package/node_modules/@herbertgao/pi-agency/package.json +53 -0
- package/node_modules/@herbertgao/pi-agency/src/index.ts +441 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/compact-thinking.ts +12 -12
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +30 -6
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/default-mode.ts +15 -9
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +27 -9
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/codemode.ts +4 -1
- package/node_modules/@herbertgao/pi-cc-extensions/package.json +2 -2
- package/node_modules/@narumitw/pi-caffeinate/package.json +4 -4
- package/node_modules/@tifan/pi-mermaid-open/package.json +5 -1
- package/node_modules/@tifan/pi-mermaid-open/src/index.ts +26 -9
- package/node_modules/@tifan/pi-recap/package.json +1 -1
- package/node_modules/@tifan/pi-recap/src/index.ts +104 -20
- package/node_modules/@tifan/pi-recap/src/models.ts +46 -4
- package/node_modules/pi-antigravity/README.md +23 -2
- package/node_modules/pi-antigravity/package.json +5 -3
- package/node_modules/pi-antigravity/src/diagnostics/diagnostics.ts +3 -2
- package/node_modules/pi-antigravity/src/features/generate-image.ts +72 -0
- package/node_modules/pi-antigravity/src/features/google-search.ts +71 -0
- package/node_modules/pi-antigravity/src/image/image.ts +86 -47
- package/node_modules/pi-antigravity/src/image/native.ts +69 -0
- package/node_modules/pi-antigravity/src/index.ts +52 -137
- package/node_modules/pi-antigravity/src/search/search.ts +130 -31
- package/node_modules/pi-antigravity/src/stream/stream.ts +162 -113
- package/node_modules/pi-antigravity/src/types/enums.ts +1 -0
- package/node_modules/pi-antigravity/src/types/types.ts +1 -1
- package/node_modules/pi-antigravity/src/utils/security.ts +47 -1
- package/node_modules/pi-antigravity/src/utils/util.ts +38 -6
- package/node_modules/pi-lens/CHANGELOG.md +1064 -0
- package/node_modules/pi-lens/README.md +115 -25
- package/node_modules/pi-lens/config/dependency-cruiser-eager-allowlist.json +6 -2
- package/node_modules/pi-lens/dist/chunk-22AVIGXS.js +560 -0
- package/node_modules/pi-lens/dist/chunk-27BBHSZC.js +106 -0
- package/node_modules/pi-lens/dist/chunk-2BEMIWEW.js +51 -0
- package/node_modules/pi-lens/dist/chunk-2EECBNC5.js +89 -0
- package/node_modules/pi-lens/dist/chunk-34U7PLGE.js +23 -0
- package/node_modules/pi-lens/dist/chunk-3I5QFT3N.js +181 -0
- package/node_modules/pi-lens/dist/chunk-3MED75HT.js +37 -0
- package/node_modules/pi-lens/dist/chunk-47D2BO4S.js +87 -0
- package/node_modules/pi-lens/dist/chunk-4RERDEXR.js +348 -0
- package/node_modules/pi-lens/dist/chunk-4W2PLC4J.js +27 -0
- package/node_modules/pi-lens/dist/chunk-52H5B5TC.js +202 -0
- package/node_modules/pi-lens/dist/chunk-54B42YRX.js +27 -0
- package/node_modules/pi-lens/dist/chunk-5RXBNSW2.js +266 -0
- package/node_modules/pi-lens/dist/chunk-5THXD6X5.js +201 -0
- package/node_modules/pi-lens/dist/chunk-5W3R6LFT.js +24 -0
- package/node_modules/pi-lens/dist/chunk-5ZEJHV35.js +341 -0
- package/node_modules/pi-lens/dist/chunk-6P62QVEA.js +118 -0
- package/node_modules/pi-lens/dist/chunk-6QIUX4EP.js +459 -0
- package/node_modules/pi-lens/dist/chunk-6VCD4VKZ.js +78 -0
- package/node_modules/pi-lens/dist/chunk-7F72PXY2.js +326 -0
- package/node_modules/pi-lens/dist/chunk-7FBF7NPR.js +998 -0
- package/node_modules/pi-lens/dist/chunk-7U2IDNXN.js +37 -0
- package/node_modules/pi-lens/dist/chunk-ABBOA7UD.js +157 -0
- package/node_modules/pi-lens/dist/chunk-AHDW3GPE.js +50 -0
- package/node_modules/pi-lens/dist/chunk-AJ3QXTRQ.js +756 -0
- package/node_modules/pi-lens/dist/chunk-AJVLWNFN.js +1610 -0
- package/node_modules/pi-lens/dist/chunk-AJXODZY6.js +112 -0
- package/node_modules/pi-lens/dist/chunk-ARFCXG7S.js +84 -0
- package/node_modules/pi-lens/dist/chunk-AS44CFQ4.js +708 -0
- package/node_modules/pi-lens/dist/chunk-AWE5TMPO.js +38 -0
- package/node_modules/pi-lens/dist/chunk-B3I2UUT4.js +4692 -0
- package/node_modules/pi-lens/dist/chunk-BRJKOBZP.js +331 -0
- package/node_modules/pi-lens/dist/chunk-BW5KFIQC.js +59 -0
- package/node_modules/pi-lens/dist/chunk-C2AUYXQH.js +149 -0
- package/node_modules/pi-lens/dist/chunk-CGGAIP7J.js +29 -0
- package/node_modules/pi-lens/dist/chunk-D6QS3U6M.js +30 -0
- package/node_modules/pi-lens/dist/chunk-DFVMIKMQ.js +349 -0
- package/node_modules/pi-lens/dist/chunk-DIULIWKU.js +169 -0
- package/node_modules/pi-lens/dist/chunk-DQ2NZ7C4.js +2317 -0
- package/node_modules/pi-lens/dist/chunk-E2WFBRHM.js +213 -0
- package/node_modules/pi-lens/dist/chunk-E4MAEDPM.js +50 -0
- package/node_modules/pi-lens/dist/chunk-EOKRQ3SA.js +30 -0
- package/node_modules/pi-lens/dist/chunk-F3AU2TMM.js +2626 -0
- package/node_modules/pi-lens/dist/chunk-F3P7VQ7H.js +170 -0
- package/node_modules/pi-lens/dist/chunk-FC4RP4I2.js +12 -0
- package/node_modules/pi-lens/dist/chunk-FJNKANOS.js +32 -0
- package/node_modules/pi-lens/dist/chunk-GUOGVTCQ.js +146 -0
- package/node_modules/pi-lens/dist/chunk-GVXA6CCE.js +18 -0
- package/node_modules/pi-lens/dist/chunk-HHYAELLJ.js +2334 -0
- package/node_modules/pi-lens/dist/chunk-HMFXILPV.js +83 -0
- package/node_modules/pi-lens/dist/chunk-HVUZXSWK.js +421 -0
- package/node_modules/pi-lens/dist/chunk-HWBZIGMJ.js +62 -0
- package/node_modules/pi-lens/dist/chunk-I3R7GKDR.js +17 -0
- package/node_modules/pi-lens/dist/chunk-I7SPGOWI.js +55 -0
- package/node_modules/pi-lens/dist/chunk-IIXOAGHR.js +38 -0
- package/node_modules/pi-lens/dist/chunk-IVP5KAB7.js +2250 -0
- package/node_modules/pi-lens/dist/chunk-IXEBJSUE.js +22 -0
- package/node_modules/pi-lens/dist/chunk-JOLITGCC.js +27 -0
- package/node_modules/pi-lens/dist/chunk-K6VYLB2U.js +145 -0
- package/node_modules/pi-lens/dist/chunk-LJDODBBZ.js +78 -0
- package/node_modules/pi-lens/dist/chunk-LNAKEO63.js +78 -0
- package/node_modules/pi-lens/dist/chunk-LSMJ6KBE.js +4139 -0
- package/node_modules/pi-lens/dist/chunk-LW6XKDZQ.js +5565 -0
- package/node_modules/pi-lens/dist/chunk-N3YQJI6O.js +899 -0
- package/node_modules/pi-lens/dist/chunk-NABLC7W3.js +148 -0
- package/node_modules/pi-lens/dist/chunk-NKOUFPQF.js +659 -0
- package/node_modules/pi-lens/dist/chunk-NL5GLMFI.js +211 -0
- package/node_modules/pi-lens/dist/chunk-NMABWBZN.js +327 -0
- package/node_modules/pi-lens/dist/chunk-NTHH2J74.js +27 -0
- package/node_modules/pi-lens/dist/chunk-NTUJEGDZ.js +59 -0
- package/node_modules/pi-lens/dist/chunk-NXL4FFQQ.js +47 -0
- package/node_modules/pi-lens/dist/chunk-NXPS2L6U.js +466 -0
- package/node_modules/pi-lens/dist/chunk-O5WILGMI.js +42 -0
- package/node_modules/pi-lens/dist/chunk-O6TQT6RI.js +48 -0
- package/node_modules/pi-lens/dist/chunk-OAXNDZJ7.js +323 -0
- package/node_modules/pi-lens/dist/chunk-ODEEOXPH.js +44 -0
- package/node_modules/pi-lens/dist/chunk-OQGFCZJ4.js +4533 -0
- package/node_modules/pi-lens/dist/chunk-ORTMY4Q4.js +282 -0
- package/node_modules/pi-lens/dist/chunk-OS32RNR2.js +442 -0
- package/node_modules/pi-lens/dist/chunk-PAK6IDME.js +189 -0
- package/node_modules/pi-lens/dist/chunk-PWFHBTSF.js +406 -0
- package/node_modules/pi-lens/dist/chunk-Q5U6FMDI.js +2352 -0
- package/node_modules/pi-lens/dist/chunk-QOZXJ4NA.js +3364 -0
- package/node_modules/pi-lens/dist/chunk-QYF5S6P6.js +45 -0
- package/node_modules/pi-lens/dist/chunk-RIISMHKN.js +36 -0
- package/node_modules/pi-lens/dist/chunk-RPD4ZSB7.js +25 -0
- package/node_modules/pi-lens/dist/chunk-RPD5K5NC.js +79 -0
- package/node_modules/pi-lens/dist/chunk-RUOG5D2C.js +262 -0
- package/node_modules/pi-lens/dist/chunk-T4ERT73Y.js +599 -0
- package/node_modules/pi-lens/dist/chunk-T6D4Q4AQ.js +54 -0
- package/node_modules/pi-lens/dist/chunk-TGPXLY2J.js +391 -0
- package/node_modules/pi-lens/dist/chunk-TLGFBM3F.js +12116 -0
- package/node_modules/pi-lens/dist/chunk-TO6WL3GM.js +88 -0
- package/node_modules/pi-lens/dist/chunk-TT22N74J.js +517 -0
- package/node_modules/pi-lens/dist/chunk-TVN5N6GY.js +21216 -0
- package/node_modules/pi-lens/dist/chunk-U3VGR4VU.js +308 -0
- package/node_modules/pi-lens/dist/chunk-UK3CMEAL.js +1250 -0
- package/node_modules/pi-lens/dist/chunk-UOPVJQ4N.js +103 -0
- package/node_modules/pi-lens/dist/chunk-UXVNL3D7.js +23 -0
- package/node_modules/pi-lens/dist/chunk-UY752QSN.js +45 -0
- package/node_modules/pi-lens/dist/chunk-V5PXFSZK.js +188 -0
- package/node_modules/pi-lens/dist/chunk-V7R425XG.js +398 -0
- package/node_modules/pi-lens/dist/chunk-VCSRSYLF.js +81 -0
- package/node_modules/pi-lens/dist/chunk-VD4JQCQC.js +162 -0
- package/node_modules/pi-lens/dist/chunk-VDBPVIKD.js +62 -0
- package/node_modules/pi-lens/dist/chunk-VHQLPIRJ.js +114 -0
- package/node_modules/pi-lens/dist/chunk-VN2AXLEX.js +5414 -0
- package/node_modules/pi-lens/dist/chunk-VNMT7C64.js +478 -0
- package/node_modules/pi-lens/dist/chunk-WONERJTP.js +309 -0
- package/node_modules/pi-lens/dist/chunk-XECLWQZN.js +85 -0
- package/node_modules/pi-lens/dist/chunk-XIMYZ3JA.js +27 -0
- package/node_modules/pi-lens/dist/chunk-XK4CIILI.js +144 -0
- package/node_modules/pi-lens/dist/chunk-Y4T27COV.js +562 -0
- package/node_modules/pi-lens/dist/chunk-YGVYKNSN.js +1860 -0
- package/node_modules/pi-lens/dist/chunk-YLF3PPT5.js +308 -0
- package/node_modules/pi-lens/dist/chunk-YSNFMJKN.js +14 -0
- package/node_modules/pi-lens/dist/chunk-Z3CCVDUB.js +76 -0
- package/node_modules/pi-lens/dist/chunk-Z54ZSOBZ.js +61 -0
- package/node_modules/pi-lens/dist/chunk-ZAWW3AF6.js +97 -0
- package/node_modules/pi-lens/dist/chunk-ZMOL6RQC.js +167 -0
- package/node_modules/pi-lens/dist/index.js +16456 -8335
- package/node_modules/pi-lens/dist/mcp/analyze-cli.js +186 -232
- package/node_modules/pi-lens/dist/mcp/cli.js +137 -98
- package/node_modules/pi-lens/dist/mcp/server.js +22589 -1573
- package/node_modules/pi-lens/dist/mcp/worker.js +97 -38
- package/node_modules/pi-lens/dist/probes/installer.js +135 -0
- package/node_modules/pi-lens/dist/workers/project-snapshot-persist-worker.js +22 -0
- package/node_modules/pi-lens/dist/workers/review-graph-persist-worker.js +15 -0
- package/node_modules/pi-lens/docs/agent-guide.md +13 -4
- package/node_modules/pi-lens/docs/agent-tools.md +42 -0
- package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +3 -2
- package/node_modules/pi-lens/docs/configuration.md +20 -1
- package/node_modules/pi-lens/docs/environment-variables.md +52 -2
- package/node_modules/pi-lens/docs/features.md +8 -4
- package/node_modules/pi-lens/docs/globalconfig.md +1 -0
- package/node_modules/pi-lens/docs/io-bridge-v2-migration.md +94 -0
- package/node_modules/pi-lens/docs/lsp-capability-matrix.md +36 -4
- package/node_modules/pi-lens/docs/lsp-idle-eviction.md +124 -0
- package/node_modules/pi-lens/docs/mcp.md +21 -5
- package/node_modules/pi-lens/docs/merge-queue-rollout.md +77 -0
- package/node_modules/pi-lens/docs/pi-lens-fixer.md +156 -88
- package/node_modules/pi-lens/docs/pi-lens-investigator.md +74 -26
- package/node_modules/pi-lens/docs/pi-lens-merge-policy.md +694 -0
- package/node_modules/pi-lens/docs/pi-lens-monitor.md +73 -7
- package/node_modules/pi-lens/docs/pi-lens-retro.md +6 -4
- package/node_modules/pi-lens/docs/pi-lens-reviewer.md +188 -48
- package/node_modules/pi-lens/docs/pi-lens-subagent.md +246 -45
- package/node_modules/pi-lens/docs/pi-lens-warden.md +18 -7
- package/node_modules/pi-lens/docs/public-api-stability.md +55 -0
- package/node_modules/pi-lens/docs/release-qa-baseline.md +84 -17
- package/node_modules/pi-lens/docs/rfcs/3654-unified-io-bridge-v2.md +316 -0
- package/node_modules/pi-lens/docs/servercapabilities.md +53 -49
- package/node_modules/pi-lens/docs/settings.md +1 -0
- package/node_modules/pi-lens/docs/usage.md +5 -1
- package/node_modules/pi-lens/grammars/tree-sitter-bash.wasm +0 -0
- package/node_modules/pi-lens/grammars/tree-sitter-bash.wasm.json +3 -3
- package/node_modules/pi-lens/package.json +18 -6
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/advisory-registry-subset-test.yml +41 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/advisory-registry-subset.yml +50 -0
- package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +1275 -62
- package/node_modules/pi-lens/scripts/download-grammars.js +5 -0
- package/node_modules/pi-lens/scripts/grammars.lock.json +6 -1
- package/node_modules/pi-lens/scripts/install-selftest.mjs +33 -34
- package/node_modules/pi-lens/scripts/lib/host-provided-deps.mjs +13 -4
- package/node_modules/pi-lens/scripts/lib/web-tree-sitter-dir.mjs +18 -0
- package/node_modules/pi-typesafe/README.md +1 -1
- package/node_modules/pi-typesafe/dist/backends.d.ts +15 -5
- package/node_modules/pi-typesafe/dist/backends.js +18 -0
- package/node_modules/pi-typesafe/dist/client.d.ts +4 -3
- package/node_modules/pi-typesafe/dist/client.js +22 -7
- package/node_modules/pi-typesafe/dist/index.d.ts +2 -2
- package/node_modules/pi-typesafe/dist/index.js +1 -1
- package/node_modules/pi-typesafe/dist/usage.d.ts +14 -4
- package/node_modules/pi-typesafe/dist/usage.js +147 -42
- package/node_modules/pi-typesafe/package.json +1 -1
- package/node_modules/pi-web-access/CHANGELOG.md +48 -0
- package/node_modules/pi-web-access/README.md +57 -11
- package/node_modules/pi-web-access/brave-rate-limit.ts +8 -2
- package/node_modules/pi-web-access/curator-page.ts +5 -1
- package/node_modules/pi-web-access/curator-server.ts +2 -0
- package/node_modules/pi-web-access/declared-web-links.ts +2 -2
- package/node_modules/pi-web-access/degoog.ts +323 -0
- package/node_modules/pi-web-access/dist/index.js +3483 -2745
- package/node_modules/pi-web-access/dist/mcp-cli.js +27443 -0
- package/node_modules/pi-web-access/exa.ts +5 -1
- package/node_modules/pi-web-access/extract.ts +41 -3
- package/node_modules/pi-web-access/firecrawl.ts +35 -4
- package/node_modules/pi-web-access/gemini-search.ts +34 -11
- package/node_modules/pi-web-access/gemini-web.ts +14 -9
- package/node_modules/pi-web-access/index.ts +153 -1202
- package/node_modules/pi-web-access/keenable.ts +221 -0
- package/node_modules/pi-web-access/mcp-cli.ts +40 -0
- package/node_modules/pi-web-access/mcp-server.ts +81 -0
- package/node_modules/pi-web-access/mcp-tool-definitions.ts +117 -0
- package/node_modules/pi-web-access/openai-search.ts +34 -1
- package/node_modules/pi-web-access/package.json +23 -5
- package/node_modules/pi-web-access/perplexity.ts +64 -56
- package/node_modules/pi-web-access/tool-arguments.ts +20 -0
- package/node_modules/pi-web-access/video-extract.ts +1 -1
- package/node_modules/pi-web-access/web-tool-contract.ts +86 -0
- package/node_modules/pi-web-access/web-tool-core.ts +1502 -0
- package/node_modules/pi-web-access/youtube-extract.ts +2 -5
- package/package.json +17 -12
- package/node_modules/@dietrichgebert/ponytail/README.es.md +0 -329
- package/node_modules/@dietrichgebert/ponytail/README.ko.md +0 -346
- package/node_modules/@dietrichgebert/ponytail/assets/benchmark-3model.svg +0 -21
- package/node_modules/@dietrichgebert/ponytail/assets/benchmark-agentic.svg +0 -62
- package/node_modules/@dietrichgebert/ponytail/assets/logo-dark.png +0 -0
- package/node_modules/@dietrichgebert/ponytail/assets/logo-dark.svg +0 -115
- package/node_modules/@dietrichgebert/ponytail/assets/logo-greenpt-dark.svg +0 -27
- package/node_modules/@dietrichgebert/ponytail/assets/logo-greenpt.svg +0 -27
- package/node_modules/@dietrichgebert/ponytail/assets/logo.png +0 -0
- package/node_modules/@dietrichgebert/ponytail/assets/retriever-icon.png +0 -0
- package/node_modules/@dietrichgebert/ponytail/assets/retriever-logo-dark.svg +0 -4
- package/node_modules/@dietrichgebert/ponytail/assets/retriever-logo-light.svg +0 -4
- package/node_modules/@dietrichgebert/ponytail/assets/social-preview.png +0 -0
- package/node_modules/@dietrichgebert/ponytail/assets/waitlist-banner-es.png +0 -0
- package/node_modules/@dietrichgebert/ponytail/assets/waitlist-banner-ko.png +0 -0
- package/node_modules/@dietrichgebert/ponytail/assets/waitlist-banner.png +0 -0
- package/node_modules/pi-lens/dist/clients/actionable-warnings-logger.js +0 -35
- package/node_modules/pi-lens/dist/clients/actionable-warnings.js +0 -1610
- package/node_modules/pi-lens/dist/clients/advisory-provenance.js +0 -593
- package/node_modules/pi-lens/dist/clients/agent-behavior-client.js +0 -147
- package/node_modules/pi-lens/dist/clients/agent-nudge.js +0 -325
- package/node_modules/pi-lens/dist/clients/analysed-root.js +0 -1
- package/node_modules/pi-lens/dist/clients/ast-grep-client.js +0 -731
- package/node_modules/pi-lens/dist/clients/ast-grep-rule-manager.js +0 -146
- package/node_modules/pi-lens/dist/clients/ast-grep-tool-logger.js +0 -118
- package/node_modules/pi-lens/dist/clients/ast-grep-types.js +0 -10
- package/node_modules/pi-lens/dist/clients/ast-grep-yaml-synth.js +0 -154
- package/node_modules/pi-lens/dist/clients/atomic-write-staging.js +0 -75
- package/node_modules/pi-lens/dist/clients/atomic-write.js +0 -189
- package/node_modules/pi-lens/dist/clients/availability-probe-flight.js +0 -12
- package/node_modules/pi-lens/dist/clients/bash-file-access.js +0 -1056
- package/node_modules/pi-lens/dist/clients/biome-client.js +0 -357
- package/node_modules/pi-lens/dist/clients/blocker-freshness.js +0 -837
- package/node_modules/pi-lens/dist/clients/blocker-past-eof.js +0 -129
- package/node_modules/pi-lens/dist/clients/bootstrap.js +0 -569
- package/node_modules/pi-lens/dist/clients/bounded-cache.js +0 -190
- package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +0 -202
- package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +0 -295
- package/node_modules/pi-lens/dist/clients/build-identity.js +0 -95
- package/node_modules/pi-lens/dist/clients/bundled-resource-health.js +0 -113
- package/node_modules/pi-lens/dist/clients/bus-events-logger.js +0 -105
- package/node_modules/pi-lens/dist/clients/bus-publish.js +0 -171
- package/node_modules/pi-lens/dist/clients/cache/rule-cache.js +0 -190
- package/node_modules/pi-lens/dist/clients/cache-manager.js +0 -524
- package/node_modules/pi-lens/dist/clients/cache-observability.js +0 -1313
- package/node_modules/pi-lens/dist/clients/call-graph.js +0 -852
- package/node_modules/pi-lens/dist/clients/cargo-manifest.js +0 -422
- package/node_modules/pi-lens/dist/clients/cascade-budget.js +0 -196
- package/node_modules/pi-lens/dist/clients/cascade-format.js +0 -315
- package/node_modules/pi-lens/dist/clients/cascade-logger.js +0 -31
- package/node_modules/pi-lens/dist/clients/cascade-types.js +0 -9
- package/node_modules/pi-lens/dist/clients/child-unref.js +0 -124
- package/node_modules/pi-lens/dist/clients/code-quality-warnings.js +0 -286
- package/node_modules/pi-lens/dist/clients/codebase-model.js +0 -173
- package/node_modules/pi-lens/dist/clients/collateral-test-role.js +0 -40
- package/node_modules/pi-lens/dist/clients/complexity-client.js +0 -462
- package/node_modules/pi-lens/dist/clients/config-core/deny.js +0 -221
- package/node_modules/pi-lens/dist/clients/config-core/index.js +0 -50
- package/node_modules/pi-lens/dist/clients/config-core/merge.js +0 -357
- package/node_modules/pi-lens/dist/clients/config-core/normalize.js +0 -340
- package/node_modules/pi-lens/dist/clients/config-core/process-spec.js +0 -248
- package/node_modules/pi-lens/dist/clients/config-core/provenance.js +0 -164
- package/node_modules/pi-lens/dist/clients/config-core/records.js +0 -218
- package/node_modules/pi-lens/dist/clients/config-core/resolve.js +0 -125
- package/node_modules/pi-lens/dist/clients/config-core/safe-object.js +0 -78
- package/node_modules/pi-lens/dist/clients/config-core/schema.js +0 -165
- package/node_modules/pi-lens/dist/clients/config-diagnostic-codes.js +0 -285
- package/node_modules/pi-lens/dist/clients/config-locations.js +0 -388
- package/node_modules/pi-lens/dist/clients/config-resolve.js +0 -798
- package/node_modules/pi-lens/dist/clients/config-schema.js +0 -251
- package/node_modules/pi-lens/dist/clients/config-warn.js +0 -407
- package/node_modules/pi-lens/dist/clients/console-guard-install.js +0 -26
- package/node_modules/pi-lens/dist/clients/cooperative-budget.js +0 -42
- package/node_modules/pi-lens/dist/clients/dead-code-client.js +0 -510
- package/node_modules/pi-lens/dist/clients/dead-code-logger.js +0 -30
- package/node_modules/pi-lens/dist/clients/deadline-utils.js +0 -280
- package/node_modules/pi-lens/dist/clients/debug-handles.js +0 -211
- package/node_modules/pi-lens/dist/clients/debug-heap.js +0 -174
- package/node_modules/pi-lens/dist/clients/deferred-lsp-work.js +0 -106
- package/node_modules/pi-lens/dist/clients/degradation-ledger.js +0 -426
- package/node_modules/pi-lens/dist/clients/demoted-finding-render.js +0 -169
- package/node_modules/pi-lens/dist/clients/dependency-checker.js +0 -885
- package/node_modules/pi-lens/dist/clients/deps/ast-grep-napi.js +0 -22
- package/node_modules/pi-lens/dist/clients/deps/js-yaml.js +0 -9
- package/node_modules/pi-lens/dist/clients/deps/minimatch.js +0 -4
- package/node_modules/pi-lens/dist/clients/deps/pi-tui.js +0 -14
- package/node_modules/pi-lens/dist/clients/deps/typebox.js +0 -14
- package/node_modules/pi-lens/dist/clients/deps/vscode-jsonrpc.js +0 -1
- package/node_modules/pi-lens/dist/clients/deps/web-tree-sitter.js +0 -24
- package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +0 -630
- package/node_modules/pi-lens/dist/clients/diagnostic-line-freshness.js +0 -305
- package/node_modules/pi-lens/dist/clients/diagnostic-logger.js +0 -73
- package/node_modules/pi-lens/dist/clients/diagnostic-tracker.js +0 -105
- package/node_modules/pi-lens/dist/clients/diagnostics-publish.js +0 -230
- package/node_modules/pi-lens/dist/clients/dispatch/ast-grep-catalog.js +0 -65
- package/node_modules/pi-lens/dist/clients/dispatch/auxiliary-lsp.js +0 -343
- package/node_modules/pi-lens/dist/clients/dispatch/collect-later-tier.js +0 -35
- package/node_modules/pi-lens/dist/clients/dispatch/diagnostic-taxonomy.js +0 -66
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +0 -1269
- package/node_modules/pi-lens/dist/clients/dispatch/fact-provider-types.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/fact-rule-runner.js +0 -17
- package/node_modules/pi-lens/dist/clients/dispatch/fact-runner.js +0 -30
- package/node_modules/pi-lens/dist/clients/dispatch/fact-scheduler.js +0 -68
- package/node_modules/pi-lens/dist/clients/dispatch/fact-store.js +0 -377
- package/node_modules/pi-lens/dist/clients/dispatch/facts/comment-facts.js +0 -22
- package/node_modules/pi-lens/dist/clients/dispatch/facts/file-content.js +0 -19
- package/node_modules/pi-lens/dist/clients/dispatch/facts/function-facts.js +0 -348
- package/node_modules/pi-lens/dist/clients/dispatch/facts/import-facts.js +0 -204
- package/node_modules/pi-lens/dist/clients/dispatch/facts/tree-sitter-facts.js +0 -34
- package/node_modules/pi-lens/dist/clients/dispatch/facts/try-catch-facts.js +0 -119
- package/node_modules/pi-lens/dist/clients/dispatch/finding-policy.js +0 -339
- package/node_modules/pi-lens/dist/clients/dispatch/indent-detect.js +0 -417
- package/node_modules/pi-lens/dist/clients/dispatch/inline-suppressions.js +0 -89
- package/node_modules/pi-lens/dist/clients/dispatch/integration.js +0 -2377
- package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +0 -11
- package/node_modules/pi-lens/dist/clients/dispatch/pending-runner-findings.js +0 -87
- package/node_modules/pi-lens/dist/clients/dispatch/plan.js +0 -278
- package/node_modules/pi-lens/dist/clients/dispatch/priorities.js +0 -20
- package/node_modules/pi-lens/dist/clients/dispatch/rule-id-normalize.js +0 -50
- package/node_modules/pi-lens/dist/clients/dispatch/rule-ignores.js +0 -69
- package/node_modules/pi-lens/dist/clients/dispatch/rule-policy.js +0 -135
- package/node_modules/pi-lens/dist/clients/dispatch/rules/async-noise.js +0 -40
- package/node_modules/pi-lens/dist/clients/dispatch/rules/async-unnecessary-wrapper.js +0 -27
- package/node_modules/pi-lens/dist/clients/dispatch/rules/cors-wildcard.js +0 -54
- package/node_modules/pi-lens/dist/clients/dispatch/rules/error-obscuring.js +0 -32
- package/node_modules/pi-lens/dist/clients/dispatch/rules/error-swallowing.js +0 -31
- package/node_modules/pi-lens/dist/clients/dispatch/rules/framework-call-noise.js +0 -67
- package/node_modules/pi-lens/dist/clients/dispatch/rules/high-complexity.js +0 -72
- package/node_modules/pi-lens/dist/clients/dispatch/rules/high-fan-out.js +0 -74
- package/node_modules/pi-lens/dist/clients/dispatch/rules/high-import-coupling.js +0 -37
- package/node_modules/pi-lens/dist/clients/dispatch/rules/missing-error-propagation.js +0 -62
- package/node_modules/pi-lens/dist/clients/dispatch/rules/no-commented-credentials.js +0 -52
- package/node_modules/pi-lens/dist/clients/dispatch/rules/pass-through-wrappers.js +0 -42
- package/node_modules/pi-lens/dist/clients/dispatch/rules/placeholder-comments.js +0 -40
- package/node_modules/pi-lens/dist/clients/dispatch/rules/unsafe-boundary.js +0 -126
- package/node_modules/pi-lens/dist/clients/dispatch/runner-context.js +0 -52
- package/node_modules/pi-lens/dist/clients/dispatch/runners/actionlint.js +0 -111
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +0 -1196
- package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +0 -296
- package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +0 -219
- package/node_modules/pi-lens/dist/clients/dispatch/runners/credo.js +0 -82
- package/node_modules/pi-lens/dist/clients/dispatch/runners/cue-vet.js +0 -416
- package/node_modules/pi-lens/dist/clients/dispatch/runners/dart-analyze.js +0 -183
- package/node_modules/pi-lens/dist/clients/dispatch/runners/detekt.js +0 -176
- package/node_modules/pi-lens/dist/clients/dispatch/runners/dotnet-build.js +0 -164
- package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +0 -195
- package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +0 -137
- package/node_modules/pi-lens/dist/clients/dispatch/runners/fact-rules.js +0 -29
- package/node_modules/pi-lens/dist/clients/dispatch/runners/fish-indent.js +0 -69
- package/node_modules/pi-lens/dist/clients/dispatch/runners/gleam-check.js +0 -167
- package/node_modules/pi-lens/dist/clients/dispatch/runners/go-vet.js +0 -104
- package/node_modules/pi-lens/dist/clients/dispatch/runners/golangci-lint.js +0 -135
- package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +0 -91
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-lint.js +0 -171
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +0 -940
- package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +0 -117
- package/node_modules/pi-lens/dist/clients/dispatch/runners/index.js +0 -108
- package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +0 -99
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ktlint.js +0 -110
- package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +0 -379
- package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +0 -167
- package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +0 -102
- package/node_modules/pi-lens/dist/clients/dispatch/runners/oxlint.js +0 -414
- package/node_modules/pi-lens/dist/clients/dispatch/runners/php-lint.js +0 -85
- package/node_modules/pi-lens/dist/clients/dispatch/runners/phpstan.js +0 -120
- package/node_modules/pi-lens/dist/clients/dispatch/runners/prisma-validate.js +0 -62
- package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +0 -445
- package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +0 -169
- package/node_modules/pi-lens/dist/clients/dispatch/runners/rubocop.js +0 -99
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ruff.js +0 -88
- package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +0 -256
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shellcheck.js +0 -173
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shfmt.js +0 -102
- package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +0 -128
- package/node_modules/pi-lens/dist/clients/dispatch/runners/spotbugs.js +0 -259
- package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +0 -183
- package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +0 -166
- package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.js +0 -163
- package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +0 -174
- package/node_modules/pi-lens/dist/clients/dispatch/runners/terragrunt.js +0 -168
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +0 -125
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tree-sitter.js +0 -643
- package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +0 -253
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +0 -496
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +0 -90
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/diagnostic-parsers.js +0 -95
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/lazy-installer.js +0 -274
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +0 -1701
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +0 -101
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/tool-failure.js +0 -235
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +0 -169
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils.js +0 -15
- package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +0 -128
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yaml-rule-parser.js +0 -242
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +0 -95
- package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +0 -79
- package/node_modules/pi-lens/dist/clients/dispatch/suppress-writer.js +0 -79
- package/node_modules/pi-lens/dist/clients/dispatch/tool-profile.js +0 -30
- package/node_modules/pi-lens/dist/clients/dispatch/types.js +0 -21
- package/node_modules/pi-lens/dist/clients/dispatch/utils/format-utils.js +0 -45
- package/node_modules/pi-lens/dist/clients/dispatch/utils/lsp-diagnostics.js +0 -35
- package/node_modules/pi-lens/dist/clients/disposition-logger.js +0 -32
- package/node_modules/pi-lens/dist/clients/disposition-publish.js +0 -124
- package/node_modules/pi-lens/dist/clients/durable-store.js +0 -97
- package/node_modules/pi-lens/dist/clients/effective-config.js +0 -415
- package/node_modules/pi-lens/dist/clients/env-utils.js +0 -83
- package/node_modules/pi-lens/dist/clients/error-class.js +0 -23
- package/node_modules/pi-lens/dist/clients/eval-timestamp.js +0 -17
- package/node_modules/pi-lens/dist/clients/event-loop-hold.js +0 -274
- package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +0 -250
- package/node_modules/pi-lens/dist/clients/extension-log.js +0 -504
- package/node_modules/pi-lens/dist/clients/extension-mode.js +0 -73
- package/node_modules/pi-lens/dist/clients/feature-hints.js +0 -103
- package/node_modules/pi-lens/dist/clients/file-kinds.js +0 -412
- package/node_modules/pi-lens/dist/clients/file-role.js +0 -134
- package/node_modules/pi-lens/dist/clients/file-time.js +0 -160
- package/node_modules/pi-lens/dist/clients/file-utils.js +0 -1032
- package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +0 -494
- package/node_modules/pi-lens/dist/clients/finding-identity.js +0 -88
- package/node_modules/pi-lens/dist/clients/fix-worklog.js +0 -103
- package/node_modules/pi-lens/dist/clients/format-events-publish.js +0 -343
- package/node_modules/pi-lens/dist/clients/format-service.js +0 -222
- package/node_modules/pi-lens/dist/clients/formatters-lazy.js +0 -9
- package/node_modules/pi-lens/dist/clients/formatters.js +0 -2032
- package/node_modules/pi-lens/dist/clients/freshness-cadence.js +0 -17
- package/node_modules/pi-lens/dist/clients/freshness.js +0 -38
- package/node_modules/pi-lens/dist/clients/generated-artifacts.js +0 -394
- package/node_modules/pi-lens/dist/clients/generation-guard.js +0 -215
- package/node_modules/pi-lens/dist/clients/git-guard.js +0 -1136
- package/node_modules/pi-lens/dist/clients/git-tracked-ignore.js +0 -243
- package/node_modules/pi-lens/dist/clients/gitleaks-client.js +0 -509
- package/node_modules/pi-lens/dist/clients/go-client.js +0 -104
- package/node_modules/pi-lens/dist/clients/govulncheck-client.js +0 -605
- package/node_modules/pi-lens/dist/clients/gradle-ktfmt-style.js +0 -348
- package/node_modules/pi-lens/dist/clients/grammar-source.js +0 -465
- package/node_modules/pi-lens/dist/clients/gzip-stage-write.js +0 -135
- package/node_modules/pi-lens/dist/clients/hashline-anchor.js +0 -424
- package/node_modules/pi-lens/dist/clients/hook-budgets.js +0 -76
- package/node_modules/pi-lens/dist/clients/host-edit-normalize.js +0 -140
- package/node_modules/pi-lens/dist/clients/host-ports.js +0 -39
- package/node_modules/pi-lens/dist/clients/indent-retarget.js +0 -154
- package/node_modules/pi-lens/dist/clients/inline-blocker-dispositions.js +0 -186
- package/node_modules/pi-lens/dist/clients/install-diagnostics.js +0 -156
- package/node_modules/pi-lens/dist/clients/installer/index.js +0 -5416
- package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh-session.js +0 -58
- package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh.js +0 -783
- package/node_modules/pi-lens/dist/clients/instance-reaper-state.js +0 -7
- package/node_modules/pi-lens/dist/clients/instance-reaper.js +0 -1137
- package/node_modules/pi-lens/dist/clients/instance-registry-lock.js +0 -145
- package/node_modules/pi-lens/dist/clients/instance-registry.js +0 -773
- package/node_modules/pi-lens/dist/clients/jscpd-client.js +0 -378
- package/node_modules/pi-lens/dist/clients/json-cache-read.js +0 -65
- package/node_modules/pi-lens/dist/clients/knip-client.js +0 -788
- package/node_modules/pi-lens/dist/clients/language-policy.js +0 -252
- package/node_modules/pi-lens/dist/clients/language-profile.js +0 -361
- package/node_modules/pi-lens/dist/clients/language-registry.js +0 -603
- package/node_modules/pi-lens/dist/clients/latency-logger.js +0 -727
- package/node_modules/pi-lens/dist/clients/lazy-import.js +0 -21
- package/node_modules/pi-lens/dist/clients/ledger-bounds.js +0 -54
- package/node_modules/pi-lens/dist/clients/lens-config.js +0 -404
- package/node_modules/pi-lens/dist/clients/lens-engine.js +0 -358
- package/node_modules/pi-lens/dist/clients/lens-events.js +0 -125
- package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +0 -467
- package/node_modules/pi-lens/dist/clients/lens-map.js +0 -1156
- package/node_modules/pi-lens/dist/clients/live-bus-emitter.js +0 -74
- package/node_modules/pi-lens/dist/clients/log-cleanup.js +0 -222
- package/node_modules/pi-lens/dist/clients/lsp/aggregation.js +0 -178
- package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +0 -421
- package/node_modules/pi-lens/dist/clients/lsp/client.js +0 -4593
- package/node_modules/pi-lens/dist/clients/lsp/config.js +0 -691
- package/node_modules/pi-lens/dist/clients/lsp/content-limits.js +0 -41
- package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +0 -225
- package/node_modules/pi-lens/dist/clients/lsp/document-drift.js +0 -467
- package/node_modules/pi-lens/dist/clients/lsp/edits.js +0 -1219
- package/node_modules/pi-lens/dist/clients/lsp/index.js +0 -8305
- package/node_modules/pi-lens/dist/clients/lsp/inferred-project.js +0 -216
- package/node_modules/pi-lens/dist/clients/lsp/jvm-runtime.js +0 -298
- package/node_modules/pi-lens/dist/clients/lsp/language.js +0 -63
- package/node_modules/pi-lens/dist/clients/lsp/launch.js +0 -746
- package/node_modules/pi-lens/dist/clients/lsp/lombok.js +0 -158
- package/node_modules/pi-lens/dist/clients/lsp/path-utils.js +0 -5
- package/node_modules/pi-lens/dist/clients/lsp/pending-aux-coverage.js +0 -251
- package/node_modules/pi-lens/dist/clients/lsp/position-encoding.js +0 -61
- package/node_modules/pi-lens/dist/clients/lsp/ruby-drive-dirs.js +0 -83
- package/node_modules/pi-lens/dist/clients/lsp/server.js +0 -3290
- package/node_modules/pi-lens/dist/clients/lsp/session-roots.js +0 -192
- package/node_modules/pi-lens/dist/clients/lsp/spawn-history.js +0 -17
- package/node_modules/pi-lens/dist/clients/lsp/sync-kind.js +0 -56
- package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +0 -332
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/capability-snapshot.js +0 -1
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/classification.js +0 -85
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/index.js +0 -10
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +0 -392
- package/node_modules/pi-lens/dist/clients/lsp/watch-queue.js +0 -61
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +0 -639
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-session.js +0 -30
- package/node_modules/pi-lens/dist/clients/lsp/workspace-sweep-hold.js +0 -184
- package/node_modules/pi-lens/dist/clients/lsp-budget.js +0 -186
- package/node_modules/pi-lens/dist/clients/lsp-document-symbols.js +0 -110
- package/node_modules/pi-lens/dist/clients/lsp-lazy.js +0 -9
- package/node_modules/pi-lens/dist/clients/lsp-mutation.js +0 -396
- package/node_modules/pi-lens/dist/clients/lsp-status.js +0 -59
- package/node_modules/pi-lens/dist/clients/map-with-concurrency.js +0 -40
- package/node_modules/pi-lens/dist/clients/mcp/analyze.js +0 -420
- package/node_modules/pi-lens/dist/clients/mcp/host-shim.js +0 -31
- package/node_modules/pi-lens/dist/clients/mcp/ipc.js +0 -523
- package/node_modules/pi-lens/dist/clients/mcp/review.js +0 -197
- package/node_modules/pi-lens/dist/clients/mcp/session.js +0 -412
- package/node_modules/pi-lens/dist/clients/memory-sampler.js +0 -208
- package/node_modules/pi-lens/dist/clients/message-end-attribution.js +0 -30
- package/node_modules/pi-lens/dist/clients/metrics-client.js +0 -107
- package/node_modules/pi-lens/dist/clients/metrics-history.js +0 -327
- package/node_modules/pi-lens/dist/clients/middle-man-analysis.js +0 -263
- package/node_modules/pi-lens/dist/clients/model-provider.js +0 -53
- package/node_modules/pi-lens/dist/clients/module-report-lsp.js +0 -189
- package/node_modules/pi-lens/dist/clients/module-report.js +0 -2150
- package/node_modules/pi-lens/dist/clients/mutating-tool.js +0 -651
- package/node_modules/pi-lens/dist/clients/mutation-attribution.js +0 -368
- package/node_modules/pi-lens/dist/clients/mutation-bridge.js +0 -240
- package/node_modules/pi-lens/dist/clients/ndjson-logger.js +0 -734
- package/node_modules/pi-lens/dist/clients/observed-mutation-sources.js +0 -101
- package/node_modules/pi-lens/dist/clients/observed-mutation.js +0 -1253
- package/node_modules/pi-lens/dist/clients/oldtext-autopatch.js +0 -128
- package/node_modules/pi-lens/dist/clients/opaque-mutation-scan.js +0 -496
- package/node_modules/pi-lens/dist/clients/opengrep-client.js +0 -333
- package/node_modules/pi-lens/dist/clients/opengrep-config.js +0 -76
- package/node_modules/pi-lens/dist/clients/package-manager.js +0 -607
- package/node_modules/pi-lens/dist/clients/package-root.js +0 -38
- package/node_modules/pi-lens/dist/clients/partial-edit-apply.js +0 -439
- package/node_modules/pi-lens/dist/clients/path-attribution-telemetry.js +0 -43
- package/node_modules/pi-lens/dist/clients/path-keyed-map.js +0 -108
- package/node_modules/pi-lens/dist/clients/path-utils.js +0 -1244
- package/node_modules/pi-lens/dist/clients/performance-report.js +0 -331
- package/node_modules/pi-lens/dist/clients/persist-debounce.js +0 -70
- package/node_modules/pi-lens/dist/clients/persistent-reverify.js +0 -271
- package/node_modules/pi-lens/dist/clients/php-cs-fixer-config.js +0 -119
- package/node_modules/pi-lens/dist/clients/pipeline.js +0 -1480
- package/node_modules/pi-lens/dist/clients/post-autofix-notice.js +0 -37
- package/node_modules/pi-lens/dist/clients/print-mode.js +0 -21
- package/node_modules/pi-lens/dist/clients/probe-home-state.js +0 -228
- package/node_modules/pi-lens/dist/clients/process-bridge.js +0 -66
- package/node_modules/pi-lens/dist/clients/process-singletons.js +0 -210
- package/node_modules/pi-lens/dist/clients/process-snapshot.js +0 -68
- package/node_modules/pi-lens/dist/clients/project-changes.js +0 -181
- package/node_modules/pi-lens/dist/clients/project-conventions.js +0 -171
- package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +0 -137
- package/node_modules/pi-lens/dist/clients/project-diagnostics/extractors.js +0 -109
- package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +0 -668
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/call-graph-impact.js +0 -118
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/dead-code.js +0 -47
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +0 -40
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/govulncheck.js +0 -34
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/jscpd.js +0 -38
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/knip.js +0 -47
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/madge.js +0 -48
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/opengrep.js +0 -40
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +0 -127
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/trivy.js +0 -81
- package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +0 -520
- package/node_modules/pi-lens/dist/clients/project-diagnostics/types.js +0 -1
- package/node_modules/pi-lens/dist/clients/project-lens-config.js +0 -807
- package/node_modules/pi-lens/dist/clients/project-report.js +0 -701
- package/node_modules/pi-lens/dist/clients/project-scale.js +0 -237
- package/node_modules/pi-lens/dist/clients/project-scan-policy.js +0 -11
- package/node_modules/pi-lens/dist/clients/project-snapshot-fingerprint.js +0 -48
- package/node_modules/pi-lens/dist/clients/project-snapshot-persist-worker.js +0 -20
- package/node_modules/pi-lens/dist/clients/project-snapshot.js +0 -1653
- package/node_modules/pi-lens/dist/clients/project-trust.js +0 -181
- package/node_modules/pi-lens/dist/clients/python-environment.js +0 -217
- package/node_modules/pi-lens/dist/clients/python-provenance.js +0 -639
- package/node_modules/pi-lens/dist/clients/quiet-window-config.js +0 -47
- package/node_modules/pi-lens/dist/clients/quiet-window.js +0 -236
- package/node_modules/pi-lens/dist/clients/read-bridge.js +0 -139
- package/node_modules/pi-lens/dist/clients/read-expansion.js +0 -266
- package/node_modules/pi-lens/dist/clients/read-guard-logger.js +0 -251
- package/node_modules/pi-lens/dist/clients/read-guard-tool-lines.js +0 -1306
- package/node_modules/pi-lens/dist/clients/read-guard.js +0 -1561
- package/node_modules/pi-lens/dist/clients/recent-touches.js +0 -240
- package/node_modules/pi-lens/dist/clients/redact/secrets.js +0 -449
- package/node_modules/pi-lens/dist/clients/resource-sampler.js +0 -628
- package/node_modules/pi-lens/dist/clients/reverse-deps.js +0 -270
- package/node_modules/pi-lens/dist/clients/review-graph/builder.js +0 -5126
- package/node_modules/pi-lens/dist/clients/review-graph/format.js +0 -33
- package/node_modules/pi-lens/dist/clients/review-graph/git-identity.js +0 -163
- package/node_modules/pi-lens/dist/clients/review-graph/import-resolvers.js +0 -481
- package/node_modules/pi-lens/dist/clients/review-graph/persist-worker.js +0 -10
- package/node_modules/pi-lens/dist/clients/review-graph/query.js +0 -244
- package/node_modules/pi-lens/dist/clients/review-graph/revision-drift.js +0 -21
- package/node_modules/pi-lens/dist/clients/review-graph/service.js +0 -96
- package/node_modules/pi-lens/dist/clients/review-graph/shared-extraction-ir.js +0 -82
- package/node_modules/pi-lens/dist/clients/review-graph/symbol-id.js +0 -103
- package/node_modules/pi-lens/dist/clients/review-graph/tsconfig-paths.js +0 -299
- package/node_modules/pi-lens/dist/clients/review-graph/types.js +0 -1
- package/node_modules/pi-lens/dist/clients/review-graph/workspace-modules.js +0 -449
- package/node_modules/pi-lens/dist/clients/review-graph-logger.js +0 -81
- package/node_modules/pi-lens/dist/clients/ruff-client.js +0 -179
- package/node_modules/pi-lens/dist/clients/rules-scanner.js +0 -131
- package/node_modules/pi-lens/dist/clients/run-duration.js +0 -55
- package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +0 -746
- package/node_modules/pi-lens/dist/clients/runtime-config.js +0 -77
- package/node_modules/pi-lens/dist/clients/runtime-context.js +0 -211
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +0 -1324
- package/node_modules/pi-lens/dist/clients/runtime-session.js +0 -2485
- package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +0 -1295
- package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +0 -2049
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +0 -3767
- package/node_modules/pi-lens/dist/clients/rust-client.js +0 -97
- package/node_modules/pi-lens/dist/clients/safe-spawn.js +0 -2357
- package/node_modules/pi-lens/dist/clients/sanitize.js +0 -286
- package/node_modules/pi-lens/dist/clients/scan-utils.js +0 -25
- package/node_modules/pi-lens/dist/clients/scratch-tree-policy.js +0 -165
- package/node_modules/pi-lens/dist/clients/search-read-registration.js +0 -94
- package/node_modules/pi-lens/dist/clients/secret-findings.js +0 -114
- package/node_modules/pi-lens/dist/clients/security-scan-client.js +0 -352
- package/node_modules/pi-lens/dist/clients/session-event-guard.js +0 -297
- package/node_modules/pi-lens/dist/clients/session-lifecycle.js +0 -484
- package/node_modules/pi-lens/dist/clients/session-start-observability.js +0 -94
- package/node_modules/pi-lens/dist/clients/session-state-store.js +0 -101
- package/node_modules/pi-lens/dist/clients/session-summary.js +0 -15
- package/node_modules/pi-lens/dist/clients/sessionstart-logger.js +0 -27
- package/node_modules/pi-lens/dist/clients/sg-runner.js +0 -876
- package/node_modules/pi-lens/dist/clients/sgconfig.js +0 -347
- package/node_modules/pi-lens/dist/clients/shared-checkout-guard.js +0 -338
- package/node_modules/pi-lens/dist/clients/single-flight.js +0 -158
- package/node_modules/pi-lens/dist/clients/situational-tool-telemetry.js +0 -108
- package/node_modules/pi-lens/dist/clients/skills-resolver.js +0 -141
- package/node_modules/pi-lens/dist/clients/slow-fs.js +0 -138
- package/node_modules/pi-lens/dist/clients/smells-rollup.js +0 -231
- package/node_modules/pi-lens/dist/clients/source-filter.js +0 -596
- package/node_modules/pi-lens/dist/clients/source-walker.js +0 -211
- package/node_modules/pi-lens/dist/clients/spawn-output-cap.js +0 -120
- package/node_modules/pi-lens/dist/clients/spawn-timeout-cooldown.js +0 -110
- package/node_modules/pi-lens/dist/clients/stale-marker.js +0 -17
- package/node_modules/pi-lens/dist/clients/startup-scan.js +0 -400
- package/node_modules/pi-lens/dist/clients/startup-timing.js +0 -130
- package/node_modules/pi-lens/dist/clients/string-utils.js +0 -33
- package/node_modules/pi-lens/dist/clients/subagent-mode.js +0 -111
- package/node_modules/pi-lens/dist/clients/symbol-containment.js +0 -24
- package/node_modules/pi-lens/dist/clients/symbol-types.js +0 -5
- package/node_modules/pi-lens/dist/clients/test-runner-client.js +0 -2507
- package/node_modules/pi-lens/dist/clients/test-runner-delivery.js +0 -287
- package/node_modules/pi-lens/dist/clients/todo-scanner.js +0 -229
- package/node_modules/pi-lens/dist/clients/tool-agreement.js +0 -423
- package/node_modules/pi-lens/dist/clients/tool-config.js +0 -249
- package/node_modules/pi-lens/dist/clients/tool-cwd.js +0 -270
- package/node_modules/pi-lens/dist/clients/tool-definition.js +0 -47
- package/node_modules/pi-lens/dist/clients/tool-event.js +0 -105
- package/node_modules/pi-lens/dist/clients/tool-policy.js +0 -2755
- package/node_modules/pi-lens/dist/clients/tool-probe.js +0 -53
- package/node_modules/pi-lens/dist/clients/tool-render.js +0 -156
- package/node_modules/pi-lens/dist/clients/tool-set-policy.js +0 -118
- package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +0 -364
- package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +0 -4195
- package/node_modules/pi-lens/dist/clients/tree-sitter-logger.js +0 -100
- package/node_modules/pi-lens/dist/clients/tree-sitter-navigator.js +0 -269
- package/node_modules/pi-lens/dist/clients/tree-sitter-query-loader.js +0 -569
- package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +0 -158
- package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +0 -1265
- package/node_modules/pi-lens/dist/clients/trivy-client.js +0 -467
- package/node_modules/pi-lens/dist/clients/tui-fit.js +0 -50
- package/node_modules/pi-lens/dist/clients/turn-context.js +0 -52
- package/node_modules/pi-lens/dist/clients/turn-end/lane.js +0 -51
- package/node_modules/pi-lens/dist/clients/turn-end/lanes/govulncheck.js +0 -112
- package/node_modules/pi-lens/dist/clients/turn-end/lanes/secrets.js +0 -204
- package/node_modules/pi-lens/dist/clients/turn-summary-render.js +0 -72
- package/node_modules/pi-lens/dist/clients/turn-summary.js +0 -132
- package/node_modules/pi-lens/dist/clients/typos-config.js +0 -29
- package/node_modules/pi-lens/dist/clients/user-notify.js +0 -51
- package/node_modules/pi-lens/dist/clients/vanished-instance-marker.js +0 -57
- package/node_modules/pi-lens/dist/clients/warm-attach.js +0 -305
- package/node_modules/pi-lens/dist/clients/widget-state.js +0 -1808
- package/node_modules/pi-lens/dist/clients/word-index-logger.js +0 -49
- package/node_modules/pi-lens/dist/clients/word-index-store.js +0 -459
- package/node_modules/pi-lens/dist/clients/word-index.js +0 -2080
- package/node_modules/pi-lens/dist/clients/workspace-topology.js +0 -443
- package/node_modules/pi-lens/dist/clients/write-ordering-guard.js +0 -65
- package/node_modules/pi-lens/dist/clients/zizmor-config.js +0 -340
- package/node_modules/pi-lens/dist/i18n.js +0 -69
- package/node_modules/pi-lens/dist/mcp/build-staleness.js +0 -124
- package/node_modules/pi-lens/dist/scripts/lib/process-scan.mjs +0 -583
- package/node_modules/pi-lens/dist/scripts/lib/skills-predicate.mjs +0 -129
- package/node_modules/pi-lens/dist/scripts/lib/web-tree-sitter-dir.mjs +0 -123
- package/node_modules/pi-lens/dist/tools/activate-tools.js +0 -87
- package/node_modules/pi-lens/dist/tools/ast-grep-outline.js +0 -137
- package/node_modules/pi-lens/dist/tools/ast-grep-replace.js +0 -244
- package/node_modules/pi-lens/dist/tools/ast-grep-search.js +0 -762
- package/node_modules/pi-lens/dist/tools/effective-config.js +0 -90
- package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +0 -375
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +0 -2571
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +0 -1745
- package/node_modules/pi-lens/dist/tools/lsp-navigation.js +0 -1367
- package/node_modules/pi-lens/dist/tools/lsp-structured-output.js +0 -294
- package/node_modules/pi-lens/dist/tools/module-report.js +0 -382
- package/node_modules/pi-lens/dist/tools/project-report.js +0 -86
- package/node_modules/pi-lens/dist/tools/render-compact.js +0 -374
- package/node_modules/pi-lens/dist/tools/scan-progress.js +0 -53
- package/node_modules/pi-lens/dist/tools/shared.js +0 -29
- package/node_modules/pi-lens/dist/tools/symbol-search.js +0 -155
|
@@ -1,1269 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Declarative Tool Dispatcher for pi-lens
|
|
3
|
-
*
|
|
4
|
-
* Redesigned to handle the full complexity of pi-lens's tool_result handler:
|
|
5
|
-
* - Multiple tools with different semantics (blocking, warning, silent)
|
|
6
|
-
* - Delta mode (baseline tracking)
|
|
7
|
-
* - Autofix handling
|
|
8
|
-
* - Output aggregation and formatting
|
|
9
|
-
*
|
|
10
|
-
* Key abstractions:
|
|
11
|
-
* - RunnerDefinition: A tool that can be run
|
|
12
|
-
* - Diagnostic: Structured issue representation
|
|
13
|
-
* - OutputSemantic: How to display (blocking, warning, silent, etc.)
|
|
14
|
-
* - BaselineStore: Track pre-existing issues for delta mode
|
|
15
|
-
*/
|
|
16
|
-
import { logExtension } from "../extension-log.js";
|
|
17
|
-
import * as fs from "node:fs";
|
|
18
|
-
import * as path from "node:path";
|
|
19
|
-
import { recordRunner } from "../widget-state.js";
|
|
20
|
-
import { incrementDegradationCount, recordDegradationOnce, } from "../degradation-ledger.js";
|
|
21
|
-
import { detectFileKind } from "../file-kinds.js";
|
|
22
|
-
import { detectFileRole } from "../file-role.js";
|
|
23
|
-
import { classifyGeneratedOrArtifactDetailed, } from "../generated-artifacts.js";
|
|
24
|
-
import { isTestFile } from "../file-utils.js";
|
|
25
|
-
import { getPrimaryDispatchGroup } from "../language-policy.js";
|
|
26
|
-
import { resolveLanguageRootForFile } from "../language-profile.js";
|
|
27
|
-
import { logLatency, phaseFinished, phaseStarted } from "../latency-logger.js";
|
|
28
|
-
import { isSpawnableCommand } from "../installer/index.js";
|
|
29
|
-
import { isAbsoluteFilePath, isWindowsPath, normalizeEphemeralMapKey, normalizeMapKey, } from "../path-utils.js";
|
|
30
|
-
import { loadPiLensProjectConfig } from "../project-lens-config.js";
|
|
31
|
-
import { RUNTIME_CONFIG, getRunnerTimeoutFloorMs } from "../runtime-config.js";
|
|
32
|
-
import { probeToolAsync } from "../tool-probe.js";
|
|
33
|
-
import { classifyDiagnostic } from "./diagnostic-taxonomy.js";
|
|
34
|
-
import { classifyProbeFailure, logAvailabilityDecision, startHostStallSampler, transientRetryDelayMs, } from "./runners/utils/availability-policy.js";
|
|
35
|
-
import { recordAvailabilityProbeOverrun, getDispatchAvailabilityGeneration, } from "./runners/utils/runner-helpers.js";
|
|
36
|
-
import { createAvailabilityProbeFlight } from "../availability-probe-flight.js";
|
|
37
|
-
import { applyDispositions } from "../diagnostic-dispositions.js";
|
|
38
|
-
import { applyInlineSuppressions } from "./inline-suppressions.js";
|
|
39
|
-
import { getToolPlan } from "./plan.js";
|
|
40
|
-
import { resolveRunnerPath } from "./runner-context.js";
|
|
41
|
-
import { classifyObservedRunner, COLLECT_LATER_THRESHOLD_MS, observeRunnerLatency, } from "./collect-later-tier.js";
|
|
42
|
-
import { deferRunnerFindings } from "./pending-runner-findings.js";
|
|
43
|
-
import { applyRulePolicy, rulePolicyMapFromConfig } from "./rule-policy.js";
|
|
44
|
-
import { getToolProfile } from "./tool-profile.js";
|
|
45
|
-
import { isRunnerSkipReason } from "./types.js";
|
|
46
|
-
const dispatcherProbeFlights = createAvailabilityProbeFlight({ generation: () => getDispatchAvailabilityGeneration() });
|
|
47
|
-
import { formatDiagnostics } from "./utils/format-utils.js";
|
|
48
|
-
// --- Runner Registry ---
|
|
49
|
-
export class RunnerRegistry {
|
|
50
|
-
runners = new Map();
|
|
51
|
-
register(runner) {
|
|
52
|
-
if (this.runners.has(runner.id))
|
|
53
|
-
return;
|
|
54
|
-
this.runners.set(runner.id, runner);
|
|
55
|
-
}
|
|
56
|
-
get(id) {
|
|
57
|
-
return this.runners.get(id);
|
|
58
|
-
}
|
|
59
|
-
getForKind(kind, filePath) {
|
|
60
|
-
const matching = [];
|
|
61
|
-
const isTest = filePath ? isTestFile(filePath) : false;
|
|
62
|
-
for (const runner of this.runners.values()) {
|
|
63
|
-
if (isTest && runner.skipTestFiles)
|
|
64
|
-
continue;
|
|
65
|
-
if (runnerAppliesToKind(runner, kind)) {
|
|
66
|
-
matching.push(runner);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
return matching.sort((a, b) => a.priority - b.priority);
|
|
70
|
-
}
|
|
71
|
-
list() {
|
|
72
|
-
return Array.from(this.runners.values());
|
|
73
|
-
}
|
|
74
|
-
clear() {
|
|
75
|
-
this.runners.clear();
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
function runnerAppliesToKind(runner, kind) {
|
|
79
|
-
return (runner.appliesTo.length === 0 ||
|
|
80
|
-
(kind !== undefined && runner.appliesTo.includes(kind)));
|
|
81
|
-
}
|
|
82
|
-
// --- Tool Availability Cache ---
|
|
83
|
-
/**
|
|
84
|
-
* Normalize a command name to a FactStore session key.
|
|
85
|
-
* Strips .cmd/.exe suffixes (case-insensitive) and lowercases,
|
|
86
|
-
* then prefixes with "session.toolCache.".
|
|
87
|
-
*/
|
|
88
|
-
export function normalizeCacheKey(cmd) {
|
|
89
|
-
const normalized = cmd.replace(/\.(cmd|exe)$/i, "").toLowerCase();
|
|
90
|
-
return `session.toolCache.${normalized}`;
|
|
91
|
-
}
|
|
92
|
-
/** Probe budget for the generic `hasTool` availability check, ms. */
|
|
93
|
-
const TOOL_PROBE_TIMEOUT_MS = 5000;
|
|
94
|
-
/**
|
|
95
|
-
* Session fact holding the epoch ms after which a TRANSIENT verdict for a
|
|
96
|
-
* command may be re-probed. Kept beside the boolean fact so both share the
|
|
97
|
-
* session's lifetime — no second global to reset (#1476).
|
|
98
|
-
*/
|
|
99
|
-
function transientRetryKey(command) {
|
|
100
|
-
return `${normalizeCacheKey(command)}.retryAt`;
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* Consecutive transient verdicts for a command, so the cooldown ESCALATES the
|
|
104
|
-
* way the policy documents (30 s, 60 s, 120 s … capped at 5 min) instead of
|
|
105
|
-
* sitting flat at 30 s.
|
|
106
|
-
*
|
|
107
|
-
* This is the highest-traffic availability consumer in the product. A flat
|
|
108
|
-
* cooldown here means a permanently sick host is re-probed every 30 s per
|
|
109
|
-
* command for the whole session — ten times the storm the policy claims to
|
|
110
|
-
* bound, and the one place the bound matters most. `createAvailabilityChecker`
|
|
111
|
-
* tracks the same counter; this keeps the two seams telling one story.
|
|
112
|
-
*/
|
|
113
|
-
function transientAttemptsKey(command) {
|
|
114
|
-
return `${normalizeCacheKey(command)}.transientAttempts`;
|
|
115
|
-
}
|
|
116
|
-
/**
|
|
117
|
-
* Is `command` usable right now? Cached per session.
|
|
118
|
-
*
|
|
119
|
-
* Latch policy (#1467/#1476): a `false` from a genuine absence is durable and
|
|
120
|
-
* is remembered for the session. A `false` from a TIMED-OUT probe is not — this
|
|
121
|
-
* is the highest-traffic availability consumer in the codebase, and caching a
|
|
122
|
-
* host stall here silently disabled a healthy tool for every later dispatch in
|
|
123
|
-
* the session. A transient verdict instead holds only for a bounded cooldown,
|
|
124
|
-
* which also stops a sick host from being re-probed on every dispatch.
|
|
125
|
-
*/
|
|
126
|
-
export async function checkToolAvailability(command, facts) {
|
|
127
|
-
const key = normalizeCacheKey(command);
|
|
128
|
-
const cached = facts.getSessionFact(key);
|
|
129
|
-
if (cached !== undefined) {
|
|
130
|
-
return cached;
|
|
131
|
-
}
|
|
132
|
-
const retryAt = facts.getSessionFact(transientRetryKey(command));
|
|
133
|
-
if (retryAt !== undefined && Date.now() < retryAt)
|
|
134
|
-
return false;
|
|
135
|
-
// A command that isn't even on disk can't pass a --version probe; the ~μs
|
|
136
|
-
// stat/PATH walk saves a guaranteed-to-fail spawn round-trip per cold tool.
|
|
137
|
-
if (!(await isSpawnableCommand(command))) {
|
|
138
|
-
facts.setSessionFact(key, false);
|
|
139
|
-
return false;
|
|
140
|
-
}
|
|
141
|
-
try {
|
|
142
|
-
// The budget is enforced by a HOST-side timer, so measure the loop stall
|
|
143
|
-
// that overlapped the window and let the shared classifier read it.
|
|
144
|
-
const sampler = startHostStallSampler();
|
|
145
|
-
const startedAt = Date.now();
|
|
146
|
-
let result;
|
|
147
|
-
let hostStallMs;
|
|
148
|
-
let probeJoined = false;
|
|
149
|
-
try {
|
|
150
|
-
const shared = dispatcherProbeFlights.run(`dispatcher:${key}`, () => probeToolAsync(command, ["--version"], {
|
|
151
|
-
timeout: TOOL_PROBE_TIMEOUT_MS,
|
|
152
|
-
}));
|
|
153
|
-
probeJoined = shared.joined;
|
|
154
|
-
result = await shared.promise;
|
|
155
|
-
}
|
|
156
|
-
finally {
|
|
157
|
-
hostStallMs = sampler.stop();
|
|
158
|
-
}
|
|
159
|
-
const elapsedMs = Date.now() - startedAt;
|
|
160
|
-
recordAvailabilityProbeOverrun(command, key, elapsedMs, TOOL_PROBE_TIMEOUT_MS, result.failure);
|
|
161
|
-
if (result.status === 0) {
|
|
162
|
-
facts.setSessionFact(key, true);
|
|
163
|
-
// The tool answered: retire the cooldown facts rather than leaving a
|
|
164
|
-
// stale retry deadline behind a `true`.
|
|
165
|
-
facts.setSessionFact(transientRetryKey(command), 0);
|
|
166
|
-
facts.setSessionFact(transientAttemptsKey(command), 0);
|
|
167
|
-
logAvailabilityDecision({
|
|
168
|
-
tool: command,
|
|
169
|
-
verdict: "available",
|
|
170
|
-
outcome: "success",
|
|
171
|
-
cause: "ok",
|
|
172
|
-
elapsedMs,
|
|
173
|
-
latched: true,
|
|
174
|
-
classifiedBy: probeJoined ? "joined" : "probe",
|
|
175
|
-
hostStallMs,
|
|
176
|
-
budgetMs: TOOL_PROBE_TIMEOUT_MS,
|
|
177
|
-
});
|
|
178
|
-
return true;
|
|
179
|
-
}
|
|
180
|
-
// `missing` for anything unclassified preserves the pre-#1476 meaning of
|
|
181
|
-
// a non-zero exit: durable, cached for the session.
|
|
182
|
-
const { outcome, cause, evidence } = classifyProbeFailure(result, {
|
|
183
|
-
hostStallMs,
|
|
184
|
-
unclassifiedFailureOutcome: "missing",
|
|
185
|
-
});
|
|
186
|
-
let retryAfterMs;
|
|
187
|
-
if (outcome === "transient") {
|
|
188
|
-
const attempts = (facts.getSessionFact(transientAttemptsKey(command)) ?? 0) + 1;
|
|
189
|
-
facts.setSessionFact(transientAttemptsKey(command), attempts);
|
|
190
|
-
retryAfterMs = transientRetryDelayMs(attempts, cause);
|
|
191
|
-
facts.setSessionFact(transientRetryKey(command), Date.now() + retryAfterMs);
|
|
192
|
-
}
|
|
193
|
-
else {
|
|
194
|
-
facts.setSessionFact(key, false);
|
|
195
|
-
facts.setSessionFact(transientAttemptsKey(command), 0);
|
|
196
|
-
}
|
|
197
|
-
logAvailabilityDecision({
|
|
198
|
-
tool: command,
|
|
199
|
-
verdict: "unavailable",
|
|
200
|
-
outcome,
|
|
201
|
-
cause,
|
|
202
|
-
elapsedMs,
|
|
203
|
-
latched: outcome !== "transient",
|
|
204
|
-
hostStallMs,
|
|
205
|
-
...(retryAfterMs !== undefined && { retryAfterMs }),
|
|
206
|
-
budgetMs: TOOL_PROBE_TIMEOUT_MS,
|
|
207
|
-
classifiedBy: probeJoined ? "joined" : "probe",
|
|
208
|
-
evidence,
|
|
209
|
-
});
|
|
210
|
-
return false;
|
|
211
|
-
}
|
|
212
|
-
catch {
|
|
213
|
-
facts.setSessionFact(key, false);
|
|
214
|
-
return false;
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
// --- Dispatch Context Factory ---
|
|
218
|
-
function readFilePrefix(filePath, maxBytes = 4096) {
|
|
219
|
-
let fd;
|
|
220
|
-
try {
|
|
221
|
-
fd = fs.openSync(filePath, "r");
|
|
222
|
-
const buffer = Buffer.alloc(maxBytes);
|
|
223
|
-
const bytesRead = fs.readSync(fd, buffer, 0, maxBytes, 0);
|
|
224
|
-
return buffer.subarray(0, bytesRead).toString("utf8");
|
|
225
|
-
}
|
|
226
|
-
catch {
|
|
227
|
-
return undefined;
|
|
228
|
-
}
|
|
229
|
-
finally {
|
|
230
|
-
if (fd !== undefined) {
|
|
231
|
-
try {
|
|
232
|
-
fs.closeSync(fd);
|
|
233
|
-
}
|
|
234
|
-
catch {
|
|
235
|
-
// ignore close errors
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
export function createDispatchContext(filePath, cwd, pi, facts, blockingOnly, modifiedRanges,
|
|
241
|
-
/** Authoritative workspace root; `cwd` may be a nested language root. */
|
|
242
|
-
projectRoot,
|
|
243
|
-
/** Ordered per-file pipeline token, when this is a post-write dispatch. */
|
|
244
|
-
writeIndex,
|
|
245
|
-
/** Runtime telemetry identity, when known (#1448) — threaded to the
|
|
246
|
-
* worklog append; see DispatchContext.telemetryModel's doc. */
|
|
247
|
-
telemetryModel, telemetryProvider) {
|
|
248
|
-
const absoluteFilePath = resolveRunnerPath(cwd, filePath);
|
|
249
|
-
const normalizedProjectRoot = normalizeMapKey(path.resolve(projectRoot ?? cwd));
|
|
250
|
-
const normalizedCwd = normalizeMapKey(resolveLanguageRootForFile(absoluteFilePath, cwd));
|
|
251
|
-
const normalizedFilePath = normalizeMapKey(absoluteFilePath);
|
|
252
|
-
// `resolveRunnerPath` intentionally normalizes map keys, which folds a
|
|
253
|
-
// literal POSIX backslash into a separator. Preserve that one proven
|
|
254
|
-
// classifier distinction while still resolving relative inputs from `cwd`.
|
|
255
|
-
const kindFilePath = !isWindowsPath(filePath) && filePath.includes("\\")
|
|
256
|
-
? path.resolve(cwd, filePath)
|
|
257
|
-
: absoluteFilePath;
|
|
258
|
-
const kind = detectFileKind(kindFilePath);
|
|
259
|
-
const contentPrefix = readFilePrefix(normalizedFilePath);
|
|
260
|
-
const fileRole = detectFileRole(normalizedFilePath, contentPrefix);
|
|
261
|
-
// Captured once here so the generated short-circuit below can emit a
|
|
262
|
-
// `dispatch_skipped_generated` record carrying the deciding evidence tier
|
|
263
|
-
// and the measured line-shape statistic — without re-reading the file
|
|
264
|
-
// (refs #2346). The content passed is the same 4096-byte prefix already
|
|
265
|
-
// read for role detection, so this classification costs no extra I/O.
|
|
266
|
-
const generatedDetail = fileRole === "generated"
|
|
267
|
-
? classifyGeneratedOrArtifactDetailed(normalizedFilePath, {
|
|
268
|
-
content: contentPrefix,
|
|
269
|
-
includeDeclarations: false,
|
|
270
|
-
})
|
|
271
|
-
: undefined;
|
|
272
|
-
const projectConfig = loadPiLensProjectConfig(normalizedCwd);
|
|
273
|
-
return {
|
|
274
|
-
filePath: normalizedFilePath,
|
|
275
|
-
projectRoot: normalizedProjectRoot,
|
|
276
|
-
cwd: normalizedCwd,
|
|
277
|
-
kind,
|
|
278
|
-
fileRole,
|
|
279
|
-
generatedEvidence: generatedDetail?.evidence,
|
|
280
|
-
generatedLineShapeMean: generatedDetail?.lineShapeMean,
|
|
281
|
-
pi,
|
|
282
|
-
autofix: false,
|
|
283
|
-
deltaMode: !pi.getFlag("no-delta"),
|
|
284
|
-
facts,
|
|
285
|
-
projectConfig,
|
|
286
|
-
blockingOnly,
|
|
287
|
-
modifiedRanges,
|
|
288
|
-
writeIndex,
|
|
289
|
-
telemetryModel,
|
|
290
|
-
telemetryProvider,
|
|
291
|
-
toolCwdMemo: {},
|
|
292
|
-
async hasTool(command) {
|
|
293
|
-
return checkToolAvailability(command, facts);
|
|
294
|
-
},
|
|
295
|
-
log(message, level) {
|
|
296
|
-
// #1333: pi owns the terminal — a runner advisory must never be a raw
|
|
297
|
-
// write. Every DispatchContext.log line lands in extension.log instead.
|
|
298
|
-
logExtension({
|
|
299
|
-
subsystem: "dispatch",
|
|
300
|
-
// exactOptionalPropertyTypes: an omitted level must stay omitted.
|
|
301
|
-
...(level !== undefined && { level }),
|
|
302
|
-
message,
|
|
303
|
-
metadata: { filePath: normalizedFilePath, kind },
|
|
304
|
-
});
|
|
305
|
-
},
|
|
306
|
-
};
|
|
307
|
-
}
|
|
308
|
-
// --- Delta Mode Logic ---
|
|
309
|
-
/**
|
|
310
|
-
* Filter diagnostics to only show NEW issues (delta mode)
|
|
311
|
-
*/
|
|
312
|
-
function filterDelta(after, before, keyFn) {
|
|
313
|
-
const beforeSet = new Set((before ?? []).map(keyFn));
|
|
314
|
-
const afterSet = new Set(after.map(keyFn));
|
|
315
|
-
const fixed = (before ?? []).filter((d) => !afterSet.has(keyFn(d)));
|
|
316
|
-
const newItems = after.filter((d) => !beforeSet.has(keyFn(d)));
|
|
317
|
-
return { new: newItems, fixed };
|
|
318
|
-
}
|
|
319
|
-
function semanticRank(semantic) {
|
|
320
|
-
if (semantic === "blocking")
|
|
321
|
-
return 4;
|
|
322
|
-
if (semantic === "warning")
|
|
323
|
-
return 3;
|
|
324
|
-
if (semantic === "fixed")
|
|
325
|
-
return 2;
|
|
326
|
-
if (semantic === "silent")
|
|
327
|
-
return 1;
|
|
328
|
-
return 0;
|
|
329
|
-
}
|
|
330
|
-
function toolPriority(tool, defectClass) {
|
|
331
|
-
return getToolProfile(tool, defectClass).dedupPriority;
|
|
332
|
-
}
|
|
333
|
-
function dedupeOverlappingDiagnostics(diagnostics) {
|
|
334
|
-
const byKey = new Map();
|
|
335
|
-
for (const d of diagnostics) {
|
|
336
|
-
const defectClass = d.defectClass ?? classifyDiagnostic(d);
|
|
337
|
-
const line = d.line ?? 1;
|
|
338
|
-
const column = d.column ?? 1;
|
|
339
|
-
const ruleKey = d.rule || d.id || "unknown";
|
|
340
|
-
const key = `${d.filePath}:${line}:${column}:${defectClass}:${ruleKey}`;
|
|
341
|
-
const current = byKey.get(key);
|
|
342
|
-
if (!current) {
|
|
343
|
-
byKey.set(key, { ...d, defectClass });
|
|
344
|
-
continue;
|
|
345
|
-
}
|
|
346
|
-
const currScore = semanticRank(current.semantic) * 100 +
|
|
347
|
-
toolPriority(current.tool, defectClass);
|
|
348
|
-
const nextScore = semanticRank(d.semantic) * 100 + toolPriority(d.tool, defectClass);
|
|
349
|
-
if (nextScore > currScore) {
|
|
350
|
-
byKey.set(key, { ...d, defectClass });
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
return [...byKey.values()];
|
|
354
|
-
}
|
|
355
|
-
function suppressLintOverlapsWithLsp(diagnostics) {
|
|
356
|
-
const lspBySpanClass = new Set();
|
|
357
|
-
const lspByLine = new Set();
|
|
358
|
-
const isLintTool = (tool) => {
|
|
359
|
-
return getToolProfile(tool).lintLike;
|
|
360
|
-
};
|
|
361
|
-
for (const d of diagnostics) {
|
|
362
|
-
if (d.tool !== "lsp")
|
|
363
|
-
continue;
|
|
364
|
-
const line = d.line ?? 1;
|
|
365
|
-
const defectClass = d.defectClass ?? classifyDiagnostic(d);
|
|
366
|
-
lspBySpanClass.add(`${d.filePath}:${line}:${defectClass}`);
|
|
367
|
-
lspByLine.add(`${d.filePath}:${line}`);
|
|
368
|
-
}
|
|
369
|
-
if (lspByLine.size === 0)
|
|
370
|
-
return diagnostics;
|
|
371
|
-
return diagnostics.filter((d) => {
|
|
372
|
-
if (d.tool === "lsp")
|
|
373
|
-
return true;
|
|
374
|
-
if (!isLintTool(d.tool))
|
|
375
|
-
return true;
|
|
376
|
-
if (d.semantic === "blocking" || d.severity === "error")
|
|
377
|
-
return true;
|
|
378
|
-
const line = d.line ?? 1;
|
|
379
|
-
const defectClass = d.defectClass ?? classifyDiagnostic(d);
|
|
380
|
-
const key = `${d.filePath}:${line}:${defectClass}`;
|
|
381
|
-
if (lspBySpanClass.has(key))
|
|
382
|
-
return false;
|
|
383
|
-
// Conservative fallback for unclassified overlap at same line.
|
|
384
|
-
if (defectClass === "unknown") {
|
|
385
|
-
return !lspByLine.has(`${d.filePath}:${line}`);
|
|
386
|
-
}
|
|
387
|
-
return true;
|
|
388
|
-
});
|
|
389
|
-
}
|
|
390
|
-
/**
|
|
391
|
-
* Dockerfile overlap dedup (#131 Mode 2): hadolint and `trivy config` both flag
|
|
392
|
-
* a few of the same Dockerfile issues (e.g. `:latest`, running as root) with
|
|
393
|
-
* different rule ids, which the rule-keyed `dedupeOverlappingDiagnostics` can't
|
|
394
|
-
* collapse. Keep hadolint authoritative on the lines it covers and drop the
|
|
395
|
-
* trivy-config finding there — trivy still contributes the security checks
|
|
396
|
-
* hadolint lacks (on other lines), and all Kubernetes findings (no hadolint
|
|
397
|
-
* diagnostics exist for YAML, so none are suppressed). Exported for unit tests.
|
|
398
|
-
*/
|
|
399
|
-
export function suppressTrivyConfigDockerOverlap(diagnostics) {
|
|
400
|
-
const hadolintLines = new Set();
|
|
401
|
-
for (const d of diagnostics) {
|
|
402
|
-
if (d.tool === "hadolint") {
|
|
403
|
-
hadolintLines.add(`${d.filePath}:${d.line ?? 1}`);
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
if (hadolintLines.size === 0)
|
|
407
|
-
return diagnostics;
|
|
408
|
-
return diagnostics.filter((d) => d.tool !== "trivy-config" ||
|
|
409
|
-
!hadolintLines.has(`${d.filePath}:${d.line ?? 1}`));
|
|
410
|
-
}
|
|
411
|
-
function isUnusedValueDiagnostic(d) {
|
|
412
|
-
const raw = `${d.id ?? ""} ${d.rule ?? ""} ${d.message ?? ""}`.toLowerCase();
|
|
413
|
-
if (raw.includes("no-unused"))
|
|
414
|
-
return true;
|
|
415
|
-
if (/\b(6133|6192|6196)\b/.test(raw))
|
|
416
|
-
return true;
|
|
417
|
-
const rule = String(d.rule ?? "").toLowerCase();
|
|
418
|
-
if (rule.includes("unused"))
|
|
419
|
-
return true;
|
|
420
|
-
const message = d.message.toLowerCase();
|
|
421
|
-
return (message.includes("is declared but its value is never read") ||
|
|
422
|
-
message.includes("is assigned a value but never used") ||
|
|
423
|
-
message.includes("declared but never used") ||
|
|
424
|
-
message.includes("unused"));
|
|
425
|
-
}
|
|
426
|
-
function promoteDeltaUnusedToBlockers(diagnostics) {
|
|
427
|
-
return diagnostics.map((d) => {
|
|
428
|
-
if (!isUnusedValueDiagnostic(d))
|
|
429
|
-
return d;
|
|
430
|
-
if (d.semantic === "blocking" || d.severity === "error")
|
|
431
|
-
return d;
|
|
432
|
-
return {
|
|
433
|
-
...d,
|
|
434
|
-
severity: "error",
|
|
435
|
-
semantic: "blocking",
|
|
436
|
-
fixSuggestion: d.fixSuggestion ??
|
|
437
|
-
"Remove the unused declaration or rename with '_' prefix if intentionally unused.",
|
|
438
|
-
};
|
|
439
|
-
});
|
|
440
|
-
}
|
|
441
|
-
function buildCoverageNotice(ctx, runnerLatencies) {
|
|
442
|
-
if (!ctx.kind)
|
|
443
|
-
return undefined;
|
|
444
|
-
const lspEnabled = !ctx.pi.getFlag("no-lsp");
|
|
445
|
-
const primary = getPrimaryDispatchGroup(ctx.kind, lspEnabled);
|
|
446
|
-
if (!primary || primary.runnerIds.length === 0)
|
|
447
|
-
return undefined;
|
|
448
|
-
const relevant = runnerLatencies.filter((r) => primary.runnerIds.includes(r.runnerId));
|
|
449
|
-
if (relevant.length === 0)
|
|
450
|
-
return undefined;
|
|
451
|
-
// #1867 catalog shape 4: this is correlation, not classification. The LSP
|
|
452
|
-
// touch already decided which scanner publications were absent for these
|
|
453
|
-
// bytes; the runner and latency assembly only preserve that exact set.
|
|
454
|
-
const unconfirmedServerIds = [
|
|
455
|
-
...new Set(relevant.flatMap((r) => r.unconfirmedServerIds ?? [])),
|
|
456
|
-
];
|
|
457
|
-
if (unconfirmedServerIds.length > 0) {
|
|
458
|
-
const deferredIds = new Set(relevant.flatMap((r) => r.deferredServerIds ?? []));
|
|
459
|
-
const markerFor = (ids) => {
|
|
460
|
-
const shown = ids.slice(0, 4);
|
|
461
|
-
const remainder = ids.length - shown.length;
|
|
462
|
-
return `${shown.join(", ")}${remainder > 0 ? ` +${remainder}` : ""}`;
|
|
463
|
-
};
|
|
464
|
-
const deferredServerIds = unconfirmedServerIds.filter((id) => deferredIds.has(id));
|
|
465
|
-
const silentServerIds = unconfirmedServerIds.filter((id) => !deferredIds.has(id));
|
|
466
|
-
// The marker describes this exact scanner set. A scanner can recover
|
|
467
|
-
// while another goes dark on the same file, so the set belongs in the
|
|
468
|
-
// session dedupe identity rather than only kind and path.
|
|
469
|
-
// #2016: these are SCANNER IDS, not filesystem paths. `normalizeMapKey`
|
|
470
|
-
// would realpath each one; on Windows that fails, falls through to
|
|
471
|
-
// `resolveNonExisting`, and resolves the id against the CURRENT process
|
|
472
|
-
// cwd, so the dedupe key differed by platform and by cwd (the #2219
|
|
473
|
-
// non-path-sentinel class). The cheap syntactic fold is what this
|
|
474
|
-
// session-scoped dedupe key actually needs. Code-unit comparator: the
|
|
475
|
-
// sorted set is a KEY, so ordering must be deterministic across locales
|
|
476
|
-
// — localeCompare is not.
|
|
477
|
-
const dedupeSet = (ids) => [...new Set(ids)]
|
|
478
|
-
.map(normalizeEphemeralMapKey)
|
|
479
|
-
.sort((a, b) => Number(a > b) - Number(a < b))
|
|
480
|
-
.join(",");
|
|
481
|
-
// #2810 round 4: the PARTITION is part of the identity, not just the
|
|
482
|
-
// scanner set. The same scanner can be silent on one edit and marked for
|
|
483
|
-
// late delivery on the next; keying on the unconfirmed set alone showed
|
|
484
|
-
// the session whichever message came first and suppressed the other, so a
|
|
485
|
-
// scanner that recovered a delivery path (or lost one) kept the stale
|
|
486
|
-
// wording for the rest of the session.
|
|
487
|
-
const onceKey = `${ctx.kind}:${ctx.filePath}:${dedupeSet(silentServerIds)}|${dedupeSet(deferredServerIds)}`;
|
|
488
|
-
if (coverageNoticeSeen.has(onceKey))
|
|
489
|
-
return undefined;
|
|
490
|
-
coverageNoticeSeen.add(onceKey);
|
|
491
|
-
const coverageParts = [];
|
|
492
|
-
if (deferredServerIds.length > 0) {
|
|
493
|
-
coverageParts.push(`coverage: ${markerFor(deferredServerIds)} deferred — diagnostics are incomplete; findings arrive at turn end if the scan lands.`);
|
|
494
|
-
}
|
|
495
|
-
if (silentServerIds.length > 0) {
|
|
496
|
-
coverageParts.push(`coverage: ${markerFor(silentServerIds)} silent — diagnostics are incomplete (not a clean result).`);
|
|
497
|
-
}
|
|
498
|
-
return {
|
|
499
|
-
id: `coverage-partial:${ctx.kind}:${path.basename(ctx.filePath)}`,
|
|
500
|
-
message: coverageParts.join("\n"),
|
|
501
|
-
filePath: ctx.filePath,
|
|
502
|
-
severity: "warning",
|
|
503
|
-
semantic: "warning",
|
|
504
|
-
tool: "pi-lens",
|
|
505
|
-
};
|
|
506
|
-
}
|
|
507
|
-
// Check primary runners first
|
|
508
|
-
const primaryHasCoverage = relevant.some((r) => r.status === "succeeded" || r.status === "failed");
|
|
509
|
-
if (primaryHasCoverage)
|
|
510
|
-
return undefined;
|
|
511
|
-
const allPrimarySkipped = relevant.every((r) => r.status === "skipped" ||
|
|
512
|
-
r.status === "when_skipped" ||
|
|
513
|
-
r.status === "test_file_skipped");
|
|
514
|
-
if (!allPrimarySkipped)
|
|
515
|
-
return undefined;
|
|
516
|
-
const plan = getToolPlan(ctx.kind);
|
|
517
|
-
const fallbackRunnerIds = new Set((plan?.groups ?? [])
|
|
518
|
-
.filter((group) => !group.runnerIds.every((runnerId) => primary.runnerIds.includes(runnerId)))
|
|
519
|
-
.flatMap((group) => group.runnerIds)
|
|
520
|
-
.filter((runnerId) => !primary.runnerIds.includes(runnerId)));
|
|
521
|
-
// Structural-only runners (tree-sitter, ast-grep) are not substitutes
|
|
522
|
-
// for real linters — don't suppress the notice if only they ran.
|
|
523
|
-
const STRUCTURAL_RUNNERS = new Set([
|
|
524
|
-
"tree-sitter",
|
|
525
|
-
"ast-grep-napi",
|
|
526
|
-
"spellcheck",
|
|
527
|
-
"fact-rules",
|
|
528
|
-
"opengrep",
|
|
529
|
-
]);
|
|
530
|
-
const anyLinterHasCoverage = runnerLatencies.some((r) => fallbackRunnerIds.has(r.runnerId) &&
|
|
531
|
-
!STRUCTURAL_RUNNERS.has(r.runnerId) &&
|
|
532
|
-
(r.status === "succeeded" || r.status === "failed"));
|
|
533
|
-
if (anyLinterHasCoverage)
|
|
534
|
-
return undefined;
|
|
535
|
-
const onceKey = `${ctx.kind}:${ctx.filePath}`;
|
|
536
|
-
if (coverageNoticeSeen.has(onceKey))
|
|
537
|
-
return undefined;
|
|
538
|
-
coverageNoticeSeen.add(onceKey);
|
|
539
|
-
return {
|
|
540
|
-
id: `coverage-unavailable:${ctx.kind}:${path.basename(ctx.filePath)}`,
|
|
541
|
-
message: `Pi-lens ${ctx.kind} analysis unavailable — language tools are missing or the LSP server isn't ready yet, so this file was not fully checked (not a clean result).`,
|
|
542
|
-
filePath: ctx.filePath,
|
|
543
|
-
severity: "warning",
|
|
544
|
-
semantic: "warning",
|
|
545
|
-
tool: "pi-lens",
|
|
546
|
-
};
|
|
547
|
-
}
|
|
548
|
-
const latencyReports = [];
|
|
549
|
-
const coverageNoticeSeen = new Set();
|
|
550
|
-
// One `dispatch_skipped_generated` phase record per file per process (refs
|
|
551
|
-
// #2346): a generated file dispatched repeatedly must not spam latency.log,
|
|
552
|
-
// so only the first skip of each file emits the row; the degradation ledger
|
|
553
|
-
// below still tallies every repetition with a bounded per-subject count.
|
|
554
|
-
const generatedSkipRecorded = new Set();
|
|
555
|
-
export function getLatencyReports() {
|
|
556
|
-
return [...latencyReports];
|
|
557
|
-
}
|
|
558
|
-
export function clearLatencyReports() {
|
|
559
|
-
latencyReports.length = 0;
|
|
560
|
-
}
|
|
561
|
-
export function clearCoverageNoticeState() {
|
|
562
|
-
coverageNoticeSeen.clear();
|
|
563
|
-
generatedSkipRecorded.clear();
|
|
564
|
-
}
|
|
565
|
-
export function formatLatencyReport(report) {
|
|
566
|
-
const lines = [];
|
|
567
|
-
lines.push(`\n═══════════════════════════════════════════════════════════════`);
|
|
568
|
-
lines.push(`📊 DISPATCH LATENCY REPORT: ${report.filePath.split("/").pop()}`);
|
|
569
|
-
lines.push(` Kind: ${report.fileKind || "unknown"} | Total: ${report.totalDurationMs}ms`);
|
|
570
|
-
lines.push(`───────────────────────────────────────────────────────────────`);
|
|
571
|
-
lines.push(`Runner Duration Status Issues Semantic`);
|
|
572
|
-
lines.push(`───────────────────────────────────────────────────────────────`);
|
|
573
|
-
for (const r of report.runners) {
|
|
574
|
-
const name = r.runnerId.padEnd(30);
|
|
575
|
-
const dur = `${r.durationMs}ms`.padStart(8);
|
|
576
|
-
const status = r.status.padStart(9);
|
|
577
|
-
const issues = String(r.diagnosticCount).padStart(6);
|
|
578
|
-
const sem = r.semantic.padStart(8);
|
|
579
|
-
const slowMarker = r.durationMs > 500 ? " 🔥" : r.durationMs > 100 ? " ⚡" : "";
|
|
580
|
-
lines.push(`${name}${dur}${status}${issues}${sem}${slowMarker}`);
|
|
581
|
-
}
|
|
582
|
-
lines.push(`───────────────────────────────────────────────────────────────`);
|
|
583
|
-
lines.push(`Total: ${report.runners.length} runners | Stopped early: ${report.stoppedEarly}`);
|
|
584
|
-
lines.push(`Diagnostics: ${report.totalDiagnostics} (${report.blockers} blockers, ${report.warnings} warnings)`);
|
|
585
|
-
// Show top 3 slowest
|
|
586
|
-
const sorted = [...report.runners].sort((a, b) => b.durationMs - a.durationMs);
|
|
587
|
-
if (sorted.length > 0 && sorted[0].durationMs > 100) {
|
|
588
|
-
lines.push(`\n🐌 Slowest runners:`);
|
|
589
|
-
for (const r of sorted.slice(0, 3)) {
|
|
590
|
-
if (r.durationMs > 50) {
|
|
591
|
-
lines.push(` ${r.runnerId}: ${r.durationMs}ms (${r.status})`);
|
|
592
|
-
}
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
lines.push(`═══════════════════════════════════════════════════════════════`);
|
|
596
|
-
return lines.join("\n");
|
|
597
|
-
}
|
|
598
|
-
/**
|
|
599
|
-
* Execute all runners in a single group.
|
|
600
|
-
*
|
|
601
|
-
* - mode "fallback": run runners sequentially and stop at the first
|
|
602
|
-
* one that succeeds (returns status !== "skipped").
|
|
603
|
-
* - mode "all" (default): run all runners in the group sequentially
|
|
604
|
-
* and collect every diagnostic.
|
|
605
|
-
*
|
|
606
|
-
* Groups themselves are run in parallel by dispatchForFile, so this
|
|
607
|
-
* function must NOT mutate shared state.
|
|
608
|
-
*/
|
|
609
|
-
async function runGroup(ctx, group, registry, onRunnerResult) {
|
|
610
|
-
const diagnostics = [];
|
|
611
|
-
const latencies = [];
|
|
612
|
-
let hadBlocker = false;
|
|
613
|
-
// Filter runners by kind if specified
|
|
614
|
-
const runnerIds = group.filterKinds
|
|
615
|
-
? group.runnerIds.filter((id) => {
|
|
616
|
-
const runner = registry.get(id);
|
|
617
|
-
return runner && ctx.kind && group.filterKinds?.includes(ctx.kind);
|
|
618
|
-
})
|
|
619
|
-
: group.runnerIds;
|
|
620
|
-
const semantic = group.semantic ?? "warning";
|
|
621
|
-
for (const runnerId of runnerIds) {
|
|
622
|
-
const runnerStart = Date.now();
|
|
623
|
-
const runner = registry.get(runnerId);
|
|
624
|
-
if (!runner) {
|
|
625
|
-
latencies.push({
|
|
626
|
-
runnerId,
|
|
627
|
-
startTime: runnerStart,
|
|
628
|
-
endTime: Date.now(),
|
|
629
|
-
durationMs: 0,
|
|
630
|
-
status: "skipped",
|
|
631
|
-
diagnosticCount: 0,
|
|
632
|
-
semantic: "unknown",
|
|
633
|
-
});
|
|
634
|
-
logLatency({
|
|
635
|
-
type: "runner",
|
|
636
|
-
filePath: ctx.filePath,
|
|
637
|
-
runnerId,
|
|
638
|
-
durationMs: 0,
|
|
639
|
-
status: "not_registered",
|
|
640
|
-
diagnosticCount: 0,
|
|
641
|
-
semantic: "unknown",
|
|
642
|
-
});
|
|
643
|
-
continue;
|
|
644
|
-
}
|
|
645
|
-
// Same skipTestFiles gate RunnerRegistry.getForKind applies for the
|
|
646
|
-
// per-edit path (#2337): the plan/group path resolves runners by id via
|
|
647
|
-
// registry.get() instead, which bypasses getForKind entirely, so a
|
|
648
|
-
// runner declaring skipTestFiles never had it enforced here.
|
|
649
|
-
if (runner.skipTestFiles && isTestFile(ctx.filePath)) {
|
|
650
|
-
latencies.push({
|
|
651
|
-
runnerId,
|
|
652
|
-
startTime: runnerStart,
|
|
653
|
-
endTime: Date.now(),
|
|
654
|
-
durationMs: Date.now() - runnerStart,
|
|
655
|
-
status: "test_file_skipped",
|
|
656
|
-
diagnosticCount: 0,
|
|
657
|
-
semantic: "none",
|
|
658
|
-
});
|
|
659
|
-
logLatency({
|
|
660
|
-
type: "runner",
|
|
661
|
-
filePath: ctx.filePath,
|
|
662
|
-
runnerId,
|
|
663
|
-
durationMs: 0,
|
|
664
|
-
status: "test_file_skipped",
|
|
665
|
-
diagnosticCount: 0,
|
|
666
|
-
semantic: "none",
|
|
667
|
-
});
|
|
668
|
-
continue;
|
|
669
|
-
}
|
|
670
|
-
// Keep explicit groups aligned with RunnerRegistry.getForKind(): an empty
|
|
671
|
-
// appliesTo list means every kind, while a populated list must contain the
|
|
672
|
-
// current kind. A filtered runner remains visible as skipped telemetry so
|
|
673
|
-
// language mismatches cannot be mistaken for runner failures.
|
|
674
|
-
const appliesToCurrentKind = runnerAppliesToKind(runner, ctx.kind);
|
|
675
|
-
if (!appliesToCurrentKind) {
|
|
676
|
-
const runnerEnd = Date.now();
|
|
677
|
-
latencies.push({
|
|
678
|
-
runnerId,
|
|
679
|
-
startTime: runnerStart,
|
|
680
|
-
endTime: runnerEnd,
|
|
681
|
-
durationMs: 0,
|
|
682
|
-
status: "skipped",
|
|
683
|
-
diagnosticCount: 0,
|
|
684
|
-
semantic: "unknown",
|
|
685
|
-
});
|
|
686
|
-
logLatency({
|
|
687
|
-
type: "runner",
|
|
688
|
-
filePath: ctx.filePath,
|
|
689
|
-
runnerId,
|
|
690
|
-
durationMs: 0,
|
|
691
|
-
status: "skipped",
|
|
692
|
-
diagnosticCount: 0,
|
|
693
|
-
semantic: "unknown",
|
|
694
|
-
metadata: { reason: "applies_to", kind: ctx.kind },
|
|
695
|
-
});
|
|
696
|
-
continue;
|
|
697
|
-
}
|
|
698
|
-
// Check preconditions
|
|
699
|
-
let shouldRun = true;
|
|
700
|
-
if (runner.when) {
|
|
701
|
-
try {
|
|
702
|
-
shouldRun = await runner.when(ctx);
|
|
703
|
-
}
|
|
704
|
-
catch (error) {
|
|
705
|
-
ctx.log(`Runner ${runner.id} precondition failed: ${error}`);
|
|
706
|
-
shouldRun = false;
|
|
707
|
-
}
|
|
708
|
-
}
|
|
709
|
-
if (!shouldRun) {
|
|
710
|
-
latencies.push({
|
|
711
|
-
runnerId,
|
|
712
|
-
startTime: runnerStart,
|
|
713
|
-
endTime: Date.now(),
|
|
714
|
-
durationMs: Date.now() - runnerStart,
|
|
715
|
-
status: "when_skipped",
|
|
716
|
-
diagnosticCount: 0,
|
|
717
|
-
semantic: runner.id,
|
|
718
|
-
});
|
|
719
|
-
logLatency({
|
|
720
|
-
type: "runner",
|
|
721
|
-
filePath: ctx.filePath,
|
|
722
|
-
runnerId,
|
|
723
|
-
durationMs: 0,
|
|
724
|
-
status: "when_skipped",
|
|
725
|
-
diagnosticCount: 0,
|
|
726
|
-
semantic: "when_condition",
|
|
727
|
-
});
|
|
728
|
-
continue;
|
|
729
|
-
}
|
|
730
|
-
const projectRoot = ctx.projectRoot ?? ctx.cwd;
|
|
731
|
-
// Only post-write dispatches participate. Project scans and direct API
|
|
732
|
-
// callers must retain their existing synchronous semantics.
|
|
733
|
-
const observedTier = ctx.writeIndex === undefined
|
|
734
|
-
? "inline"
|
|
735
|
-
: classifyObservedRunner(projectRoot, runner.id);
|
|
736
|
-
if (observedTier === "collect-later") {
|
|
737
|
-
const markedAtMs = Date.now();
|
|
738
|
-
const deferred = runRunner(ctx, runner, semantic).then((result) => {
|
|
739
|
-
const durationMs = Date.now() - markedAtMs;
|
|
740
|
-
const tier = observeRunnerLatency({
|
|
741
|
-
projectRoot,
|
|
742
|
-
runnerId: runner.id,
|
|
743
|
-
durationMs,
|
|
744
|
-
timedOut: result.failureKind === "timeout",
|
|
745
|
-
});
|
|
746
|
-
if (tier !== observedTier) {
|
|
747
|
-
logLatency({
|
|
748
|
-
type: "phase",
|
|
749
|
-
filePath: ctx.filePath,
|
|
750
|
-
phase: "runner_collect_later_tier_flip",
|
|
751
|
-
durationMs: 0,
|
|
752
|
-
metadata: {
|
|
753
|
-
runnerId: runner.id,
|
|
754
|
-
from: observedTier,
|
|
755
|
-
to: tier,
|
|
756
|
-
projectRoot,
|
|
757
|
-
},
|
|
758
|
-
});
|
|
759
|
-
}
|
|
760
|
-
if (tier === "collect-later") {
|
|
761
|
-
incrementDegradationCount({
|
|
762
|
-
kind: "runner-collect-later",
|
|
763
|
-
subject: `${projectRoot}:${runner.id}`,
|
|
764
|
-
reason: `observed ${durationMs}ms, threshold ${COLLECT_LATER_THRESHOLD_MS}ms`,
|
|
765
|
-
});
|
|
766
|
-
}
|
|
767
|
-
logLatency({
|
|
768
|
-
type: "runner",
|
|
769
|
-
filePath: ctx.filePath,
|
|
770
|
-
runnerId: runner.id,
|
|
771
|
-
startedAt: new Date(markedAtMs).toISOString(),
|
|
772
|
-
durationMs,
|
|
773
|
-
status: result.status,
|
|
774
|
-
diagnosticCount: result.diagnostics.length,
|
|
775
|
-
semantic: result.semantic ?? semantic,
|
|
776
|
-
metadata: { tier: "collect-later", delivered: "turn_end" },
|
|
777
|
-
});
|
|
778
|
-
return result;
|
|
779
|
-
});
|
|
780
|
-
deferRunnerFindings({
|
|
781
|
-
filePath: ctx.filePath,
|
|
782
|
-
cwd: ctx.cwd,
|
|
783
|
-
projectRoot,
|
|
784
|
-
runnerId: runner.id,
|
|
785
|
-
markedAtMs,
|
|
786
|
-
writeIndex: ctx.writeIndex,
|
|
787
|
-
promise: deferred,
|
|
788
|
-
});
|
|
789
|
-
// A deferred runner is still an observed runner. Keep it visible in
|
|
790
|
-
// both the edit latency report and the widget until its turn-end result
|
|
791
|
-
// replaces this pending state (#2122 F1).
|
|
792
|
-
latencies.push({
|
|
793
|
-
runnerId: runner.id,
|
|
794
|
-
startTime: runnerStart,
|
|
795
|
-
endTime: runnerStart,
|
|
796
|
-
durationMs: 0,
|
|
797
|
-
status: "pending",
|
|
798
|
-
diagnosticCount: 0,
|
|
799
|
-
semantic: semantic,
|
|
800
|
-
});
|
|
801
|
-
recordRunner(ctx.filePath, runner.id, "pending", 0, 0, ctx.writeIndex);
|
|
802
|
-
logLatency({
|
|
803
|
-
type: "runner",
|
|
804
|
-
filePath: ctx.filePath,
|
|
805
|
-
runnerId: runner.id,
|
|
806
|
-
durationMs: 0,
|
|
807
|
-
status: "pending",
|
|
808
|
-
diagnosticCount: 0,
|
|
809
|
-
semantic,
|
|
810
|
-
metadata: { tier: "collect-later", delivered: "turn_end" },
|
|
811
|
-
});
|
|
812
|
-
continue;
|
|
813
|
-
}
|
|
814
|
-
const result = await runRunner(ctx, runner, semantic);
|
|
815
|
-
onRunnerResult?.(runnerId, result);
|
|
816
|
-
const runnerEnd = Date.now();
|
|
817
|
-
const duration = runnerEnd - runnerStart;
|
|
818
|
-
const tier = ctx.writeIndex === undefined
|
|
819
|
-
? "inline"
|
|
820
|
-
: observeRunnerLatency({
|
|
821
|
-
projectRoot,
|
|
822
|
-
runnerId: runner.id,
|
|
823
|
-
durationMs: duration,
|
|
824
|
-
timedOut: result.failureKind === "timeout",
|
|
825
|
-
});
|
|
826
|
-
if (tier !== observedTier) {
|
|
827
|
-
logLatency({
|
|
828
|
-
type: "phase",
|
|
829
|
-
filePath: ctx.filePath,
|
|
830
|
-
phase: "runner_collect_later_tier_flip",
|
|
831
|
-
durationMs: 0,
|
|
832
|
-
metadata: {
|
|
833
|
-
runnerId: runner.id,
|
|
834
|
-
from: observedTier,
|
|
835
|
-
to: tier,
|
|
836
|
-
projectRoot,
|
|
837
|
-
},
|
|
838
|
-
});
|
|
839
|
-
}
|
|
840
|
-
if (tier === "collect-later") {
|
|
841
|
-
incrementDegradationCount({
|
|
842
|
-
kind: "runner-collect-later",
|
|
843
|
-
subject: `${projectRoot}:${runner.id}`,
|
|
844
|
-
reason: `observed ${duration}ms, threshold ${COLLECT_LATER_THRESHOLD_MS}ms`,
|
|
845
|
-
});
|
|
846
|
-
}
|
|
847
|
-
// Runner definitions are a typed API, but embedders/plugins can still
|
|
848
|
-
// return untyped objects at runtime. Admit only the closed taxonomy and
|
|
849
|
-
// only on actual skips so free text cannot enter durable latency metadata.
|
|
850
|
-
const skipReason = result.status === "skipped" && isRunnerSkipReason(result.skipReason)
|
|
851
|
-
? result.skipReason
|
|
852
|
-
: undefined;
|
|
853
|
-
latencies.push({
|
|
854
|
-
runnerId,
|
|
855
|
-
startTime: runnerStart,
|
|
856
|
-
endTime: runnerEnd,
|
|
857
|
-
durationMs: duration,
|
|
858
|
-
status: result.status,
|
|
859
|
-
diagnosticCount: result.diagnostics.length,
|
|
860
|
-
semantic: result.semantic ?? semantic,
|
|
861
|
-
...(skipReason !== undefined && {
|
|
862
|
-
skipReason,
|
|
863
|
-
}),
|
|
864
|
-
...(result.unconfirmedServerIds !== undefined && {
|
|
865
|
-
unconfirmedServerIds: result.unconfirmedServerIds,
|
|
866
|
-
}),
|
|
867
|
-
...(result.deferredServerIds !== undefined && {
|
|
868
|
-
deferredServerIds: result.deferredServerIds,
|
|
869
|
-
}),
|
|
870
|
-
});
|
|
871
|
-
logLatency({
|
|
872
|
-
type: "runner",
|
|
873
|
-
filePath: ctx.filePath,
|
|
874
|
-
runnerId,
|
|
875
|
-
startedAt: new Date(runnerStart).toISOString(),
|
|
876
|
-
durationMs: duration,
|
|
877
|
-
status: result.status,
|
|
878
|
-
diagnosticCount: result.diagnostics.length,
|
|
879
|
-
semantic: result.semantic ?? semantic,
|
|
880
|
-
diagnostics: result.diagnostics.length > 0
|
|
881
|
-
? result.diagnostics.map((d) => ({
|
|
882
|
-
rule: d.rule,
|
|
883
|
-
message: d.message.slice(0, 120),
|
|
884
|
-
line: d.line,
|
|
885
|
-
semantic: d.semantic,
|
|
886
|
-
}))
|
|
887
|
-
: undefined,
|
|
888
|
-
metadata: result.status === "failed" && result.failureKind
|
|
889
|
-
? {
|
|
890
|
-
failureKind: result.failureKind,
|
|
891
|
-
failureMessage: result.failureMessage,
|
|
892
|
-
}
|
|
893
|
-
: skipReason
|
|
894
|
-
? { skipReason }
|
|
895
|
-
: undefined,
|
|
896
|
-
});
|
|
897
|
-
recordRunner(ctx.filePath, runnerId, result.status, result.diagnostics.length, duration, ctx.writeIndex);
|
|
898
|
-
diagnostics.push(...result.diagnostics);
|
|
899
|
-
const resultSemantic = result.semantic ?? semantic;
|
|
900
|
-
if ((resultSemantic === "blocking" && result.diagnostics.length > 0) ||
|
|
901
|
-
result.diagnostics.some((d) => d.semantic === "blocking")) {
|
|
902
|
-
hadBlocker = true;
|
|
903
|
-
}
|
|
904
|
-
// mode:"fallback" — stop at first successful runner
|
|
905
|
-
if (group.mode === "fallback" && result.status === "succeeded") {
|
|
906
|
-
break;
|
|
907
|
-
}
|
|
908
|
-
}
|
|
909
|
-
return { diagnostics, latencies, hadBlocker };
|
|
910
|
-
}
|
|
911
|
-
// --- Main Dispatch Function ---
|
|
912
|
-
export async function dispatchForFile(ctx, groups, registry, onRunnerResult) {
|
|
913
|
-
const _overallStart = Date.now();
|
|
914
|
-
if (ctx.fileRole === "generated") {
|
|
915
|
-
// The generated short-circuit (refs #2346): never ran before this fix
|
|
916
|
-
// for name-less machine-emitted files (a scraped/minified page has no
|
|
917
|
-
// `.min.js` pattern to catch it), so the classification now also has a
|
|
918
|
-
// content-shape tier. The skip is observable — one `dispatch_skipped_generated`
|
|
919
|
-
// phase record per file per process carrying the deciding evidence tier
|
|
920
|
-
// and the measured line-shape statistic. Deliberately NOT a degradation
|
|
921
|
-
// ledger entry: skipping a generated file is healthy behavior working
|
|
922
|
-
// as designed, and the ledger's bounded kind slots are reserved for
|
|
923
|
-
// genuine degradations (#2348 review F3 — the ledger precedent at the
|
|
924
|
-
// collect-later tier flip below records an actual capability loss).
|
|
925
|
-
const evidence = ctx.generatedEvidence;
|
|
926
|
-
const lineShapeMean = ctx.generatedLineShapeMean;
|
|
927
|
-
if (!generatedSkipRecorded.has(ctx.filePath)) {
|
|
928
|
-
generatedSkipRecorded.add(ctx.filePath);
|
|
929
|
-
logLatency({
|
|
930
|
-
type: "phase",
|
|
931
|
-
filePath: ctx.filePath,
|
|
932
|
-
phase: "dispatch_skipped_generated",
|
|
933
|
-
durationMs: 0,
|
|
934
|
-
metadata: {
|
|
935
|
-
evidence: evidence ?? "unknown",
|
|
936
|
-
...(lineShapeMean !== undefined && { lineShapeMean }),
|
|
937
|
-
},
|
|
938
|
-
});
|
|
939
|
-
}
|
|
940
|
-
return {
|
|
941
|
-
diagnostics: [],
|
|
942
|
-
blockers: [],
|
|
943
|
-
warnings: [],
|
|
944
|
-
baselineWarningCount: 0,
|
|
945
|
-
fixed: [],
|
|
946
|
-
resolvedCount: 0,
|
|
947
|
-
output: "",
|
|
948
|
-
blockerOutput: "",
|
|
949
|
-
hasBlockers: false,
|
|
950
|
-
};
|
|
951
|
-
}
|
|
952
|
-
const allDiagnostics = [];
|
|
953
|
-
let stopped = false;
|
|
954
|
-
const runnerLatencies = [];
|
|
955
|
-
// Debug logging goes to latency log only (not console - avoid noise)
|
|
956
|
-
const allRunnerIds = groups.flatMap((g) => g.runnerIds);
|
|
957
|
-
logLatency({
|
|
958
|
-
type: "phase",
|
|
959
|
-
filePath: ctx.filePath,
|
|
960
|
-
phase: "dispatch_start",
|
|
961
|
-
durationMs: 0,
|
|
962
|
-
metadata: {
|
|
963
|
-
groupCount: groups.length,
|
|
964
|
-
kind: ctx.kind,
|
|
965
|
-
runners: allRunnerIds.join(","),
|
|
966
|
-
},
|
|
967
|
-
});
|
|
968
|
-
// Run all groups in parallel — they are independent and don't depend on
|
|
969
|
-
// each other's results. Within each group, mode:"fallback" semantics are
|
|
970
|
-
// preserved (sequential first-success). Results are merged in original
|
|
971
|
-
// group order so output is deterministic.
|
|
972
|
-
const groupResults = await Promise.all(groups.map((group) => runGroup(ctx, group, registry, onRunnerResult)));
|
|
973
|
-
// Count baseline warnings before filtering (for delta count display)
|
|
974
|
-
//
|
|
975
|
-
// #2489: `ctx.filePath` is `createDispatchContext`'s `normalizedFilePath`
|
|
976
|
-
// (`resolveRunnerPath` -> `path.resolve` -> `normalizeMapKey`), which is
|
|
977
|
-
// ALWAYS absolute — the #2016 invariant this seam already relies on. A
|
|
978
|
-
// prior relative-path fallback key (`session.baseline.<path relative to
|
|
979
|
-
// ctx.cwd>`) existed here for self-consistency across the abs/rel read
|
|
980
|
-
// and write, but on `ctx.facts` singletons that outlive one project root
|
|
981
|
-
// (`dispatch/integration.ts`'s module-scope `sessionFacts`, reached by
|
|
982
|
-
// the warm `pilens_analyze` MCP route across any number of cwds) two
|
|
983
|
-
// different projects dispatching files that share a relative path (e.g.
|
|
984
|
-
// both have `src/index.ts`) collided on that fallback key, so project
|
|
985
|
-
// B's first-ever delta baseline read could silently return project A's
|
|
986
|
-
// stored diagnostics. Since the absolute key can never collide across
|
|
987
|
-
// projects (an absolute path is unique on the filesystem) and both
|
|
988
|
-
// writes always land together, the relative fallback is both unneeded
|
|
989
|
-
// and the sole source of the collision — removed rather than cwd-scoped
|
|
990
|
-
// (`cwd` is not a stable identity across this seam's callers, #2494).
|
|
991
|
-
//
|
|
992
|
-
// #2489 round 2: the #2016 invariant above is enforced by
|
|
993
|
-
// `createDispatchContext`, the sole real constructor, but nothing enforced
|
|
994
|
-
// it AT THIS SEAM — a hand-built `DispatchContext` (test scaffolding, a
|
|
995
|
-
// future caller) carrying a relative `filePath` would silently key the
|
|
996
|
-
// baseline under a value the constructor could never produce, and every
|
|
997
|
-
// subsequent same-session dispatch of the real (absolute-keyed) file would
|
|
998
|
-
// read back `undefined`, never the collision itself. Mirrors the sibling
|
|
999
|
-
// guard `recordEntitySnapshotDiff` already enforces for the entity-snapshot
|
|
1000
|
-
// seam (`clients/review-graph/service.ts`, #2477): reject visibly and skip
|
|
1001
|
-
// the baseline read/write for this dispatch rather than compute one under
|
|
1002
|
-
// an unreachable key.
|
|
1003
|
-
const baselinePathSafe = isAbsoluteFilePath(ctx.filePath);
|
|
1004
|
-
if (ctx.deltaMode && !baselinePathSafe) {
|
|
1005
|
-
recordDegradationOnce({
|
|
1006
|
-
kind: "dispatch-non-absolute-baseline-path",
|
|
1007
|
-
subject: ctx.filePath,
|
|
1008
|
-
reason: "dispatchForFile requires an absolute ctx.filePath to key the delta baseline (refs #2489)",
|
|
1009
|
-
});
|
|
1010
|
-
}
|
|
1011
|
-
const baselineAbsKey = `session.baseline.${ctx.filePath}`;
|
|
1012
|
-
const previousBaseline = ctx.deltaMode && baselinePathSafe
|
|
1013
|
-
? ctx.facts.getBoundedSessionFact(baselineAbsKey)
|
|
1014
|
-
: undefined;
|
|
1015
|
-
const baselineWarnings = previousBaseline?.filter((d) => d.semantic === "warning" || d.semantic === "none");
|
|
1016
|
-
const baselineWarningCount = baselineWarnings?.length ?? 0;
|
|
1017
|
-
for (const { diagnostics: groupDiags, latencies, hadBlocker, } of groupResults) {
|
|
1018
|
-
runnerLatencies.push(...latencies);
|
|
1019
|
-
allDiagnostics.push(...groupDiags);
|
|
1020
|
-
if (hadBlocker)
|
|
1021
|
-
stopped = true;
|
|
1022
|
-
}
|
|
1023
|
-
// Apply delta mode ONCE across the full diagnostic set.
|
|
1024
|
-
// This avoids partial-baseline corruption when processing multiple groups.
|
|
1025
|
-
const dedupedDiagnostics = dedupeOverlappingDiagnostics(allDiagnostics);
|
|
1026
|
-
const fileContent = ctx.facts.getFileFact(ctx.filePath, "file.content") ?? "";
|
|
1027
|
-
// Project rule policy (`.pi-lens.json` `rules.<id>.disable`/`select`).
|
|
1028
|
-
//
|
|
1029
|
-
// Resolved from `ctx.projectRoot` (falling back to `ctx.cwd`), NOT
|
|
1030
|
-
// `ctx.projectConfig` — `ctx.projectConfig` is loaded from the nested
|
|
1031
|
-
// LANGUAGE root (`resolveLanguageRootForFile`), so in a monorepo where a
|
|
1032
|
-
// package directory has its own `.pi-lens.json`, `discoverPiLensProjectConfig`'s
|
|
1033
|
-
// upward walk stops there and never sees a repo-root policy.
|
|
1034
|
-
// `lens_diagnostics` loads its policy map from `runtime.projectRoot`; using
|
|
1035
|
-
// the same root here keeps the two surfaces in agreement. `ctx.projectConfig`
|
|
1036
|
-
// itself is untouched — thresholds and mutation flags keep their existing
|
|
1037
|
-
// language-root resolution.
|
|
1038
|
-
const rulePolicy = rulePolicyMapFromConfig(loadPiLensProjectConfig(ctx.projectRoot ?? ctx.cwd).rules);
|
|
1039
|
-
// The output-only filter pipeline: LSP/docker overlap suppression + inline
|
|
1040
|
-
// `pi-lens-ignore` + agent/user dispositions + project rule policy. Applied
|
|
1041
|
-
// AFTER dedupe so the pi renderer, widget, and delta all see one filtered
|
|
1042
|
-
// set. #690: dispositions drop false-positive/suppress marks and anything
|
|
1043
|
-
// deferred this session (flagged marks stay; lens_diagnostics tags them at
|
|
1044
|
-
// render time). #1030: the disposition anchor + store MUST key off the
|
|
1045
|
-
// PROJECT ROOT, not ctx.cwd — the mark tool writes dispositions under
|
|
1046
|
-
// runtime.projectRoot, so reading from ctx.cwd (the nested language root in
|
|
1047
|
-
// a monorepo) opened a different diagnostic-dispositions.json and silently
|
|
1048
|
-
// no-op'd every mark under a nested marker.
|
|
1049
|
-
//
|
|
1050
|
-
// #1087: "silencing is not fixing" applies to the WHOLE class, not just the
|
|
1051
|
-
// policy member. This single pipeline is applied identically to the live set
|
|
1052
|
-
// AND (below) to the delta baseline, so a finding persistently dropped by
|
|
1053
|
-
// ANY layer — overlap, inline suppression, disposition, or policy — is
|
|
1054
|
-
// absent from both sides of the delta and never oscillates into `fixed`
|
|
1055
|
-
// (which `trackAgentFixed` would otherwise inflate forever). The stored
|
|
1056
|
-
// baseline remains the unfiltered `dedupedDiagnostics`, so editing a
|
|
1057
|
-
// project's policy/suppressions never resets or corrupts the user-authored
|
|
1058
|
-
// delta baseline — the filtering is re-derived on read for both sides.
|
|
1059
|
-
const applyOutputFilters = (diags) => {
|
|
1060
|
-
const dockerOverlap = suppressTrivyConfigDockerOverlap(diags);
|
|
1061
|
-
const overlap = suppressLintOverlapsWithLsp(dockerOverlap);
|
|
1062
|
-
const inline = applyInlineSuppressions(overlap, fileContent);
|
|
1063
|
-
const disposition = applyDispositions(inline, ctx.projectRoot ?? ctx.cwd, ctx.filePath, fileContent);
|
|
1064
|
-
return applyRulePolicy(disposition, rulePolicy);
|
|
1065
|
-
};
|
|
1066
|
-
let visibleDiagnostics = applyOutputFilters(dedupedDiagnostics);
|
|
1067
|
-
let resolvedCount = 0;
|
|
1068
|
-
if (ctx.deltaMode && previousBaseline) {
|
|
1069
|
-
// Silencing a rule is not fixing it. The stored baseline is deliberately
|
|
1070
|
-
// unfiltered (below), so compare against a fully-filtered view of it
|
|
1071
|
-
// through the SAME pipeline — otherwise every persistently-suppressed
|
|
1072
|
-
// finding sits in `fixed` on every dispatch and inflates the agent's
|
|
1073
|
-
// resolved tally (trackAgentFixed) forever. Only `fixed` changes:
|
|
1074
|
-
// filtered-out ids are absent from `after` either way.
|
|
1075
|
-
const filtered = filterDelta(visibleDiagnostics, applyOutputFilters(previousBaseline), (d) => d.id);
|
|
1076
|
-
visibleDiagnostics = promoteDeltaUnusedToBlockers(filtered.new);
|
|
1077
|
-
resolvedCount = filtered.fixed.length;
|
|
1078
|
-
}
|
|
1079
|
-
// Persist full current snapshot for next run (not delta-filtered subset).
|
|
1080
|
-
// Gated on `baselinePathSafe` too: a non-absolute `ctx.filePath` already
|
|
1081
|
-
// skipped the read above (the degradation record fired there), and writing
|
|
1082
|
-
// under that same unreachable key here would just seed a baseline no real
|
|
1083
|
-
// reader (always absolute) could ever read back.
|
|
1084
|
-
if (ctx.deltaMode && baselinePathSafe) {
|
|
1085
|
-
ctx.facts.setBoundedSessionFact(baselineAbsKey, [...dedupedDiagnostics]);
|
|
1086
|
-
}
|
|
1087
|
-
// Categorize results
|
|
1088
|
-
const blockers = visibleDiagnostics.filter((d) => d.semantic === "blocking");
|
|
1089
|
-
const warnings = visibleDiagnostics.filter((d) => d.semantic === "warning" || d.semantic === "none");
|
|
1090
|
-
const fixedItems = visibleDiagnostics.filter((d) => d.semantic === "fixed");
|
|
1091
|
-
// Append fixed and fixable diagnostics to the persistent worklog, attributed
|
|
1092
|
-
// to the runtime's active model/provider when known (#1448).
|
|
1093
|
-
const worklogIdentity = {
|
|
1094
|
-
model: ctx.telemetryModel,
|
|
1095
|
-
provider: ctx.telemetryProvider,
|
|
1096
|
-
};
|
|
1097
|
-
if (fixedItems.length > 0) {
|
|
1098
|
-
import("../fix-worklog.js")
|
|
1099
|
-
.then(({ appendToWorklog }) => {
|
|
1100
|
-
appendToWorklog(ctx.cwd, fixedItems, true, worklogIdentity);
|
|
1101
|
-
})
|
|
1102
|
-
.catch(() => { });
|
|
1103
|
-
}
|
|
1104
|
-
const fixableWarnings = warnings.filter((d) => d.fixable);
|
|
1105
|
-
if (fixableWarnings.length > 0) {
|
|
1106
|
-
import("../fix-worklog.js")
|
|
1107
|
-
.then(({ appendToWorklog }) => {
|
|
1108
|
-
appendToWorklog(ctx.cwd, fixableWarnings, false, worklogIdentity);
|
|
1109
|
-
})
|
|
1110
|
-
.catch(() => { });
|
|
1111
|
-
}
|
|
1112
|
-
const inlineBlockers = blockers;
|
|
1113
|
-
const inlineFixed = fixedItems;
|
|
1114
|
-
const coverageNotice = buildCoverageNotice(ctx, runnerLatencies);
|
|
1115
|
-
// Format output — only blocking issues shown inline
|
|
1116
|
-
// Warnings tracked but not shown (noise) — surfaced via lens_diagnostics
|
|
1117
|
-
const blockerOutput = formatDiagnostics(inlineBlockers, "blocking");
|
|
1118
|
-
let output = blockerOutput;
|
|
1119
|
-
output += formatDiagnostics(inlineFixed, "fixed");
|
|
1120
|
-
if (coverageNotice) {
|
|
1121
|
-
output += formatDiagnostics([coverageNotice], "warning", 1);
|
|
1122
|
-
warnings.push(coverageNotice);
|
|
1123
|
-
}
|
|
1124
|
-
const pendingRunners = runnerLatencies
|
|
1125
|
-
.filter((runner) => runner.status === "pending")
|
|
1126
|
-
.map((runner) => runner.runnerId);
|
|
1127
|
-
if (pendingRunners.length > 0) {
|
|
1128
|
-
output += `\n⏳ Pending runners (reported at turn end): ${pendingRunners.join(", ")}\n`;
|
|
1129
|
-
}
|
|
1130
|
-
// Generate and store latency report
|
|
1131
|
-
const overallEnd = Date.now();
|
|
1132
|
-
const latencyReport = {
|
|
1133
|
-
filePath: ctx.filePath,
|
|
1134
|
-
fileKind: ctx.kind,
|
|
1135
|
-
overallStartMs: _overallStart,
|
|
1136
|
-
overallEndMs: overallEnd,
|
|
1137
|
-
totalDurationMs: overallEnd - _overallStart,
|
|
1138
|
-
runners: runnerLatencies,
|
|
1139
|
-
stoppedEarly: stopped,
|
|
1140
|
-
totalDiagnostics: visibleDiagnostics.length,
|
|
1141
|
-
blockers: blockers.length,
|
|
1142
|
-
warnings: warnings.length,
|
|
1143
|
-
};
|
|
1144
|
-
// Store for later analysis
|
|
1145
|
-
latencyReports.push(latencyReport);
|
|
1146
|
-
// Keep only last 100 reports to prevent memory bloat
|
|
1147
|
-
if (latencyReports.length > 100) {
|
|
1148
|
-
latencyReports.shift();
|
|
1149
|
-
}
|
|
1150
|
-
// Runner latencies already logged immediately after execution (line ~329)
|
|
1151
|
-
// The runnerLatencies array is stored in latencyReport for aggregate analysis
|
|
1152
|
-
// No need to log again here - would create duplicates in the log
|
|
1153
|
-
// Log summary to latency log only (not console - avoid noise)
|
|
1154
|
-
const sumMs = runnerLatencies.reduce((s, r) => s + r.durationMs, 0);
|
|
1155
|
-
const wallClockMs = latencyReport.totalDurationMs;
|
|
1156
|
-
logLatency({
|
|
1157
|
-
type: "tool_result",
|
|
1158
|
-
filePath: ctx.filePath,
|
|
1159
|
-
durationMs: wallClockMs,
|
|
1160
|
-
wallClockMs,
|
|
1161
|
-
sumMs,
|
|
1162
|
-
parallelGainMs: Math.max(0, sumMs - wallClockMs),
|
|
1163
|
-
result: "dispatch_complete",
|
|
1164
|
-
metadata: {
|
|
1165
|
-
runners: runnerLatencies.map((r) => ({
|
|
1166
|
-
id: r.runnerId,
|
|
1167
|
-
startedAt: new Date(r.startTime).toISOString(),
|
|
1168
|
-
duration: r.durationMs,
|
|
1169
|
-
status: r.status,
|
|
1170
|
-
})),
|
|
1171
|
-
totalDiagnostics: visibleDiagnostics.length,
|
|
1172
|
-
blockers: blockers.length,
|
|
1173
|
-
// #2489 round 2: distinguishes a delta baseline HIT (a prior snapshot
|
|
1174
|
-
// was read for this file this session) from a MISS (first dispatch, or
|
|
1175
|
-
// the non-absolute-path guard above skipped the read) — `dispatch_start`
|
|
1176
|
-
// (above, `metadata: { groupCount, kind, runners }`) fires before the
|
|
1177
|
-
// baseline read ever runs and cannot carry either value.
|
|
1178
|
-
baselineHit: previousBaseline !== undefined,
|
|
1179
|
-
baselineWarningCount,
|
|
1180
|
-
},
|
|
1181
|
-
});
|
|
1182
|
-
return {
|
|
1183
|
-
diagnostics: visibleDiagnostics,
|
|
1184
|
-
blockers,
|
|
1185
|
-
warnings,
|
|
1186
|
-
baselineWarningCount,
|
|
1187
|
-
fixed: fixedItems,
|
|
1188
|
-
resolvedCount,
|
|
1189
|
-
output,
|
|
1190
|
-
blockerOutput,
|
|
1191
|
-
hasBlockers: blockers.length > 0,
|
|
1192
|
-
};
|
|
1193
|
-
}
|
|
1194
|
-
// --- Run Single Runner ---
|
|
1195
|
-
/** Maximum wall-clock time a single runner may take before we abort it. */
|
|
1196
|
-
const RUNNER_TIMEOUT_MS = RUNTIME_CONFIG.dispatch.runnerTimeoutMs;
|
|
1197
|
-
function looksLikeDiagnosticCodePath(value) {
|
|
1198
|
-
if (!value)
|
|
1199
|
-
return false;
|
|
1200
|
-
const text = value.trim();
|
|
1201
|
-
if (!text)
|
|
1202
|
-
return false;
|
|
1203
|
-
const base = path.basename(text.replace(/\\/g, "/"));
|
|
1204
|
-
if (/^lsp:\d+(?::\d+)?$/i.test(text) || /^lsp:\d+(?::\d+)?$/i.test(base)) {
|
|
1205
|
-
return true;
|
|
1206
|
-
}
|
|
1207
|
-
if (/^similarity[-:]/i.test(text) || /^similarity[-:]/i.test(base)) {
|
|
1208
|
-
return true;
|
|
1209
|
-
}
|
|
1210
|
-
if (/^[a-z-]+:\d+(?::\d+)?$/i.test(text) ||
|
|
1211
|
-
/^[a-z-]+:\d+(?::\d+)?$/i.test(base)) {
|
|
1212
|
-
return true;
|
|
1213
|
-
}
|
|
1214
|
-
return false;
|
|
1215
|
-
}
|
|
1216
|
-
function normalizeDiagnosticFilePath(ctx, rawPath) {
|
|
1217
|
-
if (typeof rawPath === "string" && looksLikeDiagnosticCodePath(rawPath)) {
|
|
1218
|
-
ctx.log(`runner path normalization: ignored diagnostic code-like path '${rawPath}', using current file`);
|
|
1219
|
-
return resolveRunnerPath(ctx.cwd, ctx.filePath);
|
|
1220
|
-
}
|
|
1221
|
-
return resolveRunnerPath(ctx.cwd, rawPath || ctx.filePath);
|
|
1222
|
-
}
|
|
1223
|
-
async function runRunner(ctx, runner, defaultSemantic) {
|
|
1224
|
-
const timeoutMs = Math.max(runner.timeoutMs ?? RUNNER_TIMEOUT_MS, getRunnerTimeoutFloorMs());
|
|
1225
|
-
let timer;
|
|
1226
|
-
// #1723: mark this runner as the in-flight phase for the WHOLE race below,
|
|
1227
|
-
// not just the runner's own promise — a synchronous CPU hog inside
|
|
1228
|
-
// `runner.run` (ast-grep-napi, tree-sitter, …) blocks the event loop before
|
|
1229
|
-
// it ever gets to log its own completion, so `recentPhases` (which only
|
|
1230
|
-
// records FINISHED phases) can't name it. `phaseFinished` clears on every
|
|
1231
|
-
// exit from this race (success, runner error, or timeout) via try/finally,
|
|
1232
|
-
// so a `loop_block` sampled after this call returns never sees a stale
|
|
1233
|
-
// pointer. See `phaseStarted`'s doc comment for the identity-token
|
|
1234
|
-
// reasoning and the cost note (negligible next to a runner invocation).
|
|
1235
|
-
const phaseToken = phaseStarted(runner.id);
|
|
1236
|
-
try {
|
|
1237
|
-
const result = await Promise.race([
|
|
1238
|
-
runner.run(ctx).finally(() => clearTimeout(timer)),
|
|
1239
|
-
new Promise((_, reject) => {
|
|
1240
|
-
timer = setTimeout(() => reject(new Error(`Runner ${runner.id} timed out after ${timeoutMs}ms`)), timeoutMs);
|
|
1241
|
-
}),
|
|
1242
|
-
]);
|
|
1243
|
-
const diagnostics = result.diagnostics.map((d) => ({
|
|
1244
|
-
...d,
|
|
1245
|
-
filePath: normalizeDiagnosticFilePath(ctx, d.filePath),
|
|
1246
|
-
}));
|
|
1247
|
-
return {
|
|
1248
|
-
...result,
|
|
1249
|
-
diagnostics,
|
|
1250
|
-
semantic: result.semantic ?? defaultSemantic,
|
|
1251
|
-
};
|
|
1252
|
-
}
|
|
1253
|
-
catch (error) {
|
|
1254
|
-
clearTimeout(timer);
|
|
1255
|
-
ctx.log(`Runner ${runner.id} failed: ${error}`);
|
|
1256
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
1257
|
-
return {
|
|
1258
|
-
status: "failed",
|
|
1259
|
-
diagnostics: [],
|
|
1260
|
-
semantic: defaultSemantic,
|
|
1261
|
-
failureKind: message.includes("timed out") ? "timeout" : "exception",
|
|
1262
|
-
failureMessage: message.slice(0, 200),
|
|
1263
|
-
};
|
|
1264
|
-
}
|
|
1265
|
-
finally {
|
|
1266
|
-
phaseFinished(phaseToken);
|
|
1267
|
-
}
|
|
1268
|
-
}
|
|
1269
|
-
// --- Simple Integration Helper ---
|