@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
|
@@ -21,11 +21,11 @@
|
|
|
21
21
|
*/
|
|
22
22
|
import * as path from "node:path";
|
|
23
23
|
import { isTestMode } from "./env-utils.js";
|
|
24
|
-
import {
|
|
24
|
+
import { getGlobalPiLensLogDir } from "./probe-home-state.js";
|
|
25
25
|
import { getMaxLogSizeMB } from "./log-cleanup.js";
|
|
26
26
|
import { createNdjsonLogger } from "./ndjson-logger.js";
|
|
27
27
|
import { normalizeFilePath } from "./path-utils.js";
|
|
28
|
-
const WORD_INDEX_LOG_FILE = path.join(
|
|
28
|
+
const WORD_INDEX_LOG_FILE = path.join(getGlobalPiLensLogDir(), "word-index.log");
|
|
29
29
|
const writer = createNdjsonLogger({
|
|
30
30
|
filePath: WORD_INDEX_LOG_FILE,
|
|
31
31
|
maxBytes: getMaxLogSizeMB() * 1024 * 1024,
|
|
@@ -47,10 +47,3 @@ export function logWordIndex(entry) {
|
|
|
47
47
|
cwd: normalizeFilePath(entry.cwd),
|
|
48
48
|
});
|
|
49
49
|
}
|
|
50
|
-
export function getWordIndexLogPath() {
|
|
51
|
-
return WORD_INDEX_LOG_FILE;
|
|
52
|
-
}
|
|
53
|
-
/** Resolve once all enqueued word-index writes are on disk (tests/shutdown). */
|
|
54
|
-
export function flushWordIndexLog() {
|
|
55
|
-
return writer.flush();
|
|
56
|
-
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createDeadline, yieldIfOverBudget } from "./cooperative-budget.js";
|
|
1
|
+
import { createDeadline, yieldIfOverBudget, } from "./cooperative-budget.js";
|
|
2
2
|
/**
|
|
3
3
|
* Packed backing store for the word index's inverted postings (#2069).
|
|
4
4
|
*
|
|
@@ -30,8 +30,8 @@ import { createDeadline, yieldIfOverBudget } from "./cooperative-budget.js";
|
|
|
30
30
|
/**
|
|
31
31
|
* Bytes of backing store per posting entry: one `fileId` lane and one `line`
|
|
32
32
|
* lane, both `Int32`. This is the constant #2069's acceptance criterion is
|
|
33
|
-
* written against, and
|
|
34
|
-
*
|
|
33
|
+
* written against, and the arithmetic the memory-sample record and the
|
|
34
|
+
* regression test both read.
|
|
35
35
|
*/
|
|
36
36
|
export const WORD_POSTING_ENTRY_BYTES = 8;
|
|
37
37
|
/**
|
|
@@ -189,10 +189,6 @@ export class WordPostingList {
|
|
|
189
189
|
return list;
|
|
190
190
|
}
|
|
191
191
|
}
|
|
192
|
-
/** Estimated bytes one posting list holds, backing store plus fixed headers. */
|
|
193
|
-
export function estimatePostingListBytes(list) {
|
|
194
|
-
return list.byteLength + WORD_POSTING_LIST_OVERHEAD_BYTES;
|
|
195
|
-
}
|
|
196
192
|
/**
|
|
197
193
|
* Re-home every posting list into ONE shared `ArrayBuffer`, exactly sized.
|
|
198
194
|
*
|
|
@@ -248,8 +244,20 @@ export function compactPostingsIntoArena(postings) {
|
|
|
248
244
|
*
|
|
249
245
|
* Each `adoptArena` copies and re-homes one list within a single synchronous
|
|
250
246
|
* step, so readers never observe a partially written list.
|
|
247
|
+
*
|
|
248
|
+
* `options.deadline` and `options.beforeYield` are a test seam only (#2293):
|
|
249
|
+
* production always takes the default 8 ms wall-clock deadline. The #2117
|
|
250
|
+
* regression test used to prove the "grew during a yield" invariant by racing
|
|
251
|
+
* a real timer against a 40,000-list copy, which made the yield itself a
|
|
252
|
+
* scheduling accident — the copy sometimes finished inside the 8 ms budget
|
|
253
|
+
* and never yielded at all, so the test's own precondition went unmet under
|
|
254
|
+
* load. Injecting a deadline lets a test force a yield deterministically
|
|
255
|
+
* instead of hoping wall-clock crosses the budget; `beforeYield` runs
|
|
256
|
+
* in-line, immediately before the real cooperative pause, so a test can
|
|
257
|
+
* mutate a not-yet-adopted list at that exact point with no reliance on
|
|
258
|
+
* event-loop scheduling order.
|
|
251
259
|
*/
|
|
252
|
-
export async function compactPostingsIntoArenaCooperatively(postings) {
|
|
260
|
+
export async function compactPostingsIntoArenaCooperatively(postings, options) {
|
|
253
261
|
// Snapshot (token, list, width) in one synchronous pass; the arena is sized
|
|
254
262
|
// from these widths and only unchanged lists are adopted, so the sum of the
|
|
255
263
|
// widths actually written can never exceed the arena length.
|
|
@@ -264,15 +272,17 @@ export async function compactPostingsIntoArenaCooperatively(postings) {
|
|
|
264
272
|
return;
|
|
265
273
|
const arena = new Int32Array(lanes);
|
|
266
274
|
let offset = 0;
|
|
267
|
-
const deadline = createDeadline(8);
|
|
275
|
+
const deadline = options?.deadline ?? createDeadline(8);
|
|
268
276
|
for (const plan of planned) {
|
|
269
277
|
if (postings.get(plan.token) === plan.list &&
|
|
270
278
|
plan.list.length * 2 === plan.width &&
|
|
271
279
|
offset + plan.width <= arena.length) {
|
|
272
280
|
offset = plan.list.adoptArena(arena, offset);
|
|
273
281
|
}
|
|
274
|
-
if (deadline.expired())
|
|
282
|
+
if (deadline.expired()) {
|
|
283
|
+
await options?.beforeYield?.();
|
|
275
284
|
await yieldIfOverBudget(deadline);
|
|
285
|
+
}
|
|
276
286
|
}
|
|
277
287
|
}
|
|
278
288
|
/**
|
|
@@ -375,7 +385,8 @@ export class WordForwardEntry {
|
|
|
375
385
|
}
|
|
376
386
|
/** Pack a tokenizer tally. Insertion order is preserved. */
|
|
377
387
|
static fromTally(tally) {
|
|
378
|
-
const tokenNames =
|
|
388
|
+
const tokenNames = [];
|
|
389
|
+
tokenNames.length = tally.size;
|
|
379
390
|
const lineCounts = new Int32Array(tally.size);
|
|
380
391
|
let i = 0;
|
|
381
392
|
for (const [token, count] of tally) {
|
|
@@ -390,7 +401,7 @@ export class WordForwardEntry {
|
|
|
390
401
|
* Bytes per forward entry: one pointer-compressed slot for the shared token
|
|
391
402
|
* string and one `Int32` count lane.
|
|
392
403
|
*/
|
|
393
|
-
|
|
404
|
+
const WORD_FORWARD_ENTRY_BYTES = 8;
|
|
394
405
|
/**
|
|
395
406
|
* The word index's dense file-id space: canonical path key → integer id →
|
|
396
407
|
* display path.
|
|
@@ -725,17 +725,6 @@ async function updateWordIndexDocumentAsyncUnsafe(index, doc, shouldContinue) {
|
|
|
725
725
|
commitWordIndexDocumentReplacement(index, doc, perTokenHits, docLength, startedAt);
|
|
726
726
|
return true;
|
|
727
727
|
}
|
|
728
|
-
/** Bounds shared by every word-index build path — keep the walk off the
|
|
729
|
-
* critical path on large repos: cap the file count, and skip files too large
|
|
730
|
-
* to be hand-written source (generated/bundled output the source filter
|
|
731
|
-
* didn't already exclude).
|
|
732
|
-
*
|
|
733
|
-
* Deprecated (#776): `collectWordIndexDocs` below no longer reads this
|
|
734
|
-
* constant directly — it derives its cap from `getWordIndexMaxFilesDerived`
|
|
735
|
-
* (project-scale.ts's `maxProjectFiles` knob), which reproduces this same
|
|
736
|
-
* 6,000 default at the default base. Kept exported for tests/callers that
|
|
737
|
-
* still reference the literal. */
|
|
738
|
-
export const WORD_INDEX_MAX_FILES = 6000;
|
|
739
728
|
export const WORD_INDEX_MAX_BYTES = 512 * 1024;
|
|
740
729
|
/**
|
|
741
730
|
* Collect the bounded `{path, content}` doc set `buildWordIndex` consumes —
|
|
@@ -748,9 +737,9 @@ export const WORD_INDEX_MAX_BYTES = 512 * 1024;
|
|
|
748
737
|
export async function collectWordIndexDocs(root, shouldContinue = () => true, preflightFiles) {
|
|
749
738
|
const { collectSourceFilesAsync } = await import("./source-filter.js");
|
|
750
739
|
// #747 hardening: pass the cap INTO the walk — without it,
|
|
751
|
-
// `collectSourceFilesAsync` defaults to an unbounded traversal and
|
|
752
|
-
//
|
|
753
|
-
//
|
|
740
|
+
// `collectSourceFilesAsync` defaults to an unbounded traversal and any
|
|
741
|
+
// slice below would only trim the result AFTER the whole tree (all of
|
|
742
|
+
// $HOME, on a misrooted cwd) has already been enumerated.
|
|
754
743
|
// #760: the walk is additionally bounded by source-filter's default
|
|
755
744
|
// visited-entry budget (DEFAULT_MAX_SCAN_ENTRIES), so a mixed tree with few
|
|
756
745
|
// source files among a huge pile of non-source files can't force a
|
|
@@ -811,7 +800,7 @@ export async function collectWordIndexDocs(root, shouldContinue = () => true, pr
|
|
|
811
800
|
// Node's fs.promises.stat runs on libuv's threadpool (default 4 slots), so
|
|
812
801
|
// real parallelism tops out there; the surplus workers are queue depth that
|
|
813
802
|
// keeps the pool saturated without starving other threadpool consumers.
|
|
814
|
-
|
|
803
|
+
const WORD_INDEX_STAT_CONCURRENCY = 8;
|
|
815
804
|
const WORD_INDEX_INCREMENTAL_CHURN_THRESHOLD = 0.3;
|
|
816
805
|
// A ratio alone misclassifies one stale file in a three-file project as dense.
|
|
817
806
|
// Below this absolute floor, per-document replacement is bounded and cheaper
|
|
@@ -888,7 +877,8 @@ export async function refreshWordIndexIncrementally(index, root, shouldContinue
|
|
|
888
877
|
const statConcurrency = Number.isFinite(requestedConcurrency) && requestedConcurrency > 0
|
|
889
878
|
? Math.max(1, Math.floor(requestedConcurrency))
|
|
890
879
|
: WORD_INDEX_STAT_CONCURRENCY;
|
|
891
|
-
const statResults =
|
|
880
|
+
const statResults = [];
|
|
881
|
+
statResults.length = walked.length;
|
|
892
882
|
let cursor = 0;
|
|
893
883
|
let superseded = false;
|
|
894
884
|
const worker = async () => {
|
|
@@ -1091,7 +1081,11 @@ export async function refreshWordIndexIncrementally(index, root, shouldContinue
|
|
|
1091
1081
|
timings,
|
|
1092
1082
|
};
|
|
1093
1083
|
}
|
|
1094
|
-
|
|
1084
|
+
const WORD_INDEX_QUERY_FILTER_KEYS = [
|
|
1085
|
+
"lang",
|
|
1086
|
+
"file",
|
|
1087
|
+
"ext",
|
|
1088
|
+
];
|
|
1095
1089
|
/** Thrown by {@link parseWordIndexQuery}/{@link buildWordIndexQueryFilter} for
|
|
1096
1090
|
* an unrecognized `key:` prefix or an unrecognized `lang:` value — a query
|
|
1097
1091
|
* typo fails loudly with the supported list instead of silently degrading
|
|
@@ -1391,6 +1385,22 @@ export function centralityFromReverseDeps(index, reverseDeps, normalizeKey = (fi
|
|
|
1391
1385
|
}
|
|
1392
1386
|
/** Persisted word-index serialization format version. Bump on breaking format changes. */
|
|
1393
1387
|
export const WORD_INDEX_FORMAT_VERSION = 2;
|
|
1388
|
+
const WORD_INDEX_INT32_MAX = 2_147_483_647;
|
|
1389
|
+
// A file id and line fit in one exact Number key through this boundary.
|
|
1390
|
+
const WORD_INDEX_PACKED_FILE_ID_MAX = 4_194_303;
|
|
1391
|
+
function isCanonicalWordIndexNumber(value) {
|
|
1392
|
+
return (typeof value === "number" &&
|
|
1393
|
+
Number.isFinite(value) &&
|
|
1394
|
+
Number.isSafeInteger(value) &&
|
|
1395
|
+
!Object.is(value, -0));
|
|
1396
|
+
}
|
|
1397
|
+
function isCanonicalWordIndexToken(token) {
|
|
1398
|
+
return (typeof token === "string" &&
|
|
1399
|
+
token.length >= 2 &&
|
|
1400
|
+
token === token.toLowerCase() &&
|
|
1401
|
+
/^[a-z0-9_$]+$/.test(token) &&
|
|
1402
|
+
!STOPWORDS.has(token));
|
|
1403
|
+
}
|
|
1394
1404
|
const serializedWordIndexCaches = new WeakMap();
|
|
1395
1405
|
let _lastSerializeWork;
|
|
1396
1406
|
/** Test-only: work stats for the most recent {@link serializeWordIndex} call. */
|
|
@@ -1585,10 +1595,25 @@ export function deserializeWordIndex(data) {
|
|
|
1585
1595
|
!Array.isArray(data.files) ||
|
|
1586
1596
|
!Array.isArray(data.postings) ||
|
|
1587
1597
|
!Array.isArray(data.docLengths) ||
|
|
1588
|
-
!Array.isArray(data.fileMtimes)
|
|
1589
|
-
data.fileMtimes.length !== data.files.length) {
|
|
1598
|
+
!Array.isArray(data.fileMtimes)) {
|
|
1590
1599
|
return null;
|
|
1591
1600
|
}
|
|
1601
|
+
let canonical = data.docLengths.length === data.files.length &&
|
|
1602
|
+
data.fileMtimes.length === data.files.length;
|
|
1603
|
+
let needsDeepSanitize = !Array.isArray(data.forward);
|
|
1604
|
+
if (needsDeepSanitize)
|
|
1605
|
+
canonical = false;
|
|
1606
|
+
const fileKeys = new Set();
|
|
1607
|
+
for (const file of data.files) {
|
|
1608
|
+
if (typeof file !== "string")
|
|
1609
|
+
return null;
|
|
1610
|
+
const key = wordIndexKey(file);
|
|
1611
|
+
if (fileKeys.has(key)) {
|
|
1612
|
+
canonical = false;
|
|
1613
|
+
needsDeepSanitize = true;
|
|
1614
|
+
}
|
|
1615
|
+
fileKeys.add(key);
|
|
1616
|
+
}
|
|
1592
1617
|
const docLengths = new PathKeyedMap(wordIndexKey);
|
|
1593
1618
|
// Slot i of the wire `files` array becomes file id `fileIdBySlot[i]`. Two
|
|
1594
1619
|
// slots whose spellings fold to one key share one id, exactly as a build
|
|
@@ -1596,33 +1621,94 @@ export function deserializeWordIndex(data) {
|
|
|
1596
1621
|
// posting identities for one document.
|
|
1597
1622
|
const fileTable = new WordIndexFileTable();
|
|
1598
1623
|
const fileIdBySlot = data.files.map((file) => fileTable.intern(wordIndexKey(file), file));
|
|
1624
|
+
const slotByFileId = new Map();
|
|
1625
|
+
fileIdBySlot.forEach((fileId, slot) => {
|
|
1626
|
+
if (!slotByFileId.has(fileId))
|
|
1627
|
+
slotByFileId.set(fileId, slot);
|
|
1628
|
+
});
|
|
1599
1629
|
const fileMtimes = new PathKeyedMap(wordIndexKey);
|
|
1600
1630
|
const fileSizes = new PathKeyedMap(wordIndexKey);
|
|
1601
|
-
data.files.forEach((file, i) =>
|
|
1602
|
-
|
|
1631
|
+
data.files.forEach((file, i) => {
|
|
1632
|
+
const value = data.docLengths[i];
|
|
1633
|
+
if (!isCanonicalWordIndexNumber(value) || value < 0)
|
|
1634
|
+
canonical = false;
|
|
1635
|
+
docLengths.set(file, isCanonicalWordIndexNumber(value) && value >= 0 ? value : 0);
|
|
1636
|
+
});
|
|
1637
|
+
data.files.forEach((file, i) => {
|
|
1638
|
+
const value = data.fileMtimes[i];
|
|
1639
|
+
if (typeof value !== "number" || !Number.isFinite(value))
|
|
1640
|
+
canonical = false;
|
|
1641
|
+
fileMtimes.set(file, typeof value === "number" && Number.isFinite(value) ? value : 0);
|
|
1642
|
+
});
|
|
1603
1643
|
// #1105: `fileSizes` is optional on the wire (pre-#1105 snapshots omit it).
|
|
1604
1644
|
// Only populate when the array is present AND parallel to `files`; otherwise
|
|
1605
1645
|
// leave it empty so the refresh gate re-reads every file once to repopulate,
|
|
1606
1646
|
// rather than trusting a bogus/misaligned size. Never treated as "current".
|
|
1607
1647
|
if (Array.isArray(data.fileSizes) &&
|
|
1608
1648
|
data.fileSizes.length === data.files.length) {
|
|
1609
|
-
data.files.forEach((file, i) =>
|
|
1649
|
+
data.files.forEach((file, i) => {
|
|
1650
|
+
const value = data.fileSizes?.[i];
|
|
1651
|
+
if (!isCanonicalWordIndexNumber(value) || value < 0)
|
|
1652
|
+
canonical = false;
|
|
1653
|
+
fileSizes.set(file, isCanonicalWordIndexNumber(value) && value >= 0 ? value : 0);
|
|
1654
|
+
});
|
|
1655
|
+
}
|
|
1656
|
+
else {
|
|
1657
|
+
canonical = false;
|
|
1610
1658
|
}
|
|
1611
1659
|
const postings = new Map();
|
|
1612
|
-
|
|
1613
|
-
|
|
1660
|
+
const postingTokens = new Set();
|
|
1661
|
+
const postingFileCounts = new Map();
|
|
1662
|
+
for (const posting of data.postings) {
|
|
1663
|
+
if (!Array.isArray(posting) || posting.length !== 2) {
|
|
1664
|
+
canonical = false;
|
|
1665
|
+
needsDeepSanitize = true;
|
|
1666
|
+
continue;
|
|
1667
|
+
}
|
|
1668
|
+
const [token, flat] = posting;
|
|
1669
|
+
if (!isCanonicalWordIndexToken(token) ||
|
|
1670
|
+
postingTokens.has(token) ||
|
|
1671
|
+
!Array.isArray(flat) ||
|
|
1672
|
+
flat.length === 0 ||
|
|
1673
|
+
flat.length % 2 !== 0) {
|
|
1674
|
+
canonical = false;
|
|
1675
|
+
needsDeepSanitize = true;
|
|
1614
1676
|
continue;
|
|
1677
|
+
}
|
|
1678
|
+
postingTokens.add(token);
|
|
1615
1679
|
const lanes = [];
|
|
1616
|
-
|
|
1617
|
-
|
|
1680
|
+
const seenPairs = new Set();
|
|
1681
|
+
const observedCounts = new Map();
|
|
1682
|
+
for (let i = 0; i < flat.length; i += 2) {
|
|
1683
|
+
const slot = flat[i];
|
|
1618
1684
|
const line = flat[i + 1];
|
|
1619
|
-
if (
|
|
1620
|
-
|
|
1685
|
+
if (!isCanonicalWordIndexNumber(slot) ||
|
|
1686
|
+
slot < 0 ||
|
|
1687
|
+
slot >= fileIdBySlot.length ||
|
|
1688
|
+
!isCanonicalWordIndexNumber(line) ||
|
|
1689
|
+
line < 1 ||
|
|
1690
|
+
line > WORD_INDEX_INT32_MAX) {
|
|
1691
|
+
canonical = false;
|
|
1692
|
+
needsDeepSanitize = true;
|
|
1693
|
+
continue;
|
|
1621
1694
|
}
|
|
1695
|
+
const fileId = fileIdBySlot[slot];
|
|
1696
|
+
const pairKey = fileId <= WORD_INDEX_PACKED_FILE_ID_MAX
|
|
1697
|
+
? fileId * (WORD_INDEX_INT32_MAX + 1) + line
|
|
1698
|
+
: `${fileId}:${line}`;
|
|
1699
|
+
if (seenPairs.has(pairKey)) {
|
|
1700
|
+
canonical = false;
|
|
1701
|
+
needsDeepSanitize = true;
|
|
1702
|
+
}
|
|
1703
|
+
seenPairs.add(pairKey);
|
|
1704
|
+
lanes.push(fileId, line);
|
|
1705
|
+
observedCounts.set(fileId, (observedCounts.get(fileId) ?? 0) + 1);
|
|
1622
1706
|
}
|
|
1623
|
-
if (lanes.length
|
|
1624
|
-
|
|
1625
|
-
|
|
1707
|
+
if (lanes.length === 0)
|
|
1708
|
+
continue;
|
|
1709
|
+
const list = WordPostingList.fromLanes(token, lanes);
|
|
1710
|
+
postings.set(token, list);
|
|
1711
|
+
postingFileCounts.set(token, observedCounts);
|
|
1626
1712
|
}
|
|
1627
1713
|
// Every list above was sized exactly from the wire payload, so there is no
|
|
1628
1714
|
// growth slack to release — but the per-list `ArrayBuffer` headers are the
|
|
@@ -1631,34 +1717,128 @@ export function deserializeWordIndex(data) {
|
|
|
1631
1717
|
compactPostingsIntoArena(postings);
|
|
1632
1718
|
let forward;
|
|
1633
1719
|
if (Array.isArray(data.forward)) {
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1720
|
+
const candidate = data.files.map(() => new Map());
|
|
1721
|
+
const forwardTotals = new Map();
|
|
1722
|
+
if (data.forward.length !== data.files.length)
|
|
1723
|
+
canonical = false;
|
|
1724
|
+
if (data.forward.length !== data.files.length)
|
|
1725
|
+
needsDeepSanitize = true;
|
|
1726
|
+
for (const [entryIndex, entry] of data.forward.entries()) {
|
|
1727
|
+
if (!Array.isArray(entry) || entry.length !== 2) {
|
|
1728
|
+
canonical = false;
|
|
1729
|
+
needsDeepSanitize = true;
|
|
1637
1730
|
continue;
|
|
1731
|
+
}
|
|
1638
1732
|
const [fileIdx, tokenCounts] = entry;
|
|
1639
|
-
|
|
1640
|
-
|
|
1733
|
+
if (!isCanonicalWordIndexNumber(fileIdx) ||
|
|
1734
|
+
fileIdx !== entryIndex ||
|
|
1735
|
+
fileIdx < 0 ||
|
|
1736
|
+
fileIdx >= data.files.length ||
|
|
1737
|
+
!Array.isArray(tokenCounts)) {
|
|
1738
|
+
canonical = false;
|
|
1739
|
+
needsDeepSanitize = true;
|
|
1641
1740
|
continue;
|
|
1642
|
-
|
|
1741
|
+
}
|
|
1643
1742
|
for (const pair of tokenCounts) {
|
|
1644
|
-
if (!Array.isArray(pair) ||
|
|
1743
|
+
if (!Array.isArray(pair) ||
|
|
1744
|
+
pair.length !== 2 ||
|
|
1745
|
+
!isCanonicalWordIndexToken(pair[0]) ||
|
|
1746
|
+
!isCanonicalWordIndexNumber(pair[1]) ||
|
|
1747
|
+
pair[1] < 1 ||
|
|
1748
|
+
pair[1] > WORD_INDEX_INT32_MAX ||
|
|
1749
|
+
candidate[fileIdx].has(pair[0])) {
|
|
1750
|
+
canonical = false;
|
|
1751
|
+
needsDeepSanitize = true;
|
|
1645
1752
|
continue;
|
|
1646
|
-
const [token, count] = pair;
|
|
1647
|
-
if (typeof token === "string" && typeof count === "number") {
|
|
1648
|
-
// Point at the canonical instance the postings map holds, not
|
|
1649
|
-
// this document’s own JSON.parse allocation (#2069).
|
|
1650
|
-
perToken.set(postings.get(token)?.token ?? token, count);
|
|
1651
1753
|
}
|
|
1754
|
+
candidate[fileIdx].set(pair[0], pair[1]);
|
|
1755
|
+
forwardTotals.set(pair[0], (forwardTotals.get(pair[0]) ?? 0) + pair[1]);
|
|
1652
1756
|
}
|
|
1653
|
-
|
|
1757
|
+
}
|
|
1758
|
+
let forwardMatchesPostings = true;
|
|
1759
|
+
for (const [token, list] of postings) {
|
|
1760
|
+
if (forwardTotals.get(token) !== list.length) {
|
|
1761
|
+
forwardMatchesPostings = false;
|
|
1762
|
+
}
|
|
1763
|
+
const observed = postingFileCounts.get(token);
|
|
1764
|
+
if (!observed) {
|
|
1765
|
+
forwardMatchesPostings = false;
|
|
1766
|
+
continue;
|
|
1767
|
+
}
|
|
1768
|
+
for (const [fileId, count] of observed) {
|
|
1769
|
+
const slot = slotByFileId.get(fileId);
|
|
1770
|
+
if (slot === undefined || candidate[slot].get(token) !== count) {
|
|
1771
|
+
forwardMatchesPostings = false;
|
|
1772
|
+
}
|
|
1773
|
+
}
|
|
1774
|
+
}
|
|
1775
|
+
for (const token of forwardTotals.keys()) {
|
|
1776
|
+
if (!postingTokens.has(token))
|
|
1777
|
+
forwardMatchesPostings = false;
|
|
1778
|
+
}
|
|
1779
|
+
if (!forwardMatchesPostings)
|
|
1780
|
+
canonical = false;
|
|
1781
|
+
if (!forwardMatchesPostings)
|
|
1782
|
+
needsDeepSanitize = true;
|
|
1783
|
+
forward = new PathKeyedMap(wordIndexKey);
|
|
1784
|
+
for (let i = 0; i < data.files.length; i += 1) {
|
|
1785
|
+
forward.set(data.files[i], WordForwardEntry.fromTally(candidate[i]));
|
|
1654
1786
|
}
|
|
1655
1787
|
}
|
|
1656
|
-
|
|
1788
|
+
else if (Object.prototype.hasOwnProperty.call(data, "forward")) {
|
|
1789
|
+
canonical = false;
|
|
1790
|
+
needsDeepSanitize = true;
|
|
1791
|
+
}
|
|
1792
|
+
if (needsDeepSanitize) {
|
|
1793
|
+
const actualForwardCounts = data.files.map(() => new Map());
|
|
1794
|
+
for (const [token, list] of postings) {
|
|
1795
|
+
const seenPairs = new Set();
|
|
1796
|
+
const sanitized = new WordPostingList(token, list.length);
|
|
1797
|
+
for (let i = 0; i < list.length; i += 1) {
|
|
1798
|
+
const fileId = list.fileIdAt(i);
|
|
1799
|
+
const line = list.lineAt(i);
|
|
1800
|
+
const pairKey = `${fileId}:${line}`;
|
|
1801
|
+
if (seenPairs.has(pairKey))
|
|
1802
|
+
continue;
|
|
1803
|
+
seenPairs.add(pairKey);
|
|
1804
|
+
sanitized.push(fileId, line);
|
|
1805
|
+
const slot = slotByFileId.get(fileId);
|
|
1806
|
+
if (slot !== undefined) {
|
|
1807
|
+
const counts = actualForwardCounts[slot];
|
|
1808
|
+
counts.set(token, (counts.get(token) ?? 0) + 1);
|
|
1809
|
+
}
|
|
1810
|
+
}
|
|
1811
|
+
postings.set(token, sanitized);
|
|
1812
|
+
}
|
|
1813
|
+
compactPostingsIntoArena(postings);
|
|
1814
|
+
if (Array.isArray(data.forward)) {
|
|
1815
|
+
forward = new PathKeyedMap(wordIndexKey);
|
|
1816
|
+
for (let i = 0; i < data.files.length; i += 1) {
|
|
1817
|
+
const canonicalSlot = slotByFileId.get(fileIdBySlot[i]) ?? i;
|
|
1818
|
+
forward.set(data.files[i], WordForwardEntry.fromTally(actualForwardCounts[canonicalSlot]));
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1821
|
+
}
|
|
1822
|
+
const expectedTotalTokens = [...docLengths.values()].reduce((total, length) => total + length, 0);
|
|
1823
|
+
const totalTokens = isCanonicalWordIndexNumber(expectedTotalTokens)
|
|
1824
|
+
? expectedTotalTokens
|
|
1825
|
+
: 0;
|
|
1826
|
+
if (!isCanonicalWordIndexNumber(data.totalTokens) ||
|
|
1827
|
+
data.totalTokens !== totalTokens) {
|
|
1828
|
+
canonical = false;
|
|
1829
|
+
}
|
|
1830
|
+
if (typeof data.indexedFileCount !== "number" ||
|
|
1831
|
+
data.indexedFileCount !== docLengths.size) {
|
|
1832
|
+
canonical = false;
|
|
1833
|
+
}
|
|
1834
|
+
if (typeof data.truncated !== "boolean")
|
|
1835
|
+
canonical = false;
|
|
1836
|
+
const index = {
|
|
1657
1837
|
postings,
|
|
1658
1838
|
fileTable,
|
|
1659
1839
|
docLengths,
|
|
1660
|
-
totalTokens
|
|
1661
|
-
docCount:
|
|
1840
|
+
totalTokens,
|
|
1841
|
+
docCount: docLengths.size,
|
|
1662
1842
|
truncated: data.truncated === true,
|
|
1663
1843
|
forward,
|
|
1664
1844
|
fileMtimes,
|
|
@@ -1667,7 +1847,32 @@ export function deserializeWordIndex(data) {
|
|
|
1667
1847
|
// starts from the exact post-compaction store count (#2117).
|
|
1668
1848
|
postingStoreCount: countPostingBackingStores(postings),
|
|
1669
1849
|
recompactFlight: createSingleFlight(),
|
|
1850
|
+
// A deserialized index is a fresh object distinct from whichever index
|
|
1851
|
+
// produced `data`. Without this, every per-edit dirty mark on a
|
|
1852
|
+
// session-start reload (#2068) is a no-op against `undefined`, and
|
|
1853
|
+
// serializeWordIndexIncrementally's `!dirty` branch then returns the
|
|
1854
|
+
// stale cached wire view forever, silently dropping every later edit
|
|
1855
|
+
// from the persisted snapshot.
|
|
1856
|
+
dirtyFiles: new Set(),
|
|
1670
1857
|
};
|
|
1858
|
+
// Seed the wire cache from the snapshot just loaded so the FIRST persist
|
|
1859
|
+
// of a reloaded session (session-start's `snapshotSaveSyncMs`, #2068) also
|
|
1860
|
+
// takes the bounded incremental path instead of paying a full rebuild —
|
|
1861
|
+
// mirrors exactly what one priming `serializeWordIndex` call would cache.
|
|
1862
|
+
const tokensByFile = new Map();
|
|
1863
|
+
if (forward) {
|
|
1864
|
+
for (const file of data.files) {
|
|
1865
|
+
tokensByFile.set(wordIndexKey(file), new Set(forward.get(file)?.keys() ?? []));
|
|
1866
|
+
}
|
|
1867
|
+
}
|
|
1868
|
+
if (canonical) {
|
|
1869
|
+
serializedWordIndexCaches.set(index, {
|
|
1870
|
+
serialized: data,
|
|
1871
|
+
slotByFileId,
|
|
1872
|
+
tokensByFile,
|
|
1873
|
+
});
|
|
1874
|
+
}
|
|
1875
|
+
return index;
|
|
1671
1876
|
}
|
|
1672
1877
|
const buildStatuses = new Map();
|
|
1673
1878
|
export function getWordIndexBuildStatus(cwd) {
|
|
@@ -39,11 +39,18 @@
|
|
|
39
39
|
import * as fs from "node:fs";
|
|
40
40
|
import * as os from "node:os";
|
|
41
41
|
import * as path from "node:path";
|
|
42
|
+
import { PROJECT_CONFIG_BASENAMES } from "./config-locations.js";
|
|
42
43
|
import { logLatency } from "./latency-logger.js";
|
|
43
44
|
import { isAtOrAboveHomeDir, nameMatchesMarkerGlob, walkUpDirs, } from "./path-utils.js";
|
|
44
45
|
/** Depth cap on any upward marker walk — mirrors `findNearestMarkerRoot`'s bound. */
|
|
45
46
|
const MAX_WALK_DEPTH = 64;
|
|
46
|
-
|
|
47
|
+
/**
|
|
48
|
+
* The project config basenames, canonical first — the SHARED table, not a
|
|
49
|
+
* fourth copy of the pair (#2426 review round 2). `config-locations.ts` derives
|
|
50
|
+
* it from the one location table the resolver walks, so a change there cannot
|
|
51
|
+
* leave this marker index preferring a different file than the loaders do.
|
|
52
|
+
*/
|
|
53
|
+
const PI_LENS_CONFIG_BASENAMES = PROJECT_CONFIG_BASENAMES;
|
|
47
54
|
/** Per-directory marker cache — the shared seam every consumer reads through. */
|
|
48
55
|
const dirMarkerCache = new Map();
|
|
49
56
|
/** Downstream memo clears that must follow the topology index reset. */
|
|
@@ -15,12 +15,15 @@ import { classifyProbeFailure, createAvailabilityLatch, logAvailabilityDecision,
|
|
|
15
15
|
// presence of one is the repo's deliberate opt-in: it carries the author's
|
|
16
16
|
// chosen severities/ignores, so we let zizmor findings BLOCK in that workspace
|
|
17
17
|
// (advisory-only otherwise, like Opengrep's local-rules gate).
|
|
18
|
-
|
|
18
|
+
const LOCAL_ZIZMOR_CONFIG_NAMES = [
|
|
19
19
|
path.join(".github", "zizmor.yml"),
|
|
20
20
|
path.join(".github", "zizmor.yaml"),
|
|
21
21
|
"zizmor.yml",
|
|
22
22
|
"zizmor.yaml",
|
|
23
23
|
];
|
|
24
|
+
// Deliberately UNCEILINGED at $HOME (refs #2472 review round 3, F1): a
|
|
25
|
+
// user-level `~/zizmor.yml` (or `~/.github/zizmor.yml`) is a legitimate
|
|
26
|
+
// global config, not an escaped-workspace accident.
|
|
24
27
|
export function findLocalZizmorConfig(startDir) {
|
|
25
28
|
return findLocalToolConfig(startDir, LOCAL_ZIZMOR_CONFIG_NAMES);
|
|
26
29
|
}
|