@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
|
@@ -13,7 +13,7 @@ Same `id` as a built-in overrides it. Multiple rules per file: separate with `--
|
|
|
13
13
|
```yaml
|
|
14
14
|
id: no-foo-bar
|
|
15
15
|
language: TypeScript # PascalCase — see languages below
|
|
16
|
-
severity: warning # error | warning | info
|
|
16
|
+
severity: warning # error | warning | hint | info — pick by evidence, see below
|
|
17
17
|
message: "Avoid foo.bar() — use baz() instead"
|
|
18
18
|
note: |
|
|
19
19
|
Longer explanation / fix guidance here.
|
|
@@ -21,6 +21,39 @@ rule:
|
|
|
21
21
|
pattern: foo.bar($ARG)
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
+
**Pick the severity by the evidence behind the rule, not by feel:**
|
|
25
|
+
|
|
26
|
+
- **`error`** — only with a documented zero-false-positive audit in the `note`.
|
|
27
|
+
Only `error` maps to semantic `blocking` and stops a turn.
|
|
28
|
+
- **`warning`** — a real finding with a known, bounded false-positive rate.
|
|
29
|
+
- **`hint` / `info`** — style opinions. They render as advisory text, never
|
|
30
|
+
block, and lose the report budget to warnings when a report is capped.
|
|
31
|
+
|
|
32
|
+
Full policy and the `error`-promotion procedure: AGENTS.md's "Severity policy
|
|
33
|
+
(#1777)" section. Read it before shipping anything above `warning`.
|
|
34
|
+
|
|
35
|
+
## Before promoting to error
|
|
36
|
+
|
|
37
|
+
Three things must all be true, and the rule's `note` must record them:
|
|
38
|
+
|
|
39
|
+
1. **A multi-corpus false-positive census**, not a single-tree count. Run the
|
|
40
|
+
rule over pi-lens's `clients/`/`tests/` plus at least one real external
|
|
41
|
+
codebase of the kind the rule targets, classify every hit, and put the
|
|
42
|
+
table in the note.
|
|
43
|
+
2. **Structural narrowing before exemption.** Suppress a legitimate idiom
|
|
44
|
+
with a relational constraint (`inside`/`has`/`follows`, scoped path
|
|
45
|
+
globs), not with prose telling readers to ignore the hit. Narrow first —
|
|
46
|
+
don't reach for a lower tier as the easy way out. `no-non-null-assertion`
|
|
47
|
+
was demoted to `hint` (`0124608a`), then reverted back to `warning` once
|
|
48
|
+
the same false positives were closed with a structural exclusion instead
|
|
49
|
+
(`b3e1fd79`).
|
|
50
|
+
3. **Self-scan wiring.** Tag the rule `metadata.category: pi-lens-self-scan`
|
|
51
|
+
so `npm run astgrep:self-scan` holds this tree at zero in CI. An `error`
|
|
52
|
+
rule that never runs against pi-lens's own source is an unaudited claim.
|
|
53
|
+
|
|
54
|
+
If the post-narrowing residual is still tens of legitimate hits, stop and
|
|
55
|
+
report the numbers instead of shipping at `error`.
|
|
56
|
+
|
|
24
57
|
## Language values
|
|
25
58
|
|
|
26
59
|
`TypeScript` `JavaScript` `Python` `Go` `Rust` `Java` `C` `Cpp` `CSharp` `Kotlin` `Ruby` `Php`
|
|
@@ -67,7 +100,14 @@ constraints: # metavariable regex constraints work
|
|
|
67
100
|
|
|
68
101
|
⚠ **`has`/`inside` default to the immediate child/parent (`stopBy: neighbor`).** For a
|
|
69
102
|
recursive descendant/ancestor search add `stopBy: end`. This is the #1 migration
|
|
70
|
-
gotcha — see the `has` note
|
|
103
|
+
gotcha — see the `has` note in `reference.md`.
|
|
104
|
+
|
|
105
|
+
⚠ **`stopBy: end` alone is not a boundary.** It's a search-depth control — how far
|
|
106
|
+
the walk searches — not a stop condition; the `any:` kind list only decides what
|
|
107
|
+
CAN satisfy the match, not where the walk halts. To scope a relation to the
|
|
108
|
+
nearest enclosing function (or any other boundary), give `stopBy` its own rule.
|
|
109
|
+
See "Scoping to the nearest enclosing X" in `reference.md` (#1794 F1 — this bug
|
|
110
|
+
shipped twice in one window).
|
|
71
111
|
|
|
72
112
|
## YAML quoting — REQUIRED (js-yaml will reject the rule otherwise)
|
|
73
113
|
|
|
@@ -100,123 +140,54 @@ The parser is a real YAML parser, so unquoted special chars throw and the rule i
|
|
|
100
140
|
✅ Docs: docs/custom-rules.md
|
|
101
141
|
```
|
|
102
142
|
|
|
103
|
-
##
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
- the in-process NAPI fallback (`ast-grep-napi.ts`) parses the target file's
|
|
145
|
-
own grammar and currently runs both TS and JS rules on every jsts file. A
|
|
146
|
-
grammar-agnostic twin can therefore duplicate in fallback mode.
|
|
147
|
-
- **Decide explicitly:** if the rule must cover `.js` through the ast-grep
|
|
148
|
-
CLI/LSP baseline, ship the twin and test both. If a rule is NAPI-only or
|
|
149
|
-
fallback duplication is unacceptable, fix runner dedup/normalization before
|
|
150
|
-
relying on a single TypeScript rule for JS coverage.
|
|
151
|
-
- **Grammar-divergent bodies** still need separate variants regardless:
|
|
152
|
-
e.g. `no-flag-argument` uses `required_parameter` in TS and
|
|
153
|
-
`assignment_pattern` in JS.
|
|
154
|
-
|
|
155
|
-
✅ Node-kind facts (tree-sitter-typescript grammar — NOT the TS compiler / Roslyn):
|
|
156
|
-
- let / const → `lexical_declaration` (var is NOT here)
|
|
157
|
-
- var → `variable_declaration`
|
|
158
|
-
- a regex literal's pattern text → `regex_pattern`
|
|
159
|
-
- x[i] index access → `subscript_expression` (NOT element_access_expression)
|
|
160
|
-
- obj.prop access → `member_expression` (NOT property_access_expression)
|
|
161
|
-
- !x / -x / typeof x → `unary_expression`
|
|
162
|
-
- a ? b : c → `ternary_expression`
|
|
163
|
-
|
|
164
|
-
❌ Wrong-grammar kind names = silent dead rule. `element_access_expression`,
|
|
165
|
-
`property_access_expression`, `binary_operator`, etc. are TS-compiler/Roslyn names, not
|
|
166
|
-
tree-sitter's. napi REJECTS the whole rule ("invalid kind matcher") so it never runs.
|
|
167
|
-
Verify a kind exists before shipping:
|
|
168
|
-
node -e 'import("@ast-grep/napi").then(s=>{const r=s.ts.parse("x[i]").root();
|
|
169
|
-
const f=(n,k)=>{let c=n.kind()===k?1:0;for(const x of n.children())c+=f(x,k);return c};
|
|
170
|
-
console.log(f(r,"subscript_expression"))})' # >0 means the kind is real
|
|
171
|
-
|
|
172
|
-
✅ Test through the REAL runner from the repo root — it loads the actual shipped
|
|
173
|
-
rules from rules/ast-grep-rules/rules. Assert on diagnostic `rule` ids:
|
|
174
|
-
const res = await runner.run(ctx); // ctx.filePath = temp .ts, cwd = repo
|
|
175
|
-
For pattern/kind/regex-only rules (CLI-identical semantics) `ast-grep scan` is fine.
|
|
176
|
-
|
|
177
|
-
✅ Before shipping any text/regex detector, FP-scan the codebase:
|
|
178
|
-
ast-grep scan -r <rule>.yml clients tools
|
|
179
|
-
Real safe variants bite (e.g. ReDoS: (ba+)+ is safe — a mandatory prefix makes
|
|
180
|
-
the partition unique; flag only a single quantified atom inside the group).
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
## Matching things a pattern can't express (#305)
|
|
184
|
-
|
|
185
|
-
```
|
|
186
|
-
❌ A parameter default is NOT a `$X = false` pattern. `pattern: $FLAG = false` parses as
|
|
187
|
-
an `assignment_expression` (statement context) and never matches a function parameter.
|
|
188
|
-
Match the PARAM NODE + its child literal instead, capturing the name for reuse:
|
|
189
|
-
# TS grammar
|
|
190
|
-
- kind: required_parameter
|
|
191
|
-
all:
|
|
192
|
-
- has: { field: pattern, pattern: $FLAG }
|
|
193
|
-
- has: { any: [ { kind: "true" }, { kind: "false" } ] }
|
|
194
|
-
# JS grammar (assignment_pattern, with fields left/right)
|
|
195
|
-
- kind: assignment_pattern
|
|
196
|
-
all:
|
|
197
|
-
- has: { field: left, pattern: $FLAG }
|
|
198
|
-
- has: { field: right, any: [ { kind: "true" }, { kind: "false" } ] }
|
|
199
|
-
|
|
200
|
-
✅ Metavar consistency works ACROSS sibling clauses of an `all` — a metavar bound in one
|
|
201
|
-
`has` must match the SAME text everywhere it reappears. Use it to CORRELATE nodes, which
|
|
202
|
-
is what makes a structural rule precise:
|
|
203
|
-
all:
|
|
204
|
-
- has: { stopBy: end, kind: required_parameter, has: { field: pattern, pattern: $FLAG } }
|
|
205
|
-
- has: { stopBy: end, any: [ { pattern: "if ($FLAG) $$$" }, { pattern: "if (!$FLAG) $$$" } ] }
|
|
206
|
-
This fires ONLY when the function branches on the SAME param it declared boolean — a
|
|
207
|
-
boolean default that's never branched on, or a branch on a different var, won't match.
|
|
208
|
-
|
|
209
|
-
❌ Two `has:` keys in one mapping silently OVERWRITE (YAML: last key wins). For multiple
|
|
210
|
-
descendant constraints use `all:` with a LIST of `has` entries, never repeated `has:`.
|
|
211
|
-
|
|
212
|
-
✅ Prefer a high-precision structural guard over an unbounded denylist. Message-chain
|
|
213
|
-
(Demeter) floods on fluent/promise/builder chains; rather than denylist every fluent
|
|
214
|
-
method name, REQUIRE the chain's first calls to be accessors (`get*`/`is*`/`has*`) via
|
|
215
|
-
`constraints` regex — promise/fluent/builder methods aren't accessor-named, so they're
|
|
216
|
-
excluded by construction. Precision over recall.
|
|
143
|
+
## Reference doc — read before writing a NAPI-runner-specific or hard-to-express rule
|
|
144
|
+
|
|
145
|
+
`reference.md` (same directory) covers: ReDoS-safe regex authoring, node-text
|
|
146
|
+
string-escape quirks, `has`/`inside` `stopBy` defaults (and when to override
|
|
147
|
+
them), scoping a relation to the nearest enclosing node with a `stopBy`
|
|
148
|
+
boundary rule, the `-js` twin dedup behavior (#657), boolean-parameter
|
|
149
|
+
matching across the TS/JS grammars, and precision-over-recall heuristics for
|
|
150
|
+
denylist-shaped rules. Read it when a rule isn't matching (or over-matching)
|
|
151
|
+
the way you expect, or before shipping a `regex`/`has`-heavy rule.
|
|
152
|
+
|
|
153
|
+
## Testing a suppression
|
|
154
|
+
|
|
155
|
+
Every relational suppression (a `has`/`inside`/`not` exclusion for a
|
|
156
|
+
legitimate idiom) needs two fixtures per bound metavariable, not one:
|
|
157
|
+
|
|
158
|
+
1. **A same-binding valid case** — the idiom the exclusion is meant to
|
|
159
|
+
suppress, with the metavariable bound consistently (same receiver, same
|
|
160
|
+
key).
|
|
161
|
+
2. **A mutation-guard invalid case** — the same shape with the binding
|
|
162
|
+
broken: a different key, a different receiver, or a boundary-crossing
|
|
163
|
+
lookalike (the guard lives in the wrong scope). This proves the
|
|
164
|
+
exclusion checks the BINDING, not just the pattern's presence somewhere
|
|
165
|
+
in the file.
|
|
166
|
+
|
|
167
|
+
`rules/ast-grep-rules/rule-tests/no-non-null-assertion-test.yml` is the model: alongside the
|
|
168
|
+
get-after-has/pop-after-length valid cases, it fixtures a different-key
|
|
169
|
+
guard, a different-map guard, and an outer-function guard that must NOT
|
|
170
|
+
suppress an inner closure — each one red if the corresponding binding check
|
|
171
|
+
is deleted.
|
|
172
|
+
|
|
173
|
+
Corpus silence is not evidence. A valve with zero corpus hits needs
|
|
174
|
+
adversarial fixtures MORE, not less — `redundant-unsafe-function` targets
|
|
175
|
+
Rust, so it has no pi-lens corpus to census against, and its `# Safety`
|
|
176
|
+
valve still shipped an unbounded backward scan that over-suppressed real
|
|
177
|
+
detections, caught only by adversarial fixtures in review (`00284bcc`). A
|
|
178
|
+
documented blind spot (an idiom the rule knowingly can't distinguish from a
|
|
179
|
+
bug) becomes an `invalid`-direction fixture with a comment naming the gap,
|
|
180
|
+
never silence.
|
|
181
|
+
|
|
182
|
+
Regenerate the catalog doc with `npm run docs:rule-catalogs` after adding or
|
|
183
|
+
changing a rule — never hand-edit the generated catalog.
|
|
217
184
|
|
|
218
185
|
## Validating a candidate rule against the REAL engine (not the warm MCP cache)
|
|
219
186
|
|
|
187
|
+
Live-binary discipline (AGENTS.md shape 16) applies here too: verify parsing
|
|
188
|
+
and match behavior against a real `ast-grep` run before you write it into a
|
|
189
|
+
rule note or a test fixture — a hand-written fixture pins a guess, not a fact.
|
|
190
|
+
|
|
220
191
|
```
|
|
221
192
|
|
|
222
193
|
# inspect how a PATTERN parses → find the node kind you actually need
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# pi-lens ast-grep Rule Reference
|
|
2
|
+
|
|
3
|
+
Deep-dive companion to `SKILL.md`. Read this when you're debugging a rule
|
|
4
|
+
that isn't matching (or over-matching) the way you expect: ReDoS-safe regex
|
|
5
|
+
authoring, string-escape quirks in node text, `has`/`inside` `stopBy`
|
|
6
|
+
defaults and when to override them, boolean-parameter matching across two
|
|
7
|
+
grammars, and precision-over-recall heuristics for denylist-shaped rules.
|
|
8
|
+
|
|
9
|
+
## Hard-won gotchas (NAPI runner specifics — verified)
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
⚠ `has`/`inside` default to DIRECT child/parent — add `stopBy: end` for a recursive search.
|
|
13
|
+
This cuts BOTH ways, so think about where the target node actually lives:
|
|
14
|
+
- Target is a grandchild+ → you MUST add `stopBy: end` or the `has` never matches.
|
|
15
|
+
`switch-without-default` = `switch_statement` not has `switch_default`: the default
|
|
16
|
+
lives under `switch_body`, so without `stopBy: end` it matches nothing and every
|
|
17
|
+
switch (even ones WITH a default) is flagged. Same for `nested-ternary` catching a
|
|
18
|
+
parenthesized `a ? (b ? c : d) : e`.
|
|
19
|
+
- Target is the direct child → leave it at `neighbor` (default). Adding `stopBy: end`
|
|
20
|
+
OVER-reports: `throw_statement` has `string` + `stopBy: end` flags `throw new
|
|
21
|
+
Error("x")` (the string is nested), and `expression_statement` has `new_expression`
|
|
22
|
+
+ `stopBy: end` flags `fn(new Error())` as a discarded error. Keep these direct.
|
|
23
|
+
napi's `has` never matches the node itself, so a self-referential `kind: X` has
|
|
24
|
+
`kind: X` (with `stopBy: end`) correctly flags only genuinely-nested X.
|
|
25
|
+
|
|
26
|
+
✅ Prefer `regex` on the matched node's OWN text over `has` when you only need to
|
|
27
|
+
inspect the node — avoids recursive-descendant false positives:
|
|
28
|
+
kind: export_statement
|
|
29
|
+
regex: '^export\s+(let|var)\b' # precise; no has-recursion FP
|
|
30
|
+
(NAPI evaluates `regex` with JS RegExp on node.text() — keep it LINEAR so the
|
|
31
|
+
detector can't itself ReDoS.)
|
|
32
|
+
|
|
33
|
+
⚠ String-literal regexes match SOURCE text, not the runtime string value.
|
|
34
|
+
Inspect the exact node text before writing constraints:
|
|
35
|
+
ast-grep run --kind string --lang ts sample.ts --json=compact
|
|
36
|
+
Example: source `"\\|"` is node text `"\\\\|"` in JSON; to match a
|
|
37
|
+
source-level escaped backslash (`\\`) followed by a non-backslash, the rule
|
|
38
|
+
regex needs FOUR regex backslashes, preferably in a YAML block scalar:
|
|
39
|
+
regex: >-
|
|
40
|
+
^["'`]\\\\[^\\A-Za-z0-9$]
|
|
41
|
+
This is how `incomplete-string-escaping` catches both `"\\|"` and
|
|
42
|
+
`'\\"'`. Avoid shell here-doc probes for this class — shell/JSON escaping
|
|
43
|
+
can silently eat a backslash and make the rule look broken.
|
|
44
|
+
|
|
45
|
+
⚠ `-js` twins: remember there are TWO execution surfaces.
|
|
46
|
+
<!-- verified: clients/dispatch/runners/ast-grep-napi.ts:205-216,450-455, c170d94b -->
|
|
47
|
+
- ast-grep CLI/LSP language-gates by `language:`. A `language: TypeScript`
|
|
48
|
+
rule is not enough for standalone `.js` coverage, so shipped user-facing
|
|
49
|
+
TS/JS rules that should fire under the ast-grep LSP usually need a `-js`
|
|
50
|
+
twin with `language: JavaScript` plus its own fixture.
|
|
51
|
+
- the in-process NAPI fallback (`ast-grep-napi.ts` — pi-lens source checkout
|
|
52
|
+
only, not present in the installed package) already DEDUPES by grammar
|
|
53
|
+
(#657): `ruleLanguageForFile` (`ast-grep-napi.ts:205-216`) maps each file
|
|
54
|
+
extension to its actual grammar, and the matcher (`:450-455`) skips any
|
|
55
|
+
`language:`-tagged rule whose tag doesn't match that grammar. A TS rule
|
|
56
|
+
and its JS twin no longer double-fire on the same file in fallback mode.
|
|
57
|
+
- **`-js` twins are needed only when the rule body itself is
|
|
58
|
+
grammar-divergent** (different node kinds/fields between the TS and JS
|
|
59
|
+
grammars). A grammar-agnostic body doesn't need a twin for fallback
|
|
60
|
+
coverage — the dedup above already scopes it correctly; ship a twin only
|
|
61
|
+
when standalone `.js` coverage through the ast-grep CLI/LSP baseline is
|
|
62
|
+
required (see the first bullet).
|
|
63
|
+
- **Grammar-divergent bodies** still need separate variants regardless:
|
|
64
|
+
e.g. `no-flag-argument` uses `required_parameter` in TS and
|
|
65
|
+
`assignment_pattern` in JS.
|
|
66
|
+
|
|
67
|
+
✅ Node-kind facts (tree-sitter-typescript grammar — NOT the TS compiler / Roslyn):
|
|
68
|
+
- let / const → `lexical_declaration` (var is NOT here)
|
|
69
|
+
- var → `variable_declaration`
|
|
70
|
+
- a regex literal's pattern text → `regex_pattern`
|
|
71
|
+
- x[i] index access → `subscript_expression` (NOT element_access_expression)
|
|
72
|
+
- obj.prop access → `member_expression` (NOT property_access_expression)
|
|
73
|
+
- !x / -x / typeof x → `unary_expression`
|
|
74
|
+
- a ? b : c → `ternary_expression`
|
|
75
|
+
|
|
76
|
+
❌ Wrong-grammar kind names = silent dead rule. `element_access_expression`,
|
|
77
|
+
`property_access_expression`, `binary_operator`, etc. are TS-compiler/Roslyn names, not
|
|
78
|
+
tree-sitter's. napi REJECTS the whole rule ("invalid kind matcher") so it never runs.
|
|
79
|
+
Verify a kind exists before shipping:
|
|
80
|
+
node -e 'import("@ast-grep/napi").then(s=>{const r=s.ts.parse("x[i]").root();
|
|
81
|
+
const f=(n,k)=>{let c=n.kind()===k?1:0;for(const x of n.children())c+=f(x,k);return c};
|
|
82
|
+
console.log(f(r,"subscript_expression"))})' # >0 means the kind is real
|
|
83
|
+
|
|
84
|
+
✅ Test through the REAL runner from the pi-lens source checkout's repo root — it loads the actual shipped
|
|
85
|
+
rules from rules/ast-grep-rules/rules. Assert on diagnostic `rule` ids:
|
|
86
|
+
const res = await runner.run(ctx); // ctx.filePath = temp .ts, cwd = repo (pi-lens source checkout only — not present in the installed package)
|
|
87
|
+
For pattern/kind/regex-only rules (CLI-identical semantics) `ast-grep scan` is fine.
|
|
88
|
+
|
|
89
|
+
✅ Before shipping any text/regex detector, FP-scan the codebase:
|
|
90
|
+
ast-grep scan -r <rule>.yml clients tools
|
|
91
|
+
Real safe variants bite (e.g. ReDoS: (ba+)+ is safe — a mandatory prefix makes
|
|
92
|
+
the partition unique; flag only a single quantified atom inside the group).
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Scoping to the nearest enclosing X (#1794 F1)
|
|
96
|
+
|
|
97
|
+
`stopBy` controls how far the ancestor/descendant walk searches. It is not a
|
|
98
|
+
stop CONDITION. An `any:` kind list inside `inside`/`has` decides which
|
|
99
|
+
nodes the walk is ALLOWED to match — it does not tell the walk where to
|
|
100
|
+
halt. `stopBy: end` alone searches every ancestor up to the file root, so a
|
|
101
|
+
guard several scopes out can suppress a finding inside an unrelated closure.
|
|
102
|
+
|
|
103
|
+
To scope a relation to the nearest enclosing function (or any other
|
|
104
|
+
boundary), give `stopBy` its OWN rule — the same kind list used as the
|
|
105
|
+
match target — so the walk stops at the first satisfying ancestor and can
|
|
106
|
+
never escalate past it:
|
|
107
|
+
|
|
108
|
+
```yaml
|
|
109
|
+
inside:
|
|
110
|
+
stopBy: # the BOUNDARY: halts the walk here
|
|
111
|
+
any:
|
|
112
|
+
- kind: function_declaration
|
|
113
|
+
- kind: method_definition
|
|
114
|
+
- kind: arrow_function
|
|
115
|
+
- kind: function_expression
|
|
116
|
+
any: # the MATCH TARGET: same list, different job
|
|
117
|
+
- kind: function_declaration
|
|
118
|
+
- kind: method_definition
|
|
119
|
+
- kind: arrow_function
|
|
120
|
+
- kind: function_expression
|
|
121
|
+
has:
|
|
122
|
+
stopBy: end
|
|
123
|
+
pattern: $M.has($K)
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
This is the fix for #1794 F1: an earlier `no-non-null-assertion` exclusion
|
|
127
|
+
used `stopBy: end` with only the `any:` kind list as the match target, so a
|
|
128
|
+
`.has()`/`.length` guard in an OUTER function suppressed a closure's `!`
|
|
129
|
+
several scopes in. The same defect shape — `stopBy: end` mistaken for a
|
|
130
|
+
boundary — shipped twice in the same 2026-08-20 window: once here, and once
|
|
131
|
+
in `redundant-unsafe-function`'s `# Safety` valve (an unbounded backward
|
|
132
|
+
comment scan, fixed in `00284bcc`). See
|
|
133
|
+
`rules/ast-grep-rules/rules/no-non-null-assertion.yml` for the full working
|
|
134
|
+
rule.
|
|
135
|
+
|
|
136
|
+
## Matching things a pattern can't express (#305)
|
|
137
|
+
|
|
138
|
+
```
|
|
139
|
+
❌ A parameter default is NOT a `$X = false` pattern. `pattern: $FLAG = false` parses as
|
|
140
|
+
an `assignment_expression` (statement context) and never matches a function parameter.
|
|
141
|
+
Match the PARAM NODE + its child literal instead, capturing the name for reuse:
|
|
142
|
+
# TS grammar
|
|
143
|
+
- kind: required_parameter
|
|
144
|
+
all:
|
|
145
|
+
- has: { field: pattern, pattern: $FLAG }
|
|
146
|
+
- has: { any: [ { kind: "true" }, { kind: "false" } ] }
|
|
147
|
+
# JS grammar (assignment_pattern, with fields left/right)
|
|
148
|
+
- kind: assignment_pattern
|
|
149
|
+
all:
|
|
150
|
+
- has: { field: left, pattern: $FLAG }
|
|
151
|
+
- has: { field: right, any: [ { kind: "true" }, { kind: "false" } ] }
|
|
152
|
+
|
|
153
|
+
✅ Metavar consistency works ACROSS sibling clauses of an `all` — a metavar bound in one
|
|
154
|
+
`has` must match the SAME text everywhere it reappears. Use it to CORRELATE nodes, which
|
|
155
|
+
is what makes a structural rule precise:
|
|
156
|
+
all:
|
|
157
|
+
- has: { stopBy: end, kind: required_parameter, has: { field: pattern, pattern: $FLAG } }
|
|
158
|
+
- has: { stopBy: end, any: [ { pattern: "if ($FLAG) $$$" }, { pattern: "if (!$FLAG) $$$" } ] }
|
|
159
|
+
This fires ONLY when the function branches on the SAME param it declared boolean — a
|
|
160
|
+
boolean default that's never branched on, or a branch on a different var, won't match.
|
|
161
|
+
|
|
162
|
+
❌ Two `has:` keys in one mapping silently OVERWRITE (YAML: last key wins). For multiple
|
|
163
|
+
descendant constraints use `all:` with a LIST of `has` entries, never repeated `has:`.
|
|
164
|
+
|
|
165
|
+
✅ Prefer a high-precision structural guard over an unbounded denylist. Message-chain
|
|
166
|
+
(Demeter) floods on fluent/promise/builder chains; rather than denylist every fluent
|
|
167
|
+
method name, REQUIRE the chain's first calls to be accessors (`get*`/`is*`/`has*`) via
|
|
168
|
+
`constraints` regex — promise/fluent/builder methods aren't accessor-named, so they're
|
|
169
|
+
excluded by construction. Precision over recall.
|
|
170
|
+
```
|
|
@@ -6,7 +6,7 @@ description: Use when writing a new pi-lens tree-sitter query rule YAML file —
|
|
|
6
6
|
# Writing a pi-lens tree-sitter Rule
|
|
7
7
|
|
|
8
8
|
Drop path: `rules/tree-sitter-queries/<language>/<id>.yml`
|
|
9
|
-
Language dir is **lowercase**: `typescript` `javascript` `tsx` `python` `go` `rust` `java` `csharp` `kotlin` `ruby` `cpp` `c` `css`
|
|
9
|
+
Language dir is **lowercase**: `typescript` `javascript` `tsx` `python` `go` `rust` `java` `csharp` `kotlin` `php` `ruby` `cpp` `c` `css`
|
|
10
10
|
|
|
11
11
|
Project rules merge with built-ins (both run). To disable a language's built-ins: rename dir to `<lang>-disabled/`.
|
|
12
12
|
|
|
@@ -115,6 +115,8 @@ predicates:
|
|
|
115
115
|
treeSitterRunner.run() via makeRealRunnerCtx (tests/support/real-runner-ctx.ts) —
|
|
116
116
|
runQueryOnFile bypasses dispatch (skip_test_files, tiers, delta, rule cache).
|
|
117
117
|
Template: tests/clients/dispatch/runners/tree-sitter-skip-test-files.test.ts.
|
|
118
|
+
(These test paths exist only in a pi-lens source checkout — the installed
|
|
119
|
+
npm package ships no tests/ directory.)
|
|
118
120
|
|
|
119
121
|
✅ JS files also run typescript/ rules (shared grammar) — one rule in
|
|
120
122
|
rules/tree-sitter-queries/typescript/ covers BOTH .ts and .js. No -js copy needed.
|
|
Binary file
|
|
@@ -7,6 +7,55 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [2.27.0] - 2026-08-20
|
|
11
|
+
|
|
12
|
+
### Highlights
|
|
13
|
+
- MCP servers can now come from packages, runtime extension APIs, or the usual config files.
|
|
14
|
+
- Static bearer tokens can use the OS credential store, with a stdin-only CLI for safer token management.
|
|
15
|
+
- Long-lived sessions recover better when remote MCP servers are slow, refreshed, or reconnected.
|
|
16
|
+
- OAuth flows clean up their callback listener when idle and work better inside nested terminal UI prompts.
|
|
17
|
+
- Search, metadata cache writes, direct-tool counts, and UI stream pruning now do less repeated work.
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
- `/pi-mcp` now works as an alias for `/mcp` when a host reserves `/mcp`. Thanks to [@inxeoz](https://github.com/inxeoz) for #391.
|
|
21
|
+
- `registerMcpServer({ pi, name, definition })` lets other extensions register and dispose session-scoped MCP servers at runtime. Registrations are proxy-tool-only, never persisted, and duplicate names fail closed. Thanks to [@bendavis78](https://github.com/bendavis78) and [@fmoda3](https://github.com/fmoda3) for the runtime API request in #376/#382.
|
|
22
|
+
- Pi packages can ship prefixed MCP server definitions with `pi.mcp` manifest entries, without asking users to edit MCP config files. Thanks to [@bendavis78](https://github.com/bendavis78) for #376 and [@fmoda3](https://github.com/fmoda3) for the manifest design.
|
|
23
|
+
- Static bearer tokens can opt into OS credential-store lookup with URL-bound records by setting `bearerTokenStore: true`. The new `pi-mcp-adapter token set|status|remove <server>` CLI reads tokens from stdin and never accepts a token as an argument. Thanks to [@AlexanderBartash](https://github.com/AlexanderBartash) for issue #366.
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
- Search ranking now reuses normalized MCP tool fields and keyword tokens per catalog.
|
|
27
|
+
- Per-request header commands collect process cleanup data in one snapshot per pass, reducing cold HTTP connect overhead.
|
|
28
|
+
- Metadata cache saves write compact JSON while preserving atomic replacement and cross-process merges.
|
|
29
|
+
- High-frequency UI stream event-log pruning tracks the latest checkpoint event ID instead of rescanning retained patches.
|
|
30
|
+
- The MCP panel reuses direct-tool counts and token totals across renders while keeping toggle and reconnect updates immediate.
|
|
31
|
+
|
|
32
|
+
### Fixed
|
|
33
|
+
- Short-lived `mcpScript` workers no longer emit false unmanaged file-descriptor warnings on Node 24. Thanks to [@blalor](https://github.com/blalor) for PR #407.
|
|
34
|
+
- OAuth callback listeners are released after idle auth flows, and MCP pickers stay hidden while nested OAuth input is active. Thanks to [@trevorleibert-mixpanel](https://github.com/trevorleibert-mixpanel) for PRs #403 and #404.
|
|
35
|
+
- Request-header command cleanup can scan large process lists without overflowing `spawnSync`'s 1 MiB default buffer, which previously caused spurious `HTTP request headers command cleanup failed: ps exited with code unknown` refresh failures on busy hosts. Thanks to [@rtfpessoa](https://github.com/rtfpessoa) for PR #399.
|
|
36
|
+
- Slow but healthy remote keep-alive servers are no longer marked failed when a bounded tools/list refresh times out. Thanks to [@brightmeowso](https://github.com/brightmeowso) for #400.
|
|
37
|
+
- Cached metadata reconstruction now reuses one selector candidate index, avoiding repeated scans of large cached catalogs at startup.
|
|
38
|
+
- MCP status consumers no longer see a connected catalog before Pi's model-facing tool surface is current. The first connected status snapshot now waits for direct-tool synchronization. Thanks to [@dmorn](https://github.com/dmorn) for PR #380.
|
|
39
|
+
- JSON-string MCP tool-call arguments are normalized before approval and transport, preserving all fields and embedded quotes. Thanks to [@sebbean](https://github.com/sebbean) for PR #377.
|
|
40
|
+
- Session tool approvals are scoped to the approved argument payload instead of every later call to the same tool. Thanks to [@spaceshipmike](https://github.com/spaceshipmike) for #367.
|
|
41
|
+
- MCP panel commands no longer hang in RPC, JSON, and print modes when terminal-only custom UI is unavailable. Thanks to [@shixin-guo](https://github.com/shixin-guo) for PR #365.
|
|
42
|
+
- Compact MCP rows now show a bounded tool-input preview and skip leading blank output lines in collapsed result previews.
|
|
43
|
+
- MCP gateway requests nested inside proxy `args` are recovered instead of silently showing status, and invalid nested gateway requests now fail with guidance. Thanks to [@ibrmora](https://github.com/ibrmora) for #363.
|
|
44
|
+
- Remote keep-alive tool catalogs refresh before user input, adapter-triggered turns, and health checks. Expired Streamable HTTP sessions reconnect so long-lived Pi sessions can discover replacement catalogs without restarting. Thanks to [@dmorn](https://github.com/dmorn) for #369 and PR #370.
|
|
45
|
+
|
|
46
|
+
## [2.26.0] - 2026-08-14
|
|
47
|
+
|
|
48
|
+
### Added
|
|
49
|
+
- Added per-server `requestHeadersCommand` support for deriving fail-closed HTTP headers from the exact outbound request on every Streamable HTTP or SSE call. Thanks @kgreen18 for PR #353.
|
|
50
|
+
- Added `settings.warnOnLargeDirectTools` to suppress the advisory for 75 or more resolved direct tools. Thanks @Roshvan for issue #358.
|
|
51
|
+
|
|
52
|
+
### Changed
|
|
53
|
+
- Refined request-header command result handling types without changing runtime behavior.
|
|
54
|
+
|
|
55
|
+
### Fixed
|
|
56
|
+
- Matched adapter-owned config and state paths to the host agent directory when Pi is rebranded, including its environment override and config directory. Thanks @mindplay-dk for issue #356.
|
|
57
|
+
- Avoided O(tools²) cross-server tool-name collision scans at startup by skipping collision candidates when selectors are absent and sharing one indexed candidate set when `includeTools` or `excludeTools` is configured. Thanks @mjlbach for PR #357 and @cataldoc for issue #354.
|
|
58
|
+
|
|
10
59
|
## [2.25.0] - 2026-08-13
|
|
11
60
|
|
|
12
61
|
### Added
|