@herbertgao/pi-extensions 2026.8.5 → 2026.8.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +2 -2
- package/node_modules/@herbertgao/pi-cc-extensions/README.md +2 -2
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +19 -7
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +30 -9
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/compact-thinking.ts +272 -22
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +74 -5
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +94 -77
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/markdown-enhance.ts +48 -6
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/message-display.ts +1 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/hover.ts +14 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +55 -17
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/layout.ts +41 -2
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-renderer.ts +75 -6
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/types.ts +7 -3
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +64 -1
- package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
- package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +16 -0
- package/node_modules/@herbertgao/pi-subagents/README.md +30 -22
- package/node_modules/@herbertgao/pi-subagents/examples/agent-tool-description.md +5 -5
- package/node_modules/@herbertgao/pi-subagents/package.json +7 -7
- package/node_modules/@herbertgao/pi-subagents/src/agent-file-toggle.ts +7 -1
- package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +48 -19
- package/node_modules/@herbertgao/pi-subagents/src/agent-runner.ts +22 -15
- package/node_modules/@herbertgao/pi-subagents/src/custom-agents.ts +26 -2
- package/node_modules/@herbertgao/pi-subagents/src/index.ts +219 -40
- package/node_modules/@herbertgao/pi-subagents/src/invocation-config.ts +101 -3
- package/node_modules/@herbertgao/pi-subagents/src/nested-tools.ts +18 -4
- package/node_modules/@herbertgao/pi-subagents/src/settings.ts +99 -0
- package/node_modules/@herbertgao/pi-subagents/src/types.ts +22 -3
- package/node_modules/@herbertgao/pi-subagents/src/ui/agent-widget.ts +51 -3
- package/node_modules/@herbertgao/pi-subagents/src/ui/conversation-viewer.ts +20 -2
- package/node_modules/@herbertgao/pi-subagents/src/ui/fleet-list.ts +34 -10
- package/node_modules/@herbertgao/pi-subagents/src/usage.ts +129 -1
- package/node_modules/@herbertgao/pi-subagents/src/worktree.ts +29 -5
- package/node_modules/@juicesharp/rpiv-ask-user-question/README.md +3 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/ask-user-question.ts +46 -10
- package/node_modules/@juicesharp/rpiv-ask-user-question/config.ts +25 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/configuration.md +13 -4
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/hosts.md +8 -1
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/localization.md +3 -1
- package/node_modules/@juicesharp/rpiv-ask-user-question/locales/en.json +2 -2
- package/node_modules/@juicesharp/rpiv-ask-user-question/locales/zh.json +2 -2
- package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +3 -2
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/build-questionnaire.ts +10 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/key-router.ts +3 -1
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/questionnaire-session.ts +30 -7
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/state.ts +14 -6
- package/node_modules/@juicesharp/rpiv-ask-user-question/view/dialog-builder.ts +30 -4
- package/node_modules/@juicesharp/rpiv-ask-user-question/view/tab-content-strategy.ts +26 -5
- package/node_modules/@narumitw/pi-btw/README.md +119 -103
- package/node_modules/@narumitw/pi-btw/dist/index.ts +2898 -0
- package/node_modules/@narumitw/pi-btw/dist/index.ts.map +7 -0
- package/node_modules/@narumitw/pi-btw/package.json +13 -9
- package/node_modules/@narumitw/pi-btw/src/btw.ts +40 -42
- package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +55 -10
- package/node_modules/@narumitw/pi-btw/src/main-tree-picker.ts +390 -0
- package/node_modules/@narumitw/pi-btw/src/menu.ts +78 -15
- package/node_modules/@narumitw/pi-btw/src/settings.ts +22 -2
- package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +136 -45
- package/node_modules/pi-lens/CHANGELOG.md +1004 -0
- package/node_modules/pi-lens/README.md +11 -3
- package/node_modules/pi-lens/config/ruff/core.toml +42 -0
- package/node_modules/pi-lens/dist/clients/actionable-warnings.js +130 -27
- package/node_modules/pi-lens/dist/clients/advisory-provenance.js +427 -0
- package/node_modules/pi-lens/dist/clients/agent-nudge.js +79 -16
- package/node_modules/pi-lens/dist/clients/ast-grep-client.js +9 -3
- package/node_modules/pi-lens/dist/clients/atomic-write.js +9 -3
- package/node_modules/pi-lens/dist/clients/bash-file-access.js +285 -8
- package/node_modules/pi-lens/dist/clients/biome-client.js +176 -37
- package/node_modules/pi-lens/dist/clients/blocker-freshness.js +428 -0
- package/node_modules/pi-lens/dist/clients/blocker-past-eof.js +119 -0
- package/node_modules/pi-lens/dist/clients/bootstrap.js +12 -1
- package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +12 -3
- package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +192 -0
- package/node_modules/pi-lens/dist/clients/bus-events-logger.js +62 -6
- package/node_modules/pi-lens/dist/clients/bus-publish.js +11 -3
- package/node_modules/pi-lens/dist/clients/cascade-budget.js +196 -0
- package/node_modules/pi-lens/dist/clients/cascade-format.js +76 -2
- package/node_modules/pi-lens/dist/clients/cascade-types.js +9 -1
- package/node_modules/pi-lens/dist/clients/child-unref.js +54 -6
- package/node_modules/pi-lens/dist/clients/code-quality-warnings.js +76 -24
- package/node_modules/pi-lens/dist/clients/console-guard-install.js +16 -4
- package/node_modules/pi-lens/dist/clients/dead-code-client.js +249 -52
- package/node_modules/pi-lens/dist/clients/deadline-utils.js +8 -1
- package/node_modules/pi-lens/dist/clients/debug-handles.js +5 -0
- package/node_modules/pi-lens/dist/clients/degradation-ledger.js +62 -13
- package/node_modules/pi-lens/dist/clients/dependency-checker.js +43 -9
- package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +153 -37
- package/node_modules/pi-lens/dist/clients/diagnostic-line-freshness.js +298 -0
- package/node_modules/pi-lens/dist/clients/diagnostics-publish.js +10 -3
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +165 -11
- package/node_modules/pi-lens/dist/clients/dispatch/integration.js +325 -72
- package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +7 -4
- package/node_modules/pi-lens/dist/clients/dispatch/plan.js +5 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +234 -18
- package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +187 -19
- package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +6 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/credo.js +11 -9
- package/node_modules/pi-lens/dist/clients/dispatch/runners/cue-vet.js +398 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +11 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +12 -7
- package/node_modules/pi-lens/dist/clients/dispatch/runners/go-vet.js +18 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +895 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/index.js +4 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +16 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +81 -41
- package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +16 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +23 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +331 -55
- package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +38 -5
- package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +97 -19
- package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +14 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +20 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +22 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.js +10 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +18 -6
- package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +73 -12
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +488 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +84 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/lazy-installer.js +260 -27
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +943 -93
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +86 -11
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/tool-failure.js +72 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +106 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +9 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +18 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +4 -2
- package/node_modules/pi-lens/dist/clients/disposition-publish.js +10 -3
- package/node_modules/pi-lens/dist/clients/eval-timestamp.js +17 -0
- package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +28 -5
- package/node_modules/pi-lens/dist/clients/extension-log.js +317 -3
- package/node_modules/pi-lens/dist/clients/file-kinds.js +8 -2
- package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +294 -0
- package/node_modules/pi-lens/dist/clients/finding-identity.js +88 -0
- package/node_modules/pi-lens/dist/clients/fix-worklog.js +5 -1
- package/node_modules/pi-lens/dist/clients/format-events-publish.js +39 -8
- package/node_modules/pi-lens/dist/clients/formatters-lazy.js +3 -2
- package/node_modules/pi-lens/dist/clients/formatters.js +500 -115
- package/node_modules/pi-lens/dist/clients/generation-guard.js +216 -0
- package/node_modules/pi-lens/dist/clients/git-guard.js +49 -21
- package/node_modules/pi-lens/dist/clients/gitleaks-client.js +181 -8
- package/node_modules/pi-lens/dist/clients/go-client.js +21 -39
- package/node_modules/pi-lens/dist/clients/govulncheck-client.js +219 -10
- package/node_modules/pi-lens/dist/clients/grammar-source.js +333 -10
- package/node_modules/pi-lens/dist/clients/host-ports.js +9 -1
- package/node_modules/pi-lens/dist/clients/installer/index.js +1119 -101
- package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh-session.js +58 -0
- package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh.js +715 -0
- package/node_modules/pi-lens/dist/clients/instance-reaper.js +643 -97
- package/node_modules/pi-lens/dist/clients/instance-registry.js +87 -17
- package/node_modules/pi-lens/dist/clients/jscpd-client.js +86 -15
- package/node_modules/pi-lens/dist/clients/knip-client.js +361 -24
- package/node_modules/pi-lens/dist/clients/language-policy.js +8 -2
- package/node_modules/pi-lens/dist/clients/language-profile.js +2 -0
- package/node_modules/pi-lens/dist/clients/latency-logger.js +487 -9
- package/node_modules/pi-lens/dist/clients/lazy-import.js +21 -0
- package/node_modules/pi-lens/dist/clients/ledger-bounds.js +21 -0
- package/node_modules/pi-lens/dist/clients/lens-events.js +56 -25
- package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +16 -0
- package/node_modules/pi-lens/dist/clients/live-bus-emitter.js +45 -2
- package/node_modules/pi-lens/dist/clients/lsp/aggregation.js +30 -4
- package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +160 -20
- package/node_modules/pi-lens/dist/clients/lsp/client.js +1666 -148
- package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +111 -0
- package/node_modules/pi-lens/dist/clients/lsp/document-drift.js +389 -0
- package/node_modules/pi-lens/dist/clients/lsp/index.js +2496 -171
- package/node_modules/pi-lens/dist/clients/lsp/inferred-project.js +215 -0
- package/node_modules/pi-lens/dist/clients/lsp/jvm-runtime.js +146 -14
- package/node_modules/pi-lens/dist/clients/lsp/language.js +48 -4
- package/node_modules/pi-lens/dist/clients/lsp/server.js +517 -69
- package/node_modules/pi-lens/dist/clients/lsp/spawn-history.js +22 -0
- package/node_modules/pi-lens/dist/clients/lsp/sync-kind.js +43 -0
- package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +172 -0
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/classification.js +21 -5
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +61 -3
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +422 -28
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-session.js +30 -0
- package/node_modules/pi-lens/dist/clients/lsp/workspace-sweep-hold.js +175 -0
- package/node_modules/pi-lens/dist/clients/lsp-lazy.js +3 -2
- package/node_modules/pi-lens/dist/clients/mcp/analyze.js +4 -0
- package/node_modules/pi-lens/dist/clients/mcp/session.js +39 -18
- package/node_modules/pi-lens/dist/clients/model-provider.js +53 -0
- package/node_modules/pi-lens/dist/clients/module-report.js +8 -0
- package/node_modules/pi-lens/dist/clients/opengrep-client.js +15 -1
- package/node_modules/pi-lens/dist/clients/package-manager.js +170 -14
- package/node_modules/pi-lens/dist/clients/path-attribution-telemetry.js +27 -0
- package/node_modules/pi-lens/dist/clients/path-utils.js +160 -0
- package/node_modules/pi-lens/dist/clients/pipeline.js +178 -30
- package/node_modules/pi-lens/dist/clients/post-autofix-notice.js +37 -0
- package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +17 -3
- package/node_modules/pi-lens/dist/clients/project-diagnostics/extractors.js +89 -22
- package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +85 -15
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +15 -3
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +23 -2
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/trivy.js +50 -2
- package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +5 -0
- package/node_modules/pi-lens/dist/clients/project-lens-config.js +3 -0
- package/node_modules/pi-lens/dist/clients/project-snapshot.js +299 -0
- package/node_modules/pi-lens/dist/clients/quiet-window-config.js +47 -0
- package/node_modules/pi-lens/dist/clients/quiet-window.js +11 -25
- package/node_modules/pi-lens/dist/clients/read-guard-logger.js +1 -1
- package/node_modules/pi-lens/dist/clients/read-guard.js +184 -10
- package/node_modules/pi-lens/dist/clients/resource-sampler.js +49 -17
- package/node_modules/pi-lens/dist/clients/reverse-deps.js +50 -11
- package/node_modules/pi-lens/dist/clients/review-graph/query.js +76 -4
- package/node_modules/pi-lens/dist/clients/run-duration.js +55 -0
- package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +248 -13
- package/node_modules/pi-lens/dist/clients/runtime-context.js +112 -12
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +472 -61
- package/node_modules/pi-lens/dist/clients/runtime-session.js +359 -13
- package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +217 -22
- package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +269 -22
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +948 -87
- package/node_modules/pi-lens/dist/clients/rust-client.js +21 -37
- package/node_modules/pi-lens/dist/clients/safe-spawn.js +220 -7
- package/node_modules/pi-lens/dist/clients/scratch-tree-policy.js +161 -0
- package/node_modules/pi-lens/dist/clients/search-read-registration.js +34 -6
- package/node_modules/pi-lens/dist/clients/security-scan-client.js +224 -8
- package/node_modules/pi-lens/dist/clients/sg-runner.js +249 -37
- package/node_modules/pi-lens/dist/clients/single-flight.js +158 -0
- package/node_modules/pi-lens/dist/clients/smells-rollup.js +18 -11
- package/node_modules/pi-lens/dist/clients/stale-marker.js +17 -0
- package/node_modules/pi-lens/dist/clients/startup-timing.js +26 -2
- package/node_modules/pi-lens/dist/clients/test-runner-client.js +574 -32
- package/node_modules/pi-lens/dist/clients/tool-event.js +56 -5
- package/node_modules/pi-lens/dist/clients/tool-policy.js +127 -20
- package/node_modules/pi-lens/dist/clients/tool-set-policy.js +76 -0
- package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +75 -1
- package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +769 -64
- package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +11 -0
- package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +90 -0
- package/node_modules/pi-lens/dist/clients/trivy-client.js +19 -1
- package/node_modules/pi-lens/dist/clients/warm-attach.js +17 -0
- package/node_modules/pi-lens/dist/clients/widget-state.js +336 -36
- package/node_modules/pi-lens/dist/clients/word-index.js +305 -33
- package/node_modules/pi-lens/dist/clients/zizmor-config.js +214 -14
- package/node_modules/pi-lens/dist/index.js +64677 -49484
- package/node_modules/pi-lens/dist/mcp/server.js +8 -2
- package/node_modules/pi-lens/dist/tools/activate-tools.js +17 -5
- package/node_modules/pi-lens/dist/tools/ast-grep-replace.js +9 -4
- package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +5 -2
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +469 -56
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +190 -46
- package/node_modules/pi-lens/dist/tools/lsp-navigation.js +46 -7
- package/node_modules/pi-lens/dist/tools/symbol-search.js +1 -1
- package/node_modules/pi-lens/docs/agent-guide.md +44 -14
- package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +518 -501
- package/node_modules/pi-lens/docs/dispositions.md +21 -0
- package/node_modules/pi-lens/docs/features.md +33 -6
- package/node_modules/pi-lens/docs/globalconfig.md +14 -0
- package/node_modules/pi-lens/docs/language-coverage.md +71 -5
- package/node_modules/pi-lens/docs/mcp.md +2 -2
- package/node_modules/pi-lens/docs/servercapabilities.md +4 -1
- package/node_modules/pi-lens/docs/settings.md +25 -1
- package/node_modules/pi-lens/docs/usage.md +24 -5
- package/node_modules/pi-lens/docs/word-index.md +35 -0
- package/node_modules/pi-lens/package.json +10 -6
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/no-reflect-get-js-snapshot.yml +23 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/no-reflect-get-snapshot.yml +23 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/ts-void-zero-snapshot.yml +23 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-bare-object-param-test.yml +16 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-chained-type-assertions-test.yml +22 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-compile-call-test.yml +29 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-conditional-empty-object-spread-js-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-conditional-empty-object-spread-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-dupe-class-members-test.yml +33 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-inner-html-js-test.yml +7 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-inner-html-test.yml +7 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-known-value-widening-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-non-null-assertion-test.yml +216 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-js-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-js-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-return-value-in-generator-test.yml +12 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-runtime-typeof-test.yml +33 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-server-bind-wildcard-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-shape-in-symbol-names-test.yml +13 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-sql-in-code-js-test.yml +5 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-sql-in-code-test.yml +5 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-laundering-test.yml +11 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-parameters-test.yml +12 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-returns-test.yml +16 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unsafe-dictionary-any-test.yml +10 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unsafe-dictionary-unknown-test.yml +8 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/redundant-unsafe-function-test.yml +35 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/require-safety-comment-for-as-unknown-as-test.yml +177 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/ts-void-zero-test.yml +1 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-await-expression-member-js.yml +13 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-await-expression-member.yml +13 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-host-path-in-win32-branch.yml +2 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-object-param.yml +60 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-chained-type-assertions.yml +66 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-compile-call.yml +63 -5
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-conditional-empty-object-spread-js.yml +21 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-conditional-empty-object-spread.yml +29 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-dupe-class-members.yml +52 -8
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-inner-html-js.yml +27 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-inner-html.yml +27 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-known-value-widening.yml +71 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-non-null-assertion.yml +316 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-raw-json-store-write.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply-js.yml +29 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply.yml +30 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get-js.yml +41 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get.yml +42 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-return-value-in-generator.yml +22 -5
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-runtime-typeof.yml +121 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-server-bind-wildcard.yml +23 -7
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-shape-in-symbol-names.yml +68 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-sql-in-code-js.yml +41 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-sql-in-code.yml +41 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-laundering.yml +32 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-parameters.yml +67 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-returns.yml +106 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unsafe-dictionary-any.yml +50 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unsafe-dictionary-unknown.yml +56 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-win32-isabsolute-for-qualification.yml +2 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/redundant-unsafe-function.yml +32 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/require-safety-comment-for-as-unknown-as.yml +184 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/ts-void-zero.yml +5 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/self-scan-baseline.json +5 -0
- package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +132 -1
- package/node_modules/pi-lens/scripts/download-grammars.js +25 -0
- package/node_modules/pi-lens/scripts/grammars.lock.json +9 -0
- package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +12 -11
- package/node_modules/pi-lens/skills/pi-lens-lsp-navigation/SKILL.md +22 -22
- package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/SKILL.md +87 -116
- package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/reference.md +170 -0
- package/node_modules/pi-lens/skills/pi-lens-write-tree-sitter-rule/SKILL.md +3 -1
- package/node_modules/pi-lens/vendor/grammars/tree-sitter-cue.wasm +0 -0
- package/node_modules/pi-mcp-adapter/CHANGELOG.md +49 -0
- package/node_modules/pi-mcp-adapter/README.md +51 -6
- package/node_modules/pi-mcp-adapter/agent-dir.ts +12 -4
- package/node_modules/pi-mcp-adapter/cli.js +188 -5
- package/node_modules/pi-mcp-adapter/commands.ts +128 -22
- package/node_modules/pi-mcp-adapter/config.ts +28 -10
- package/node_modules/pi-mcp-adapter/direct-tools.ts +23 -19
- package/node_modules/pi-mcp-adapter/index.ts +219 -32
- package/node_modules/pi-mcp-adapter/init.ts +36 -4
- package/node_modules/pi-mcp-adapter/lifecycle.ts +315 -24
- package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +39 -6
- package/node_modules/pi-mcp-adapter/mcp-bearer-store.ts +387 -0
- package/node_modules/pi-mcp-adapter/mcp-callback-server.ts +27 -3
- package/node_modules/pi-mcp-adapter/mcp-code.ts +4 -0
- package/node_modules/pi-mcp-adapter/mcp-panel.ts +42 -13
- package/node_modules/pi-mcp-adapter/mcp-setup-panel.ts +2 -1
- package/node_modules/pi-mcp-adapter/metadata-cache.ts +46 -25
- package/node_modules/pi-mcp-adapter/package-mcp-loader.ts +168 -0
- package/node_modules/pi-mcp-adapter/package.json +4 -1
- package/node_modules/pi-mcp-adapter/proxy-modes.ts +5 -4
- package/node_modules/pi-mcp-adapter/request-headers-command.ts +330 -0
- package/node_modules/pi-mcp-adapter/search-ranking.ts +92 -22
- package/node_modules/pi-mcp-adapter/server-manager.ts +145 -2
- package/node_modules/pi-mcp-adapter/session-recovery.ts +7 -0
- package/node_modules/pi-mcp-adapter/tool-approval.ts +15 -2
- package/node_modules/pi-mcp-adapter/tool-metadata.ts +38 -18
- package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +44 -4
- package/node_modules/pi-mcp-adapter/types.ts +95 -10
- package/node_modules/pi-mcp-adapter/ui-server.ts +18 -16
- package/node_modules/pi-mcp-adapter/utils.ts +70 -0
- package/node_modules/pi-web-access/CHANGELOG.md +37 -0
- package/node_modules/pi-web-access/README.md +38 -14
- package/node_modules/pi-web-access/anysearch.ts +4 -2
- package/node_modules/pi-web-access/auth-fetch.ts +148 -0
- package/node_modules/pi-web-access/brave.ts +16 -4
- package/node_modules/pi-web-access/chrome-cookies.ts +110 -23
- package/node_modules/pi-web-access/curator-page.ts +8 -3
- package/node_modules/pi-web-access/curator-server.ts +5 -1
- package/node_modules/pi-web-access/exa.ts +18 -7
- package/node_modules/pi-web-access/extract.ts +134 -37
- package/node_modules/pi-web-access/fetch-params.ts +17 -3
- package/node_modules/pi-web-access/firecrawl.ts +172 -12
- package/node_modules/pi-web-access/gemini-search.ts +33 -7
- package/node_modules/pi-web-access/index.ts +160 -104
- package/node_modules/pi-web-access/package.json +2 -2
- package/node_modules/pi-web-access/page-query.ts +4 -2
- package/node_modules/pi-web-access/parallel-mcp.ts +249 -0
- package/node_modules/pi-web-access/parallel.ts +2 -2
- package/node_modules/pi-web-access/query-rewrite.ts +51 -0
- package/node_modules/pi-web-access/serper.ts +211 -0
- package/node_modules/pi-web-access/summary-model-scope.ts +12 -4
- package/node_modules/pi-web-access/summary-review.ts +51 -23
- package/node_modules/pi-web-access/tavily.ts +16 -4
- package/node_modules/pi-web-access/utils.ts +87 -0
- package/node_modules/pi-web-access/valyu.ts +199 -0
- package/node_modules/pi-web-access/youtube-extract.ts +2 -2
- package/package.json +13 -13
|
@@ -1,22 +1,97 @@
|
|
|
1
|
+
import { LEDGER_FIELD_MAX } from "../../../ledger-bounds.js";
|
|
2
|
+
/**
|
|
3
|
+
* The first non-empty line of a tool's output, bounded.
|
|
4
|
+
*
|
|
5
|
+
* Replaces six hand-rolled copies that spelled the same idea two ways —
|
|
6
|
+
* `text.trim().split("\n")[0]` and `(text ?? "").trim().split("\n")[0] ||
|
|
7
|
+
* fallback` — with differing (or absent) length caps. Two behaviours the
|
|
8
|
+
* copies got wrong and this does not: a leading blank line no longer yields an
|
|
9
|
+
* empty "first line", and `\r\n` output no longer keeps its carriage return.
|
|
10
|
+
*
|
|
11
|
+
* Returns `""` when the text is empty or all-whitespace, so callers keep using
|
|
12
|
+
* `firstOutputLine(x) || fallback`.
|
|
13
|
+
*/
|
|
14
|
+
export function firstOutputLine(text, max = LEDGER_FIELD_MAX) {
|
|
15
|
+
for (const line of String(text ?? "").split(/\r?\n/)) {
|
|
16
|
+
const trimmed = line.trim();
|
|
17
|
+
if (!trimmed)
|
|
18
|
+
continue;
|
|
19
|
+
return trimmed.length > max ? `${trimmed.slice(0, max)}…` : trimmed;
|
|
20
|
+
}
|
|
21
|
+
return "";
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Decide whether a tool ran, and if not, why (#1816).
|
|
25
|
+
*
|
|
26
|
+
* The defect this closes (the #1736 class): a runner that reads only its
|
|
27
|
+
* parsed diagnostics reports a CLEAN file whenever the parse yields nothing —
|
|
28
|
+
* including when the tool exited non-zero on an unknown flag, was killed by a
|
|
29
|
+
* signal, or never spawned at all. An empty result must distinguish clean from
|
|
30
|
+
* errored.
|
|
31
|
+
*
|
|
32
|
+
* Classification order, most specific first:
|
|
33
|
+
* 1. `result.error` or a signal — the process never completed. `did-not-run`.
|
|
34
|
+
* 2. `status === null` with no error — no exit status ever arrived, so no
|
|
35
|
+
* analysis can be claimed. `did-not-run`.
|
|
36
|
+
* 3. `reportMissing` — an artifact tool wrote no report. Nonzero exit means
|
|
37
|
+
* `report-missing`; exit 0 means a genuinely clean run that had nothing
|
|
38
|
+
* to write.
|
|
39
|
+
* 4. A nonzero status outside the caller's declared `ran` table.
|
|
40
|
+
* `rejected-invocation`.
|
|
41
|
+
* 5. A nonzero status with nothing to parse. `did-not-run` — a tool that
|
|
42
|
+
* analysed the file says SOMETHING, so silence plus failure is evidence
|
|
43
|
+
* it never got that far.
|
|
44
|
+
* Everything else ran.
|
|
45
|
+
*
|
|
46
|
+
* Note what is deliberately NOT a non-ran path: a nonzero status WITH output
|
|
47
|
+
* and no contradicting table. Most linters exit non-zero precisely because
|
|
48
|
+
* they found something, and their findings are on stdout.
|
|
49
|
+
*/
|
|
50
|
+
export function classifyRunOutcome(input) {
|
|
51
|
+
const { result, exitCodes, reportMissing } = input;
|
|
52
|
+
const status = result.status ?? null;
|
|
53
|
+
const signal = result.signal ?? null;
|
|
54
|
+
const output = input.output ?? result.stdout;
|
|
55
|
+
const base = {
|
|
56
|
+
status,
|
|
57
|
+
signal,
|
|
58
|
+
firstOutputLine: firstOutputLine(result.stderr) ||
|
|
59
|
+
firstOutputLine(result.stdout) ||
|
|
60
|
+
firstOutputLine(result.error?.message),
|
|
61
|
+
};
|
|
62
|
+
if (result.error || signal)
|
|
63
|
+
return { kind: "did-not-run", ...base };
|
|
64
|
+
if (status === null)
|
|
65
|
+
return { kind: "did-not-run", ...base };
|
|
66
|
+
if (reportMissing) {
|
|
67
|
+
return status === 0
|
|
68
|
+
? { kind: "ran", ...base }
|
|
69
|
+
: { kind: "report-missing", ...base };
|
|
70
|
+
}
|
|
71
|
+
if (status !== 0 && exitCodes && !exitCodes.ran.includes(status)) {
|
|
72
|
+
return { kind: "rejected-invocation", ...base };
|
|
73
|
+
}
|
|
74
|
+
if (status !== 0 && !output?.trim()) {
|
|
75
|
+
return { kind: "did-not-run", ...base };
|
|
76
|
+
}
|
|
77
|
+
return { kind: "ran", ...base };
|
|
78
|
+
}
|
|
1
79
|
/**
|
|
2
80
|
* True when a tool both failed and produced nothing to parse — it never got as
|
|
3
81
|
* far as linting the file. Callers map this to `skipped`, never `succeeded`.
|
|
4
82
|
*
|
|
5
|
-
*
|
|
6
|
-
* `
|
|
7
|
-
* `
|
|
8
|
-
*
|
|
9
|
-
* that
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* Tools that exit non-zero *because* they found something are unaffected: their
|
|
14
|
-
* findings are on stdout, so the output half of the test is false.
|
|
83
|
+
* Kept as its own export because callers outside the dispatch runners use it
|
|
84
|
+
* (`dead-code-client.ts`, `knip-client.ts`). It now DELEGATES to
|
|
85
|
+
* `classifyRunOutcome` rather than restating the rule, but keeps its exact
|
|
86
|
+
* historical semantics: the `!output.trim()` conjunct stays here so a spawn
|
|
87
|
+
* error that still produced partial output keeps reaching the parser, which is
|
|
88
|
+
* what today's callers depend on. `classifyRunOutcome` is the stricter,
|
|
89
|
+
* outcome-typed reading; migrate callers to it deliberately, not by accident.
|
|
15
90
|
*
|
|
16
91
|
* `output` defaults to stdout. Runners that parse stderr too pass the exact
|
|
17
92
|
* string they are about to hand the parser, so "nothing to parse" means both
|
|
18
93
|
* streams rather than just one.
|
|
19
94
|
*/
|
|
20
95
|
export function spawnFailedWithNoOutput(result, output = result.stdout) {
|
|
21
|
-
return (
|
|
96
|
+
return (classifyRunOutcome({ result, output }).kind !== "ran" && !output?.trim());
|
|
22
97
|
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One wording for a tool that produced no usable result, and the runner gate
|
|
3
|
+
* that emits it to the degradation ledger (#1816).
|
|
4
|
+
*/
|
|
5
|
+
import { incrementDegradationCount } from "../../../degradation-ledger.js";
|
|
6
|
+
import { truncateForLedger } from "../../../ledger-bounds.js";
|
|
7
|
+
import { classifyRunOutcome, firstOutputLine, } from "./spawn-outcome.js";
|
|
8
|
+
/**
|
|
9
|
+
* One wording for "this tool did not produce a usable result" (#1816).
|
|
10
|
+
*
|
|
11
|
+
* Before this, five reason builders spelled the same sentence five ways and
|
|
12
|
+
* twelve sites truncated with their own literal, and NONE of them named the
|
|
13
|
+
* signal — so a SIGKILLed tool read exactly like a clean exit 0. The wording
|
|
14
|
+
* here is fixed, the truncation is the ledger's own `LEDGER_FIELD_MAX` policy
|
|
15
|
+
* applied once at the end, and the signal is always named when present.
|
|
16
|
+
*
|
|
17
|
+
* Shape: `tool (k=v, k=v) <what happened> with <what was missing>: <detail>`
|
|
18
|
+
*/
|
|
19
|
+
export function formatToolFailure(input) {
|
|
20
|
+
const entries = Object.entries(input.fields ?? {}).filter(([, value]) => value !== undefined && value !== "");
|
|
21
|
+
const identity = entries.length
|
|
22
|
+
? `${input.tool} (${entries.map(([key, value]) => `${key}=${value}`).join(", ")})`
|
|
23
|
+
: input.tool;
|
|
24
|
+
// A signal is the strongest available explanation, so it displaces the exit
|
|
25
|
+
// status rather than sitting beside a `null` one.
|
|
26
|
+
const what = input.signal
|
|
27
|
+
? `was killed by ${input.signal}`
|
|
28
|
+
: input.status === null
|
|
29
|
+
? "did not run (spawn failure)"
|
|
30
|
+
: `exited ${input.status}`;
|
|
31
|
+
const missing = input.reportMissing ? "no report file" : "no output";
|
|
32
|
+
const detail = firstOutputLine(input.stderr) || firstOutputLine(input.stdout) || "no stderr";
|
|
33
|
+
return truncateForLedger(`${identity} ${what} with ${missing}: ${detail}`);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* `formatToolFailure` fed straight from a `classifyRunOutcome` verdict — the
|
|
37
|
+
* path every migrated runner takes, so the outcome and the wording can never
|
|
38
|
+
* disagree about the status or the signal.
|
|
39
|
+
*/
|
|
40
|
+
export function formatRunOutcomeFailure(tool, outcome, fields) {
|
|
41
|
+
return formatToolFailure({
|
|
42
|
+
tool,
|
|
43
|
+
status: outcome.status,
|
|
44
|
+
signal: outcome.signal,
|
|
45
|
+
stderr: outcome.firstOutputLine,
|
|
46
|
+
reportMissing: outcome.kind === "report-missing",
|
|
47
|
+
fields: { outcome: outcome.kind, ...fields },
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* The migrated runners' one call: classify the spawn, and when the tool did
|
|
52
|
+
* NOT run, record a bounded `runner-empty-result` row and hand back the
|
|
53
|
+
* `skipped` verdict. Returns `null` when the tool ran, meaning "carry on and
|
|
54
|
+
* parse".
|
|
55
|
+
*
|
|
56
|
+
* `incrementDegradationCount` keeps the record bounded — one latest-reason
|
|
57
|
+
* entry per (kind, subject) with an exact event tally — so a permanently
|
|
58
|
+
* broken tool costs one ledger row, not one per dispatched file. `subject` is
|
|
59
|
+
* the tool id, which is the discriminating identity a reader needs: WHICH tool
|
|
60
|
+
* is silently contributing nothing.
|
|
61
|
+
*/
|
|
62
|
+
export function skipUnlessToolRan(tool, input, fields) {
|
|
63
|
+
const outcome = classifyRunOutcome(input);
|
|
64
|
+
if (outcome.kind === "ran")
|
|
65
|
+
return null;
|
|
66
|
+
incrementDegradationCount({
|
|
67
|
+
kind: "runner-empty-result",
|
|
68
|
+
subject: tool,
|
|
69
|
+
reason: formatRunOutcomeFailure(tool, outcome, fields),
|
|
70
|
+
});
|
|
71
|
+
return { status: "skipped", diagnostics: [], semantic: "none" };
|
|
72
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared toolchain-availability lifecycle (#1476 Sonar follow-up).
|
|
3
|
+
*
|
|
4
|
+
* `candidate-probe.ts` factored out the PATH sweep the Go and Rust clients ran,
|
|
5
|
+
* but the LIFECYCLE around it stayed written twice: the transient-aware latch,
|
|
6
|
+
* the in-flight dedupe that keeps concurrent first-time callers to one sweep,
|
|
7
|
+
* the path memo, and the two `availability_decision` records. Two copies of one
|
|
8
|
+
* rule is how #1467's fix missed seven sites, so the rule lives here once and
|
|
9
|
+
* each client contributes only its configuration.
|
|
10
|
+
*
|
|
11
|
+
* Callers keep their own public method names — `isGoAvailableAsync`,
|
|
12
|
+
* `findCargoPathAsync` — because other modules call them; only the body moves.
|
|
13
|
+
*/
|
|
14
|
+
import { createAvailabilityLatch, logAvailabilityDecision, } from "./availability-policy.js";
|
|
15
|
+
import { probeAvailabilityCandidates } from "./candidate-probe.js";
|
|
16
|
+
/**
|
|
17
|
+
* Own one toolchain's availability: sweep the platform candidate list, memoize
|
|
18
|
+
* the path that answered, and park the verdict behind the shared latch so a
|
|
19
|
+
* timed-out probe expires instead of latching "the toolchain is not installed"
|
|
20
|
+
* for the life of the process.
|
|
21
|
+
*/
|
|
22
|
+
export function createToolchainAvailability(config) {
|
|
23
|
+
const availabilityLatch = createAvailabilityLatch();
|
|
24
|
+
let toolPath = null;
|
|
25
|
+
/** Classification of the candidate sweep, for the retry decision. */
|
|
26
|
+
let sweepSawTransient = false;
|
|
27
|
+
let sweepTransientCause = "probe-timeout";
|
|
28
|
+
let sweepHostStallMs = 0;
|
|
29
|
+
/** What the last classified candidate returned, for the decision record. */
|
|
30
|
+
let sweepEvidence;
|
|
31
|
+
let ensureInFlight = null;
|
|
32
|
+
async function findPath() {
|
|
33
|
+
if (toolPath)
|
|
34
|
+
return toolPath;
|
|
35
|
+
const paths = process.platform === "win32" ? config.windowsPaths : config.unixPaths;
|
|
36
|
+
const sweep = await probeAvailabilityCandidates(paths, config.probeArgs, config.budgetMs);
|
|
37
|
+
sweepSawTransient = sweep.sawTransient;
|
|
38
|
+
sweepTransientCause = sweep.transientCause;
|
|
39
|
+
sweepHostStallMs = sweep.hostStallMs;
|
|
40
|
+
sweepEvidence = sweep.evidence;
|
|
41
|
+
if (sweep.foundPath)
|
|
42
|
+
toolPath = sweep.foundPath;
|
|
43
|
+
return sweep.foundPath;
|
|
44
|
+
}
|
|
45
|
+
async function resolveAvailability() {
|
|
46
|
+
const startedAt = Date.now();
|
|
47
|
+
const found = (await findPath()) !== null;
|
|
48
|
+
if (found) {
|
|
49
|
+
availabilityLatch.noteAvailable();
|
|
50
|
+
config.log(`${config.label} found: ${toolPath}`);
|
|
51
|
+
logAvailabilityDecision({
|
|
52
|
+
tool: config.tool,
|
|
53
|
+
verdict: "available",
|
|
54
|
+
outcome: "success",
|
|
55
|
+
cause: "ok",
|
|
56
|
+
elapsedMs: Date.now() - startedAt,
|
|
57
|
+
latched: true,
|
|
58
|
+
hostStallMs: sweepHostStallMs,
|
|
59
|
+
budgetMs: config.budgetMs,
|
|
60
|
+
classifiedBy: "probe",
|
|
61
|
+
...(sweepEvidence !== undefined && { evidence: sweepEvidence }),
|
|
62
|
+
});
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
// A timed-out version probe is evidence about this moment, not about
|
|
66
|
+
// whether the toolchain is installed; it expires instead of latching.
|
|
67
|
+
const outcome = sweepSawTransient ? "transient" : "missing";
|
|
68
|
+
const cause = sweepSawTransient ? sweepTransientCause : "not-found";
|
|
69
|
+
const retryAfterMs = availabilityLatch.noteUnavailable(outcome, cause);
|
|
70
|
+
logAvailabilityDecision({
|
|
71
|
+
tool: config.tool,
|
|
72
|
+
verdict: "unavailable",
|
|
73
|
+
outcome,
|
|
74
|
+
cause,
|
|
75
|
+
elapsedMs: Date.now() - startedAt,
|
|
76
|
+
latched: outcome !== "transient",
|
|
77
|
+
hostStallMs: sweepHostStallMs,
|
|
78
|
+
...(retryAfterMs > 0 && { retryAfterMs }),
|
|
79
|
+
budgetMs: config.budgetMs,
|
|
80
|
+
// Derived from the sweep's own candidate probes, and carrying what the
|
|
81
|
+
// last of them returned (#1500).
|
|
82
|
+
classifiedBy: "probe",
|
|
83
|
+
...(sweepEvidence !== undefined && { evidence: sweepEvidence }),
|
|
84
|
+
});
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
async function isAvailable() {
|
|
88
|
+
// `read()` returns null when the last verdict was transient and its
|
|
89
|
+
// cooldown expired, which re-enters the candidate sweep (#1476).
|
|
90
|
+
const memo = availabilityLatch.read();
|
|
91
|
+
if (memo !== null)
|
|
92
|
+
return memo;
|
|
93
|
+
// Now that a verdict can expire, concurrent callers arriving just after a
|
|
94
|
+
// cooldown must share ONE sweep rather than each spawning their own.
|
|
95
|
+
if (ensureInFlight)
|
|
96
|
+
return ensureInFlight;
|
|
97
|
+
ensureInFlight = resolveAvailability();
|
|
98
|
+
try {
|
|
99
|
+
return await ensureInFlight;
|
|
100
|
+
}
|
|
101
|
+
finally {
|
|
102
|
+
ensureInFlight = null;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return { findPath, isAvailable };
|
|
106
|
+
}
|
|
@@ -3,6 +3,7 @@ import * as path from "node:path";
|
|
|
3
3
|
import { safeSpawnAsync } from "../../safe-spawn.js";
|
|
4
4
|
import { PRIORITY } from "../priorities.js";
|
|
5
5
|
import { createAvailabilityChecker, resolveToolCommandWithInstallFallback, } from "./utils/runner-helpers.js";
|
|
6
|
+
import { skipUnlessToolRan } from "./utils/tool-failure.js";
|
|
6
7
|
const vale = createAvailabilityChecker("vale", ".exe");
|
|
7
8
|
/**
|
|
8
9
|
* Check for a .vale.ini config file in cwd or parent dirs.
|
|
@@ -89,6 +90,14 @@ const valeRunner = {
|
|
|
89
90
|
return { status: "skipped", diagnostics: [], semantic: "none" };
|
|
90
91
|
// Vale exits 0 even on findings, non-zero only on errors
|
|
91
92
|
const result = await safeSpawnAsync(cmd, ["--output", "JSON", ctx.filePath], { cwd, timeout: 15000 });
|
|
93
|
+
// #1816: this runner read `result.status` zero times, so a Vale that
|
|
94
|
+
// rejected its config exited nonzero with an empty stdout, parsed to
|
|
95
|
+
// zero alerts, and reported clean prose. No exit-code table: Vale's
|
|
96
|
+
// nonzero codes vary with --minAlertLevel, so the conservative
|
|
97
|
+
// nothing-to-parse rule is the only safe discriminator here.
|
|
98
|
+
const skipped = skipUnlessToolRan("vale", { result });
|
|
99
|
+
if (skipped)
|
|
100
|
+
return skipped;
|
|
92
101
|
const raw = result.stdout || "";
|
|
93
102
|
const diagnostics = parseValeOutput(raw, ctx.filePath);
|
|
94
103
|
if (diagnostics.length === 0) {
|
|
@@ -2,6 +2,7 @@ import { safeSpawnAsync } from "../../safe-spawn.js";
|
|
|
2
2
|
import { getLinterPolicyForCwd, hasYamllintConfig } from "../../tool-policy.js";
|
|
3
3
|
import { PRIORITY } from "../priorities.js";
|
|
4
4
|
import { createAvailabilityChecker, resolveToolCommandWithInstallFallback, } from "./utils/runner-helpers.js";
|
|
5
|
+
import { skipUnlessToolRan } from "./utils/tool-failure.js";
|
|
5
6
|
const yamllint = createAvailabilityChecker("yamllint", ".exe");
|
|
6
7
|
export { hasYamllintConfig };
|
|
7
8
|
function parseYamllintParsable(raw, filePath) {
|
|
@@ -55,7 +56,23 @@ const yamllintRunner = {
|
|
|
55
56
|
const result = await safeSpawnAsync(cmd, ["-f", "parsable", ctx.filePath], {
|
|
56
57
|
timeout: 15000,
|
|
57
58
|
});
|
|
58
|
-
|
|
59
|
+
// #1816: this runner read `result.status` zero times, so a yamllint
|
|
60
|
+
// that rejected its config reported a clean YAML file.
|
|
61
|
+
//
|
|
62
|
+
// No exit-code table: yamllint returns 2 both for "warnings only" and
|
|
63
|
+
// for an argparse usage error, so declaring 2 a rejection would discard
|
|
64
|
+
// real warnings. The discriminator is the STREAM instead. `-f parsable`
|
|
65
|
+
// writes findings to stdout and nothing else; stderr carries usage text
|
|
66
|
+
// and tracebacks. So the gate judges "nothing to parse" on stdout alone,
|
|
67
|
+
// while the parser still reads both streams.
|
|
68
|
+
const raw = `${result.stdout ?? ""}${result.stderr ?? ""}`;
|
|
69
|
+
const skipped = skipUnlessToolRan("yamllint", {
|
|
70
|
+
result,
|
|
71
|
+
output: result.stdout,
|
|
72
|
+
});
|
|
73
|
+
if (skipped)
|
|
74
|
+
return skipped;
|
|
75
|
+
const diagnostics = parseYamllintParsable(raw, ctx.filePath);
|
|
59
76
|
if (diagnostics.length === 0) {
|
|
60
77
|
return { status: "succeeded", diagnostics: [], semantic: "none" };
|
|
61
78
|
}
|
|
@@ -24,7 +24,9 @@ function parseZigOutput(raw, filePath) {
|
|
|
24
24
|
line: Number.parseInt(lineStr, 10) || 1,
|
|
25
25
|
column: Number.parseInt(colStr, 10) || 1,
|
|
26
26
|
severity,
|
|
27
|
-
|
|
27
|
+
// `zig build-exe <file>` does not load build.zig module/import context.
|
|
28
|
+
// Its findings are useful evidence, but cannot prove a project blocker.
|
|
29
|
+
semantic: "warning",
|
|
28
30
|
tool: "zig",
|
|
29
31
|
rule: `zig-${level}`,
|
|
30
32
|
fixable: false,
|
|
@@ -82,7 +84,7 @@ const zigCheckRunner = {
|
|
|
82
84
|
return {
|
|
83
85
|
status: hasErrors ? "failed" : "succeeded",
|
|
84
86
|
diagnostics,
|
|
85
|
-
semantic:
|
|
87
|
+
semantic: "warning",
|
|
86
88
|
};
|
|
87
89
|
},
|
|
88
90
|
};
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
import { logBusEvent } from "./bus-events-logger.js";
|
|
25
25
|
import { isBusPublishEnabled } from "./bus-publish.js";
|
|
26
26
|
import { normalizeFilePath } from "./path-utils.js";
|
|
27
|
-
import { createLiveBusEmitter, recordStaleBusFailure, } from "./live-bus-emitter.js";
|
|
27
|
+
import { createLiveBusEmitter, recordStaleBusFailure, resolveLiveBusEmitter, } from "./live-bus-emitter.js";
|
|
28
28
|
export const BUS_DISPOSITION_EVENT = "pilens:diagnostic:disposition";
|
|
29
29
|
export const BUS_DISPOSITION_VERSION = 1;
|
|
30
30
|
const liveEmitter = createLiveBusEmitter();
|
|
@@ -67,8 +67,13 @@ export function publishDisposition(args) {
|
|
|
67
67
|
}
|
|
68
68
|
return;
|
|
69
69
|
}
|
|
70
|
-
const
|
|
71
|
-
|
|
70
|
+
const resolution = resolveLiveBusEmitter(liveEmitter, () => ({
|
|
71
|
+
event: BUS_DISPOSITION_EVENT,
|
|
72
|
+
cwd: normalizeFilePath(args.cwd),
|
|
73
|
+
}));
|
|
74
|
+
if (resolution.outcome === "stale-session")
|
|
75
|
+
return;
|
|
76
|
+
if (resolution.outcome === "unwired") {
|
|
72
77
|
if (!hasLoggedUnwired) {
|
|
73
78
|
hasLoggedUnwired = true;
|
|
74
79
|
logBusEvent({
|
|
@@ -79,6 +84,7 @@ export function publishDisposition(args) {
|
|
|
79
84
|
}
|
|
80
85
|
return;
|
|
81
86
|
}
|
|
87
|
+
const busEmit = resolution.emit;
|
|
82
88
|
try {
|
|
83
89
|
const payload = {
|
|
84
90
|
v: BUS_DISPOSITION_VERSION,
|
|
@@ -106,6 +112,7 @@ export function publishDisposition(args) {
|
|
|
106
112
|
outcome: "emit_failed",
|
|
107
113
|
cwd: normalizeFilePath(args.cwd),
|
|
108
114
|
error: String(err),
|
|
115
|
+
ctxSource: resolution.ctxSource,
|
|
109
116
|
});
|
|
110
117
|
if (!hasLoggedFailure) {
|
|
111
118
|
hasLoggedFailure = true;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { performance } from "node:perf_hooks";
|
|
2
|
+
/**
|
|
3
|
+
* The moment pi-lens's module graph started evaluating, captured as this
|
|
4
|
+
* module's first statement (#1374 host-boot vs extension-eval split).
|
|
5
|
+
*
|
|
6
|
+
* This module is otherwise side-effect-free by design (#1434 S3d review): it
|
|
7
|
+
* does nothing but capture a timestamp. `clients/console-guard-install.ts`
|
|
8
|
+
* imports it as its FIRST import so the capture happens before the guard's
|
|
9
|
+
* own install work, and `clients/startup-timing.ts` imports it too, for the
|
|
10
|
+
* constant alone. Before this split, `startup-timing.ts` imported the
|
|
11
|
+
* constant FROM `console-guard-install.ts` — which meant importing
|
|
12
|
+
* startup-timing anywhere (e.g. a test measuring load time) silently
|
|
13
|
+
* installed the console guard as a side effect. Splitting the constant out
|
|
14
|
+
* means importing this module, or `startup-timing.ts`, never installs
|
|
15
|
+
* anything.
|
|
16
|
+
*/
|
|
17
|
+
export const PI_LENS_EVAL_STARTED_MS = performance.now();
|
|
@@ -143,15 +143,38 @@ export function resetEventLoopMonitor() {
|
|
|
143
143
|
windowStartCpuMs = cpuTotalMs();
|
|
144
144
|
}
|
|
145
145
|
/**
|
|
146
|
-
* Decide whether
|
|
147
|
-
* threshold logic is testable without the (vitest-flaky) native
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
*
|
|
146
|
+
* Decide whether THIS block beats the session's running high-water. Pure so
|
|
147
|
+
* the threshold logic is testable without the (vitest-flaky) native
|
|
148
|
+
* histogram. Requires `maxMs > lastLoggedMs + deltaMs` above a floor
|
|
149
|
+
* (`minMs`) so noise near the current max doesn't keep re-triggering the
|
|
150
|
+
* high-water bookkeeping.
|
|
151
|
+
*
|
|
152
|
+
* NOTE (#1723): this is no longer the logging gate — see
|
|
153
|
+
* `shouldLogLoopBlock` for that. This function now answers a narrower
|
|
154
|
+
* question ("is this a new session worst?", used for the `worstSoFar`
|
|
155
|
+
* metadata flag and for deciding whether to advance the high-water), because
|
|
156
|
+
* gating the LOG on it hid every sub-maximum block after a session's first
|
|
157
|
+
* large one, which made loop_block-vs-pull-timeout correlation undecidable.
|
|
151
158
|
*/
|
|
152
159
|
export function shouldLogWorstBlock(maxMs, lastLoggedMs, minMs = 60, deltaMs = 25) {
|
|
153
160
|
return maxMs >= minMs && maxMs > lastLoggedMs + deltaMs;
|
|
154
161
|
}
|
|
162
|
+
/**
|
|
163
|
+
* Decide whether a block is worth persisting to `latency.log` AT ALL (#1723).
|
|
164
|
+
* Every block at or above the floor (`minMs`) qualifies — not only a new
|
|
165
|
+
* session worst — because a session's later blocks can be smaller than an
|
|
166
|
+
* early spike yet still be exactly the ones that starved an LSP pull
|
|
167
|
+
* (#1549/#1713) and are otherwise invisible to the correlation.
|
|
168
|
+
*
|
|
169
|
+
* Volume is bounded by CALL CADENCE, not by this gate: the `turn_end` caller
|
|
170
|
+
* invokes this at most once per turn (the histogram window is reset every
|
|
171
|
+
* turn), so the natural cap is one `loop_block` record per turn — a jittery
|
|
172
|
+
* session cannot flood the log because there is nowhere for a second sample
|
|
173
|
+
* to come from within the same turn.
|
|
174
|
+
*/
|
|
175
|
+
export function shouldLogLoopBlock(maxMs, minMs = 60) {
|
|
176
|
+
return maxMs >= minMs;
|
|
177
|
+
}
|
|
155
178
|
/** Test-only: stop and clear the monitor so cases don't leak into each other. */
|
|
156
179
|
export function _stopEventLoopMonitorForTest() {
|
|
157
180
|
histogram?.disable();
|