@herbertgao/pi-extensions 2026.8.6 → 2026.8.8
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 +8 -6
- package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +2 -2
- package/node_modules/@herbertgao/pi-cc-extensions/README.md +2 -2
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +19 -7
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +30 -9
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/compact-thinking.ts +320 -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 +79 -17
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/hover.ts +27 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +66 -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 +5 -4
- package/node_modules/@juicesharp/rpiv-ask-user-question/ask-user-question.ts +174 -100
- 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 +5 -1
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/keyboard.md +10 -2
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/localization.md +10 -6
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/tool-schema.md +11 -5
- package/node_modules/@juicesharp/rpiv-ask-user-question/locales/en.json +5 -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 +140 -97
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/questionnaire-session.ts +63 -28
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/selectors/projections.ts +22 -15
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/state-reducer.ts +11 -1
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/state.ts +14 -6
- package/node_modules/@juicesharp/rpiv-ask-user-question/tool/response-envelope.ts +11 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/tool/types.ts +11 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/view/components/multi-select-view.ts +31 -17
- package/node_modules/@juicesharp/rpiv-ask-user-question/view/components/preview/preview-block-renderer.ts +15 -6
- package/node_modules/@juicesharp/rpiv-ask-user-question/view/components/wrapping-select.ts +15 -6
- package/node_modules/@juicesharp/rpiv-ask-user-question/view/dialog-builder.ts +86 -38
- package/node_modules/@juicesharp/rpiv-ask-user-question/view/tab-content-strategy.ts +76 -9
- 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-plugins/fast-mode/dist/index.mjs +44 -1856
- package/node_modules/@pi-plugins/fast-mode/dist/index.mjs.map +1 -1
- package/node_modules/@pi-plugins/fast-mode/package.json +4 -6
- package/node_modules/pi-lens/CHANGELOG.md +999 -0
- package/node_modules/pi-lens/README.md +117 -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 +381 -13
- 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 +129 -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 +206 -0
- package/node_modules/pi-lens/dist/clients/cache-observability.js +353 -76
- 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 +84 -14
- package/node_modules/pi-lens/dist/clients/demoted-finding-render.js +155 -0
- package/node_modules/pi-lens/dist/clients/dependency-checker.js +25 -3
- package/node_modules/pi-lens/dist/clients/deps/pi-tui.js +8 -2
- package/node_modules/pi-lens/dist/clients/deps/typebox.js +8 -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/detekt.js +9 -6
- 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/hadolint.js +9 -7
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +895 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +8 -6
- 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 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +25 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/oxlint.js +20 -5
- package/node_modules/pi-lens/dist/clients/dispatch/runners/phpstan.js +44 -11
- 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 +17 -8
- package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +32 -4
- package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +47 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.js +14 -4
- package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +127 -28
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +12 -7
- 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 +188 -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 +21 -10
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +18 -2
- 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 +316 -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 +87 -8
- 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 +9 -2
- 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 +128 -8
- package/node_modules/pi-lens/dist/clients/lsp/client.js +1660 -164
- 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 +2423 -151
- 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 +22 -1
- package/node_modules/pi-lens/dist/clients/ndjson-logger.js +114 -23
- 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 +23 -9
- package/node_modules/pi-lens/dist/clients/project-lens-config.js +3 -0
- package/node_modules/pi-lens/dist/clients/project-report.js +62 -27
- 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 +8 -3
- package/node_modules/pi-lens/dist/clients/read-guard.js +253 -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/builder.js +194 -31
- package/node_modules/pi-lens/dist/clients/review-graph/query.js +52 -4
- package/node_modules/pi-lens/dist/clients/review-graph/revision-drift.js +21 -0
- package/node_modules/pi-lens/dist/clients/review-graph/workspace-modules.js +6 -3
- 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 +352 -45
- package/node_modules/pi-lens/dist/clients/runtime-session.js +373 -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 +620 -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/session-event-guard.js +184 -0
- 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/source-filter.js +6 -2
- package/node_modules/pi-lens/dist/clients/stale-marker.js +17 -0
- package/node_modules/pi-lens/dist/clients/startup-scan.js +5 -2
- 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-logger.js +1 -0
- 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 +61407 -48577
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +476 -57
- 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 +27 -10
- 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/scripts/install-selftest.mjs +99 -11
- package/node_modules/pi-lens/scripts/lib/host-provided-deps.mjs +75 -0
- package/node_modules/pi-lens/scripts/lib/warm-loader-cache.mjs +285 -0
- package/node_modules/pi-lens/scripts/warm-loader-cache.mjs +233 -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 +37 -0
- package/node_modules/pi-web-access/README.md +32 -13
- 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/chrome-cookies.ts +86 -15
- 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/data-uri-sanitize.ts +406 -0
- package/node_modules/pi-web-access/exa.ts +18 -7
- package/node_modules/pi-web-access/extract.ts +40 -5
- package/node_modules/pi-web-access/firecrawl.ts +18 -2
- package/node_modules/pi-web-access/gemini-search.ts +16 -4
- package/node_modules/pi-web-access/github-extract.ts +65 -36
- package/node_modules/pi-web-access/index.ts +60 -61
- package/node_modules/pi-web-access/openai-search.ts +17 -6
- 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/pdf-extract.ts +18 -5
- 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/ssrf-protection.ts +12 -2
- 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 +14 -14
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
id: require-safety-comment-for-as-unknown-as
|
|
2
|
+
valid:
|
|
3
|
+
- |
|
|
4
|
+
// SAFETY: checked above
|
|
5
|
+
const a = x as unknown as Foo;
|
|
6
|
+
- |
|
|
7
|
+
const b = /* SAFETY: inline */ x as unknown as Foo;
|
|
8
|
+
- |
|
|
9
|
+
// SAFETY: arg is validated upstream
|
|
10
|
+
foo(x as unknown as Foo);
|
|
11
|
+
# 2026-08-20 (#1727/#1777): this rule now owns the `as unknown as` shape
|
|
12
|
+
# alone, so a single concrete `as` and a concrete CHAIN are both out of scope
|
|
13
|
+
# here (the chain belongs to no-chained-type-assertions.yml). Widening the
|
|
14
|
+
# pattern back to any assertion reds both.
|
|
15
|
+
- 'const c = x as Foo;'
|
|
16
|
+
- 'const d = x as A as B;'
|
|
17
|
+
# #1847: the `inside:` kind list omitted `export_statement`, so a
|
|
18
|
+
# SAFETY: comment above an EXPORTED cast could not satisfy the valve.
|
|
19
|
+
# Dropping `export_statement` from the rule's kind list reds this case.
|
|
20
|
+
- |
|
|
21
|
+
// SAFETY: node exposes this at runtime, absent from @types/node
|
|
22
|
+
export const b = (globalThis as unknown as { z: number }).z;
|
|
23
|
+
# #1847: same gap for a class-field cast — the kind list omitted
|
|
24
|
+
# `public_field_definition`. Dropping it from the rule's kind list
|
|
25
|
+
# reds this case.
|
|
26
|
+
- |
|
|
27
|
+
class Foo {
|
|
28
|
+
// SAFETY: server always sends this field at runtime
|
|
29
|
+
bar: unknown = (globalThis as unknown as { z: number }).z;
|
|
30
|
+
}
|
|
31
|
+
# #1852 review (F1): same gap for an enum member's initializer cast —
|
|
32
|
+
# the kind list omitted `enum_assignment`. Dropping it from the
|
|
33
|
+
# rule's kind list reds this case. Covers plain, `const`, and
|
|
34
|
+
# `export` enum alike — `enum_assignment` is the member node itself,
|
|
35
|
+
# unaffected by keywords on the enclosing `enum_declaration`.
|
|
36
|
+
# (`declare enum` members have no initializer expression to cast, so
|
|
37
|
+
# there is nothing to probe for that flavor.)
|
|
38
|
+
- |
|
|
39
|
+
enum Direction {
|
|
40
|
+
// SAFETY: node exposes this at runtime, absent from @types/node
|
|
41
|
+
Up = (globalThis as unknown as { z: number }).z,
|
|
42
|
+
}
|
|
43
|
+
- |
|
|
44
|
+
const enum Direction {
|
|
45
|
+
// SAFETY: node exposes this at runtime, absent from @types/node
|
|
46
|
+
Up = (globalThis as unknown as { z: number }).z,
|
|
47
|
+
}
|
|
48
|
+
- |
|
|
49
|
+
export enum Direction {
|
|
50
|
+
// SAFETY: node exposes this at runtime, absent from @types/number
|
|
51
|
+
Up = (globalThis as unknown as { z: number }).z,
|
|
52
|
+
}
|
|
53
|
+
# #1852 review over-suppression probe: two casts inside ONE exported
|
|
54
|
+
# declaration under a single SAFETY: comment. This is pre-existing
|
|
55
|
+
# behavior, not new — the same one-comment-covers-the-whole-statement
|
|
56
|
+
# trade already applied to `lexical_declaration`/`variable_declaration`
|
|
57
|
+
# before #1847 (verified: an unexported `const pair = {a: x as unknown
|
|
58
|
+
# as Foo, b: y as unknown as Foo}` under one SAFETY: comment was
|
|
59
|
+
# already 0 findings on master). The "Scope and known gap" note above
|
|
60
|
+
# states the valve is statement-scoped, not cast-scoped, by design:
|
|
61
|
+
# "a comment is accepted if it directly precedes... the assertion's
|
|
62
|
+
# containing... statement." `export_statement` inherits that same
|
|
63
|
+
# trade; it does not introduce a new one. Locked in here so a future
|
|
64
|
+
# narrowing of the scope is a deliberate choice, not an accident.
|
|
65
|
+
- |
|
|
66
|
+
// SAFETY: both fields document the same upstream payload shape
|
|
67
|
+
export const pair = { a: x as unknown as Foo, b: y as unknown as Foo };
|
|
68
|
+
# #1870: tree-sitter-typescript calls an object-literal member a `pair`.
|
|
69
|
+
# A comment directly above that pair is the natural local anchor.
|
|
70
|
+
- |
|
|
71
|
+
const config = {
|
|
72
|
+
// SAFETY: input is validated by the config loader
|
|
73
|
+
value: input as unknown as string,
|
|
74
|
+
};
|
|
75
|
+
- |
|
|
76
|
+
configure({
|
|
77
|
+
// SAFETY: input is validated by the config loader
|
|
78
|
+
value: input as unknown as string,
|
|
79
|
+
});
|
|
80
|
+
# Direct comments immediately above casts in array elements and call
|
|
81
|
+
# arguments are supported by the direct-cast arm.
|
|
82
|
+
- |
|
|
83
|
+
const values = [
|
|
84
|
+
// SAFETY: input is validated by the config loader
|
|
85
|
+
input as unknown as string,
|
|
86
|
+
];
|
|
87
|
+
- |
|
|
88
|
+
configure(
|
|
89
|
+
// SAFETY: input is validated by the config loader
|
|
90
|
+
input as unknown as string,
|
|
91
|
+
);
|
|
92
|
+
invalid:
|
|
93
|
+
- "const a = x as unknown as Foo;"
|
|
94
|
+
- |
|
|
95
|
+
const b = x as unknown as Foo; // no safety note
|
|
96
|
+
- |
|
|
97
|
+
// some other comment
|
|
98
|
+
const c = x as unknown as Foo;
|
|
99
|
+
# The comment must actually claim safety. A comment mentioning the word in
|
|
100
|
+
# prose without the `SAFETY:` marker does not clear it — deleting the
|
|
101
|
+
# `SAFETY\s*:` regex from the rule reds this case.
|
|
102
|
+
- |
|
|
103
|
+
// this cast is safe, trust me
|
|
104
|
+
const d = x as unknown as Foo;
|
|
105
|
+
# #1834: the `follows: {stopBy: end}` scan is unbounded — it must not walk
|
|
106
|
+
# past the contiguous comment block into an EARLIER statement's SAFETY:
|
|
107
|
+
# comment. A stray SAFETY: comment anywhere earlier in the same block must
|
|
108
|
+
# not exempt a later, undocumented cast.
|
|
109
|
+
- |
|
|
110
|
+
function f(x: unknown, y: unknown) {
|
|
111
|
+
// SAFETY: this comment documents a DIFFERENT assertion below.
|
|
112
|
+
const a = (y as unknown as string).length;
|
|
113
|
+
|
|
114
|
+
const b = (x as unknown as string).length;
|
|
115
|
+
return a + b;
|
|
116
|
+
}
|
|
117
|
+
# SAFETY: on cast A must not bleed to cast B directly below it, even with
|
|
118
|
+
# no other statement in between.
|
|
119
|
+
- |
|
|
120
|
+
// SAFETY: documents castA only
|
|
121
|
+
const castA = a as unknown as Foo;
|
|
122
|
+
const castB = b as unknown as Foo;
|
|
123
|
+
# #1847: an exported cast with no SAFETY: comment must still flag —
|
|
124
|
+
# adding `export_statement` to the valve must not turn it into a
|
|
125
|
+
# blanket exemption for every exported cast.
|
|
126
|
+
- "export const b = (globalThis as unknown as { z: number }).z;"
|
|
127
|
+
# #1847: an undocumented class-field cast must still flag — adding
|
|
128
|
+
# `public_field_definition` to the valve must not exempt every field
|
|
129
|
+
# cast regardless of a SAFETY: comment.
|
|
130
|
+
- |
|
|
131
|
+
class Foo {
|
|
132
|
+
bar: unknown = (globalThis as unknown as { z: number }).z;
|
|
133
|
+
}
|
|
134
|
+
# #1852 review (F1): an undocumented enum-member cast must still flag
|
|
135
|
+
# — adding `enum_assignment` to the valve must not exempt every enum
|
|
136
|
+
# member cast regardless of a SAFETY: comment.
|
|
137
|
+
- |
|
|
138
|
+
enum Direction {
|
|
139
|
+
Up = (globalThis as unknown as { z: number }).z,
|
|
140
|
+
}
|
|
141
|
+
# #1852 review over-suppression probe: a SAFETY: comment separated
|
|
142
|
+
# from the cast by an unrelated statement must NOT suppress. This is
|
|
143
|
+
# already enforced by #1834's `stopBy: {not: {kind: comment}}` bound
|
|
144
|
+
# (the comment is no longer the statement's immediate preceding
|
|
145
|
+
# sibling once another statement sits between them), but it had no
|
|
146
|
+
# dedicated minimal fixture — the existing #1834 cases both pair the
|
|
147
|
+
# comment with a DIFFERENT documented cast, not a bare intervening
|
|
148
|
+
# statement.
|
|
149
|
+
- |
|
|
150
|
+
// SAFETY: documents nothing below — an unrelated call sits between
|
|
151
|
+
doSomethingUnrelated();
|
|
152
|
+
const b = x as unknown as Foo;
|
|
153
|
+
# A comment on an unrelated sibling pair must not reach a later pair.
|
|
154
|
+
- |
|
|
155
|
+
const config = {
|
|
156
|
+
unrelated: 1,
|
|
157
|
+
// SAFETY: this documents a different property
|
|
158
|
+
other: 2,
|
|
159
|
+
target: input as unknown as string,
|
|
160
|
+
};
|
|
161
|
+
# An outer pair comment must not cross into a nested pair.
|
|
162
|
+
- |
|
|
163
|
+
const config = {
|
|
164
|
+
// SAFETY: only the parent property is validated
|
|
165
|
+
parent: {
|
|
166
|
+
nestedTarget: value as unknown as string,
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
# A nested pair comment must not travel outward to a parent cast.
|
|
170
|
+
- |
|
|
171
|
+
const config = {
|
|
172
|
+
parent: value as unknown as string,
|
|
173
|
+
// SAFETY: only the nested property is validated
|
|
174
|
+
nested: {
|
|
175
|
+
child: value as unknown as string,
|
|
176
|
+
},
|
|
177
|
+
};
|
|
@@ -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
|