pi-lens 4.1.2 → 4.1.4
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/CHANGELOG.md +1308 -0
- package/README.md +3 -0
- package/config/biome/core.jsonc +11 -2
- package/config/dependency-cruiser-eager-allowlist.json +91 -0
- package/dist/clients/actionable-warnings-logger.js +18 -3
- package/dist/clients/actionable-warnings.js +927 -80
- package/dist/clients/agent-behavior-client.js +13 -4
- package/dist/clients/ast-grep-client.js +136 -9
- package/dist/clients/ast-grep-rule-manager.js +60 -5
- package/dist/clients/ast-grep-tool-logger.js +2 -2
- package/dist/clients/availability-probe-flight.js +12 -0
- package/dist/clients/bash-file-access.js +1 -3
- package/dist/clients/biome-client.js +16 -2
- package/dist/clients/blocker-freshness.js +34 -0
- package/dist/clients/bootstrap.js +509 -73
- package/dist/clients/bounded-cache.js +152 -12
- package/dist/clients/bounded-telemetry.js +115 -23
- package/dist/clients/build-identity.js +95 -0
- package/dist/clients/bundled-resource-health.js +113 -0
- package/dist/clients/bus-events-logger.js +2 -2
- package/dist/clients/bus-publish.js +3 -0
- package/dist/clients/cache/rule-cache.js +33 -5
- package/dist/clients/cache-manager.js +105 -6
- package/dist/clients/cache-observability.js +46 -19
- package/dist/clients/cargo-manifest.js +422 -0
- package/dist/clients/cascade-logger.js +17 -3
- package/dist/clients/code-quality-warnings.js +13 -3
- package/dist/clients/complexity-client.js +16 -5
- package/dist/clients/config-core/deny.js +221 -0
- package/dist/clients/config-core/index.js +47 -0
- package/dist/clients/config-core/merge.js +357 -0
- package/dist/clients/config-core/normalize.js +340 -0
- package/dist/clients/config-core/process-spec.js +248 -0
- package/dist/clients/config-core/provenance.js +171 -0
- package/dist/clients/config-core/records.js +218 -0
- package/dist/clients/config-core/resolve.js +125 -0
- package/dist/clients/config-core/safe-object.js +78 -0
- package/dist/clients/config-core/schema.js +167 -0
- package/dist/clients/config-diagnostic-codes.js +281 -0
- package/dist/clients/config-locations.js +160 -0
- package/dist/clients/config-resolve.js +789 -0
- package/dist/clients/config-schema.js +197 -0
- package/dist/clients/config-warn.js +407 -0
- package/dist/clients/dead-code-client.js +33 -25
- package/dist/clients/dead-code-logger.js +2 -2
- package/dist/clients/deadline-utils.js +178 -0
- package/dist/clients/debug-handles.js +2 -2
- package/dist/clients/debug-heap.js +3 -3
- package/dist/clients/deferred-lsp-work.js +106 -0
- package/dist/clients/degradation-ledger.js +166 -8
- package/dist/clients/demoted-finding-render.js +14 -0
- package/dist/clients/dependency-checker.js +28 -22
- package/dist/clients/deps/minimatch.js +1 -1
- package/dist/clients/diagnostic-line-freshness.js +12 -9
- package/dist/clients/diagnostic-logger.js +14 -4
- package/dist/clients/dispatch/collect-later-tier.js +39 -0
- package/dist/clients/dispatch/dispatcher.js +304 -19
- package/dist/clients/dispatch/fact-store.js +328 -9
- package/dist/clients/dispatch/integration.js +214 -107
- package/dist/clients/dispatch/pending-runner-findings.js +87 -0
- package/dist/clients/dispatch/plan.js +21 -5
- package/dist/clients/dispatch/runners/actionlint.js +0 -1
- package/dist/clients/dispatch/runners/ast-grep-napi.js +550 -77
- package/dist/clients/dispatch/runners/biome-check.js +0 -1
- package/dist/clients/dispatch/runners/cpp-check.js +0 -1
- package/dist/clients/dispatch/runners/credo.js +0 -1
- package/dist/clients/dispatch/runners/cue-vet.js +0 -1
- package/dist/clients/dispatch/runners/dart-analyze.js +0 -1
- package/dist/clients/dispatch/runners/detekt.js +0 -1
- package/dist/clients/dispatch/runners/dotnet-build.js +0 -1
- package/dist/clients/dispatch/runners/elixir-check.js +0 -1
- package/dist/clients/dispatch/runners/eslint.js +5 -2
- package/dist/clients/dispatch/runners/fact-rules.js +0 -1
- package/dist/clients/dispatch/runners/fish-indent.js +0 -1
- package/dist/clients/dispatch/runners/gleam-check.js +0 -1
- package/dist/clients/dispatch/runners/go-vet.js +1 -3
- package/dist/clients/dispatch/runners/golangci-lint.js +0 -1
- package/dist/clients/dispatch/runners/hadolint.js +0 -1
- package/dist/clients/dispatch/runners/helm-lint.js +16 -4
- package/dist/clients/dispatch/runners/helm-render.js +54 -10
- package/dist/clients/dispatch/runners/htmlhint.js +0 -1
- package/dist/clients/dispatch/runners/index.js +1 -3
- package/dist/clients/dispatch/runners/javac.js +0 -1
- package/dist/clients/dispatch/runners/ktlint.js +0 -1
- package/dist/clients/dispatch/runners/lsp.js +37 -2
- package/dist/clients/dispatch/runners/markdownlint.js +4 -2
- package/dist/clients/dispatch/runners/mypy.js +0 -1
- package/dist/clients/dispatch/runners/oxlint.js +24 -22
- package/dist/clients/dispatch/runners/php-lint.js +0 -1
- package/dist/clients/dispatch/runners/phpstan.js +0 -1
- package/dist/clients/dispatch/runners/prisma-validate.js +0 -1
- package/dist/clients/dispatch/runners/psscriptanalyzer.js +4 -1
- package/dist/clients/dispatch/runners/pyright.js +7 -4
- package/dist/clients/dispatch/runners/rubocop.js +0 -1
- package/dist/clients/dispatch/runners/ruff.js +0 -1
- package/dist/clients/dispatch/runners/rust-clippy.js +9 -6
- package/dist/clients/dispatch/runners/shellcheck.js +0 -1
- package/dist/clients/dispatch/runners/shfmt.js +0 -1
- package/dist/clients/dispatch/runners/spellcheck.js +0 -1
- package/dist/clients/dispatch/runners/spotbugs.js +0 -1
- package/dist/clients/dispatch/runners/sqlfluff.js +0 -1
- package/dist/clients/dispatch/runners/stylelint.js +0 -1
- package/dist/clients/dispatch/runners/swiftlint.js +0 -1
- package/dist/clients/dispatch/runners/taplo.js +0 -1
- package/dist/clients/dispatch/runners/terragrunt.js +0 -1
- package/dist/clients/dispatch/runners/tflint.js +0 -1
- package/dist/clients/dispatch/runners/tree-sitter.js +0 -1
- package/dist/clients/dispatch/runners/trivy-config.js +0 -1
- package/dist/clients/dispatch/runners/utils/availability-policy.js +3 -0
- package/dist/clients/dispatch/runners/utils/diagnostic-parsers.js +3 -4
- package/dist/clients/dispatch/runners/utils/runner-helpers.js +270 -105
- package/dist/clients/dispatch/runners/utils/spawn-outcome.js +4 -0
- package/dist/clients/dispatch/runners/utils/tool-failure.js +19 -7
- package/dist/clients/dispatch/runners/utils/toolchain-availability.js +89 -26
- package/dist/clients/dispatch/runners/vale.js +0 -1
- package/dist/clients/dispatch/runners/yaml-rule-parser.js +51 -17
- package/dist/clients/dispatch/runners/yamllint.js +0 -1
- package/dist/clients/dispatch/runners/zig-check.js +0 -1
- package/dist/clients/disposition-logger.js +3 -3
- package/dist/clients/effective-config.js +403 -0
- package/dist/clients/error-class.js +23 -0
- package/dist/clients/event-loop-hold.js +274 -0
- package/dist/clients/event-loop-monitor.js +66 -1
- package/dist/clients/extension-log.js +2 -2
- package/dist/clients/feature-hints.js +2 -1
- package/dist/clients/file-time.js +6 -1
- package/dist/clients/file-utils.js +266 -13
- package/dist/clients/finding-delivery-gate.js +55 -13
- package/dist/clients/format-service.js +6 -1
- package/dist/clients/formatters.js +303 -104
- package/dist/clients/freshness-cadence.js +17 -0
- package/dist/clients/generated-artifacts.js +114 -19
- package/dist/clients/generation-guard.js +4 -9
- package/dist/clients/git-guard.js +198 -48
- package/dist/clients/git-tracked-ignore.js +32 -1
- package/dist/clients/go-client.js +39 -0
- package/dist/clients/govulncheck-client.js +5 -1
- package/dist/clients/gradle-ktfmt-style.js +252 -0
- package/dist/clients/gzip-stage-write.js +7 -0
- package/dist/clients/hashline-anchor.js +424 -0
- package/dist/clients/hook-budgets.js +76 -0
- package/dist/clients/host-edit-normalize.js +5 -2
- package/dist/clients/host-ports.js +1 -1
- package/dist/clients/installer/index.js +200 -84
- package/dist/clients/installer/managed-tool-refresh.js +3 -1
- package/dist/clients/instance-reaper.js +108 -243
- package/dist/clients/instance-registry-lock.js +145 -0
- package/dist/clients/instance-registry.js +435 -122
- package/dist/clients/jscpd-client.js +6 -1
- package/dist/clients/language-profile.js +4 -2
- package/dist/clients/language-registry.js +595 -0
- package/dist/clients/latency-logger.js +179 -3
- package/dist/clients/ledger-bounds.js +13 -0
- package/dist/clients/lens-config.js +141 -30
- package/dist/clients/lens-engine.js +30 -37
- package/dist/clients/lens-flag-registry.js +67 -6
- package/dist/clients/lens-map.js +3 -1
- package/dist/clients/log-cleanup.js +2 -2
- package/dist/clients/lsp/aggregation.js +3 -1
- package/dist/clients/lsp/cascade-tier.js +4 -0
- package/dist/clients/lsp/client.js +672 -49
- package/dist/clients/lsp/config.js +504 -156
- package/dist/clients/lsp/diagnostic-binding.js +10 -5
- package/dist/clients/lsp/edits.js +15 -2
- package/dist/clients/lsp/index.js +1179 -247
- package/dist/clients/lsp/jvm-runtime.js +5 -0
- package/dist/clients/lsp/language.js +18 -169
- package/dist/clients/lsp/launch.js +38 -9
- package/dist/clients/lsp/pending-aux-coverage.js +113 -12
- package/dist/clients/lsp/server.js +426 -160
- package/dist/clients/lsp/session-roots.js +192 -0
- package/dist/clients/lsp/spawn-history.js +2 -7
- package/dist/clients/lsp/tsserver-sync.js +9 -2
- package/dist/clients/lsp/workspace-diagnostics-cache.js +17 -7
- package/dist/clients/lsp/workspace-sweep-hold.js +32 -23
- package/dist/clients/lsp-mutation.js +179 -23
- package/dist/clients/map-with-concurrency.js +36 -0
- package/dist/clients/mcp/analyze.js +45 -10
- package/dist/clients/mcp/session.js +19 -17
- package/dist/clients/memory-sampler.js +28 -1
- package/dist/clients/message-end-attribution.js +30 -0
- package/dist/clients/metrics-history.js +21 -4
- package/dist/clients/middle-man-analysis.js +2 -4
- package/dist/clients/module-report.js +20 -45
- package/dist/clients/mutating-tool.js +651 -0
- package/dist/clients/mutation-attribution.js +368 -0
- package/dist/clients/mutation-bridge.js +240 -0
- package/dist/clients/ndjson-logger.js +247 -20
- package/dist/clients/observed-mutation-sources.js +101 -0
- package/dist/clients/observed-mutation.js +1215 -0
- package/dist/clients/opaque-mutation-scan.js +300 -40
- package/dist/clients/opengrep-config.js +4 -0
- package/dist/clients/package-manager.js +201 -44
- package/dist/clients/partial-edit-apply.js +359 -80
- package/dist/clients/path-attribution-telemetry.js +23 -7
- package/dist/clients/path-keyed-map.js +35 -3
- package/dist/clients/path-utils.js +460 -13
- package/dist/clients/persist-debounce.js +8 -1
- package/dist/clients/php-cs-fixer-config.js +114 -0
- package/dist/clients/pipeline.js +77 -24
- package/dist/clients/probe-home-state.js +228 -0
- package/dist/clients/process-bridge.js +66 -0
- package/dist/clients/process-singletons.js +210 -0
- package/dist/clients/process-snapshot.js +68 -0
- package/dist/clients/project-diagnostics/fresh-fetch.js +4 -3
- package/dist/clients/project-diagnostics/runner-adapters/madge.js +2 -1
- package/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +27 -3
- package/dist/clients/project-diagnostics/scanner.js +61 -24
- package/dist/clients/project-lens-config.js +393 -122
- package/dist/clients/project-snapshot.js +85 -35
- package/dist/clients/python-environment.js +217 -0
- package/dist/clients/python-provenance.js +639 -0
- package/dist/clients/quiet-window.js +6 -1
- package/dist/clients/read-bridge.js +13 -21
- package/dist/clients/read-expansion.js +9 -46
- package/dist/clients/read-guard-logger.js +39 -6
- package/dist/clients/read-guard-tool-lines.js +364 -212
- package/dist/clients/read-guard.js +95 -7
- package/dist/clients/recent-touches.js +17 -5
- package/dist/clients/resource-sampler.js +195 -96
- package/dist/clients/review-graph/builder.js +752 -132
- package/dist/clients/review-graph/service.js +55 -3
- package/dist/clients/review-graph/shared-extraction-ir.js +7 -15
- package/dist/clients/review-graph/tsconfig-paths.js +5 -1
- package/dist/clients/review-graph/workspace-modules.js +10 -74
- package/dist/clients/review-graph-logger.js +30 -4
- package/dist/clients/runtime-agent-end.js +18 -2
- package/dist/clients/runtime-context.js +49 -16
- package/dist/clients/runtime-coordinator.js +93 -6
- package/dist/clients/runtime-session.js +169 -34
- package/dist/clients/runtime-tool-call.js +183 -35
- package/dist/clients/runtime-tool-result.js +894 -241
- package/dist/clients/runtime-turn.js +1264 -74
- package/dist/clients/rust-client.js +31 -0
- package/dist/clients/safe-spawn.js +191 -28
- package/dist/clients/sanitize.js +7 -1
- package/dist/clients/scratch-tree-policy.js +1 -3
- package/dist/clients/security-scan-client.js +51 -17
- package/dist/clients/session-lifecycle.js +238 -42
- package/dist/clients/session-start-observability.js +79 -0
- package/dist/clients/sessionstart-logger.js +12 -3
- package/dist/clients/sg-runner.js +27 -15
- package/dist/clients/sgconfig.js +6 -1
- package/dist/clients/shared-checkout-guard.js +338 -0
- package/dist/clients/skills-resolver.js +105 -0
- package/dist/clients/smells-rollup.js +2 -2
- package/dist/clients/spawn-output-cap.js +37 -0
- package/dist/clients/spawn-timeout-cooldown.js +15 -1
- package/dist/clients/startup-scan.js +6 -7
- package/dist/clients/startup-timing.js +69 -4
- package/dist/clients/string-utils.js +33 -0
- package/dist/clients/subagent-mode.js +17 -4
- package/dist/clients/test-runner-client.js +586 -118
- package/dist/clients/test-runner-delivery.js +239 -0
- package/dist/clients/tool-definition.js +41 -1
- package/dist/clients/tool-policy.js +92 -22
- package/dist/clients/tree-sitter-cache.js +40 -40
- package/dist/clients/tree-sitter-client.js +97 -53
- package/dist/clients/tree-sitter-logger.js +19 -3
- package/dist/clients/tree-sitter-query-loader.js +81 -1
- package/dist/clients/tree-sitter-shared.js +51 -46
- package/dist/clients/tree-sitter-symbol-extractor.js +28 -0
- package/dist/clients/typos-config.js +5 -0
- package/dist/clients/user-notify.js +6 -2
- package/dist/clients/warm-attach.js +8 -10
- package/dist/clients/widget-state.js +191 -26
- package/dist/clients/word-index-logger.js +15 -3
- package/dist/clients/word-index-store.js +463 -0
- package/dist/clients/word-index.js +815 -125
- package/dist/clients/workspace-topology.js +25 -1
- package/dist/clients/zizmor-config.js +29 -6
- package/dist/index.js +68577 -53950
- package/dist/mcp/analyze-cli.js +3 -1
- package/dist/mcp/build-staleness.js +8 -7
- package/dist/mcp/cli.js +3 -1
- package/dist/mcp/server.js +133 -6
- package/dist/scripts/lib/process-scan.mjs +583 -0
- package/dist/scripts/lib/skills-predicate.mjs +129 -0
- package/dist/tools/effective-config.js +89 -0
- package/dist/tools/lens-diagnostics.js +99 -24
- package/dist/tools/lsp-diagnostics.js +81 -85
- package/dist/tools/lsp-navigation.js +40 -17
- package/dist/tools/shared.js +0 -1
- package/docs/agent-guide.md +68 -3
- package/docs/ast-grep_rules_catalog.md +41 -10
- package/docs/astplayground.md +26 -17
- package/docs/configuration.md +222 -0
- package/docs/dependencies.md +3 -3
- package/docs/features.md +44 -5
- package/docs/language-coverage.md +2 -2
- package/docs/pi-lens-fixer.md +25 -0
- package/docs/pi-lens-investigator.md +25 -0
- package/docs/pi-lens-reviewer.md +27 -0
- package/docs/pi-lens-subagent.md +38 -0
- package/docs/pi-lens-warden.md +55 -0
- package/docs/public-api-stability.md +359 -0
- package/docs/release-qa-baseline.md +182 -0
- package/docs/subagent-compat.md +110 -30
- package/docs/tree-sitter_rules_catalog.md +2 -2
- package/package.json +17 -21
- package/rules/ast-grep-rules/rule-tests/c-no-malloc-free-test.yml +20 -0
- package/rules/ast-grep-rules/rule-tests/cpp-no-malloc-free-test.yml +25 -0
- package/rules/ast-grep-rules/rule-tests/cpp-no-printf-test.yml +19 -0
- package/rules/ast-grep-rules/rule-tests/go-no-fmt-println-test.yml +19 -0
- package/rules/ast-grep-rules/rule-tests/go-no-panic-in-lib-test.yml +17 -0
- package/rules/ast-grep-rules/rule-tests/go-no-underscore-func-name-test.yml +18 -0
- package/rules/ast-grep-rules/rule-tests/go-prefer-errors-is-test.yml +15 -0
- package/rules/ast-grep-rules/rule-tests/go-prefer-string-builder-test.yml +21 -0
- package/rules/ast-grep-rules/rule-tests/hyphenated-svg-attribute-test.yml +11 -0
- package/rules/ast-grep-rules/rule-tests/kotlin-no-lateinit-test.yml +17 -0
- package/rules/ast-grep-rules/rule-tests/kotlin-no-nullable-boolean-test.yml +15 -0
- package/rules/ast-grep-rules/rule-tests/kotlin-no-println-test.yml +19 -0
- package/rules/ast-grep-rules/rule-tests/kotlin-no-unnecessary-let-test.yml +7 -0
- package/rules/ast-grep-rules/rule-tests/kotlin-no-unsafe-cast-test.yml +7 -0
- package/rules/ast-grep-rules/rule-tests/kotlin-no-var-test.yml +7 -0
- package/rules/ast-grep-rules/rule-tests/kotlin-prefer-data-class-test.yml +25 -0
- package/rules/ast-grep-rules/rule-tests/kotlin-prefer-is-empty-test.yml +11 -0
- package/rules/ast-grep-rules/rule-tests/no-important-test.yml +21 -0
- package/rules/ast-grep-rules/rule-tests/no-raw-types-test.yml +30 -0
- package/rules/ast-grep-rules/rule-tests/no-string-concat-in-loop-test.yml +100 -0
- package/rules/ast-grep-rules/rule-tests/no-system-out-println-test.yml +7 -0
- package/rules/ast-grep-rules/rule-tests/prefer-string-is-empty-test.yml +7 -0
- package/rules/ast-grep-rules/rule-tests/python-optional-type-test.yml +9 -0
- package/rules/ast-grep-rules/rule-tests/reducible-list-comprehension-test.yml +11 -0
- package/rules/ast-grep-rules/rule-tests/ruby-symbol-to-proc-candidate-test.yml +10 -0
- package/rules/ast-grep-rules/rule-tests/rust-no-chars-enumerate-test.yml +7 -0
- package/rules/ast-grep-rules/rules/c-no-malloc-free.yml +39 -0
- package/rules/ast-grep-rules/rules/cpp-no-malloc-free.yml +45 -0
- package/rules/ast-grep-rules/rules/cpp-no-printf.yml +41 -0
- package/rules/ast-grep-rules/rules/go-no-fmt-println.yml +43 -0
- package/rules/ast-grep-rules/rules/go-no-panic-in-lib.yml +41 -0
- package/rules/ast-grep-rules/rules/go-no-underscore-func-name.yml +35 -0
- package/rules/ast-grep-rules/rules/go-prefer-errors-is.yml +40 -0
- package/rules/ast-grep-rules/rules/go-prefer-string-builder.yml +43 -0
- package/rules/ast-grep-rules/rules/hyphenated-svg-attribute.yml +32 -0
- package/rules/ast-grep-rules/rules/kotlin-no-lateinit.yml +37 -0
- package/rules/ast-grep-rules/rules/kotlin-no-nullable-boolean.yml +33 -0
- package/rules/ast-grep-rules/rules/kotlin-no-println.yml +42 -0
- package/rules/ast-grep-rules/rules/kotlin-no-unnecessary-let.yml +28 -0
- package/rules/ast-grep-rules/rules/kotlin-no-unsafe-cast.yml +28 -0
- package/rules/ast-grep-rules/rules/kotlin-no-var.yml +35 -0
- package/rules/ast-grep-rules/rules/kotlin-prefer-data-class.yml +66 -0
- package/rules/ast-grep-rules/rules/kotlin-prefer-is-empty.yml +35 -0
- package/rules/ast-grep-rules/rules/no-important.yml +21 -0
- package/rules/ast-grep-rules/rules/no-raw-types.yml +33 -0
- package/rules/ast-grep-rules/rules/no-string-concat-in-loop.yml +90 -0
- package/rules/ast-grep-rules/rules/no-system-out-println.yml +16 -0
- package/rules/ast-grep-rules/rules/prefer-string-is-empty.yml +11 -0
- package/rules/ast-grep-rules/rules/python-optional-type.yml +22 -0
- package/rules/ast-grep-rules/rules/reducible-list-comprehension.yml +29 -0
- package/rules/ast-grep-rules/rules/ruby-symbol-to-proc-candidate.yml +25 -0
- package/rules/ast-grep-rules/rules/rust-no-chars-enumerate.yml +19 -0
- package/rules/tree-sitter-queries/python/python-cross-language-method.yml +3 -3
- package/rules/tree-sitter-queries/python/python-hallucinated-import.yml +2 -2
- package/rules/tree-sitter-queries/python/python-sql-injection.yml +12 -2
- package/scripts/analyze-pi-lens-logs.mjs +192 -1
- package/scripts/install-selftest.mjs +58 -2
- package/scripts/lib/skills-predicate.mjs +129 -0
- package/scripts/rpc-load-check.mjs +3 -1
|
@@ -197,7 +197,6 @@ const biomeCheckJsonRunner = {
|
|
|
197
197
|
id: "biome-check-json",
|
|
198
198
|
appliesTo: ["jsts"],
|
|
199
199
|
priority: PRIORITY.FORMAT_AND_LINT_PRIMARY,
|
|
200
|
-
enabledByDefault: true,
|
|
201
200
|
async run(ctx) {
|
|
202
201
|
const cwd = ctx.cwd || path.dirname(ctx.filePath);
|
|
203
202
|
const policy = getJstsLintPolicyForCwd(cwd);
|
|
@@ -24,7 +24,11 @@ function makeEslintProbe(cmd) {
|
|
|
24
24
|
return createCwdCachedProbe((cwd) => safeSpawnAsync(cmd, ["--version"], {
|
|
25
25
|
timeout: ESLINT_PROBE_BUDGET_MS,
|
|
26
26
|
cwd,
|
|
27
|
-
}), {
|
|
27
|
+
}), {
|
|
28
|
+
tool: "eslint",
|
|
29
|
+
budgetMs: ESLINT_PROBE_BUDGET_MS,
|
|
30
|
+
flightKeyComponent: cmd,
|
|
31
|
+
});
|
|
28
32
|
}
|
|
29
33
|
const eslintAvailabilityByCmd = new Map();
|
|
30
34
|
function getEslintProbe(cmd) {
|
|
@@ -74,7 +78,6 @@ const eslintRunner = {
|
|
|
74
78
|
id: "eslint",
|
|
75
79
|
appliesTo: ["jsts"],
|
|
76
80
|
priority: PRIORITY.LINT_SECONDARY,
|
|
77
|
-
enabledByDefault: true,
|
|
78
81
|
async run(ctx) {
|
|
79
82
|
const cwd = ctx.cwd || process.cwd();
|
|
80
83
|
const userHasConfig = hasEslintConfig(cwd);
|
|
@@ -13,7 +13,6 @@ const factRulesRunner = {
|
|
|
13
13
|
id: "fact-rules",
|
|
14
14
|
appliesTo: ["jsts", "python", "go", "rust", "ruby", "shell", "cmake"],
|
|
15
15
|
priority: PRIORITY.GENERAL_ANALYSIS + 1,
|
|
16
|
-
enabledByDefault: true,
|
|
17
16
|
async run(ctx) {
|
|
18
17
|
const diagnostics = evaluateRules(ctx);
|
|
19
18
|
if (diagnostics.length === 0) {
|
|
@@ -4,18 +4,16 @@
|
|
|
4
4
|
* Runs `go vet` for Go files to catch common mistakes.
|
|
5
5
|
*/
|
|
6
6
|
import { relative, resolve, sep, posix } from "node:path";
|
|
7
|
-
import {
|
|
7
|
+
import { goClient } from "../../go-client.js";
|
|
8
8
|
import { safeSpawnAsync } from "../../safe-spawn.js";
|
|
9
9
|
import { stripAnsi } from "../../sanitize.js";
|
|
10
10
|
import { skipUnlessToolRan } from "./utils/tool-failure.js";
|
|
11
11
|
import { parseGoVetOutput } from "./utils/diagnostic-parsers.js";
|
|
12
12
|
import { PRIORITY } from "../priorities.js";
|
|
13
|
-
const goClient = new GoClient();
|
|
14
13
|
const goVetRunner = {
|
|
15
14
|
id: "go-vet",
|
|
16
15
|
appliesTo: ["go"],
|
|
17
16
|
priority: PRIORITY.SPECIALIZED_ANALYSIS,
|
|
18
|
-
enabledByDefault: true,
|
|
19
17
|
timeoutMs: 40_000,
|
|
20
18
|
async run(ctx) {
|
|
21
19
|
// Resolve go path using platform-aware lookup (handles system install paths on Windows)
|
|
@@ -2,12 +2,18 @@ import * as path from "node:path";
|
|
|
2
2
|
import { PathKeyedMap } from "../../path-keyed-map.js";
|
|
3
3
|
import { normalizeMapKey } from "../../path-utils.js";
|
|
4
4
|
import { safeSpawnAsync } from "../../safe-spawn.js";
|
|
5
|
+
import { truncatedByOutputCap } from "../../spawn-output-cap.js";
|
|
5
6
|
import { findNearestDirWithMarker } from "../../workspace-topology.js";
|
|
6
7
|
import { PRIORITY } from "../priorities.js";
|
|
7
8
|
import { createAvailabilityChecker, resolveAvailableOrInstall, } from "./utils/runner-helpers.js";
|
|
8
9
|
const helm = createAvailabilityChecker("helm", ".exe");
|
|
9
10
|
const inFlightByChartRoot = new PathKeyedMap(normalizeMapKey);
|
|
10
11
|
const HELM_LINT_TIMEOUT_MS = 30_000;
|
|
12
|
+
// `helm lint` prints one `[LEVEL]` line per finding for one chart, so nothing
|
|
13
|
+
// legitimate approaches 8 MiB: this bounds a wedged or runaway helm rather than
|
|
14
|
+
// real lint output, and it is what makes `outputTruncated` reachable for this
|
|
15
|
+
// runner at all (#2100). Same value as the sibling report caps.
|
|
16
|
+
const MAX_HELM_LINT_OUTPUT_BYTES = 8 * 1024 * 1024;
|
|
11
17
|
const SKIPPED = {
|
|
12
18
|
status: "skipped",
|
|
13
19
|
diagnostics: [],
|
|
@@ -93,7 +99,17 @@ async function lintChart(chartRoot, cwd) {
|
|
|
93
99
|
timeout: HELM_LINT_TIMEOUT_MS,
|
|
94
100
|
deadlineAt: Date.now() + HELM_LINT_TIMEOUT_MS,
|
|
95
101
|
resourceLabel: "helm-lint",
|
|
102
|
+
maxOutputBytes: MAX_HELM_LINT_OUTPUT_BYTES,
|
|
96
103
|
});
|
|
104
|
+
// FIRST (#2100): the cap kill is OUR SIGTERM, so it also sets
|
|
105
|
+
// `spawnFailure.kind === "killed"` and `failure === "signal"`. Read after
|
|
106
|
+
// those two, a truncated lint was reported as a server_error — helm blamed
|
|
107
|
+
// for output we threw away. A timed-out or aborted run carries
|
|
108
|
+
// `outputTruncated` too, and `truncatedByOutputCap` leaves those to the
|
|
109
|
+
// typed-failure block below so they keep reporting timeout/aborted.
|
|
110
|
+
if (truncatedByOutputCap(result)) {
|
|
111
|
+
return failedResult("parser_error", "helm lint output was truncated before parsing completed");
|
|
112
|
+
}
|
|
97
113
|
const output = [result.stdout, result.stderr].filter(Boolean).join("\n");
|
|
98
114
|
const diagnostics = parseHelmLintOutput(output, chartRoot);
|
|
99
115
|
const typedFailure = result.spawnFailure?.kind;
|
|
@@ -110,9 +126,6 @@ async function lintChart(chartRoot, cwd) {
|
|
|
110
126
|
if (result.failure) {
|
|
111
127
|
return failedResult(result.failure === "timeout" ? "timeout" : result.failure, result.error?.message || `helm lint ${result.failure}`);
|
|
112
128
|
}
|
|
113
|
-
if (result.outputTruncated) {
|
|
114
|
-
return failedResult("parser_error", "helm lint output was truncated before parsing completed");
|
|
115
|
-
}
|
|
116
129
|
const hasErrorDiagnostic = diagnostics.some((diagnostic) => diagnostic.severity === "error");
|
|
117
130
|
if (result.status !== 0 && !hasErrorDiagnostic) {
|
|
118
131
|
return failedResult(output.trim() ? "parser_error" : "server_error", output.trim() || "helm lint exited without an error diagnostic");
|
|
@@ -131,7 +144,6 @@ const helmLintRunner = {
|
|
|
131
144
|
id: "helm-lint",
|
|
132
145
|
appliesTo: ["yaml", "helm-template"],
|
|
133
146
|
priority: PRIORITY.GENERAL_ANALYSIS,
|
|
134
|
-
enabledByDefault: true,
|
|
135
147
|
skipTestFiles: false,
|
|
136
148
|
timeoutMs: 35_000,
|
|
137
149
|
async run(ctx) {
|
|
@@ -78,6 +78,7 @@ import { normalizeMapKey } from "../../path-utils.js";
|
|
|
78
78
|
import { loadPiLensProjectConfig } from "../../project-lens-config.js";
|
|
79
79
|
import { getProjectTrustState, projectTrustDenialReason, } from "../../project-trust.js";
|
|
80
80
|
import { safeSpawnAsync } from "../../safe-spawn.js";
|
|
81
|
+
import { killedForOutputCap, truncatedByOutputCap, } from "../../spawn-output-cap.js";
|
|
81
82
|
import { isTrivyEnabled, resolveSeverityFloor } from "../../trivy-client.js";
|
|
82
83
|
import { findNearestDirWithMarker } from "../../workspace-topology.js";
|
|
83
84
|
import { PRIORITY } from "../priorities.js";
|
|
@@ -100,6 +101,15 @@ const TRIVY_TIMEOUT_MS = 45_000;
|
|
|
100
101
|
const MAX_RENDERED_FILES = 400;
|
|
101
102
|
/** Bytes of trivy report we retain. Truncation is reported, never parsed past. */
|
|
102
103
|
const MAX_REPORT_BYTES = 8 * 1024 * 1024;
|
|
104
|
+
/**
|
|
105
|
+
* Bytes of `helm template` output we retain. The manifests go to `--output-dir`,
|
|
106
|
+
* so stdout is one short "wrote <path>" line per file — bounded near
|
|
107
|
+
* {@link MAX_RENDERED_FILES} — and stderr carries template errors. 8 MiB is
|
|
108
|
+
* therefore a blast-radius bound on a chart that loops or a helm that wedges,
|
|
109
|
+
* not a working limit, and it is what makes `render.outputTruncated` reachable
|
|
110
|
+
* at all (#2100).
|
|
111
|
+
*/
|
|
112
|
+
const MAX_RENDER_OUTPUT_BYTES = 8 * 1024 * 1024;
|
|
103
113
|
const SKIPPED = {
|
|
104
114
|
status: "skipped",
|
|
105
115
|
diagnostics: [],
|
|
@@ -661,6 +671,16 @@ export async function runIacPass(options) {
|
|
|
661
671
|
// hold in memory rather than trusting the chart's size (shape 9).
|
|
662
672
|
maxOutputBytes: MAX_REPORT_BYTES,
|
|
663
673
|
});
|
|
674
|
+
// FIRST (#2100): hitting the cap makes safe-spawn SIGTERM trivy, so a
|
|
675
|
+
// truncated report also arrives as a killed spawn with a null status. Read
|
|
676
|
+
// after the gate below, this said "the IaC pass failed" when what actually
|
|
677
|
+
// happened is that WE stopped reading. A timed-out or aborted scan carries
|
|
678
|
+
// the flag too and stays with the failure gate, which names its real cause.
|
|
679
|
+
if (truncatedByOutputCap(scan)) {
|
|
680
|
+
return [
|
|
681
|
+
coverageGap(chartRoot, "iac-report-unreadable", `Rendered-manifest IaC checks did not run: the trivy report exceeded ${MAX_REPORT_BYTES} bytes and was truncated before parsing.`),
|
|
682
|
+
];
|
|
683
|
+
}
|
|
664
684
|
const scanFailure = spawnFailureKind(scan);
|
|
665
685
|
// `trivy config` is not given `--exit-code`, so it exits 0 whenever it
|
|
666
686
|
// completed. ANY nonzero status is therefore a real error, with or without
|
|
@@ -673,11 +693,6 @@ export async function runIacPass(options) {
|
|
|
673
693
|
coverageGap(chartRoot, "iac-pass-failed", `Rendered-manifest IaC checks failed to complete (${why}): ${detail}`),
|
|
674
694
|
];
|
|
675
695
|
}
|
|
676
|
-
if (scan.outputTruncated) {
|
|
677
|
-
return [
|
|
678
|
-
coverageGap(chartRoot, "iac-report-unreadable", `Rendered-manifest IaC checks did not run: the trivy report exceeded ${MAX_REPORT_BYTES} bytes and was truncated before parsing.`),
|
|
679
|
-
];
|
|
680
|
-
}
|
|
681
696
|
const sourceByRendered = new PathKeyedMap(normalizeMapKey);
|
|
682
697
|
for (const manifest of options.manifests) {
|
|
683
698
|
sourceByRendered.set(manifest.renderedPath, {
|
|
@@ -754,7 +769,30 @@ async function renderAndValidate(chartRoot, cwd, filePath) {
|
|
|
754
769
|
timeout: RENDER_TIMEOUT_MS,
|
|
755
770
|
deadlineAt: Date.now() + RENDER_TIMEOUT_MS,
|
|
756
771
|
resourceLabel: "helm-render",
|
|
772
|
+
maxOutputBytes: MAX_RENDER_OUTPUT_BYTES,
|
|
757
773
|
});
|
|
774
|
+
const renderOutput = [render.stdout, render.stderr]
|
|
775
|
+
.filter(Boolean)
|
|
776
|
+
.join("\n");
|
|
777
|
+
// `killedForOutputCap` is platform-neutral. POSIX usually reports SIGTERM,
|
|
778
|
+
// but Windows reports status 1 with no failure or signal. A timed-out or
|
|
779
|
+
// aborted render retains its own classification.
|
|
780
|
+
const renderCapped = truncatedByOutputCap(render);
|
|
781
|
+
if (killedForOutputCap(render)) {
|
|
782
|
+
// helm was cut off mid-render, so the scratch tree is a PREFIX —
|
|
783
|
+
// reading it back would report the manifests we never saw as clean
|
|
784
|
+
// (shape 10). Not parsed as a chart failure either: helm never reported
|
|
785
|
+
// a verdict, and `parseHelmTemplateFailure` synthesizes a BLOCKING
|
|
786
|
+
// "helm template failed" finding when it sees no `Error:` line, which
|
|
787
|
+
// would blame the chart for our own cap (the #1487 inversion).
|
|
788
|
+
logRenderPass(filePath, chartRoot, startedAt, {
|
|
789
|
+
outcome: "render-truncated",
|
|
790
|
+
diagnostics: 1,
|
|
791
|
+
});
|
|
792
|
+
return summarize([
|
|
793
|
+
coverageGap(chartRoot, "render-truncated", `helm template produced more than ${MAX_RENDER_OUTPUT_BYTES} bytes and was stopped mid-render, so the rendered manifests are UNCHECKED rather than clean.`),
|
|
794
|
+
]);
|
|
795
|
+
}
|
|
758
796
|
const startupFailure = spawnFailureKind(render);
|
|
759
797
|
if (startupFailure) {
|
|
760
798
|
// The runner never got a verdict about the chart. Reporting this as a
|
|
@@ -766,9 +804,6 @@ async function renderAndValidate(chartRoot, cwd, filePath) {
|
|
|
766
804
|
});
|
|
767
805
|
return failedResult(startupFailure, render.error?.message || `helm template ${startupFailure}`);
|
|
768
806
|
}
|
|
769
|
-
const renderOutput = [render.stdout, render.stderr]
|
|
770
|
-
.filter(Boolean)
|
|
771
|
-
.join("\n");
|
|
772
807
|
if (render.status !== 0) {
|
|
773
808
|
// Before blaming the chart: did helm reject OUR OWN command line? An old
|
|
774
809
|
// helm (v2 has no `helm template --output-dir`) or a wrapper shim exits
|
|
@@ -785,7 +820,9 @@ async function renderAndValidate(chartRoot, cwd, filePath) {
|
|
|
785
820
|
}
|
|
786
821
|
// A failed RENDER is a real diagnostic: the chart cannot be installed.
|
|
787
822
|
const diagnostics = parseHelmTemplateFailure(renderOutput, chartRoot);
|
|
788
|
-
if (
|
|
823
|
+
if (renderCapped) {
|
|
824
|
+
// helm reported this failure itself, but we kept only a prefix of
|
|
825
|
+
// what it said, so the report above may be missing errors.
|
|
789
826
|
diagnostics.push(coverageGap(chartRoot, "render-truncated", "helm template output was truncated, so this failure report may be incomplete."));
|
|
790
827
|
}
|
|
791
828
|
logRenderPass(filePath, chartRoot, startedAt, {
|
|
@@ -804,6 +841,14 @@ async function renderAndValidate(chartRoot, cwd, filePath) {
|
|
|
804
841
|
sourceMapped: manifest.sourceMapped,
|
|
805
842
|
}));
|
|
806
843
|
}
|
|
844
|
+
if (renderCapped) {
|
|
845
|
+
// helm exited 0, so `--output-dir` holds the COMPLETE tree and every
|
|
846
|
+
// manifest above was validated from disk — the cap only cost us the
|
|
847
|
+
// "wrote <path>" lines on stdout, which this runner never parses.
|
|
848
|
+
// Recorded rather than silent (shape 8), but deliberately not an
|
|
849
|
+
// UNCHECKED claim: nothing was skipped (review F1).
|
|
850
|
+
diagnostics.push(coverageGap(chartRoot, "render-output-truncated", `helm template printed more than ${MAX_RENDER_OUTPUT_BYTES} bytes and its stdout was truncated. The rendered manifests were still validated from disk; only helm's own progress output was lost.`));
|
|
851
|
+
}
|
|
807
852
|
if (tree.truncated) {
|
|
808
853
|
// A partly-validated chart reported as clean is the shape-10 trap.
|
|
809
854
|
diagnostics.push(coverageGap(chartRoot, "render-truncated", `This chart rendered more than ${MAX_RENDERED_FILES} manifests; only the first ${MAX_RENDERED_FILES} were validated, so the rest are UNCHECKED rather than clean.`));
|
|
@@ -848,7 +893,6 @@ const helmRenderRunner = {
|
|
|
848
893
|
id: "helm-render",
|
|
849
894
|
appliesTo: ["yaml", "helm-template"],
|
|
850
895
|
priority: PRIORITY.GENERAL_ANALYSIS,
|
|
851
|
-
enabledByDefault: true,
|
|
852
896
|
skipTestFiles: false,
|
|
853
897
|
timeoutMs: RENDER_TIMEOUT_MS + TRIVY_TIMEOUT_MS + 10_000,
|
|
854
898
|
async run(ctx) {
|
|
@@ -57,9 +57,7 @@ export function registerDefaultRunners(registry) {
|
|
|
57
57
|
registry.register(lspRunner); // Unified LSP type-checking for all languages (priority 4)
|
|
58
58
|
registry.register(pyrightRunner); // Python type-checking (priority 5) - fallback when --lens-lsp disabled
|
|
59
59
|
registry.register(biomeCheckJsonRunner); // Biome check with JSON output for diagnostic capture (priority 9)
|
|
60
|
-
//
|
|
61
|
-
// project-wide pass via lens_diagnostics mode=full (refreshRunners) instead.
|
|
62
|
-
registry.register(astGrepNapiRunner); // TS/JS structural analysis via NAPI (priority 15, post-write disabled)
|
|
60
|
+
registry.register(astGrepNapiRunner); // JS/TS, CSS, and HTML structural analysis via NAPI (priority 15)
|
|
63
61
|
registry.register(treeSitterRunner); // Tree-sitter structural analysis (priority 14)
|
|
64
62
|
registry.register(ruffRunner); // Python linting (priority 10)
|
|
65
63
|
registry.register(shellcheckRunner); // Shell script linting (priority 20)
|
|
@@ -15,6 +15,7 @@ import { logExtension } from "../../extension-log.js";
|
|
|
15
15
|
import { getLspCapableKinds } from "../../language-policy.js";
|
|
16
16
|
import { touchCoverageGap } from "../../lsp/diagnostic-binding.js";
|
|
17
17
|
import { getLSPService } from "../../lsp/index.js";
|
|
18
|
+
import { LSP_SERVERS } from "../../lsp/server.js";
|
|
18
19
|
import { RUNTIME_CONFIG } from "../../runtime-config.js";
|
|
19
20
|
import { PRIORITY } from "../priorities.js";
|
|
20
21
|
import { resolveRunnerPath } from "../runner-context.js";
|
|
@@ -32,8 +33,42 @@ const LSP_SPAWN_BUDGET_MS = RUNTIME_CONFIG.pipeline.lspSpawnBudgetMs;
|
|
|
32
33
|
// can't dominate the per-edit pipeline budget. Diagnostics that arrive
|
|
33
34
|
// after the cap still land in the client's cache and surface on the
|
|
34
35
|
// next edit. Overridable via PI_LENS_LSP_DIAGNOSTICS_MAX_WAIT_MS.
|
|
35
|
-
const LSP_DIAGNOSTICS_WAIT_MS = 2500;
|
|
36
|
+
export const LSP_DIAGNOSTICS_WAIT_MS = 2500;
|
|
36
37
|
const MAX_CODE_ACTION_TITLES = 3;
|
|
38
|
+
/**
|
|
39
|
+
* Fixed margin above the worst-case cold-spawn-plus-diagnostics wait, so
|
|
40
|
+
* scheduling jitter alone can't reopen the F2 race below.
|
|
41
|
+
*/
|
|
42
|
+
const LSP_COLD_SPAWN_MARGIN_MS = 5_000;
|
|
43
|
+
/**
|
|
44
|
+
* This runner's own dispatch wall-clock budget. `runRunner` in
|
|
45
|
+
* `dispatcher.ts` races `runner.timeoutMs ?? RUNNER_TIMEOUT_MS` (30s)
|
|
46
|
+
* against `runner.run()` for the WHOLE call — reading the file, waiting for
|
|
47
|
+
* a client (bounded by `LSP_SPAWN_BUDGET_MS`, raised per-server via
|
|
48
|
+
* `LSPServerInfo.clientWaitTimeoutMs`), then waiting for diagnostics
|
|
49
|
+
* (`LSP_DIAGNOSTICS_WAIT_MS`).
|
|
50
|
+
*
|
|
51
|
+
* Left undeclared, this runner inherited the shared 30s default. A server
|
|
52
|
+
* whose `clientWaitTimeoutMs` exceeds that — Prisma's 40s, Vue's 30s
|
|
53
|
+
* (#2169, #2176) — could never actually use its own raised wait: the outer
|
|
54
|
+
* race always fired first, at 30s, so raising a server's floor without also
|
|
55
|
+
* raising this ceiling was a no-op on the real dispatch path (fix-round F2,
|
|
56
|
+
* #2233). Derive the ceiling from the registry instead of a second
|
|
57
|
+
* hand-picked literal, so the next slow server's `clientWaitTimeoutMs` keeps
|
|
58
|
+
* this budget correct automatically: the highest declared
|
|
59
|
+
* `clientWaitTimeoutMs` (or the shared 5s default, whichever is larger),
|
|
60
|
+
* plus the diagnostics wait that still runs after a cold spawn succeeds,
|
|
61
|
+
* plus a fixed margin.
|
|
62
|
+
*
|
|
63
|
+
* This raises the failure-detection latency for every OTHER language's
|
|
64
|
+
* hung-server case too (30s -> the value below), not just the five servers
|
|
65
|
+
* that need the headroom — the tradeoff is stated in PR #2233's body. It
|
|
66
|
+
* remains well inside the spread other dispatch runners already use
|
|
67
|
+
* (pyright 75s, golangci-lint/dotnet-build/rust-clippy 90s).
|
|
68
|
+
*/
|
|
69
|
+
export const LSP_RUNNER_TIMEOUT_MS = Math.max(LSP_SPAWN_BUDGET_MS, ...LSP_SERVERS.map((server) => server.clientWaitTimeoutMs ?? 0)) +
|
|
70
|
+
LSP_DIAGNOSTICS_WAIT_MS +
|
|
71
|
+
LSP_COLD_SPAWN_MARGIN_MS;
|
|
37
72
|
function normalizeActionTitle(title) {
|
|
38
73
|
return title.replace(/\s+/g, " ").trim();
|
|
39
74
|
}
|
|
@@ -58,7 +93,7 @@ const lspRunner = {
|
|
|
58
93
|
// is now the only step this seam needs (#1545).
|
|
59
94
|
appliesTo: getLspCapableKinds(),
|
|
60
95
|
priority: PRIORITY.LSP_PRIMARY,
|
|
61
|
-
|
|
96
|
+
timeoutMs: LSP_RUNNER_TIMEOUT_MS,
|
|
62
97
|
async run(ctx) {
|
|
63
98
|
const diagnosticPath = resolveRunnerPath(ctx.cwd, ctx.filePath);
|
|
64
99
|
// Only run if LSP is not disabled via --no-lsp
|
|
@@ -5,7 +5,10 @@ import { createAvailabilityChecker, resolveToolCommandWithInstallFallback, } fro
|
|
|
5
5
|
import { parseToolRun } from "./utils/tool-failure.js";
|
|
6
6
|
import { isInSpawnTimeoutCooldown, noteSpawnTimeout, } from "../../spawn-timeout-cooldown.js";
|
|
7
7
|
import { finishParsedRun } from "./utils/tool-failure.js";
|
|
8
|
-
const markdownlint = createAvailabilityChecker("markdownlint-cli2", ".cmd"
|
|
8
|
+
const markdownlint = createAvailabilityChecker("markdownlint-cli2", ".cmd", [
|
|
9
|
+
"--no-globs",
|
|
10
|
+
"-",
|
|
11
|
+
]);
|
|
9
12
|
// markdownlint-cli2 exit codes (its README's "Exit Codes" section): 0 = no
|
|
10
13
|
// findings, 1 = lint findings, 2 = unexpected error (unreadable config, bad
|
|
11
14
|
// glob, crash). Only 2 is a rejected invocation.
|
|
@@ -91,7 +94,6 @@ const markdownlintRunner = {
|
|
|
91
94
|
id: "markdownlint",
|
|
92
95
|
appliesTo: ["markdown"],
|
|
93
96
|
priority: PRIORITY.DOC_QUALITY,
|
|
94
|
-
enabledByDefault: true,
|
|
95
97
|
skipTestFiles: false,
|
|
96
98
|
async run(ctx) {
|
|
97
99
|
const cwd = ctx.cwd || process.cwd();
|
|
@@ -6,14 +6,18 @@
|
|
|
6
6
|
*
|
|
7
7
|
* Requires: oxlint (npm install -g oxlint)
|
|
8
8
|
*/
|
|
9
|
-
import
|
|
10
|
-
import * as path from "node:path";
|
|
11
|
-
import { walkUpDirs } from "../../path-utils.js";
|
|
9
|
+
import { findLocalBinUpwards } from "../../package-manager.js";
|
|
12
10
|
import { safeSpawnAsync } from "../../safe-spawn.js";
|
|
11
|
+
import { truncatedByOutputCap } from "../../spawn-output-cap.js";
|
|
13
12
|
import { getJstsLintPolicyForCwd, hasVitePlusConfig, } from "../../tool-policy.js";
|
|
14
13
|
import { PRIORITY } from "../priorities.js";
|
|
15
14
|
import { resolveToolCommand, resolveToolCommandWithInstallFallback, } from "./utils/runner-helpers.js";
|
|
16
15
|
import { finishParsedRun, parseToolRun } from "./utils/tool-failure.js";
|
|
16
|
+
// One file's JSON report. Nothing legitimate approaches 8 MiB here, so this is
|
|
17
|
+
// a blast-radius bound on a runaway or wedged oxlint rather than a working
|
|
18
|
+
// limit — the same value MAX_SG_OUTPUT_BYTES and MAX_REPORT_BYTES use, and what
|
|
19
|
+
// makes `outputTruncated` reachable for this runner at all (#2100).
|
|
20
|
+
const MAX_OXLINT_OUTPUT_BYTES = 8 * 1024 * 1024;
|
|
17
21
|
const OXLINT_NO_FILES = Symbol("oxlint-no-files");
|
|
18
22
|
const OXLINT_NO_FILES_UNCONFIRMED = Symbol("oxlint-no-files-unconfirmed");
|
|
19
23
|
const OXLINT_NO_FILES_BANNER = "No files found to lint. Please check your paths and ignore patterns.";
|
|
@@ -24,21 +28,19 @@ const OXLINT_NO_FILES_REPORT_KEYS = new Set([
|
|
|
24
28
|
"threads_count",
|
|
25
29
|
"start_time",
|
|
26
30
|
]);
|
|
31
|
+
/**
|
|
32
|
+
* Vite+'s `vp` from the project's own `node_modules/.bin`.
|
|
33
|
+
*
|
|
34
|
+
* Delegates to THE shared bin walker (#2544 review F1). This was a private,
|
|
35
|
+
* UNCEILINGED copy of that walk, while `formatters.ts`'s `oxfmtFormatter`
|
|
36
|
+
* resolved the SAME binary — `vp` — through the ceilinged `findInNodeModules`:
|
|
37
|
+
* one `vp` resolver stopped at `$HOME` and the other climbed past it to the
|
|
38
|
+
* filesystem root, so which policy applied depended on whether the format path
|
|
39
|
+
* or the lint path asked. A `node_modules/.bin/vp` at or above `$HOME` can
|
|
40
|
+
* never be this project's own Vite+ install (#2514).
|
|
41
|
+
*/
|
|
27
42
|
function resolveLocalVp(cwd) {
|
|
28
|
-
|
|
29
|
-
for (const dir of walkUpDirs(cwd)) {
|
|
30
|
-
const candidates = isWin
|
|
31
|
-
? [
|
|
32
|
-
path.join(dir, "node_modules", ".bin", "vp.cmd"),
|
|
33
|
-
path.join(dir, "node_modules", ".bin", "vp"),
|
|
34
|
-
]
|
|
35
|
-
: [path.join(dir, "node_modules", ".bin", "vp")];
|
|
36
|
-
for (const candidate of candidates) {
|
|
37
|
-
if (fs.existsSync(candidate))
|
|
38
|
-
return candidate;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
return null;
|
|
43
|
+
return findLocalBinUpwards("vp", cwd) ?? null;
|
|
42
44
|
}
|
|
43
45
|
async function resolveVitePlusCommand(cwd) {
|
|
44
46
|
const local = resolveLocalVp(cwd);
|
|
@@ -54,7 +56,6 @@ const oxlintRunner = {
|
|
|
54
56
|
id: "oxlint",
|
|
55
57
|
appliesTo: ["jsts"],
|
|
56
58
|
priority: PRIORITY.LINT_SECONDARY,
|
|
57
|
-
enabledByDefault: true,
|
|
58
59
|
skipTestFiles: false,
|
|
59
60
|
async run(ctx) {
|
|
60
61
|
const cwd = ctx.cwd || process.cwd();
|
|
@@ -86,6 +87,7 @@ const oxlintRunner = {
|
|
|
86
87
|
// Run oxlint (or Vite+'s vp lint wrapper) on the file.
|
|
87
88
|
const result = await safeSpawnAsync(cmd, args, {
|
|
88
89
|
timeout: 30000,
|
|
90
|
+
maxOutputBytes: MAX_OXLINT_OUTPUT_BYTES,
|
|
89
91
|
});
|
|
90
92
|
// Oxlint exits 0 whenever nothing at ERROR severity was found — that
|
|
91
93
|
// includes a run that found only warnings, its own default severity
|
|
@@ -194,16 +196,16 @@ const oxlintRunner = {
|
|
|
194
196
|
};
|
|
195
197
|
function oxlintProcessState(result) {
|
|
196
198
|
const failureKind = result.spawnFailure?.kind;
|
|
197
|
-
if (result
|
|
198
|
-
return "
|
|
199
|
+
if (truncatedByOutputCap(result))
|
|
200
|
+
return "truncated";
|
|
199
201
|
if (result.failure === "timeout" || failureKind === "timeout")
|
|
200
202
|
return "timeout";
|
|
201
203
|
if (result.failure === "aborted" || failureKind === "killed")
|
|
202
204
|
return "killed";
|
|
205
|
+
if (result.signal || result.failure === "signal")
|
|
206
|
+
return "signal";
|
|
203
207
|
if (result.failure === "spawn" || result.error)
|
|
204
208
|
return "spawn";
|
|
205
|
-
if (result.outputTruncated)
|
|
206
|
-
return "truncated";
|
|
207
209
|
return "normal";
|
|
208
210
|
}
|
|
209
211
|
function isNonnegativeInteger(value) {
|
|
@@ -77,6 +77,7 @@ function notePsDecision(latch, tool, verdict) {
|
|
|
77
77
|
cause: verdict.available ? "ok" : verdict.cause,
|
|
78
78
|
elapsedMs: verdict.elapsedMs,
|
|
79
79
|
latched: verdict.available || isLatchingOutcome(verdict.outcome),
|
|
80
|
+
classifiedBy: "probe",
|
|
80
81
|
hostStallMs: verdict.hostStallMs,
|
|
81
82
|
...(retryAfterMs !== undefined && { retryAfterMs }),
|
|
82
83
|
budgetMs: PS_TIMEOUT_MS,
|
|
@@ -268,7 +269,6 @@ const psScriptAnalyzerRunner = {
|
|
|
268
269
|
id: "psscriptanalyzer",
|
|
269
270
|
appliesTo: ["powershell"],
|
|
270
271
|
priority: PRIORITY.GENERAL_ANALYSIS,
|
|
271
|
-
enabledByDefault: true,
|
|
272
272
|
skipTestFiles: false,
|
|
273
273
|
async run(ctx) {
|
|
274
274
|
const cmd = await resolvePowerShellCmd();
|
|
@@ -412,6 +412,9 @@ const psScriptAnalyzerRunner = {
|
|
|
412
412
|
latched: false,
|
|
413
413
|
hostStallMs,
|
|
414
414
|
budgetMs: PS_TIMEOUT_MS,
|
|
415
|
+
// A read of the process's own stdout, not classifyProbeFailure, is
|
|
416
|
+
// what decided this (#2209).
|
|
417
|
+
classifiedBy: "caller",
|
|
415
418
|
});
|
|
416
419
|
incrementDegradationCount({
|
|
417
420
|
kind: "grammar-blocked",
|