@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
|
@@ -67,11 +67,12 @@ import * as path from "node:path";
|
|
|
67
67
|
import { writeFileAtomicAsync } from "./atomic-write.js";
|
|
68
68
|
import { sweepOwnStagingFiles, } from "./atomic-write-staging.js";
|
|
69
69
|
import { acquireQuarantinePidFileLock } from "./bounded-pid-file-lock.js";
|
|
70
|
-
import {
|
|
70
|
+
import { unrefChildAndPipes, } from "./child-unref.js";
|
|
71
71
|
import { incrementDegradationCount, recordDegradationOnce, } from "./degradation-ledger.js";
|
|
72
72
|
import { getGlobalPiLensDir } from "./file-utils.js";
|
|
73
73
|
import { isInstanceRegistryEnabled, pruneDeadInstances as pruneDeadRegistryInstances, readInstanceRegistry, } from "./instance-registry.js";
|
|
74
74
|
import { logLatency } from "./latency-logger.js";
|
|
75
|
+
import { queryProcessTable, windowsExe } from "./process-snapshot.js";
|
|
75
76
|
const isWindows = process.platform === "win32";
|
|
76
77
|
/**
|
|
77
78
|
* KILL eligibility: pid-confirmed-dead ONLY. Heartbeat staleness must never
|
|
@@ -249,31 +250,14 @@ export async function sweepAtomicWriteStages(directories, options = {}) {
|
|
|
249
250
|
const isPidAlive = options.isPidAlive ?? realIsPidAlive;
|
|
250
251
|
return sweepOwnStagingFiles(directories, { maxEntries, isPidAlive });
|
|
251
252
|
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
*
|
|
257
|
-
*
|
|
258
|
-
*
|
|
259
|
-
|
|
260
|
-
if (fs.existsSync("/bin/ps"))
|
|
261
|
-
return "/bin/ps";
|
|
262
|
-
if (fs.existsSync("/usr/bin/ps"))
|
|
263
|
-
return "/usr/bin/ps";
|
|
264
|
-
return "/bin/ps";
|
|
265
|
-
}
|
|
266
|
-
/** Escape a value for embedding in a WQL LIKE clause: WQL uses `'` as the
|
|
267
|
-
* string delimiter (doubled to escape) and `%`/`_` as wildcards — the marker
|
|
268
|
-
* is an opaque path string, so escape all three before interpolating. */
|
|
269
|
-
function escapeWqlLikeValue(value) {
|
|
270
|
-
return value.replaceAll("'", "''").replaceAll(/[%_]/g, (ch) => `[${ch}]`);
|
|
271
|
-
}
|
|
272
|
-
/** Escape a value for a WQL EQUALITY comparison: only the string delimiter
|
|
273
|
-
* needs escaping — `%`/`_` are literal outside `LIKE`. */
|
|
274
|
-
function escapeWqlStringValue(value) {
|
|
275
|
-
return value.replaceAll("'", "''");
|
|
276
|
-
}
|
|
253
|
+
/**
|
|
254
|
+
* Interpreter resolution, WQL escaping and the platform listing itself all
|
|
255
|
+
* live in the ONE process-table seam (#2443): `scripts/lib/process-scan.mjs`,
|
|
256
|
+
* reached from clients/ through `clients/process-snapshot.ts`. This file used
|
|
257
|
+
* to carry its own copy of each, which is how the three queries below drifted
|
|
258
|
+
* apart from the two in `clients/resource-sampler.ts` and the two in
|
|
259
|
+
* `scripts/`. `windowsExe` is re-exported by the seam and imported above.
|
|
260
|
+
*/
|
|
277
261
|
/** Search running processes whose command line contains `marker` (Windows,
|
|
278
262
|
* via CIM/WQL). Returns matching pids. Best-effort: any failure ⇒ [], but a
|
|
279
263
|
* failure is RECORDED (#1857 class sweep) — "the search found no orphan" and
|
|
@@ -282,14 +266,26 @@ function escapeWqlStringValue(value) {
|
|
|
282
266
|
async function findPidsByMarkerWindows(marker) {
|
|
283
267
|
if (!isWindows || !marker)
|
|
284
268
|
return [];
|
|
285
|
-
const
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
269
|
+
const result = await queryProcessTable({
|
|
270
|
+
fields: ["pid"],
|
|
271
|
+
filter: { column: "CommandLine", op: "like", values: [marker] },
|
|
272
|
+
// The query's own powershell.exe command line embeds the marker, so
|
|
273
|
+
// without this exclusion the search matches itself.
|
|
274
|
+
excludeSelfPid: true,
|
|
275
|
+
}, {
|
|
276
|
+
timeoutMs: BACKSTOP_SCAN_TIMEOUT_MS,
|
|
277
|
+
// #2527 review F2: omitting `onTimeout` falls through to
|
|
278
|
+
// child-unref.ts's default — one bare, unverified `child.kill()`, no
|
|
279
|
+
// tree kill, no identity-carrying record — inside the orphan backstop
|
|
280
|
+
// path, the exact abandonment `terminateScannerChild`'s own doc
|
|
281
|
+
// comment says it exists to prevent. This query shares the backstop's
|
|
282
|
+
// scanner identity and budget (same producer as
|
|
283
|
+
// `enumerateManagedProcesses`), so it gets the same kind.
|
|
284
|
+
onTimeout: (child) => terminateScannerChild(child, {
|
|
285
|
+
kind: "orphan-backstop-scanner-escalated",
|
|
286
|
+
timeoutMs: BACKSTOP_SCAN_TIMEOUT_MS,
|
|
287
|
+
}),
|
|
288
|
+
});
|
|
293
289
|
if (result.status !== "ok") {
|
|
294
290
|
recordDegradationOnce({
|
|
295
291
|
kind: "orphan-backstop-scan-failed",
|
|
@@ -297,10 +293,7 @@ async function findPidsByMarkerWindows(marker) {
|
|
|
297
293
|
reason: `marker command-line search ${result.status}`,
|
|
298
294
|
});
|
|
299
295
|
}
|
|
300
|
-
return result.
|
|
301
|
-
.split(/\r?\n/)
|
|
302
|
-
.map((line) => Number(line.trim()))
|
|
303
|
-
.filter((n) => Number.isFinite(n) && n > 0);
|
|
296
|
+
return result.rows.map((row) => row.pid);
|
|
304
297
|
}
|
|
305
298
|
/** Fetch command lines for a set of pids in one query (Windows: CIM; POSIX:
|
|
306
299
|
* `ps`). Returns a pid → command-line map; pids that can't be resolved are
|
|
@@ -317,59 +310,35 @@ async function queryCommandLines(pids) {
|
|
|
317
310
|
const map = new Map();
|
|
318
311
|
if (valid.length === 0)
|
|
319
312
|
return map;
|
|
320
|
-
const
|
|
321
|
-
|
|
322
|
-
|
|
313
|
+
const result = await queryProcessTable({
|
|
314
|
+
fields: ["pid", "command"],
|
|
315
|
+
filter: { column: "ProcessId", op: "eq", values: valid },
|
|
316
|
+
}, {
|
|
317
|
+
timeoutMs: BACKSTOP_SCAN_TIMEOUT_MS,
|
|
318
|
+
// #2527 review F2: same rationale as findPidsByMarkerWindows above —
|
|
319
|
+
// route through the reaper's own tree-kill-and-verify machinery with
|
|
320
|
+
// the backstop's kind rather than falling through to the unverified
|
|
321
|
+
// default kill with no ledger record.
|
|
322
|
+
onTimeout: (child) => terminateScannerChild(child, {
|
|
323
|
+
kind: "orphan-backstop-scanner-escalated",
|
|
324
|
+
timeoutMs: BACKSTOP_SCAN_TIMEOUT_MS,
|
|
325
|
+
}),
|
|
326
|
+
});
|
|
327
|
+
// POSIX `ps -p` exits nonzero when NONE of the requested pids exist, which
|
|
328
|
+
// is a legitimate clean result for this caller, so that one status is not
|
|
329
|
+
// recorded on that platform. The shared collector calls it an exit failure;
|
|
330
|
+
// this caller's command contract makes it the expected empty table. Windows
|
|
331
|
+
// CIM has no such convention, so an exit failure there is a real failure.
|
|
332
|
+
const psReportedNoSuchPid = !isWindows && result.status === "exit-error";
|
|
333
|
+
if (result.status !== "ok" && !psReportedNoSuchPid) {
|
|
323
334
|
recordDegradationOnce({
|
|
324
335
|
kind: "orphan-backstop-scan-failed",
|
|
325
336
|
subject: "identity-query",
|
|
326
|
-
reason: `command-line identity query ${status}; reap suppressed this sweep`,
|
|
337
|
+
reason: `command-line identity query ${result.status}; reap suppressed this sweep`,
|
|
327
338
|
});
|
|
328
|
-
};
|
|
329
|
-
if (isWindows) {
|
|
330
|
-
const filter = valid.map((p) => `ProcessId=${p}`).join(" OR ");
|
|
331
|
-
const psScript = `Get-CimInstance Win32_Process -Filter "${filter}" ` +
|
|
332
|
-
`| ForEach-Object { "$($_.ProcessId)\t$($_.CommandLine)" }`;
|
|
333
|
-
const powershell = windowsExe("WindowsPowerShell\\v1.0\\powershell.exe");
|
|
334
|
-
const result = await spawnCollectStdoutResult(powershell, ["-NoProfile", "-NonInteractive", "-Command", psScript], { shell: false, windowsHide: true, stdio: ["ignore", "pipe", "ignore"] }, { timeoutMs: BACKSTOP_SCAN_TIMEOUT_MS });
|
|
335
|
-
noteFailure(result.status);
|
|
336
|
-
for (const line of result.stdout.split(/\r?\n/)) {
|
|
337
|
-
const tab = line.indexOf("\t");
|
|
338
|
-
if (tab <= 0)
|
|
339
|
-
continue;
|
|
340
|
-
const pid = Number(line.slice(0, tab).trim());
|
|
341
|
-
if (Number.isFinite(pid) && pid > 0)
|
|
342
|
-
map.set(pid, line.slice(tab + 1));
|
|
343
|
-
}
|
|
344
|
-
return map;
|
|
345
|
-
}
|
|
346
|
-
const result = await spawnCollectStdoutResult(posixPsPath(), ["-p", valid.join(","), "-o", "pid=,args="], { shell: false, stdio: ["ignore", "pipe", "ignore"] }, { timeoutMs: BACKSTOP_SCAN_TIMEOUT_MS });
|
|
347
|
-
// `ps -p` exits nonzero when NONE of the pids exist, which is a legitimate
|
|
348
|
-
// clean result here, so only spawn/timeout failures are recorded. The
|
|
349
|
-
// shared collector calls that an exit failure, but this caller's command
|
|
350
|
-
// contract makes that status the expected empty-table result.
|
|
351
|
-
if (result.status !== "exit-error")
|
|
352
|
-
noteFailure(result.status);
|
|
353
|
-
for (const line of result.stdout.split(/\r?\n/)) {
|
|
354
|
-
// Linear parse (S8786/S6594: avoid regex backtracking on
|
|
355
|
-
// attacker-lengthenable ps output) — trim leading whitespace,
|
|
356
|
-
// then split on the first whitespace run: " 1234 args here".
|
|
357
|
-
const trimmed = line.trimStart();
|
|
358
|
-
if (!trimmed)
|
|
359
|
-
continue;
|
|
360
|
-
let i = 0;
|
|
361
|
-
while (i < trimmed.length && trimmed[i] >= "0" && trimmed[i] <= "9")
|
|
362
|
-
i++;
|
|
363
|
-
if (i === 0)
|
|
364
|
-
continue;
|
|
365
|
-
const pidStr = trimmed.slice(0, i);
|
|
366
|
-
let j = i;
|
|
367
|
-
while (j < trimmed.length && (trimmed[j] === " " || trimmed[j] === "\t"))
|
|
368
|
-
j++;
|
|
369
|
-
const pid = Number(pidStr);
|
|
370
|
-
if (Number.isFinite(pid) && pid > 0)
|
|
371
|
-
map.set(pid, trimmed.slice(j));
|
|
372
339
|
}
|
|
340
|
+
for (const row of result.rows)
|
|
341
|
+
map.set(row.pid, row.command);
|
|
373
342
|
return map;
|
|
374
343
|
}
|
|
375
344
|
/**
|
|
@@ -401,8 +370,8 @@ export function buildIdentityMatcher(cmdlines) {
|
|
|
401
370
|
/** Post-kill liveness poll budget. `taskkill /F /T` returns before the kernel
|
|
402
371
|
* has finished tearing the tree down, so a single immediate check would
|
|
403
372
|
* report false `alive`s. */
|
|
404
|
-
|
|
405
|
-
|
|
373
|
+
const KILL_VERIFY_ATTEMPTS = 5;
|
|
374
|
+
const KILL_VERIFY_INTERVAL_MS = 100;
|
|
406
375
|
/** `setTimeout` as an awaitable, with the timer unref'd so a settled one-shot
|
|
407
376
|
* `pi --print` never waits on best-effort kill verification. */
|
|
408
377
|
function sleepUnref(ms) {
|
|
@@ -490,7 +459,7 @@ async function verifyPidGone(pid, options = {}) {
|
|
|
490
459
|
* (script path), not the process image name, exactly like the existing
|
|
491
460
|
* marker-search's WQL LIKE query below.
|
|
492
461
|
*/
|
|
493
|
-
|
|
462
|
+
const MANAGED_BINARIES = [
|
|
494
463
|
{ name: "ast-grep", launcher: "native" },
|
|
495
464
|
{ name: "opengrep-core", launcher: "native" },
|
|
496
465
|
{ name: "opengrep", launcher: "native" },
|
|
@@ -605,104 +574,42 @@ export function partitionBackstopCandidates(processes, registry, isPidAlive, opt
|
|
|
605
574
|
}
|
|
606
575
|
/** Enumerate live OS processes whose command line contains one of
|
|
607
576
|
* `MANAGED_BINARY_NAMES` (#658), independent of the instance registry.
|
|
608
|
-
*
|
|
609
|
-
*
|
|
610
|
-
*
|
|
577
|
+
* One projected process-table query through the shared seam, narrowed to
|
|
578
|
+
* managed binaries in JS; returns `{pid, parentPid, command, ageMs}` rows.
|
|
579
|
+
* Best-effort: any failure ⇒ [], with the scan status carried alongside so
|
|
580
|
+
* an empty table is never mistaken for a scan that did not run. */
|
|
611
581
|
async function enumerateManagedProcesses(options = {}) {
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
const secondTab = line.indexOf("\t", firstTab + 1);
|
|
644
|
-
if (secondTab <= 0)
|
|
645
|
-
continue;
|
|
646
|
-
const thirdTab = line.indexOf("\t", secondTab + 1);
|
|
647
|
-
if (thirdTab <= 0)
|
|
648
|
-
continue;
|
|
649
|
-
const pid = Number(line.slice(0, firstTab).trim());
|
|
650
|
-
const parentPid = Number(line.slice(firstTab + 1, secondTab).trim());
|
|
651
|
-
const ageMs = parseNonNegativeMs(line.slice(secondTab + 1, thirdTab));
|
|
652
|
-
const command = line.slice(thirdTab + 1);
|
|
653
|
-
if (!Number.isFinite(pid) || pid <= 0)
|
|
654
|
-
continue;
|
|
655
|
-
processes.push({ pid, parentPid, command, ageMs });
|
|
656
|
-
}
|
|
657
|
-
return narrowToManagedBinaries(processes, result);
|
|
658
|
-
}
|
|
659
|
-
// POSIX: enumerate everything, filter in JS by managed-name substring —
|
|
660
|
-
// there is no single-query WQL-style server-side filter available.
|
|
661
|
-
// `etime` is the POSIX-standard elapsed-time column (Linux and macOS both
|
|
662
|
-
// support it; `etimes` is Linux-only), and supplies the spawn-grace age.
|
|
663
|
-
const result = await spawnCollectStdoutResult(posixPsPath(), [...POSIX_PS_ARGS], { shell: false, stdio: ["ignore", "pipe", "ignore"] }, collect);
|
|
664
|
-
const processes = [];
|
|
665
|
-
for (const line of result.stdout.split(/\r?\n/)) {
|
|
666
|
-
// Linear parse (S8786/S6594): " pid ppid etime args here".
|
|
667
|
-
const trimmed = line.trimStart();
|
|
668
|
-
if (!trimmed)
|
|
669
|
-
continue;
|
|
670
|
-
let i = 0;
|
|
671
|
-
while (i < trimmed.length && trimmed[i] >= "0" && trimmed[i] <= "9")
|
|
672
|
-
i++;
|
|
673
|
-
if (i === 0)
|
|
674
|
-
continue;
|
|
675
|
-
const pid = Number(trimmed.slice(0, i));
|
|
676
|
-
let rest = trimmed.slice(i);
|
|
677
|
-
let k = 0;
|
|
678
|
-
while (k < rest.length && (rest[k] === " " || rest[k] === "\t"))
|
|
679
|
-
k++;
|
|
680
|
-
rest = rest.slice(k);
|
|
681
|
-
let j = 0;
|
|
682
|
-
while (j < rest.length && rest[j] >= "0" && rest[j] <= "9")
|
|
683
|
-
j++;
|
|
684
|
-
if (j === 0)
|
|
685
|
-
continue;
|
|
686
|
-
const parentPid = Number(rest.slice(0, j));
|
|
687
|
-
rest = rest.slice(j);
|
|
688
|
-
let m = 0;
|
|
689
|
-
while (m < rest.length && (rest[m] === " " || rest[m] === "\t"))
|
|
690
|
-
m++;
|
|
691
|
-
rest = rest.slice(m);
|
|
692
|
-
// etime token: a non-whitespace run of digits, ':' and '-'.
|
|
693
|
-
let e = 0;
|
|
694
|
-
while (e < rest.length && rest[e] !== " " && rest[e] !== "\t")
|
|
695
|
-
e++;
|
|
696
|
-
const ageMs = ageMsFromPosixEtime(rest.slice(0, e));
|
|
697
|
-
let n = e;
|
|
698
|
-
while (n < rest.length && (rest[n] === " " || rest[n] === "\t"))
|
|
699
|
-
n++;
|
|
700
|
-
const args = rest.slice(n);
|
|
701
|
-
if (!Number.isFinite(pid) || pid <= 0)
|
|
702
|
-
continue;
|
|
703
|
-
processes.push({ pid, parentPid, command: args, ageMs });
|
|
704
|
-
}
|
|
705
|
-
return narrowToManagedBinaries(processes, result);
|
|
582
|
+
// #1857: `Name = '…'` equality replaces eight leading-wildcard
|
|
583
|
+
// `CommandLine LIKE '%…%'` clauses, and the projection carries an age so
|
|
584
|
+
// the spawn-grace guard has something to reason from. The image-name set is
|
|
585
|
+
// DERIVED from MANAGED_BINARIES (MANAGED_IMAGE_NAMES), so adding a managed
|
|
586
|
+
// binary cannot leave a stale parallel list behind.
|
|
587
|
+
//
|
|
588
|
+
// POSIX `ps` cannot express that filter — the seam reports it as
|
|
589
|
+
// `serverSideFiltered: false` and hands back the whole table — which is why
|
|
590
|
+
// `narrowToManagedBinaries` runs on BOTH platforms rather than only on the
|
|
591
|
+
// POSIX branch. Windows over-collects for its own reason anyway
|
|
592
|
+
// (`node.exe` is a superset image name covering every node process on the
|
|
593
|
+
// machine).
|
|
594
|
+
const scanTimeoutMs = options.timeoutMs ?? BACKSTOP_SCAN_TIMEOUT_MS;
|
|
595
|
+
const result = await queryProcessTable({
|
|
596
|
+
fields: ["pid", "ppid", "ageMs", "command"],
|
|
597
|
+
filter: { column: "Name", op: "eq", values: MANAGED_IMAGE_NAMES },
|
|
598
|
+
}, {
|
|
599
|
+
timeoutMs: scanTimeoutMs,
|
|
600
|
+
onTimeout: (child) => terminateScannerChild(child, {
|
|
601
|
+
verifyAttempts: options.verifyAttempts,
|
|
602
|
+
verifyIntervalMs: options.verifyIntervalMs,
|
|
603
|
+
kind: "orphan-backstop-scanner-escalated",
|
|
604
|
+
timeoutMs: scanTimeoutMs,
|
|
605
|
+
}),
|
|
606
|
+
});
|
|
607
|
+
return narrowToManagedBinaries(result.rows.map((row) => ({
|
|
608
|
+
pid: row.pid,
|
|
609
|
+
parentPid: row.ppid,
|
|
610
|
+
command: row.command,
|
|
611
|
+
ageMs: row.ageMs,
|
|
612
|
+
})), result);
|
|
706
613
|
}
|
|
707
614
|
/**
|
|
708
615
|
* The ONE place a raw OS-process snapshot is narrowed to managed binaries.
|
|
@@ -730,6 +637,18 @@ function narrowToManagedBinaries(processes, result) {
|
|
|
730
637
|
* exists to fix, so the scanner now gets exactly what an orphan gets:
|
|
731
638
|
* `taskkill /F /T` or a POSIX group kill, then a verified liveness poll. The
|
|
732
639
|
* escalation is recorded with the scanner's identity, never swallowed.
|
|
640
|
+
*
|
|
641
|
+
* The kill attempt itself is real regardless of what happens next: this
|
|
642
|
+
* handler is invoked the instant the caller's timer elapses, which can race
|
|
643
|
+
* a query child that is genuinely about to close successfully (its own
|
|
644
|
+
* "close" event may still win the overall settle — see
|
|
645
|
+
* `child-unref.ts#spawnCollectStdoutResult`, which resolves on whichever of
|
|
646
|
+
* "close" or the timeout handler's own settle lands first). This function has
|
|
647
|
+
* no way to observe that outcome — it runs strictly BEFORE the caller's
|
|
648
|
+
* promise resolves — so it always records the escalation it actually
|
|
649
|
+
* attempted; callers whose escalation kind can fire on that race classify it
|
|
650
|
+
* as informational rather than a warning (see
|
|
651
|
+
* `degradation-ledger.ts`'s `resource-sampler-scanner-escalated` doc comment).
|
|
733
652
|
*/
|
|
734
653
|
export async function terminateScannerChild(child, options) {
|
|
735
654
|
const pid = child.pid;
|
|
@@ -740,9 +659,9 @@ export async function terminateScannerChild(child, options) {
|
|
|
740
659
|
})
|
|
741
660
|
: "invalid";
|
|
742
661
|
incrementDegradationCount({
|
|
743
|
-
kind:
|
|
662
|
+
kind: options.kind,
|
|
744
663
|
subject: `${isWindows ? "win32-cim" : "posix-ps"}#${pid ?? "no-pid"}`,
|
|
745
|
-
reason: `scan exceeded its timeout; tree kill reported ${outcome}`,
|
|
664
|
+
reason: `scan exceeded its ${options.timeoutMs}ms timeout; tree kill reported ${outcome}`,
|
|
746
665
|
});
|
|
747
666
|
return outcome;
|
|
748
667
|
}
|
|
@@ -755,51 +674,6 @@ function matchesManagedBinary(command) {
|
|
|
755
674
|
const lower = command.toLowerCase();
|
|
756
675
|
return MANAGED_BINARY_NAMES.some((name) => lower.includes(name.toLowerCase()));
|
|
757
676
|
}
|
|
758
|
-
/**
|
|
759
|
-
* Parse the Windows age column: a non-negative integer millisecond count, or
|
|
760
|
-
* anything else. A negative or malformed value is `undefined`, not zero and
|
|
761
|
-
* not a clamp — a nonsensical age means the age is UNKNOWN, and the grace
|
|
762
|
-
* guard must spare an unknown-age process rather than reason from a number it
|
|
763
|
-
* cannot trust. That rule is what surfaced the local-time tick bug during the
|
|
764
|
-
* host probe instead of silently sparing everything.
|
|
765
|
-
*/
|
|
766
|
-
function parseNonNegativeMs(raw) {
|
|
767
|
-
const token = raw.trim();
|
|
768
|
-
if (!/^\d+$/.test(token))
|
|
769
|
-
return undefined;
|
|
770
|
-
const value = Number(token);
|
|
771
|
-
return Number.isFinite(value) ? value : undefined;
|
|
772
|
-
}
|
|
773
|
-
/**
|
|
774
|
-
* POSIX enumeration columns. Exported so a real-`ps` test can assert this
|
|
775
|
-
* exact argument vector is accepted by the host's `ps` — a rejected column
|
|
776
|
-
* would make the whole backstop silently return zero rows, and this is the
|
|
777
|
-
* one part of the fix that cannot be checked from a Windows dev machine.
|
|
778
|
-
*/
|
|
779
|
-
export const POSIX_PS_ARGS = [
|
|
780
|
-
"-eo",
|
|
781
|
-
"pid=,ppid=,etime=,args=",
|
|
782
|
-
];
|
|
783
|
-
/** Parse `ps -o etime` output: `[[dd-]hh:]mm:ss`. Returns undefined for any
|
|
784
|
-
* shape the column did not produce (a `ps` without the column emits the
|
|
785
|
-
* command line where the token was expected). */
|
|
786
|
-
export function ageMsFromPosixEtime(raw) {
|
|
787
|
-
const token = raw.trim();
|
|
788
|
-
if (!/^(?:\d+-)?(?:\d+:)?\d+:\d+$/.test(token))
|
|
789
|
-
return undefined;
|
|
790
|
-
let days = 0;
|
|
791
|
-
let rest = token;
|
|
792
|
-
const dash = rest.indexOf("-");
|
|
793
|
-
if (dash >= 0) {
|
|
794
|
-
days = Number(rest.slice(0, dash));
|
|
795
|
-
rest = rest.slice(dash + 1);
|
|
796
|
-
}
|
|
797
|
-
const parts = rest.split(":").map(Number);
|
|
798
|
-
if (parts.some((part) => !Number.isFinite(part)))
|
|
799
|
-
return undefined;
|
|
800
|
-
const [hours, minutes, seconds] = parts.length === 3 ? parts : [0, parts[0], parts[1]];
|
|
801
|
-
return ((days * 24 + hours) * 60 * 60 + minutes * 60 + seconds) * 1000;
|
|
802
|
-
}
|
|
803
677
|
/**
|
|
804
678
|
* Fire-and-forget REGISTRY-INDEPENDENT backstop sweep (#658): finds
|
|
805
679
|
* pi-lens-managed LSP/scanner processes the registry-driven `sweepOrphans`
|
|
@@ -970,11 +844,11 @@ function classifyKillOutcome(killed, unverified) {
|
|
|
970
844
|
* not time-critical, so paying its cost once per half hour instead of once
|
|
971
845
|
* per session_start removes essentially all of its aggregate cost.
|
|
972
846
|
*/
|
|
973
|
-
|
|
847
|
+
const BACKSTOP_COOLDOWN_MS = 30 * 60 * 1000;
|
|
974
848
|
/** How long after session_start the deferred sweep fires. Chosen to clear the
|
|
975
849
|
* warmup window it was measured starving: `warmup_total` median 3288ms,
|
|
976
850
|
* worst on record 5480ms (#1857). */
|
|
977
|
-
|
|
851
|
+
const BACKSTOP_START_DELAY_MS = 30_000;
|
|
978
852
|
/** Cap on process identities embedded in one latency record. */
|
|
979
853
|
const BACKSTOP_IDENTITY_LOG_LIMIT = 10;
|
|
980
854
|
/**
|
|
@@ -982,7 +856,7 @@ const BACKSTOP_IDENTITY_LOG_LIMIT = 10;
|
|
|
982
856
|
* a candidate that was 1ms too fresh is comfortably past the grace by the
|
|
983
857
|
* time the retry looks at it again.
|
|
984
858
|
*/
|
|
985
|
-
|
|
859
|
+
const BACKSTOP_GRACE_RETRY_MARGIN_MS = 30_000;
|
|
986
860
|
/** How long the sweep lock may be held before another process reclaims it.
|
|
987
861
|
* Well above the scan timeout plus the kill budget, and irrelevant when the
|
|
988
862
|
* holder dies — the lock reclaims immediately on a dead owner pid
|
|
@@ -192,9 +192,12 @@ export function getInstanceRoots(entry) {
|
|
|
192
192
|
* pi-lens process reads on every heartbeat. Eviction drops the OLDEST
|
|
193
193
|
* NON-PRIMARY root: `projectRoot` is the host's own working directory and the
|
|
194
194
|
* one the shared-checkout guard most needs, so it is never evicted.
|
|
195
|
-
* Deliberately smaller than `SESSION_ROOT_CAP` (128,
|
|
196
|
-
*
|
|
197
|
-
*
|
|
195
|
+
* Deliberately smaller than `SESSION_ROOT_CAP` (128, `clients/lsp/
|
|
196
|
+
* session-roots.ts`) because that registry lives in memory for one process
|
|
197
|
+
* while this one is serialized to disk for all of them. The two are not
|
|
198
|
+
* mirrors: they answer different questions about different populations, so
|
|
199
|
+
* #2518's one-store rule (a root's LSP config cannot be evicted while the
|
|
200
|
+
* root is served) does not extend to this cap.
|
|
198
201
|
*/
|
|
199
202
|
const INSTANCE_ROOT_CAP = 32;
|
|
200
203
|
/**
|
|
@@ -160,15 +160,6 @@ function computeProjectLanguageProfile(projectRoot, sourceFiles) {
|
|
|
160
160
|
detectedKinds,
|
|
161
161
|
};
|
|
162
162
|
}
|
|
163
|
-
export function hasLanguage(profile, kind) {
|
|
164
|
-
return !!profile.present[kind];
|
|
165
|
-
}
|
|
166
|
-
export function hasAnyLanguage(profile, kinds) {
|
|
167
|
-
return kinds.some((kind) => hasLanguage(profile, kind));
|
|
168
|
-
}
|
|
169
|
-
export function isLanguageConfigured(profile, kind) {
|
|
170
|
-
return !!profile.configured[kind];
|
|
171
|
-
}
|
|
172
163
|
export function getDefaultStartupTools(profile) {
|
|
173
164
|
const tools = new Set();
|
|
174
165
|
for (const kind of Object.keys(LANGUAGE_POLICY)) {
|