@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
package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-win32-isabsolute-for-qualification.yml
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
id: no-win32-isabsolute-for-qualification
|
|
2
2
|
language: TypeScript
|
|
3
3
|
severity: warning
|
|
4
|
+
metadata:
|
|
5
|
+
category: pi-lens-self-scan
|
|
4
6
|
message: "Use isFullyQualified for path qualification instead of win32.isAbsolute"
|
|
5
7
|
note: |
|
|
6
8
|
Qualification must follow the input path's shape. Use clients/path-utils.ts
|
|
@@ -9,6 +9,31 @@ note: |
|
|
|
9
9
|
the `unsafe` keyword should be removed) or it is misplaced (an unsafe
|
|
10
10
|
operation lives outside an `unsafe { … }` block and should be wrapped).
|
|
11
11
|
Either case warrants review.
|
|
12
|
+
|
|
13
|
+
Exempt when a `/// # Safety` doc-comment section precedes the function:
|
|
14
|
+
Rust's own convention (rustdoc's `missing_safety_doc` lint, and
|
|
15
|
+
clippy's `undocumented_unsafe_blocks`) is that an `unsafe fn` states
|
|
16
|
+
its caller obligations in a `# Safety` doc section instead of wrapping
|
|
17
|
+
its whole body in a redundant `unsafe { ... }` block — the function
|
|
18
|
+
signature IS the unsafe boundary, the doc section is where the
|
|
19
|
+
contract lives.
|
|
20
|
+
|
|
21
|
+
2026-08-20 (review round, refs #1806): the first ship of this valve
|
|
22
|
+
used `follows: {stopBy: end, kind: line_comment, regex: '#\s*Safety'}`,
|
|
23
|
+
copying the `SAFETY:`-comment shape from `no-chained-type-assertions`
|
|
24
|
+
too literally. `stopBy: end` scans EVERY preceding sibling all the way
|
|
25
|
+
to the top of the file — one `# Safety` comment ANYWHERE earlier
|
|
26
|
+
(a stray file-top note, or a doc block that belongs to a DIFFERENT,
|
|
27
|
+
earlier function) exempted every `unsafe fn` after it. Probe: a
|
|
28
|
+
documented function followed by two undocumented ones scored 0 hits;
|
|
29
|
+
the two alone scored 2. Fixed by bounding the backward scan with
|
|
30
|
+
`stopBy: {not: {kind: line_comment}}` — it stops at the first
|
|
31
|
+
non-comment sibling, so only the CONTIGUOUS run of `///`/`//` lines
|
|
32
|
+
directly above the function is searched, never an earlier function's
|
|
33
|
+
doc block or an unrelated comment further up the file. (This valve
|
|
34
|
+
shipped with zero corpus hits either side in the original PR —
|
|
35
|
+
corpus silence isn't proof of correctness; the fixtures below are
|
|
36
|
+
the whole evidence, deliberately adversarial.)
|
|
12
37
|
rule:
|
|
13
38
|
all:
|
|
14
39
|
- kind: function_item
|
|
@@ -19,3 +44,10 @@ rule:
|
|
|
19
44
|
has:
|
|
20
45
|
kind: unsafe_block
|
|
21
46
|
stopBy: end
|
|
47
|
+
- not:
|
|
48
|
+
follows:
|
|
49
|
+
stopBy:
|
|
50
|
+
not:
|
|
51
|
+
kind: line_comment
|
|
52
|
+
kind: line_comment
|
|
53
|
+
regex: '#\s*Safety'
|
package/node_modules/pi-lens/rules/ast-grep-rules/rules/require-safety-comment-for-as-unknown-as.yml
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
id: require-safety-comment-for-as-unknown-as
|
|
2
|
+
language: TypeScript
|
|
3
|
+
severity: error
|
|
4
|
+
metadata:
|
|
5
|
+
category: pi-lens-self-scan
|
|
6
|
+
message: "'x as unknown as T' with no nearby SAFETY: comment — state the invariant TypeScript can't check"
|
|
7
|
+
note: |
|
|
8
|
+
Narrowed port of dmmulroy/anti-slop's
|
|
9
|
+
`require-safety-comment-for-type-assertion`
|
|
10
|
+
(src/rules/require-safety-comment-for-type-assertion.ts, MIT).
|
|
11
|
+
Upstream requires a `SAFETY:` comment before EVERY non-const type
|
|
12
|
+
assertion (`as`/angle-bracket), walking up through statement-owner
|
|
13
|
+
node kinds looking for a preceding comment. This port narrows the
|
|
14
|
+
target to `x as unknown as T` specifically — the two-hop cast through
|
|
15
|
+
`unknown`. The 2026-08-19 audit found 2,180 non-const assertions
|
|
16
|
+
repo-wide and ZERO `SAFETY:` comments; requiring one on every
|
|
17
|
+
assertion would mean authoring ~1,750 comments in one PR. `as unknown
|
|
18
|
+
as` is the form that actually launders evidence (routes through the
|
|
19
|
+
top type rather than a single verifiable hop), and it is the exact
|
|
20
|
+
shape AGENTS.md's defect shape 13 already asks for in prose: "when a
|
|
21
|
+
call site hands the policy an outcome it did NOT derive... justify it
|
|
22
|
+
in a comment at the call site." This rule makes that convention
|
|
23
|
+
checkable for its most evidence-destroying form.
|
|
24
|
+
|
|
25
|
+
2026-08-20 (refs #1727, #1777): promoted `hint` -> `error`. `error` is
|
|
26
|
+
the only tier that maps to semantic `blocking`
|
|
27
|
+
(`clients/dispatch/runners/ast-grep-napi.ts`), so AGENTS.md's severity
|
|
28
|
+
policy requires a documented zero-false-positive audit here. Two
|
|
29
|
+
changes make that audit come out clean.
|
|
30
|
+
|
|
31
|
+
1. STRUCTURAL SCOPING: test paths are excluded (`ignores:` below). In a
|
|
32
|
+
test, `x as unknown as T` is almost always a partial test double —
|
|
33
|
+
reaching into a private field or stubbing the two methods of a
|
|
34
|
+
surface the subject actually calls. The "invariant TypeScript can't
|
|
35
|
+
check" there is "this stub covers what the code under test touches",
|
|
36
|
+
which is the test's own subject matter, not a hidden runtime claim.
|
|
37
|
+
Four-corpus census (2026-08-20) confirms the shape concentrates in
|
|
38
|
+
test paths rather than assuming it:
|
|
39
|
+
|
|
40
|
+
| corpus | total | test-path | non-test | suppressed |
|
|
41
|
+
|---|---:|---:|---:|---:|
|
|
42
|
+
| pi-lens (`clients/`+`tests/`) | 305 | 289 | 16 | 95% |
|
|
43
|
+
| pi core (`packages/`) | 182 | 155 | 27 | 85% |
|
|
44
|
+
| opencode (`packages/`) | 194 | 154 | 40 | 79% |
|
|
45
|
+
| oh-my-pi (`packages/`) | 1803 | 1644 | 159 | 91% |
|
|
46
|
+
|
|
47
|
+
This is a FALSE-NEGATIVE bias, deliberately, and it is not small:
|
|
48
|
+
289 uncommented `as unknown as` sites in pi-lens's own `tests/`
|
|
49
|
+
now raise NO diagnostic at all, where each previously raised an
|
|
50
|
+
`error` through `no-chained-type-assertions.yml`'s `unknown` arm.
|
|
51
|
+
The same trade costs 1,644 sites on oh-my-pi. It is a path glob,
|
|
52
|
+
not a semantic check — ast-grep cannot verify a cast is really a
|
|
53
|
+
test double, only that it lives under a test path.
|
|
54
|
+
|
|
55
|
+
2. REPO-SIDE REMEDIATION: the 16 remaining `clients/` sites were read
|
|
56
|
+
individually and each was given a truthful `SAFETY:` comment
|
|
57
|
+
naming the specific invariant (an optional Node API absent from
|
|
58
|
+
`@types/node`, a two-phase-init field filled before first read, a
|
|
59
|
+
`Object.fromEntries` key-type loss, a process-global stash). None
|
|
60
|
+
was a comment written to silence the rule; where the cast had no
|
|
61
|
+
justification it was replaced instead
|
|
62
|
+
(`clients/runtime-context.ts`).
|
|
63
|
+
|
|
64
|
+
Post-narrowing census on pi-lens: 0 findings over `clients/` +
|
|
65
|
+
`tests/`. The rule is tagged `metadata.category: pi-lens-self-scan`,
|
|
66
|
+
so CI's `npm run astgrep:self-scan` lane keeps it at zero.
|
|
67
|
+
|
|
68
|
+
Placement contract: a `SAFETY:` comment may directly precede the cast,
|
|
69
|
+
its enclosing statement, or an object-literal member (`pair`) containing
|
|
70
|
+
the cast. Array elements and call arguments are also supported through the
|
|
71
|
+
direct-cast arm when the comment is immediately above the cast expression.
|
|
72
|
+
JSX attributes, class static blocks, and switch cases are not comment
|
|
73
|
+
anchors for this valve; place those comments on the enclosing statement.
|
|
74
|
+
Inline comments remain valid, for example `/* SAFETY: ... */ x as unknown
|
|
75
|
+
as T`. Upstream walks an arbitrary number of statement-owner levels looking
|
|
76
|
+
for ANY preceding comment in the file; this port only checks one level up
|
|
77
|
+
from the assertion and one level up from its immediate containing
|
|
78
|
+
statement or supported object member. There is NO dominance verification:
|
|
79
|
+
the rule proves a comment is adjacent, never that the comment is true or
|
|
80
|
+
that it describes this cast.
|
|
81
|
+
|
|
82
|
+
2026-08-20 (#1847, found in #1843's review): the "one level up from
|
|
83
|
+
its immediate containing statement" kind list omitted
|
|
84
|
+
`export_statement` and `public_field_definition`, so a `SAFETY:`
|
|
85
|
+
comment placed directly above an exported cast (`export const b =
|
|
86
|
+
(x as unknown as T).y;`) or a class-field cast (`bar: unknown = (x as
|
|
87
|
+
unknown as T).y;`) could not satisfy the valve — the rule is
|
|
88
|
+
`error`-tier and semantically `blocking`, so this left no escape for
|
|
89
|
+
those two shapes. Added both kinds. Verified the containing-statement
|
|
90
|
+
walk already covers casts nested deeper without a new kind: a cast
|
|
91
|
+
inside a `static {}` init block or an arrow-function body still
|
|
92
|
+
resolves to an ancestor `lexical_declaration`/`variable_declaration`
|
|
93
|
+
already in the list (probed with ast-grep's own `--rule` scan, not
|
|
94
|
+
reasoning about the grammar from memory), and a `SAFETY:` comment on
|
|
95
|
+
an `export const` nested inside a `namespace` block clears the valve
|
|
96
|
+
through the same `export_statement` kind — `stopBy: end` already
|
|
97
|
+
walks past the namespace wrapper to find it. `readonly`/`abstract`/
|
|
98
|
+
`static`/private-`#name` class fields all parse to the same
|
|
99
|
+
`public_field_definition` kind, so one entry covers all of them.
|
|
100
|
+
|
|
101
|
+
2026-08-20 (#1852 review, F1): the same defect shape one more time —
|
|
102
|
+
an enum member's initializer cast (`enum Foo { A = (x as unknown as
|
|
103
|
+
T).y }`) has no recognized ancestor either. The member's own kind is
|
|
104
|
+
`enum_assignment` (probed the same way: `ast-grep scan --rule` against
|
|
105
|
+
a real `enum`/`const enum`/`export enum` snippet rather than guessing
|
|
106
|
+
from the export/field precedent). One `enum_assignment` kind entry
|
|
107
|
+
covers plain, `const`, and `export` enums alike, the same way
|
|
108
|
+
`public_field_definition` covered every class-field modifier —
|
|
109
|
+
`enum_assignment` is the member-list node itself, unaffected by
|
|
110
|
+
keywords on the enclosing `enum_declaration`. `declare enum` members
|
|
111
|
+
have no initializer expression to cast, so there is nothing to probe
|
|
112
|
+
there.
|
|
113
|
+
|
|
114
|
+
Matched pair with `no-chained-type-assertions.yml`. As of 2026-08-20
|
|
115
|
+
the two PARTITION the assertion space instead of overlapping: this
|
|
116
|
+
rule owns `x as unknown as T` (with the `SAFETY:` escape valve); that
|
|
117
|
+
rule owns the concrete `x as A as B` chain, which has no escape valve
|
|
118
|
+
because it has no legitimate reading. Before the split both rules
|
|
119
|
+
matched the identical `as unknown as` site list (verified: 16/16
|
|
120
|
+
pi-lens, 182/182 pi, 194/194 opencode), so every uncommented site
|
|
121
|
+
raised two diagnostics for one defect.
|
|
122
|
+
|
|
123
|
+
2026-08-20 (#1834): both `follows` checks used `stopBy: end`, which
|
|
124
|
+
scans EVERY preceding sibling all the way to the top of the enclosing
|
|
125
|
+
block, not just the comment directly above the cast. A `SAFETY:`
|
|
126
|
+
comment attached to one cast silently exempted every LATER cast in the
|
|
127
|
+
same block, including casts on a different subject with no
|
|
128
|
+
justification of their own. Probe: `// SAFETY: ...` above `const a =
|
|
129
|
+
(y as unknown as string).length` followed by an undocumented `const b
|
|
130
|
+
= (x as unknown as string).length` scored 0 hits; `b`'s cast should
|
|
131
|
+
have been flagged. Fixed the same way as `redundant-unsafe-function`'s
|
|
132
|
+
identical valve (PR #1821, refs #1806): bound the backward scan with
|
|
133
|
+
`stopBy: {not: {kind: comment}}`, so it stops at the first non-comment
|
|
134
|
+
sibling and only ever searches the CONTIGUOUS comment run directly
|
|
135
|
+
above the cast (or its containing statement), never an earlier
|
|
136
|
+
statement's comment. The "Scope and known gap" note above already
|
|
137
|
+
described this contiguous-comment intent; the shipped pattern didn't
|
|
138
|
+
implement it.
|
|
139
|
+
|
|
140
|
+
2026-08-20 (#1870): the pair arm is bounded by the nearest `pair`. An
|
|
141
|
+
outer object member's SAFETY comment must not suppress a cast in a nested
|
|
142
|
+
member, and a nested member's comment must not suppress a parent cast.
|
|
143
|
+
The direct-cast arm remains the precise escape valve for comments adjacent
|
|
144
|
+
to casts in array elements and call arguments.
|
|
145
|
+
ignores:
|
|
146
|
+
- "**/*.test.ts"
|
|
147
|
+
- "**/*.test.tsx"
|
|
148
|
+
- "**/*.test.mts"
|
|
149
|
+
- "**/*.test.cts"
|
|
150
|
+
- "**/*.spec.ts"
|
|
151
|
+
- "**/*.spec.tsx"
|
|
152
|
+
- "**/tests/**"
|
|
153
|
+
- "**/test/**"
|
|
154
|
+
- "**/__tests__/**"
|
|
155
|
+
rule:
|
|
156
|
+
pattern: $X as unknown as $Y
|
|
157
|
+
not:
|
|
158
|
+
any:
|
|
159
|
+
- follows:
|
|
160
|
+
kind: comment
|
|
161
|
+
regex: 'SAFETY\s*:'
|
|
162
|
+
stopBy: { not: { kind: comment } }
|
|
163
|
+
- inside:
|
|
164
|
+
stopBy: { kind: pair }
|
|
165
|
+
any:
|
|
166
|
+
- kind: pair
|
|
167
|
+
follows:
|
|
168
|
+
kind: comment
|
|
169
|
+
regex: 'SAFETY\s*:'
|
|
170
|
+
stopBy: { not: { kind: comment } }
|
|
171
|
+
- inside:
|
|
172
|
+
stopBy: end
|
|
173
|
+
any:
|
|
174
|
+
- kind: expression_statement
|
|
175
|
+
- kind: lexical_declaration
|
|
176
|
+
- kind: variable_declaration
|
|
177
|
+
- kind: return_statement
|
|
178
|
+
- kind: export_statement
|
|
179
|
+
- kind: public_field_definition
|
|
180
|
+
- kind: enum_assignment
|
|
181
|
+
follows:
|
|
182
|
+
kind: comment
|
|
183
|
+
regex: 'SAFETY\s*:'
|
|
184
|
+
stopBy: { not: { kind: comment } }
|
|
@@ -5,6 +5,11 @@ message: void 0 for undefined - use undefined directly
|
|
|
5
5
|
metadata:
|
|
6
6
|
weight: 2
|
|
7
7
|
category: slop
|
|
8
|
+
note: |
|
|
9
|
+
Replacing `void 0` with `undefined` can change behavior when a local binding
|
|
10
|
+
shadows `undefined`. Shadowing `undefined` is itself a defect, and this fix
|
|
11
|
+
does not attempt to detect it.
|
|
8
12
|
rule:
|
|
9
13
|
kind: unary_expression
|
|
10
14
|
pattern: "void 0"
|
|
15
|
+
fix: undefined
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_comment": "Regenerate with `npm run astgrep:self-scan -- --update-baseline` AFTER triaging every new entry (fix the underlying finding, or confirm it's a legitimate exception and document why in the same PR). Never regenerate to silently swallow an unreviewed hit.",
|
|
3
|
+
"generatedAt": "2026-08-19T20:44:05.206Z",
|
|
4
|
+
"allowed": []
|
|
5
|
+
}
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* ~/.pi-lens/actionable-warnings*.log JSONL advisory pipeline (inject/suppress)
|
|
13
13
|
* ~/.pi-lens/ast-grep-tools*.log JSONL MCP ast-grep search/replace telemetry
|
|
14
14
|
* ~/.pi-lens/logs/*.jsonl JSONL diagnostic findings
|
|
15
|
+
* ~/.pi-lens/projects/<slug>/worklog.jsonl JSONL fix worklog (rule/tool/model/provider, #1448)
|
|
15
16
|
*/
|
|
16
17
|
|
|
17
18
|
import fs from "node:fs";
|
|
@@ -69,6 +70,7 @@ async function main() {
|
|
|
69
70
|
analyzeSessionStart(files.sessionStart, state),
|
|
70
71
|
analyzeActionableWarnings(files.actionableWarnings, state),
|
|
71
72
|
analyzeAstGrepTools(files.astGrepTools, state),
|
|
73
|
+
analyzeWorklog(files.worklog, state),
|
|
72
74
|
]);
|
|
73
75
|
|
|
74
76
|
const report = buildReport(state);
|
|
@@ -139,6 +141,13 @@ function discoverLogFiles(logRoot, archived) {
|
|
|
139
141
|
.filter((name) => name.endsWith(".jsonl"))
|
|
140
142
|
.map((name) => path.join(logsDir, name));
|
|
141
143
|
|
|
144
|
+
// worklog.jsonl lives per-project under projects/<slug>/ (getProjectDataDir),
|
|
145
|
+
// not at the log root — walk one level to find every project's file (#1448).
|
|
146
|
+
const projectsDir = path.join(logRoot, "projects");
|
|
147
|
+
const worklogs = safeReaddir(projectsDir)
|
|
148
|
+
.map((slug) => path.join(projectsDir, slug, "worklog.jsonl"))
|
|
149
|
+
.filter((file) => fs.existsSync(file));
|
|
150
|
+
|
|
142
151
|
const byPrefix = (prefix) =>
|
|
143
152
|
allRootFiles.filter((file) => {
|
|
144
153
|
const base = path.basename(file);
|
|
@@ -156,6 +165,7 @@ function discoverLogFiles(logRoot, archived) {
|
|
|
156
165
|
actionableWarnings: byPrefix("actionable-warnings"),
|
|
157
166
|
astGrepTools: byPrefix("ast-grep-tools"),
|
|
158
167
|
diagnostics: dailyLogs,
|
|
168
|
+
worklog: worklogs,
|
|
159
169
|
};
|
|
160
170
|
}
|
|
161
171
|
|
|
@@ -192,6 +202,13 @@ function createState(files) {
|
|
|
192
202
|
aborted: 0,
|
|
193
203
|
timedOutSweeps: 0,
|
|
194
204
|
timedOutFilesTotal: 0,
|
|
205
|
+
// #1618: per-reason breakdown of the same total. Populated from each
|
|
206
|
+
// sweep's `unconfirmedByReason` metadata when present; a sweep logged
|
|
207
|
+
// by a pre-#1618 build carries no such field, so its files are
|
|
208
|
+
// bucketed under "budget (pre-#1618 build)" — the ABSENT field is
|
|
209
|
+
// itself the vintage signal, not an assumption that every one of
|
|
210
|
+
// those files really was a budget timeout.
|
|
211
|
+
unconfirmedByReason: counter(),
|
|
195
212
|
sweeps: [],
|
|
196
213
|
progress: [],
|
|
197
214
|
},
|
|
@@ -263,6 +280,14 @@ function createState(files) {
|
|
|
263
280
|
errors: [],
|
|
264
281
|
slow: [],
|
|
265
282
|
},
|
|
283
|
+
worklog: {
|
|
284
|
+
// key: "<rule>||<model>" (model "" when the entry predates #1448 or the
|
|
285
|
+
// runtime didn't know it) -> { total, autoFixed }
|
|
286
|
+
byRuleModel: new Map(),
|
|
287
|
+
byModel: counter(),
|
|
288
|
+
byModelAutoFixed: counter(),
|
|
289
|
+
byProvider: counter(),
|
|
290
|
+
},
|
|
266
291
|
};
|
|
267
292
|
}
|
|
268
293
|
|
|
@@ -349,6 +374,27 @@ async function analyzeLatency(files, state) {
|
|
|
349
374
|
if (timedOut > 0) {
|
|
350
375
|
ws.timedOutSweeps += 1;
|
|
351
376
|
ws.timedOutFilesTotal += timedOut;
|
|
377
|
+
// #1618: attribute by the REAL per-reason tally when the build
|
|
378
|
+
// that wrote this log line has it — a service-destroyed file
|
|
379
|
+
// must never count toward "hit the per-file budget" the way it
|
|
380
|
+
// used to (the forensics tool that found #1618 in the first
|
|
381
|
+
// place read this exact field and mis-blamed budget exhaustion
|
|
382
|
+
// for what were mostly service-destroyed files).
|
|
383
|
+
const byReason = entry.metadata?.unconfirmedByReason;
|
|
384
|
+
if (byReason && typeof byReason === "object") {
|
|
385
|
+
for (const [reason, count] of Object.entries(byReason)) {
|
|
386
|
+
const n = Number(count) || 0;
|
|
387
|
+
if (n > 0) ws.unconfirmedByReason.inc(reason, n);
|
|
388
|
+
}
|
|
389
|
+
} else {
|
|
390
|
+
// Vintage-attribution fallback: no `unconfirmedByReason` means
|
|
391
|
+
// this line predates #1618 — the absent field IS the signal,
|
|
392
|
+
// not proof every file here was really a budget timeout.
|
|
393
|
+
ws.unconfirmedByReason.inc(
|
|
394
|
+
"budget (pre-#1618 build)",
|
|
395
|
+
timedOut,
|
|
396
|
+
);
|
|
397
|
+
}
|
|
352
398
|
state.smellTotals.inc("lsp-workspace-file-timeouts");
|
|
353
399
|
pushTop(
|
|
354
400
|
ws.sweeps,
|
|
@@ -737,6 +783,39 @@ async function analyzeAstGrepTools(files, state) {
|
|
|
737
783
|
}
|
|
738
784
|
}
|
|
739
785
|
|
|
786
|
+
/**
|
|
787
|
+
* Per-model rollup (#1448): rule × model counts and auto-fixed vs
|
|
788
|
+
* agent-required rates, from worklog.jsonl's optional `model`/`provider`
|
|
789
|
+
* fields. Entries predating #1448 (or written outside a live agent turn)
|
|
790
|
+
* have neither field — bucketed under the empty-string model/provider key so
|
|
791
|
+
* "unattributed" volume stays visible rather than silently dropped.
|
|
792
|
+
*/
|
|
793
|
+
async function analyzeWorklog(files, state) {
|
|
794
|
+
for (const file of files) {
|
|
795
|
+
await forEachJsonLine(file, "worklog", state, (entry) => {
|
|
796
|
+
const ts = dateOf(entry.timestamp);
|
|
797
|
+
if (!inWindow(ts)) return;
|
|
798
|
+
state.seen.inc("worklog");
|
|
799
|
+
const rule = entry.rule ?? "unknown";
|
|
800
|
+
const model = entry.model ?? "";
|
|
801
|
+
const provider = entry.provider ?? "";
|
|
802
|
+
const key = `${rule}||${model}`;
|
|
803
|
+
const row = state.worklog.byRuleModel.get(key) ?? {
|
|
804
|
+
rule,
|
|
805
|
+
model,
|
|
806
|
+
total: 0,
|
|
807
|
+
autoFixed: 0,
|
|
808
|
+
};
|
|
809
|
+
row.total += 1;
|
|
810
|
+
if (entry.autoFixed) row.autoFixed += 1;
|
|
811
|
+
state.worklog.byRuleModel.set(key, row);
|
|
812
|
+
state.worklog.byModel.inc(model || "(unknown)");
|
|
813
|
+
if (entry.autoFixed) state.worklog.byModelAutoFixed.inc(model || "(unknown)");
|
|
814
|
+
state.worklog.byProvider.inc(provider || "(unknown)");
|
|
815
|
+
});
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
|
|
740
819
|
async function forEachJsonLine(file, bucket, state, visitor) {
|
|
741
820
|
await forEachLine(file, async (line) => {
|
|
742
821
|
if (!line.trim()) return;
|
|
@@ -1166,11 +1245,21 @@ function buildReport(state) {
|
|
|
1166
1245
|
"Full LSP workspace sweeps that logged a start but never a completion (hang/kill signature — the 8h-hang class #383 hardened)",
|
|
1167
1246
|
ws.progress.slice(0, limit),
|
|
1168
1247
|
);
|
|
1248
|
+
// #1618: "hit the per-file budget" used to be this smell's blanket
|
|
1249
|
+
// description regardless of WHY a file was unconfirmed — the exact
|
|
1250
|
+
// mislabeling the forensics pass on this class found (81/111 "budget"
|
|
1251
|
+
// files were actually service-destroyed). Render the real breakdown when
|
|
1252
|
+
// available.
|
|
1253
|
+
const unconfirmedReasonBreakdown = ws.unconfirmedByReason
|
|
1254
|
+
.top(limit)
|
|
1255
|
+
.map(({ key, count }) => `${key}=${count}`)
|
|
1256
|
+
.join(", ");
|
|
1169
1257
|
addSmell(
|
|
1170
1258
|
smells,
|
|
1171
1259
|
"lsp-workspace-file-timeouts",
|
|
1172
1260
|
smellCount("lsp-workspace-file-timeouts"),
|
|
1173
|
-
`Full LSP sweeps
|
|
1261
|
+
`Full LSP sweeps produced an unconfirmed file (${ws.timedOutFilesTotal} files across ${ws.timedOutSweeps} sweeps)` +
|
|
1262
|
+
(unconfirmedReasonBreakdown ? ` — by reason: ${unconfirmedReasonBreakdown}` : ""),
|
|
1174
1263
|
ws.sweeps.slice(0, limit),
|
|
1175
1264
|
);
|
|
1176
1265
|
|
|
@@ -1206,6 +1295,11 @@ function buildReport(state) {
|
|
|
1206
1295
|
aborted: ws.aborted,
|
|
1207
1296
|
timedOutSweeps: ws.timedOutSweeps,
|
|
1208
1297
|
timedOutFilesTotal: ws.timedOutFilesTotal,
|
|
1298
|
+
// #1618: the real per-reason breakdown of `timedOutFilesTotal`.
|
|
1299
|
+
// "budget (pre-#1618 build)" means those log lines predate the
|
|
1300
|
+
// per-reason tally entirely — an older build's absence of the field,
|
|
1301
|
+
// not a claim those files really timed out.
|
|
1302
|
+
unconfirmedByReason: ws.unconfirmedByReason.toJSON(),
|
|
1209
1303
|
},
|
|
1210
1304
|
},
|
|
1211
1305
|
cascade: {
|
|
@@ -1259,6 +1353,17 @@ function buildReport(state) {
|
|
|
1259
1353
|
errors: state.astGrep.errors.slice(0, limit),
|
|
1260
1354
|
slow: state.astGrep.slow.slice(0, limit),
|
|
1261
1355
|
},
|
|
1356
|
+
worklog: {
|
|
1357
|
+
byModel: state.worklog.byModel.top(limit * 2),
|
|
1358
|
+
byProvider: state.worklog.byProvider.top(limit * 2),
|
|
1359
|
+
byRuleModel: [...state.worklog.byRuleModel.values()]
|
|
1360
|
+
.map((row) => ({
|
|
1361
|
+
...row,
|
|
1362
|
+
autoFixedRate: row.total ? row.autoFixed / row.total : 0,
|
|
1363
|
+
}))
|
|
1364
|
+
.sort((a, b) => b.total - a.total)
|
|
1365
|
+
.slice(0, limit * 3),
|
|
1366
|
+
},
|
|
1262
1367
|
};
|
|
1263
1368
|
}
|
|
1264
1369
|
|
|
@@ -1396,7 +1501,33 @@ function printReport(report) {
|
|
|
1396
1501
|
console.log(
|
|
1397
1502
|
` started=${ws.started} completed=${ws.completed} incomplete=${ws.incomplete} aborted=${ws.aborted} fileTimeouts=${ws.timedOutFilesTotal} (in ${ws.timedOutSweeps} sweeps)`,
|
|
1398
1503
|
);
|
|
1504
|
+
// #1618: never let a flat count alone read as "budget exhaustion" —
|
|
1505
|
+
// print the real per-reason split (or its absence, which itself means
|
|
1506
|
+
// every line here predates the tally).
|
|
1507
|
+
const reasons = Object.entries(ws.unconfirmedByReason ?? {});
|
|
1508
|
+
if (reasons.length) {
|
|
1509
|
+
console.log(
|
|
1510
|
+
` by reason: ${reasons.map(([reason, count]) => `${reason}=${count}`).join(", ")}`,
|
|
1511
|
+
);
|
|
1512
|
+
}
|
|
1399
1513
|
}
|
|
1514
|
+
const wl = report.worklog;
|
|
1515
|
+
if (wl && (wl.byModel.length || wl.byRuleModel.length)) {
|
|
1516
|
+
console.log("\nWorklog per-model rollup (#1448)");
|
|
1517
|
+
console.log(
|
|
1518
|
+
` by model: ${wl.byModel.map((x) => `${x.key}=${x.count}`).join(", ")}`,
|
|
1519
|
+
);
|
|
1520
|
+
if (wl.byProvider.length)
|
|
1521
|
+
console.log(
|
|
1522
|
+
` by provider: ${wl.byProvider.map((x) => `${x.key}=${x.count}`).join(", ")}`,
|
|
1523
|
+
);
|
|
1524
|
+
console.log(" rule × model (auto-fixed vs agent-required):");
|
|
1525
|
+
for (const row of wl.byRuleModel.slice(0, limit))
|
|
1526
|
+
console.log(
|
|
1527
|
+
` ${String(row.total).padStart(5)} ${row.rule} [${row.model || "(unknown)"}] autoFixed=${row.autoFixed} (${(row.autoFixedRate * 100).toFixed(0)}%)`,
|
|
1528
|
+
);
|
|
1529
|
+
}
|
|
1530
|
+
|
|
1400
1531
|
const timeouts = Object.entries(report.latency.phaseTimeouts ?? {});
|
|
1401
1532
|
if (timeouts.length) {
|
|
1402
1533
|
console.log("\nPhase timeouts");
|
|
@@ -39,6 +39,24 @@ export const SOURCE_OVERRIDES = {
|
|
|
39
39
|
url: "https://unpkg.com/@tree-sitter-grammars/tree-sitter-yaml@0.7.1/tree-sitter-yaml.wasm",
|
|
40
40
|
},
|
|
41
41
|
};
|
|
42
|
+
/**
|
|
43
|
+
* Grammars committed under `vendor/grammars/` rather than fetched.
|
|
44
|
+
*
|
|
45
|
+
* tree-sitter-cue: no published wasm exists — npm's `tree-sitter-cue` is a
|
|
46
|
+
* native binding, the `tree-sitter-wasms` aggregator has no CUE, and upstream
|
|
47
|
+
* cuts no releases — so we build it from a pinned commit (#1522).
|
|
48
|
+
*/
|
|
49
|
+
export const VENDORED_GRAMMARS = {
|
|
50
|
+
"tree-sitter-cue.wasm": {
|
|
51
|
+
repo: "https://github.com/eonpatapon/tree-sitter-cue",
|
|
52
|
+
commit: "dd7b90e0770ff18070c515937ba3c3d6d93db00e",
|
|
53
|
+
license: "MIT",
|
|
54
|
+
buildCommand: "npx tree-sitter-cli build --wasm",
|
|
55
|
+
sha256: "sha256:751f8cc8ccf72da760133e3d365562ff7bbf5b951e0b73568576fd159db7d601",
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
/** Directory the committed grammars live in, relative to the package root. */
|
|
59
|
+
export const VENDORED_DIR = "vendor/grammars";
|
|
42
60
|
/** The package a grammar's sidecar records (override or the global aggregator). */
|
|
43
61
|
export function expectedPackage(filename, manifest) {
|
|
44
62
|
return manifest.overrides?.[filename]?.package ?? SOURCE_OVERRIDES[filename]?.package ?? manifest.package;
|
|
@@ -210,6 +228,13 @@ async function regenerateManifest() {
|
|
|
210
228
|
version: TREE_SITTER_WASMS_VERSION,
|
|
211
229
|
grammars: sorted,
|
|
212
230
|
...(Object.keys(SOURCE_OVERRIDES).length ? { overrides: SOURCE_OVERRIDES } : {}),
|
|
231
|
+
// Re-emitted from the map above, not copied from the old manifest: a
|
|
232
|
+
// `--write-manifest` run on a tree-sitter-wasms bump must not silently
|
|
233
|
+
// drop the committed grammars' provenance, which would leave the guard
|
|
234
|
+
// with nothing to check.
|
|
235
|
+
...(Object.keys(VENDORED_GRAMMARS).length
|
|
236
|
+
? { vendored: VENDORED_GRAMMARS }
|
|
237
|
+
: {}),
|
|
213
238
|
};
|
|
214
239
|
writeFileSync(MANIFEST_PATH, `${JSON.stringify(manifest, null, 2)}\n`);
|
|
215
240
|
console.error(`Wrote ${MANIFEST_PATH} (${GRAMMARS.length} grammars).`);
|
|
@@ -40,5 +40,14 @@
|
|
|
40
40
|
"version": "0.7.1",
|
|
41
41
|
"url": "https://unpkg.com/@tree-sitter-grammars/tree-sitter-yaml@0.7.1/tree-sitter-yaml.wasm"
|
|
42
42
|
}
|
|
43
|
+
},
|
|
44
|
+
"vendored": {
|
|
45
|
+
"tree-sitter-cue.wasm": {
|
|
46
|
+
"repo": "https://github.com/eonpatapon/tree-sitter-cue",
|
|
47
|
+
"commit": "dd7b90e0770ff18070c515937ba3c3d6d93db00e",
|
|
48
|
+
"license": "MIT",
|
|
49
|
+
"buildCommand": "npx tree-sitter-cli build --wasm",
|
|
50
|
+
"sha256": "sha256:751f8cc8ccf72da760133e3d365562ff7bbf5b951e0b73568576fd159db7d601"
|
|
51
|
+
}
|
|
43
52
|
}
|
|
44
53
|
}
|
|
@@ -52,12 +52,17 @@ Use `$$$` when you don't need the captured value; `$$$NAME` when you do.
|
|
|
52
52
|
|
|
53
53
|
Use these instead of writing raw YAML:
|
|
54
54
|
|
|
55
|
-
| Parameter | What it does |
|
|
56
|
-
|
|
57
|
-
| `insideKind` | Only match inside an ancestor of this node kind |
|
|
58
|
-
| `hasKind` | Only match nodes
|
|
59
|
-
| `
|
|
60
|
-
| `
|
|
55
|
+
| Parameter | Tool | What it does |
|
|
56
|
+
|---|---|---|
|
|
57
|
+
| `insideKind` | both | Only match inside an ancestor of this node kind (searches ALL ancestors, `stopBy: end`) |
|
|
58
|
+
| `hasKind` | both | Only match nodes whose **immediate child** has this kind (`stopBy: neighbor` — NOT recursive) |
|
|
59
|
+
| `hasDescendantKind` | both | Only match nodes containing this kind **anywhere in their descendants** (`stopBy: end`) — use this instead of `hasKind` when the target isn't a direct child |
|
|
60
|
+
| `follows` | both | Only match nodes preceded by a sibling matching this pattern |
|
|
61
|
+
| `precedes` | both | Only match nodes followed by a sibling matching this pattern |
|
|
62
|
+
|
|
63
|
+
`hasKind` and `hasDescendantKind` are mutually exclusive on both tools — combining them errors.
|
|
64
|
+
|
|
65
|
+
⚠ `insideKind` searches ALL ancestors (`stopBy: end`) with no boundary of its own — on a deeply nested file it can escalate past the enclosing function you meant and match against an unrelated outer scope; scope with `paths` or a raw YAML `rule:` with its own `stopBy` boundary if that matters.
|
|
61
66
|
|
|
62
67
|
```
|
|
63
68
|
# console.log only inside functions
|
|
@@ -152,13 +157,9 @@ Use these as starting points, then scope `paths` tightly.
|
|
|
152
157
|
|
|
153
158
|
| Task | Pattern / params |
|
|
154
159
|
|---|---|
|
|
155
|
-
| Find pi lifecycle handlers | `pattern: pi.on($EVENT, $HANDLER)` |
|
|
156
|
-
| Find timers | `pattern: setTimeout($CALLBACK, $$$REST)` or `setInterval($CALLBACK, $$$REST)` |
|
|
157
|
-
| Find immediate/deferred work | `pattern: setImmediate($CALLBACK)` |
|
|
158
|
-
| Find promise callbacks | `pattern: $PROMISE.then($CALLBACK)` / `.catch($CALLBACK)` / `.finally($CALLBACK)` |
|
|
159
160
|
| Find object-literal function dependency by name | `pattern: { resetLSPService: $FN, $$$REST }` |
|
|
160
|
-
| Find fire-and-forget async calls | `pattern: void $CALL` |
|
|
161
161
|
| Find empty catches | `pattern: try { $$$BODY } catch ($ERR) { }` |
|
|
162
|
+
| Find fire-and-forget async calls | `pattern: void $CALL` |
|
|
162
163
|
|
|
163
164
|
For lifecycle bugs, search first, then use the returned `details.matchLocations[].readSlice` handle for bounded context.
|
|
164
165
|
|
|
@@ -13,39 +13,39 @@ Use `lsp_diagnostics` before builds/tests or after touching several files:
|
|
|
13
13
|
|
|
14
14
|
| Need | Tool call |
|
|
15
15
|
|---|---|
|
|
16
|
-
| Check one file | `lsp_diagnostics({
|
|
17
|
-
| Check a folder | `lsp_diagnostics({
|
|
18
|
-
| Check exact touched files | `lsp_diagnostics({
|
|
19
|
-
| Slow server (Rust, Java) | `lsp_diagnostics({
|
|
20
|
-
| Include warnings | `lsp_diagnostics({
|
|
16
|
+
| Check one file | `lsp_diagnostics({ path: "src/file.ts" })` |
|
|
17
|
+
| Check a folder | `lsp_diagnostics({ path: "src/", severity: "error" })` |
|
|
18
|
+
| Check exact touched files | `lsp_diagnostics({ paths: ["src/a.ts", "src/b.ts"], concurrency: 8 })` |
|
|
19
|
+
| Slow server (Rust, Java) | `lsp_diagnostics({ paths: files, waitMs: 2000 })` |
|
|
20
|
+
| Include warnings | `lsp_diagnostics({ paths: files, severity: "all" })` |
|
|
21
21
|
|
|
22
|
-
Prefer explicit `
|
|
22
|
+
Prefer explicit `paths` batches after multi-file edits — bounded concurrency, no unrelated directory noise.
|
|
23
23
|
|
|
24
24
|
## Navigation (Code Intelligence)
|
|
25
25
|
|
|
26
26
|
| Question | Operation | Parameters |
|
|
27
27
|
|---|---|---|
|
|
28
|
-
| Where is this defined? | `definition` |
|
|
29
|
-
| Where is this symbol's *type* defined? | `typeDefinition` |
|
|
30
|
-
| Where is this declared (vs defined)? | `declaration` |
|
|
31
|
-
| Find all usages | `references` |
|
|
32
|
-
| What type is this? | `hover` |
|
|
33
|
-
| Call signature | `signatureHelp` |
|
|
34
|
-
| Symbols in this file | `documentSymbol` |
|
|
35
|
-
| Find symbol across project | `workspaceSymbol` | query +
|
|
36
|
-
| Quick fixes available | `codeAction` |
|
|
37
|
-
| Rename symbol safely | `rename` |
|
|
38
|
-
| Who implements this? | `implementation` |
|
|
39
|
-
| Who calls this function? | `prepareCallHierarchy` → `incomingCalls` |
|
|
40
|
-
| What does this call? | `prepareCallHierarchy` → `outgoingCalls` |
|
|
41
|
-
| What commands does the server offer? | `capabilities` | (optional
|
|
28
|
+
| Where is this defined? | `definition` | path, line, character |
|
|
29
|
+
| Where is this symbol's *type* defined? | `typeDefinition` | path, line, character |
|
|
30
|
+
| Where is this declared (vs defined)? | `declaration` | path, line, character |
|
|
31
|
+
| Find all usages | `references` | path, line, character |
|
|
32
|
+
| What type is this? | `hover` | path, line, character |
|
|
33
|
+
| Call signature | `signatureHelp` | path, line, character (at arg position) |
|
|
34
|
+
| Symbols in this file | `documentSymbol` | path |
|
|
35
|
+
| Find symbol across project | `workspaceSymbol` | query + path (strongly recommended) |
|
|
36
|
+
| Quick fixes available | `codeAction` | path, line, character, endLine, endCharacter |
|
|
37
|
+
| Rename symbol safely | `rename` | path, line, character, newName |
|
|
38
|
+
| Who implements this? | `implementation` | path, line, character |
|
|
39
|
+
| Who calls this function? | `prepareCallHierarchy` → `incomingCalls` | path, line, character |
|
|
40
|
+
| What does this call? | `prepareCallHierarchy` → `outgoingCalls` | path, line, character |
|
|
41
|
+
| What commands does the server offer? | `capabilities` | (optional path) — lists advertised commands |
|
|
42
42
|
| Run a server command (e.g. organize imports) | `executeCommand` | command (+ commandArguments); dry-run unless `apply:true` |
|
|
43
43
|
|
|
44
44
|
## Call Hierarchy Pattern
|
|
45
45
|
|
|
46
46
|
```
|
|
47
47
|
// Step 1
|
|
48
|
-
lsp_navigation(operation="prepareCallHierarchy",
|
|
48
|
+
lsp_navigation(operation="prepareCallHierarchy", path="src/api.ts", line=42, character=10)
|
|
49
49
|
// → returns callHierarchyItem
|
|
50
50
|
|
|
51
51
|
// Step 2
|
|
@@ -56,7 +56,7 @@ lsp_navigation(operation="outgoingCalls", callHierarchyItem=<item from step 1>)
|
|
|
56
56
|
## Operational Notes
|
|
57
57
|
|
|
58
58
|
- **`definition` returns nothing?** The file may not be open/indexed yet. Read it first, then retry.
|
|
59
|
-
- **`workspaceSymbol` empty?** Always pass `
|
|
59
|
+
- **`workspaceSymbol` empty?** Always pass `path`. Unscoped queries are best-effort and frequently return nothing. If TypeScript returns "No Project", open the scoped file first.
|
|
60
60
|
- **`references`** — query from the *definition site* for full cross-file coverage; usage-site queries can be partial.
|
|
61
61
|
- **`signatureHelp`** — only valid at call-site argument positions; declaration positions return empty.
|
|
62
62
|
- **`workspaceDiagnostics`** — tracked push snapshot only, not an active check. Use `lsp_diagnostics` when you need fresh results.
|