@herbertgao/pi-extensions 2026.9.1 → 2026.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- package/THIRD_PARTY_NOTICES.md +24 -0
- package/node_modules/@herbertgao/sol-pi/LICENSE +19 -0
- package/node_modules/@herbertgao/sol-pi/README.md +159 -0
- package/node_modules/@herbertgao/sol-pi/SECURITY.md +26 -0
- package/node_modules/@herbertgao/sol-pi/THIRD_PARTY_NOTICES.md +19 -0
- package/node_modules/@herbertgao/sol-pi/agents-install.md +150 -0
- package/node_modules/@herbertgao/sol-pi/assets/sol-pi-hero.png +0 -0
- package/node_modules/@herbertgao/sol-pi/docs/compatibility.md +69 -0
- package/node_modules/@herbertgao/sol-pi/docs/configuration.md +75 -0
- package/node_modules/@herbertgao/sol-pi/package.json +76 -0
- package/node_modules/@herbertgao/sol-pi/scripts/check-pi-compat.mjs +32 -0
- package/node_modules/@herbertgao/sol-pi/scripts/check-sol-pi-config.mjs +120 -0
- package/node_modules/@herbertgao/sol-pi/sol-pi.example.json +10 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/config.ts +135 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/action-fusion/file-queue.ts +74 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/action-fusion/index.ts +185 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/action-fusion/then-run.ts +128 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/evidence-preserving-reducer/archive.ts +53 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/evidence-preserving-reducer/candidate.ts +101 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/evidence-preserving-reducer/config.ts +71 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/evidence-preserving-reducer/index.ts +220 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/evidence-preserving-reducer/journal.ts +25 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/evidence-preserving-reducer/provider.ts +164 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/evidence-preserving-reducer/receipt.ts +177 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/observation-pack/index.ts +227 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/observation-pack/ledger.ts +20 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/observation-pack/observation.ts +252 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/economics.ts +237 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/extension.ts +455 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/index.ts +49 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/plan.ts +79 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/state.ts +208 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/tools.ts +100 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/index.ts +42 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/runtime-paths.ts +17 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/tui.ts +71 -0
- package/node_modules/@narumitw/pi-btw/README.md +57 -141
- package/node_modules/@narumitw/pi-btw/dist/index.ts +478 -43
- 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 +28 -3
- 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-lens/CHANGELOG.md +260 -0
- package/node_modules/pi-lens/README.md +13 -8
- package/node_modules/pi-lens/config/dependency-cruiser-eager-allowlist.json +3 -1
- package/node_modules/pi-lens/dist/clients/actionable-warnings-logger.js +0 -7
- package/node_modules/pi-lens/dist/clients/advisory-provenance.js +1 -1
- package/node_modules/pi-lens/dist/clients/analysed-root.js +1 -0
- package/node_modules/pi-lens/dist/clients/ast-grep-client.js +1 -1
- package/node_modules/pi-lens/dist/clients/ast-grep-tool-logger.js +1 -8
- 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 -1
- package/node_modules/pi-lens/dist/clients/biome-client.js +13 -2
- package/node_modules/pi-lens/dist/clients/blocker-freshness.js +0 -6
- package/node_modules/pi-lens/dist/clients/bootstrap.js +4 -4
- package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +1 -1
- package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +2 -5
- package/node_modules/pi-lens/dist/clients/bus-events-logger.js +1 -9
- package/node_modules/pi-lens/dist/clients/cache-observability.js +122 -6
- package/node_modules/pi-lens/dist/clients/cargo-manifest.js +2 -2
- package/node_modules/pi-lens/dist/clients/cascade-logger.js +0 -7
- package/node_modules/pi-lens/dist/clients/child-unref.js +1 -19
- package/node_modules/pi-lens/dist/clients/complexity-client.js +5 -0
- package/node_modules/pi-lens/dist/clients/config-core/index.js +11 -8
- package/node_modules/pi-lens/dist/clients/config-core/process-spec.js +1 -1
- package/node_modules/pi-lens/dist/clients/config-core/provenance.js +2 -9
- package/node_modules/pi-lens/dist/clients/config-core/records.js +1 -1
- package/node_modules/pi-lens/dist/clients/config-core/schema.js +3 -5
- package/node_modules/pi-lens/dist/clients/config-diagnostic-codes.js +3 -1
- package/node_modules/pi-lens/dist/clients/config-resolve.js +10 -7
- package/node_modules/pi-lens/dist/clients/config-schema.js +56 -2
- package/node_modules/pi-lens/dist/clients/config-warn.js +2 -2
- package/node_modules/pi-lens/dist/clients/dead-code-client.js +8 -1
- package/node_modules/pi-lens/dist/clients/dead-code-logger.js +0 -4
- package/node_modules/pi-lens/dist/clients/dependency-checker.js +5 -1
- package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +1 -1
- package/node_modules/pi-lens/dist/clients/diagnostic-logger.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/collect-later-tier.js +0 -4
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +38 -41
- package/node_modules/pi-lens/dist/clients/dispatch/facts/function-facts.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/facts/import-facts.js +5 -1
- package/node_modules/pi-lens/dist/clients/dispatch/integration.js +18 -1
- 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 +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +3 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +2 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +7 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/credo.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/cue-vet.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/dart-analyze.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/detekt.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/dotnet-build.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/fish-indent.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/gleam-check.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/go-vet.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/golangci-lint.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-lint.js +3 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +3 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ktlint.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +19 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +3 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/oxlint.js +3 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/php-lint.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/phpstan.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/prisma-validate.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +15 -11
- package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/rubocop.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ruff.js +3 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +12 -11
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shellcheck.js +3 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shfmt.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +5 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/spotbugs.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +3 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +3 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/terragrunt.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +5 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +2 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/diagnostic-parsers.js +1 -64
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +8 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils.js +0 -21
- package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +2 -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 +5 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +2 -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 +0 -7
- package/node_modules/pi-lens/dist/clients/effective-config.js +12 -2
- package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +2 -2
- package/node_modules/pi-lens/dist/clients/extension-log.js +2 -0
- package/node_modules/pi-lens/dist/clients/file-kinds.js +1 -38
- package/node_modules/pi-lens/dist/clients/file-role.js +18 -1
- package/node_modules/pi-lens/dist/clients/file-time.js +1 -1
- package/node_modules/pi-lens/dist/clients/file-utils.js +5 -1
- package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +4 -0
- package/node_modules/pi-lens/dist/clients/format-service.js +0 -1
- package/node_modules/pi-lens/dist/clients/formatters.js +66 -93
- package/node_modules/pi-lens/dist/clients/generated-artifacts.js +3 -4
- package/node_modules/pi-lens/dist/clients/generation-guard.js +4 -0
- package/node_modules/pi-lens/dist/clients/git-guard.js +5 -0
- package/node_modules/pi-lens/dist/clients/gitleaks-client.js +42 -6
- package/node_modules/pi-lens/dist/clients/govulncheck-client.js +48 -7
- package/node_modules/pi-lens/dist/clients/grammar-source.js +3 -3
- package/node_modules/pi-lens/dist/clients/installer/index.js +416 -61
- package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh.js +84 -18
- package/node_modules/pi-lens/dist/clients/instance-reaper.js +6 -6
- package/node_modules/pi-lens/dist/clients/jscpd-client.js +9 -1
- package/node_modules/pi-lens/dist/clients/knip-client.js +9 -2
- package/node_modules/pi-lens/dist/clients/language-profile.js +12 -11
- package/node_modules/pi-lens/dist/clients/language-registry.js +5 -1
- package/node_modules/pi-lens/dist/clients/latency-logger.js +7 -7
- package/node_modules/pi-lens/dist/clients/ledger-bounds.js +21 -1
- package/node_modules/pi-lens/dist/clients/lens-config.js +23 -0
- package/node_modules/pi-lens/dist/clients/lens-engine.js +3 -4
- package/node_modules/pi-lens/dist/clients/lens-events.js +1 -1
- package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +18 -0
- package/node_modules/pi-lens/dist/clients/lens-map.js +1 -1
- package/node_modules/pi-lens/dist/clients/log-cleanup.js +0 -36
- package/node_modules/pi-lens/dist/clients/lsp/client.js +4 -3
- package/node_modules/pi-lens/dist/clients/lsp/config.js +37 -7
- package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +24 -1
- package/node_modules/pi-lens/dist/clients/lsp/document-drift.js +79 -1
- package/node_modules/pi-lens/dist/clients/lsp/edits.js +3 -3
- package/node_modules/pi-lens/dist/clients/lsp/index.js +491 -64
- package/node_modules/pi-lens/dist/clients/lsp/inferred-project.js +1 -1
- package/node_modules/pi-lens/dist/clients/lsp/language.js +0 -8
- 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 +0 -2
- package/node_modules/pi-lens/dist/clients/lsp/server.js +62 -15
- package/node_modules/pi-lens/dist/clients/lsp/sync-kind.js +0 -1
- package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +5 -5
- 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 +37 -4
- package/node_modules/pi-lens/dist/clients/lsp-document-symbols.js +1 -1
- package/node_modules/pi-lens/dist/clients/mcp/analyze.js +3 -0
- package/node_modules/pi-lens/dist/clients/mcp/session.js +2 -0
- package/node_modules/pi-lens/dist/clients/metrics-history.js +28 -107
- package/node_modules/pi-lens/dist/clients/middle-man-analysis.js +1 -1
- package/node_modules/pi-lens/dist/clients/module-report.js +1 -1
- package/node_modules/pi-lens/dist/clients/mutating-tool.js +3 -3
- package/node_modules/pi-lens/dist/clients/mutation-attribution.js +3 -3
- package/node_modules/pi-lens/dist/clients/ndjson-logger.js +0 -4
- package/node_modules/pi-lens/dist/clients/observed-mutation.js +9 -9
- package/node_modules/pi-lens/dist/clients/opaque-mutation-scan.js +2 -6
- package/node_modules/pi-lens/dist/clients/opengrep-client.js +2 -0
- package/node_modules/pi-lens/dist/clients/opengrep-config.js +1 -1
- package/node_modules/pi-lens/dist/clients/package-manager.js +2 -1
- package/node_modules/pi-lens/dist/clients/path-utils.js +23 -2
- package/node_modules/pi-lens/dist/clients/performance-report.js +2 -2
- package/node_modules/pi-lens/dist/clients/php-cs-fixer-config.js +9 -4
- package/node_modules/pi-lens/dist/clients/pipeline.js +5 -4
- 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 +38 -10
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +10 -9
- 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 +1 -1
- package/node_modules/pi-lens/dist/clients/project-lens-config.js +49 -1
- package/node_modules/pi-lens/dist/clients/project-scan-policy.js +3 -51
- package/node_modules/pi-lens/dist/clients/python-provenance.js +1 -1
- package/node_modules/pi-lens/dist/clients/read-guard-logger.js +3 -1
- package/node_modules/pi-lens/dist/clients/read-guard.js +5 -2
- package/node_modules/pi-lens/dist/clients/recent-touches.js +2 -2
- package/node_modules/pi-lens/dist/clients/review-graph/builder.js +3 -5
- package/node_modules/pi-lens/dist/clients/review-graph/import-resolvers.js +1 -1
- package/node_modules/pi-lens/dist/clients/review-graph-logger.js +2 -0
- package/node_modules/pi-lens/dist/clients/ruff-client.js +18 -9
- package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +10 -1
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +5 -0
- package/node_modules/pi-lens/dist/clients/runtime-session.js +58 -14
- package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +11 -1
- package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +4 -1
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +48 -1
- package/node_modules/pi-lens/dist/clients/sanitize.js +0 -11
- package/node_modules/pi-lens/dist/clients/scan-utils.js +1 -56
- package/node_modules/pi-lens/dist/clients/security-scan-client.js +2 -2
- package/node_modules/pi-lens/dist/clients/session-event-guard.js +69 -1
- package/node_modules/pi-lens/dist/clients/session-summary.js +0 -24
- package/node_modules/pi-lens/dist/clients/sg-runner.js +2 -1
- package/node_modules/pi-lens/dist/clients/sgconfig.js +1 -5
- package/node_modules/pi-lens/dist/clients/shared-checkout-guard.js +1 -1
- package/node_modules/pi-lens/dist/clients/situational-tool-telemetry.js +108 -0
- package/node_modules/pi-lens/dist/clients/smells-rollup.js +2 -2
- package/node_modules/pi-lens/dist/clients/startup-scan.js +2 -10
- package/node_modules/pi-lens/dist/clients/test-runner-client.js +291 -76
- package/node_modules/pi-lens/dist/clients/test-runner-delivery.js +77 -72
- package/node_modules/pi-lens/dist/clients/tool-config.js +199 -0
- package/node_modules/pi-lens/dist/clients/tool-cwd.js +299 -0
- package/node_modules/pi-lens/dist/clients/tool-policy.js +1 -1
- package/node_modules/pi-lens/dist/clients/tool-probe.js +53 -0
- package/node_modules/pi-lens/dist/clients/tool-set-policy.js +42 -0
- package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +1 -52
- package/node_modules/pi-lens/dist/clients/trivy-client.js +9 -1
- package/node_modules/pi-lens/dist/clients/tui-fit.js +0 -4
- package/node_modules/pi-lens/dist/clients/turn-context.js +52 -0
- package/node_modules/pi-lens/dist/clients/user-notify.js +0 -4
- package/node_modules/pi-lens/dist/clients/widget-state.js +4 -3
- package/node_modules/pi-lens/dist/clients/word-index-logger.js +0 -7
- package/node_modules/pi-lens/dist/clients/word-index-store.js +3 -7
- package/node_modules/pi-lens/dist/clients/word-index.js +9 -16
- package/node_modules/pi-lens/dist/clients/zizmor-config.js +1 -1
- package/node_modules/pi-lens/dist/index.js +19969 -17481
- package/node_modules/pi-lens/dist/mcp/analyze-cli.js +3 -2
- package/node_modules/pi-lens/dist/mcp/build-staleness.js +1 -1
- package/node_modules/pi-lens/dist/mcp/server.js +135 -159
- package/node_modules/pi-lens/dist/scripts/lib/process-scan.mjs +1 -1
- package/node_modules/pi-lens/dist/scripts/lib/skills-predicate.mjs +1 -1
- package/node_modules/pi-lens/dist/tools/activate-tools.js +10 -7
- package/node_modules/pi-lens/dist/tools/ast-grep-outline.js +2 -13
- package/node_modules/pi-lens/dist/tools/ast-grep-replace.js +8 -13
- package/node_modules/pi-lens/dist/tools/ast-grep-search.js +83 -39
- package/node_modules/pi-lens/dist/tools/effective-config.js +4 -3
- package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +1 -10
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +354 -86
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +54 -112
- package/node_modules/pi-lens/dist/tools/lsp-navigation.js +20 -44
- package/node_modules/pi-lens/dist/tools/lsp-structured-output.js +3 -3
- package/node_modules/pi-lens/dist/tools/module-report.js +5 -9
- package/node_modules/pi-lens/dist/tools/project-report.js +9 -17
- package/node_modules/pi-lens/dist/tools/render-compact.js +281 -2
- package/node_modules/pi-lens/dist/tools/symbol-search.js +3 -4
- package/node_modules/pi-lens/docs/agent-guide.md +3 -4
- package/node_modules/pi-lens/docs/agent-tools.md +46 -22
- package/node_modules/pi-lens/docs/configuration.md +9 -0
- package/node_modules/pi-lens/docs/environment-variables.md +0 -5
- package/node_modules/pi-lens/docs/features.md +5 -5
- package/node_modules/pi-lens/docs/globalconfig.md +31 -1
- package/node_modules/pi-lens/docs/lsp-capability-matrix.md +9 -1
- package/node_modules/pi-lens/docs/mcp.md +13 -1
- package/node_modules/pi-lens/docs/pi-lens-fixer.md +71 -0
- package/node_modules/pi-lens/docs/pi-lens-investigator.md +15 -0
- package/node_modules/pi-lens/docs/pi-lens-monitor.md +88 -0
- package/node_modules/pi-lens/docs/pi-lens-reviewer.md +41 -0
- package/node_modules/pi-lens/docs/pi-lens-subagent.md +21 -2
- package/node_modules/pi-lens/docs/public-api-stability.md +1 -0
- package/node_modules/pi-lens/docs/real-harness.md +46 -0
- package/node_modules/pi-lens/docs/release-qa-baseline.md +17 -5
- package/node_modules/pi-lens/docs/servercapabilities.md +2 -3
- package/node_modules/pi-lens/docs/settings.md +37 -2
- package/node_modules/pi-lens/docs/tools_improvement2.md +4 -4
- package/node_modules/pi-lens/docs/tree-sitter_rules_catalog.md +1 -1
- package/node_modules/pi-lens/docs/usage.md +13 -3
- package/node_modules/pi-lens/docs/word-index.md +1 -1
- package/node_modules/pi-lens/package.json +15 -15
- package/node_modules/pi-lens/rules/tree-sitter-queries/typescript/sql-injection.yml +7 -3
- package/node_modules/pi-lens/rules/typos/_typos.toml +4 -2
- package/node_modules/pi-lens/scripts/lib/skills-predicate.mjs +1 -1
- package/node_modules/pi-lens/scripts/lib/warm-loader-cache.mjs +1 -1
- package/node_modules/pi-lens/scripts/warm-loader-cache.mjs +4 -2
- package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +8 -6
- package/node_modules/pi-lens/skills/pi-lens-lsp-navigation/SKILL.md +19 -9
- package/node_modules/pi-web-access/CHANGELOG.md +29 -0
- package/node_modules/pi-web-access/README.md +33 -22
- package/node_modules/pi-web-access/abortable.ts +17 -0
- package/node_modules/pi-web-access/crawl4ai.ts +204 -0
- package/node_modules/pi-web-access/credential-source.ts +1 -0
- package/node_modules/pi-web-access/curator-page.ts +20 -2
- package/node_modules/pi-web-access/curator-run.ts +44 -0
- package/node_modules/pi-web-access/curator-server.ts +3 -1
- package/node_modules/pi-web-access/duckduckgo.ts +1 -1
- package/node_modules/pi-web-access/extract.ts +57 -12
- package/node_modules/pi-web-access/fetch-params.ts +1 -1
- package/node_modules/pi-web-access/gemini-search.ts +9 -5
- package/node_modules/pi-web-access/index.ts +25 -18
- package/node_modules/pi-web-access/openai-search.ts +35 -13
- package/node_modules/pi-web-access/package.json +2 -2
- package/node_modules/pi-web-access/page-query.ts +5 -2
- package/node_modules/pi-web-access/query-rewrite.ts +5 -2
- package/node_modules/pi-web-access/serpapi.ts +220 -0
- package/node_modules/pi-web-access/ssrf-protection.ts +5 -1
- package/node_modules/pi-web-access/storage.ts +10 -0
- package/node_modules/pi-web-access/summary-review.ts +34 -21
- package/node_modules/pi-web-access/utils.ts +6 -4
- package/package.json +7 -4
- package/node_modules/pi-lens/dist/tools/ast-dump.js +0 -103
|
@@ -55,7 +55,7 @@ const TYPESCRIPT_DIAGNOSTIC_SOURCES = new Set(["typescript", "ts", "tsserver"]);
|
|
|
55
55
|
export function isTsProjectFile(filePath) {
|
|
56
56
|
return TS_PROJECT_EXTENSIONS.has(path.extname(filePath).toLowerCase());
|
|
57
57
|
}
|
|
58
|
-
|
|
58
|
+
function isTypeScriptSourcedDiagnostic(d) {
|
|
59
59
|
return TYPESCRIPT_DIAGNOSTIC_SOURCES.has((d.source ?? "").toLowerCase());
|
|
60
60
|
}
|
|
61
61
|
/**
|
|
@@ -61,11 +61,3 @@ export function getLanguageId(filePath) {
|
|
|
61
61
|
LANGUAGE_EXTENSIONS[base.toLowerCase()] ??
|
|
62
62
|
getBasenameLanguageId(base));
|
|
63
63
|
}
|
|
64
|
-
/**
|
|
65
|
-
* Get all extensions for a language ID
|
|
66
|
-
*/
|
|
67
|
-
export function getExtensionsForLanguage(languageId) {
|
|
68
|
-
return Object.entries(LANGUAGE_EXTENSIONS)
|
|
69
|
-
.filter(([, id]) => id === languageId)
|
|
70
|
-
.map(([ext]) => ext);
|
|
71
|
-
}
|
|
@@ -2,4 +2,4 @@
|
|
|
2
2
|
* Re-export from shared path-utils.
|
|
3
3
|
* Kept as a local module for LSP imports that use relative paths.
|
|
4
4
|
*/
|
|
5
|
-
export { isUnderDir,
|
|
5
|
+
export { isUnderDir, normalizeEphemeralMapKey, normalizeMapKey, pathsEqual, uriToDiskPath, uriToPath, } from "../path-utils.js";
|
|
@@ -187,8 +187,6 @@ export function drainPendingAuxiliaryCoverage() {
|
|
|
187
187
|
export function pendingAuxiliaryCoverageSize() {
|
|
188
188
|
return pending.size;
|
|
189
189
|
}
|
|
190
|
-
/** Test-only alias for the store-size assertion seam. */
|
|
191
|
-
export const pendingAuxiliaryCoverageSizeForTests = pendingAuxiliaryCoverageSize;
|
|
192
190
|
/**
|
|
193
191
|
* Drain (read and reset) the cap-eviction count accumulated since the last
|
|
194
192
|
* drain. Mirrors {@link drainPendingAuxiliaryCoverage}'s consume-once shape
|
|
@@ -26,6 +26,8 @@ import { logSessionStart } from "../sessionstart-logger.js";
|
|
|
26
26
|
import { findLocalSgconfig, resolveBaselineSgconfig } from "../sgconfig.js";
|
|
27
27
|
import { findLocalTyposConfig } from "../typos-config.js";
|
|
28
28
|
import { resolvePackagePath } from "../package-root.js";
|
|
29
|
+
import { resolveToolCwd } from "../tool-cwd.js";
|
|
30
|
+
import { recordDegradationOnce } from "../degradation-ledger.js";
|
|
29
31
|
import { hasCargoWorkspaceTable, readCargoWorkspaceExclude, readCargoWorkspaceMembers, readTextFileOrUndefined, } from "../cargo-manifest.js";
|
|
30
32
|
import { resolveAstGrepNativeExe } from "./wait-policy/index.js";
|
|
31
33
|
import { hasSpawnFailureKind, isCommandAvailableAsync, safeSpawnAsync, } from "../safe-spawn.js";
|
|
@@ -36,6 +38,48 @@ import { normalizeMapKey } from "./path-utils.js";
|
|
|
36
38
|
import { getRubyVersionDirNamesSync } from "./ruby-drive-dirs.js";
|
|
37
39
|
import { getProcessSingleton } from "../process-singletons.js";
|
|
38
40
|
import { createGenerationSource, } from "../generation-guard.js";
|
|
41
|
+
function withRootMarkers(root, markers) {
|
|
42
|
+
root.rootMarkers = markers;
|
|
43
|
+
return root;
|
|
44
|
+
}
|
|
45
|
+
/** Resolve a server identity cwd through the shared tool-cwd seam. */
|
|
46
|
+
export async function resolveLspServerCwd(server, filePath, sessionCwd, onRootFailure) {
|
|
47
|
+
const rootMarkers = server.rootMarkers ?? server.root.rootMarkers;
|
|
48
|
+
let serverRoot;
|
|
49
|
+
let rootFailed = false;
|
|
50
|
+
try {
|
|
51
|
+
serverRoot = await server.root(filePath);
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
55
|
+
rootFailed = true;
|
|
56
|
+
onRootFailure?.(reason);
|
|
57
|
+
}
|
|
58
|
+
const isFileDirFallback = serverRoot !== undefined &&
|
|
59
|
+
rootMarkers?.length &&
|
|
60
|
+
path.resolve(serverRoot) === path.resolve(path.dirname(filePath));
|
|
61
|
+
if (!serverRoot || isFileDirFallback) {
|
|
62
|
+
if (!serverRoot) {
|
|
63
|
+
recordDegradationOnce({
|
|
64
|
+
kind: "tool-cwd-resolution",
|
|
65
|
+
subject: server.id,
|
|
66
|
+
reason: `lsp:server-root-${rootFailed ? "failed" : "fallback"}:${filePath}`,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
if (!rootMarkers?.length)
|
|
70
|
+
return undefined;
|
|
71
|
+
return resolveToolCwd("lsp", server.id, filePath, {
|
|
72
|
+
cwd: path.dirname(path.resolve(filePath)),
|
|
73
|
+
rootMarkers,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
const boundedServerRoot = enforceLspRootCeiling(serverRoot, sessionCwd, filePath);
|
|
77
|
+
return resolveToolCwd("lsp", server.id, filePath, {
|
|
78
|
+
cwd: sessionCwd,
|
|
79
|
+
rootMarkers,
|
|
80
|
+
serverRoot: boundedServerRoot,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
39
83
|
const FIXTURE_ROOT_SEGMENTS = new Set(["__fixtures__", "testdata"]);
|
|
40
84
|
const FALLBACK_PROJECT_MARKERS = [
|
|
41
85
|
".git",
|
|
@@ -845,12 +889,12 @@ function normalizeRootKey(root) {
|
|
|
845
889
|
}
|
|
846
890
|
function IgnoreHomeRoot(primary) {
|
|
847
891
|
const homeKey = normalizeRootKey(os.homedir());
|
|
848
|
-
return async (file) => {
|
|
892
|
+
return withRootMarkers(async (file) => {
|
|
849
893
|
const root = await primary(file);
|
|
850
894
|
if (!root)
|
|
851
895
|
return undefined;
|
|
852
896
|
return normalizeRootKey(root) === homeKey ? undefined : root;
|
|
853
|
-
};
|
|
897
|
+
}, primary.rootMarkers ?? []);
|
|
854
898
|
}
|
|
855
899
|
function rubyBinCandidates(baseName) {
|
|
856
900
|
const candidates = [];
|
|
@@ -879,6 +923,7 @@ function createInteractiveServer(spec) {
|
|
|
879
923
|
name: spec.name,
|
|
880
924
|
extensions: spec.extensions,
|
|
881
925
|
root: spec.root,
|
|
926
|
+
rootMarkers: spec.root.rootMarkers,
|
|
882
927
|
fallbackFor: spec.fallbackFor,
|
|
883
928
|
availabilityKey: typeof spec.command === "string" && isSimpleCommand(spec.command)
|
|
884
929
|
? spec.command
|
|
@@ -917,29 +962,29 @@ function createInteractiveServer(spec) {
|
|
|
917
962
|
}
|
|
918
963
|
export function PriorityRoot(markerGroups, excludePatterns, stopDir) {
|
|
919
964
|
const resolvers = markerGroups.map((markers) => NearestRoot(markers, excludePatterns, stopDir));
|
|
920
|
-
return async (file) => {
|
|
965
|
+
return withRootMarkers(async (file) => {
|
|
921
966
|
for (const resolve of resolvers) {
|
|
922
967
|
const root = await resolve(file);
|
|
923
968
|
if (root)
|
|
924
969
|
return root;
|
|
925
970
|
}
|
|
926
971
|
return undefined;
|
|
927
|
-
};
|
|
972
|
+
}, markerGroups.flat());
|
|
928
973
|
}
|
|
929
974
|
export const FileDirRoot = async (file) => {
|
|
930
975
|
const candidate = path.resolve(path.dirname(file));
|
|
931
976
|
return nearestNonExcludedFallbackRoot(candidate);
|
|
932
977
|
};
|
|
933
978
|
export function RootWithFallback(primary, fallback = FileDirRoot) {
|
|
934
|
-
return async (file) => {
|
|
979
|
+
return withRootMarkers(async (file) => {
|
|
935
980
|
const primaryRoot = await primary(file);
|
|
936
981
|
if (primaryRoot)
|
|
937
982
|
return primaryRoot;
|
|
938
983
|
return fallback(file);
|
|
939
|
-
};
|
|
984
|
+
}, primary.rootMarkers ?? []);
|
|
940
985
|
}
|
|
941
986
|
export function WorkspacePriorityRoot(markerGroups, excludePatterns) {
|
|
942
|
-
return async (file) => PriorityRoot(markerGroups, excludePatterns, process.cwd())(file);
|
|
987
|
+
return withRootMarkers(async (file) => PriorityRoot(markerGroups, excludePatterns, process.cwd())(file), markerGroups.flat());
|
|
943
988
|
}
|
|
944
989
|
function isPermissionFsError(err) {
|
|
945
990
|
const code = err?.code;
|
|
@@ -1010,7 +1055,7 @@ export function NearestRoot(includePatterns, excludePatterns, stopDir) {
|
|
|
1010
1055
|
// re-walk cost for configless repos is a known trade-off; bounding the
|
|
1011
1056
|
// walk with stopDir for in-cwd files is the tracked optimization (#1412).
|
|
1012
1057
|
const inFlight = new Map();
|
|
1013
|
-
return async (file) => {
|
|
1058
|
+
return withRootMarkers(async (file) => {
|
|
1014
1059
|
// Cache key is the resolved directory — all files in the same dir share a root.
|
|
1015
1060
|
const startDir = path.resolve(path.dirname(file));
|
|
1016
1061
|
const dirKey = normalizeMapKey(startDir);
|
|
@@ -1052,6 +1097,7 @@ export function NearestRoot(includePatterns, excludePatterns, stopDir) {
|
|
|
1052
1097
|
// glob markers like `*.csproj` match real project filenames (#201).
|
|
1053
1098
|
for (const pattern of includePatterns) {
|
|
1054
1099
|
if ((await markerExists(currentDir, pattern)) &&
|
|
1100
|
+
(pattern !== ".git" || currentDir !== os.tmpdir()) &&
|
|
1055
1101
|
!(await isExcludedLspRoot(currentDir))) {
|
|
1056
1102
|
return enforceLspRootCeiling(currentDir, process.cwd(), file);
|
|
1057
1103
|
}
|
|
@@ -1073,7 +1119,7 @@ export function NearestRoot(includePatterns, excludePatterns, stopDir) {
|
|
|
1073
1119
|
finally {
|
|
1074
1120
|
inFlight.delete(dirKey);
|
|
1075
1121
|
}
|
|
1076
|
-
};
|
|
1122
|
+
}, includePatterns);
|
|
1077
1123
|
}
|
|
1078
1124
|
/** Alias kept for backward compatibility */
|
|
1079
1125
|
export const createRootDetector = NearestRoot;
|
|
@@ -1579,7 +1625,7 @@ async function hasAgentLevelProjectMarker(extensionRootKey) {
|
|
|
1579
1625
|
}
|
|
1580
1626
|
return false;
|
|
1581
1627
|
}
|
|
1582
|
-
const TypeScriptRoot = DenoExcludeRoot(async (file) => {
|
|
1628
|
+
const TypeScriptRoot = withRootMarkers(DenoExcludeRoot(async (file) => {
|
|
1583
1629
|
const extensionRootKey = piAgentExtensionsRootKey(file);
|
|
1584
1630
|
if (extensionRootKey) {
|
|
1585
1631
|
// Bounded walk so we never adopt a parent (e.g. ~/.pi/agent/) as the
|
|
@@ -1603,13 +1649,14 @@ const TypeScriptRoot = DenoExcludeRoot(async (file) => {
|
|
|
1603
1649
|
if (projectRoot)
|
|
1604
1650
|
return projectRoot;
|
|
1605
1651
|
return FileDirRoot(file);
|
|
1606
|
-
});
|
|
1652
|
+
}), [...TS_CONFIG_MARKERS, ...TS_TOOLING_MARKERS]);
|
|
1607
1653
|
export const TypeScriptServer = {
|
|
1608
1654
|
id: "typescript",
|
|
1609
1655
|
name: "TypeScript Language Server",
|
|
1610
1656
|
extensions: JS_TS_LSP_EXTENSIONS,
|
|
1611
1657
|
autoPropagateDiagnostics: true,
|
|
1612
1658
|
root: TypeScriptRoot,
|
|
1659
|
+
rootMarkers: TypeScriptRoot.rootMarkers,
|
|
1613
1660
|
async spawn(root, options) {
|
|
1614
1661
|
const fs = await import("node:fs/promises");
|
|
1615
1662
|
const nativeLsp = await findNativeTypeScriptLsp(root);
|
|
@@ -1919,7 +1966,7 @@ function sessionHoistCeiling(sessionCwd, file) {
|
|
|
1919
1966
|
}
|
|
1920
1967
|
function RustWorkspaceRoot() {
|
|
1921
1968
|
const crateRoot = createRootDetector(["Cargo.toml", "Cargo.lock"]);
|
|
1922
|
-
return async (file) => {
|
|
1969
|
+
return withRootMarkers(async (file) => {
|
|
1923
1970
|
const root = await crateRoot(file);
|
|
1924
1971
|
if (!root)
|
|
1925
1972
|
return undefined;
|
|
@@ -1958,7 +2005,7 @@ function RustWorkspaceRoot() {
|
|
|
1958
2005
|
current = parent;
|
|
1959
2006
|
}
|
|
1960
2007
|
return root;
|
|
1961
|
-
};
|
|
2008
|
+
}, crateRoot.rootMarkers ?? []);
|
|
1962
2009
|
}
|
|
1963
2010
|
/**
|
|
1964
2011
|
* Resolve whether `parentPomPath`'s <modules> block declares `childDir` as one
|
|
@@ -2011,7 +2058,7 @@ function JavaWorkspaceRoot() {
|
|
|
2011
2058
|
"build.gradle",
|
|
2012
2059
|
".classpath",
|
|
2013
2060
|
]);
|
|
2014
|
-
return async (file) => {
|
|
2061
|
+
return withRootMarkers(async (file) => {
|
|
2015
2062
|
const root = await moduleRoot(file);
|
|
2016
2063
|
if (!root)
|
|
2017
2064
|
return undefined;
|
|
@@ -2051,7 +2098,7 @@ function JavaWorkspaceRoot() {
|
|
|
2051
2098
|
current = parent;
|
|
2052
2099
|
}
|
|
2053
2100
|
return enforceLspRootCeiling(lastHop, sessionCwd, file);
|
|
2054
|
-
};
|
|
2101
|
+
}, moduleRoot.rootMarkers ?? []);
|
|
2055
2102
|
}
|
|
2056
2103
|
export const RustServer = {
|
|
2057
2104
|
id: "rust",
|
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
* always sent, so an unrecognized/absent value never regresses `Full`/`None`
|
|
17
17
|
* behavior.
|
|
18
18
|
*/
|
|
19
|
-
export const TEXT_DOCUMENT_SYNC_KIND_NONE = 0;
|
|
20
19
|
export const TEXT_DOCUMENT_SYNC_KIND_FULL = 1;
|
|
21
20
|
export const TEXT_DOCUMENT_SYNC_KIND_INCREMENTAL = 2;
|
|
22
21
|
function isSyncKind(value) {
|
|
@@ -37,7 +37,7 @@ import { normalizeMapKey } from "../path-utils.js";
|
|
|
37
37
|
// ---------------------------------------------------------------------------
|
|
38
38
|
// Constants
|
|
39
39
|
// ---------------------------------------------------------------------------
|
|
40
|
-
|
|
40
|
+
const TSSERVER_REQUEST_COMMAND = "typescript.tsserverRequest";
|
|
41
41
|
/**
|
|
42
42
|
* tsserver's synthetic inferred-project name, as its own source builds it:
|
|
43
43
|
* `"/dev/null/inferredProject" + counter + "*"`. `/dev/null` is a deliberate
|
|
@@ -219,13 +219,13 @@ export async function fetchTsserverProjectIdentity(svc, file) {
|
|
|
219
219
|
// ---------------------------------------------------------------------------
|
|
220
220
|
// Helpers
|
|
221
221
|
// ---------------------------------------------------------------------------
|
|
222
|
-
|
|
222
|
+
function isTsserverSyncRawDiagnostic(value) {
|
|
223
223
|
if (!value || typeof value !== "object")
|
|
224
224
|
return false;
|
|
225
225
|
const v = value;
|
|
226
226
|
return typeof v.message === "string" && typeof v.category === "string";
|
|
227
227
|
}
|
|
228
|
-
|
|
228
|
+
function tsserverSeverityFromCategory(category) {
|
|
229
229
|
switch (category) {
|
|
230
230
|
case "error":
|
|
231
231
|
return 1;
|
|
@@ -242,7 +242,7 @@ export function tsserverSeverityFromCategory(category) {
|
|
|
242
242
|
* `LSPDiagnostic`. Both `line`/`offset` are 1-based in tsserver's protocol
|
|
243
243
|
* and 0-based in LSP — this conversion handles that.
|
|
244
244
|
*/
|
|
245
|
-
|
|
245
|
+
function tsserverSyncDiagnosticToLsp(d) {
|
|
246
246
|
const startLine = Math.max(0, (d.startLocation?.line ?? 1) - 1);
|
|
247
247
|
const startChar = Math.max(0, (d.startLocation?.offset ?? 1) - 1);
|
|
248
248
|
const endLine = Math.max(0, (d.endLocation?.line ?? d.startLocation?.line ?? 1) - 1);
|
|
@@ -265,7 +265,7 @@ export function tsserverSyncDiagnosticToLsp(d) {
|
|
|
265
265
|
* executed, the response envelope isn't `{success:true, body:[...]}`, or
|
|
266
266
|
* any error is thrown.
|
|
267
267
|
*/
|
|
268
|
-
|
|
268
|
+
async function runTsserverSyncCommand(svc, file, command) {
|
|
269
269
|
if (typeof svc.executeCommand !== "function")
|
|
270
270
|
return undefined;
|
|
271
271
|
const outcome = await svc.executeCommand(file, TSSERVER_REQUEST_COMMAND, [
|
|
@@ -24,6 +24,12 @@ export function classifyServerWaitTier(serverId, snapshot) {
|
|
|
24
24
|
const mode = snapshot.workspaceDiagnosticsSupport?.mode;
|
|
25
25
|
if (mode === "pull")
|
|
26
26
|
return "pull-capable";
|
|
27
|
+
if (snapshot.customServer === true &&
|
|
28
|
+
mode === "push-only" &&
|
|
29
|
+
snapshot.diagnosticsUnsupported === true &&
|
|
30
|
+
snapshot.diagnosticsPublished !== true) {
|
|
31
|
+
return "diagnostics-unsupported";
|
|
32
|
+
}
|
|
27
33
|
if (mode !== "push-only")
|
|
28
34
|
return "waits";
|
|
29
35
|
const strategy = getStrategy(serverId, snapshot.launchVariant);
|
|
@@ -73,6 +73,7 @@ export function resolveAstGrepNativeExe(platform = process.platform, arch = proc
|
|
|
73
73
|
return undefined;
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
|
+
/** @public — loaded by scripts/probe-clean-signal.mjs through a dynamic import wrapper knip cannot see. */
|
|
76
77
|
export const SERVER_DIAGNOSTIC_STRATEGIES = {
|
|
77
78
|
typescript: {
|
|
78
79
|
seedFirstPush: true,
|
|
@@ -287,7 +288,7 @@ const NATIVE_TS7_DIAGNOSTIC_STRATEGY = {
|
|
|
287
288
|
silentOnClean: false,
|
|
288
289
|
};
|
|
289
290
|
/** Fallback for unknown servers. Conservative defaults. */
|
|
290
|
-
|
|
291
|
+
const DEFAULT_STRATEGY = {
|
|
291
292
|
seedFirstPush: false,
|
|
292
293
|
pullRetryBudgetMs: 250,
|
|
293
294
|
debounceMs: 150,
|
|
@@ -8,6 +8,7 @@ import { normalizeMapKey } from "../path-utils.js";
|
|
|
8
8
|
import { loadReverseDependencyIndexFromSnapshot } from "../reverse-deps.js";
|
|
9
9
|
import { freshnessFromMtime } from "../freshness.js";
|
|
10
10
|
import { logLatency } from "../latency-logger.js";
|
|
11
|
+
import { recordDegradationOnce } from "../degradation-ledger.js";
|
|
11
12
|
import { compareOrdinal } from "../string-utils.js";
|
|
12
13
|
import { workspaceDiagnosticsCacheSessionStart } from "./workspace-diagnostics-session.js";
|
|
13
14
|
import { createDiskBindingCache, } from "./diagnostic-binding.js";
|
|
@@ -31,12 +32,17 @@ import { createDiskBindingCache, } from "./diagnostic-binding.js";
|
|
|
31
32
|
* `LSPWorkspaceDiagnosticResult.timedOut` in `./index.ts`) into
|
|
32
33
|
* `WorkspaceDiagnosticsCacheEntry`.
|
|
33
34
|
*/
|
|
35
|
+
// v3 (#2776): cached diagnostics must carry per-diagnostic `serverId`
|
|
36
|
+
// provenance before replay, because primary/auxiliary partitioning is
|
|
37
|
+
// server-owned rather than source-owned. v2 entries predate that contract and
|
|
38
|
+
// are rejected so the owning server can re-collect them instead of silently
|
|
39
|
+
// demoting old primary findings to auxiliary.
|
|
34
40
|
// v2 (#1095): entries may carry an optional `contentHash` fingerprint of the
|
|
35
41
|
// file bytes the cached diagnostics were computed against, so a `lookup` can
|
|
36
42
|
// surface a content `binding` (boundToCurrentDisk) beyond the mtime proxy.
|
|
37
43
|
// Legacy v1 entries are rejected by the version guard and re-scanned — a
|
|
38
44
|
// deliberately clean break so no entry lacking the field is ever served.
|
|
39
|
-
export const WORKSPACE_DIAGNOSTICS_CACHE_VERSION =
|
|
45
|
+
export const WORKSPACE_DIAGNOSTICS_CACHE_VERSION = 3;
|
|
40
46
|
const CACHE_FILE = "lsp-workspace-diagnostics.json";
|
|
41
47
|
function cachePath(cwd) {
|
|
42
48
|
return path.join(getProjectDataDir(cwd), "cache", CACHE_FILE);
|
|
@@ -161,11 +167,34 @@ export function loadWorkspaceDiagnosticsCache(cwd) {
|
|
|
161
167
|
if (!parsed || typeof parsed !== "object")
|
|
162
168
|
return undefined;
|
|
163
169
|
const cache = parsed;
|
|
164
|
-
if (cache.version !== WORKSPACE_DIAGNOSTICS_CACHE_VERSION)
|
|
170
|
+
if (cache.version !== WORKSPACE_DIAGNOSTICS_CACHE_VERSION) {
|
|
171
|
+
if (cache.version === 1 || cache.version === 2) {
|
|
172
|
+
recordDegradationOnce({
|
|
173
|
+
kind: "lsp-workspace-cache-migration",
|
|
174
|
+
subject: path.resolve(cwd),
|
|
175
|
+
reason: `rejected v${cache.version} cache with ${cache.entries && typeof cache.entries === "object"
|
|
176
|
+
? Object.keys(cache.entries).length
|
|
177
|
+
: 0} entries during provenance migration`,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
165
180
|
return undefined;
|
|
181
|
+
}
|
|
166
182
|
if (!cache.entries || typeof cache.entries !== "object")
|
|
167
183
|
return undefined;
|
|
168
|
-
|
|
184
|
+
const validEntries = {};
|
|
185
|
+
for (const [key, entry] of Object.entries(cache.entries)) {
|
|
186
|
+
if (!entry || typeof entry !== "object")
|
|
187
|
+
continue;
|
|
188
|
+
if (!Array.isArray(entry.diagnostics) ||
|
|
189
|
+
entry.diagnostics.some((diagnostic) => !diagnostic ||
|
|
190
|
+
typeof diagnostic !== "object" ||
|
|
191
|
+
typeof diagnostic.serverId !== "string" ||
|
|
192
|
+
diagnostic.serverId.length === 0)) {
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
validEntries[key] = entry;
|
|
196
|
+
}
|
|
197
|
+
return { ...cache, entries: validEntries };
|
|
169
198
|
});
|
|
170
199
|
}
|
|
171
200
|
export function saveWorkspaceDiagnosticsCache(cwd, cache) {
|
|
@@ -470,6 +499,9 @@ export function createWorkspaceDiagnosticsCacheContext(cwd) {
|
|
|
470
499
|
depIndexColdRefusalCount = 0;
|
|
471
500
|
};
|
|
472
501
|
return {
|
|
502
|
+
importsFor(filePath) {
|
|
503
|
+
return getImports(filePath);
|
|
504
|
+
},
|
|
473
505
|
lookup(filePath, scopeKey) {
|
|
474
506
|
// #1669 review N4: the epoch guarded `persist()` but not `lookup()` —
|
|
475
507
|
// an in-flight sweep kept REPLAYING disowned entries into its OWN
|
|
@@ -552,11 +584,12 @@ export function createWorkspaceDiagnosticsCacheContext(cwd) {
|
|
|
552
584
|
};
|
|
553
585
|
},
|
|
554
586
|
record(filePath, scopeKey, diagnostics, mtimeMs, contentHash, sizeBytes) {
|
|
587
|
+
const scanGeneration = Date.now();
|
|
555
588
|
entries[cacheKeyFor(filePath)] = {
|
|
556
589
|
diagnostics,
|
|
557
590
|
count: diagnostics.length,
|
|
558
591
|
mtimeMs,
|
|
559
|
-
scannedAt:
|
|
592
|
+
scannedAt: scanGeneration,
|
|
560
593
|
scopeKey,
|
|
561
594
|
// #1793: stamp whether THIS FILE actually had dependency
|
|
562
595
|
// knowledge this sweep (not just whether SOME index was
|
|
@@ -2,7 +2,7 @@ import { getLSPService } from "./lsp/index.js";
|
|
|
2
2
|
// Grounded against this repo's workspace-native TypeScript 7.0.2 server
|
|
3
3
|
// (`tsc --lsp --stdio`) on 2026-07-30: 20 already-open documentSymbol calls
|
|
4
4
|
// measured p50 3.70 ms / p95 5.28 ms. Keep generous headroom for slower hosts.
|
|
5
|
-
|
|
5
|
+
const LSP_DOCUMENT_SYMBOL_TIMEOUT_MS = 150;
|
|
6
6
|
export const SYMBOL_KIND_NAMES = {
|
|
7
7
|
1: "file",
|
|
8
8
|
2: "module",
|
|
@@ -367,6 +367,9 @@ export async function analyzeFile(filePath, cwd, options = {}) {
|
|
|
367
367
|
const lspRunner = latencyReport?.runners.find((runner) => runner.runnerId === "lsp");
|
|
368
368
|
const lsp = lspRunner
|
|
369
369
|
? {
|
|
370
|
+
// `deferred` means the runner entered the LSP path but its auxiliary
|
|
371
|
+
// coverage is delivered later, so it still counts as ran here. The
|
|
372
|
+
// status remains available to surfaces that need the coverage detail.
|
|
370
373
|
ran: lspRunner.status !== "skipped" &&
|
|
371
374
|
lspRunner.status !== "when_skipped" &&
|
|
372
375
|
lspRunner.status !== "test_file_skipped",
|
|
@@ -30,6 +30,7 @@ import { RuntimeCoordinator } from "../runtime-coordinator.js";
|
|
|
30
30
|
import { handleSessionStart } from "../runtime-session.js";
|
|
31
31
|
import { handleTurnEnd } from "../runtime-turn.js";
|
|
32
32
|
import { createMcpHost } from "./host-shim.js";
|
|
33
|
+
import { startSituationalToolTelemetrySession } from "../situational-tool-telemetry.js";
|
|
33
34
|
let contextPromise;
|
|
34
35
|
let resolvedRuntime;
|
|
35
36
|
/**
|
|
@@ -79,6 +80,7 @@ function joinMessages(consumed) {
|
|
|
79
80
|
* `pilens_health` afterwards for the scan results as they land.
|
|
80
81
|
*/
|
|
81
82
|
export async function runSessionStart(cwd) {
|
|
83
|
+
startSituationalToolTelemetrySession("mcp");
|
|
82
84
|
const ctx = await getMcpSessionContext();
|
|
83
85
|
const host = createMcpHost(undefined, cwd);
|
|
84
86
|
await handleSessionStart({
|
|
@@ -93,7 +93,7 @@ export function loadHistory() {
|
|
|
93
93
|
/**
|
|
94
94
|
* Save history to disk
|
|
95
95
|
*/
|
|
96
|
-
|
|
96
|
+
function saveHistory(history) {
|
|
97
97
|
const historyDir = getProjectDataDir(process.cwd());
|
|
98
98
|
if (!fs.existsSync(historyDir)) {
|
|
99
99
|
fs.mkdirSync(historyDir, { recursive: true });
|
|
@@ -161,10 +161,35 @@ export function captureSnapshot(filePath, metrics) {
|
|
|
161
161
|
}, SAVE_DEBOUNCE_MS);
|
|
162
162
|
saveTimer.unref?.();
|
|
163
163
|
}
|
|
164
|
+
// --- Trend Analysis ---
|
|
164
165
|
/**
|
|
165
|
-
*
|
|
166
|
-
*
|
|
166
|
+
* Compute trend direction from history snapshots
|
|
167
|
+
* Uses last 3 snapshots for stability (or 2 if only 2 available)
|
|
167
168
|
*/
|
|
169
|
+
function computeTrend(history) {
|
|
170
|
+
if (history.length < 2)
|
|
171
|
+
return "stable";
|
|
172
|
+
const recent = history.slice(-3);
|
|
173
|
+
const first = recent[0];
|
|
174
|
+
const last = recent[recent.length - 1];
|
|
175
|
+
// Use MI as primary indicator, cognitive as secondary
|
|
176
|
+
const miDelta = last.mi - first.mi;
|
|
177
|
+
const cogDelta = last.cognitive - first.cognitive;
|
|
178
|
+
// Thresholds (MI changes < 2 are noise)
|
|
179
|
+
if (miDelta > 2)
|
|
180
|
+
return "improving";
|
|
181
|
+
if (miDelta < -2)
|
|
182
|
+
return "regressing";
|
|
183
|
+
// If MI is stable, check cognitive
|
|
184
|
+
if (cogDelta < -10)
|
|
185
|
+
return "improving";
|
|
186
|
+
if (cogDelta > 10)
|
|
187
|
+
return "regressing";
|
|
188
|
+
return "stable";
|
|
189
|
+
}
|
|
190
|
+
// --- Technical Debt Index (TDI) ---
|
|
191
|
+
// Test-reached through a child-process `require` string
|
|
192
|
+
/** @public — reached through a child-process `require` string in tests/clients/metrics-history-stderr.test.ts; knip cannot see it. */
|
|
168
193
|
export function captureSnapshots(files) {
|
|
169
194
|
const history = loadHistory();
|
|
170
195
|
for (const file of files) {
|
|
@@ -200,110 +225,6 @@ export function captureSnapshots(files) {
|
|
|
200
225
|
saveHistory(history);
|
|
201
226
|
return history;
|
|
202
227
|
}
|
|
203
|
-
// --- Trend Analysis ---
|
|
204
|
-
/**
|
|
205
|
-
* Compute trend direction from history snapshots
|
|
206
|
-
* Uses last 3 snapshots for stability (or 2 if only 2 available)
|
|
207
|
-
*/
|
|
208
|
-
export function computeTrend(history) {
|
|
209
|
-
if (history.length < 2)
|
|
210
|
-
return "stable";
|
|
211
|
-
const recent = history.slice(-3);
|
|
212
|
-
const first = recent[0];
|
|
213
|
-
const last = recent[recent.length - 1];
|
|
214
|
-
// Use MI as primary indicator, cognitive as secondary
|
|
215
|
-
const miDelta = last.mi - first.mi;
|
|
216
|
-
const cogDelta = last.cognitive - first.cognitive;
|
|
217
|
-
// Thresholds (MI changes < 2 are noise)
|
|
218
|
-
if (miDelta > 2)
|
|
219
|
-
return "improving";
|
|
220
|
-
if (miDelta < -2)
|
|
221
|
-
return "regressing";
|
|
222
|
-
// If MI is stable, check cognitive
|
|
223
|
-
if (cogDelta < -10)
|
|
224
|
-
return "improving";
|
|
225
|
-
if (cogDelta > 10)
|
|
226
|
-
return "regressing";
|
|
227
|
-
return "stable";
|
|
228
|
-
}
|
|
229
|
-
/**
|
|
230
|
-
* Get delta between current snapshot and previous
|
|
231
|
-
*/
|
|
232
|
-
export function getDelta(history) {
|
|
233
|
-
if (!history || history.history.length < 2)
|
|
234
|
-
return null;
|
|
235
|
-
const current = history.history[history.history.length - 1];
|
|
236
|
-
const previous = history.history[history.history.length - 2];
|
|
237
|
-
return {
|
|
238
|
-
mi: Math.round((current.mi - previous.mi) * 10) / 10,
|
|
239
|
-
cognitive: current.cognitive - previous.cognitive,
|
|
240
|
-
trend: history.trend,
|
|
241
|
-
};
|
|
242
|
-
}
|
|
243
|
-
/**
|
|
244
|
-
* Get trend emoji for display
|
|
245
|
-
*/
|
|
246
|
-
export function getTrendEmoji(trend) {
|
|
247
|
-
switch (trend) {
|
|
248
|
-
case "improving":
|
|
249
|
-
return "📈";
|
|
250
|
-
case "regressing":
|
|
251
|
-
return "📉";
|
|
252
|
-
default:
|
|
253
|
-
return "➡️";
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
/**
|
|
257
|
-
* Get trend summary across all files
|
|
258
|
-
*/
|
|
259
|
-
export function getTrendSummary(history) {
|
|
260
|
-
let improving = 0;
|
|
261
|
-
let regressing = 0;
|
|
262
|
-
let stable = 0;
|
|
263
|
-
const regressions = [];
|
|
264
|
-
for (const [file, fileHistory] of Object.entries(history.files)) {
|
|
265
|
-
switch (fileHistory.trend) {
|
|
266
|
-
case "improving":
|
|
267
|
-
improving++;
|
|
268
|
-
break;
|
|
269
|
-
case "regressing": {
|
|
270
|
-
regressing++;
|
|
271
|
-
const delta = getDelta(fileHistory);
|
|
272
|
-
if (delta) {
|
|
273
|
-
regressions.push({ file, miDelta: delta.mi });
|
|
274
|
-
}
|
|
275
|
-
break;
|
|
276
|
-
}
|
|
277
|
-
default:
|
|
278
|
-
stable++;
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
// Sort regressions by MI delta (worst first)
|
|
282
|
-
regressions.sort((a, b) => a.miDelta - b.miDelta);
|
|
283
|
-
return {
|
|
284
|
-
improving,
|
|
285
|
-
regressing,
|
|
286
|
-
stable,
|
|
287
|
-
worstRegressions: regressions.slice(0, 5),
|
|
288
|
-
};
|
|
289
|
-
}
|
|
290
|
-
/**
|
|
291
|
-
* Format trend for metrics table
|
|
292
|
-
*/
|
|
293
|
-
export function formatTrendCell(filePath, history) {
|
|
294
|
-
const relativePath = path.relative(process.cwd(), filePath);
|
|
295
|
-
const fileHistory = history.files[relativePath];
|
|
296
|
-
if (!fileHistory || fileHistory.history.length < 2) {
|
|
297
|
-
return "—"; // No history
|
|
298
|
-
}
|
|
299
|
-
const delta = getDelta(fileHistory);
|
|
300
|
-
if (!delta)
|
|
301
|
-
return "—";
|
|
302
|
-
const emoji = getTrendEmoji(delta.trend);
|
|
303
|
-
const miSign = delta.mi > 0 ? "+" : "";
|
|
304
|
-
const miColor = delta.mi > 0 ? "🟢" : delta.mi < 0 ? "🔴" : "⚪";
|
|
305
|
-
return `${emoji} ${miColor}${miSign}${delta.mi}`;
|
|
306
|
-
}
|
|
307
228
|
/**
|
|
308
229
|
* Calculate Technical Debt Index for the project.
|
|
309
230
|
* Score: 0 = perfect, 100 = maximum debt.
|
|
@@ -159,7 +159,7 @@ function isAccessorLine(rawLine) {
|
|
|
159
159
|
* extracted data — no re-parsing, no file I/O beyond the lines already read
|
|
160
160
|
* by the caller.
|
|
161
161
|
*/
|
|
162
|
-
|
|
162
|
+
function analyzeMiddleMan(classEntry, lines, languageId) {
|
|
163
163
|
if (!languageId)
|
|
164
164
|
return undefined;
|
|
165
165
|
const selfSpec = SELF_TOKEN[languageId];
|
|
@@ -48,7 +48,7 @@ import { symbolExtractionGrammar, TreeSitterSymbolExtractor, } from "./tree-sitt
|
|
|
48
48
|
// lsp.ts) to be re-homed in #236, where LSP writes provenance-tagged edges INTO
|
|
49
49
|
// the review graph (computed once, persisted) so this path just reads them.
|
|
50
50
|
/** Hard payload bound for the per-symbol who-uses-this section. */
|
|
51
|
-
|
|
51
|
+
const MAX_MODULE_REPORT_REFS = 100;
|
|
52
52
|
function normalizeMaxRefsPerSymbol(value) {
|
|
53
53
|
if (value === undefined || !Number.isFinite(value))
|
|
54
54
|
return 10;
|
|
@@ -113,7 +113,7 @@ function asRecord(value) {
|
|
|
113
113
|
* field list the seam classifies with — a second spelling list would arm on
|
|
114
114
|
* inputs the seam cannot resolve, and miss ones it can.
|
|
115
115
|
*/
|
|
116
|
-
|
|
116
|
+
function resolveMutationPath(input) {
|
|
117
117
|
for (const key of ["path", "filePath", "file_path"]) {
|
|
118
118
|
const value = input[key];
|
|
119
119
|
if (typeof value === "string" && value.length > 0)
|
|
@@ -141,7 +141,7 @@ export function readMutationPathField(event) {
|
|
|
141
141
|
* base62 anchor — handled by `clients/hashline-anchor.ts`. Do not reach for
|
|
142
142
|
* this function there.
|
|
143
143
|
*/
|
|
144
|
-
|
|
144
|
+
function parseHashlineAnchor(anchor) {
|
|
145
145
|
if (typeof anchor !== "string")
|
|
146
146
|
return undefined;
|
|
147
147
|
const trimmed = anchor.trim();
|
|
@@ -153,7 +153,7 @@ export function parseHashlineAnchor(anchor) {
|
|
|
153
153
|
return Number.isInteger(line) && line > 0 ? line : undefined;
|
|
154
154
|
}
|
|
155
155
|
/** Bounding box plus per-range detail for a multi-range edit. */
|
|
156
|
-
|
|
156
|
+
function combineRanges(ranges) {
|
|
157
157
|
const starts = ranges.map(([start]) => start);
|
|
158
158
|
const ends = ranges.map(([, end]) => end);
|
|
159
159
|
return {
|