@herbertgao/pi-extensions 2026.8.4 → 2026.8.6
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 +5 -5
- package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +11 -3
- package/node_modules/@herbertgao/pi-cc-extensions/README.md +11 -3
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +24 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +91 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/compact-thinking.ts +7 -3
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +74 -5
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/index.ts +7 -6
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +21 -12
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/default-mode.ts +4 -5
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/markdown-enhance.ts +53 -14
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +22 -12
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/result.ts +2 -4
- package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
- package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +18 -0
- package/node_modules/@herbertgao/pi-subagents/package.json +8 -4
- package/node_modules/@herbertgao/pi-subagents/src/agent-color.ts +72 -67
- package/node_modules/@herbertgao/pi-subagents/src/agent-file-toggle.ts +255 -0
- package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +191 -3
- package/node_modules/@herbertgao/pi-subagents/src/agent-runner.ts +20 -4
- package/node_modules/@herbertgao/pi-subagents/src/index.ts +289 -113
- package/node_modules/@herbertgao/pi-subagents/src/output-file.ts +24 -1
- package/node_modules/@herbertgao/pi-subagents/src/ui/agent-widget.ts +24 -2
- package/node_modules/@herbertgao/pi-subagents/src/ui/fleet-list.ts +15 -6
- package/node_modules/@herbertgao/pi-subagents/src/ui/schedule-menu.ts +9 -8
- package/node_modules/@herbertgao/pi-subagents/src/ui/select-item.ts +48 -0
- package/node_modules/@herbertgao/pi-subagents/src/worktree.ts +9 -5
- package/node_modules/@juicesharp/rpiv-ask-user-question/README.md +2 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/ask-user-question.ts +20 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/hosts.md +6 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/keyboard.md +7 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +2 -2
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/build-questionnaire.ts +7 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/key-router.ts +16 -5
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/questionnaire-session.ts +4 -2
- package/node_modules/@narumitw/pi-btw/README.md +32 -24
- package/node_modules/@narumitw/pi-btw/package.json +6 -6
- package/node_modules/@narumitw/pi-btw/src/btw.ts +4 -2
- package/node_modules/@narumitw/pi-btw/src/menu.ts +34 -13
- package/node_modules/@narumitw/pi-btw/src/settings.ts +22 -2
- package/node_modules/pi-lens/CHANGELOG.md +2535 -954
- package/node_modules/pi-lens/README.md +13 -0
- package/node_modules/pi-lens/dist/clients/actionable-warnings.js +73 -18
- package/node_modules/pi-lens/dist/clients/advisory-provenance.js +314 -0
- package/node_modules/pi-lens/dist/clients/agent-behavior-client.js +21 -4
- package/node_modules/pi-lens/dist/clients/agent-nudge.js +14 -7
- package/node_modules/pi-lens/dist/clients/ast-grep-client.js +68 -16
- package/node_modules/pi-lens/dist/clients/ast-grep-types.js +0 -1
- package/node_modules/pi-lens/dist/clients/ast-grep-yaml-synth.js +37 -10
- package/node_modules/pi-lens/dist/clients/atomic-write-staging.js +63 -0
- package/node_modules/pi-lens/dist/clients/atomic-write.js +114 -14
- package/node_modules/pi-lens/dist/clients/bash-file-access.js +193 -23
- package/node_modules/pi-lens/dist/clients/biome-client.js +136 -24
- package/node_modules/pi-lens/dist/clients/bootstrap.js +11 -2
- package/node_modules/pi-lens/dist/clients/bounded-cache.js +34 -0
- package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +192 -0
- package/node_modules/pi-lens/dist/clients/bus-events-logger.js +62 -6
- package/node_modules/pi-lens/dist/clients/bus-publish.js +19 -4
- package/node_modules/pi-lens/dist/clients/cache/rule-cache.js +47 -5
- package/node_modules/pi-lens/dist/clients/cache-manager.js +97 -9
- package/node_modules/pi-lens/dist/clients/cache-observability.js +301 -14
- package/node_modules/pi-lens/dist/clients/call-graph.js +449 -117
- package/node_modules/pi-lens/dist/clients/cascade-format.js +57 -2
- package/node_modules/pi-lens/dist/clients/child-unref.js +85 -0
- package/node_modules/pi-lens/dist/clients/codebase-model.js +52 -23
- package/node_modules/pi-lens/dist/clients/collateral-test-role.js +40 -0
- package/node_modules/pi-lens/dist/clients/complexity-client.js +2 -1
- package/node_modules/pi-lens/dist/clients/console-guard-install.js +26 -0
- package/node_modules/pi-lens/dist/clients/cooperative-budget.js +42 -0
- package/node_modules/pi-lens/dist/clients/dead-code-client.js +137 -31
- package/node_modules/pi-lens/dist/clients/debug-handles.js +206 -0
- package/node_modules/pi-lens/dist/clients/debug-heap.js +167 -0
- package/node_modules/pi-lens/dist/clients/degradation-ledger.js +153 -0
- package/node_modules/pi-lens/dist/clients/dependency-checker.js +361 -77
- package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +65 -13
- package/node_modules/pi-lens/dist/clients/diagnostics-publish.js +18 -4
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +176 -29
- package/node_modules/pi-lens/dist/clients/dispatch/facts/function-facts.js +23 -7
- package/node_modules/pi-lens/dist/clients/dispatch/facts/import-facts.js +8 -18
- package/node_modules/pi-lens/dist/clients/dispatch/facts/tree-sitter-facts.js +8 -5
- package/node_modules/pi-lens/dist/clients/dispatch/indent-detect.js +35 -0
- package/node_modules/pi-lens/dist/clients/dispatch/inline-suppressions.js +17 -8
- package/node_modules/pi-lens/dist/clients/dispatch/integration.js +1172 -683
- package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +14 -0
- package/node_modules/pi-lens/dist/clients/dispatch/plan.js +11 -1
- package/node_modules/pi-lens/dist/clients/dispatch/rule-id-normalize.js +50 -0
- package/node_modules/pi-lens/dist/clients/dispatch/rule-policy.js +135 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +23 -5
- package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +5 -9
- package/node_modules/pi-lens/dist/clients/dispatch/runners/detekt.js +3 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-lint.js +154 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +3 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/index.js +5 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +47 -6
- package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +4 -9
- package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +9 -5
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ruff.js +4 -8
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shellcheck.js +2 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shfmt.js +2 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/spotbugs.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/terragrunt.js +163 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +37 -5
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tree-sitter.js +3 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +13 -7
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +226 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +69 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/lazy-installer.js +3 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +473 -42
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +22 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +97 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yaml-rule-parser.js +5 -4
- package/node_modules/pi-lens/dist/clients/disposition-publish.js +18 -4
- package/node_modules/pi-lens/dist/clients/durable-store.js +97 -0
- package/node_modules/pi-lens/dist/clients/eval-timestamp.js +17 -0
- package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +94 -3
- package/node_modules/pi-lens/dist/clients/extension-log.js +432 -0
- package/node_modules/pi-lens/dist/clients/extension-mode.js +73 -0
- package/node_modules/pi-lens/dist/clients/file-kinds.js +57 -0
- package/node_modules/pi-lens/dist/clients/file-role.js +18 -3
- package/node_modules/pi-lens/dist/clients/file-utils.js +56 -34
- package/node_modules/pi-lens/dist/clients/fix-worklog.js +5 -1
- package/node_modules/pi-lens/dist/clients/format-events-publish.js +51 -7
- package/node_modules/pi-lens/dist/clients/format-service.js +24 -8
- package/node_modules/pi-lens/dist/clients/formatters-lazy.js +8 -0
- package/node_modules/pi-lens/dist/clients/formatters.js +358 -61
- package/node_modules/pi-lens/dist/clients/generated-artifacts.js +148 -15
- package/node_modules/pi-lens/dist/clients/git-guard.js +678 -11
- package/node_modules/pi-lens/dist/clients/git-tracked-ignore.js +4 -0
- package/node_modules/pi-lens/dist/clients/go-client.js +23 -40
- package/node_modules/pi-lens/dist/clients/govulncheck-client.js +124 -7
- package/node_modules/pi-lens/dist/clients/grammar-source.js +12 -4
- package/node_modules/pi-lens/dist/clients/gzip-stage-write.js +21 -3
- package/node_modules/pi-lens/dist/clients/host-ports.js +31 -0
- package/node_modules/pi-lens/dist/clients/installer/index.js +395 -100
- package/node_modules/pi-lens/dist/clients/instance-reaper.js +142 -172
- package/node_modules/pi-lens/dist/clients/jscpd-client.js +27 -55
- package/node_modules/pi-lens/dist/clients/knip-client.js +58 -42
- package/node_modules/pi-lens/dist/clients/language-policy.js +14 -2
- package/node_modules/pi-lens/dist/clients/language-profile.js +13 -7
- package/node_modules/pi-lens/dist/clients/latency-logger.js +72 -1
- package/node_modules/pi-lens/dist/clients/lens-config.js +12 -1
- package/node_modules/pi-lens/dist/clients/lens-engine.js +86 -17
- package/node_modules/pi-lens/dist/clients/lens-events.js +63 -9
- package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +16 -0
- package/node_modules/pi-lens/dist/clients/lens-map.js +94 -19
- package/node_modules/pi-lens/dist/clients/live-bus-emitter.js +73 -0
- package/node_modules/pi-lens/dist/clients/log-cleanup.js +2 -1
- package/node_modules/pi-lens/dist/clients/lsp/aggregation.js +30 -4
- package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +59 -14
- package/node_modules/pi-lens/dist/clients/lsp/client.js +662 -56
- package/node_modules/pi-lens/dist/clients/lsp/config.js +13 -2
- package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +115 -0
- package/node_modules/pi-lens/dist/clients/lsp/edits.js +1012 -121
- package/node_modules/pi-lens/dist/clients/lsp/index.js +2025 -800
- package/node_modules/pi-lens/dist/clients/lsp/launch.js +32 -26
- package/node_modules/pi-lens/dist/clients/lsp/path-utils.js +1 -1
- package/node_modules/pi-lens/dist/clients/lsp/ruby-drive-dirs.js +83 -0
- package/node_modules/pi-lens/dist/clients/lsp/server.js +437 -86
- package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +96 -0
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/classification.js +21 -5
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +18 -3
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +28 -4
- package/node_modules/pi-lens/dist/clients/lsp-lazy.js +8 -0
- package/node_modules/pi-lens/dist/clients/lsp-mutation.js +248 -0
- package/node_modules/pi-lens/dist/clients/mcp/analyze.js +127 -32
- package/node_modules/pi-lens/dist/clients/mcp/ipc.js +157 -24
- package/node_modules/pi-lens/dist/clients/mcp/session.js +235 -14
- package/node_modules/pi-lens/dist/clients/memory-sampler.js +115 -0
- package/node_modules/pi-lens/dist/clients/metrics-client.js +2 -1
- package/node_modules/pi-lens/dist/clients/metrics-history.js +2 -1
- package/node_modules/pi-lens/dist/clients/model-provider.js +53 -0
- package/node_modules/pi-lens/dist/clients/module-report-lsp.js +5 -0
- package/node_modules/pi-lens/dist/clients/module-report.js +168 -3
- package/node_modules/pi-lens/dist/clients/ndjson-logger.js +319 -118
- package/node_modules/pi-lens/dist/clients/opengrep-client.js +1 -1
- package/node_modules/pi-lens/dist/clients/partial-edit-apply.js +120 -5
- package/node_modules/pi-lens/dist/clients/path-utils.js +110 -9
- package/node_modules/pi-lens/dist/clients/pipeline.js +76 -15
- package/node_modules/pi-lens/dist/clients/print-mode.js +21 -0
- package/node_modules/pi-lens/dist/clients/project-changes.js +40 -0
- package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +3 -2
- package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +1 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/call-graph-impact.js +8 -0
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +23 -2
- package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +21 -1
- package/node_modules/pi-lens/dist/clients/project-lens-config.js +86 -9
- package/node_modules/pi-lens/dist/clients/project-report.js +27 -13
- package/node_modules/pi-lens/dist/clients/project-snapshot.js +175 -20
- package/node_modules/pi-lens/dist/clients/project-trust.js +181 -0
- package/node_modules/pi-lens/dist/clients/quiet-window.js +18 -4
- package/node_modules/pi-lens/dist/clients/read-bridge.js +147 -0
- package/node_modules/pi-lens/dist/clients/read-guard-logger.js +159 -1
- package/node_modules/pi-lens/dist/clients/read-guard-tool-lines.js +150 -29
- package/node_modules/pi-lens/dist/clients/read-guard.js +185 -4
- package/node_modules/pi-lens/dist/clients/resource-sampler.js +70 -84
- package/node_modules/pi-lens/dist/clients/review-graph/builder.js +1122 -221
- package/node_modules/pi-lens/dist/clients/review-graph/git-identity.js +2 -1
- package/node_modules/pi-lens/dist/clients/review-graph/import-resolvers.js +21 -10
- package/node_modules/pi-lens/dist/clients/review-graph/query.js +24 -0
- package/node_modules/pi-lens/dist/clients/review-graph/symbol-id.js +46 -0
- package/node_modules/pi-lens/dist/clients/review-graph/tsconfig-paths.js +57 -6
- package/node_modules/pi-lens/dist/clients/review-graph/workspace-modules.js +51 -3
- package/node_modules/pi-lens/dist/clients/review-graph-logger.js +30 -1
- package/node_modules/pi-lens/dist/clients/ruff-client.js +27 -44
- package/node_modules/pi-lens/dist/clients/run-duration.js +55 -0
- package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +257 -77
- package/node_modules/pi-lens/dist/clients/runtime-context.js +129 -12
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +242 -26
- package/node_modules/pi-lens/dist/clients/runtime-session.js +428 -117
- package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +71 -48
- package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +342 -33
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +619 -93
- package/node_modules/pi-lens/dist/clients/rust-client.js +23 -38
- package/node_modules/pi-lens/dist/clients/safe-spawn.js +777 -62
- package/node_modules/pi-lens/dist/clients/security-scan-client.js +90 -6
- package/node_modules/pi-lens/dist/clients/session-state-store.js +3 -2
- package/node_modules/pi-lens/dist/clients/sg-runner.js +424 -196
- package/node_modules/pi-lens/dist/clients/slow-fs.js +2 -1
- package/node_modules/pi-lens/dist/clients/smells-rollup.js +231 -0
- package/node_modules/pi-lens/dist/clients/source-filter.js +184 -20
- package/node_modules/pi-lens/dist/clients/source-walker.js +66 -10
- package/node_modules/pi-lens/dist/clients/startup-scan.js +15 -16
- package/node_modules/pi-lens/dist/clients/startup-timing.js +7 -1
- package/node_modules/pi-lens/dist/clients/test-runner-client.js +469 -32
- package/node_modules/pi-lens/dist/clients/tool-event.js +35 -0
- package/node_modules/pi-lens/dist/clients/tool-policy.js +390 -39
- package/node_modules/pi-lens/dist/clients/tool-render.js +155 -0
- package/node_modules/pi-lens/dist/clients/tool-set-policy.js +76 -0
- package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +6 -1
- package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +419 -50
- package/node_modules/pi-lens/dist/clients/tree-sitter-logger.js +21 -0
- package/node_modules/pi-lens/dist/clients/tree-sitter-query-loader.js +7 -1
- package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +7 -2
- package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +44 -7
- package/node_modules/pi-lens/dist/clients/user-notify.js +51 -0
- package/node_modules/pi-lens/dist/clients/vanished-instance-marker.js +57 -0
- package/node_modules/pi-lens/dist/clients/warm-attach.js +50 -13
- package/node_modules/pi-lens/dist/clients/widget-state.js +300 -43
- package/node_modules/pi-lens/dist/clients/word-index.js +680 -81
- package/node_modules/pi-lens/dist/clients/workspace-topology.js +89 -6
- package/node_modules/pi-lens/dist/index.js +51785 -36118
- package/node_modules/pi-lens/dist/mcp/analyze-cli.js +182 -29
- package/node_modules/pi-lens/dist/mcp/server.js +219 -46
- package/node_modules/pi-lens/dist/tools/activate-tools.js +17 -5
- package/node_modules/pi-lens/dist/tools/ast-grep-replace.js +9 -4
- package/node_modules/pi-lens/dist/tools/ast-grep-search.js +93 -27
- package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +5 -2
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +203 -38
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +210 -42
- package/node_modules/pi-lens/dist/tools/lsp-navigation.js +46 -3
- package/node_modules/pi-lens/dist/tools/module-report.js +9 -0
- package/node_modules/pi-lens/dist/tools/symbol-search.js +1 -1
- package/node_modules/pi-lens/docs/agent-guide.md +40 -15
- package/node_modules/pi-lens/docs/agent-tools.md +21 -10
- package/node_modules/pi-lens/docs/analysisall.md +192 -0
- package/node_modules/pi-lens/docs/api-ports-inventory.md +165 -0
- package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +14 -3
- package/node_modules/pi-lens/docs/durable-store-audit-1202.md +32 -0
- package/node_modules/pi-lens/docs/environment-variables.md +44 -0
- package/node_modules/pi-lens/docs/fable.md +27 -0
- package/node_modules/pi-lens/docs/features.md +45 -3
- package/node_modules/pi-lens/docs/globalconfig.md +56 -1
- package/node_modules/pi-lens/docs/language-coverage.md +4 -3
- package/node_modules/pi-lens/docs/lsp-capability-matrix.md +2 -2
- package/node_modules/pi-lens/docs/mcp.md +37 -4
- package/node_modules/pi-lens/docs/servercapabilities.md +3 -3
- package/node_modules/pi-lens/docs/settings.md +18 -1
- package/node_modules/pi-lens/docs/tools.md +4 -1
- package/node_modules/pi-lens/docs/usage.md +41 -5
- package/node_modules/pi-lens/docs/word-index.md +35 -0
- package/node_modules/pi-lens/package.json +10 -10
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-bare-except-test.yml +49 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-bare-host-path-in-win32-branch-test.yml +87 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-chained-type-assertions-test.yml +8 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-conditional-empty-object-spread-js-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-conditional-empty-object-spread-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-nested-links-test.yml +11 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-raw-json-store-write-test.yml +17 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-js-test.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-test.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-js-test.yml +8 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-test.yml +8 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-laundering-test.yml +11 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-win32-isabsolute-for-qualification-test.yml +16 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-except.yml +3 -15
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-host-path-in-win32-branch.yml +25 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-chained-type-assertions.yml +21 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-conditional-empty-object-spread-js.yml +21 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-conditional-empty-object-spread.yml +29 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-nested-links.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-raw-json-store-write.yml +30 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply-js.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get-js.yml +13 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get.yml +16 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-laundering.yml +27 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-win32-isabsolute-for-qualification.yml +23 -0
- package/node_modules/pi-lens/rules/tree-sitter-queries/tsx/no-nested-links.yml +4 -6
- package/node_modules/pi-lens/rules/tree-sitter-queries/typescript/duplicate-function-arg.yml +2 -2
- package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +134 -2
- package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +10 -11
- package/node_modules/pi-lens/skills/pi-lens-lsp-navigation/SKILL.md +22 -22
- package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/SKILL.md +8 -114
- package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/reference.md +129 -0
- package/node_modules/pi-lens/skills/pi-lens-write-tree-sitter-rule/SKILL.md +3 -1
- package/node_modules/pi-mcp-adapter/CHANGELOG.md +38 -0
- package/node_modules/pi-mcp-adapter/README.md +38 -4
- package/node_modules/pi-mcp-adapter/agent-dir.ts +12 -4
- package/node_modules/pi-mcp-adapter/agent-plugin-loader.ts +1 -1
- package/node_modules/pi-mcp-adapter/cli.js +25 -4
- package/node_modules/pi-mcp-adapter/commands.ts +15 -7
- package/node_modules/pi-mcp-adapter/config.ts +4 -4
- package/node_modules/pi-mcp-adapter/direct-tools.ts +58 -8
- package/node_modules/pi-mcp-adapter/host-html-template.ts +0 -8
- package/node_modules/pi-mcp-adapter/index.ts +8 -3
- package/node_modules/pi-mcp-adapter/init.ts +29 -5
- package/node_modules/pi-mcp-adapter/lifecycle.ts +0 -4
- package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +1 -2
- package/node_modules/pi-mcp-adapter/mcp-auth.ts +60 -2
- package/node_modules/pi-mcp-adapter/mcp-panel.ts +45 -9
- package/node_modules/pi-mcp-adapter/mcp-script-worker.mjs +22 -20
- package/node_modules/pi-mcp-adapter/mcp-setup-panel.ts +2 -1
- package/node_modules/pi-mcp-adapter/metadata-cache.ts +37 -4
- package/node_modules/pi-mcp-adapter/npx-resolver.ts +81 -26
- package/node_modules/pi-mcp-adapter/package.json +4 -3
- package/node_modules/pi-mcp-adapter/proxy-modes.ts +108 -26
- package/node_modules/pi-mcp-adapter/request-headers-command.ts +336 -0
- package/node_modules/pi-mcp-adapter/search-ranking.ts +86 -7
- package/node_modules/pi-mcp-adapter/server-manager.ts +41 -7
- package/node_modules/pi-mcp-adapter/session-recovery.ts +8 -2
- package/node_modules/pi-mcp-adapter/tool-approval.ts +48 -7
- package/node_modules/pi-mcp-adapter/tool-metadata.ts +62 -4
- package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +138 -12
- package/node_modules/pi-mcp-adapter/types.ts +176 -27
- package/node_modules/pi-mcp-adapter/ui-server.ts +20 -1
- package/node_modules/pi-web-access/CHANGELOG.md +14 -0
- package/node_modules/pi-web-access/README.md +18 -12
- package/node_modules/pi-web-access/auth-fetch.ts +148 -0
- package/node_modules/pi-web-access/chrome-cookies.ts +110 -23
- package/node_modules/pi-web-access/curator-page.ts +5 -3
- package/node_modules/pi-web-access/curator-server.ts +2 -1
- package/node_modules/pi-web-access/extract.ts +106 -34
- package/node_modules/pi-web-access/fetch-params.ts +17 -3
- package/node_modules/pi-web-access/firecrawl.ts +172 -12
- package/node_modules/pi-web-access/gemini-search.ts +18 -4
- package/node_modules/pi-web-access/index.ts +120 -48
- package/node_modules/pi-web-access/package.json +2 -2
- package/node_modules/pi-web-access/summary-review.ts +11 -5
- package/node_modules/pi-web-access/youtube-extract.ts +2 -2
- package/package.json +12 -13
- package/node_modules/pi-lens/dist/clients/ast-grep-parser.js +0 -86
- package/node_modules/pi-lens/dist/clients/lsp/interactive-install.js +0 -367
- package/node_modules/pi-lens/dist/clients/lsp/lsp-index.js +0 -10
- package/node_modules/pi-lens/dist/clients/lsp/server-strategies.js +0 -5
- package/node_modules/pi-lens/dist/clients/project-metadata.js +0 -690
- package/node_modules/pi-lens/dist/clients/source-groups.js +0 -96
- package/node_modules/pi-lens/dist/clients/startup-marker.js +0 -6
- package/node_modules/pi-lens/dist/clients/types.js +0 -11
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Lazy dispatch integration seam for startup-cost control (#1394). */
|
|
2
|
+
let integrationPromise;
|
|
3
|
+
/** Start loading the runner graph once; callers may fire-and-forget this. */
|
|
4
|
+
export function warmDispatchIntegration() {
|
|
5
|
+
return (integrationPromise ??= import("./integration.js"));
|
|
6
|
+
}
|
|
7
|
+
/** Await the same promise used by session-start warming and first use. */
|
|
8
|
+
export function loadDispatchIntegration() {
|
|
9
|
+
return warmDispatchIntegration();
|
|
10
|
+
}
|
|
11
|
+
/** Test-only reset; production sessions intentionally retain the promise. */
|
|
12
|
+
export function resetDispatchIntegrationForTests() {
|
|
13
|
+
integrationPromise = undefined;
|
|
14
|
+
}
|
|
@@ -118,6 +118,11 @@ export const LANGUAGE_CAPABILITY_MATRIX = {
|
|
|
118
118
|
{ mode: "all", runnerIds: ["actionlint"], filterKinds: ["yaml"] },
|
|
119
119
|
],
|
|
120
120
|
},
|
|
121
|
+
"helm-template": {
|
|
122
|
+
name: "Helm Template Linting",
|
|
123
|
+
capabilities: ["lint"],
|
|
124
|
+
writeGroups: [primary("helm-template")],
|
|
125
|
+
},
|
|
121
126
|
sql: {
|
|
122
127
|
name: "SQL Processing",
|
|
123
128
|
capabilities: ["format", "lint"],
|
|
@@ -218,9 +223,14 @@ export const LANGUAGE_CAPABILITY_MATRIX = {
|
|
|
218
223
|
},
|
|
219
224
|
terraform: {
|
|
220
225
|
name: "Terraform Linting",
|
|
221
|
-
capabilities: ["types", "lint"],
|
|
226
|
+
capabilities: ["types", "lint", "security"],
|
|
222
227
|
writeGroups: [primary("terraform")],
|
|
223
228
|
},
|
|
229
|
+
terragrunt: {
|
|
230
|
+
name: "Terragrunt Linting",
|
|
231
|
+
capabilities: ["lint", "format"],
|
|
232
|
+
writeGroups: [primary("terragrunt")],
|
|
233
|
+
},
|
|
224
234
|
nix: {
|
|
225
235
|
name: "Nix Linting",
|
|
226
236
|
capabilities: ["types", "lint"],
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalize a rule id to the form a user typically writes in a
|
|
3
|
+
* `pi-lens-ignore` comment, an inline suppression, or a project-level
|
|
4
|
+
* `disable`/`select` list. Strips the `ast-grep:` LSP source prefix and the
|
|
5
|
+
* language suffix used by the rule catalogs.
|
|
6
|
+
*/
|
|
7
|
+
import * as fs from "node:fs";
|
|
8
|
+
import * as path from "node:path";
|
|
9
|
+
import { getAstGrepRuleSources } from "../sgconfig.js";
|
|
10
|
+
/** Derive language tags from shipped rule filenames, rather than a list. */
|
|
11
|
+
export function deriveRuleIdLanguageSuffixes(ruleRoot) {
|
|
12
|
+
const suffixes = new Set();
|
|
13
|
+
const visit = (dir) => {
|
|
14
|
+
let entries;
|
|
15
|
+
try {
|
|
16
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
for (const entry of entries) {
|
|
22
|
+
const entryPath = path.join(dir, entry.name);
|
|
23
|
+
if (entry.isDirectory())
|
|
24
|
+
visit(entryPath);
|
|
25
|
+
else {
|
|
26
|
+
const match = /-([a-z0-9]+)\.ya?ml$/i.exec(entry.name);
|
|
27
|
+
if (match)
|
|
28
|
+
suffixes.add(match[1].toLowerCase());
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
visit(ruleRoot);
|
|
33
|
+
return suffixes;
|
|
34
|
+
}
|
|
35
|
+
const bundledCodeRabbitRules = getAstGrepRuleSources().find((source) => source.origin === "bundled" && source.tier === "secondary");
|
|
36
|
+
const RULE_ID_LANGUAGE_SUFFIXES = new Set(["js"]);
|
|
37
|
+
if (bundledCodeRabbitRules) {
|
|
38
|
+
for (const suffix of deriveRuleIdLanguageSuffixes(bundledCodeRabbitRules.dir)) {
|
|
39
|
+
RULE_ID_LANGUAGE_SUFFIXES.add(suffix);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
export function normalizeRuleId(ruleId) {
|
|
43
|
+
const normalized = ruleId.replace(/^ast-grep:/, "");
|
|
44
|
+
for (const suffix of RULE_ID_LANGUAGE_SUFFIXES) {
|
|
45
|
+
if (normalized.endsWith(`-${suffix}`)) {
|
|
46
|
+
return normalized.slice(0, -(suffix.length + 1));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return normalized;
|
|
50
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project-level rule policy (`.pi-lens.json` `rules.<id>.disable` /
|
|
3
|
+
* `rules.<id>.select`) — output-only filtering of dispatches, so the project's
|
|
4
|
+
* own policy narrows what the user actually sees without widening the trusted
|
|
5
|
+
* surface area (widget state, baseline, dedup, and per-edit record stay
|
|
6
|
+
* authoritative).
|
|
7
|
+
*
|
|
8
|
+
* Matching is PROJECT-WIDE. The outer `rules.<key>` is a grouping label only —
|
|
9
|
+
* it does not scope which diagnostics a `disable`/`select` list under it can
|
|
10
|
+
* match. Every `disable` entry across every key is unioned into one drop list,
|
|
11
|
+
* and every `select` entry across every key is unioned into one allowlist.
|
|
12
|
+
* Disable is checked first, so it wins globally regardless of which key it's
|
|
13
|
+
* configured under.
|
|
14
|
+
*
|
|
15
|
+
* Match normalization is consolidated with the rest of the rule-id surfaces:
|
|
16
|
+
* `inline-suppressions.ts` and `lens-diagnostics.ts`'s `normalizeRuleId`
|
|
17
|
+
* both strip the `ast-grep:` prefix and the `-js` suffix, so a user listing
|
|
18
|
+
* `no-eval` once under `disable` covers both the LSP tag (`ast-grep:no-eval`)
|
|
19
|
+
* and the napi tag (`no-eval` / `no-eval-js`). Sharing the normalization keeps
|
|
20
|
+
* the three surfaces from drifting.
|
|
21
|
+
*/
|
|
22
|
+
import { normalizeRuleId } from "./rule-id-normalize.js";
|
|
23
|
+
/**
|
|
24
|
+
* Decide whether a rule id (in the form it's emitted on a diagnostic — e.g.
|
|
25
|
+
* `ast-grep:no-eval`, `no-eval-js`, `no-eval`, `ts:2322`) should be filtered
|
|
26
|
+
* out under a project's rule policy map. Returns `dropped: true` when the
|
|
27
|
+
* diagnostic would be hidden from output.
|
|
28
|
+
*
|
|
29
|
+
* Project-wide: every `disable` entry across every configured key is checked
|
|
30
|
+
* first (disable wins globally over select). Then every `select` entry
|
|
31
|
+
* across every key is unioned into one allowlist — a non-empty union that
|
|
32
|
+
* the rule doesn't match also drops it. An absent/empty union across all
|
|
33
|
+
* keys means "no restriction". Matching uses the same normalization as
|
|
34
|
+
* inline suppression so a configured `no-eval` entry covers
|
|
35
|
+
* `ast-grep:no-eval` and `no-eval-js`.
|
|
36
|
+
*/
|
|
37
|
+
export function evaluateRulePolicy(ruleId, policyMap) {
|
|
38
|
+
if (!policyMap)
|
|
39
|
+
return { dropped: false };
|
|
40
|
+
const raw = ruleId || "";
|
|
41
|
+
const norm = normalizeRuleId(raw);
|
|
42
|
+
if (scanList(policyMap, (e) => e.disable, raw, norm).matched) {
|
|
43
|
+
return { dropped: true };
|
|
44
|
+
}
|
|
45
|
+
const select = scanList(policyMap, (e) => e.select, raw, norm);
|
|
46
|
+
return { dropped: select.sawEntry && !select.matched };
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Union one list (`disable` or `select`) across every key in the map and test
|
|
50
|
+
* the rule against it. `sawEntry` reports whether the union was non-empty,
|
|
51
|
+
* which is what makes a `select` union restrictive rather than absent.
|
|
52
|
+
*/
|
|
53
|
+
function scanList(policyMap, pick, raw, norm) {
|
|
54
|
+
let sawEntry = false;
|
|
55
|
+
for (const entry of Object.values(policyMap)) {
|
|
56
|
+
for (const candidate of (entry && pick(entry)) ?? []) {
|
|
57
|
+
sawEntry = true;
|
|
58
|
+
if (matchesRule(candidate, raw, norm))
|
|
59
|
+
return { matched: true, sawEntry };
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return { matched: false, sawEntry };
|
|
63
|
+
}
|
|
64
|
+
function matchesRule(entry, raw, normalized) {
|
|
65
|
+
if (entry === raw)
|
|
66
|
+
return true;
|
|
67
|
+
return normalizeRuleId(entry) === normalized;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Filter an array of diagnostics (returns a new array) by the project rule
|
|
71
|
+
* policy map. `rule` is preferred; code-only diagnostics use `code` as their
|
|
72
|
+
* policy key so project-diagnostics details and rendered summaries cannot
|
|
73
|
+
* disagree about a finding that has no explicit rule field. `Diagnostic.id`
|
|
74
|
+
* remains a dedup key (`eslint:unknown:12`), not a policy key, so id-only
|
|
75
|
+
* findings (including blocking parse errors) remain exempt.
|
|
76
|
+
*
|
|
77
|
+
* Used by both the per-edit dispatcher and the `lens-diagnostics` tool's
|
|
78
|
+
* `mode=delta`/`mode=all`/`mode=full` paths so a project's own policy
|
|
79
|
+
* applies consistently across every output surface.
|
|
80
|
+
*/
|
|
81
|
+
export function applyRulePolicy(diagnostics, policyMap) {
|
|
82
|
+
if (!policyMap)
|
|
83
|
+
return diagnostics;
|
|
84
|
+
// Fast-path: if every entry has neither disable nor select, there is no
|
|
85
|
+
// output filter to apply. Keeps the hot path (most projects have only
|
|
86
|
+
// thresholds) cheap.
|
|
87
|
+
let hasFilter = false;
|
|
88
|
+
for (const rawEntry of Object.values(policyMap)) {
|
|
89
|
+
if (!rawEntry || typeof rawEntry !== "object" || Array.isArray(rawEntry)) {
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
const entry = rawEntry;
|
|
93
|
+
if ((entry.disable?.length ?? 0) > 0 || (entry.select?.length ?? 0) > 0) {
|
|
94
|
+
hasFilter = true;
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (!hasFilter)
|
|
99
|
+
return diagnostics;
|
|
100
|
+
return diagnostics.filter((d) => {
|
|
101
|
+
const ruleId = d.rule ?? d.code;
|
|
102
|
+
if (!ruleId)
|
|
103
|
+
return true;
|
|
104
|
+
const { dropped } = evaluateRulePolicy(ruleId, policyMap);
|
|
105
|
+
return !dropped;
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Build the policy map from a `PiLensProjectConfig.rules`-shaped value. Returns
|
|
110
|
+
* undefined when there's nothing to filter (the hot path), or a map suitable
|
|
111
|
+
* for `applyRulePolicy` otherwise. Excludes entries whose only field is
|
|
112
|
+
* `threshold` (a threshold is a separate concern handled elsewhere) so the
|
|
113
|
+
* filter step doesn't repeat the work.
|
|
114
|
+
*/
|
|
115
|
+
export function rulePolicyMapFromConfig(rules) {
|
|
116
|
+
if (!rules)
|
|
117
|
+
return undefined;
|
|
118
|
+
let built;
|
|
119
|
+
for (const [key, rawEntry] of Object.entries(rules)) {
|
|
120
|
+
if (!rawEntry || typeof rawEntry !== "object" || Array.isArray(rawEntry)) {
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
const entry = rawEntry;
|
|
124
|
+
const hasDisable = (entry.disable?.length ?? 0) > 0;
|
|
125
|
+
const hasSelect = (entry.select?.length ?? 0) > 0;
|
|
126
|
+
if (!hasDisable && !hasSelect)
|
|
127
|
+
continue;
|
|
128
|
+
built ??= {};
|
|
129
|
+
built[key] = {
|
|
130
|
+
...(hasDisable ? { disable: entry.disable } : {}),
|
|
131
|
+
...(hasSelect ? { select: entry.select } : {}),
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
return built;
|
|
135
|
+
}
|
|
@@ -19,6 +19,12 @@ import { isAuxiliaryLspAlive } from "../../lsp/index.js";
|
|
|
19
19
|
import { resolveAstGrepNativeExe } from "../../lsp/wait-policy/index.js";
|
|
20
20
|
import { PRIORITY } from "../priorities.js";
|
|
21
21
|
import { calculateRuleComplexity, isOverlyBroadPattern, isStructuredRule, loadYamlRules, loadYamlRulesFresh, MAX_BLOCKING_RULE_COMPLEXITY, } from "./yaml-rule-parser.js";
|
|
22
|
+
const defaultUnsupportedLanguageLog = new Set();
|
|
23
|
+
const UNSUPPORTED_RULE_ID_SAMPLE_SIZE = 5;
|
|
24
|
+
/** Clear per-session unsupported-language telemetry dedupe. */
|
|
25
|
+
export function resetAstGrepUnsupportedLanguageLog() {
|
|
26
|
+
defaultUnsupportedLanguageLog.clear();
|
|
27
|
+
}
|
|
22
28
|
// Lazy load the napi package
|
|
23
29
|
let sg;
|
|
24
30
|
let sgLoadAttempted = false;
|
|
@@ -237,7 +243,7 @@ export function evaluateAstGrepRules(filePath, rootNode, cwd, kind, options = {}
|
|
|
237
243
|
const maxTotalDiagnostics = options.maxTotalDiagnostics ?? MAX_TOTAL_DIAGNOSTICS;
|
|
238
244
|
const blockingOnly = options.blockingOnly === true;
|
|
239
245
|
const log = options.log;
|
|
240
|
-
const unsupportedLanguageLog = options.unsupportedLanguageLog ??
|
|
246
|
+
const unsupportedLanguageLog = options.unsupportedLanguageLog ?? defaultUnsupportedLanguageLog;
|
|
241
247
|
const diagnostics = [];
|
|
242
248
|
const seenRuleIds = new Set();
|
|
243
249
|
const suppressLinterOverlap = kind === "jsts" && hasEslintConfig(cwd);
|
|
@@ -249,15 +255,28 @@ export function evaluateAstGrepRules(filePath, rootNode, cwd, kind, options = {}
|
|
|
249
255
|
const flushUnsupportedRuleSkips = () => {
|
|
250
256
|
if (newlyUnsupported.size === 0)
|
|
251
257
|
return;
|
|
258
|
+
const firstSeenLanguages = Array.from(newlyUnsupported.entries()).filter(([language]) => !unsupportedLanguageLog.has(language));
|
|
259
|
+
for (const [language] of firstSeenLanguages) {
|
|
260
|
+
unsupportedLanguageLog.add(language);
|
|
261
|
+
}
|
|
262
|
+
if (firstSeenLanguages.length === 0) {
|
|
263
|
+
newlyUnsupported.clear();
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
for (const [language] of firstSeenLanguages)
|
|
267
|
+
unsupportedLanguageLog.add(language);
|
|
252
268
|
logLatency({
|
|
253
269
|
type: "phase",
|
|
254
270
|
phase: "astgrep_napi_unsupported_rules_skipped",
|
|
255
271
|
filePath,
|
|
256
272
|
durationMs: 0,
|
|
257
273
|
metadata: {
|
|
258
|
-
skippedByLanguage: Object.fromEntries(
|
|
274
|
+
skippedByLanguage: Object.fromEntries(firstSeenLanguages.map(([language, ruleIds]) => [
|
|
259
275
|
language,
|
|
260
|
-
{
|
|
276
|
+
{
|
|
277
|
+
count: ruleIds.length,
|
|
278
|
+
ruleIds: ruleIds.slice(0, UNSUPPORTED_RULE_ID_SAMPLE_SIZE),
|
|
279
|
+
},
|
|
261
280
|
])),
|
|
262
281
|
},
|
|
263
282
|
});
|
|
@@ -315,8 +334,7 @@ export function evaluateAstGrepRules(filePath, rootNode, cwd, kind, options = {}
|
|
|
315
334
|
lang !== "typescript" &&
|
|
316
335
|
lang !== "tsx" &&
|
|
317
336
|
lang !== "javascript") {
|
|
318
|
-
if (!unsupportedLanguageLog.has(
|
|
319
|
-
unsupportedLanguageLog.add(rule.id);
|
|
337
|
+
if (!unsupportedLanguageLog.has(lang)) {
|
|
320
338
|
const ids = newlyUnsupported.get(lang) ?? [];
|
|
321
339
|
ids.push(rule.id);
|
|
322
340
|
newlyUnsupported.set(lang, ids);
|
|
@@ -6,9 +6,8 @@
|
|
|
6
6
|
* mutating files mid-dispatch after LSP sync has already happened.
|
|
7
7
|
*/
|
|
8
8
|
import * as path from "node:path";
|
|
9
|
-
import { resolvePackagePath } from "../../package-root.js";
|
|
10
9
|
import { safeSpawnAsync } from "../../safe-spawn.js";
|
|
11
|
-
import {
|
|
10
|
+
import { biomeConfigArgs, getAutofixCapability, getJstsLintPolicyForCwd, } from "../../tool-policy.js";
|
|
12
11
|
import { PRIORITY } from "../priorities.js";
|
|
13
12
|
import { resolveToolCommandWithInstallFallback } from "./utils/runner-helpers.js";
|
|
14
13
|
function parseBiomeJson(raw, filePath) {
|
|
@@ -60,13 +59,10 @@ const biomeCheckJsonRunner = {
|
|
|
60
59
|
if (!cmd) {
|
|
61
60
|
return { status: "skipped", diagnostics: [], semantic: "none" };
|
|
62
61
|
}
|
|
63
|
-
//
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
(userConfigPath ??
|
|
68
|
-
resolvePackagePath(import.meta.url, "config/biome/core.jsonc")),
|
|
69
|
-
];
|
|
62
|
+
// Shared config-args seam (#1247): `biomeClient.fixFileAsync` consumes
|
|
63
|
+
// the same builder, so the user's config / package fallback applies on
|
|
64
|
+
// `lint --write` too.
|
|
65
|
+
const configArg = biomeConfigArgs(cwd);
|
|
70
66
|
// Run biome lint (diagnostics only - format is handled separately)
|
|
71
67
|
const checkResult = await safeSpawnAsync(cmd, [
|
|
72
68
|
"lint",
|
|
@@ -4,6 +4,7 @@ import { safeSpawnAsync } from "../../safe-spawn.js";
|
|
|
4
4
|
import { getLinterPolicyForCwd } from "../../tool-policy.js";
|
|
5
5
|
import { PRIORITY } from "../priorities.js";
|
|
6
6
|
import { createAvailabilityChecker } from "./utils/runner-helpers.js";
|
|
7
|
+
import { spawnFailedWithNoOutput } from "./utils/spawn-outcome.js";
|
|
7
8
|
const detekt = createAvailabilityChecker("detekt", ".bat");
|
|
8
9
|
const DETEKT_CONFIG_CANDIDATES = [
|
|
9
10
|
"detekt.yml",
|
|
@@ -145,10 +146,10 @@ const detektRunner = {
|
|
|
145
146
|
return { status: "skipped", diagnostics: [], semantic: "none" };
|
|
146
147
|
const absPath = path.resolve(cwd, ctx.filePath);
|
|
147
148
|
const result = await safeSpawnAsync(cmd, ["--input", absPath, "--config", configPath], { cwd, timeout: 60000 });
|
|
148
|
-
|
|
149
|
+
const raw = `${result.stdout ?? ""}${result.stderr ?? ""}`;
|
|
150
|
+
if (spawnFailedWithNoOutput(result, raw)) {
|
|
149
151
|
return { status: "skipped", diagnostics: [], semantic: "none" };
|
|
150
152
|
}
|
|
151
|
-
const raw = `${result.stdout ?? ""}${result.stderr ?? ""}`;
|
|
152
153
|
const diagnostics = parseDetektOutput(raw, ctx.filePath);
|
|
153
154
|
if (diagnostics.length === 0) {
|
|
154
155
|
return { status: "succeeded", diagnostics: [], semantic: "none" };
|
|
@@ -3,6 +3,7 @@ import { safeSpawnAsync } from "../../safe-spawn.js";
|
|
|
3
3
|
import { getLinterPolicyForCwd } from "../../tool-policy.js";
|
|
4
4
|
import { PRIORITY } from "../priorities.js";
|
|
5
5
|
import { createAvailabilityChecker, resolveToolCommandWithInstallFallback, } from "./utils/runner-helpers.js";
|
|
6
|
+
import { spawnFailedWithNoOutput } from "./utils/spawn-outcome.js";
|
|
6
7
|
const hadolint = createAvailabilityChecker("hadolint", ".exe");
|
|
7
8
|
function parseHadolintOutput(raw, filePath) {
|
|
8
9
|
try {
|
|
@@ -52,7 +53,7 @@ const hadolintRunner = {
|
|
|
52
53
|
return { status: "skipped", diagnostics: [], semantic: "none" };
|
|
53
54
|
}
|
|
54
55
|
const result = await safeSpawnAsync(cmd, ["--format", "json", "--no-fail", path.resolve(cwd, ctx.filePath)], { cwd });
|
|
55
|
-
if (result
|
|
56
|
+
if (spawnFailedWithNoOutput(result)) {
|
|
56
57
|
return { status: "skipped", diagnostics: [], semantic: "none" };
|
|
57
58
|
}
|
|
58
59
|
const output = result.stdout || "";
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import * as path from "node:path";
|
|
2
|
+
import { PathKeyedMap } from "../../path-keyed-map.js";
|
|
3
|
+
import { normalizeMapKey } from "../../path-utils.js";
|
|
4
|
+
import { safeSpawnAsync } from "../../safe-spawn.js";
|
|
5
|
+
import { findNearestDirWithMarker } from "../../workspace-topology.js";
|
|
6
|
+
import { PRIORITY } from "../priorities.js";
|
|
7
|
+
import { createAvailabilityChecker, resolveAvailableOrInstall, } from "./utils/runner-helpers.js";
|
|
8
|
+
const helm = createAvailabilityChecker("helm", ".exe");
|
|
9
|
+
const inFlightByChartRoot = new PathKeyedMap(normalizeMapKey);
|
|
10
|
+
const HELM_LINT_TIMEOUT_MS = 30_000;
|
|
11
|
+
const SKIPPED = {
|
|
12
|
+
status: "skipped",
|
|
13
|
+
diagnostics: [],
|
|
14
|
+
semantic: "none",
|
|
15
|
+
};
|
|
16
|
+
function isWithin(root, candidate) {
|
|
17
|
+
const relative = path.relative(normalizeMapKey(root), normalizeMapKey(candidate));
|
|
18
|
+
return relative === "" || (!relative.startsWith(`..${path.sep}`) && relative !== ".." && !path.isAbsolute(relative));
|
|
19
|
+
}
|
|
20
|
+
function diagnosticLocation(message, chartRoot) {
|
|
21
|
+
const location = message.match(/(?:^|\s)([^:\r\n]+\.(?:ya?ml|tpl|json))(?::(\d+))?(?::\d+)?(?::|\s)/i);
|
|
22
|
+
if (!location) {
|
|
23
|
+
return { filePath: path.join(chartRoot, "Chart.yaml"), message };
|
|
24
|
+
}
|
|
25
|
+
const candidate = path.resolve(chartRoot, location[1]);
|
|
26
|
+
return {
|
|
27
|
+
filePath: isWithin(chartRoot, candidate)
|
|
28
|
+
? candidate
|
|
29
|
+
: path.join(chartRoot, "Chart.yaml"),
|
|
30
|
+
line: location[2] ? Number(location[2]) : undefined,
|
|
31
|
+
message,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export function parseHelmLintOutput(raw, chartRoot) {
|
|
35
|
+
const diagnostics = [];
|
|
36
|
+
for (const line of raw.split(/\r?\n/)) {
|
|
37
|
+
const match = line.trim().match(/^\[(INFO|WARNING|ERROR)\]\s*(.+)$/);
|
|
38
|
+
if (!match) {
|
|
39
|
+
// helm indents multi-line diagnostic detail under its [LEVEL] header
|
|
40
|
+
// (#1342 review): fold continuation text into the open diagnostic
|
|
41
|
+
// instead of silently dropping it.
|
|
42
|
+
const last = diagnostics[diagnostics.length - 1];
|
|
43
|
+
if (last && /^\s+\S/.test(line)) {
|
|
44
|
+
last.message += `
|
|
45
|
+
${line.trim()}`;
|
|
46
|
+
}
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
const level = match[1];
|
|
50
|
+
const location = diagnosticLocation(match[2].trim(), chartRoot);
|
|
51
|
+
const severity = level === "ERROR" ? "error" : level === "WARNING" ? "warning" : "info";
|
|
52
|
+
diagnostics.push({
|
|
53
|
+
id: `helm-lint-${diagnostics.length + 1}-${level.toLowerCase()}`,
|
|
54
|
+
message: location.message,
|
|
55
|
+
filePath: location.filePath,
|
|
56
|
+
line: location.line,
|
|
57
|
+
column: 1,
|
|
58
|
+
severity,
|
|
59
|
+
semantic: severity === "error" ? "blocking" : "warning",
|
|
60
|
+
tool: "helm-lint",
|
|
61
|
+
rule: level.toLowerCase(),
|
|
62
|
+
fixable: false,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
return diagnostics;
|
|
66
|
+
}
|
|
67
|
+
function failedResult(kind, message) {
|
|
68
|
+
return {
|
|
69
|
+
status: "failed",
|
|
70
|
+
diagnostics: [],
|
|
71
|
+
semantic: "warning",
|
|
72
|
+
failureKind: kind,
|
|
73
|
+
failureMessage: message.slice(0, 200),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
async function lintChart(chartRoot, cwd) {
|
|
77
|
+
const cmd = await resolveAvailableOrInstall(helm, "helm", cwd);
|
|
78
|
+
if (!cmd) {
|
|
79
|
+
const outcome = helm.getOutcome(cwd);
|
|
80
|
+
return {
|
|
81
|
+
status: "failed",
|
|
82
|
+
diagnostics: [],
|
|
83
|
+
semantic: "warning",
|
|
84
|
+
failureKind: "unavailable",
|
|
85
|
+
failureMessage: `helm unavailable (${outcome ?? "unknown"})`,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
const result = await safeSpawnAsync(cmd, ["lint", chartRoot], {
|
|
89
|
+
cwd,
|
|
90
|
+
timeout: HELM_LINT_TIMEOUT_MS,
|
|
91
|
+
deadlineAt: Date.now() + HELM_LINT_TIMEOUT_MS,
|
|
92
|
+
resourceLabel: "helm-lint",
|
|
93
|
+
});
|
|
94
|
+
const output = [result.stdout, result.stderr].filter(Boolean).join("\n");
|
|
95
|
+
const diagnostics = parseHelmLintOutput(output, chartRoot);
|
|
96
|
+
const typedFailure = result.spawnFailure?.kind;
|
|
97
|
+
if (typedFailure) {
|
|
98
|
+
const failureKind = typedFailure === "tool-not-found"
|
|
99
|
+
? "unavailable"
|
|
100
|
+
: typedFailure === "timeout"
|
|
101
|
+
? "timeout"
|
|
102
|
+
: typedFailure === "killed" && result.failure === "aborted"
|
|
103
|
+
? "aborted"
|
|
104
|
+
: "server_error";
|
|
105
|
+
return failedResult(failureKind, result.error?.message || `helm lint ${typedFailure}`);
|
|
106
|
+
}
|
|
107
|
+
if (result.failure) {
|
|
108
|
+
return failedResult(result.failure === "timeout" ? "timeout" : result.failure, result.error?.message || `helm lint ${result.failure}`);
|
|
109
|
+
}
|
|
110
|
+
if (result.outputTruncated) {
|
|
111
|
+
return failedResult("parser_error", "helm lint output was truncated before parsing completed");
|
|
112
|
+
}
|
|
113
|
+
const hasErrorDiagnostic = diagnostics.some((diagnostic) => diagnostic.severity === "error");
|
|
114
|
+
if (result.status !== 0 && !hasErrorDiagnostic) {
|
|
115
|
+
return failedResult(output.trim() ? "parser_error" : "server_error", output.trim() || "helm lint exited without an error diagnostic");
|
|
116
|
+
}
|
|
117
|
+
return {
|
|
118
|
+
status: "succeeded",
|
|
119
|
+
diagnostics,
|
|
120
|
+
semantic: diagnostics.some((item) => item.severity === "error")
|
|
121
|
+
? "blocking"
|
|
122
|
+
: diagnostics.length > 0
|
|
123
|
+
? "warning"
|
|
124
|
+
: "none",
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
const helmLintRunner = {
|
|
128
|
+
id: "helm-lint",
|
|
129
|
+
appliesTo: ["yaml", "helm-template"],
|
|
130
|
+
priority: PRIORITY.GENERAL_ANALYSIS,
|
|
131
|
+
enabledByDefault: true,
|
|
132
|
+
skipTestFiles: false,
|
|
133
|
+
timeoutMs: 35_000,
|
|
134
|
+
async run(ctx) {
|
|
135
|
+
const workspaceRoot = path.resolve(ctx.projectRoot ?? ctx.cwd);
|
|
136
|
+
const startDir = path.dirname(path.resolve(ctx.filePath));
|
|
137
|
+
const discovered = findNearestDirWithMarker(startDir, "chartYamlPath");
|
|
138
|
+
if (!discovered)
|
|
139
|
+
return SKIPPED;
|
|
140
|
+
const chartRoot = path.resolve(discovered);
|
|
141
|
+
if (!isWithin(workspaceRoot, chartRoot))
|
|
142
|
+
return SKIPPED;
|
|
143
|
+
const existing = inFlightByChartRoot.get(chartRoot);
|
|
144
|
+
if (existing)
|
|
145
|
+
return existing;
|
|
146
|
+
const promise = lintChart(chartRoot, ctx.cwd).finally(() => {
|
|
147
|
+
if (inFlightByChartRoot.get(chartRoot) === promise)
|
|
148
|
+
inFlightByChartRoot.delete(chartRoot);
|
|
149
|
+
});
|
|
150
|
+
inFlightByChartRoot.set(chartRoot, promise);
|
|
151
|
+
return promise;
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
export default helmLintRunner;
|
|
@@ -3,6 +3,7 @@ import { safeSpawnAsync } from "../../safe-spawn.js";
|
|
|
3
3
|
import { getLinterPolicyForCwd } from "../../tool-policy.js";
|
|
4
4
|
import { PRIORITY } from "../priorities.js";
|
|
5
5
|
import { createAvailabilityChecker, resolveToolCommandWithInstallFallback, } from "./utils/runner-helpers.js";
|
|
6
|
+
import { spawnFailedWithNoOutput } from "./utils/spawn-outcome.js";
|
|
6
7
|
const htmlhint = createAvailabilityChecker("htmlhint");
|
|
7
8
|
const HTMLHINT_RULES = {
|
|
8
9
|
"tag-pair": true,
|
|
@@ -71,10 +72,10 @@ const htmlhintRunner = {
|
|
|
71
72
|
"unix",
|
|
72
73
|
path.resolve(cwd, ctx.filePath),
|
|
73
74
|
], { cwd });
|
|
74
|
-
|
|
75
|
+
const output = result.stdout || result.stderr || "";
|
|
76
|
+
if (spawnFailedWithNoOutput(result, output)) {
|
|
75
77
|
return { status: "skipped", diagnostics: [], semantic: "none" };
|
|
76
78
|
}
|
|
77
|
-
const output = result.stdout || result.stderr || "";
|
|
78
79
|
const diagnostics = parseHtmlhintOutput(output, ctx.filePath);
|
|
79
80
|
if (diagnostics.length === 0) {
|
|
80
81
|
return { status: "succeeded", diagnostics: [], semantic: "none" };
|
|
@@ -16,6 +16,7 @@ import gleamCheckRunner from "./gleam-check.js";
|
|
|
16
16
|
import goVetRunner from "./go-vet.js";
|
|
17
17
|
import golangciRunner from "./golangci-lint.js";
|
|
18
18
|
import hadolintRunner from "./hadolint.js";
|
|
19
|
+
import helmLintRunner from "./helm-lint.js";
|
|
19
20
|
import htmlhintRunner from "./htmlhint.js";
|
|
20
21
|
import javacRunner from "./javac.js";
|
|
21
22
|
import ktlintRunner from "./ktlint.js";
|
|
@@ -40,6 +41,7 @@ import sqlfluffRunner from "./sqlfluff.js";
|
|
|
40
41
|
import stylelintRunner from "./stylelint.js";
|
|
41
42
|
import swiftlintRunner from "./swiftlint.js";
|
|
42
43
|
import taploRunner from "./taplo.js";
|
|
44
|
+
import terragruntRunner from "./terragrunt.js";
|
|
43
45
|
import tflintRunner from "./tflint.js";
|
|
44
46
|
import trivyConfigRunner from "./trivy-config.js";
|
|
45
47
|
import valeRunner from "./vale.js";
|
|
@@ -81,6 +83,7 @@ export function registerDefaultRunners(registry) {
|
|
|
81
83
|
registry.register(factRulesRunner); // FactRule pipeline — all registered rules (priority 21)
|
|
82
84
|
registry.register(htmlhintRunner); // HTML linting — tag pairs, attribute rules (priority 20)
|
|
83
85
|
registry.register(hadolintRunner); // Dockerfile linting — syntax, best practices (priority 20)
|
|
86
|
+
registry.register(helmLintRunner); // Helm chart linting (priority 20)
|
|
84
87
|
registry.register(valeRunner); // Prose/style linting for Markdown — config-gated (.vale.ini) (priority 30)
|
|
85
88
|
registry.register(phpLintRunner); // PHP syntax validation via php -l (priority 20)
|
|
86
89
|
registry.register(psScriptAnalyzerRunner); // PowerShell linting via PSScriptAnalyzer module (priority 20)
|
|
@@ -88,7 +91,8 @@ export function registerDefaultRunners(registry) {
|
|
|
88
91
|
registry.register(ktlintRunner); // Kotlin linting via ktlint (priority 10)
|
|
89
92
|
registry.register(detektRunner); // Kotlin static analysis via detekt (priority 20, config-gated)
|
|
90
93
|
registry.register(tflintRunner); // Terraform linting via tflint (priority 20)
|
|
91
|
-
registry.register(
|
|
94
|
+
registry.register(terragruntRunner); // Terragrunt linting via terragrunt hcl validate (priority 20)
|
|
95
|
+
registry.register(trivyConfigRunner); // IaC misconfig (Dockerfile/k8s/Terraform) via trivy config (priority 20, trivy.enabled-gated)
|
|
92
96
|
registry.register(taploRunner); // TOML linting/validation via taplo (priority 10)
|
|
93
97
|
registry.register(dartAnalyzeRunner); // Dart analysis via dart analyze (priority 20)
|
|
94
98
|
registry.register(javacRunner); // Java compile diagnostics via javac (priority 20)
|