@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
|
@@ -18,7 +18,7 @@ import { containerNameChain, getOpenDocumentSymbols, lspSymbolKindName, } from "
|
|
|
18
18
|
import { isAtOrAboveHomeDir, normalizeFilePath, normalizeMapKey, toProjectRelativePath, } from "../path-utils.js";
|
|
19
19
|
import { collectProjectSourceFilesWithBudgetAsync } from "../project-scan-policy.js";
|
|
20
20
|
import { getReviewGraphMaxFilesDerived } from "../project-scale.js";
|
|
21
|
-
import { compareOrdinal } from "../string-utils.js";
|
|
21
|
+
import { compareOrdinal, escapeRegExp } from "../string-utils.js";
|
|
22
22
|
import { BoundedLruCache } from "../bounded-cache.js";
|
|
23
23
|
import { jsTsCandidatePaths, resolveAliasedImport, resolveImportToFiles, resolveProjectReferenceImport, resolveWorkspacePackageImport, } from "./import-resolvers.js";
|
|
24
24
|
import { RUNTIME_CONFIG } from "../runtime-config.js";
|
|
@@ -27,7 +27,7 @@ import { buildQualifiedName, findOwnerName } from "../symbol-containment.js";
|
|
|
27
27
|
import { logTreeSitterCacheStats } from "../tree-sitter-logger.js";
|
|
28
28
|
import { flushReviewGraphLogSync, logReviewGraph, makeReviewGraphBuildMetadata, } from "../review-graph-logger.js";
|
|
29
29
|
import { getSharedTreeSitterClient } from "../tree-sitter-shared.js";
|
|
30
|
-
import { TreeSitterSymbolExtractor, } from "../tree-sitter-symbol-extractor.js";
|
|
30
|
+
import { symbolExtractionGrammar, TreeSitterSymbolExtractor, } from "../tree-sitter-symbol-extractor.js";
|
|
31
31
|
import { withTreeSitterRoot } from "../tree-sitter-shared.js";
|
|
32
32
|
import { incrementDegradationCount } from "../degradation-ledger.js";
|
|
33
33
|
import { resolveGitIdentity } from "./git-identity.js";
|
|
@@ -92,8 +92,6 @@ const MAIN_KINDS = new Set([
|
|
|
92
92
|
// so a repo heavy in JSON/YAML/Markdown doesn't trip the cap on files the graph
|
|
93
93
|
// would have filtered out anyway (the cap is on the walk, not on noise). #250.
|
|
94
94
|
const MAIN_KIND_EXTENSIONS = Array.from(MAIN_KINDS).flatMap((kind) => KIND_EXTENSIONS[kind] ?? []);
|
|
95
|
-
/** The bounded, source-filtered extension set shared by graph cache readers. */
|
|
96
|
-
export const REVIEW_GRAPH_SOURCE_EXTENSIONS = MAIN_KIND_EXTENSIONS;
|
|
97
95
|
const CHANGED_SYMBOLS_PREFIX = "session.reviewGraph.changedSymbols:";
|
|
98
96
|
const extractorCache = new Map();
|
|
99
97
|
const REVIEW_GRAPH_MAX_WARM_WORKSPACES = 8;
|
|
@@ -103,27 +101,20 @@ const REVIEW_GRAPH_MAX_WARM_WORKSPACES = 8;
|
|
|
103
101
|
// spelling is resolved once; repeated builds reuse the result. The project
|
|
104
102
|
// memo is bounded and workspace-cache clears provide a freshness boundary.
|
|
105
103
|
const REVIEW_GRAPH_SOURCE_PATH_MEMO_ENTRIES = 16_384;
|
|
106
|
-
|
|
104
|
+
// BoundedLruCache, not BoundedFifoMap: a hit here must refresh the workspace's
|
|
105
|
+
// recency (the hand-rolled version did its own delete+set for exactly that),
|
|
106
|
+
// so a workspace still being built is never the one evicted (#2442).
|
|
107
|
+
const _sourcePathMemos = new BoundedLruCache(REVIEW_GRAPH_MAX_WARM_WORKSPACES);
|
|
107
108
|
function sourcePathMemo(cwd) {
|
|
108
109
|
const key = normalizeMapKey(path.resolve(cwd));
|
|
109
110
|
const existing = _sourcePathMemos.get(key);
|
|
110
|
-
if (existing)
|
|
111
|
-
// The workspace map is also bounded LRU; a hit must refresh its recency.
|
|
112
|
-
_sourcePathMemos.delete(key);
|
|
113
|
-
_sourcePathMemos.set(key, existing);
|
|
111
|
+
if (existing)
|
|
114
112
|
return existing;
|
|
115
|
-
}
|
|
116
113
|
const memo = {
|
|
117
114
|
cache: new BoundedLruCache(REVIEW_GRAPH_SOURCE_PATH_MEMO_ENTRIES),
|
|
118
115
|
normalizeCalls: { value: 0 },
|
|
119
116
|
};
|
|
120
117
|
_sourcePathMemos.set(key, memo);
|
|
121
|
-
while (_sourcePathMemos.size > REVIEW_GRAPH_MAX_WARM_WORKSPACES) {
|
|
122
|
-
const oldest = _sourcePathMemos.keys().next().value;
|
|
123
|
-
if (oldest === undefined)
|
|
124
|
-
break;
|
|
125
|
-
_sourcePathMemos.delete(oldest);
|
|
126
|
-
}
|
|
127
118
|
return memo;
|
|
128
119
|
}
|
|
129
120
|
function normalizeGraphSourcePath(memo, raw) {
|
|
@@ -414,7 +405,7 @@ export function estimateReviewGraphStoreBytes(totalNodes, totalEdges) {
|
|
|
414
405
|
// cleared). Bounding only the cache left the full graph resident on the fact, so
|
|
415
406
|
// both sites go through `retainedGraph` below, memoized per graph instance so the
|
|
416
407
|
// two sites share ONE bounded object instead of trimming twice (#2255 review F2).
|
|
417
|
-
|
|
408
|
+
const GRAPH_MAX_IN_MEMORY_BYTES_DEFAULT = 512 * 1024 * 1024;
|
|
418
409
|
function graphMaxInMemoryBytes() {
|
|
419
410
|
const raw = Number(process.env.PI_LENS_GRAPH_MAX_IN_MEMORY_BYTES);
|
|
420
411
|
return Number.isFinite(raw) && raw > 0
|
|
@@ -528,12 +519,15 @@ function headSliceGraph(graph, cap) {
|
|
|
528
519
|
* This bounds the VALUE, not the store, and deliberately adds no second bounding
|
|
529
520
|
* mechanism to `FactStore` (#2243 owns the store-level discipline).
|
|
530
521
|
*
|
|
531
|
-
* `sessionFacts` entry COUNT
|
|
532
|
-
*
|
|
533
|
-
* (`dispatch/integration.ts`)
|
|
534
|
-
*
|
|
535
|
-
*
|
|
536
|
-
*
|
|
522
|
+
* `sessionFacts` entry COUNT (a separate #2240 sibling, #2282) is now bounded
|
|
523
|
+
* too: `session.baseline.${path}` (`dispatch/dispatcher.ts`),
|
|
524
|
+
* `session.baseline.cascade.${path}` (`dispatch/integration.ts`), and this
|
|
525
|
+
* module's own `changedSymbols`/`entitySnapshot` per-file keys all go through
|
|
526
|
+
* `FactStore.setBoundedSessionFact`/`getBoundedSessionFact`, an LRU-count-cap
|
|
527
|
+
* sibling of the per-file `fileFacts` bound reusing the SAME discipline
|
|
528
|
+
* (#2243), not a second mechanism. `session.reviewGraph` itself stays on the
|
|
529
|
+
* plain, unbounded `sessionFacts` map — its key is a fixed singleton, so the
|
|
530
|
+
* VALUE bound below is what keeps IT small, not an entry-count cap.
|
|
537
531
|
*/
|
|
538
532
|
function setSessionReviewGraphFact(cwd, facts, graph) {
|
|
539
533
|
const retained = retainedGraph(cwd, graph);
|
|
@@ -826,9 +820,6 @@ function makeCtx(filePath, cwd, facts) {
|
|
|
826
820
|
log: () => { },
|
|
827
821
|
};
|
|
828
822
|
}
|
|
829
|
-
function escapeRegExp(string) {
|
|
830
|
-
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
831
|
-
}
|
|
832
823
|
function createEmptyGraph() {
|
|
833
824
|
return {
|
|
834
825
|
version: REVIEW_GRAPH_VERSION,
|
|
@@ -974,7 +965,7 @@ function diffSignatureMaps(previous, next) {
|
|
|
974
965
|
// `RUNTIME_CONFIG.reviewGraph.maxFiles` constant as the fallback — the ratio
|
|
975
966
|
// table reproduces that same 1,000-file default at the default base, so this
|
|
976
967
|
// is behavior-neutral when nothing is configured.
|
|
977
|
-
|
|
968
|
+
function getReviewGraphMaxFiles(cwd) {
|
|
978
969
|
const override = Number.parseInt(process.env.PI_LENS_REVIEW_GRAPH_MAX_FILES ?? "", 10);
|
|
979
970
|
return Number.isFinite(override) && override > 0
|
|
980
971
|
? override
|
|
@@ -1226,13 +1217,15 @@ function indexEdge(graph, edge) {
|
|
|
1226
1217
|
graph.edgesByTo.set(edge.to, to);
|
|
1227
1218
|
}
|
|
1228
1219
|
/**
|
|
1229
|
-
* Drop `edge` from both adjacency buckets
|
|
1230
|
-
*
|
|
1231
|
-
*
|
|
1220
|
+
* Drop `edge` from both adjacency buckets. This is kept for the single-edge
|
|
1221
|
+
* dedupe path; multi-file removal uses `unindexEdges` below so a shared hub
|
|
1222
|
+
* bucket is scanned once rather than once per removed edge (#2074).
|
|
1232
1223
|
*/
|
|
1233
1224
|
function unindexEdge(graph, edge) {
|
|
1234
1225
|
const from = graph.edgesByFrom.get(edge.from);
|
|
1235
1226
|
if (from) {
|
|
1227
|
+
// Count the full bucket as the linear `indexOf` scan's bounded work.
|
|
1228
|
+
_rebuildCounters.removeOwnedEdgePositions += from.length;
|
|
1236
1229
|
const at = from.indexOf(edge);
|
|
1237
1230
|
if (at >= 0)
|
|
1238
1231
|
from.splice(at, 1);
|
|
@@ -1241,6 +1234,7 @@ function unindexEdge(graph, edge) {
|
|
|
1241
1234
|
}
|
|
1242
1235
|
const to = graph.edgesByTo.get(edge.to);
|
|
1243
1236
|
if (to) {
|
|
1237
|
+
_rebuildCounters.removeOwnedEdgePositions += to.length;
|
|
1244
1238
|
const at = to.indexOf(edge);
|
|
1245
1239
|
if (at >= 0)
|
|
1246
1240
|
to.splice(at, 1);
|
|
@@ -1248,6 +1242,49 @@ function unindexEdge(graph, edge) {
|
|
|
1248
1242
|
graph.edgesByTo.delete(edge.to);
|
|
1249
1243
|
}
|
|
1250
1244
|
}
|
|
1245
|
+
/**
|
|
1246
|
+
* Remove a batch of edges from both live adjacency indexes. Each touched
|
|
1247
|
+
* bucket is filtered once, so the work is proportional to the bucket lengths,
|
|
1248
|
+
* not to the product of a hub's fan-in and its removed-edge count (#2074).
|
|
1249
|
+
*/
|
|
1250
|
+
function unindexEdges(graph, removedEdges) {
|
|
1251
|
+
const fromIds = new Set();
|
|
1252
|
+
const toIds = new Set();
|
|
1253
|
+
for (const edge of removedEdges) {
|
|
1254
|
+
fromIds.add(edge.from);
|
|
1255
|
+
toIds.add(edge.to);
|
|
1256
|
+
}
|
|
1257
|
+
for (const fromId of fromIds) {
|
|
1258
|
+
const bucket = graph.edgesByFrom.get(fromId);
|
|
1259
|
+
if (!bucket)
|
|
1260
|
+
continue;
|
|
1261
|
+
const kept = [];
|
|
1262
|
+
for (const edge of bucket) {
|
|
1263
|
+
_rebuildCounters.removeOwnedEdgePositions++;
|
|
1264
|
+
if (!removedEdges.has(edge))
|
|
1265
|
+
kept.push(edge);
|
|
1266
|
+
}
|
|
1267
|
+
if (kept.length === 0)
|
|
1268
|
+
graph.edgesByFrom.delete(fromId);
|
|
1269
|
+
else
|
|
1270
|
+
graph.edgesByFrom.set(fromId, kept);
|
|
1271
|
+
}
|
|
1272
|
+
for (const toId of toIds) {
|
|
1273
|
+
const bucket = graph.edgesByTo.get(toId);
|
|
1274
|
+
if (!bucket)
|
|
1275
|
+
continue;
|
|
1276
|
+
const kept = [];
|
|
1277
|
+
for (const edge of bucket) {
|
|
1278
|
+
_rebuildCounters.removeOwnedEdgePositions++;
|
|
1279
|
+
if (!removedEdges.has(edge))
|
|
1280
|
+
kept.push(edge);
|
|
1281
|
+
}
|
|
1282
|
+
if (kept.length === 0)
|
|
1283
|
+
graph.edgesByTo.delete(toId);
|
|
1284
|
+
else
|
|
1285
|
+
graph.edgesByTo.set(toId, kept);
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1251
1288
|
function addEdge(graph, edge) {
|
|
1252
1289
|
graph.edges.push(edge);
|
|
1253
1290
|
indexEdge(graph, edge);
|
|
@@ -2621,9 +2658,16 @@ async function tryResumeFromCheckpoint(cwd, filesToBuild, ignoredIds) {
|
|
|
2621
2658
|
}
|
|
2622
2659
|
const graph = loaded.graph;
|
|
2623
2660
|
// Evict every stale (content-changed) processed file so its outdated
|
|
2624
|
-
// contribution is replaced by a fresh walk below.
|
|
2661
|
+
// contribution is replaced by a fresh walk below. One shared drop set,
|
|
2662
|
+
// compacted once (#2074) — pruneOrphanNonFileNodes reads graph.edges next,
|
|
2663
|
+
// so the compaction must land before it runs.
|
|
2664
|
+
const removedEdges = new Set();
|
|
2625
2665
|
for (const file of stale)
|
|
2626
|
-
removeFileOwnedGraphData(graph, file);
|
|
2666
|
+
removeFileOwnedGraphData(graph, file, removedEdges);
|
|
2667
|
+
if (removedEdges.size > 0) {
|
|
2668
|
+
unindexEdges(graph, removedEdges);
|
|
2669
|
+
graph.edges = graph.edges.filter((edge) => !removedEdges.has(edge));
|
|
2670
|
+
}
|
|
2627
2671
|
pruneOrphanNonFileNodes(graph);
|
|
2628
2672
|
graph.changedSymbolsByFile = new Map();
|
|
2629
2673
|
const remaining = filesToBuild.filter((file) => !reusableHashes.has(file));
|
|
@@ -2654,7 +2698,7 @@ export function _readReviewGraphCheckpointForTests(cwd) {
|
|
|
2654
2698
|
}
|
|
2655
2699
|
/** Test hook: force any pending debounced persist to write immediately. */
|
|
2656
2700
|
export function flushReviewGraphPersistsForTests() {
|
|
2657
|
-
for (const key of
|
|
2701
|
+
for (const key of _pendingPersist.keys()) {
|
|
2658
2702
|
const pending = _pendingPersist.get(key);
|
|
2659
2703
|
if (!pending)
|
|
2660
2704
|
continue;
|
|
@@ -2718,7 +2762,7 @@ export function flushReviewGraphPersist(cwd, source = "cli") {
|
|
|
2718
2762
|
let pending = _pendingPersist.get(key);
|
|
2719
2763
|
const removedWorkerRequests = [];
|
|
2720
2764
|
let selectedWorkerRequest;
|
|
2721
|
-
for (const [id, request] of
|
|
2765
|
+
for (const [id, request] of _workerRequests) {
|
|
2722
2766
|
if (request.key !== key)
|
|
2723
2767
|
continue;
|
|
2724
2768
|
_workerRequests.delete(id);
|
|
@@ -2883,7 +2927,7 @@ function upsertChangedSymbols(graph, facts, filePath) {
|
|
|
2883
2927
|
if (detectFileRole(filePath) === "test")
|
|
2884
2928
|
return;
|
|
2885
2929
|
const normalized = normalizeMapKey(filePath);
|
|
2886
|
-
const changed = facts.
|
|
2930
|
+
const changed = facts.getBoundedSessionFact(`${CHANGED_SYMBOLS_PREFIX}${normalized}`);
|
|
2887
2931
|
if (changed && changed.length > 0) {
|
|
2888
2932
|
graph.changedSymbolsByFile.set(normalized, [...changed]);
|
|
2889
2933
|
}
|
|
@@ -3158,45 +3202,13 @@ function addJsTsFile(graph, cwd, filePath, facts, ignoredIds) {
|
|
|
3158
3202
|
}
|
|
3159
3203
|
}
|
|
3160
3204
|
}
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
return "rust";
|
|
3169
|
-
case "ruby":
|
|
3170
|
-
return "ruby";
|
|
3171
|
-
case "cxx": {
|
|
3172
|
-
const ext = filePath ? path.extname(filePath).toLowerCase() : "";
|
|
3173
|
-
return ext === ".c" || ext === ".h" ? "c" : "cpp";
|
|
3174
|
-
}
|
|
3175
|
-
case "java":
|
|
3176
|
-
return "java";
|
|
3177
|
-
case "kotlin":
|
|
3178
|
-
return "kotlin";
|
|
3179
|
-
case "dart":
|
|
3180
|
-
return "dart";
|
|
3181
|
-
case "elixir":
|
|
3182
|
-
return "elixir";
|
|
3183
|
-
case "csharp":
|
|
3184
|
-
return "csharp";
|
|
3185
|
-
case "php":
|
|
3186
|
-
return "php";
|
|
3187
|
-
case "swift":
|
|
3188
|
-
return "swift";
|
|
3189
|
-
case "lua":
|
|
3190
|
-
return "lua";
|
|
3191
|
-
case "ocaml":
|
|
3192
|
-
return "ocaml";
|
|
3193
|
-
case "zig":
|
|
3194
|
-
return "zig";
|
|
3195
|
-
case "shell":
|
|
3196
|
-
return "bash";
|
|
3197
|
-
default:
|
|
3198
|
-
return undefined;
|
|
3199
|
-
}
|
|
3205
|
+
// The review graph's kind -> tree-sitter grammar answer. Delegates to the
|
|
3206
|
+
// registry-derived resolver (#2424): this used to be a hand-written switch that
|
|
3207
|
+
// re-derived the `.c`/`.h` split inline and drifted from the ext -> grammar
|
|
3208
|
+
// authority. Exported for the language-identity golden snapshot
|
|
3209
|
+
// (scripts/gen-language-snapshot.mjs).
|
|
3210
|
+
export function mapKindToTreeSitterLanguage(kind, filePath) {
|
|
3211
|
+
return symbolExtractionGrammar(kind, filePath);
|
|
3200
3212
|
}
|
|
3201
3213
|
async function getExtractor(languageId) {
|
|
3202
3214
|
if (extractorCache.has(languageId))
|
|
@@ -3467,7 +3479,7 @@ function addTreeSitterFile(graph, cwd, filePath, languageId, extracted, ignoredI
|
|
|
3467
3479
|
* SymbolInformation results (including native TypeScript 7) recover the same
|
|
3468
3480
|
* containment through `containerName` when the owner is present in the result.
|
|
3469
3481
|
*/
|
|
3470
|
-
|
|
3482
|
+
function addLspFallbackSymbols(graph, filePath, languageId, symbols) {
|
|
3471
3483
|
const normalized = normalizeMapKey(filePath);
|
|
3472
3484
|
const fileNodeId = `file:${normalized}`;
|
|
3473
3485
|
let added = 0;
|
|
@@ -3622,46 +3634,55 @@ function addCxxIncludeEdges(graph, cwd, filePath, ignoredIds, contentOverride) {
|
|
|
3622
3634
|
});
|
|
3623
3635
|
}
|
|
3624
3636
|
}
|
|
3625
|
-
|
|
3637
|
+
/**
|
|
3638
|
+
* Drop the nodes/edges a changed file owns, and index-maintain as it goes.
|
|
3639
|
+
* `removedEdges` accumulates edges to drop from `graph.edges` — the CALLER
|
|
3640
|
+
* compacts the array once for the whole batch (#2074): before this, each call
|
|
3641
|
+
* ran its own `graph.edges.filter()`, so a batch of N changed files scanned
|
|
3642
|
+
* the whole edge array N times (changedFiles x graph, not changedFiles x
|
|
3643
|
+
* fan-in/out).
|
|
3644
|
+
*
|
|
3645
|
+
* `removedIds` is exactly `fileNodes`/`symbolNodesByFile`'s entries for this
|
|
3646
|
+
* file — `file` and `symbol` are the only node kinds that ever set `filePath`
|
|
3647
|
+
* (`module`/`external` placeholders never do) — so no `graph.nodes` scan is
|
|
3648
|
+
* needed either, and the owned edges are read straight off `edgesByFrom` /
|
|
3649
|
+
* `edgesByTo` instead of scanning `graph.edges`.
|
|
3650
|
+
*/
|
|
3651
|
+
function removeFileOwnedGraphData(graph, filePath, removedEdges) {
|
|
3626
3652
|
const normalized = normalizeMapKey(filePath);
|
|
3627
|
-
const fileNodeId = `file:${normalized}`;
|
|
3628
|
-
const
|
|
3629
|
-
const
|
|
3630
|
-
for (const [id, node] of graph.nodes) {
|
|
3631
|
-
if (node.filePath !== normalized)
|
|
3632
|
-
continue;
|
|
3633
|
-
removedIds.add(id);
|
|
3634
|
-
if (node.kind === "symbol")
|
|
3635
|
-
removedSymbolIds.add(id);
|
|
3636
|
-
}
|
|
3653
|
+
const fileNodeId = graph.fileNodes.get(normalized) ?? `file:${normalized}`;
|
|
3654
|
+
const removedSymbolIds = new Set(graph.symbolNodesByFile.get(normalized));
|
|
3655
|
+
const removedIds = new Set(removedSymbolIds);
|
|
3637
3656
|
if (graph.nodes.has(fileNodeId))
|
|
3638
3657
|
removedIds.add(fileNodeId);
|
|
3658
|
+
const candidates = new Set();
|
|
3659
|
+
for (const id of removedIds) {
|
|
3660
|
+
for (const edge of graph.edgesByFrom.get(id) ?? []) {
|
|
3661
|
+
_rebuildCounters.removeOwnedEdgeVisits++;
|
|
3662
|
+
candidates.add(edge);
|
|
3663
|
+
}
|
|
3664
|
+
for (const edge of graph.edgesByTo.get(id) ?? []) {
|
|
3665
|
+
_rebuildCounters.removeOwnedEdgeVisits++;
|
|
3666
|
+
candidates.add(edge);
|
|
3667
|
+
}
|
|
3668
|
+
}
|
|
3639
3669
|
const preservedIncomingSymbolEdges = [];
|
|
3640
|
-
const
|
|
3641
|
-
|
|
3670
|
+
for (const edge of candidates) {
|
|
3671
|
+
// A cross-edge can be discovered from both changed files' adjacency
|
|
3672
|
+
// buckets. Preserve and remove it only once, matching eager unindexing
|
|
3673
|
+
// while the batch indexes remain live until the end.
|
|
3674
|
+
if (removedEdges.has(edge))
|
|
3675
|
+
continue;
|
|
3642
3676
|
const fromRemoved = removedIds.has(edge.from);
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
if (removedSymbolIds.has(edge.to)) {
|
|
3677
|
+
// Preserve importer edges to the stable file node id; the node is
|
|
3678
|
+
// re-added below.
|
|
3679
|
+
if (!fromRemoved && edge.to === fileNodeId)
|
|
3680
|
+
continue;
|
|
3681
|
+
if (!fromRemoved && removedSymbolIds.has(edge.to)) {
|
|
3649
3682
|
preservedIncomingSymbolEdges.push({ ...edge });
|
|
3650
|
-
droppedEdges.push(edge);
|
|
3651
|
-
return false;
|
|
3652
3683
|
}
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
return true;
|
|
3656
|
-
if (toRemoved)
|
|
3657
|
-
droppedEdges.push(edge);
|
|
3658
|
-
return !toRemoved;
|
|
3659
|
-
});
|
|
3660
|
-
// #2074: keep the adjacency indexes live instead of rebuilding them over the
|
|
3661
|
-
// whole graph afterwards. Only the dropped edges' own buckets are touched.
|
|
3662
|
-
// Unconditional: on an unindexed graph every bucket lookup simply misses.
|
|
3663
|
-
for (const edge of droppedEdges)
|
|
3664
|
-
unindexEdge(graph, edge);
|
|
3684
|
+
removedEdges.add(edge);
|
|
3685
|
+
}
|
|
3665
3686
|
for (const id of removedIds) {
|
|
3666
3687
|
const node = graph.nodes.get(id);
|
|
3667
3688
|
graph.nodes.delete(id);
|
|
@@ -3769,18 +3790,30 @@ async function addFileToGraph(graph, cwd, file, facts, ignoredIds, contentOverri
|
|
|
3769
3790
|
/**
|
|
3770
3791
|
* #2074 acceptance instrumentation. `restoreComparisons` counts edge-metadata
|
|
3771
3792
|
* stringifications inside `restoreValidIncomingEdges`; `importTargetEdgeScans`
|
|
3772
|
-
* counts edges visited by `importTargetsForFile
|
|
3773
|
-
*
|
|
3774
|
-
*
|
|
3775
|
-
*
|
|
3793
|
+
* counts edges visited by `importTargetsForFile`; `removeOwnedEdgeVisits`
|
|
3794
|
+
* counts edges visited while collecting a changed file's owned edges in
|
|
3795
|
+
* `removeFileOwnedGraphData`. Before this change all three grew with the whole
|
|
3796
|
+
* graph on every one-file rebuild, and `removeOwnedEdgeVisits` grew with
|
|
3797
|
+
* changedFiles x graph on a multi-file batch (one full `graph.edges` scan per
|
|
3798
|
+
* file). `removeOwnedEdgePositions` counts adjacency positions examined while
|
|
3799
|
+
* removing edges; batching keeps a high-fan-in bucket linear instead of
|
|
3800
|
+
* rescanning its prefix for every edge. They are the count-based signal the
|
|
3801
|
+
* issue asks for, because wall time on this hardware is IO-noisy (#1920).
|
|
3776
3802
|
*/
|
|
3777
|
-
const _rebuildCounters = {
|
|
3803
|
+
const _rebuildCounters = {
|
|
3804
|
+
restoreComparisons: 0,
|
|
3805
|
+
importTargetEdgeScans: 0,
|
|
3806
|
+
removeOwnedEdgeVisits: 0,
|
|
3807
|
+
removeOwnedEdgePositions: 0,
|
|
3808
|
+
};
|
|
3778
3809
|
export function _getReviewGraphRebuildCountersForTests() {
|
|
3779
3810
|
return { ..._rebuildCounters };
|
|
3780
3811
|
}
|
|
3781
3812
|
export function _resetReviewGraphRebuildCountersForTests() {
|
|
3782
3813
|
_rebuildCounters.restoreComparisons = 0;
|
|
3783
3814
|
_rebuildCounters.importTargetEdgeScans = 0;
|
|
3815
|
+
_rebuildCounters.removeOwnedEdgeVisits = 0;
|
|
3816
|
+
_rebuildCounters.removeOwnedEdgePositions = 0;
|
|
3784
3817
|
}
|
|
3785
3818
|
/**
|
|
3786
3819
|
* Identity of an edge for dedupe purposes, WITHIN one target bucket: the array
|
|
@@ -3893,10 +3926,18 @@ async function updateGraphFiles(graph, cwd, files, facts, ignoredIds) {
|
|
|
3893
3926
|
priorTargets: importTargetsForFile(graph, file),
|
|
3894
3927
|
}));
|
|
3895
3928
|
const preservedIncoming = [];
|
|
3929
|
+
// #2074: one shared drop set for the whole batch, compacted into graph.edges
|
|
3930
|
+
// exactly once below — not once per file, which made a multi-file rebuild
|
|
3931
|
+
// scan the edge array changedFiles times over.
|
|
3932
|
+
const removedEdges = new Set();
|
|
3896
3933
|
for (const file of files) {
|
|
3897
|
-
preservedIncoming.push(...removeFileOwnedGraphData(graph, file));
|
|
3934
|
+
preservedIncoming.push(...removeFileOwnedGraphData(graph, file, removedEdges));
|
|
3898
3935
|
await addFileToGraph(graph, cwd, file, facts, ignoredIds);
|
|
3899
3936
|
}
|
|
3937
|
+
if (removedEdges.size > 0) {
|
|
3938
|
+
unindexEdges(graph, removedEdges);
|
|
3939
|
+
graph.edges = graph.edges.filter((edge) => !removedEdges.has(edge));
|
|
3940
|
+
}
|
|
3900
3941
|
restoreValidIncomingEdges(graph, preservedIncoming);
|
|
3901
3942
|
resolveDeferredSymbolEdges(graph, false);
|
|
3902
3943
|
graph.changedSymbolsByFile.clear();
|
|
@@ -90,7 +90,7 @@ function resolveDart(cwd, filePath, source) {
|
|
|
90
90
|
// JS/TS extension from the specifier before re-appending candidate extensions
|
|
91
91
|
// lets that universal pattern resolve to the real source file. Exported so
|
|
92
92
|
// builder.ts's warm `localImportToFile` shares the exact same regex (#694).
|
|
93
|
-
|
|
93
|
+
const JS_TS_EXT_RE = /\.(mjs|cjs|mts|cts|jsx?|tsx?)$/i;
|
|
94
94
|
/**
|
|
95
95
|
* Ordered candidate list for resolving a relative JS/TS import specifier
|
|
96
96
|
* (already resolved to an absolute base path) to an on-disk file, with
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { recordDegradationOnce } from "../degradation-ledger.js";
|
|
2
|
+
import { isAbsoluteFilePath, normalizeMapKey } from "../path-utils.js";
|
|
1
3
|
import { computeImpactCascade as computeImpactCascadeImpl, computeTransitiveImpact as computeTransitiveImpactImpl, } from "./query.js";
|
|
2
4
|
import { buildOrUpdateGraph as buildOrUpdateGraphImpl, } from "./builder.js";
|
|
3
5
|
import { formatImpactCascade as formatImpactCascadeImpl } from "./format.js";
|
|
@@ -19,7 +21,57 @@ export function computeTransitiveImpact(graph, seedFile, options) {
|
|
|
19
21
|
return computeTransitiveImpactImpl(graph, seedFile, options);
|
|
20
22
|
}
|
|
21
23
|
export function recordEntitySnapshotDiff(facts, filePath, nextSnapshot) {
|
|
22
|
-
|
|
24
|
+
// #2477 round 2 (reviewer F1/F2): folding `cwd` into this key was REVERTED.
|
|
25
|
+
// The writer (`clients/dispatch/runners/tree-sitter.ts`) passes `ctx.cwd`,
|
|
26
|
+
// which `createDispatchContext` (`clients/dispatch/dispatcher.ts:324-326`)
|
|
27
|
+
// sets to the file's NEAREST LANGUAGE-ROOT (`resolveLanguageRootForFile`),
|
|
28
|
+
// while the reader (`upsertChangedSymbols`, `clients/review-graph/builder.ts`,
|
|
29
|
+
// reached via `computeCascadeForFile` → `buildOrUpdateGraph`) keys off the
|
|
30
|
+
// WORKSPACE cwd. In a monorepo/cargo-workspace/go-module layout those two
|
|
31
|
+
// cwd values diverge, so a folded `(cwd, path)` key the builder reader can
|
|
32
|
+
// never hit zeroed `graphChangedSymbolCount` on every build — reproduced:
|
|
33
|
+
// master returns `["alpha","beta"]`, the folded-key version returns `[]`
|
|
34
|
+
// — and made the cascade over-fan to every symbol (`query.ts:230-238`
|
|
35
|
+
// treats an empty `changedSymbols` as "no narrowing").
|
|
36
|
+
//
|
|
37
|
+
// The #2477 cross-project collision this was meant to close cannot reach
|
|
38
|
+
// this function in production: the sole writer always passes `ctx.filePath`,
|
|
39
|
+
// which `createDispatchContext` sets via `resolveRunnerPath` to an
|
|
40
|
+
// ALWAYS-ABSOLUTE path (the #2016 invariant, `dispatcher.ts:320,327,346`).
|
|
41
|
+
// A relative `filePath` here can only happen through a caller regression.
|
|
42
|
+
// Enforce that instead of re-keying: reject a non-absolute `filePath` with
|
|
43
|
+
// a visible, bounded ledger record (never silently, per AGENTS.md) and
|
|
44
|
+
// skip the diff rather than compute one under a key the real reader could
|
|
45
|
+
// never reach anyway. `recordDegradationOnce` (not a thrown error) is used
|
|
46
|
+
// because the sole call site's surrounding try/catch
|
|
47
|
+
// (`tree-sitter.ts` — "entity snapshot / blast-radius enrichment is
|
|
48
|
+
// best-effort") is a BARE, UNLOGGED catch: a thrown error there vanishes
|
|
49
|
+
// with no trace, which is strictly worse than a ledger record.
|
|
50
|
+
if (!isAbsoluteFilePath(filePath)) {
|
|
51
|
+
recordDegradationOnce({
|
|
52
|
+
kind: "review-graph-non-absolute-entity-path",
|
|
53
|
+
subject: filePath,
|
|
54
|
+
reason: "recordEntitySnapshotDiff requires an absolute filePath (refs #2477)",
|
|
55
|
+
});
|
|
56
|
+
return { added: [], removed: [], modified: [] };
|
|
57
|
+
}
|
|
58
|
+
// Normalize once at this boundary, then reuse the folded path for both
|
|
59
|
+
// per-file facts. An unnormalized write is a key the builder reader can never
|
|
60
|
+
// hit, and an unnormalized snapshot forks a second empty diff (#2355).
|
|
61
|
+
const normalizedFilePath = normalizeMapKey(filePath);
|
|
62
|
+
const snapshotKey = `${ENTITY_SNAPSHOT_PREFIX}${normalizedFilePath}`;
|
|
63
|
+
const changedSymbolsKey = `${CHANGED_SYMBOLS_PREFIX}${normalizedFilePath}`;
|
|
64
|
+
const stored = facts.getBoundedSessionFact(snapshotKey);
|
|
65
|
+
// An evicted snapshot is unknown, not empty. Diffing against an empty Map
|
|
66
|
+
// puts every entity in `added`, which reads downstream as "the whole file
|
|
67
|
+
// changed" and schedules a blast-radius run for a file that did not change.
|
|
68
|
+
// Re-seed the snapshot and report no diff instead (#2282 review F1).
|
|
69
|
+
if (stored === undefined && facts.wasBoundedSessionFactEvicted(snapshotKey)) {
|
|
70
|
+
facts.setBoundedSessionFact(snapshotKey, new Map(nextSnapshot));
|
|
71
|
+
facts.setBoundedSessionFact(changedSymbolsKey, []);
|
|
72
|
+
return { added: [], removed: [], modified: [] };
|
|
73
|
+
}
|
|
74
|
+
const prev = stored ?? new Map();
|
|
23
75
|
const added = [];
|
|
24
76
|
const removed = [];
|
|
25
77
|
const modified = [];
|
|
@@ -38,7 +90,7 @@ export function recordEntitySnapshotDiff(facts, filePath, nextSnapshot) {
|
|
|
38
90
|
.map((key) => key.split(":")[1])
|
|
39
91
|
.filter(Boolean)),
|
|
40
92
|
];
|
|
41
|
-
facts.
|
|
42
|
-
facts.
|
|
93
|
+
facts.setBoundedSessionFact(snapshotKey, new Map(nextSnapshot));
|
|
94
|
+
facts.setBoundedSessionFact(changedSymbolsKey, changedSymbols);
|
|
43
95
|
return { added, removed, modified };
|
|
44
96
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
+
import { BoundedFifoMap } from "../bounded-cache.js";
|
|
2
3
|
import { normalizeMapKey } from "../path-utils.js";
|
|
3
4
|
/**
|
|
4
5
|
* THE producer/consumer hash contract, in one place (#955 review): scanner
|
|
@@ -17,7 +18,10 @@ export function reviewGraphIrContentHash(content) {
|
|
|
17
18
|
// registry's lifetime is the scan-to-build window, not the process lifetime.
|
|
18
19
|
const MAX_ROOTS = 8;
|
|
19
20
|
const MAX_FILES_PER_ROOT = 20_000;
|
|
20
|
-
|
|
21
|
+
// Both levels are FIFO, matching the hand-rolled blocks these replaced: no
|
|
22
|
+
// read on either map refreshed recency before #2442, and the consume-once
|
|
23
|
+
// contract above means a read is normally a DELETE anyway.
|
|
24
|
+
const roots = new BoundedFifoMap(MAX_ROOTS);
|
|
21
25
|
let accepted = 0;
|
|
22
26
|
let rejected = 0;
|
|
23
27
|
function rootKey(cwd) {
|
|
@@ -33,23 +37,11 @@ export function publishReviewGraphFileIr(cwd, entry) {
|
|
|
33
37
|
const key = rootKey(cwd);
|
|
34
38
|
let files = roots.get(key);
|
|
35
39
|
if (!files) {
|
|
36
|
-
files = new
|
|
40
|
+
files = new BoundedFifoMap(MAX_FILES_PER_ROOT);
|
|
37
41
|
roots.set(key, files);
|
|
38
|
-
while (roots.size > MAX_ROOTS) {
|
|
39
|
-
const oldest = roots.keys().next().value;
|
|
40
|
-
if (oldest === undefined)
|
|
41
|
-
break;
|
|
42
|
-
roots.delete(oldest);
|
|
43
|
-
}
|
|
44
42
|
}
|
|
45
43
|
const fileKey = normalizeMapKey(entry.filePath);
|
|
46
|
-
files.delete(fileKey);
|
|
47
|
-
while (files.size >= MAX_FILES_PER_ROOT) {
|
|
48
|
-
const oldest = files.keys().next().value;
|
|
49
|
-
if (oldest === undefined)
|
|
50
|
-
break;
|
|
51
|
-
files.delete(oldest);
|
|
52
|
-
}
|
|
44
|
+
files.delete(fileKey); // republish is a refresh: it becomes the newest
|
|
53
45
|
files.set(fileKey, { ...entry, filePath: fileKey });
|
|
54
46
|
}
|
|
55
47
|
/**
|