@herbertgao/pi-extensions 2026.8.6 → 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 +1 -1
- package/node_modules/@herbertgao/pi-cc-extensions/README.md +1 -1
- 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/renderer/compact-mode.ts +94 -77
- 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 +6 -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 +17 -13
- 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 +21 -6
- package/node_modules/@herbertgao/pi-subagents/src/usage.ts +129 -1
- package/node_modules/@herbertgao/pi-subagents/src/worktree.ts +20 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/README.md +1 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/ask-user-question.ts +26 -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 +2 -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 +120 -111
- 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 +10 -6
- package/node_modules/@narumitw/pi-btw/src/btw.ts +36 -40
- 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 +45 -2
- package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +136 -45
- package/node_modules/pi-lens/CHANGELOG.md +909 -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 +126 -13
- package/node_modules/pi-lens/dist/clients/agent-nudge.js +67 -11
- 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 +61 -30
- 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/cascade-budget.js +196 -0
- package/node_modules/pi-lens/dist/clients/cascade-format.js +20 -1
- 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/dead-code-client.js +123 -31
- 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 +25 -3
- package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +147 -33
- package/node_modules/pi-lens/dist/clients/diagnostic-line-freshness.js +298 -0
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +52 -2
- package/node_modules/pi-lens/dist/clients/dispatch/integration.js +256 -88
- 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 +60 -53
- 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 +275 -13
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +21 -6
- 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 +734 -64
- 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 +9 -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/event-loop-monitor.js +28 -5
- package/node_modules/pi-lens/dist/clients/extension-log.js +22 -1
- 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/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 +31 -0
- package/node_modules/pi-lens/dist/clients/gitleaks-client.js +181 -8
- package/node_modules/pi-lens/dist/clients/govulncheck-client.js +109 -9
- package/node_modules/pi-lens/dist/clients/grammar-source.js +333 -10
- package/node_modules/pi-lens/dist/clients/host-ports.js +8 -0
- package/node_modules/pi-lens/dist/clients/installer/index.js +1114 -100
- 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 +82 -6
- package/node_modules/pi-lens/dist/clients/knip-client.js +310 -10
- 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 +440 -11
- 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-flag-registry.js +8 -0
- package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +102 -7
- package/node_modules/pi-lens/dist/clients/lsp/client.js +1516 -159
- package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +83 -1
- package/node_modules/pi-lens/dist/clients/lsp/document-drift.js +389 -0
- package/node_modules/pi-lens/dist/clients/lsp/index.js +2274 -147
- 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 +277 -16
- 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 +79 -3
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +43 -0
- 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/session.js +10 -2
- 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 +154 -33
- 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 +84 -14
- 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/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 +52 -4
- package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +96 -7
- package/node_modules/pi-lens/dist/clients/runtime-context.js +8 -1
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +308 -45
- package/node_modules/pi-lens/dist/clients/runtime-session.js +332 -9
- package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +217 -22
- package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +212 -79
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +575 -67
- 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 +157 -24
- package/node_modules/pi-lens/dist/clients/sg-runner.js +116 -22
- package/node_modules/pi-lens/dist/clients/single-flight.js +158 -0
- package/node_modules/pi-lens/dist/clients/stale-marker.js +17 -0
- package/node_modules/pi-lens/dist/clients/startup-timing.js +19 -1
- package/node_modules/pi-lens/dist/clients/test-runner-client.js +151 -16
- package/node_modules/pi-lens/dist/clients/tool-event.js +56 -5
- package/node_modules/pi-lens/dist/clients/tool-policy.js +125 -20
- 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/widget-state.js +336 -36
- package/node_modules/pi-lens/dist/clients/zizmor-config.js +214 -14
- package/node_modules/pi-lens/dist/index.js +67738 -55739
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +466 -54
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +132 -43
- package/node_modules/pi-lens/dist/tools/lsp-navigation.js +46 -7
- package/node_modules/pi-lens/docs/agent-guide.md +6 -1
- package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +515 -506
- package/node_modules/pi-lens/docs/dispositions.md +21 -0
- package/node_modules/pi-lens/docs/features.md +19 -5
- package/node_modules/pi-lens/docs/globalconfig.md +3 -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 +19 -1
- package/node_modules/pi-lens/docs/usage.md +1 -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 +15 -1
- 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-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 +2 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-test.yml +2 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-js-test.yml +2 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-test.yml +2 -1
- 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-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 +57 -12
- 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-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 +22 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply.yml +23 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get-js.yml +33 -5
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get.yml +34 -8
- 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 +6 -1
- 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 +53 -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 +2 -0
- package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/SKILL.md +80 -3
- package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/reference.md +41 -0
- package/node_modules/pi-lens/vendor/grammars/tree-sitter-cue.wasm +0 -0
- package/node_modules/pi-mcp-adapter/CHANGELOG.md +36 -0
- package/node_modules/pi-mcp-adapter/README.md +47 -5
- package/node_modules/pi-mcp-adapter/cli.js +163 -1
- package/node_modules/pi-mcp-adapter/commands.ts +128 -22
- package/node_modules/pi-mcp-adapter/config.ts +25 -7
- package/node_modules/pi-mcp-adapter/direct-tools.ts +5 -4
- 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/metadata-cache.ts +32 -21
- package/node_modules/pi-mcp-adapter/package-mcp-loader.ts +168 -0
- package/node_modules/pi-mcp-adapter/package.json +3 -1
- package/node_modules/pi-mcp-adapter/proxy-modes.ts +5 -4
- package/node_modules/pi-mcp-adapter/request-headers-command.ts +31 -37
- package/node_modules/pi-mcp-adapter/search-ranking.ts +92 -22
- package/node_modules/pi-mcp-adapter/server-manager.ts +140 -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-result-renderer.ts +44 -4
- package/node_modules/pi-mcp-adapter/types.ts +2 -0
- 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 +23 -0
- package/node_modules/pi-web-access/README.md +27 -9
- package/node_modules/pi-web-access/anysearch.ts +4 -2
- package/node_modules/pi-web-access/brave.ts +16 -4
- package/node_modules/pi-web-access/curator-page.ts +6 -3
- package/node_modules/pi-web-access/curator-server.ts +4 -1
- package/node_modules/pi-web-access/exa.ts +18 -7
- package/node_modules/pi-web-access/extract.ts +28 -3
- package/node_modules/pi-web-access/gemini-search.ts +16 -4
- package/node_modules/pi-web-access/index.ts +41 -57
- package/node_modules/pi-web-access/package.json +1 -1
- 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 +44 -22
- 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/package.json +13 -13
|
@@ -6,9 +6,325 @@ note: |
|
|
|
6
6
|
The ! operator bypasses TypeScript's null checking which can lead to
|
|
7
7
|
runtime errors. Use optional chaining (?.), nullish coalescing (??),
|
|
8
8
|
or explicit null checks instead.
|
|
9
|
+
|
|
10
|
+
#1777 census and decision: the original false-positive census (49
|
|
11
|
+
hits across pi-lens, nestjs/nest, and colinhacks/zod) found 88% of
|
|
12
|
+
hits were the narrow-after-check idiom TypeScript can't itself
|
|
13
|
+
verify. Two of those idiom shapes are common enough, and structural
|
|
14
|
+
enough, to exclude with an ast-grep relational constraint instead of
|
|
15
|
+
demoting the whole rule — so the rule stays at `warning` and gets
|
|
16
|
+
narrower instead:
|
|
17
|
+
|
|
18
|
+
1. `$M.get($K)!` when the enclosing function ALSO contains a call to
|
|
19
|
+
`$M.has($K)` — same receiver, same key (ast-grep enforces the
|
|
20
|
+
metavariable binding, so a `.has()` check on a DIFFERENT key or a
|
|
21
|
+
DIFFERENT map does not suppress the finding).
|
|
22
|
+
2. `$A.pop()!` / `$A.shift()!` inside a `while`/`for`/`if` whose
|
|
23
|
+
condition references `$A.length` — again same-array-binding, so a
|
|
24
|
+
length check on a different array does not suppress it.
|
|
25
|
+
|
|
26
|
+
Both exclusions are scoped to the nearest enclosing function via a
|
|
27
|
+
`stopBy` BOUNDARY rule, not the whole file.
|
|
28
|
+
|
|
29
|
+
Review round 1 found two proven defects in the first version of this
|
|
30
|
+
narrowing, both fixed here:
|
|
31
|
+
|
|
32
|
+
- **F1 (high):** the original `stopBy: end` on the `inside` relation
|
|
33
|
+
is a search-DEPTH flag, not a stop condition — it walked ancestors
|
|
34
|
+
all the way to the file root. The `any:` kind list only chose which
|
|
35
|
+
ancestor could SATISFY the match; it did not stop the walk. Result:
|
|
36
|
+
a `.has()`/`.length` guard in an OUTER function suppressed a
|
|
37
|
+
closure's `!` inside an INNER function, and closures are common in
|
|
38
|
+
this codebase. Fixed by giving `stopBy` its own RULE (the same
|
|
39
|
+
function-kind `any:` list) so the ancestor walk halts at the
|
|
40
|
+
nearest enclosing function no matter what — it can find a
|
|
41
|
+
satisfying guard there or fail, but it can never look further out.
|
|
42
|
+
- **F2 (medium):** the `has: pattern: $M.has($K)` search is blind to
|
|
43
|
+
branch polarity — `if (!m.has(k)) { return m.get(k)!; }` (a REAL
|
|
44
|
+
bug: the key is proven ABSENT on that branch) was suppressed
|
|
45
|
+
exactly like `if (m.has(k)) { return m.get(k)!; }` (safe). ast-grep
|
|
46
|
+
has no dataflow model to tell "guards the branch I'm in" from
|
|
47
|
+
"guards the branch I'm NOT in," so the fix is a blunter, safer
|
|
48
|
+
instrument: `not: inside: { kind: unary_expression }` on the `has`
|
|
49
|
+
pattern removes ANY negated `.has()` call from counting as a guard,
|
|
50
|
+
full stop. This closes the real-bug shape but also cost one
|
|
51
|
+
previously-correct suppression: `if (!m.has(k)) return; ...
|
|
52
|
+
m.get(k)!` (an early-return guard clause, genuinely safe) now flags
|
|
53
|
+
again, because ast-grep can't distinguish it from the bug shape
|
|
54
|
+
that shares its `!m.has(k)` syntax. Accepted: the two shapes are
|
|
55
|
+
structurally identical to a syntax matcher, and re-flagging safe
|
|
56
|
+
code is cheaper than missing the bug shape. Both directions are
|
|
57
|
+
fixtured in `rule-tests/no-non-null-assertion-test.yml`.
|
|
58
|
+
|
|
59
|
+
Approximation caveat: even after F1/F2, ast-grep matches
|
|
60
|
+
structurally, not semantically. It cannot verify the guard genuinely
|
|
61
|
+
DOMINATES the use (no intervening mutation of `$M`/`$A` or
|
|
62
|
+
reassignment of the narrowed variable) or that the key is the same
|
|
63
|
+
value at runtime versus merely the same source text. It also can't
|
|
64
|
+
read branch polarity beyond the single `!` case F2 special-cases —
|
|
65
|
+
`if (x.has(k) === false)` or `if (x.has(k) ? false : true)` would
|
|
66
|
+
still slip past undetected. The suppression is deliberately biased
|
|
67
|
+
toward false negatives — leaving a real risk unflagged — over false
|
|
68
|
+
positives, which is the correct default bias for a lint the census
|
|
69
|
+
showed fires mostly on legitimate code; F2 is the one place that
|
|
70
|
+
bias is deliberately overridden, because a same-branch bug is worse
|
|
71
|
+
than an unnecessary warning on safe code.
|
|
72
|
+
|
|
73
|
+
Re-census on the F1/F2/F5-fixed rule, four corpora, hit count before
|
|
74
|
+
(no exclusions) → after:
|
|
75
|
+
- pi-lens (this repo, `clients/` `tools/` `index.ts`): 43 → 36 (7
|
|
76
|
+
suppressed, -16%). All 7 verified by hand: `.get()!`-after-`.has()`
|
|
77
|
+
guard clauses in `tree-sitter-client.ts` (`loadLanguage`,
|
|
78
|
+
`getParser`) and `review-graph/builder.ts`, plus
|
|
79
|
+
`pop()!`/`shift()!` inside `while (x.length > 0)` loops in
|
|
80
|
+
`call-graph.ts`, `pipeline.ts`, `tree-sitter-client.ts`
|
|
81
|
+
(`bindingNames`), and `review-graph/workspace-modules.ts`.
|
|
82
|
+
`project-report.ts:531`'s `indices.get(w)!` was an 8th hit
|
|
83
|
+
suppressed by the PRE-F2 rule — its only `indices.has(w)` in scope
|
|
84
|
+
is `if (!indices.has(w))`, i.e. exactly the F2 negation blind spot,
|
|
85
|
+
and it happened to land on genuinely safe code (the `else` branch
|
|
86
|
+
where `w` having been visited already implies `indices` has an
|
|
87
|
+
entry) purely by accident, not because the rule proved anything.
|
|
88
|
+
The F2 fix removes that accidental suppression along with the real
|
|
89
|
+
ones, so it correctly flags again post-fix.
|
|
90
|
+
- inspiration-pi: 674 → 655 (19 suppressed, -2.8%).
|
|
91
|
+
- inspiration-opencode: 1067 → 1060 (7 suppressed, -0.7%).
|
|
92
|
+
- inspiration-oh-my-pi: 3569 → 3544 (25 suppressed, -0.7%).
|
|
93
|
+
|
|
94
|
+
Honest read of the residual: pi-lens's own residual (36) is NOT
|
|
95
|
+
dominated by the genuine cross-boundary-risk class
|
|
96
|
+
(`dart.getCommand(cwd)!` right after `dart.isAvailableAsync(cwd)`,
|
|
97
|
+
and similar) — that class accounts for roughly 7 of the 36. The rest
|
|
98
|
+
(~29) are still legitimate-idiom shaped, just not expressible by
|
|
99
|
+
these two structural constraints: a property re-asserted after its
|
|
100
|
+
parent was checked (`r.enclosingSymbol!.name` after `.filter((r) =>
|
|
101
|
+
r.enclosingSymbol)` in `read-guard.ts`), a boolean flag standing in
|
|
102
|
+
for a narrowed variable, a value narrowed by a ternary rather than
|
|
103
|
+
`.has()` (`index.forward!` in `word-index.ts`), and a
|
|
104
|
+
module-singleton pattern (`format-service.ts`'s
|
|
105
|
+
`globalFormatService!`). Tracked as #1818.
|
|
106
|
+
|
|
107
|
+
2026-08-20 (#1818 round 2): two of the four named unexpressed shapes
|
|
108
|
+
DO have a cheap structural signature after all, and are now
|
|
109
|
+
excluded:
|
|
110
|
+
|
|
111
|
+
1. **Ternary-narrow**: `$TO.$TP ? ...$TO.$TP!... : ...` — the
|
|
112
|
+
`$TO.$TP!` sits under the `consequence` field of a ternary whose
|
|
113
|
+
`condition` is the identical `$TO.$TP` truthy check, even when
|
|
114
|
+
the assertion is nested inside a closure passed to `.map()` (the
|
|
115
|
+
`word-index.ts` and `lsp/index.ts` cases). `field: consequence`
|
|
116
|
+
on the `inside` relation ties the MATCHED NODE ITSELF to the
|
|
117
|
+
consequence branch, so a same-shaped assertion sitting in the
|
|
118
|
+
`alternative` branch (a real narrowing bug: falsy there) is left
|
|
119
|
+
unaffected, and so is one nested inside an unrelated INNER
|
|
120
|
+
ternary whose own condition does not match (see the review-round-1
|
|
121
|
+
fixtures below).
|
|
122
|
+
2. **Filter-then-map re-assert**: `$OBJ.filter(($F) => $F.$PROP)
|
|
123
|
+
.map(($M) => ...$M.$PROP!...)` — `$M` is the SAME metavariable as
|
|
124
|
+
both the map callback's own parameter and the asserted receiver,
|
|
125
|
+
so the exclusion fires only when the narrowed value is literally
|
|
126
|
+
that parameter, not an unrelated same-named variable elsewhere
|
|
127
|
+
(the `read-guard.ts` case, 2 sites × 3 properties each).
|
|
128
|
+
|
|
129
|
+
Both follow the same discipline as the `#1777` exclusions above:
|
|
130
|
+
`stopBy` is a RULE (nearest ternary, never `end`) on the ternary
|
|
131
|
+
exclusion, and the suppression is guarded by same-metavariable
|
|
132
|
+
binding, not mere presence of the guard shape anywhere in scope.
|
|
133
|
+
Fixtured (suppressed shape, mismatched-binding lookalike, and — for
|
|
134
|
+
the ternary — the opposite-branch and nested-ternary bug lookalikes)
|
|
135
|
+
in `rule-tests/no-non-null-assertion-test.yml`.
|
|
136
|
+
|
|
137
|
+
2026-08-20, review round 1 (four findings, all fixed in this
|
|
138
|
+
revision):
|
|
139
|
+
|
|
140
|
+
- **N1 (medium):** the original ternary exclusion used `has: field:
|
|
141
|
+
consequence` — an EXISTENCE check on the ternary as a whole, not
|
|
142
|
+
an identity check on the matched node. `o.y ? o.y!.length :
|
|
143
|
+
o.y!.length` (the identical assertion in BOTH branches) made the
|
|
144
|
+
alternative-branch instance inherit the suppression, because the
|
|
145
|
+
consequence branch's matching text satisfied the existence check
|
|
146
|
+
regardless of which instance was actually being evaluated. Fixed
|
|
147
|
+
by switching to `field: consequence` directly on the `inside`
|
|
148
|
+
relation, which IS an identity check on the matched node's actual
|
|
149
|
+
position. Fixtured as an `invalid` case (both-branches-same-shape
|
|
150
|
+
must still flag on the alternative instance).
|
|
151
|
+
- **N2 (medium):** two mutation-proof gaps. (a) The ternary
|
|
152
|
+
`stopBy: kind: ternary_expression` was provably load-bearing but
|
|
153
|
+
had no fixture proving it: `o.y ? (flag ? 1 : o.y!.length) : 0` —
|
|
154
|
+
the assertion's NEAREST ternary is the inner one, whose own
|
|
155
|
+
condition (`flag`) does not match `$TO.$TP`, so it must still
|
|
156
|
+
flag; weakening `stopBy` to `end` lets the search escalate past
|
|
157
|
+
the inner ternary to the outer one (whose condition DOES match)
|
|
158
|
+
and wrongly suppresses it. (b) The filter-map `$M` binding had no
|
|
159
|
+
fixture proving an unrelated variable inside the SAME callback
|
|
160
|
+
still flags: `rs.filter((r) => r.sym).map((m) => stray.sym!.name)`
|
|
161
|
+
— decoupling `$M` from the map callback's own parameter (e.g. to
|
|
162
|
+
an unconstrained `$ANY`) wrongly suppresses `stray.sym!` too, since
|
|
163
|
+
the filter-map SHAPE would match even though the asserted value is
|
|
164
|
+
not the map's own parameter. Both fixtured as `invalid` cases.
|
|
165
|
+
- **N3 (low):** the filter-map exclusion's intermediate "nearest
|
|
166
|
+
enclosing arrow_function" `inside`/`stopBy` layer could not be
|
|
167
|
+
shown load-bearing by any constructed fixture — removed; see the
|
|
168
|
+
exclusion's own comment below for why it was redundant.
|
|
169
|
+
- **N4 (low):** this rule's `note:` is unaffected; the mismatched
|
|
170
|
+
before/after scope pairing N4 named lives in
|
|
171
|
+
`no-unknown-returns.yml`'s note, fixed there.
|
|
172
|
+
|
|
173
|
+
Re-census, pi-lens `clients/` `tools/` `index.ts`: 36 → 27 (9
|
|
174
|
+
suppressed). All 9 verified by hand: 1 in `word-index.ts`, 2 in
|
|
175
|
+
`lsp/index.ts` (an `AbortSignal`-narrowed-by-truthy-ternary variant
|
|
176
|
+
of the same idiom), and the 6 `read-guard.ts` sites already named
|
|
177
|
+
above. Four-corpus census (F1/F2-fixed rule → round-2 rule; these
|
|
178
|
+
corpora move independently of pi-lens's own history and the
|
|
179
|
+
upstream trees have drifted since the #1777 note, so treat this as
|
|
180
|
+
a fresh baseline rather than a delta against the numbers above):
|
|
181
|
+
inspiration-pi 659 → 657, inspiration-opencode 1078 → 1071,
|
|
182
|
+
inspiration-oh-my-pi 3548 → 3543.
|
|
183
|
+
|
|
184
|
+
The two remaining named shapes — a boolean flag standing in for a
|
|
185
|
+
narrowed variable, and a property re-asserted after its PARENT
|
|
186
|
+
(rather than itself) was checked — were re-probed and are still not
|
|
187
|
+
expressible: both require proving that an assignment or a `.filter`
|
|
188
|
+
predicate on a DIFFERENT expression than the one being asserted
|
|
189
|
+
actually dominates the assertion, which needs a dataflow model, not
|
|
190
|
+
a syntax-tree relation. The module-singleton case
|
|
191
|
+
(`format-service.ts`'s `globalFormatService!`) was also re-probed: a
|
|
192
|
+
direct `if (!$X) { $X = ...; }` guard immediately before `return
|
|
193
|
+
$X!` would be structurally expressible the same way as the
|
|
194
|
+
`#1777` `.has()` exclusion, but `format-service.ts`'s actual
|
|
195
|
+
instance routes the check through an intermediate boolean
|
|
196
|
+
(`shouldCreateNew`) rather than testing `$X` directly, which is the
|
|
197
|
+
boolean-flag shape, not a new one — so no rule was added for it
|
|
198
|
+
rather than risk a suppression that can't tell "just assigned" from
|
|
199
|
+
"assigned in an unrelated earlier branch." The residual (27, was 36)
|
|
200
|
+
is smaller but still idiom-dominated: pending the maintainer's
|
|
201
|
+
standing decision, severity stays `warning`.
|
|
9
202
|
rule:
|
|
10
203
|
pattern: $X!
|
|
11
204
|
not:
|
|
12
205
|
any:
|
|
13
206
|
- kind: function_type
|
|
14
207
|
- kind: method_signature
|
|
208
|
+
- all:
|
|
209
|
+
# #1818 round 2 (review round 1 N1 fix): ternary-narrow.
|
|
210
|
+
# `$TO.$TP ? ...$TO.$TP!... : ...` — the consequence branch is
|
|
211
|
+
# reached only when `$TO.$TP` is truthy, but a closure nested in
|
|
212
|
+
# that branch (an arrow passed to `.map()`, etc.) loses TS's own
|
|
213
|
+
# narrowing across the function boundary. `stopBy` bounds the
|
|
214
|
+
# walk to the NEAREST enclosing ternary (never an outer one —
|
|
215
|
+
# see the round-1-N2a fixture below for why that matters).
|
|
216
|
+
# `field: consequence` on the `inside` relation is an IDENTITY
|
|
217
|
+
# check on the matched node's own position in that ternary's
|
|
218
|
+
# subtree — it ties OUR SPECIFIC node to the consequence branch,
|
|
219
|
+
# not merely to "a same-shaped node exists somewhere in the
|
|
220
|
+
# consequence." The original version used `has: field:
|
|
221
|
+
# consequence` instead, which is an EXISTENCE check on the
|
|
222
|
+
# ternary as a whole: `o.y ? o.y!.length : o.y!.length` (the
|
|
223
|
+
# same assertion repeated in BOTH branches) made the
|
|
224
|
+
# alternative-branch instance — a real narrowing bug, since
|
|
225
|
+
# `o.y` is falsy on that branch — inherit the suppression,
|
|
226
|
+
# because the consequence branch's identical text satisfied the
|
|
227
|
+
# existence check for both instances. `field: consequence`
|
|
228
|
+
# closes that gap: it only matches a node that IS reachable via
|
|
229
|
+
# the consequence field specifically, so the alternative-branch
|
|
230
|
+
# instance is left flagged. Named `$TO`/`$TP`, not `$X`/`$P`:
|
|
231
|
+
# the outer `pattern: $X!` already binds `$X` to the WHOLE
|
|
232
|
+
# asserted expression (e.g. `index.forward`), so reusing `$X`
|
|
233
|
+
# here would force it to match `index.forward.$P!` — a
|
|
234
|
+
# different shape — instead of decomposing `index.forward` into
|
|
235
|
+
# object+property.
|
|
236
|
+
- pattern: $TO.$TP!
|
|
237
|
+
- inside:
|
|
238
|
+
stopBy:
|
|
239
|
+
kind: ternary_expression
|
|
240
|
+
kind: ternary_expression
|
|
241
|
+
field: consequence
|
|
242
|
+
has:
|
|
243
|
+
field: condition
|
|
244
|
+
pattern: $TO.$TP
|
|
245
|
+
- all:
|
|
246
|
+
# #1818 round 2 (review round 1 N3: simplified): a property
|
|
247
|
+
# re-asserted after a `.filter()` on that SAME property,
|
|
248
|
+
# immediately chained into `.map()` — TS's narrowing from
|
|
249
|
+
# `.filter((r) => r.$PROP)` does not carry into the separate
|
|
250
|
+
# `.map()` callback closure. `$M` (the map callback's
|
|
251
|
+
# parameter) is the SAME metavariable as the assertion's
|
|
252
|
+
# receiver, so the exclusion only fires when the asserted value
|
|
253
|
+
# is literally the map callback's own parameter, not an
|
|
254
|
+
# unrelated same-named variable (fixtured: `stray.sym!` inside
|
|
255
|
+
# a `.filter(...).map((m) => ...)` callback must still flag,
|
|
256
|
+
# because `$M` can only bind to "m", never to "stray"); `$PROP`
|
|
257
|
+
# must match on both the filter predicate and the assertion.
|
|
258
|
+
# An earlier version of this exclusion added an intermediate
|
|
259
|
+
# "nearest enclosing arrow_function" boundary before this
|
|
260
|
+
# `inside`; review round 1 could not construct a case where
|
|
261
|
+
# that boundary changed the result — the outer `stopBy: end`
|
|
262
|
+
# below already walks to the SAME call_expression regardless of
|
|
263
|
+
# which arrow_function ancestor the search starts from, because
|
|
264
|
+
# the pattern match on that call_expression is a self-contained
|
|
265
|
+
# structural check independent of the path taken to reach it —
|
|
266
|
+
# so the intermediate layer was removed rather than kept as
|
|
267
|
+
# decoration that looked load-bearing but wasn't.
|
|
268
|
+
- pattern: $M.$PROP!
|
|
269
|
+
- inside:
|
|
270
|
+
stopBy: end
|
|
271
|
+
kind: call_expression
|
|
272
|
+
pattern: $OBJ.filter(($F) => $F.$PROP).map(($M) => $BODY)
|
|
273
|
+
- all:
|
|
274
|
+
- pattern: $M.get($K)!
|
|
275
|
+
- inside:
|
|
276
|
+
# stopBy is a boundary RULE, not a search-depth flag: the
|
|
277
|
+
# ancestor walk stops at the nearest node matching this
|
|
278
|
+
# rule, so it can never escalate past the nearest
|
|
279
|
+
# enclosing function into an outer scope (#1777 F1 fix).
|
|
280
|
+
stopBy:
|
|
281
|
+
any:
|
|
282
|
+
- kind: function_declaration
|
|
283
|
+
- kind: method_definition
|
|
284
|
+
- kind: arrow_function
|
|
285
|
+
- kind: function_expression
|
|
286
|
+
any:
|
|
287
|
+
- kind: function_declaration
|
|
288
|
+
- kind: method_definition
|
|
289
|
+
- kind: arrow_function
|
|
290
|
+
- kind: function_expression
|
|
291
|
+
has:
|
|
292
|
+
stopBy: end
|
|
293
|
+
pattern: $M.has($K)
|
|
294
|
+
# Exclude a negated has() check from counting as a guard
|
|
295
|
+
# (#1777 F2 fix): ast-grep can't read branch polarity, so
|
|
296
|
+
# this can't tell a `if (!m.has(k)) return;` early-return
|
|
297
|
+
# guard clause (safe) from `if (!m.has(k)) { ...
|
|
298
|
+
# m.get(k)! }` (a real bug — the key is proven ABSENT in
|
|
299
|
+
# that branch). Refusing to treat ANY negated has() as a
|
|
300
|
+
# guard is the only structural signal available; it
|
|
301
|
+
# trades a few now-unflagged-turned-flagged early-return
|
|
302
|
+
# guard clauses for closing the real-bug shape. See the
|
|
303
|
+
# rule note for the accepted regression.
|
|
304
|
+
not:
|
|
305
|
+
inside:
|
|
306
|
+
kind: unary_expression
|
|
307
|
+
- all:
|
|
308
|
+
- any:
|
|
309
|
+
- pattern: $A.pop()!
|
|
310
|
+
- pattern: $A.shift()!
|
|
311
|
+
- inside:
|
|
312
|
+
# Same stopBy boundary fix as the get/has exclusion above.
|
|
313
|
+
stopBy:
|
|
314
|
+
any:
|
|
315
|
+
- kind: function_declaration
|
|
316
|
+
- kind: method_definition
|
|
317
|
+
- kind: arrow_function
|
|
318
|
+
- kind: function_expression
|
|
319
|
+
# No function kinds here (#1777 F5): a function node has no
|
|
320
|
+
# `condition` field, so it could never satisfy the `has`
|
|
321
|
+
# check below — the stopBy boundary above already keeps
|
|
322
|
+
# the walk from escalating past the function regardless.
|
|
323
|
+
any:
|
|
324
|
+
- kind: while_statement
|
|
325
|
+
- kind: for_statement
|
|
326
|
+
- kind: if_statement
|
|
327
|
+
has:
|
|
328
|
+
field: condition
|
|
329
|
+
stopBy: end
|
|
330
|
+
pattern: $A.length
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
id: no-raw-json-store-write
|
|
2
2
|
language: TypeScript
|
|
3
3
|
severity: warning
|
|
4
|
+
metadata:
|
|
5
|
+
category: pi-lens-self-scan
|
|
4
6
|
message: "Use the atomic write seam for JSON stores instead of writeFileSync"
|
|
5
7
|
note: |
|
|
6
8
|
JSON-backed durable state must be committed through clients/durable-store.ts
|
|
@@ -8,10 +10,15 @@ note: |
|
|
|
8
10
|
clients/atomic-write.ts. This rule covers the direct
|
|
9
11
|
writeFileSync(path, JSON.stringify(data)) shape. Build scripts and the
|
|
10
12
|
installer's wx lock writes are intentionally outside this rule's scope.
|
|
13
|
+
Test fixtures that write throwaway JSON files for a test's own setup are
|
|
14
|
+
not durable production state either (#1718 self-scan triage: 200 hits,
|
|
15
|
+
all in tests/, none carrying read-modify-write isolation requirements) --
|
|
16
|
+
excluded the same way build scripts already are.
|
|
11
17
|
ignores:
|
|
12
18
|
- "**/clients/atomic-write.ts"
|
|
13
19
|
- "**/clients/installer/index.ts"
|
|
14
20
|
- "**/scripts/**"
|
|
21
|
+
- "**/tests/**"
|
|
15
22
|
rule:
|
|
16
23
|
any:
|
|
17
24
|
- pattern: writeFileSync($PATH, JSON.stringify($$$ARGS))
|
|
@@ -1,9 +1,29 @@
|
|
|
1
1
|
id: no-reflect-apply-js
|
|
2
2
|
language: JavaScript
|
|
3
|
-
severity:
|
|
3
|
+
severity: error
|
|
4
4
|
message: "Reflect.apply() — use a typed call (fn.apply(...) or fn(...args)) instead"
|
|
5
|
+
metadata:
|
|
6
|
+
category: pi-lens-self-scan
|
|
5
7
|
note: |
|
|
6
8
|
Reflect.apply reaches for reflection where a typed call already works.
|
|
7
9
|
Prefer Function#apply or a direct call with spread arguments.
|
|
10
|
+
|
|
11
|
+
This rule has no autofix because a function can have a shadowed own `.apply`
|
|
12
|
+
property. The semantically exact `Function.prototype.apply.call` rewrite is
|
|
13
|
+
worse than the diagnostic.
|
|
14
|
+
|
|
15
|
+
2026-08-20 (refs #1856): PROMOTED from `warning` to `error` with the
|
|
16
|
+
same structural Proxy apply-trap carve-out as the TypeScript twin.
|
|
8
17
|
rule:
|
|
9
|
-
|
|
18
|
+
all:
|
|
19
|
+
- pattern: Reflect.apply($$$ARGS)
|
|
20
|
+
- not:
|
|
21
|
+
inside:
|
|
22
|
+
kind: method_definition
|
|
23
|
+
stopBy: end
|
|
24
|
+
has:
|
|
25
|
+
field: name
|
|
26
|
+
regex: "^apply$"
|
|
27
|
+
inside:
|
|
28
|
+
pattern: new Proxy($TARGET, $HANDLER)
|
|
29
|
+
stopBy: end
|
|
@@ -1,9 +1,30 @@
|
|
|
1
1
|
id: no-reflect-apply
|
|
2
2
|
language: TypeScript
|
|
3
|
-
severity:
|
|
3
|
+
severity: error
|
|
4
4
|
message: "Reflect.apply() — use a typed call (fn.apply(...) or fn(...args)) instead"
|
|
5
|
+
metadata:
|
|
6
|
+
category: pi-lens-self-scan
|
|
5
7
|
note: |
|
|
6
8
|
Reflect.apply reaches for reflection where a typed call already works.
|
|
7
9
|
Prefer Function#apply or a direct call with spread arguments.
|
|
10
|
+
|
|
11
|
+
This rule has no autofix because a function can have a shadowed own `.apply`
|
|
12
|
+
property. The semantically exact `Function.prototype.apply.call` rewrite is
|
|
13
|
+
worse than the diagnostic.
|
|
14
|
+
|
|
15
|
+
2026-08-20 (refs #1856): PROMOTED from `warning` to `error`. Standard
|
|
16
|
+
forwarding inside an inline `new Proxy` apply trap is excluded
|
|
17
|
+
structurally; a method merely named `apply` elsewhere remains in scope.
|
|
8
18
|
rule:
|
|
9
|
-
|
|
19
|
+
all:
|
|
20
|
+
- pattern: Reflect.apply($$$ARGS)
|
|
21
|
+
- not:
|
|
22
|
+
inside:
|
|
23
|
+
kind: method_definition
|
|
24
|
+
stopBy: end
|
|
25
|
+
has:
|
|
26
|
+
field: name
|
|
27
|
+
regex: "^apply$"
|
|
28
|
+
inside:
|
|
29
|
+
pattern: new Proxy($TARGET, $HANDLER)
|
|
30
|
+
stopBy: end
|
|
@@ -1,13 +1,41 @@
|
|
|
1
1
|
id: no-reflect-get-js
|
|
2
2
|
language: JavaScript
|
|
3
|
-
severity:
|
|
3
|
+
severity: error
|
|
4
4
|
message: "Reflect.get(obj, key) — use a typed property access (obj.prop or obj[key]) instead"
|
|
5
|
+
metadata:
|
|
6
|
+
category: pi-lens-self-scan
|
|
5
7
|
note: |
|
|
6
8
|
Reflect.get reaches for reflection where a typed property access
|
|
7
9
|
already works. Prefer dot or bracket access.
|
|
8
10
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
2026-08-20 (refs #1856): PROMOTED from `warning` to `error` with the
|
|
12
|
+
same structural Proxy get-trap carve-out as the TypeScript twin. Both
|
|
13
|
+
arities remain diagnostic elsewhere, but only the two-argument branch is
|
|
14
|
+
fixable because a receiver changes access semantics.
|
|
12
15
|
rule:
|
|
13
|
-
|
|
16
|
+
all:
|
|
17
|
+
- pattern: $CALL
|
|
18
|
+
- any:
|
|
19
|
+
- pattern: Reflect.get($OBJ, $KEY)
|
|
20
|
+
- pattern: Reflect.get($GET_TARGET, $PROP, $RECEIVER)
|
|
21
|
+
- not:
|
|
22
|
+
inside:
|
|
23
|
+
kind: method_definition
|
|
24
|
+
stopBy: end
|
|
25
|
+
has:
|
|
26
|
+
field: name
|
|
27
|
+
regex: "^get$"
|
|
28
|
+
inside:
|
|
29
|
+
pattern: new Proxy($TARGET, $HANDLER)
|
|
30
|
+
stopBy: end
|
|
31
|
+
rewriters:
|
|
32
|
+
- id: rewrite-two-argument-reflect-get-js
|
|
33
|
+
rule:
|
|
34
|
+
pattern: Reflect.get($OBJ, $KEY)
|
|
35
|
+
fix: "$OBJ[$KEY]"
|
|
36
|
+
transform:
|
|
37
|
+
REWRITTEN:
|
|
38
|
+
rewrite:
|
|
39
|
+
rewriters: [rewrite-two-argument-reflect-get-js]
|
|
40
|
+
source: $CALL
|
|
41
|
+
fix: $REWRITTEN
|
|
@@ -1,16 +1,42 @@
|
|
|
1
1
|
id: no-reflect-get
|
|
2
2
|
language: TypeScript
|
|
3
|
-
severity:
|
|
3
|
+
severity: error
|
|
4
4
|
message: "Reflect.get(obj, key) — use a typed property access (obj.prop or obj[key]) instead"
|
|
5
|
+
metadata:
|
|
6
|
+
category: pi-lens-self-scan
|
|
5
7
|
note: |
|
|
6
8
|
Reflect.get reaches for reflection where a typed property access
|
|
7
9
|
already works. Prefer dot or bracket access.
|
|
8
10
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
than allowlisted by call site.
|
|
11
|
+
2026-08-20 (refs #1856): PROMOTED from `warning` to `error`. The
|
|
12
|
+
standard receiver-forwarding call inside an inline `new Proxy` get
|
|
13
|
+
trap is excluded structurally. Both arities remain in scope elsewhere,
|
|
14
|
+
including a method merely named `get` outside a Proxy call. Only the
|
|
15
|
+
two-argument branch is fixable because a receiver changes access semantics.
|
|
15
16
|
rule:
|
|
16
|
-
|
|
17
|
+
all:
|
|
18
|
+
- pattern: $CALL
|
|
19
|
+
- any:
|
|
20
|
+
- pattern: Reflect.get($OBJ, $KEY)
|
|
21
|
+
- pattern: Reflect.get($GET_TARGET, $PROP, $RECEIVER)
|
|
22
|
+
- not:
|
|
23
|
+
inside:
|
|
24
|
+
kind: method_definition
|
|
25
|
+
stopBy: end
|
|
26
|
+
has:
|
|
27
|
+
field: name
|
|
28
|
+
regex: "^get$"
|
|
29
|
+
inside:
|
|
30
|
+
pattern: new Proxy($TARGET, $HANDLER)
|
|
31
|
+
stopBy: end
|
|
32
|
+
rewriters:
|
|
33
|
+
- id: rewrite-two-argument-reflect-get
|
|
34
|
+
rule:
|
|
35
|
+
pattern: Reflect.get($OBJ, $KEY)
|
|
36
|
+
fix: "$OBJ[$KEY]"
|
|
37
|
+
transform:
|
|
38
|
+
REWRITTEN:
|
|
39
|
+
rewrite:
|
|
40
|
+
rewriters: [rewrite-two-argument-reflect-get]
|
|
41
|
+
source: $CALL
|
|
42
|
+
fix: $REWRITTEN
|
|
@@ -12,9 +12,23 @@ note: |
|
|
|
12
12
|
|
|
13
13
|
The rule matches a `function_definition` that contains BOTH a
|
|
14
14
|
`yield` node AND a `return_statement` with a value (`return\s+\S`).
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
`block`
|
|
15
|
+
Each `has:` uses `stopBy: {kind: function_definition}` (not the
|
|
16
|
+
plain `stopBy: end` this rule shipped with originally) — it needs
|
|
17
|
+
to search past the `block` wrapper (the function body isn't a
|
|
18
|
+
direct child of `function_definition`), but must NOT cross into a
|
|
19
|
+
nested `function_definition`. A bare `stopBy: end` searches every
|
|
20
|
+
descendant regardless of depth, so a `yield` in an outer
|
|
21
|
+
`async def lifespan(app):` and an unrelated `return 42` inside a
|
|
22
|
+
nested `def handler():` got conflated into one false positive
|
|
23
|
+
(#1806 audit: 3 FP hits, none were actual generators — the yield
|
|
24
|
+
and the value-return belonged to different functions).
|
|
25
|
+
|
|
26
|
+
A nested function that is itself a real generator (has its own
|
|
27
|
+
`yield` AND its own value-`return`) is still flagged: the scanner
|
|
28
|
+
visits every `function_definition` node independently, including
|
|
29
|
+
nested ones, and `stopBy: {kind: function_definition}` only blocks
|
|
30
|
+
the OUTER function's search from reaching into the inner one — it
|
|
31
|
+
doesn't stop the inner function from being checked on its own.
|
|
18
32
|
|
|
19
33
|
Bare `return` (no value) is allowed and intentionally not flagged.
|
|
20
34
|
metadata:
|
|
@@ -24,8 +38,11 @@ rule:
|
|
|
24
38
|
- kind: function_definition
|
|
25
39
|
- has:
|
|
26
40
|
kind: yield
|
|
27
|
-
stopBy:
|
|
41
|
+
stopBy:
|
|
42
|
+
kind: function_definition
|
|
28
43
|
- has:
|
|
29
44
|
kind: return_statement
|
|
30
45
|
regex: 'return\s+\S'
|
|
31
|
-
stopBy:
|
|
46
|
+
stopBy:
|
|
47
|
+
kind: function_definition
|
|
48
|
+
|