@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
|
@@ -23,39 +23,7 @@ import { isBlocking, reconcileScanDiagnostics, } from "../clients/widget-state.j
|
|
|
23
23
|
import { baseName, compactRenderResult } from "./render-compact.js";
|
|
24
24
|
import { makeProgressReporter, scanningSummaryLine } from "./scan-progress.js";
|
|
25
25
|
import { isWarmAttached, tryWarmAttachedDiagnostics, } from "../clients/warm-attach.js";
|
|
26
|
-
|
|
27
|
-
".ts": [".ts", ".tsx", ".mts", ".cts"],
|
|
28
|
-
".tsx": [".ts", ".tsx", ".mts", ".cts"],
|
|
29
|
-
".js": [".js", ".jsx", ".mjs", ".cjs"],
|
|
30
|
-
".py": [".py", ".pyi"],
|
|
31
|
-
".rs": [".rs"],
|
|
32
|
-
".go": [".go"],
|
|
33
|
-
".rb": [".rb", ".rake", ".gemspec"],
|
|
34
|
-
".java": [".java"],
|
|
35
|
-
".kt": [".kt", ".kts"],
|
|
36
|
-
".swift": [".swift"],
|
|
37
|
-
".cs": [".cs"],
|
|
38
|
-
".cpp": [".cpp", ".cc", ".cxx", ".hpp", ".hxx"],
|
|
39
|
-
".c": [".c", ".h"],
|
|
40
|
-
".zig": [".zig", ".zon"],
|
|
41
|
-
".hs": [".hs", ".lhs"],
|
|
42
|
-
".ex": [".ex", ".exs"],
|
|
43
|
-
".gleam": [".gleam"],
|
|
44
|
-
".tf": [".tf", ".tfvars"],
|
|
45
|
-
".nix": [".nix"],
|
|
46
|
-
".sh": [".sh", ".bash", ".zsh"],
|
|
47
|
-
".php": [".php"],
|
|
48
|
-
".lua": [".lua"],
|
|
49
|
-
".dart": [".dart"],
|
|
50
|
-
".vue": [".vue"],
|
|
51
|
-
".svelte": [".svelte"],
|
|
52
|
-
".css": [".css", ".scss", ".less"],
|
|
53
|
-
".html": [".html", ".htm"],
|
|
54
|
-
".json": [".json", ".jsonc"],
|
|
55
|
-
".yaml": [".yaml", ".yml"],
|
|
56
|
-
".toml": [".toml"],
|
|
57
|
-
".prisma": [".prisma"],
|
|
58
|
-
};
|
|
26
|
+
import { extensionsForLanguage, SCAN_LANGUAGE_PRIORITY, } from "../clients/language-registry.js";
|
|
59
27
|
const MAX_FILES = 100;
|
|
60
28
|
const MAX_BATCH_FILES = 100;
|
|
61
29
|
const MAX_DIAGNOSTICS = 200;
|
|
@@ -192,9 +160,10 @@ function projectIgnorePredicate(root) {
|
|
|
192
160
|
* This walk was fully synchronous with NO yielding of any kind, bounded only by
|
|
193
161
|
* `maxFiles` *kept* — an ignored-heavy or cloud-backed (OneDrive/network) tree
|
|
194
162
|
* could traverse unboundedly many entries, and a single stalled `readdirSync`
|
|
195
|
-
* held the loop for the whole stall. It is also called once PER
|
|
196
|
-
* `runDirectoryDiagnostics`'s `
|
|
197
|
-
*
|
|
163
|
+
* held the loop for the whole stall. It is also called once PER FAMILY in
|
|
164
|
+
* `runDirectoryDiagnostics`'s `SCAN_LANGUAGE_PRIORITY` loop (#2434, grouped by
|
|
165
|
+
* family since #2458 fix-round F1), so a directory-mode `lsp_diagnostics`
|
|
166
|
+
* could pay that cost several times over.
|
|
198
167
|
*
|
|
199
168
|
* The traversal is deliberately still **depth-first with immediate descent**
|
|
200
169
|
* (not the shared stack-based `walkTreeStackAsync`): the `maxFiles` cap makes
|
|
@@ -276,6 +245,10 @@ onConfirmedNoBlockers) {
|
|
|
276
245
|
// compact-render as a bare "N diagnostics" — that erases the fact some
|
|
277
246
|
// files' clean status was never actually confirmed by the server.
|
|
278
247
|
const unconfirmedFiles = details?.unconfirmedFiles ?? 0;
|
|
248
|
+
const navigationOnlyFiles = details?.navigationOnlyFiles ?? 0;
|
|
249
|
+
if (navigationOnlyFiles > 0) {
|
|
250
|
+
return `lsp_diagnostics${scope} — ${count} ${noun} · ${details?.cleanFiles ?? 0} clean · ${navigationOnlyFiles} navigation-only`;
|
|
251
|
+
}
|
|
279
252
|
if (unconfirmedFiles > 0) {
|
|
280
253
|
const cleanFiles = details?.cleanFiles ?? 0;
|
|
281
254
|
const timedOutFiles = details?.timedOutFiles ?? 0;
|
|
@@ -456,13 +429,17 @@ async function collectDiagnosticsForFile(absPath, lspService, waitMs, serverScop
|
|
|
456
429
|
// `touchFile` is the authoritative collection boundary for every scope: it
|
|
457
430
|
// preserves per-touch timeout, content-binding, and silent-clean confirmation
|
|
458
431
|
// metadata while returning diagnostics from only the requested clients. The
|
|
459
|
-
//
|
|
460
|
-
//
|
|
432
|
+
// getDiagnostics fallback below remains for the two states a REAL service
|
|
433
|
+
// still reaches: the file read threw (no content to touch with), or the
|
|
434
|
+
// touch resolved no clients and returned `undefined` (clients/lsp/index.ts
|
|
435
|
+
// `touchFile`'s `no_clients`/`destroyed` returns). #2598 deleted the third
|
|
436
|
+
// reason — "an older/mock service without touchFile" — because the real
|
|
437
|
+
// `LSPService` has always defined the method unconditionally, so that arm
|
|
438
|
+
// was reachable only from a partial test double (AGENTS.md shape 7).
|
|
461
439
|
// #1179: the result is an explicit wrapper so side-channel fields survive
|
|
462
440
|
// array copies; confirmation was added when Marksman's lower-level clean verdict
|
|
463
441
|
// proved that a successful empty collection also needs explicit provenance.
|
|
464
442
|
let touched;
|
|
465
|
-
let usedTouch = false;
|
|
466
443
|
try {
|
|
467
444
|
content = fs.readFileSync(absPath, "utf-8");
|
|
468
445
|
if (isWarmAttached()) {
|
|
@@ -497,39 +474,30 @@ async function collectDiagnosticsForFile(absPath, lspService, waitMs, serverScop
|
|
|
497
474
|
// field across the socket. An older incumbent omits it → empty → the
|
|
498
475
|
// pre-#1470 handling, unchanged.
|
|
499
476
|
unconfirmedServerIds: attached.response.unconfirmedServerIds ?? [],
|
|
477
|
+
diagnosticsUnsupportedServerIds: [],
|
|
500
478
|
content,
|
|
501
479
|
};
|
|
502
480
|
}
|
|
503
481
|
}
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
clientScope: serverScope,
|
|
513
|
-
});
|
|
514
|
-
timedOut = touched?.inconclusive === true;
|
|
515
|
-
}
|
|
516
|
-
else {
|
|
517
|
-
await lspService.openFile(absPath, content, {
|
|
518
|
-
preserveDiagnostics: false,
|
|
519
|
-
});
|
|
520
|
-
}
|
|
482
|
+
touched = await lspService.touchFile(absPath, content, {
|
|
483
|
+
diagnostics: "document",
|
|
484
|
+
collectDiagnostics: true,
|
|
485
|
+
maxClientWaitMs: waitMs,
|
|
486
|
+
source: "lsp_diagnostics",
|
|
487
|
+
clientScope: serverScope,
|
|
488
|
+
});
|
|
489
|
+
timedOut = touched?.inconclusive === true;
|
|
521
490
|
}
|
|
522
491
|
catch {
|
|
523
492
|
// Non-fatal: getDiagnostics may still have stale/health information.
|
|
524
493
|
}
|
|
525
494
|
// Only fall through to the unscoped getDiagnostics() read when the touch
|
|
526
|
-
//
|
|
527
|
-
//
|
|
528
|
-
//
|
|
529
|
-
//
|
|
530
|
-
//
|
|
531
|
-
|
|
532
|
-
const diagnostics = usedTouch && touched !== undefined
|
|
495
|
+
// produced nothing to read — it threw, the file read threw before it ran, or
|
|
496
|
+
// it resolved no clients at all. When touched IS defined it's already the
|
|
497
|
+
// answer — reusing it is what makes serverScope:"primary" actually skip
|
|
498
|
+
// auxiliary scanners and drops the common case back to a single LSP round
|
|
499
|
+
// trip instead of two.
|
|
500
|
+
const diagnostics = touched !== undefined
|
|
533
501
|
? touched.diags
|
|
534
502
|
: await lspService.getDiagnostics(absPath, waitMs !== undefined ? "document" : "full");
|
|
535
503
|
// #586: honor each auxiliary profile's native inline-suppression comment
|
|
@@ -546,25 +514,26 @@ async function collectDiagnosticsForFile(absPath, lspService, waitMs, serverScop
|
|
|
546
514
|
fileRole: detectFileRole(absPath, content),
|
|
547
515
|
})
|
|
548
516
|
: diagnostics;
|
|
549
|
-
// #1095: surface the touch's content binding (only
|
|
550
|
-
// one; the
|
|
517
|
+
// #1095: surface the touch's content binding (only a touch that resolved
|
|
518
|
+
// clients carries one; the getDiagnostics fallback leaves it undefined →
|
|
551
519
|
// "unknown", no demotion).
|
|
552
|
-
const binding =
|
|
520
|
+
const binding = touched?.binding;
|
|
553
521
|
// #1470: `"partial"` counts here. `confirmedByTouch` feeds
|
|
554
522
|
// `canTrustTouchConfirmation`, which asks about the PRIMARY's own verdict —
|
|
555
523
|
// and a partial touch is one whose primary confirmed while an auxiliary was
|
|
556
524
|
// cut off. Excluding it would render "Primary LSP: unconfirmed" for a primary
|
|
557
525
|
// that did confirm. The coverage gap is carried separately, below.
|
|
558
|
-
const confirmedByTouch =
|
|
526
|
+
const confirmedByTouch = touchCompletedConfirmationPolicy(touched);
|
|
559
527
|
return {
|
|
560
528
|
diagnostics: filtered,
|
|
561
529
|
timedOut,
|
|
562
530
|
skipReason: touched?.skipReason,
|
|
563
531
|
confirmedByTouch,
|
|
564
|
-
// #1470: only a touch
|
|
565
|
-
//
|
|
566
|
-
//
|
|
567
|
-
unconfirmedServerIds:
|
|
532
|
+
// #1470: only a touch that resolved clients contributes a coverage gap;
|
|
533
|
+
// the getDiagnostics fallback never reports one, which is honest — that
|
|
534
|
+
// path claims no confirmation at all.
|
|
535
|
+
unconfirmedServerIds: touchCoverageGap(touched),
|
|
536
|
+
diagnosticsUnsupportedServerIds: touched?.diagnosticsUnsupportedServerIds ?? [],
|
|
568
537
|
content,
|
|
569
538
|
binding,
|
|
570
539
|
};
|
|
@@ -814,7 +783,7 @@ onConfirmedNoBlockers) {
|
|
|
814
783
|
};
|
|
815
784
|
}
|
|
816
785
|
}
|
|
817
|
-
const { diagnostics: rawDiags, timedOut, confirmedByTouch, unconfirmedServerIds, content: collectedContent, binding, skipReason, } = await collectDiagnosticsForFile(file, lspService, waitMs, serverScope);
|
|
786
|
+
const { diagnostics: rawDiags, timedOut, confirmedByTouch, unconfirmedServerIds, diagnosticsUnsupportedServerIds, content: collectedContent, binding, skipReason, } = await collectDiagnosticsForFile(file, lspService, waitMs, serverScope);
|
|
818
787
|
const health = lspService.getDiagnosticsHealth?.(file);
|
|
819
788
|
// #570: a timed-out priming check is never a confirmed "clean" — treat it
|
|
820
789
|
// as unconfirmed without consulting the (unrelated) silent-tier
|
|
@@ -825,7 +794,12 @@ onConfirmedNoBlockers) {
|
|
|
825
794
|
// be merged in rather than discarded.
|
|
826
795
|
let effectiveRawDiags = rawDiags;
|
|
827
796
|
let confirmation;
|
|
828
|
-
if (
|
|
797
|
+
if (diagnosticsUnsupportedServerIds.length > 0) {
|
|
798
|
+
// No diagnostic provider and no push evidence is a capability boundary,
|
|
799
|
+
// not a clean result and not a timeout.
|
|
800
|
+
confirmation = undefined;
|
|
801
|
+
}
|
|
802
|
+
else if (skipReason !== undefined) {
|
|
829
803
|
confirmation = "unconfirmed";
|
|
830
804
|
}
|
|
831
805
|
else if (timedOut) {
|
|
@@ -888,6 +862,7 @@ onConfirmedNoBlockers) {
|
|
|
888
862
|
if (cacheCtx &&
|
|
889
863
|
scopeKey !== undefined &&
|
|
890
864
|
confirmation !== "unconfirmed" &&
|
|
865
|
+
diagnosticsUnsupportedServerIds.length === 0 &&
|
|
891
866
|
unconfirmedServerIds.length === 0) {
|
|
892
867
|
cacheCtx.record(file, scopeKey, effectiveRawDiags, stat.mtimeMs, collectedContent !== undefined
|
|
893
868
|
? hashDiagnosticContent(collectedContent)
|
|
@@ -901,6 +876,7 @@ onConfirmedNoBlockers) {
|
|
|
901
876
|
timedOut: confirmation === "unconfirmed" ? timedOut : undefined,
|
|
902
877
|
...(skipReason !== undefined && { skipReason }),
|
|
903
878
|
primaryServerId: primaryServerId(file),
|
|
879
|
+
diagnosticsUnsupported: diagnosticsUnsupportedServerIds.length > 0,
|
|
904
880
|
};
|
|
905
881
|
}
|
|
906
882
|
async function runFileDiagnostics(absPath, severity, lspService, waitMs, nextWriteIndex, serverScope = "all", cwd = process.cwd(),
|
|
@@ -910,7 +886,7 @@ onConfirmedNoBlockers) {
|
|
|
910
886
|
// Reserve the token before awaiting this file's LSP result. The direct-file
|
|
911
887
|
// path performs its own confirmation/reconciliation below (#1198).
|
|
912
888
|
const writeIndex = nextWriteIndex?.();
|
|
913
|
-
const { diagnostics: rawDiags, timedOut, confirmedByTouch, unconfirmedServerIds, content: collectedContent, binding, skipReason, } = await collectDiagnosticsForFile(absPath, lspService, waitMs, serverScope);
|
|
889
|
+
const { diagnostics: rawDiags, timedOut, confirmedByTouch, unconfirmedServerIds, diagnosticsUnsupportedServerIds, content: collectedContent, binding, skipReason, } = await collectDiagnosticsForFile(absPath, lspService, waitMs, serverScope);
|
|
914
890
|
const lspHealth = lspService.getDiagnosticsHealth?.(absPath);
|
|
915
891
|
const unavailable = lspUnavailableMessage(absPath, lspHealth);
|
|
916
892
|
// #533: an empty result needs a confirmed/unconfirmed verdict — a push-only,
|
|
@@ -924,7 +900,10 @@ onConfirmedNoBlockers) {
|
|
|
924
900
|
// diagnostics it surfaces are merged in, not discarded.
|
|
925
901
|
let effectiveRawDiags = rawDiags;
|
|
926
902
|
let confirmation;
|
|
927
|
-
if (
|
|
903
|
+
if (diagnosticsUnsupportedServerIds.length > 0) {
|
|
904
|
+
confirmation = undefined;
|
|
905
|
+
}
|
|
906
|
+
else if (skipReason !== undefined) {
|
|
928
907
|
confirmation = "unconfirmed";
|
|
929
908
|
}
|
|
930
909
|
else if (timedOut) {
|
|
@@ -992,6 +971,9 @@ onConfirmedNoBlockers) {
|
|
|
992
971
|
// auxiliary findings exist — a wall of ast-grep/opengrep noise must never
|
|
993
972
|
// bury whether the actual language server confirmed the file clean.
|
|
994
973
|
const primaryLine = (() => {
|
|
974
|
+
if (diagnosticsUnsupportedServerIds.length > 0) {
|
|
975
|
+
return `Primary LSP${primaryId ? ` (${primaryId})` : ""}: navigation-only — diagnostics unsupported (no pull provider or publish evidence).`;
|
|
976
|
+
}
|
|
995
977
|
if (timedOut) {
|
|
996
978
|
return ("Primary LSP: check timed out — NOT the same as 0 diagnostics; the " +
|
|
997
979
|
"file may still have errors that just hadn't been reported yet. " +
|
|
@@ -1068,6 +1050,7 @@ onConfirmedNoBlockers) {
|
|
|
1068
1050
|
truncated,
|
|
1069
1051
|
unconfirmed,
|
|
1070
1052
|
timedOut: unconfirmed ? timedOut : undefined,
|
|
1053
|
+
navigationOnlyFiles: diagnosticsUnsupportedServerIds.length > 0 ? 1 : undefined,
|
|
1071
1054
|
...(skipReason !== undefined && { skipReason }),
|
|
1072
1055
|
// #1470: which servers this result does NOT speak for. Absent when it
|
|
1073
1056
|
// speaks for all of them.
|
|
@@ -1091,7 +1074,12 @@ function tallyConfirmation(results) {
|
|
|
1091
1074
|
let clean = 0;
|
|
1092
1075
|
let unconfirmed = 0;
|
|
1093
1076
|
let timedOut = 0;
|
|
1077
|
+
let navigationOnly = 0;
|
|
1094
1078
|
for (const result of results) {
|
|
1079
|
+
if (result.diagnosticsUnsupported) {
|
|
1080
|
+
navigationOnly += 1;
|
|
1081
|
+
continue;
|
|
1082
|
+
}
|
|
1095
1083
|
if (result.diagnostics.length > 0)
|
|
1096
1084
|
continue;
|
|
1097
1085
|
if (result.confirmation === "unconfirmed") {
|
|
@@ -1105,11 +1093,13 @@ function tallyConfirmation(results) {
|
|
|
1105
1093
|
clean += 1;
|
|
1106
1094
|
}
|
|
1107
1095
|
}
|
|
1108
|
-
return { clean, unconfirmed, timedOut };
|
|
1096
|
+
return { clean, unconfirmed, timedOut, navigationOnly };
|
|
1109
1097
|
}
|
|
1110
1098
|
function classifyBatchFileOutcome(result) {
|
|
1111
1099
|
if (result.error)
|
|
1112
1100
|
return "failed";
|
|
1101
|
+
if (result.diagnosticsUnsupported)
|
|
1102
|
+
return "unsupported";
|
|
1113
1103
|
// A timed-out/unconfirmed answer may contain partial findings, but it cannot
|
|
1114
1104
|
// honestly be called a complete findings result. Keep the raw findings for
|
|
1115
1105
|
// investigation while making the aggregate incomplete.
|
|
@@ -1265,6 +1255,7 @@ async function runBatchFileDiagnostics(absPaths, severity, lspService, options)
|
|
|
1265
1255
|
};
|
|
1266
1256
|
}
|
|
1267
1257
|
const { results, fileErrors, lspHealthWarnings, total, truncated, display, primaryDisplay, auxiliaryDisplay, clean, unconfirmed, timedOut, outcomeCounts, incompleteFiles, } = await collectBatchDiagnostics(absPaths, severity, lspService, options);
|
|
1258
|
+
const navigationOnly = results.filter((result) => result.diagnosticsUnsupported).length;
|
|
1268
1259
|
const lines = [
|
|
1269
1260
|
`Files checked: ${results.length}`,
|
|
1270
1261
|
`Total diagnostics: ${total}`,
|
|
@@ -1335,6 +1326,7 @@ async function runBatchFileDiagnostics(absPaths, severity, lspService, options)
|
|
|
1335
1326
|
truncated,
|
|
1336
1327
|
cleanFiles: clean,
|
|
1337
1328
|
unconfirmedFiles: unconfirmed,
|
|
1329
|
+
navigationOnlyFiles: navigationOnly > 0 ? navigationOnly : undefined,
|
|
1338
1330
|
timedOutFiles: timedOut > 0 ? timedOut : undefined,
|
|
1339
1331
|
outcomes: results.map((result) => ({
|
|
1340
1332
|
file: result.file,
|
|
@@ -1350,18 +1342,42 @@ async function runBatchFileDiagnostics(absPaths, severity, lspService, options)
|
|
|
1350
1342
|
},
|
|
1351
1343
|
};
|
|
1352
1344
|
}
|
|
1345
|
+
/**
|
|
1346
|
+
* The scan-language DECISION `runDirectoryDiagnostics` makes, pulled out as
|
|
1347
|
+
* its own function so `tests/tools/lsp-diagnostics-scan-family.test.ts` can
|
|
1348
|
+
* pin it against the golden `LANG_EXTENSIONS` table for every 1- and
|
|
1349
|
+
* 2-extension combination in that table's universe without spinning up one
|
|
1350
|
+
* real directory (and the full LSP-mocked tool) per combination — `hasMatch`
|
|
1351
|
+
* is the only I/O-shaped seam, so the caller decides whether it is backed by
|
|
1352
|
+
* a real `collectFiles` walk (production) or an in-memory extension-set probe
|
|
1353
|
+
* (tests).
|
|
1354
|
+
*
|
|
1355
|
+
* Walks `SCAN_LANGUAGE_PRIORITY`'s FAMILIES in order and unions each member
|
|
1356
|
+
* id's {@link extensionsForLanguage} into ONE `hasMatch` call — the first
|
|
1357
|
+
* family with any match wins the whole directory for this pass. Grouping by
|
|
1358
|
+
* family (not trying each id alone) is what makes a directory mixing BOTH
|
|
1359
|
+
* extensions of a registry-split pair (`.ts`+`.tsx`, `.css`+`.scss`, ...)
|
|
1360
|
+
* behavior-preserving vs the pre-#2434 bundled-key table: a flat per-id loop
|
|
1361
|
+
* stopped at the first id with ANY match, silently losing the sibling half of
|
|
1362
|
+
* a split pair present in the same directory (#2458 fix-round F1).
|
|
1363
|
+
*/
|
|
1364
|
+
export async function resolveDirectoryScanExtensions(hasMatch) {
|
|
1365
|
+
for (const family of SCAN_LANGUAGE_PRIORITY) {
|
|
1366
|
+
const exts = family.flatMap((languageId) => extensionsForLanguage(languageId));
|
|
1367
|
+
if (await hasMatch(exts)) {
|
|
1368
|
+
return exts;
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
return undefined;
|
|
1372
|
+
}
|
|
1353
1373
|
async function runDirectoryDiagnostics(absPath, severity, lspService, options) {
|
|
1354
|
-
let extension;
|
|
1355
1374
|
let collectedFiles = [];
|
|
1356
1375
|
const isIgnored = projectIgnorePredicate(absPath);
|
|
1357
|
-
|
|
1358
|
-
collectedFiles = await collectFiles(absPath, exts, MAX_FILES + 1, isIgnored);
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
}
|
|
1363
|
-
}
|
|
1364
|
-
if (!extension || collectedFiles.length === 0) {
|
|
1376
|
+
await resolveDirectoryScanExtensions(async (exts) => {
|
|
1377
|
+
collectedFiles = await collectFiles(absPath, [...exts], MAX_FILES + 1, isIgnored);
|
|
1378
|
+
return collectedFiles.length > 0;
|
|
1379
|
+
});
|
|
1380
|
+
if (collectedFiles.length === 0) {
|
|
1365
1381
|
return {
|
|
1366
1382
|
content: [
|
|
1367
1383
|
{
|
|
@@ -1379,7 +1395,8 @@ async function runDirectoryDiagnostics(absPath, severity, lspService, options) {
|
|
|
1379
1395
|
}
|
|
1380
1396
|
const wasCapped = collectedFiles.length > MAX_FILES;
|
|
1381
1397
|
const filesToProcess = collectedFiles.slice(0, MAX_FILES);
|
|
1382
|
-
const { fileErrors, lspHealthWarnings, total, truncated, display, primaryDisplay, auxiliaryDisplay, clean, unconfirmed, timedOut, } = await collectBatchDiagnostics(filesToProcess, severity, lspService, options);
|
|
1398
|
+
const { results, fileErrors, lspHealthWarnings, total, truncated, display, primaryDisplay, auxiliaryDisplay, clean, unconfirmed, timedOut, } = await collectBatchDiagnostics(filesToProcess, severity, lspService, options);
|
|
1399
|
+
const navigationOnly = results.filter((result) => result.diagnosticsUnsupported).length;
|
|
1383
1400
|
let text;
|
|
1384
1401
|
if (total === 0) {
|
|
1385
1402
|
// #533/#570: an unconfirmed-containing directory result must never
|
|
@@ -1463,6 +1480,7 @@ async function runDirectoryDiagnostics(absPath, severity, lspService, options) {
|
|
|
1463
1480
|
truncated,
|
|
1464
1481
|
cleanFiles: clean,
|
|
1465
1482
|
unconfirmedFiles: unconfirmed,
|
|
1483
|
+
navigationOnlyFiles: navigationOnly > 0 ? navigationOnly : undefined,
|
|
1466
1484
|
timedOutFiles: timedOut > 0 ? timedOut : undefined,
|
|
1467
1485
|
fileErrors: fileErrors.length > 0 ? fileErrors : undefined,
|
|
1468
1486
|
lspHealthWarnings: lspHealthWarnings.length > 0 ? lspHealthWarnings : undefined,
|
|
@@ -10,6 +10,8 @@ import { Type } from "../clients/deps/typebox.js";
|
|
|
10
10
|
import { logLatency } from "../clients/latency-logger.js";
|
|
11
11
|
import { newLspMutationCorrelationId, recordLspMutationOutcome, } from "../clients/lsp-mutation.js";
|
|
12
12
|
import { uriToPath } from "../clients/path-utils.js";
|
|
13
|
+
import { escapeRegExp } from "../clients/string-utils.js";
|
|
14
|
+
import { isRecordableProjectPath } from "../clients/file-utils.js";
|
|
13
15
|
import { compactRenderResult } from "./render-compact.js";
|
|
14
16
|
import { applyWorkspaceEdit, summarizeWorkspaceEdit, } from "../clients/lsp/edits.js";
|
|
15
17
|
import { getLSPService, } from "../clients/lsp/index.js";
|
|
@@ -106,9 +108,6 @@ function emptyReasonForOperation(operation) {
|
|
|
106
108
|
return "no-call-hierarchy-results";
|
|
107
109
|
return "no-results";
|
|
108
110
|
}
|
|
109
|
-
function escapeRegExp(value) {
|
|
110
|
-
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
111
|
-
}
|
|
112
111
|
function parseSymbolSelector(symbol) {
|
|
113
112
|
const trimmed = symbol.trim();
|
|
114
113
|
const match = /^([^#]*)(?:#(-?\d+))?$/.exec(trimmed);
|
|
@@ -530,16 +529,16 @@ async function openFileBestEffort(lspService, filePath, waitForDiagnostics = fal
|
|
|
530
529
|
if (!fileContent)
|
|
531
530
|
return;
|
|
532
531
|
try {
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
}
|
|
532
|
+
// #2598: `touchFile` is defined unconditionally on the real `LSPService`
|
|
533
|
+
// (clients/lsp/index.ts), so the former `typeof … === "function"` hedge
|
|
534
|
+
// and its `openFile` arm were reachable only from a partial test double
|
|
535
|
+
// (AGENTS.md shape 7). Nothing here reads the result — a touch that
|
|
536
|
+
// resolves no clients is already the no-op this helper wants.
|
|
537
|
+
await lspService.touchFile(filePath, fileContent, {
|
|
538
|
+
diagnostics: waitForDiagnostics ? "document" : "none",
|
|
539
|
+
source: "lsp_navigation",
|
|
540
|
+
clientScope: waitForDiagnostics ? "all" : "primary",
|
|
541
|
+
});
|
|
543
542
|
}
|
|
544
543
|
catch {
|
|
545
544
|
/* LSP server may not be ready yet — proceed anyway */
|
|
@@ -729,7 +728,7 @@ getFlag, mutationDeps) {
|
|
|
729
728
|
},
|
|
730
729
|
],
|
|
731
730
|
details: {
|
|
732
|
-
...
|
|
731
|
+
...payload.details,
|
|
733
732
|
failureKind: meta.failureKind,
|
|
734
733
|
},
|
|
735
734
|
};
|
|
@@ -779,15 +778,37 @@ getFlag, mutationDeps) {
|
|
|
779
778
|
if (requestedApply &&
|
|
780
779
|
["rename", "rename_file", "executeCommand"].includes(operation)) {
|
|
781
780
|
const cwd = ctx.cwd || ".";
|
|
781
|
+
// Name the specific LSP operation in the receipt rather than a
|
|
782
|
+
// generic "lsp-edit" tag, so a rename's change-log entry reads
|
|
783
|
+
// differently from an executeCommand-solicited edit (#2450).
|
|
784
|
+
const mutationSource = operation === "executeCommand" ? "lsp-execute-command" : "lsp-rename";
|
|
782
785
|
mutationContext = {
|
|
783
786
|
cwd,
|
|
784
787
|
correlationId: newLspMutationCorrelationId(_toolCallId),
|
|
785
|
-
tool:
|
|
786
|
-
source:
|
|
788
|
+
tool: `lsp_navigation:${operation}`,
|
|
789
|
+
source: mutationSource,
|
|
787
790
|
...mutationDeps,
|
|
788
791
|
readGuard: getFlag("no-read-guard", cwd)
|
|
789
792
|
? undefined
|
|
790
793
|
: mutationDeps?.readGuard,
|
|
794
|
+
// #2450 review round 2 (F4)/round 3 (F2, F4): the SAME gate
|
|
795
|
+
// `registerMutationBridge` applies internally in `index.ts`, so
|
|
796
|
+
// this directly-threaded path and the bridge fallback
|
|
797
|
+
// (`clients/lsp-mutation.ts`, reached when `mutationDeps` is
|
|
798
|
+
// absent/partial — e.g. the MCP server) agree on which files
|
|
799
|
+
// count as project source, rather than the direct path
|
|
800
|
+
// recording an ignored/vendor write the fallback would drop.
|
|
801
|
+
// `no-read-guard` is intentionally NOT checked here (round 3
|
|
802
|
+
// F2): it gates only the read-guard stamp above, the same
|
|
803
|
+
// canonical split `clients/runtime-tool-result.ts` applies
|
|
804
|
+
// (`:1120`, `:1485`) — bookkeeping (turn-state / receipts)
|
|
805
|
+
// still runs under `--no-read-guard`. Judge against the
|
|
806
|
+
// project root, not the request `cwd` (round 3 F4): a
|
|
807
|
+
// sub-package `cwd` must not read a sibling-package rename as
|
|
808
|
+
// external.
|
|
809
|
+
isRecordable: (filePath) => {
|
|
810
|
+
return isRecordableProjectPath(filePath, mutationDeps?.runtime?.projectRoot ?? cwd);
|
|
811
|
+
},
|
|
791
812
|
};
|
|
792
813
|
}
|
|
793
814
|
const isCallHierarchyTraversal = operation === "incomingCalls" || operation === "outgoingCalls";
|
|
@@ -9,7 +9,7 @@ function finiteNumber(value) {
|
|
|
9
9
|
? value
|
|
10
10
|
: undefined;
|
|
11
11
|
}
|
|
12
|
-
|
|
12
|
+
function lspStatusFromFailureKind(failureKind) {
|
|
13
13
|
if (failureKind === "success" || failureKind === "fallback_success") {
|
|
14
14
|
return "success";
|
|
15
15
|
}
|
|
@@ -145,7 +145,7 @@ function collectCallHierarchyLocationSummaries(result, operation) {
|
|
|
145
145
|
}
|
|
146
146
|
return out;
|
|
147
147
|
}
|
|
148
|
-
|
|
148
|
+
function collectLspToolLocationsForOperation(operation, result, filePath) {
|
|
149
149
|
if ([
|
|
150
150
|
"definition",
|
|
151
151
|
"typeDefinition",
|
|
@@ -210,7 +210,7 @@ function parseBalancedJsonPrefix(text) {
|
|
|
210
210
|
}
|
|
211
211
|
return undefined;
|
|
212
212
|
}
|
|
213
|
-
|
|
213
|
+
function parseLspNavigationTextPayload(text) {
|
|
214
214
|
const notes = [];
|
|
215
215
|
const hints = [];
|
|
216
216
|
const errors = [];
|
|
@@ -65,7 +65,7 @@ export function selectCompactText(result, args, expanded, summarize) {
|
|
|
65
65
|
}
|
|
66
66
|
/** Apply a CompactStyle to text. `brand` uses raw blue ANSI; the rest defer to
|
|
67
67
|
* the theme so error-red and normal output stay consistent with the host. */
|
|
68
|
-
|
|
68
|
+
function paintCompact(style, text, theme) {
|
|
69
69
|
if (style === "brand") {
|
|
70
70
|
return `${PI_LENS_BLUE_FG}${text}${RESET_FG}`;
|
|
71
71
|
}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import * as path from "node:path";
|
|
9
9
|
import { Type } from "../clients/deps/typebox.js";
|
|
10
10
|
import { symbolSearch, } from "../clients/lens-engine.js";
|
|
11
|
-
import {
|
|
11
|
+
import { compactRenderResult } from "./render-compact.js";
|
|
12
12
|
/**
|
|
13
13
|
* Machine-actionable follow-up hint (#771) — mirrors ast-grep-search.ts's
|
|
14
14
|
* `suggestedDump` pattern. Cheap enough to attach per hit rather than only the
|
|
@@ -153,4 +153,3 @@ export function createSymbolSearchTool(getProjectRoot) {
|
|
|
153
153
|
}
|
|
154
154
|
// Re-exported so tests importing from this module can reach baseName without
|
|
155
155
|
// a second import path.
|
|
156
|
-
export { baseName };
|
|
@@ -45,10 +45,20 @@ On every write/edit, and at session/turn boundaries, pi-lens runs — without yo
|
|
|
45
45
|
| **Structural rules** | ast-grep (NAPI engine) + tree-sitter rules flag correctness/security smells. |
|
|
46
46
|
| **Opengrep security scan** | Always-on: per-edit via an auxiliary LSP, plus a cached project-wide CLI scan for `mode=full`. |
|
|
47
47
|
| **Other scanners** | Config-/presence-gated: gitleaks (secrets), trivy (CVEs/IaC/license), govulncheck (Go), knip/jscpd/madge (JS/TS dead-code/dupes/cycles), vulture (Python), zizmor (GH Actions), typos. |
|
|
48
|
-
| **Test-runner-on-write** | Related/affected tests are run asynchronously for the next turn's findings (edit-scoped, not a full-suite run). |
|
|
48
|
+
| **Test-runner-on-write** | Related/affected tests are run asynchronously for the next turn's findings (edit-scoped, not a full-suite run). Integration/e2e tests are never auto-fired — see below. |
|
|
49
49
|
| **Read-guard** | Tracks that you read a file before editing it; blocks/warns zero-read or stale-range edits. |
|
|
50
50
|
| **Context injection** | Injects session-start guidance and turn-end findings into your context (see §2). |
|
|
51
51
|
|
|
52
|
+
**Test-runner-on-write scope.** A built-in exclusion list keeps integration/e2e
|
|
53
|
+
suites out of the auto-fired batch — `**/integration/**`, `**/e2e/**`,
|
|
54
|
+
`**/*.integration.*`, `**/*.e2e.*` — since those commonly spawn external
|
|
55
|
+
processes (another CLI, a browser, a live provider) that don't belong on an
|
|
56
|
+
unattended per-edit turn. This is a fixed, built-in list; there is no
|
|
57
|
+
per-project config knob for it. If a runner itself fails to complete (a
|
|
58
|
+
timeout, or a missing provider/binary — not a failing assertion), pi-lens
|
|
59
|
+
delivers it as an advisory ("could not complete last turn"), not as a
|
|
60
|
+
"fix before continuing" blocker — you didn't introduce anything to fix.
|
|
61
|
+
|
|
52
62
|
You don't invoke these. They happen. Your job is to **read the results** and **respond**.
|
|
53
63
|
|
|
54
64
|
---
|
|
@@ -185,9 +195,62 @@ pi-lens writes to files **outside your own tool calls** (`docs/features.md`
|
|
|
185
195
|
- **`write` then `edit` on the same file, same turn:** the write's autofix
|
|
186
196
|
demotes to deferred too, so the file's mutation history stays coherent. This
|
|
187
197
|
resets at the next turn.
|
|
198
|
+
- **Any other tool that edits a file:** pi-lens recognizes it by the SHAPE of
|
|
199
|
+
its arguments rather than its name (`clients/mutating-tool.ts`), so a host or
|
|
200
|
+
extension tool called `replace` or `insert` gets the same chain `edit` gets:
|
|
201
|
+
a turn-state entry, a change-log receipt attributed to that tool, and a
|
|
202
|
+
*deferred* auto-fix. Its lines are resolved when the anchor is unambiguous
|
|
203
|
+
(roughly two-thirds of anchors in practice — `clients/hashline-anchor.ts`);
|
|
204
|
+
otherwise the mutation is recorded whole-file with lines unknown, and the
|
|
205
|
+
read-before-edit guard takes its no-line-info arm rather than guessing.
|
|
206
|
+
Deferred is the default for every edit-shaped tool pi-lens cannot place,
|
|
207
|
+
because formatting between the steps of a multi-call rewrite fights the tool
|
|
208
|
+
that is still writing.
|
|
209
|
+
- **A tool whose shape is unrecognized too:** pi-lens watches instead of
|
|
210
|
+
guessing (`clients/observed-mutation.ts`). A call that names a file gets a
|
|
211
|
+
bounded pre/post snapshot of THAT PATH — the file itself, or a directory's own
|
|
212
|
+
entries — and nothing else, so a write landing on a neighbouring file is never
|
|
213
|
+
attributed to it. Anything that changed is replayed through the same chain,
|
|
214
|
+
and the tool is then remembered as mutating: for this session on the first
|
|
215
|
+
sighting, persisted under the project's data directory on the second, so a
|
|
216
|
+
later session classifies it by name with no snapshot at all. Three quiet
|
|
217
|
+
observations in a row withdraw a session attribution again, and a withdrawn
|
|
218
|
+
tool can be learned back from a later real edit. An observation pi-lens could
|
|
219
|
+
not finish — a directory with more entries than it watches — counts as
|
|
220
|
+
neither, so a wide codemod is never written off on a look it never took. A
|
|
221
|
+
call that names
|
|
222
|
+
no file is caught at `agent_settled` by an incremental content check over the
|
|
223
|
+
files pi-lens has already read, written, diagnosed or opened on a language
|
|
224
|
+
server — a rotating window per turn, reading only what actually moved; a file
|
|
225
|
+
it has never seen has no baseline, so that last-resort net does not cover it,
|
|
226
|
+
and a file it cannot verify is reported as such rather than reformatted on a
|
|
227
|
+
timestamp alone.
|
|
188
228
|
- The conservative actionable-warnings autofix (LSP quickfixes, hard-capped)
|
|
189
229
|
is unchanged: it always runs at `agent_end`.
|
|
190
230
|
|
|
231
|
+
**Extension authors: record your own writes.** If your extension writes files
|
|
232
|
+
outside pi-lens's tool events — its own registered tool, a spawned rewriter —
|
|
233
|
+
tell pi-lens through the in-process mutation bridge, the write-side sibling of
|
|
234
|
+
the read bridge:
|
|
235
|
+
|
|
236
|
+
```js
|
|
237
|
+
const bridge = globalThis[Symbol.for("pi-lens:mutation-bridge")];
|
|
238
|
+
if (bridge?.version === 1) {
|
|
239
|
+
bridge.recordMutation({
|
|
240
|
+
filePath, // absolute path
|
|
241
|
+
kind: "edit", // "write" replaces the whole file; "edit" is partial
|
|
242
|
+
editRanges: [[12, 18]], // optional, 1-based inclusive
|
|
243
|
+
consumer: "my-extension",
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
Check `version` before calling; a version you do not recognize is unsupported.
|
|
249
|
+
Calling when pi-lens is absent or the guard is disabled is safe — the bridge is
|
|
250
|
+
missing or drops the call. `recordMutation` returns `true` when pi-lens took the
|
|
251
|
+
record and `false` when it dropped it, so you can count your own drops. pi-lens's
|
|
252
|
+
own `ast_grep_replace apply:true` records through this same bridge.
|
|
253
|
+
|
|
191
254
|
Consequences for you:
|
|
192
255
|
|
|
193
256
|
- Your exact written bytes may be reformatted/fixed. **This is expected pipeline
|