@herbertgao/pi-extensions 2026.9.0 → 2026.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/node_modules/@czottmann/pi-automode/CHANGELOG.md +13 -1
- package/node_modules/@czottmann/pi-automode/README.md +20 -0
- package/node_modules/@czottmann/pi-automode/docs/GLOSSARY.md +1 -1
- package/node_modules/@czottmann/pi-automode/docs/automode-classifier-flow.md +2 -1
- package/node_modules/@czottmann/pi-automode/docs/defaults.md +3 -2
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/classifier.ts +38 -2
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/constants.ts +5 -3
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/extension.ts +11 -3
- package/node_modules/@czottmann/pi-automode/package.json +1 -1
- package/node_modules/@narumitw/pi-btw/README.md +57 -141
- package/node_modules/@narumitw/pi-btw/dist/index.ts +466 -41
- package/node_modules/@narumitw/pi-btw/dist/index.ts.map +4 -4
- package/node_modules/@narumitw/pi-btw/docs/workflows.md +74 -0
- package/node_modules/@narumitw/pi-btw/package.json +2 -1
- package/node_modules/@narumitw/pi-btw/src/btw.ts +15 -1
- package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +32 -2
- package/node_modules/@narumitw/pi-btw/src/keybindings.ts +330 -0
- package/node_modules/@narumitw/pi-btw/src/menu.ts +136 -19
- package/node_modules/@narumitw/pi-btw/src/settings.ts +32 -0
- package/node_modules/@narumitw/pi-btw/src/side-thread.ts +57 -5
- package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +52 -30
- package/node_modules/@pi-plugins/fast-mode/README.md +5 -3
- package/node_modules/@pi-plugins/fast-mode/dist/index.d.mts.map +1 -1
- package/node_modules/@pi-plugins/fast-mode/dist/index.mjs +20 -55
- package/node_modules/@pi-plugins/fast-mode/dist/index.mjs.map +1 -1
- package/node_modules/@pi-plugins/fast-mode/package.json +1 -1
- package/node_modules/pi-lens/CHANGELOG.md +1072 -0
- package/node_modules/pi-lens/README.md +3 -0
- package/node_modules/pi-lens/config/biome/core.jsonc +11 -2
- package/node_modules/pi-lens/config/dependency-cruiser-eager-allowlist.json +13 -1
- package/node_modules/pi-lens/dist/clients/actionable-warnings-logger.js +2 -9
- package/node_modules/pi-lens/dist/clients/actionable-warnings.js +927 -80
- package/node_modules/pi-lens/dist/clients/advisory-provenance.js +1 -1
- package/node_modules/pi-lens/dist/clients/agent-behavior-client.js +13 -4
- package/node_modules/pi-lens/dist/clients/ast-grep-client.js +123 -3
- package/node_modules/pi-lens/dist/clients/ast-grep-rule-manager.js +60 -5
- package/node_modules/pi-lens/dist/clients/ast-grep-tool-logger.js +2 -9
- package/node_modules/pi-lens/dist/clients/ast-grep-types.js +2 -0
- package/node_modules/pi-lens/dist/clients/bash-file-access.js +133 -3
- package/node_modules/pi-lens/dist/clients/biome-client.js +9 -2
- package/node_modules/pi-lens/dist/clients/blocker-freshness.js +14 -6
- package/node_modules/pi-lens/dist/clients/bootstrap.js +509 -73
- package/node_modules/pi-lens/dist/clients/bounded-cache.js +152 -12
- package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +1 -1
- package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +59 -9
- package/node_modules/pi-lens/dist/clients/bundled-resource-health.js +113 -0
- package/node_modules/pi-lens/dist/clients/bus-events-logger.js +3 -11
- package/node_modules/pi-lens/dist/clients/cache/rule-cache.js +31 -4
- package/node_modules/pi-lens/dist/clients/cache-manager.js +105 -6
- package/node_modules/pi-lens/dist/clients/cache-observability.js +40 -19
- package/node_modules/pi-lens/dist/clients/cargo-manifest.js +422 -0
- package/node_modules/pi-lens/dist/clients/cascade-logger.js +2 -9
- package/node_modules/pi-lens/dist/clients/child-unref.js +1 -19
- package/node_modules/pi-lens/dist/clients/code-quality-warnings.js +13 -3
- package/node_modules/pi-lens/dist/clients/complexity-client.js +16 -5
- package/node_modules/pi-lens/dist/clients/config-core/deny.js +221 -0
- package/node_modules/pi-lens/dist/clients/config-core/index.js +50 -0
- package/node_modules/pi-lens/dist/clients/config-core/merge.js +357 -0
- package/node_modules/pi-lens/dist/clients/config-core/normalize.js +340 -0
- package/node_modules/pi-lens/dist/clients/config-core/process-spec.js +248 -0
- package/node_modules/pi-lens/dist/clients/config-core/provenance.js +164 -0
- package/node_modules/pi-lens/dist/clients/config-core/records.js +218 -0
- package/node_modules/pi-lens/dist/clients/config-core/resolve.js +125 -0
- package/node_modules/pi-lens/dist/clients/config-core/safe-object.js +78 -0
- package/node_modules/pi-lens/dist/clients/config-core/schema.js +165 -0
- package/node_modules/pi-lens/dist/clients/config-diagnostic-codes.js +281 -0
- package/node_modules/pi-lens/dist/clients/config-locations.js +160 -0
- package/node_modules/pi-lens/dist/clients/config-resolve.js +789 -0
- package/node_modules/pi-lens/dist/clients/config-schema.js +234 -0
- package/node_modules/pi-lens/dist/clients/config-warn.js +407 -0
- package/node_modules/pi-lens/dist/clients/dead-code-client.js +19 -14
- package/node_modules/pi-lens/dist/clients/dead-code-logger.js +2 -6
- package/node_modules/pi-lens/dist/clients/deadline-utils.js +178 -0
- package/node_modules/pi-lens/dist/clients/debug-handles.js +2 -2
- package/node_modules/pi-lens/dist/clients/debug-heap.js +3 -3
- package/node_modules/pi-lens/dist/clients/deferred-lsp-work.js +106 -0
- package/node_modules/pi-lens/dist/clients/degradation-ledger.js +113 -7
- package/node_modules/pi-lens/dist/clients/dependency-checker.js +8 -19
- package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +1 -1
- package/node_modules/pi-lens/dist/clients/diagnostic-line-freshness.js +12 -9
- package/node_modules/pi-lens/dist/clients/diagnostic-logger.js +15 -5
- package/node_modules/pi-lens/dist/clients/dispatch/collect-later-tier.js +0 -4
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +162 -44
- package/node_modules/pi-lens/dist/clients/dispatch/fact-store.js +97 -0
- package/node_modules/pi-lens/dist/clients/dispatch/integration.js +27 -8
- package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +0 -6
- package/node_modules/pi-lens/dist/clients/dispatch/pending-runner-findings.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/plan.js +0 -3
- package/node_modules/pi-lens/dist/clients/dispatch/rules/high-complexity.js +2 -2
- package/node_modules/pi-lens/dist/clients/dispatch/rules/high-fan-out.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/actionlint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +383 -27
- package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +4 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/credo.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/cue-vet.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/dart-analyze.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/detekt.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/dotnet-build.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/fact-rules.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/fish-indent.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/gleam-check.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/go-vet.js +1 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/golangci-lint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-lint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +1 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ktlint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/oxlint.js +14 -18
- package/node_modules/pi-lens/dist/clients/dispatch/runners/php-lint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/phpstan.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/prisma-validate.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +6 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +7 -4
- package/node_modules/pi-lens/dist/clients/dispatch/runners/rubocop.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ruff.js +1 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +1 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shellcheck.js +1 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shfmt.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +4 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/spotbugs.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/terragrunt.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tree-sitter.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +3 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/diagnostic-parsers.js +3 -67
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +194 -80
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +84 -15
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils.js +0 -21
- package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yaml-rule-parser.js +2 -20
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/utils/format-utils.js +2 -2
- package/node_modules/pi-lens/dist/clients/disposition-logger.js +3 -10
- package/node_modules/pi-lens/dist/clients/effective-config.js +403 -0
- package/node_modules/pi-lens/dist/clients/error-class.js +23 -0
- package/node_modules/pi-lens/dist/clients/event-loop-hold.js +274 -0
- package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +2 -2
- package/node_modules/pi-lens/dist/clients/extension-log.js +2 -2
- package/node_modules/pi-lens/dist/clients/feature-hints.js +2 -1
- package/node_modules/pi-lens/dist/clients/file-kinds.js +1 -38
- package/node_modules/pi-lens/dist/clients/file-time.js +7 -2
- package/node_modules/pi-lens/dist/clients/file-utils.js +117 -10
- package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +50 -13
- package/node_modules/pi-lens/dist/clients/format-service.js +6 -2
- package/node_modules/pi-lens/dist/clients/formatters.js +385 -104
- package/node_modules/pi-lens/dist/clients/freshness-cadence.js +17 -0
- package/node_modules/pi-lens/dist/clients/generated-artifacts.js +116 -22
- package/node_modules/pi-lens/dist/clients/generation-guard.js +4 -9
- package/node_modules/pi-lens/dist/clients/git-guard.js +6 -1
- package/node_modules/pi-lens/dist/clients/go-client.js +39 -0
- package/node_modules/pi-lens/dist/clients/gradle-ktfmt-style.js +252 -0
- package/node_modules/pi-lens/dist/clients/grammar-source.js +3 -3
- package/node_modules/pi-lens/dist/clients/hashline-anchor.js +424 -0
- package/node_modules/pi-lens/dist/clients/hook-budgets.js +76 -0
- package/node_modules/pi-lens/dist/clients/host-edit-normalize.js +5 -2
- package/node_modules/pi-lens/dist/clients/host-ports.js +1 -1
- package/node_modules/pi-lens/dist/clients/installer/index.js +289 -59
- package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh.js +84 -18
- package/node_modules/pi-lens/dist/clients/instance-reaper.js +110 -236
- package/node_modules/pi-lens/dist/clients/instance-registry.js +6 -3
- package/node_modules/pi-lens/dist/clients/language-profile.js +0 -9
- package/node_modules/pi-lens/dist/clients/language-registry.js +599 -0
- package/node_modules/pi-lens/dist/clients/latency-logger.js +165 -9
- package/node_modules/pi-lens/dist/clients/ledger-bounds.js +34 -1
- package/node_modules/pi-lens/dist/clients/lens-config.js +160 -30
- package/node_modules/pi-lens/dist/clients/lens-engine.js +33 -41
- package/node_modules/pi-lens/dist/clients/lens-events.js +1 -1
- package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +77 -6
- package/node_modules/pi-lens/dist/clients/lens-map.js +1 -1
- package/node_modules/pi-lens/dist/clients/log-cleanup.js +2 -38
- package/node_modules/pi-lens/dist/clients/lsp/aggregation.js +3 -1
- package/node_modules/pi-lens/dist/clients/lsp/client.js +172 -33
- package/node_modules/pi-lens/dist/clients/lsp/config.js +484 -158
- package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +1 -1
- package/node_modules/pi-lens/dist/clients/lsp/document-drift.js +1 -1
- package/node_modules/pi-lens/dist/clients/lsp/edits.js +18 -5
- package/node_modules/pi-lens/dist/clients/lsp/index.js +892 -96
- package/node_modules/pi-lens/dist/clients/lsp/inferred-project.js +1 -1
- package/node_modules/pi-lens/dist/clients/lsp/language.js +18 -177
- package/node_modules/pi-lens/dist/clients/lsp/launch.js +2 -1
- package/node_modules/pi-lens/dist/clients/lsp/path-utils.js +1 -1
- package/node_modules/pi-lens/dist/clients/lsp/pending-aux-coverage.js +5 -18
- package/node_modules/pi-lens/dist/clients/lsp/server.js +284 -147
- package/node_modules/pi-lens/dist/clients/lsp/session-roots.js +116 -23
- package/node_modules/pi-lens/dist/clients/lsp/spawn-history.js +2 -7
- package/node_modules/pi-lens/dist/clients/lsp/sync-kind.js +0 -1
- package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +14 -7
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/classification.js +6 -0
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +2 -1
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +1 -1
- package/node_modules/pi-lens/dist/clients/lsp-document-symbols.js +1 -1
- package/node_modules/pi-lens/dist/clients/lsp-mutation.js +163 -21
- package/node_modules/pi-lens/dist/clients/map-with-concurrency.js +36 -0
- package/node_modules/pi-lens/dist/clients/mcp/analyze.js +33 -4
- package/node_modules/pi-lens/dist/clients/mcp/session.js +5 -16
- package/node_modules/pi-lens/dist/clients/memory-sampler.js +8 -3
- package/node_modules/pi-lens/dist/clients/metrics-history.js +28 -107
- package/node_modules/pi-lens/dist/clients/middle-man-analysis.js +3 -5
- package/node_modules/pi-lens/dist/clients/module-report.js +21 -46
- package/node_modules/pi-lens/dist/clients/mutating-tool.js +651 -0
- package/node_modules/pi-lens/dist/clients/mutation-attribution.js +368 -0
- package/node_modules/pi-lens/dist/clients/mutation-bridge.js +240 -0
- package/node_modules/pi-lens/dist/clients/ndjson-logger.js +247 -24
- package/node_modules/pi-lens/dist/clients/observed-mutation-sources.js +101 -0
- package/node_modules/pi-lens/dist/clients/observed-mutation.js +1215 -0
- package/node_modules/pi-lens/dist/clients/opaque-mutation-scan.js +70 -28
- package/node_modules/pi-lens/dist/clients/opengrep-config.js +5 -1
- package/node_modules/pi-lens/dist/clients/package-manager.js +195 -26
- package/node_modules/pi-lens/dist/clients/partial-edit-apply.js +359 -80
- package/node_modules/pi-lens/dist/clients/path-attribution-telemetry.js +23 -7
- package/node_modules/pi-lens/dist/clients/path-keyed-map.js +21 -2
- package/node_modules/pi-lens/dist/clients/path-utils.js +451 -15
- package/node_modules/pi-lens/dist/clients/performance-report.js +2 -2
- package/node_modules/pi-lens/dist/clients/persist-debounce.js +8 -1
- package/node_modules/pi-lens/dist/clients/php-cs-fixer-config.js +114 -0
- package/node_modules/pi-lens/dist/clients/pipeline.js +79 -18
- package/node_modules/pi-lens/dist/clients/probe-home-state.js +228 -0
- package/node_modules/pi-lens/dist/clients/process-bridge.js +66 -0
- package/node_modules/pi-lens/dist/clients/process-snapshot.js +68 -0
- package/node_modules/pi-lens/dist/clients/project-changes.js +1 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/extractors.js +1 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +4 -3
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/jscpd.js +1 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/knip.js +1 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/madge.js +1 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/opengrep.js +1 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +28 -4
- package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +51 -20
- package/node_modules/pi-lens/dist/clients/project-lens-config.js +438 -122
- package/node_modules/pi-lens/dist/clients/project-scan-policy.js +3 -51
- package/node_modules/pi-lens/dist/clients/project-snapshot.js +52 -24
- package/node_modules/pi-lens/dist/clients/python-environment.js +217 -0
- package/node_modules/pi-lens/dist/clients/python-provenance.js +639 -0
- package/node_modules/pi-lens/dist/clients/quiet-window.js +6 -1
- package/node_modules/pi-lens/dist/clients/read-bridge.js +13 -21
- package/node_modules/pi-lens/dist/clients/read-expansion.js +9 -46
- package/node_modules/pi-lens/dist/clients/read-guard-logger.js +16 -5
- package/node_modules/pi-lens/dist/clients/read-guard-tool-lines.js +364 -212
- package/node_modules/pi-lens/dist/clients/read-guard.js +26 -2
- package/node_modules/pi-lens/dist/clients/recent-touches.js +2 -2
- package/node_modules/pi-lens/dist/clients/resource-sampler.js +195 -96
- package/node_modules/pi-lens/dist/clients/review-graph/builder.js +155 -114
- package/node_modules/pi-lens/dist/clients/review-graph/import-resolvers.js +1 -1
- package/node_modules/pi-lens/dist/clients/review-graph/service.js +55 -3
- package/node_modules/pi-lens/dist/clients/review-graph/shared-extraction-ir.js +7 -15
- package/node_modules/pi-lens/dist/clients/review-graph/workspace-modules.js +10 -74
- package/node_modules/pi-lens/dist/clients/review-graph-logger.js +9 -3
- package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +19 -3
- package/node_modules/pi-lens/dist/clients/runtime-context.js +49 -16
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +25 -6
- package/node_modules/pi-lens/dist/clients/runtime-session.js +184 -32
- package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +179 -36
- package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +797 -243
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +1028 -53
- package/node_modules/pi-lens/dist/clients/rust-client.js +31 -0
- package/node_modules/pi-lens/dist/clients/safe-spawn.js +33 -10
- package/node_modules/pi-lens/dist/clients/sanitize.js +7 -12
- package/node_modules/pi-lens/dist/clients/scan-utils.js +1 -56
- package/node_modules/pi-lens/dist/clients/scratch-tree-policy.js +1 -3
- package/node_modules/pi-lens/dist/clients/security-scan-client.js +3 -0
- package/node_modules/pi-lens/dist/clients/session-lifecycle.js +1 -1
- package/node_modules/pi-lens/dist/clients/session-start-observability.js +79 -0
- package/node_modules/pi-lens/dist/clients/session-summary.js +0 -24
- package/node_modules/pi-lens/dist/clients/sessionstart-logger.js +12 -3
- package/node_modules/pi-lens/dist/clients/sgconfig.js +7 -6
- package/node_modules/pi-lens/dist/clients/shared-checkout-guard.js +1 -1
- package/node_modules/pi-lens/dist/clients/skills-resolver.js +105 -0
- package/node_modules/pi-lens/dist/clients/smells-rollup.js +4 -4
- package/node_modules/pi-lens/dist/clients/startup-scan.js +2 -10
- package/node_modules/pi-lens/dist/clients/string-utils.js +13 -0
- package/node_modules/pi-lens/dist/clients/subagent-mode.js +17 -4
- package/node_modules/pi-lens/dist/clients/test-runner-client.js +176 -39
- package/node_modules/pi-lens/dist/clients/test-runner-delivery.js +244 -0
- package/node_modules/pi-lens/dist/clients/tool-definition.js +41 -1
- package/node_modules/pi-lens/dist/clients/tool-policy.js +92 -22
- package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +40 -40
- package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +87 -100
- package/node_modules/pi-lens/dist/clients/tree-sitter-logger.js +2 -2
- package/node_modules/pi-lens/dist/clients/tree-sitter-query-loader.js +81 -1
- package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +51 -46
- package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +28 -0
- package/node_modules/pi-lens/dist/clients/tui-fit.js +0 -4
- package/node_modules/pi-lens/dist/clients/typos-config.js +5 -0
- package/node_modules/pi-lens/dist/clients/user-notify.js +6 -6
- package/node_modules/pi-lens/dist/clients/widget-state.js +191 -26
- package/node_modules/pi-lens/dist/clients/word-index-logger.js +2 -9
- package/node_modules/pi-lens/dist/clients/word-index-store.js +23 -12
- package/node_modules/pi-lens/dist/clients/word-index.js +252 -47
- package/node_modules/pi-lens/dist/clients/workspace-topology.js +8 -1
- package/node_modules/pi-lens/dist/clients/zizmor-config.js +4 -1
- package/node_modules/pi-lens/dist/index.js +65899 -55340
- package/node_modules/pi-lens/dist/mcp/analyze-cli.js +3 -1
- package/node_modules/pi-lens/dist/mcp/build-staleness.js +1 -1
- package/node_modules/pi-lens/dist/mcp/server.js +127 -5
- package/node_modules/pi-lens/dist/scripts/lib/process-scan.mjs +583 -0
- package/node_modules/pi-lens/dist/scripts/lib/skills-predicate.mjs +129 -0
- package/node_modules/pi-lens/dist/tools/effective-config.js +89 -0
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +96 -25
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +104 -86
- package/node_modules/pi-lens/dist/tools/lsp-navigation.js +37 -16
- package/node_modules/pi-lens/dist/tools/lsp-structured-output.js +3 -3
- package/node_modules/pi-lens/dist/tools/render-compact.js +1 -1
- package/node_modules/pi-lens/dist/tools/shared.js +0 -1
- package/node_modules/pi-lens/dist/tools/symbol-search.js +1 -2
- package/node_modules/pi-lens/docs/agent-guide.md +64 -1
- package/node_modules/pi-lens/docs/configuration.md +222 -0
- package/node_modules/pi-lens/docs/dependencies.md +3 -3
- package/node_modules/pi-lens/docs/features.md +44 -5
- package/node_modules/pi-lens/docs/globalconfig.md +20 -0
- package/node_modules/pi-lens/docs/language-coverage.md +2 -2
- package/node_modules/pi-lens/docs/lsp-capability-matrix.md +9 -1
- package/node_modules/pi-lens/docs/pi-lens-fixer.md +25 -0
- package/node_modules/pi-lens/docs/pi-lens-investigator.md +25 -0
- package/node_modules/pi-lens/docs/pi-lens-reviewer.md +33 -0
- package/node_modules/pi-lens/docs/pi-lens-subagent.md +49 -0
- package/node_modules/pi-lens/docs/pi-lens-warden.md +55 -0
- package/node_modules/pi-lens/docs/public-api-stability.md +359 -0
- package/node_modules/pi-lens/docs/release-qa-baseline.md +190 -0
- package/node_modules/pi-lens/docs/servercapabilities.md +7 -3
- package/node_modules/pi-lens/docs/subagent-compat.md +110 -30
- package/node_modules/pi-lens/docs/tree-sitter_rules_catalog.md +2 -2
- package/node_modules/pi-lens/docs/word-index.md +1 -1
- package/node_modules/pi-lens/package.json +18 -35
- package/node_modules/pi-lens/rules/tree-sitter-queries/python/python-cross-language-method.yml +3 -3
- package/node_modules/pi-lens/rules/tree-sitter-queries/python/python-hallucinated-import.yml +2 -2
- package/node_modules/pi-lens/rules/tree-sitter-queries/python/python-sql-injection.yml +12 -2
- package/node_modules/pi-lens/rules/typos/_typos.toml +4 -2
- package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +192 -1
- package/node_modules/pi-lens/scripts/install-selftest.mjs +58 -2
- package/node_modules/pi-lens/scripts/lib/skills-predicate.mjs +129 -0
- package/node_modules/pi-lens/scripts/lib/warm-loader-cache.mjs +1 -1
- package/node_modules/pi-lens/scripts/rpc-load-check.mjs +3 -1
- package/node_modules/pi-lens/scripts/warm-loader-cache.mjs +4 -2
- package/node_modules/pi-web-access/CHANGELOG.md +28 -0
- package/node_modules/pi-web-access/README.md +62 -15
- package/node_modules/pi-web-access/curator-page.ts +3 -1
- package/node_modules/pi-web-access/curator-server.ts +5 -1
- package/node_modules/pi-web-access/gemini-search.ts +8 -4
- package/node_modules/pi-web-access/github-extract.ts +242 -1
- package/node_modules/pi-web-access/index.ts +118 -64
- package/node_modules/pi-web-access/mistral-search.ts +281 -0
- package/node_modules/pi-web-access/package.json +2 -2
- package/node_modules/pi-web-access/perplexity.ts +14 -1
- package/node_modules/pi-web-access/utils.ts +23 -6
- package/node_modules/pi-web-access/xai-search.ts +96 -33
- package/package.json +6 -6
|
@@ -10,16 +10,16 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import * as fs from "node:fs";
|
|
12
12
|
import * as path from "node:path";
|
|
13
|
+
import { incrementDegradationCount, recordDegradationOnce, } from "../../degradation-ledger.js";
|
|
13
14
|
import { loadAstGrepNapi, } from "../../deps/ast-grep-napi.js";
|
|
14
15
|
import { minimatch } from "../../deps/minimatch.js";
|
|
15
|
-
import { getAstGrepRuleSources, } from "../../sgconfig.js";
|
|
16
16
|
import { logLatency } from "../../latency-logger.js";
|
|
17
|
+
import { hasAuxiliaryLspPublishedForRoot } from "../../lsp/index.js";
|
|
18
|
+
import { clearPendingAuxiliaryCoverage, hasPendingAuxiliaryCoverage, recordNapiFallbackCoverage, } from "../../lsp/pending-aux-coverage.js";
|
|
19
|
+
import { getAstGrepRuleSources, } from "../../sgconfig.js";
|
|
17
20
|
import { hasEslintConfig } from "../../tool-policy.js";
|
|
18
21
|
import { enabledAuxiliaryLspServerIds } from "../auxiliary-lsp.js";
|
|
19
22
|
import { classifyDefect } from "../diagnostic-taxonomy.js";
|
|
20
|
-
import { incrementDegradationCount, recordDegradationOnce, } from "../../degradation-ledger.js";
|
|
21
|
-
import { hasAuxiliaryLspPublishedForRoot } from "../../lsp/index.js";
|
|
22
|
-
import { clearPendingAuxiliaryCoverage, hasPendingAuxiliaryCoverage, recordNapiFallbackCoverage, } from "../../lsp/pending-aux-coverage.js";
|
|
23
23
|
import { PRIORITY } from "../priorities.js";
|
|
24
24
|
import { calculateRuleComplexity, isOverlyBroadPattern, isStructuredRule, loadYamlRules, loadYamlRulesFresh, MAX_BLOCKING_RULE_COMPLEXITY, } from "./yaml-rule-parser.js";
|
|
25
25
|
const defaultUnsupportedLanguageLog = new Set();
|
|
@@ -184,7 +184,9 @@ export async function loadSg() {
|
|
|
184
184
|
}
|
|
185
185
|
})();
|
|
186
186
|
sgLoadPromise = task;
|
|
187
|
-
task
|
|
187
|
+
// `task` never rejects (the IIFE catches), so the derived promise is inert;
|
|
188
|
+
// `void` records that no consumer awaits it (oxlint no-floating-promises).
|
|
189
|
+
void task.finally(() => {
|
|
188
190
|
if (sgLoadPromise === task)
|
|
189
191
|
sgLoadPromise = undefined;
|
|
190
192
|
});
|
|
@@ -436,6 +438,218 @@ export function getLang(filePath, sgModule) {
|
|
|
436
438
|
}
|
|
437
439
|
return lang;
|
|
438
440
|
}
|
|
441
|
+
/**
|
|
442
|
+
* Budget for embedded-`<script>` evaluation (#2347 review F2/F4). Every nonempty
|
|
443
|
+
* script body is reparsed as JS and EVERY `language: JavaScript` rule runs
|
|
444
|
+
* against it, so the work is `rules * bodies * body-size`, all multiplied by
|
|
445
|
+
* the native addon's per-call overhead. Measured on this seam (full catalog,
|
|
446
|
+
* real addon, 2026-08-30): ~8.5 ms per small body, ~9 s for 500 blocks, and
|
|
447
|
+
* ~19.5 s for one ~1 MiB dense body (the shape that made the byte axis the
|
|
448
|
+
* real bound). The caps apply to EVERY body — first one included — so an
|
|
449
|
+
* oversized single inline script is omitted and recorded like any other
|
|
450
|
+
* over-budget body. Hand-authored HTML carries a handful of small inline
|
|
451
|
+
* scripts, so the caps only ever trip on generated/pathological pages, where a
|
|
452
|
+
* bounded, recorded partial evaluation beats a seconds-long synchronous stall
|
|
453
|
+
* on the per-edit hook. Budget truncation is a coverage loss and is recorded
|
|
454
|
+
* (see `emitHtmlScriptDegradations`).
|
|
455
|
+
*/
|
|
456
|
+
export const MAX_SCRIPT_BODIES_EVALUATED = 64;
|
|
457
|
+
/**
|
|
458
|
+
* Cumulative parsed script-body size cap; bounds the `rules * bytes` work.
|
|
459
|
+
* Every body — including the first — must fit within the running total.
|
|
460
|
+
*/
|
|
461
|
+
export const MAX_SCRIPT_BODY_BYTES_EVALUATED = 128 * 1024;
|
|
462
|
+
/**
|
|
463
|
+
* UTF-16 code-unit indexes, in the original file, of every line start, newest
|
|
464
|
+
* line last. `@ast-grep/napi` reports line/column/index in UTF-16 code units
|
|
465
|
+
* (verified against 0.45.1 with `é` and emoji), so the line table must be
|
|
466
|
+
* built in the SAME unit; a UTF-8 byte walk would shift every coordinate that
|
|
467
|
+
* follows a multibyte character.
|
|
468
|
+
*/
|
|
469
|
+
function computeLineStartsUtf16(content) {
|
|
470
|
+
const starts = [0];
|
|
471
|
+
for (let i = 0; i < content.length; i++) {
|
|
472
|
+
if (content.charCodeAt(i) === 0x0a)
|
|
473
|
+
starts.push(i + 1);
|
|
474
|
+
}
|
|
475
|
+
return starts;
|
|
476
|
+
}
|
|
477
|
+
/** 0-based line and code-unit column for a UTF-16 index, via binary search. */
|
|
478
|
+
function filePositionForIndex(lineStarts, index) {
|
|
479
|
+
let lo = 0;
|
|
480
|
+
let hi = lineStarts.length - 1;
|
|
481
|
+
while (lo < hi) {
|
|
482
|
+
const mid = (lo + hi + 1) >> 1;
|
|
483
|
+
if (lineStarts[mid] <= index)
|
|
484
|
+
lo = mid;
|
|
485
|
+
else
|
|
486
|
+
hi = mid - 1;
|
|
487
|
+
}
|
|
488
|
+
return { line: lo, column: index - lineStarts[lo] };
|
|
489
|
+
}
|
|
490
|
+
/**
|
|
491
|
+
* Extract every `<script>` body from an HTML root and parse it as JavaScript
|
|
492
|
+
* (#2347). Mirrors the ast-grep CLI/LSP: the injection is unconditional —
|
|
493
|
+
* `type` and `src` attributes do not suppress it (verified against the 0.45.1
|
|
494
|
+
* CLI with `text/template`, `application/ld+json`, and `src`-bearing script
|
|
495
|
+
* tags, all injected). Whitespace-only bodies are skipped (nothing to match).
|
|
496
|
+
* A body the JS grammar cannot parse is dropped the way an unparseable `.js`
|
|
497
|
+
* file would be; the failure is counted, never silent. The evaluation budget
|
|
498
|
+
* (count + cumulative bytes) is applied BEFORE any grammar parse. The caller
|
|
499
|
+
* emits the bounded degradation records from the result — collection stays
|
|
500
|
+
* pure so the count evidence is directly testable.
|
|
501
|
+
*/
|
|
502
|
+
export function collectHtmlScriptInjections(htmlRoot, sgModule) {
|
|
503
|
+
// SAFETY: `AstGrepNapi` is the loaded addon module's own (typed) shape, so
|
|
504
|
+
// its `js` accessor is guaranteed present while the addon lives; this
|
|
505
|
+
// narrowing only names the subshape this helper consumes (a `js` grammar
|
|
506
|
+
// whose parses expose `findAll`), and the absence check right below
|
|
507
|
+
// degrades to "no embedded coverage" rather than throwing when the addon
|
|
508
|
+
// ever drops the grammar.
|
|
509
|
+
const addon = sgModule;
|
|
510
|
+
if (!addon.js) {
|
|
511
|
+
return {
|
|
512
|
+
injections: [],
|
|
513
|
+
scriptElementCount: 0,
|
|
514
|
+
bodiesEvaluated: 0,
|
|
515
|
+
truncatedBodies: 0,
|
|
516
|
+
parseFailures: 0,
|
|
517
|
+
missingJsGrammar: true,
|
|
518
|
+
htmlScanFailure: false,
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
let scripts;
|
|
522
|
+
try {
|
|
523
|
+
scripts = htmlRoot.findAll({ rule: { kind: "script_element" } });
|
|
524
|
+
}
|
|
525
|
+
catch {
|
|
526
|
+
return {
|
|
527
|
+
injections: [],
|
|
528
|
+
scriptElementCount: 0,
|
|
529
|
+
bodiesEvaluated: 0,
|
|
530
|
+
truncatedBodies: 0,
|
|
531
|
+
parseFailures: 0,
|
|
532
|
+
missingJsGrammar: false,
|
|
533
|
+
htmlScanFailure: true,
|
|
534
|
+
};
|
|
535
|
+
}
|
|
536
|
+
// Extract every nonempty body first (text extraction is cheap) so the raw
|
|
537
|
+
// script-element count is exact, then apply the budget BEFORE parsing any
|
|
538
|
+
// of them.
|
|
539
|
+
let scriptElementCount = 0;
|
|
540
|
+
const candidates = [];
|
|
541
|
+
for (const element of scripts) {
|
|
542
|
+
scriptElementCount += 1;
|
|
543
|
+
let raw;
|
|
544
|
+
for (const child of element.children()) {
|
|
545
|
+
if (child.kind() === "raw_text") {
|
|
546
|
+
raw = child;
|
|
547
|
+
break;
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
if (!raw)
|
|
551
|
+
continue;
|
|
552
|
+
const body = raw.text();
|
|
553
|
+
if (!body.trim())
|
|
554
|
+
continue;
|
|
555
|
+
candidates.push({
|
|
556
|
+
body,
|
|
557
|
+
startIndex: raw.range().start.index,
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
let budgetedBytes = 0;
|
|
561
|
+
const selected = [];
|
|
562
|
+
let truncatedBodies = 0;
|
|
563
|
+
for (const candidate of candidates) {
|
|
564
|
+
const bytes = Buffer.byteLength(candidate.body, "utf8");
|
|
565
|
+
// EVERY body must fit inside both caps — including the first. There is
|
|
566
|
+
// no "one big script" allowance: a single over-cap body (a ~1 MiB dense
|
|
567
|
+
// inline script measured 19.5 s of synchronous rule traversal on this
|
|
568
|
+
// seam) is omitted like any other over-budget body, and the omission is
|
|
569
|
+
// recorded via `truncatedBodies`, so the bounded
|
|
570
|
+
// `ast-grep-napi-html-script-budget` degradation record always explains
|
|
571
|
+
// why that file lost embedded coverage.
|
|
572
|
+
if (selected.length >= MAX_SCRIPT_BODIES_EVALUATED ||
|
|
573
|
+
budgetedBytes + bytes > MAX_SCRIPT_BODY_BYTES_EVALUATED) {
|
|
574
|
+
truncatedBodies += 1;
|
|
575
|
+
continue;
|
|
576
|
+
}
|
|
577
|
+
selected.push(candidate);
|
|
578
|
+
budgetedBytes += bytes;
|
|
579
|
+
}
|
|
580
|
+
const injections = [];
|
|
581
|
+
let parseFailures = 0;
|
|
582
|
+
for (const candidate of selected) {
|
|
583
|
+
try {
|
|
584
|
+
const root = addon.js.parse(candidate.body).root();
|
|
585
|
+
injections.push({
|
|
586
|
+
body: candidate.body,
|
|
587
|
+
startIndex: candidate.startIndex,
|
|
588
|
+
root,
|
|
589
|
+
});
|
|
590
|
+
}
|
|
591
|
+
catch {
|
|
592
|
+
parseFailures += 1;
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
return {
|
|
596
|
+
injections,
|
|
597
|
+
scriptElementCount,
|
|
598
|
+
bodiesEvaluated: selected.length,
|
|
599
|
+
truncatedBodies,
|
|
600
|
+
parseFailures,
|
|
601
|
+
missingJsGrammar: false,
|
|
602
|
+
htmlScanFailure: false,
|
|
603
|
+
};
|
|
604
|
+
}
|
|
605
|
+
/**
|
|
606
|
+
* Emit bounded, discriminating degradation records for every embedded-script
|
|
607
|
+
* coverage loss (#2347 review F3). Each failure mode keeps its own kind so the
|
|
608
|
+
* ledger answers WHICH failure and WHICH file; subjects are the normalized file
|
|
609
|
+
* path, bounded by the ledger's own per-kind window. Collection failures
|
|
610
|
+
* (`missingJsGrammar`, `htmlScanFailure`) are once-per-file-per-session
|
|
611
|
+
* categorical events; parse failures and budget truncation are counted per file
|
|
612
|
+
* so the EXACT totals survive past the retained-entry window.
|
|
613
|
+
*/
|
|
614
|
+
function emitHtmlScriptDegradations(filePath, result) {
|
|
615
|
+
if (result.missingJsGrammar) {
|
|
616
|
+
recordDegradationOnce({
|
|
617
|
+
kind: "ast-grep-napi-html-js-grammar-missing",
|
|
618
|
+
subject: filePath,
|
|
619
|
+
reason: "addon exposes no js grammar; embedded <script> coverage dropped",
|
|
620
|
+
});
|
|
621
|
+
}
|
|
622
|
+
if (result.htmlScanFailure) {
|
|
623
|
+
recordDegradationOnce({
|
|
624
|
+
kind: "ast-grep-napi-html-script-scan-failed",
|
|
625
|
+
subject: filePath,
|
|
626
|
+
reason: "script_element enumeration failed; embedded <script> coverage dropped",
|
|
627
|
+
});
|
|
628
|
+
}
|
|
629
|
+
if (result.parseFailures > 0) {
|
|
630
|
+
incrementDegradationCount({
|
|
631
|
+
kind: "ast-grep-napi-html-script-parse-failed",
|
|
632
|
+
subject: filePath,
|
|
633
|
+
reason: `${result.parseFailures} of ${result.bodiesEvaluated} script bodies refused to parse as JS`,
|
|
634
|
+
metadata: {
|
|
635
|
+
scriptElementCount: result.scriptElementCount,
|
|
636
|
+
parseFailures: result.parseFailures,
|
|
637
|
+
},
|
|
638
|
+
});
|
|
639
|
+
}
|
|
640
|
+
if (result.truncatedBodies > 0) {
|
|
641
|
+
incrementDegradationCount({
|
|
642
|
+
kind: "ast-grep-napi-html-script-budget",
|
|
643
|
+
subject: filePath,
|
|
644
|
+
reason: `script budget truncated coverage: ${result.bodiesEvaluated}/${result.scriptElementCount} bodies evaluated, ${result.truncatedBodies} dropped`,
|
|
645
|
+
metadata: {
|
|
646
|
+
scriptElementCount: result.scriptElementCount,
|
|
647
|
+
bodiesEvaluated: result.bodiesEvaluated,
|
|
648
|
+
truncatedBodies: result.truncatedBodies,
|
|
649
|
+
},
|
|
650
|
+
});
|
|
651
|
+
}
|
|
652
|
+
}
|
|
439
653
|
function duplicateRuleIds(rules) {
|
|
440
654
|
const counts = new Map();
|
|
441
655
|
for (const rule of rules) {
|
|
@@ -512,6 +726,38 @@ export function evaluateAstGrepRules(filePath, rootNode, cwd, kind, options = {}
|
|
|
512
726
|
const seenRuleIds = new Set();
|
|
513
727
|
const suppressLinterOverlap = kind === "jsts" && hasEslintConfig(cwd);
|
|
514
728
|
const fileLang = ruleLanguageForFile(filePath);
|
|
729
|
+
// Embedded `<script>` coverage (#2347): on an HTML file, every script body
|
|
730
|
+
// is parsed as JavaScript and `language: JavaScript` rules run inside it —
|
|
731
|
+
// the exact behavior the ast-grep CLI/LSP has (verified against 0.45.1).
|
|
732
|
+
// `content` + `sgModule` are only needed for HTML; other callers of this
|
|
733
|
+
// shared seam (the per-edit runner and the project scanner both now pass
|
|
734
|
+
// them) cost a no-op on non-HTML files. The collection is budget-bounded
|
|
735
|
+
// and every silent-failure mode plus the budget cut is recorded, so "no
|
|
736
|
+
// embedded findings" stays distinguishable from "coverage was dropped"
|
|
737
|
+
// (#2347 review F2/F3).
|
|
738
|
+
const htmlCollection = fileLang === "html" &&
|
|
739
|
+
options.content !== undefined &&
|
|
740
|
+
options.sgModule !== undefined
|
|
741
|
+
? collectHtmlScriptInjections(rootNode, options.sgModule)
|
|
742
|
+
: {
|
|
743
|
+
injections: [],
|
|
744
|
+
scriptElementCount: 0,
|
|
745
|
+
bodiesEvaluated: 0,
|
|
746
|
+
truncatedBodies: 0,
|
|
747
|
+
parseFailures: 0,
|
|
748
|
+
missingJsGrammar: false,
|
|
749
|
+
htmlScanFailure: false,
|
|
750
|
+
};
|
|
751
|
+
const htmlInjections = htmlCollection.injections;
|
|
752
|
+
emitHtmlScriptDegradations(filePath, htmlCollection);
|
|
753
|
+
// UTF-16 code-unit index of each line start in the ORIGINAL file, used to
|
|
754
|
+
// translate an injected match's body-relative UTF-16 index back to file
|
|
755
|
+
// line/column. The unit matters: napi positions are UTF-16, so a UTF-8 byte
|
|
756
|
+
// table would shift every coordinate after a multibyte character (#2347
|
|
757
|
+
// review F1).
|
|
758
|
+
const fileLineStarts = htmlInjections.length > 0 && options.content !== undefined
|
|
759
|
+
? computeLineStartsUtf16(options.content)
|
|
760
|
+
: [];
|
|
515
761
|
// Unsupported-language skips are expected in bulk (every non-jsts rule in the
|
|
516
762
|
// catalog, e.g. ~30 Python rules) — aggregate them into ONE latency-log entry
|
|
517
763
|
// per evaluation instead of per-rule terminal lines (#282 follow-up).
|
|
@@ -547,6 +793,18 @@ export function evaluateAstGrepRules(filePath, rootNode, cwd, kind, options = {}
|
|
|
547
793
|
// ship for a language nobody decided a route for, which is the
|
|
548
794
|
// class this issue closed regrowing.
|
|
549
795
|
route: skipRouteFor(language),
|
|
796
|
+
// #2347 observability: on an HTML file the per-language skip
|
|
797
|
+
// count is only part of the picture — `mismatch:*->html`
|
|
798
|
+
// entries name a rule family that never enters scripts, and
|
|
799
|
+
// `htmlInlineScriptCount` says whether the file offered any
|
|
800
|
+
// script bodies to enter. A `javascript->html` mismatch here
|
|
801
|
+
// is necessarily `0` (JS rules RUN when scripts exist), so the
|
|
802
|
+
// field makes "no injection target" distinguishable from the
|
|
803
|
+
// same key on a plain non-HTML file, keeping the residual
|
|
804
|
+
// coverage gap countable in production.
|
|
805
|
+
...(fileLang === "html"
|
|
806
|
+
? { htmlInlineScriptCount: htmlInjections.length }
|
|
807
|
+
: {}),
|
|
550
808
|
},
|
|
551
809
|
])),
|
|
552
810
|
},
|
|
@@ -627,9 +885,20 @@ export function evaluateAstGrepRules(filePath, rootNode, cwd, kind, options = {}
|
|
|
627
885
|
// rules) goes dark on every .tsx file. `language: TSX` rules
|
|
628
886
|
// stay tsx-exclusive — they're already scoped to fileLang
|
|
629
887
|
// "tsx" by the exact-match check.
|
|
888
|
+
// #2347: `language: JavaScript` rules run INSIDE an HTML file's
|
|
889
|
+
// embedded `<script>` bodies instead of being filtered out as a
|
|
890
|
+
// language mismatch — that filter is what closed napi's embedded
|
|
891
|
+
// coverage entirely while the ast-grep CLI/LSP resolves the
|
|
892
|
+
// injections itself. Only when the file has at least one inline
|
|
893
|
+
// script body; with none, a `javascript->html` rule stays a
|
|
894
|
+
// genuine mismatch with nothing to run against (countable via
|
|
895
|
+
// `htmlInlineScriptCount` in the skip record).
|
|
896
|
+
const runsInsideHtmlScript = fileLang === "html" &&
|
|
897
|
+
lang === "javascript" &&
|
|
898
|
+
htmlInjections.length > 0;
|
|
630
899
|
if (lang && fileLang && lang !== fileLang) {
|
|
631
900
|
const runsAsTsOnTsx = fileLang === "tsx" && lang === "typescript";
|
|
632
|
-
if (!runsAsTsOnTsx) {
|
|
901
|
+
if (!runsAsTsOnTsx && !runsInsideHtmlScript) {
|
|
633
902
|
const key = `mismatch:${lang}->${fileLang}`;
|
|
634
903
|
if (!unsupportedLanguageLog.has(key)) {
|
|
635
904
|
const ids = newlyUnsupported.get(key) ?? [];
|
|
@@ -648,7 +917,31 @@ export function evaluateAstGrepRules(filePath, rootNode, cwd, kind, options = {}
|
|
|
648
917
|
if (!rule.rule)
|
|
649
918
|
continue;
|
|
650
919
|
try {
|
|
651
|
-
|
|
920
|
+
// A `language: JavaScript` rule on an HTML file with inline
|
|
921
|
+
// scripts runs against EACH parsed script body; every other rule
|
|
922
|
+
// runs against the file root. `scope.position` maps a match onto
|
|
923
|
+
// 0-based FILE line/column — injection matches are body-relative
|
|
924
|
+
// and must be translated via the injection's `startIndex` and the
|
|
925
|
+
// file's line-start table, all in UTF-16 code units (#2347); the
|
|
926
|
+
// file-root scope is the node's own range, so its derived
|
|
927
|
+
// id/diagnostic stay byte-identical to the pre-#2347 path.
|
|
928
|
+
const scopes = runsInsideHtmlScript
|
|
929
|
+
? htmlInjections.map((injection) => ({
|
|
930
|
+
root: injection.root,
|
|
931
|
+
position(match) {
|
|
932
|
+
const start = match.range().start;
|
|
933
|
+
return filePositionForIndex(fileLineStarts, injection.startIndex + start.index);
|
|
934
|
+
},
|
|
935
|
+
}))
|
|
936
|
+
: [
|
|
937
|
+
{
|
|
938
|
+
root: rootNode,
|
|
939
|
+
position(match) {
|
|
940
|
+
const start = match.range().start;
|
|
941
|
+
return { line: start.line, column: start.column };
|
|
942
|
+
},
|
|
943
|
+
},
|
|
944
|
+
];
|
|
652
945
|
// Delegate matching to napi's native engine, which handles the
|
|
653
946
|
// full ast-grep rule grammar (pattern, kind, has/inside/follows/
|
|
654
947
|
// precedes/stopBy/field/nthChild, any/all/not) plus metavariable
|
|
@@ -657,28 +950,41 @@ export function evaluateAstGrepRules(filePath, rootNode, cwd, kind, options = {}
|
|
|
657
950
|
// (#663; `NapiConfig.utils: Record<string, Rule>` per
|
|
658
951
|
// @ast-grep/napi's types, same shape napi already expects for
|
|
659
952
|
// `rule`/`constraints`). A faithful js-yaml parse feeds the rule
|
|
660
|
-
// object straight through. If napi rejects the rule
|
|
661
|
-
// or invalid-kind rule, or an unresolved `matches:`
|
|
662
|
-
// skip
|
|
663
|
-
// interpreter.
|
|
953
|
+
// object straight through. If napi rejects the rule for a scope
|
|
954
|
+
// (a malformed or invalid-kind rule, or an unresolved `matches:`
|
|
955
|
+
// reference), skip that scope — never silently match nothing
|
|
956
|
+
// through a partial interpreter. The reject log fires once per
|
|
957
|
+
// rule; a grammar-level rejection is uniform across scopes.
|
|
664
958
|
const nativeConfig = { rule: rule.rule };
|
|
665
959
|
if (rule.constraints)
|
|
666
960
|
nativeConfig.constraints = rule.constraints;
|
|
667
961
|
if (rule.utils)
|
|
668
962
|
nativeConfig.utils = rule.utils;
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
963
|
+
const collected = [];
|
|
964
|
+
let rejectLogged = false;
|
|
965
|
+
for (const scope of scopes) {
|
|
966
|
+
let found;
|
|
967
|
+
try {
|
|
968
|
+
found = scope.root.findAll(nativeConfig);
|
|
969
|
+
}
|
|
970
|
+
catch (err) {
|
|
971
|
+
if (!rejectLogged) {
|
|
972
|
+
rejectLogged = true;
|
|
973
|
+
log?.(`ast-grep-napi: rule "${rule.id}" rejected by native engine (${err instanceof Error ? err.message : String(err)})`);
|
|
974
|
+
}
|
|
975
|
+
continue;
|
|
976
|
+
}
|
|
977
|
+
for (const match of found) {
|
|
978
|
+
if (collected.length >= maxMatchesPerRule)
|
|
979
|
+
break;
|
|
980
|
+
collected.push({ match, position: scope.position(match) });
|
|
981
|
+
}
|
|
982
|
+
if (collected.length >= maxMatchesPerRule)
|
|
983
|
+
break;
|
|
675
984
|
}
|
|
676
|
-
const
|
|
677
|
-
for (const match of limitedMatches) {
|
|
985
|
+
for (const { position } of collected) {
|
|
678
986
|
if (diagnostics.length >= maxTotalDiagnostics)
|
|
679
987
|
break;
|
|
680
|
-
const node = match;
|
|
681
|
-
const range = node.range();
|
|
682
988
|
// #1777: carry the rule's own tier through. The old collapse
|
|
683
989
|
// (`=== "error" ? "error" : "warning"`) erased hint and info,
|
|
684
990
|
// so the quiet tier the #1727 anti-slop rules ship at did not
|
|
@@ -691,11 +997,11 @@ export function evaluateAstGrepRules(filePath, rootNode, cwd, kind, options = {}
|
|
|
691
997
|
const defectClass = classifyDefect(rule.id, "ast-grep-napi", rule.message || rule.id);
|
|
692
998
|
const ruleFix = explicitRuleFixSuggestion(rule);
|
|
693
999
|
diagnostics.push({
|
|
694
|
-
id: `ast-grep-napi-${
|
|
1000
|
+
id: `ast-grep-napi-${position.line}-${rule.id}`,
|
|
695
1001
|
message: `[${rule.metadata?.category || "slop"}] ${rule.message || rule.id}`,
|
|
696
1002
|
filePath,
|
|
697
|
-
line:
|
|
698
|
-
column:
|
|
1003
|
+
line: position.line + 1,
|
|
1004
|
+
column: position.column + 1,
|
|
699
1005
|
severity,
|
|
700
1006
|
semantic,
|
|
701
1007
|
tool: "ast-grep-napi",
|
|
@@ -725,7 +1031,6 @@ const astGrepNapiRunner = {
|
|
|
725
1031
|
id: "ast-grep-napi",
|
|
726
1032
|
appliesTo: ["jsts", "css", "html"],
|
|
727
1033
|
priority: PRIORITY.SPECIALIZED_ANALYSIS,
|
|
728
|
-
enabledByDefault: true,
|
|
729
1034
|
skipTestFiles: true,
|
|
730
1035
|
async run(ctx) {
|
|
731
1036
|
if (!canHandle(ctx.filePath)) {
|
|
@@ -812,7 +1117,12 @@ const astGrepNapiRunner = {
|
|
|
812
1117
|
catch {
|
|
813
1118
|
return { status: "skipped", diagnostics: [], semantic: "none" };
|
|
814
1119
|
}
|
|
815
|
-
|
|
1120
|
+
// #2336: napi is standing in for the ast-grep auxiliary LSP exactly when
|
|
1121
|
+
// that server is expected but has not published for this root. Gate B
|
|
1122
|
+
// above already returned for the published case, so reaching here with
|
|
1123
|
+
// the auxiliary enabled IS the substitute role.
|
|
1124
|
+
const runningAsLspSubstitute = astGrepLspEnabled && !astGrepLspPublished;
|
|
1125
|
+
if (runningAsLspSubstitute) {
|
|
816
1126
|
// #2324 F3/R2-A/R2-B: napi is about to ACTUALLY EVALUATE RULES —
|
|
817
1127
|
// every early-return skip above (load failure, missing file,
|
|
818
1128
|
// unresolved language, stat/size/read/parse failure) is now behind
|
|
@@ -837,11 +1147,57 @@ const astGrepNapiRunner = {
|
|
|
837
1147
|
recordNapiFallbackCoverage(ctx.filePath);
|
|
838
1148
|
clearPendingAuxiliaryCoverage(ctx.filePath, "ast-grep");
|
|
839
1149
|
}
|
|
1150
|
+
// #2336: the substitute runs at the severity floor the server it replaces
|
|
1151
|
+
// would have used. The ast-grep auxiliary profile states that floor in
|
|
1152
|
+
// words — "the rule severity is deliberate, so preserve ast-grep's
|
|
1153
|
+
// severity semantics: ERROR can block, WARNING/INFO stay advisory"
|
|
1154
|
+
// (clients/dispatch/auxiliary-lsp.ts:179-183). `blockingOnly` drops every
|
|
1155
|
+
// rule whose declared severity is not `error`, which is 380 of the 481
|
|
1156
|
+
// bundled rules, so the substitute delivered a fifth of the coverage the
|
|
1157
|
+
// LSP delivers and the runner reported zero diagnostics in all 255
|
|
1158
|
+
// retained dispatch records. Nothing downstream needs the filter for
|
|
1159
|
+
// noise control: `dispatcher.ts` already shows only `semantic:
|
|
1160
|
+
// "blocking"` diagnostics inline and routes warning-tier ones to
|
|
1161
|
+
// lens_diagnostics, and `tree-sitter.ts:525` already runs its full query
|
|
1162
|
+
// set under `blockingOnly` for the same reason.
|
|
1163
|
+
//
|
|
1164
|
+
// Scoped to the substitute role deliberately. Evaluating the full catalog
|
|
1165
|
+
// costs ~6x more per file (measured on this repo: 2.4 ms -> 23 ms at 68
|
|
1166
|
+
// lines, 19 ms -> 188 ms at 1275 lines), and outside the substitute role
|
|
1167
|
+
// either the LSP is publishing (Gate B skipped napi already) or the user
|
|
1168
|
+
// retired ast-grep with `no-ast-grep`. Paying the cost only when napi is
|
|
1169
|
+
// the sole ast-grep surface buys coverage that nothing else provides.
|
|
840
1170
|
const diagnostics = evaluateAstGrepRules(ctx.filePath, rootNode, ctx.cwd, ctx.kind, {
|
|
841
|
-
blockingOnly: ctx.blockingOnly,
|
|
1171
|
+
blockingOnly: runningAsLspSubstitute ? false : ctx.blockingOnly,
|
|
842
1172
|
projectRoot: ctx.projectRoot,
|
|
843
1173
|
log: (message) => ctx.log(message),
|
|
1174
|
+
content,
|
|
1175
|
+
sgModule,
|
|
844
1176
|
});
|
|
1177
|
+
if (runningAsLspSubstitute) {
|
|
1178
|
+
// #2336 observability: the dispatcher's own runner record carries
|
|
1179
|
+
// `diagnosticCount`, which is what showed 0 of 255. It cannot say WHICH
|
|
1180
|
+
// severity floor produced that count. One line per substitute run —
|
|
1181
|
+
// the same cadence as the runner record it annotates — names the floor
|
|
1182
|
+
// and the tier mix, so a future "napi found nothing" reading can tell
|
|
1183
|
+
// an empty catalog pass from a filtered one.
|
|
1184
|
+
const bySeverity = {};
|
|
1185
|
+
for (const d of diagnostics) {
|
|
1186
|
+
bySeverity[d.severity] = (bySeverity[d.severity] ?? 0) + 1;
|
|
1187
|
+
}
|
|
1188
|
+
logLatency({
|
|
1189
|
+
type: "phase",
|
|
1190
|
+
phase: "astgrep_napi_substitute_floor",
|
|
1191
|
+
filePath: ctx.filePath,
|
|
1192
|
+
durationMs: 0,
|
|
1193
|
+
metadata: {
|
|
1194
|
+
floor: "lsp-equivalent",
|
|
1195
|
+
ctxBlockingOnly: ctx.blockingOnly === true,
|
|
1196
|
+
diagnosticCount: diagnostics.length,
|
|
1197
|
+
bySeverity,
|
|
1198
|
+
},
|
|
1199
|
+
});
|
|
1200
|
+
}
|
|
845
1201
|
const hasBlocking = diagnostics.some((d) => d.semantic === "blocking");
|
|
846
1202
|
let semantic = "none";
|
|
847
1203
|
if (hasBlocking) {
|
|
@@ -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);
|
|
@@ -97,6 +97,10 @@ async function resolveCompiler(absPath, cwd) {
|
|
|
97
97
|
flavor: "msvc",
|
|
98
98
|
};
|
|
99
99
|
}
|
|
100
|
+
// Mirrors the deliberate global-PATH probes in utils/runner-helpers.ts:
|
|
101
|
+
// this never resolves a config file or a target path, so there is no cwd
|
|
102
|
+
// for it to get wrong.
|
|
103
|
+
// cwd-exempt: presence probe only -- `cl` with no args and no target file, used solely to detect whether MSVC is on PATH
|
|
100
104
|
const clProbe = await safeSpawnAsync("cl", [], { timeout: 5000 });
|
|
101
105
|
if (!clProbe.error && clProbe.status !== null) {
|
|
102
106
|
return {
|
|
@@ -175,7 +179,6 @@ const cppCheckRunner = {
|
|
|
175
179
|
id: "cpp-check",
|
|
176
180
|
appliesTo: ["cxx"],
|
|
177
181
|
priority: PRIORITY.GENERAL_ANALYSIS,
|
|
178
|
-
enabledByDefault: true,
|
|
179
182
|
skipTestFiles: false,
|
|
180
183
|
async run(ctx) {
|
|
181
184
|
const cwd = ctx.cwd || process.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)
|