@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
|
@@ -63,4 +63,35 @@ export class RustClient {
|
|
|
63
63
|
isRustFile(filePath) {
|
|
64
64
|
return path.extname(filePath).toLowerCase() === ".rs";
|
|
65
65
|
}
|
|
66
|
+
/** Forget the memoized cargo path and latched availability verdict — #2455. */
|
|
67
|
+
resetAvailability() {
|
|
68
|
+
this.availability.reset();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* The one `RustClient` this process owns (#2455 fix round 4, F2).
|
|
73
|
+
*
|
|
74
|
+
* Same shape as `go-client.ts`'s `goClient`, and the same round-2 defect: the
|
|
75
|
+
* runner (`dispatch/runners/rust-clippy.ts`) and `bootstrap.ts` each built
|
|
76
|
+
* their own instance, so `resetRustAvailability` re-armed one latch while
|
|
77
|
+
* `handleSessionStart`'s "Active tools" line read the other's never-expiring
|
|
78
|
+
* probe-class "missing" verdict. One instance, in the module that owns the
|
|
79
|
+
* class; `tests/clients/toolchain-client-singleton.test.ts` holds the line.
|
|
80
|
+
*/
|
|
81
|
+
export const rustClient = new RustClient();
|
|
82
|
+
/**
|
|
83
|
+
* Forget `rustClient`'s memoized cargo path and latched availability verdict —
|
|
84
|
+
* #2455. Same #1496/#1535 shape as `resetZizmorTokenAvailability`; wired into
|
|
85
|
+
* `handleSessionStart` beside it (`clients/runtime-session.ts`) so a Rust
|
|
86
|
+
* toolchain installed mid-process is observed by the next session instead of
|
|
87
|
+
* staying "missing" for the rest of the process's life.
|
|
88
|
+
*
|
|
89
|
+
* This module — not `rust-clippy.ts` — because the reset must sit beside the
|
|
90
|
+
* single instance it clears (#2455 fix round 4, F2). `rust-clippy.ts`'s
|
|
91
|
+
* `clippyAvailabilityByCargo` is a separate, already-covered latch: it rides
|
|
92
|
+
* `createCwdCachedProbe`'s shared `availabilityGeneration` counter (see
|
|
93
|
+
* `runner-helpers.ts`'s `resetDispatchAvailabilityState`), not this reset.
|
|
94
|
+
*/
|
|
95
|
+
export function resetRustAvailability() {
|
|
96
|
+
rustClient.resetAvailability();
|
|
66
97
|
}
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
import { spawn, spawnSync, } from "node:child_process";
|
|
17
17
|
import * as fs from "node:fs";
|
|
18
18
|
import * as path from "node:path";
|
|
19
|
+
import { BoundedFifoMap } from "./bounded-cache.js";
|
|
19
20
|
import { logLatency } from "./latency-logger.js";
|
|
20
21
|
import { recordDegradation } from "./degradation-ledger.js";
|
|
21
22
|
import { logExtension } from "./extension-log.js";
|
|
@@ -570,23 +571,21 @@ function resolveWindowsPathEntry(entry, effectiveCwd, env) {
|
|
|
570
571
|
* cache is also count-bounded with oldest-entry eviction because a long-lived
|
|
571
572
|
* process can encounter unbounded cwd/environment combinations.
|
|
572
573
|
*/
|
|
573
|
-
const WINDOWS_COMMAND_CACHE_MAX_ENTRIES = 256;
|
|
574
|
+
export const WINDOWS_COMMAND_CACHE_MAX_ENTRIES = 256;
|
|
574
575
|
const WINDOWS_COMMAND_NEGATIVE_CACHE_TTL_MS = 1000;
|
|
575
|
-
const windowsCommandCache = new
|
|
576
|
+
const windowsCommandCache = new BoundedFifoMap(WINDOWS_COMMAND_CACHE_MAX_ENTRIES);
|
|
576
577
|
/** Reset after session replacement or a successful managed install. */
|
|
577
578
|
export function resetSafeSpawnWindowsCommandCache() {
|
|
578
579
|
windowsCommandCache.clear();
|
|
579
580
|
loggedSpawnClassifications.clear();
|
|
580
581
|
}
|
|
581
582
|
function cacheWindowsCommandResult(key, resolved) {
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
windowsCommandCache.delete(oldest);
|
|
589
|
-
}
|
|
583
|
+
// Resolution entries are session-scoped and cheap to recompute. The
|
|
584
|
+
// caller always deletes any stale entry for `key` before reaching here
|
|
585
|
+
// (see resolveWindowsCommandForEnvironment), so this can only grow the
|
|
586
|
+
// map; BoundedFifoMap evicts the oldest insertion first once the map
|
|
587
|
+
// exceeds capacity, so a long-lived process cannot retain every cwd /
|
|
588
|
+
// environment it has ever touched.
|
|
590
589
|
windowsCommandCache.set(key, { resolved, checkedAt: Date.now() });
|
|
591
590
|
}
|
|
592
591
|
function getPathExts(env) {
|
|
@@ -848,6 +847,30 @@ const EXIT_PIPE_IDLE_MAX_WAIT_MS = 2000;
|
|
|
848
847
|
* - Kills the process on timeout (preventing zombies)
|
|
849
848
|
* - Supports cancellation via AbortSignal
|
|
850
849
|
*
|
|
850
|
+
* ## Why this bound is NOT `bounded()` — the one documented exception (#2523)
|
|
851
|
+
*
|
|
852
|
+
* #2523 slice 2 folded every other "deadline AND abort signal" implementation
|
|
853
|
+
* in the tree onto `clients/deadline-utils.ts#bounded`. This one stays, and it
|
|
854
|
+
* is not a copy of the same idea:
|
|
855
|
+
*
|
|
856
|
+
* `bounded()` ABANDONS a promise — it stops waiting and lets the work run on
|
|
857
|
+
* unobserved, which is safe precisely because everything it wraps is in-process
|
|
858
|
+
* (a dynamic import, an LSP round trip, a `stat`). This function's work is a
|
|
859
|
+
* CHILD PROCESS, and abandoning one leaks it. So its timer does not settle a
|
|
860
|
+
* race at all: `timeoutId` sets `timedOut`, then runs `killTree()` — SIGTERM,
|
|
861
|
+
* an escalation timer, SIGKILL, and on Windows a `taskkill /T` of the whole
|
|
862
|
+
* tree — and the promise settles only when the child's own `close` arrives (or
|
|
863
|
+
* the escalation gives up). The result it produces carries the teardown
|
|
864
|
+
* EVIDENCE (`timeoutTeardown`, #2010): which signal killed it, whether the
|
|
865
|
+
* tree actually died, how long it took. Replacing that with `bounded()` would
|
|
866
|
+
* return `undefined` at the deadline and leave a live `vitest`/`gradle` behind
|
|
867
|
+
* — the orphan class #2504 measured as 59 concurrent spawns starving a turn.
|
|
868
|
+
*
|
|
869
|
+
* The rule the exception preserves: a bound that can CANCEL its work must
|
|
870
|
+
* cancel it. `bounded()` is for work that cannot be cancelled; this is not
|
|
871
|
+
* that. Anything wrapping THIS function still gets `bounded()` around its own
|
|
872
|
+
* await if it needs one.
|
|
873
|
+
*
|
|
851
874
|
* @example
|
|
852
875
|
* const result = await safeSpawnAsync("npm", ["test"], { timeout: 30000 });
|
|
853
876
|
* if (result.error) console.error("Failed:", result.error);
|
|
@@ -6,8 +6,14 @@
|
|
|
6
6
|
*/
|
|
7
7
|
// --- Constants ---
|
|
8
8
|
// ANSI escape codes for colors and formatting
|
|
9
|
+
// oxlint-disable-next-line no-control-regex -- ESC (\x1b) is the literal ANSI escape-sequence lead byte this pattern strips, not accidental input.
|
|
9
10
|
const ANSI_ESCAPE = /\x1b\[[0-9;]*m/g;
|
|
10
|
-
|
|
11
|
+
// Full ECMA-48 CSI grammar (parameter bytes 0-9;? , intermediate bytes
|
|
12
|
+
// space-/, final byte @-~) — matches every CSI sequence ANSI_ESCAPE does
|
|
13
|
+
// plus non-SGR ones (cursor moves, private-mode `?` sequences like
|
|
14
|
+
// `\x1b[?25l`, etc.), not just the `m`-terminated color codes.
|
|
15
|
+
// oxlint-disable-next-line no-control-regex -- ESC (\x1b) is the literal ANSI escape-sequence lead byte this pattern strips, not accidental input.
|
|
16
|
+
const ANSI_ESCAPE_EXTENDED = /\x1b\[[0-9;?]*[ -/]*[@-~]/g;
|
|
11
17
|
// Common error patterns from different tools
|
|
12
18
|
const ERROR_INDICATORS = [
|
|
13
19
|
/\berror\b/i,
|
|
@@ -37,17 +43,6 @@ const DETAIL_PATTERNS = [
|
|
|
37
43
|
export function stripAnsi(text) {
|
|
38
44
|
return text.replace(ANSI_ESCAPE, "").replace(ANSI_ESCAPE_EXTENDED, "");
|
|
39
45
|
}
|
|
40
|
-
/**
|
|
41
|
-
* Normalize whitespace in a string.
|
|
42
|
-
* Collapses multiple spaces/tabs to single space, trims lines.
|
|
43
|
-
*/
|
|
44
|
-
export function normalizeWhitespace(text) {
|
|
45
|
-
return text
|
|
46
|
-
.split(/\r?\n/)
|
|
47
|
-
.map((line) => line.replace(/\s+/g, " ").trim())
|
|
48
|
-
.filter((line) => line.length > 0)
|
|
49
|
-
.join("\n");
|
|
50
|
-
}
|
|
51
46
|
/**
|
|
52
47
|
* Check if a line contains error indicators.
|
|
53
48
|
*/
|
|
@@ -1,59 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { collectSourceFiles, collectSourceFilesAsync, isBuildArtifact, } from "./source-filter.js";
|
|
3
|
-
/**
|
|
4
|
-
* Common parsing logic for ast-grep JSON output (handles both array and NDJSON).
|
|
5
|
-
*/
|
|
6
|
-
// biome-ignore lint/suspicious/noExplicitAny: ast-grep JSON output is untyped
|
|
7
|
-
export function parseAstGrepJson(raw) {
|
|
8
|
-
if (!raw)
|
|
9
|
-
return [];
|
|
10
|
-
const trimmed = raw.trim();
|
|
11
|
-
if (trimmed.startsWith("[")) {
|
|
12
|
-
try {
|
|
13
|
-
return JSON.parse(trimmed);
|
|
14
|
-
}
|
|
15
|
-
catch {
|
|
16
|
-
return [];
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
return trimmed.split("\n").flatMap((l) => {
|
|
20
|
-
try {
|
|
21
|
-
return [JSON.parse(l)];
|
|
22
|
-
}
|
|
23
|
-
catch {
|
|
24
|
-
return [];
|
|
25
|
-
}
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Check if a file should be ignored based on project type and common patterns.
|
|
30
|
-
*
|
|
31
|
-
* @deprecated Use `isBuildArtifact()` from `source-filter.js` instead for artifact
|
|
32
|
-
* detection, or compose your own filter using `collectSourceFiles()`. This function
|
|
33
|
-
* is kept for backward compatibility.
|
|
34
|
-
*/
|
|
35
|
-
export function shouldIgnoreFile(filePath, isTsProject) {
|
|
36
|
-
const relPath = filePath.replace(/\\/g, "/");
|
|
37
|
-
// Use new source-filter module for artifact detection
|
|
38
|
-
if (isTsProject && isBuildArtifact(filePath))
|
|
39
|
-
return true;
|
|
40
|
-
// Legacy: simple JS check for non-TS projects (hand-written JS)
|
|
41
|
-
const isJs = relPath.endsWith(".js") ||
|
|
42
|
-
relPath.endsWith(".mjs") ||
|
|
43
|
-
relPath.endsWith(".cjs");
|
|
44
|
-
if (isTsProject && isJs)
|
|
45
|
-
return true;
|
|
46
|
-
// Ignore test scripts and common test patterns
|
|
47
|
-
if (isTestFile(filePath))
|
|
48
|
-
return true;
|
|
49
|
-
// Ignore hidden directories and common build outputs
|
|
50
|
-
const pathParts = relPath.split("/").filter(Boolean);
|
|
51
|
-
for (const segment of pathParts.slice(0, -1)) {
|
|
52
|
-
if (isExcludedDirName(segment))
|
|
53
|
-
return true;
|
|
54
|
-
}
|
|
55
|
-
return false;
|
|
56
|
-
}
|
|
1
|
+
import { collectSourceFiles, collectSourceFilesAsync, } from "./source-filter.js";
|
|
57
2
|
/**
|
|
58
3
|
* Recursively find source files in a directory, respecting common excludes.
|
|
59
4
|
*
|
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
* fully in scope.
|
|
55
55
|
*/
|
|
56
56
|
import { EXCLUDED_DIRS, getExcludedDirGlobs } from "./file-utils.js";
|
|
57
|
+
import { escapeRegExp } from "./string-utils.js";
|
|
57
58
|
/** Directory-name entries only — drops glob entries (e.g. `*.dSYM`) that a
|
|
58
59
|
* bare directory-name/regex exclude can't express. */
|
|
59
60
|
function literalExcludedDirNames() {
|
|
@@ -68,9 +69,6 @@ function literalExcludedDirNames() {
|
|
|
68
69
|
export function getScratchTreeGlobPatterns() {
|
|
69
70
|
return getExcludedDirGlobs();
|
|
70
71
|
}
|
|
71
|
-
function escapeRegExp(literal) {
|
|
72
|
-
return literal.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
73
|
-
}
|
|
74
72
|
/** Bare directory names, for tools (opengrep/semgrep `--exclude`) that treat a
|
|
75
73
|
* slash-free pattern as "this directory name, anywhere in the tree". */
|
|
76
74
|
export function getScratchTreeDirNames() {
|
|
@@ -71,6 +71,7 @@ export class SecurityScanClient {
|
|
|
71
71
|
logDurableAbsence(evidence, elapsedMs = 0) {
|
|
72
72
|
logAvailabilityDecision({
|
|
73
73
|
tool: this.toolName,
|
|
74
|
+
producer: "security-scan",
|
|
74
75
|
verdict: "unavailable",
|
|
75
76
|
outcome: "missing",
|
|
76
77
|
cause: "not-found",
|
|
@@ -154,6 +155,7 @@ export class SecurityScanClient {
|
|
|
154
155
|
this.log(`${this.toolName} found: ${probe.stdout.trim().split("\n")[0]}`);
|
|
155
156
|
logAvailabilityDecision({
|
|
156
157
|
tool: this.toolName,
|
|
158
|
+
producer: "security-scan",
|
|
157
159
|
verdict: "available",
|
|
158
160
|
outcome: "success",
|
|
159
161
|
cause: "ok",
|
|
@@ -185,6 +187,7 @@ export class SecurityScanClient {
|
|
|
185
187
|
: 0;
|
|
186
188
|
logAvailabilityDecision({
|
|
187
189
|
tool: this.toolName,
|
|
190
|
+
producer: "security-scan",
|
|
188
191
|
verdict: "unavailable",
|
|
189
192
|
outcome,
|
|
190
193
|
cause,
|
|
@@ -91,7 +91,7 @@ export function getActivePrimaryRoot() {
|
|
|
91
91
|
* `concurrent-secondary`: skip the destructive resets and the expensive
|
|
92
92
|
* battery, leave the registered primary's ctx/session id/root untouched. The
|
|
93
93
|
* root still gets served — `initLSPConfig` registers session roots lazily,
|
|
94
|
-
* per file (`clients/lsp/session-roots.ts
|
|
94
|
+
* per file (`clients/lsp/session-roots.ts`), not from this handler.
|
|
95
95
|
*
|
|
96
96
|
* Ordering note: the root check sits BELOW the `priorCtxActive === true`
|
|
97
97
|
* branch so a live sibling still reports the more specific
|
|
@@ -1,10 +1,42 @@
|
|
|
1
1
|
import { logLatency } from "./latency-logger.js";
|
|
2
|
+
import { getProcessSingleton } from "./process-singletons.js";
|
|
2
3
|
/**
|
|
3
4
|
* The complete observability path for a concurrent secondary. It deliberately
|
|
4
5
|
* emits one bind record only: secondary sessions skip every primary reset and
|
|
5
6
|
* hydration phase.
|
|
6
7
|
*/
|
|
8
|
+
// #2249: bounded per-session rollup of declined binds, counted at this shared
|
|
9
|
+
// seam so every decline the process's PRIMARY has seen this session —
|
|
10
|
+
// `concurrent-secondary` and `secondary-root` alike — is summarized in one row
|
|
11
|
+
// at session end instead of requiring a reader to hand-count
|
|
12
|
+
// `concurrent_session_bind` lines. Process-singleton backed (AGENTS.md catalog
|
|
13
|
+
// shape 25), NOT a module-scope `let` like the other `*_rollup` counters
|
|
14
|
+
// (bus-events-logger.ts, path-attribution-telemetry.ts): a `let` here exists
|
|
15
|
+
// once per module EVALUATION, not once per process, and #2146 measured one pid
|
|
16
|
+
// evaluating this exact graph nine times — a bare `let` would only ever see
|
|
17
|
+
// the binds routed through its own copy, undercounting every rollup that
|
|
18
|
+
// isn't reached through the first evaluation. `decideSessionStart` never
|
|
19
|
+
// returns a declined classification outside `concurrent-secondary`/
|
|
20
|
+
// `secondary-root` (session-lifecycle.ts), so those two are the whole
|
|
21
|
+
// contract; `unclassified` is a bounded third bucket for the legacy callers
|
|
22
|
+
// this function's `classification?` param still accepts.
|
|
23
|
+
const BIND_ROLLUP_FAMILY = "concurrent-session-bind-rollup";
|
|
24
|
+
const BIND_ROLLUP_VERSION = 1;
|
|
25
|
+
function bindRollupCounts() {
|
|
26
|
+
return getProcessSingleton(BIND_ROLLUP_FAMILY, BIND_ROLLUP_VERSION, () => ({
|
|
27
|
+
"concurrent-secondary": 0,
|
|
28
|
+
"secondary-root": 0,
|
|
29
|
+
unclassified: 0,
|
|
30
|
+
}));
|
|
31
|
+
}
|
|
32
|
+
function bindRollupKey(classification) {
|
|
33
|
+
return classification === "concurrent-secondary" ||
|
|
34
|
+
classification === "secondary-root"
|
|
35
|
+
? classification
|
|
36
|
+
: "unclassified";
|
|
37
|
+
}
|
|
7
38
|
export function logConcurrentSessionBind(args) {
|
|
39
|
+
bindRollupCounts()[bindRollupKey(args.classification)] += 1;
|
|
8
40
|
logLatency({
|
|
9
41
|
type: "phase",
|
|
10
42
|
filePath: "<pi-lens>",
|
|
@@ -13,3 +45,50 @@ export function logConcurrentSessionBind(args) {
|
|
|
13
45
|
metadata: args,
|
|
14
46
|
});
|
|
15
47
|
}
|
|
48
|
+
/** Snapshot of the current rollup counters, keyed by classification.
|
|
49
|
+
* Non-mutating — for tests/observability, mirroring
|
|
50
|
+
* `getBusEventRollupCounts`/`getVerifiedPathAttributionGuessCount`. */
|
|
51
|
+
export function getConcurrentSessionBindRollupCounts() {
|
|
52
|
+
return { ...bindRollupCounts() };
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Log one `concurrent_session_bind_rollup` row summarizing this session's
|
|
56
|
+
* declined binds by classification, then clear the counters. Call from
|
|
57
|
+
* index.ts's `session_shutdown` handler at the same primary-only placement as
|
|
58
|
+
* `emitBusEventRollupAtSessionEnd`/`emitVerifiedPathAttributionRollup` — a
|
|
59
|
+
* concurrent secondary's own shutdown returns before reaching that point, and
|
|
60
|
+
* the counters are process-wide state a still-live secondary would still need.
|
|
61
|
+
* A no-op when nothing was ever declined this session, matching those same
|
|
62
|
+
* rollups' "no noise on an ordinary session" shape.
|
|
63
|
+
*/
|
|
64
|
+
export function emitConcurrentSessionBindRollupAtSessionEnd(cwd) {
|
|
65
|
+
const counts = bindRollupCounts();
|
|
66
|
+
const total = counts["concurrent-secondary"] +
|
|
67
|
+
counts["secondary-root"] +
|
|
68
|
+
counts.unclassified;
|
|
69
|
+
if (total === 0)
|
|
70
|
+
return;
|
|
71
|
+
logLatency({
|
|
72
|
+
type: "phase",
|
|
73
|
+
filePath: cwd,
|
|
74
|
+
phase: "concurrent_session_bind_rollup",
|
|
75
|
+
durationMs: 0,
|
|
76
|
+
metadata: { ...counts },
|
|
77
|
+
});
|
|
78
|
+
resetConcurrentSessionBindRollupCounts();
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Session-boundary reset (AGENTS.md catalog shape 17). Call from index.ts's
|
|
82
|
+
* `session_start` handler on the PRIMARY continuation path only — never from
|
|
83
|
+
* a declined bind's own `session_start`, which is exactly what increments
|
|
84
|
+
* these counters, so resetting there would erase every prior sibling's tally
|
|
85
|
+
* from the same primary session. Covers the case a primary session never
|
|
86
|
+
* reaches `session_shutdown` (a crash, a forced kill) and the process's next
|
|
87
|
+
* primary must still start from zero. Also exported for tests.
|
|
88
|
+
*/
|
|
89
|
+
export function resetConcurrentSessionBindRollupCounts() {
|
|
90
|
+
const counts = bindRollupCounts();
|
|
91
|
+
counts["concurrent-secondary"] = 0;
|
|
92
|
+
counts["secondary-root"] = 0;
|
|
93
|
+
counts.unclassified = 0;
|
|
94
|
+
}
|
|
@@ -1,30 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Session Summary — generates turn_end and session-end summaries
|
|
3
3
|
*/
|
|
4
|
-
export function formatSessionSummary(stats) {
|
|
5
|
-
if (stats.totalShown === 0)
|
|
6
|
-
return "";
|
|
7
|
-
const lines = [
|
|
8
|
-
"## Diagnostic Summary",
|
|
9
|
-
"",
|
|
10
|
-
`Shown to agent: ${stats.totalShown}`,
|
|
11
|
-
`Auto-fixed: ${stats.totalAutoFixed} (${pct(stats.totalAutoFixed, stats.totalShown)}%)`,
|
|
12
|
-
`Fixed by agent: ${stats.totalAgentFixed} (${pct(stats.totalAgentFixed, stats.totalShown)}%)`,
|
|
13
|
-
"",
|
|
14
|
-
];
|
|
15
|
-
if (stats.topViolations.length > 0) {
|
|
16
|
-
lines.push("Top violations:");
|
|
17
|
-
for (const { ruleId, count } of stats.topViolations.slice(0, 5)) {
|
|
18
|
-
lines.push(` - ${ruleId} (${count}x)`);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
return lines.join("\n");
|
|
22
|
-
}
|
|
23
|
-
function pct(part, total) {
|
|
24
|
-
if (total === 0)
|
|
25
|
-
return "0";
|
|
26
|
-
return Math.round((part / total) * 100).toString();
|
|
27
|
-
}
|
|
28
4
|
export function formatSlopScoreSummary(summary) {
|
|
29
5
|
if (summary.totalRuleDiagnostics === 0 || summary.totalKlocWritten <= 0) {
|
|
30
6
|
return "";
|
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
import * as path from "node:path";
|
|
2
2
|
import { isTestMode } from "./env-utils.js";
|
|
3
|
-
import {
|
|
3
|
+
import { getGlobalPiLensLogDir } from "./probe-home-state.js";
|
|
4
|
+
import { getMaxLogSizeMB } from "./log-cleanup.js";
|
|
4
5
|
import { createNdjsonLogger } from "./ndjson-logger.js";
|
|
5
|
-
export const SESSIONSTART_LOG_FILE = path.join(
|
|
6
|
+
export const SESSIONSTART_LOG_FILE = path.join(getGlobalPiLensLogDir(), "sessionstart.log");
|
|
6
7
|
// All ordinary writers share this queue, preserving their in-process order.
|
|
7
|
-
|
|
8
|
+
// Bounded like every other global sink (#2505): an unbounded sink has no
|
|
9
|
+
// size check on the write path at all, so it grows until the
|
|
10
|
+
// once-per-process session-start sweep happens to look at it — which, in a
|
|
11
|
+
// long-lived process (the warm MCP server), may be never.
|
|
12
|
+
const writer = createNdjsonLogger({
|
|
13
|
+
filePath: SESSIONSTART_LOG_FILE,
|
|
14
|
+
maxBytes: getMaxLogSizeMB() * 1024 * 1024,
|
|
15
|
+
backupPath: `${SESSIONSTART_LOG_FILE}.1`,
|
|
16
|
+
});
|
|
8
17
|
export function logSessionStart(message) {
|
|
9
18
|
if (isTestMode())
|
|
10
19
|
return;
|
|
@@ -8,8 +8,13 @@ import { findLocalToolConfig } from "./path-utils.js";
|
|
|
8
8
|
// ast-grep's root config marker. The `ast-grep lsp` server is workspace-gated:
|
|
9
9
|
// it only operates in a project that has an `sgconfig.y[a]ml` at (or above) the
|
|
10
10
|
// file. These are the names ast-grep itself looks for as root markers.
|
|
11
|
-
|
|
12
|
-
/**
|
|
11
|
+
const SGCONFIG_NAMES = ["sgconfig.yml", "sgconfig.yaml"];
|
|
12
|
+
/**
|
|
13
|
+
* Nearest `sgconfig.y[a]ml` walking up from `startDir`, or undefined if none.
|
|
14
|
+
* Deliberately UNCEILINGED at $HOME (refs #2472 review round 3, F1): ast-grep
|
|
15
|
+
* itself resolves `~/sgconfig.yml` as a legitimate global root config, not an
|
|
16
|
+
* escaped-workspace accident.
|
|
17
|
+
*/
|
|
13
18
|
export function findLocalSgconfig(startDir) {
|
|
14
19
|
return findLocalToolConfig(startDir, SGCONFIG_NAMES);
|
|
15
20
|
}
|
|
@@ -60,10 +65,6 @@ export function getAstGrepRuleSources(projectRoot = process.cwd()) {
|
|
|
60
65
|
return true;
|
|
61
66
|
});
|
|
62
67
|
}
|
|
63
|
-
/** Compatibility export retained for callers that only need ordered dirs. */
|
|
64
|
-
export function shippedRuleDirsInPrecedenceOrder(projectRoot = process.cwd()) {
|
|
65
|
-
return getAstGrepRuleSources(projectRoot).map((source) => source.dir);
|
|
66
|
-
}
|
|
67
68
|
function findYamlFiles(dir) {
|
|
68
69
|
const files = [];
|
|
69
70
|
let entries;
|
|
@@ -115,7 +115,7 @@ function isCleanDryRun(argsAfterVerb) {
|
|
|
115
115
|
* replacement for the forbidden `git stash`. Blocking it would push
|
|
116
116
|
* operators back toward stash.
|
|
117
117
|
*/
|
|
118
|
-
|
|
118
|
+
const WORKTREE_MUTATING_GIT_MATCHER = {
|
|
119
119
|
id: "worktree-mutating",
|
|
120
120
|
indirectAlwaysMatches: false,
|
|
121
121
|
// `git checkout --help` opens documentation and changes nothing. This
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolves the skills directory the `resources_discover` handler (#205)
|
|
3
|
+
* registers, and reports the one condition that pi previously loaded with NO
|
|
4
|
+
* visible signal: `<packageRoot>/skills` is absent, unreadable, or holds no
|
|
5
|
+
* skill pi's own loader would find (#2626).
|
|
6
|
+
*
|
|
7
|
+
* `resolvePackagePath(import.meta.url, "skills")`-equivalent resolution
|
|
8
|
+
* (`clients/package-root.ts`'s `getPackageRoot`) is correct for both the
|
|
9
|
+
* source and compiled `dist/` layouts — it walks up from the loaded entry
|
|
10
|
+
* file to the nearest `package.json`. It goes wrong silently, not loudly,
|
|
11
|
+
* when that walk lands somewhere with no `skills/` beside it: `skills/`
|
|
12
|
+
* missing from an installed package, or the entry file copied out of the
|
|
13
|
+
* package tree by a managed extension cache so the nearest `package.json`
|
|
14
|
+
* is the cache's own. Either way `resources_discover` used to hand pi a
|
|
15
|
+
* path that does not exist, `pi` registered zero skills, and nothing — no
|
|
16
|
+
* extension error, no stderr line — said so (investigated on #2587).
|
|
17
|
+
*
|
|
18
|
+
* #2626 review round 2, F1: the FIRST version of this fix inverted the
|
|
19
|
+
* acceptance criterion — it returned `[]` (no skills registered) whenever
|
|
20
|
+
* its own predicate disagreed with pi's real loader, which is worse than
|
|
21
|
+
* the bug it fixed on every layout the predicate got wrong (dropping skills
|
|
22
|
+
* pi WOULD have loaded, a regression vs. pre-fix `master`). The acceptance
|
|
23
|
+
* criteria ask for a RECORD, never a changed return value: this module
|
|
24
|
+
* returns `[skillsDir]` UNCONDITIONALLY, exactly like the pre-fix handler —
|
|
25
|
+
* pi's own `loadSkills`/`collectSkillEntries` already treat a nonexistent
|
|
26
|
+
* path as zero skills from that entry, gracefully, so handing it a path
|
|
27
|
+
* that turns out to be empty is exactly as safe as `master`'s behavior
|
|
28
|
+
* always was. The health check below is PURELY observational.
|
|
29
|
+
*
|
|
30
|
+
* #2636 review F4: the ENOENT/EACCES classification shell below used to be
|
|
31
|
+
* hand-rolled here, character-identical to the ast-grep/tree-sitter sites
|
|
32
|
+
* #2636 fixed for the same silent-zero shape — now shared via
|
|
33
|
+
* `bundled-resource-health.ts`, with `scanEntriesForSkills` supplied as this
|
|
34
|
+
* module's own "what counts as found" predicate.
|
|
35
|
+
*/
|
|
36
|
+
import * as path from "node:path";
|
|
37
|
+
import { fileURLToPath } from "node:url";
|
|
38
|
+
import * as fs from "node:fs";
|
|
39
|
+
import { scanEntriesForSkills } from "../scripts/lib/skills-predicate.mjs";
|
|
40
|
+
import { classifyBundledResourceDir, describeBundledResourceHealth, reportBundledResourceDirHealth, } from "./bundled-resource-health.js";
|
|
41
|
+
import { logLatency } from "./latency-logger.js";
|
|
42
|
+
import { getPackageRoot } from "./package-root.js";
|
|
43
|
+
/** The ledger kind this module records under (`clients/degradation-ledger.ts`). */
|
|
44
|
+
const SKILLS_DIR_MISSING_KIND = "skills-dir-missing";
|
|
45
|
+
/**
|
|
46
|
+
* Read `skillsDir` and classify it, sharing `classifyBundledResourceDir`'s
|
|
47
|
+
* ENOENT/EACCES/empty shell but counting pi-LOADABLE skill entry points
|
|
48
|
+
* (`scanEntriesForSkills`), not a bare directory listing — a `skills/`
|
|
49
|
+
* holding only a stray `.gitkeep` must read "empty", not "healthy".
|
|
50
|
+
*/
|
|
51
|
+
function checkSkillsHealth(skillsDir) {
|
|
52
|
+
return classifyBundledResourceDir(skillsDir, (dir) => {
|
|
53
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
54
|
+
return scanEntriesForSkills(dir, entries, true).length;
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Resolve the skill path for `resources_discover`. ALWAYS returns
|
|
59
|
+
* `[skillsDir]` (see the module doc for why — F1). When `skillsDir` is
|
|
60
|
+
* absent, unreadable, or holds no skill pi's loader would find, records ONE
|
|
61
|
+
* bounded `skills-dir-missing` degradation and a single `notifyUserDegradation`
|
|
62
|
+
* warning, both naming the resolved path and the entry file's directory.
|
|
63
|
+
*
|
|
64
|
+
* Either way, one `skills_resolved` phase/latency record is written so an
|
|
65
|
+
* empty ledger (no `skills-dir-missing` row) is distinguishable from
|
|
66
|
+
* "`resources_discover` never ran at all" (#2626 review F5) — the SAME
|
|
67
|
+
* silent-zero shape one level up the call stack.
|
|
68
|
+
*/
|
|
69
|
+
export function resolveSkillPaths(importMetaUrl) {
|
|
70
|
+
const packageRoot = getPackageRoot(importMetaUrl);
|
|
71
|
+
const skillsDir = path.join(packageRoot, "skills");
|
|
72
|
+
const health = checkSkillsHealth(skillsDir);
|
|
73
|
+
logLatency({
|
|
74
|
+
type: "phase",
|
|
75
|
+
phase: "skills_resolved",
|
|
76
|
+
filePath: skillsDir,
|
|
77
|
+
durationMs: 0,
|
|
78
|
+
metadata: {
|
|
79
|
+
status: health.status,
|
|
80
|
+
entryCount: health.status === "healthy" ? health.entryCount : 0,
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
if (health.status !== "healthy") {
|
|
84
|
+
const entryDir = path.dirname(fileURLToPath(importMetaUrl));
|
|
85
|
+
const reason = `${describeBundledResourceHealth(health, skillsDir, `no SKILL.md (or loadable .md) found under ${skillsDir}`)} (entry loaded from ${entryDir})`;
|
|
86
|
+
// #2626 review F3: the notify-once gate previously re-derived "have we
|
|
87
|
+
// already recorded this" by scanning `getDegradationSummary()` and
|
|
88
|
+
// comparing the RAW `skillsDir` against subjects the ledger stores
|
|
89
|
+
// `truncateForLedger`-ed — a mismatch on any subject over
|
|
90
|
+
// `LEDGER_FIELD_MAX` (200 chars, an ordinary length for a managed-cache
|
|
91
|
+
// path) renotified on every call. `reportBundledResourceDirHealth`
|
|
92
|
+
// reads `incrementDegradationCount`'s own return value for the rising
|
|
93
|
+
// edge, computed after the SAME truncation the ledger stores by, so
|
|
94
|
+
// there is no separate key to keep in sync.
|
|
95
|
+
// #2636 review round 2, F1: the shipped notify sentence ("registers
|
|
96
|
+
// zero skills") is user-visible product text #2626 chose deliberately
|
|
97
|
+
// — it names the exact SYMPTOM this whole issue exists to surface, so
|
|
98
|
+
// the shared helper's generic "<label> unavailable" template must
|
|
99
|
+
// never silently replace it. Passed explicitly rather than inferred
|
|
100
|
+
// from `label` so this stays a per-caller decision, not a convention
|
|
101
|
+
// the next caller has to remember.
|
|
102
|
+
reportBundledResourceDirHealth(SKILLS_DIR_MISSING_KIND, skillsDir, health, "skills", reason, `pi-lens: registers zero skills — ${reason}.`);
|
|
103
|
+
}
|
|
104
|
+
return [skillsDir];
|
|
105
|
+
}
|
|
@@ -55,14 +55,14 @@
|
|
|
55
55
|
*/
|
|
56
56
|
import * as fs from "node:fs";
|
|
57
57
|
import * as path from "node:path";
|
|
58
|
-
import {
|
|
58
|
+
import { getGlobalPiLensLogDir } from "./probe-home-state.js";
|
|
59
59
|
/** Bounded tail-read budget PER source log file — never a full-file scan. */
|
|
60
60
|
export const SMELLS_TAIL_BYTES_PER_FILE = 64 * 1024;
|
|
61
|
-
|
|
61
|
+
const SMELLS_ROLLING_WINDOW_MS = 24 * 60 * 60_000;
|
|
62
62
|
/** Re-check cadence at `turn_end`, mirroring `memory-sampler.ts`'s pattern —
|
|
63
63
|
* cheap enough (bounded ~128KB I/O) not to need finer throttling, but a
|
|
64
64
|
* fixed interval keeps it from running on every single turn. */
|
|
65
|
-
|
|
65
|
+
const SMELLS_TURN_CHECK_INTERVAL = 20;
|
|
66
66
|
/** Trivial threshold constants (#1123 item 3's explicit design ask). Counts
|
|
67
67
|
* strictly below these never surface anywhere. */
|
|
68
68
|
export const SMELLS_THRESHOLDS = {
|
|
@@ -159,7 +159,7 @@ function isOpengrepRespawn(entry) {
|
|
|
159
159
|
* `2 * SMELLS_TAIL_BYTES_PER_FILE` regardless of how large the (size-rotated,
|
|
160
160
|
* up to ~10MB) source files are. `root` is injectable for tests.
|
|
161
161
|
*/
|
|
162
|
-
export function countRecentSmells(root =
|
|
162
|
+
export function countRecentSmells(root = getGlobalPiLensLogDir(), sessionStartMs) {
|
|
163
163
|
const sinceMs = sessionStartMs ?? Date.now() - SMELLS_ROLLING_WINDOW_MS;
|
|
164
164
|
const busTail = tailReadText(path.join(root, "bus-events.log"), SMELLS_TAIL_BYTES_PER_FILE);
|
|
165
165
|
const latencyTail = tailReadText(path.join(root, "latency.log"), SMELLS_TAIL_BYTES_PER_FILE);
|
|
@@ -16,7 +16,7 @@ import { isAtOrAboveHomeDir } from "./path-utils.js";
|
|
|
16
16
|
import { getStartupScanMaxSourceFilesDerived } from "./project-scale.js";
|
|
17
17
|
import { shouldRecurseIntoDir, walkTreeStackAsync, walkTreeStackSync, } from "./source-walker.js";
|
|
18
18
|
import { getDirectoryMarkers, registerWorkspaceTopologyReset, } from "./workspace-topology.js";
|
|
19
|
-
|
|
19
|
+
const PROJECT_ROOT_MARKERS = [
|
|
20
20
|
".git",
|
|
21
21
|
"package.json",
|
|
22
22
|
"pyproject.toml",
|
|
@@ -24,16 +24,8 @@ export const PROJECT_ROOT_MARKERS = [
|
|
|
24
24
|
"go.mod",
|
|
25
25
|
"composer.json",
|
|
26
26
|
];
|
|
27
|
-
// Deprecated (#776): no longer read directly below — `computeStartupScanContext`
|
|
28
|
-
// / `resolveStartupScanContextAsync` now default `maxSourceFiles` to
|
|
29
|
-
// `getStartupScanMaxSourceFilesDerived(cwd)` (project-scale.ts's
|
|
30
|
-
// `maxProjectFiles` knob), which reproduces this same 2,000 value at the
|
|
31
|
-
// default base. Kept exported for tests/callers that still reference the
|
|
32
|
-
// literal.
|
|
33
|
-
export const MAX_STARTUP_SOURCE_FILES = 2000;
|
|
34
27
|
// #758: hard ceiling on the number of directory entries the startup source
|
|
35
28
|
// count walk will visit before it gives up and declares the tree too big to
|
|
36
|
-
// warm. The source-file early-exit (MAX_STARTUP_SOURCE_FILES) only fires when
|
|
37
29
|
// a project has MANY source files — a repo with FEW source files but a huge
|
|
38
30
|
// pile of non-source files (e.g. a game mod: 300 scripts among 84k data files)
|
|
39
31
|
// never trips it, so the pre-#758 walk traversed the entire tree, dominated by
|
|
@@ -77,7 +69,7 @@ export const _resetStartupScanMaxEntriesForTests = _maxEntries._resetForTests;
|
|
|
77
69
|
*
|
|
78
70
|
* The content-derived reasons `too-many-source-files` and `too-many-entries`
|
|
79
71
|
* (#758) are the ones that are TTL'd. They can go stale on their own: the repo
|
|
80
|
-
* can shrink below
|
|
72
|
+
* can shrink below the source-file cap (or below the entry ceiling)
|
|
81
73
|
* between sessions, and nothing else would notice
|
|
82
74
|
* — the seq-based freshness check that guards every other
|
|
83
75
|
* `project-snapshot.json` field never fires for them, because pi-lens never
|
|
@@ -18,3 +18,16 @@
|
|
|
18
18
|
export function compareOrdinal(a, b) {
|
|
19
19
|
return a < b ? -1 : a > b ? 1 : 0;
|
|
20
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* Escape a string for safe interpolation into a `RegExp` source, so every
|
|
23
|
+
* regex metacharacter it contains is matched literally instead of taking on
|
|
24
|
+
* its regex meaning. This is the ONE runtime copy (#2558) — string-utils.ts
|
|
25
|
+
* is a leaf (no imports of its own), so importing it never creates a cycle.
|
|
26
|
+
* Before #2558 this same body was hand-copied under this name (and as
|
|
27
|
+
* `escapeRegExpChar`/`escapeRegExpLiteral`) into ~8 production modules and 3
|
|
28
|
+
* test helpers; fold new call sites onto this export instead of re-copying
|
|
29
|
+
* it.
|
|
30
|
+
*/
|
|
31
|
+
export function escapeRegExp(value) {
|
|
32
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
33
|
+
}
|