@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
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
id: no-await-expression-member-js
|
|
2
2
|
language: JavaScript
|
|
3
3
|
severity: hint
|
|
4
|
-
message: "
|
|
4
|
+
message: "(await expr).prop — do not rewrite to await expr.prop (that reads .prop off the unresolved promise). Keep the parens, or destructure first: const x = await expr; x.prop"
|
|
5
5
|
note: |
|
|
6
|
-
(await expr).prop
|
|
6
|
+
`(await expr).prop` awaits `expr` first, THEN reads `.prop` off the
|
|
7
|
+
resolved value. `await expr.prop` is NOT equivalent: `.` binds
|
|
8
|
+
tighter than `await`, so it reads `.prop` off the still-pending
|
|
9
|
+
Promise first (almost always `undefined`, since Promise objects
|
|
10
|
+
don't have arbitrary properties) and only then awaits that.
|
|
11
|
+
The rule previously told the caller to make this exact swap — bad
|
|
12
|
+
advice that fabricates a bug at every fix site (#1806 audit). The
|
|
13
|
+
correct move is either to keep the parenthesized form as-is (it's
|
|
14
|
+
already correct, just not "unnecessary") or to destructure into a
|
|
15
|
+
named variable first: `const resolved = await expr; resolved.prop`.
|
|
16
|
+
There's no autofix here on purpose — which form reads better is a
|
|
17
|
+
judgment call, not a mechanical rewrite.
|
|
7
18
|
Exception: (await import(...)).prop is the standard dynamic import pattern.
|
|
8
19
|
rule:
|
|
9
20
|
pattern: "(await $EXPR).$PROP"
|
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
id: no-await-expression-member
|
|
2
2
|
language: TypeScript
|
|
3
3
|
severity: hint
|
|
4
|
-
message: "
|
|
4
|
+
message: "(await expr).prop — do not rewrite to await expr.prop (that reads .prop off the unresolved promise). Keep the parens, or destructure first: const x = await expr; x.prop"
|
|
5
5
|
note: |
|
|
6
|
-
(await expr).prop
|
|
6
|
+
`(await expr).prop` awaits `expr` first, THEN reads `.prop` off the
|
|
7
|
+
resolved value. `await expr.prop` is NOT equivalent: `.` binds
|
|
8
|
+
tighter than `await`, so it reads `.prop` off the still-pending
|
|
9
|
+
Promise first (almost always `undefined`, since Promise objects
|
|
10
|
+
don't have arbitrary properties) and only then awaits that.
|
|
11
|
+
The rule previously told the caller to make this exact swap — bad
|
|
12
|
+
advice that fabricates a bug at every fix site (#1806 audit). The
|
|
13
|
+
correct move is either to keep the parenthesized form as-is (it's
|
|
14
|
+
already correct, just not "unnecessary") or to destructure into a
|
|
15
|
+
named variable first: `const resolved = await expr; resolved.prop`.
|
|
16
|
+
There's no autofix here on purpose — which form reads better is a
|
|
17
|
+
judgment call, not a mechanical rewrite.
|
|
7
18
|
Exception: (await import(...)).prop is the standard dynamic import pattern.
|
|
8
19
|
rule:
|
|
9
20
|
pattern: "(await $EXPR).$PROP"
|
package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-host-path-in-win32-branch.yml
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
id: no-bare-host-path-in-win32-branch
|
|
2
2
|
language: TypeScript
|
|
3
3
|
severity: warning
|
|
4
|
+
metadata:
|
|
5
|
+
category: pi-lens-self-scan
|
|
4
6
|
message: "Use win32 path operations inside a branch committed to Windows path semantics"
|
|
5
7
|
note: |
|
|
6
8
|
A branch guarded by isWindowsPath/isFullyQualifiedWin32 has committed to
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
id: no-bare-object-param
|
|
2
|
+
language: TypeScript
|
|
3
|
+
severity: error
|
|
4
|
+
metadata:
|
|
5
|
+
category: pi-lens-self-scan
|
|
6
|
+
message: "Parameter typed bare 'object' — guarantees nothing about shape, use Record<string, unknown> or a real interface"
|
|
7
|
+
note: |
|
|
8
|
+
`object` only tells the compiler "not a primitive" — it doesn't
|
|
9
|
+
guarantee any property exists, so every consumer still has to cast
|
|
10
|
+
or reach for `as` before doing anything useful. Use
|
|
11
|
+
`Record<string, unknown>` for an open bag of properties, or a real
|
|
12
|
+
interface/type when the shape is known.
|
|
13
|
+
|
|
14
|
+
Scope: direct annotations only — a parameter (required or optional)
|
|
15
|
+
whose type annotation is exactly the bare `object` keyword, matched
|
|
16
|
+
structurally at the `predefined_type` leaf so it fires the same way
|
|
17
|
+
whether the parameter sits in a function declaration, an arrow
|
|
18
|
+
function, a class method, an interface method signature, or a
|
|
19
|
+
function-type alias (all four share the same
|
|
20
|
+
`required_parameter`/`optional_parameter` -> `type_annotation` ->
|
|
21
|
+
`predefined_type` shape in tree-sitter-typescript). Anti-slop's
|
|
22
|
+
transitive-alias-resolution half (flag a parameter typed with an
|
|
23
|
+
alias that itself resolves to bare `object`) is intentionally
|
|
24
|
+
dropped — that needs same-file symbol lookup ast-grep doesn't do.
|
|
25
|
+
A union member (`object | null`) or an array element (`object[]`)
|
|
26
|
+
is NOT flagged: the type_annotation's only content must be the bare
|
|
27
|
+
keyword, so wrapping it in anything else takes it out of scope
|
|
28
|
+
rather than risk a wider, noisier match than the direct case calls
|
|
29
|
+
for. Capitalized `Object` is a different node kind (`type_identifier`,
|
|
30
|
+
not `predefined_type`) and was never in scope.
|
|
31
|
+
|
|
32
|
+
No JS variant: JavaScript has no type annotations, so this pattern
|
|
33
|
+
has nothing to match there (same call as no-unknown-laundering.yml).
|
|
34
|
+
|
|
35
|
+
FP-scan (napi engine, every .ts/.tsx file under clients/ and tests/,
|
|
36
|
+
998 files): exactly one hit, `clients/host-ports.ts:8` —
|
|
37
|
+
`export type HostLogSink = (entry: object) => void;`. That's a
|
|
38
|
+
function-type alias, confirming the rule does cover function-type
|
|
39
|
+
parameters, not just declarations/methods. Fixed in the same PR by
|
|
40
|
+
narrowing to `Record<string, unknown>`: `HostLogSink` feeds
|
|
41
|
+
`NdjsonLogger.log(obj: unknown)` through the host's log sink, and
|
|
42
|
+
every real log record is a structured key/value bag, not an opaque
|
|
43
|
+
non-primitive — `Record<string, unknown>` says that honestly without
|
|
44
|
+
over-committing to a fixed shape. Zero hits remained after the fix,
|
|
45
|
+
so severity stays at `warning` rather than `hint`.
|
|
46
|
+
|
|
47
|
+
2026-08-19 (refs #1718): promoted `warning` -> `error` as part of the
|
|
48
|
+
anti-slop pattern adoption. Re-ran the FP scan on the current tree
|
|
49
|
+
(clients/ + tests/, same napi engine): still 0 hits. A zero-violation
|
|
50
|
+
rule costs nothing to run at `error`, and it stays free only if
|
|
51
|
+
promoted before someone writes the first one.
|
|
52
|
+
rule:
|
|
53
|
+
kind: predefined_type
|
|
54
|
+
regex: "^object$"
|
|
55
|
+
inside:
|
|
56
|
+
kind: type_annotation
|
|
57
|
+
inside:
|
|
58
|
+
any:
|
|
59
|
+
- kind: required_parameter
|
|
60
|
+
- kind: optional_parameter
|
|
@@ -1,21 +1,66 @@
|
|
|
1
1
|
id: no-chained-type-assertions
|
|
2
2
|
language: TypeScript
|
|
3
|
-
severity:
|
|
3
|
+
severity: error
|
|
4
|
+
metadata:
|
|
5
|
+
category: pi-lens-self-scan
|
|
4
6
|
message: "Chained type assertion (x as A as B) — stacking assertions with no runtime check between them"
|
|
5
7
|
note: |
|
|
6
8
|
`x as A as B` stacks two assertions with no runtime check between
|
|
7
9
|
them, so the compiler can't verify either hop. Narrow with a type
|
|
8
10
|
guard, or assert once to the type you actually need. `as const`
|
|
9
11
|
chains are allowed — they don't launder the value's type, they just
|
|
10
|
-
freeze a literal.
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
freeze a literal.
|
|
13
|
+
|
|
14
|
+
2026-08-19 (refs #1718): promoted `warning` -> `error` and DROPPED the
|
|
15
|
+
`as unknown as $B` exemption as part of adopting anti-slop's
|
|
16
|
+
`no-chained-type-assertions` at its upstream strictness for the
|
|
17
|
+
shipped catalog. anti-slop's own rule (dmmulroy/anti-slop,
|
|
18
|
+
src/rules/no-chained-type-assertions.ts) treats `as unknown as` as a
|
|
19
|
+
forbidden chain too — routing a cast through `unknown` still discards
|
|
20
|
+
the original type's evidence, it just discards it in two hops instead
|
|
21
|
+
of one. The earlier note here argued `as unknown as` was the
|
|
22
|
+
TypeScript-endorsed safe-cast idiom (no-as-any.yml's own
|
|
23
|
+
recommendation) and cited a 22-hit FP scan where every chained-assertion
|
|
24
|
+
hit in pi-lens's own tree was that form — that FP-load argument is
|
|
25
|
+
still true, but it is an argument for pi-lens's OWN code, and this
|
|
26
|
+
catalog ships to other repositories. Users get the stricter upstream
|
|
27
|
+
form; pi-lens's own ~22 `as unknown as` chains stay non-conforming
|
|
28
|
+
until #1718 designs a self-scan baseline (or a follow-up narrows this
|
|
29
|
+
rule back down) — the same trade the audit made for every hint-tier
|
|
30
|
+
row in this PR: adopt the useful pattern for the product without
|
|
31
|
+
forcing pi-lens's own history to retroactively conform in the same PR.
|
|
32
|
+
|
|
33
|
+
2026-08-20 (review round, refs #1718): `error` severity is semantic-
|
|
34
|
+
blocking (ast-grep-napi.ts:699) with no independent escape valve — a
|
|
35
|
+
caller who follows the sibling `require-safety-comment-for-as-unknown-as.yml`
|
|
36
|
+
hint and adds a `SAFETY:` comment still hit a hard block, because the
|
|
37
|
+
two rules were wired independently. Fixed by giving THIS rule its own
|
|
38
|
+
`SAFETY:` exemption for the `as unknown as` arm specifically (the same
|
|
39
|
+
relational check — `follows`/`inside` a preceding comment matching
|
|
40
|
+
`SAFETY\s*:` — as the sibling hint rule, so a commented site satisfies
|
|
41
|
+
both at once). A genuine two-concrete-type chain (`x as A as B`, no
|
|
42
|
+
`unknown` hop) gets NO escape valve: that shape has no legitimate
|
|
43
|
+
reading upstream or here, so it stays hard-blocked. The two rules are
|
|
44
|
+
now a coherent pair: an uncommented `as unknown as` chain is a hard
|
|
45
|
+
error; a `SAFETY:`-commented one is clean; the hint rule keeps
|
|
46
|
+
teaching the convention on every OTHER assertion form.
|
|
47
|
+
|
|
48
|
+
2026-08-20 (refs #1727, #1777): the `as unknown as` arm is REMOVED from
|
|
49
|
+
this rule and delegated wholly to
|
|
50
|
+
`require-safety-comment-for-as-unknown-as.yml`, which was promoted to
|
|
51
|
+
`error` in the same change. The two rules previously matched the exact
|
|
52
|
+
same site list — verified identical on four corpora (16/16 pi-lens
|
|
53
|
+
`clients/`, 182/182 pi core, 194/194 opencode, and 1803 of this rule's
|
|
54
|
+
1849 oh-my-pi hits) — so every uncommented `x as unknown as T` raised
|
|
55
|
+
TWO diagnostics for one defect, one of them semantic-blocking. They now
|
|
56
|
+
partition the space: that rule owns the `unknown` hop and carries the
|
|
57
|
+
`SAFETY:` escape valve; this rule owns the concrete `x as A as B`
|
|
58
|
+
chain, which keeps NO escape valve because it has no legitimate
|
|
59
|
+
reading. Residual census for the concrete arm alone (2026-08-20):
|
|
60
|
+
pi-lens 0, pi core 0, opencode 0, oh-my-pi 46. Tagged
|
|
61
|
+
`metadata.category: pi-lens-self-scan` so CI holds pi-lens's own tree
|
|
62
|
+
at that zero.
|
|
18
63
|
rule:
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
pattern:
|
|
64
|
+
all:
|
|
65
|
+
- pattern: $X as $A as $B
|
|
66
|
+
- not: { pattern: $X as unknown as $B }
|
|
@@ -9,12 +9,70 @@ note: |
|
|
|
9
9
|
`compile(source, ...)` with non-literal source compiles arbitrary code
|
|
10
10
|
that may be executed later. If `source` is user-controlled, this is
|
|
11
11
|
a code injection vulnerability.
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
|
|
13
|
+
Static/trusted source is suppressed (the rule's original ship still
|
|
14
|
+
described this design in prose but the shipped pattern matched every
|
|
15
|
+
compile() call unconditionally — #1806 audit: 3 FP hits, all in an
|
|
16
|
+
eval runner's `ast.parse` → `compile` pipeline). A source is trusted
|
|
17
|
+
when it is:
|
|
18
|
+
- a string literal (`compile('print(1)', ...)`);
|
|
19
|
+
- the direct result of an `ast.<method>(...)` call
|
|
20
|
+
(`compile(ast.parse(source), ...)`); or
|
|
21
|
+
- a variable of the SAME name assigned from `ast.<method>(...)`
|
|
22
|
+
SOMEWHERE in the nearest enclosing function
|
|
23
|
+
(`module = ast.parse(source); compile(module, ...)`).
|
|
24
|
+
The third case covers the common "parse once, compile the tree"
|
|
25
|
+
idiom (including intermediate `ast.Module`/`ast.Expression`
|
|
26
|
+
reconstructions built from an already-parsed tree) without full
|
|
27
|
+
dataflow analysis. It is honestly a same-scope, same-name,
|
|
28
|
+
ANY-ORDER heuristic, not real reaching-definitions: it does not
|
|
29
|
+
check that the `ast.<method>(...)` assignment happens BEFORE the
|
|
30
|
+
`compile()` call, so a later reassignment to untrusted input
|
|
31
|
+
(`module = ast.parse(source); module = user_input;
|
|
32
|
+
compile(module, ...)`) is a known, accepted miss (fixture pins it
|
|
33
|
+
under `valid:` with an explanatory comment — ast-grep's relational
|
|
34
|
+
rules can't express statement ordering, only ancestor/descendant/
|
|
35
|
+
sibling-existence). Anything else (a bare identifier with no such
|
|
36
|
+
assignment anywhere in scope, string concatenation, a call to
|
|
37
|
+
something other than `ast.*`) is still flagged.
|
|
38
|
+
|
|
39
|
+
2026-08-20 (review round, refs #1806): two follow-up fixes.
|
|
40
|
+
(1) The "same function" scope was `inside: {stopBy: end, kind:
|
|
41
|
+
function_definition}`, which climbs the WHOLE ancestor chain and
|
|
42
|
+
matches the first function_definition ANYWHERE above — including an
|
|
43
|
+
outer function, past a nested one. A nested function whose own
|
|
44
|
+
parameter happens to share a name with an outer function's
|
|
45
|
+
`ast.parse`-derived variable (shadowing, not the same binding) was
|
|
46
|
+
wrongly trusted. Bounded to the NEAREST enclosing function with
|
|
47
|
+
`stopBy: {kind: function_definition}` on the `inside` ascent itself
|
|
48
|
+
(same boundary-rule shape used to scope `no-return-value-in-generator`
|
|
49
|
+
in this PR's first round) — it stops climbing at the first
|
|
50
|
+
function_definition found instead of continuing past it.
|
|
51
|
+
(2) `pattern: compile($SRC, $$$REST)` has a literal comma in its
|
|
52
|
+
source text, so it never matched the single-argument form
|
|
53
|
+
`compile(user_input)` — a silent arity regression from the original
|
|
54
|
+
`compile($$$ARGS)` (any arity). Restored via an explicit `compile($SRC)`
|
|
55
|
+
alternative, mirroring the `$DB.query($SQL)` / `$DB.query($SQL, $$$REST)`
|
|
56
|
+
two-arity shape already used in `no-sql-in-code`.
|
|
16
57
|
rule:
|
|
17
|
-
|
|
58
|
+
any:
|
|
59
|
+
- pattern: compile($SRC)
|
|
60
|
+
- pattern: compile($SRC, $$$REST)
|
|
61
|
+
constraints:
|
|
62
|
+
SRC:
|
|
63
|
+
not:
|
|
64
|
+
any:
|
|
65
|
+
- kind: string
|
|
66
|
+
- pattern: ast.$METHOD($$$A)
|
|
67
|
+
- all:
|
|
68
|
+
- kind: identifier
|
|
69
|
+
- inside:
|
|
70
|
+
stopBy:
|
|
71
|
+
kind: function_definition
|
|
72
|
+
kind: function_definition
|
|
73
|
+
has:
|
|
74
|
+
stopBy: end
|
|
75
|
+
pattern: $SRC = ast.$METHOD($$$A)
|
|
18
76
|
has_fix: false
|
|
19
77
|
tags:
|
|
20
78
|
- python
|
|
@@ -9,12 +9,40 @@ rule:
|
|
|
9
9
|
- inside:
|
|
10
10
|
field: name
|
|
11
11
|
matches: is-class-members
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
any:
|
|
13
|
+
# 2026-08-20 (review round, refs #1806): staticness must be
|
|
14
|
+
# compared BETWEEN the pair, not blanket-exempted. A static
|
|
15
|
+
# member and a same-named instance member live in separate
|
|
16
|
+
# namespaces (`ClassName.foo` vs `instance.foo`) — no
|
|
17
|
+
# overwrite, correctly exempt. Two static members (or two
|
|
18
|
+
# instance members) with the same name DO collide — the
|
|
19
|
+
# original review-round fix over-corrected by excluding
|
|
20
|
+
# ANY static-enclosed accessor from pairing at all, which
|
|
21
|
+
# silently dropped the rule's core case
|
|
22
|
+
# (`static foo(){} static foo(){}`, the exact silent
|
|
23
|
+
# overwrite this rule exists to catch). These two arms
|
|
24
|
+
# require the anchor and its paired duplicate to agree on
|
|
25
|
+
# staticness: a static anchor only pairs with a later
|
|
26
|
+
# static member, a non-static anchor only pairs with a
|
|
27
|
+
# later non-static member.
|
|
28
|
+
- all:
|
|
29
|
+
- matches: is-static-member
|
|
30
|
+
- precedes:
|
|
31
|
+
stopBy: end
|
|
32
|
+
all:
|
|
33
|
+
- matches: is-static-member
|
|
34
|
+
- has:
|
|
35
|
+
matches: accessor-name
|
|
36
|
+
- all:
|
|
37
|
+
- not:
|
|
38
|
+
matches: is-static-member
|
|
39
|
+
- precedes:
|
|
40
|
+
stopBy: end
|
|
41
|
+
all:
|
|
42
|
+
- not:
|
|
43
|
+
matches: is-static-member
|
|
44
|
+
- has:
|
|
45
|
+
matches: accessor-name
|
|
18
46
|
- matches: member-name
|
|
19
47
|
all:
|
|
20
48
|
- not:
|
|
@@ -33,13 +61,21 @@ rule:
|
|
|
33
61
|
utils:
|
|
34
62
|
duplicate-field:
|
|
35
63
|
matches: is-class-members
|
|
64
|
+
not:
|
|
65
|
+
# Anchored on the member's own text (which starts at its first
|
|
66
|
+
# modifier keyword), not on the single nearest-preceding-sibling
|
|
67
|
+
# token. `follows: pattern: $$ACCESS` only ever binds the LAST
|
|
68
|
+
# modifier before the name — for `static async foo() {}` that is
|
|
69
|
+
# "async", so a `not: regex: static` check nested under that
|
|
70
|
+
# follows clause never sees "static" and the escape valve never
|
|
71
|
+
# fires (#1806 audit: 3 FP hits, static factory + same-named
|
|
72
|
+
# instance method both flagged as duplicates).
|
|
73
|
+
regex: '^static\b'
|
|
36
74
|
has:
|
|
37
75
|
matches: member-name
|
|
38
76
|
any:
|
|
39
77
|
- follows:
|
|
40
78
|
pattern: $$ACCESS
|
|
41
|
-
not:
|
|
42
|
-
regex: static
|
|
43
79
|
not:
|
|
44
80
|
regex: constructor
|
|
45
81
|
- not:
|
|
@@ -51,6 +87,14 @@ utils:
|
|
|
51
87
|
matches: member-name
|
|
52
88
|
follows:
|
|
53
89
|
pattern: $$ACCESS
|
|
90
|
+
is-static-member:
|
|
91
|
+
# Anchored on the member's own text (which starts at its first
|
|
92
|
+
# modifier keyword), not on the single nearest-preceding-sibling
|
|
93
|
+
# token — see the `duplicate-field` comment below for why
|
|
94
|
+
# `follows: pattern: $$ACCESS` can't be trusted to see "static"
|
|
95
|
+
# once another modifier (e.g. "async") sits closer to the name.
|
|
96
|
+
matches: is-class-members
|
|
97
|
+
regex: '^static\b'
|
|
54
98
|
is-class-members:
|
|
55
99
|
any:
|
|
56
100
|
- kind: method_definition
|
|
@@ -6,8 +6,33 @@ note: |
|
|
|
6
6
|
innerHTML and outerHTML can introduce XSS vulnerabilities when used with
|
|
7
7
|
user-supplied data. Use textContent for plain text or a library like DOMPurify
|
|
8
8
|
for sanitized HTML.
|
|
9
|
+
|
|
10
|
+
The assignment forms (`$EL.innerHTML = $VAL` / `$EL.outerHTML = $VAL`)
|
|
11
|
+
are NOT flagged when `$VAL` is a plain string literal or a template
|
|
12
|
+
literal with no `${...}` substitution — clearing a node
|
|
13
|
+
(`el.innerHTML = ''`) or setting static markup
|
|
14
|
+
(`el.innerHTML = "<hr>"`) can't carry injected content, since the
|
|
15
|
+
right-hand side is fixed at author time. Before this constraint every
|
|
16
|
+
literal assignment matched too, which is why 8/8 sampled hits in the
|
|
17
|
+
audit corpus were this exact "clear/reset" idiom (#1806). A dynamic
|
|
18
|
+
value (an identifier, a call, or a template literal with a
|
|
19
|
+
substitution) is still flagged — that's the actual injection surface.
|
|
20
|
+
`insertAdjacentHTML(...)` keeps its original unconditional match: its
|
|
21
|
+
argument shape (`position, html`) doesn't fit the same RHS-literal
|
|
22
|
+
check cleanly, and the issue that drove this fix was specifically the
|
|
23
|
+
assignment forms.
|
|
9
24
|
rule:
|
|
10
25
|
any:
|
|
11
|
-
- pattern: $EL.innerHTML =
|
|
12
|
-
- pattern: $EL.outerHTML =
|
|
26
|
+
- pattern: $EL.innerHTML = $VAL
|
|
27
|
+
- pattern: $EL.outerHTML = $VAL
|
|
13
28
|
- pattern: $EL.insertAdjacentHTML($$$)
|
|
29
|
+
constraints:
|
|
30
|
+
VAL:
|
|
31
|
+
not:
|
|
32
|
+
any:
|
|
33
|
+
- kind: string
|
|
34
|
+
- all:
|
|
35
|
+
- kind: template_string
|
|
36
|
+
- not:
|
|
37
|
+
has:
|
|
38
|
+
kind: template_substitution
|
|
@@ -6,8 +6,33 @@ note: |
|
|
|
6
6
|
innerHTML and outerHTML can introduce XSS vulnerabilities when used with
|
|
7
7
|
user-supplied data. Use textContent for plain text or a library like DOMPurify
|
|
8
8
|
for sanitized HTML.
|
|
9
|
+
|
|
10
|
+
The assignment forms (`$EL.innerHTML = $VAL` / `$EL.outerHTML = $VAL`)
|
|
11
|
+
are NOT flagged when `$VAL` is a plain string literal or a template
|
|
12
|
+
literal with no `${...}` substitution — clearing a node
|
|
13
|
+
(`el.innerHTML = ''`) or setting static markup
|
|
14
|
+
(`el.innerHTML = "<hr>"`) can't carry injected content, since the
|
|
15
|
+
right-hand side is fixed at author time. Before this constraint every
|
|
16
|
+
literal assignment matched too, which is why 8/8 sampled hits in the
|
|
17
|
+
audit corpus were this exact "clear/reset" idiom (#1806). A dynamic
|
|
18
|
+
value (an identifier, a call, or a template literal with a
|
|
19
|
+
substitution) is still flagged — that's the actual injection surface.
|
|
20
|
+
`insertAdjacentHTML(...)` keeps its original unconditional match: its
|
|
21
|
+
argument shape (`position, html`) doesn't fit the same RHS-literal
|
|
22
|
+
check cleanly, and the issue that drove this fix was specifically the
|
|
23
|
+
assignment forms.
|
|
9
24
|
rule:
|
|
10
25
|
any:
|
|
11
|
-
- pattern: $EL.innerHTML =
|
|
12
|
-
- pattern: $EL.outerHTML =
|
|
26
|
+
- pattern: $EL.innerHTML = $VAL
|
|
27
|
+
- pattern: $EL.outerHTML = $VAL
|
|
13
28
|
- pattern: $EL.insertAdjacentHTML($$$)
|
|
29
|
+
constraints:
|
|
30
|
+
VAL:
|
|
31
|
+
not:
|
|
32
|
+
any:
|
|
33
|
+
- kind: string
|
|
34
|
+
- all:
|
|
35
|
+
- kind: template_string
|
|
36
|
+
- not:
|
|
37
|
+
has:
|
|
38
|
+
kind: template_substitution
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
id: no-known-value-widening
|
|
2
|
+
language: TypeScript
|
|
3
|
+
severity: hint
|
|
4
|
+
message: "const initialized from an object literal, widened by a Record<...> annotation — prefer inference or 'satisfies'"
|
|
5
|
+
note: |
|
|
6
|
+
Narrowed port of dmmulroy/anti-slop's `no-known-value-widening`
|
|
7
|
+
(src/rules/no-known-value-widening.ts, MIT). Upstream is a full
|
|
8
|
+
data-flow rule: it resolves `const` variable references transitively,
|
|
9
|
+
walks return statements, assignments, property definitions, and type
|
|
10
|
+
assertions, and flags ANY syntactically-known value (object/array/
|
|
11
|
+
function/literal, or a stable `const` binding that resolves to one)
|
|
12
|
+
flowing into an explicitly broad target type (`unknown`, `object`, an
|
|
13
|
+
open `Record<...>`/mapped-type dictionary, or an anonymous object
|
|
14
|
+
type). None of that data-flow — resolving a variable back to its
|
|
15
|
+
declaration, walking a return path — is something ast-grep's
|
|
16
|
+
structural matcher does; building a fake version of it would be
|
|
17
|
+
exactly the "vacuous guard" failure mode this repo's own review
|
|
18
|
+
process screens for.
|
|
19
|
+
|
|
20
|
+
This port keeps ONE syntactically self-contained sub-case: a `const`
|
|
21
|
+
declared with an object-literal initializer AND a `Record<K, V>`
|
|
22
|
+
annotation, matched in the same statement (`const x: Record<K, V> =
|
|
23
|
+
{ ... }`). That is exactly what the 2026-08-19 audit measured (87
|
|
24
|
+
hits repo-wide vs. only 30 `satisfies` uses) and is the shape upstream
|
|
25
|
+
cites as the primary example: the object literal's own key/value
|
|
26
|
+
types are already known at the declaration site, and `Record<K, V>`
|
|
27
|
+
throws that evidence away in favor of a uniform key type — `satisfies
|
|
28
|
+
Record<K, V>` (or no annotation at all, letting inference stand) keeps
|
|
29
|
+
the literal's precise keys and value types AND still gets the
|
|
30
|
+
dictionary-shape check.
|
|
31
|
+
|
|
32
|
+
Everything else upstream covers — return-type widening, assignment
|
|
33
|
+
widening, transitively-resolved `const` references, `as`/type-literal
|
|
34
|
+
targets — is out of scope for this port. Shipped at `hint`: this is a
|
|
35
|
+
readability/precision rule, not a defect-prevention one (this repo's
|
|
36
|
+
audit explicitly ranked it below the top 5 for that reason), and an
|
|
37
|
+
annotated `Record<K, V>` initializer is frequently deliberate (a
|
|
38
|
+
lookup table whose value type is genuinely uniform across keys).
|
|
39
|
+
Self-scan note: do NOT try to make pi-lens's own tree clean against
|
|
40
|
+
this rule; the adopting PR records the 2026-08-19 hit count instead.
|
|
41
|
+
|
|
42
|
+
2026-08-20 (refs #1727, #1777): CONSIDERED for promotion to `error`,
|
|
43
|
+
KEPT at `hint`. AGENTS.md's severity policy admits a rule to `error`
|
|
44
|
+
only with a documented zero-false-positive audit, and `error` is the
|
|
45
|
+
only tier that maps to semantic `blocking`, so promoting it stops an
|
|
46
|
+
agent mid-turn on any file carrying a hit. Four-corpus census, ast-grep
|
|
47
|
+
CLI 0.45:
|
|
48
|
+
|
|
49
|
+
| corpus | hits |
|
|
50
|
+
|---|---:|
|
|
51
|
+
| pi-lens `clients/` | 90 |
|
|
52
|
+
| pi-lens `tests/` | 55 |
|
|
53
|
+
| pi core `packages/` | 74 (64 outside test paths) |
|
|
54
|
+
| opencode `packages/` | 193 (173) |
|
|
55
|
+
| oh-my-pi `packages/` | 828 (687) |
|
|
56
|
+
|
|
57
|
+
Verdict: no structural narrowing found. Every one of the 90 `clients/`
|
|
58
|
+
hits is a module-level lookup table whose value type genuinely IS
|
|
59
|
+
uniform (`LANGUAGE_TO_GRAMMAR`, `DELIVERY_SURFACES`, `EMOJI`,
|
|
60
|
+
`TREE_SITTER_EXT_TO_LANG`) — the exact deliberate use this note already
|
|
61
|
+
names. `Record<K, V>` on a lookup table and `Record<K, V>` on a value
|
|
62
|
+
whose keys were known and thrown away are the SAME syntax; the
|
|
63
|
+
difference is intent, which no relational constraint can read. Splitting
|
|
64
|
+
by `export const` at module scope versus a local `const` was probed and
|
|
65
|
+
rejected: it would encode "module-level tables are fine" as a rule of
|
|
66
|
+
the language, which it is not. Promotion needs a `satisfies` migration
|
|
67
|
+
of pi-lens's own tables, not a rule change.
|
|
68
|
+
rule:
|
|
69
|
+
pattern:
|
|
70
|
+
context: "const $NAME: Record<$K, $V> = { $$$PROPS };"
|
|
71
|
+
selector: variable_declarator
|