@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
|
@@ -34,6 +34,112 @@ pi-lens gives AI coding agents fast, language-aware feedback while they write/ed
|
|
|
34
34
|
- MCP server (experimental) so Claude Code or any MCP client can drive the
|
|
35
35
|
same diagnostics/read-substitute tools pi-lens exposes to pi
|
|
36
36
|
|
|
37
|
+
## Architecture
|
|
38
|
+
|
|
39
|
+
Most lifecycle events enter through one wrapper, which drops and counts events
|
|
40
|
+
that arrive on a replaced session. `tool_call` registers raw: it delegates
|
|
41
|
+
straight to a handler that owns its own total guard. Events fan out into the
|
|
42
|
+
edit-time lane and the LSP lane. Both lanes write into the findings stores.
|
|
43
|
+
Nothing reaches the agent from those stores until a freshness gate or an
|
|
44
|
+
explicit age label clears it.
|
|
45
|
+
|
|
46
|
+
```mermaid
|
|
47
|
+
flowchart TD
|
|
48
|
+
subgraph host["pi host"]
|
|
49
|
+
HOST["Host events<br/>tool_call, tool_result, turn_start/end,<br/>session_start/shutdown, agent_end, context"]
|
|
50
|
+
WRAP["Stale-ctx wrapper<br/>skips and counts events on a replaced session<br/>tool_result, turn_start, turn_end, agent_end,<br/>agent_settled, session_start, context"]
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
subgraph guards["Guards"]
|
|
54
|
+
RG["Read-guard<br/>blocks edits that lack prior reading"]
|
|
55
|
+
GG["Git-guard<br/>holds commit/push while findings stay unresolved"]
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
subgraph edit["Edit-time lane"]
|
|
59
|
+
PIPE["Post-write pipeline<br/>secrets, format, autofix, sync, lint, tests"]
|
|
60
|
+
PLAN["Dispatch plan<br/>per file kind, per capability group"]
|
|
61
|
+
RUN["Runners<br/>format, lint, types, security, smells, docs"]
|
|
62
|
+
STRUCT["Structural rules<br/>tree-sitter queries and ast-grep"]
|
|
63
|
+
BUS["files-touched bus<br/>tells extensions which paths moved"]
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
subgraph lsp["LSP lane"]
|
|
67
|
+
POOL["Client pool<br/>warm reuse, idle eviction"]
|
|
68
|
+
DIAGS["File and workspace diagnostics"]
|
|
69
|
+
CASC["Impact cascade<br/>tiered wait policy"]
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
STORES["Findings stores<br/>widget state, warning caches, project snapshot"]
|
|
73
|
+
|
|
74
|
+
subgraph gate["Freshness gating"]
|
|
75
|
+
FRESH["Path freshness<br/>mtime vs scan time, past-EOF, dependency drift"]
|
|
76
|
+
DISPO["Dispositions<br/>false-positive, suppress, defer, flagged"]
|
|
77
|
+
LABEL["Explicit age label<br/>for findings no path gate can check"]
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
subgraph deliver["Delivery surfaces"]
|
|
81
|
+
TURN["Turn-end findings injection"]
|
|
82
|
+
WIDGET["Widget and footer tally"]
|
|
83
|
+
TOOLS["lens_diagnostics tool"]
|
|
84
|
+
NUDGE["Agent nudges"]
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
SESSION["Session lifecycle<br/>primary, sequential replacement, concurrent secondary"]
|
|
88
|
+
SINKS["Observability sinks<br/>latency.log, degradation ledger, bounded telemetry,<br/>cache observability, cascade and tree-sitter logs"]
|
|
89
|
+
|
|
90
|
+
HOST --> WRAP
|
|
91
|
+
HOST -->|tool_call, raw| RG
|
|
92
|
+
HOST -->|tool_call, raw| GG
|
|
93
|
+
WRAP -->|session_start| SESSION
|
|
94
|
+
WRAP -->|tool_result| PIPE
|
|
95
|
+
WRAP -->|tool_result, records reads and writes| RG
|
|
96
|
+
SESSION --> POOL
|
|
97
|
+
SESSION --> STORES
|
|
98
|
+
PIPE --> PLAN
|
|
99
|
+
PLAN --> RUN
|
|
100
|
+
PLAN --> STRUCT
|
|
101
|
+
PIPE --> POOL
|
|
102
|
+
PIPE --> BUS
|
|
103
|
+
POOL --> DIAGS
|
|
104
|
+
DIAGS --> CASC
|
|
105
|
+
RUN --> STORES
|
|
106
|
+
STRUCT --> STORES
|
|
107
|
+
DIAGS --> STORES
|
|
108
|
+
CASC --> STORES
|
|
109
|
+
BUS --> NUDGE
|
|
110
|
+
RG -->|read and edit history filter| NUDGE
|
|
111
|
+
STORES --> FRESH
|
|
112
|
+
STORES --> LABEL
|
|
113
|
+
FRESH --> DISPO
|
|
114
|
+
DISPO --> TURN
|
|
115
|
+
DISPO --> WIDGET
|
|
116
|
+
DISPO --> TOOLS
|
|
117
|
+
LABEL --> TURN
|
|
118
|
+
TURN --> GG
|
|
119
|
+
WRAP --> SINKS
|
|
120
|
+
PIPE --> SINKS
|
|
121
|
+
RUN --> SINKS
|
|
122
|
+
STRUCT --> SINKS
|
|
123
|
+
POOL --> SINKS
|
|
124
|
+
CASC --> SINKS
|
|
125
|
+
RG --> SINKS
|
|
126
|
+
GG --> SINKS
|
|
127
|
+
FRESH --> SINKS
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Architecture-level view, updated when a lane changes. Per-tool inventories live
|
|
131
|
+
in [features](docs/features.md) and
|
|
132
|
+
[language coverage](docs/language-coverage.md). Today the edit-time lane carries
|
|
133
|
+
45+ runner modules over 35+ file kinds, and the LSP lane speaks to a dozen-plus
|
|
134
|
+
language servers.
|
|
135
|
+
|
|
136
|
+
The gating box is an abstraction, not a call order. Freshness covers several
|
|
137
|
+
independent mechanisms: path freshness against scan time, past-EOF line checks,
|
|
138
|
+
and forward-import dependency drift. Dispositions are one more filter alongside
|
|
139
|
+
them, not a second stage every finding walks through. Read the box as "a finding
|
|
140
|
+
passes the gates that apply to it", and see `clients/finding-delivery-gate.ts`
|
|
141
|
+
for the per-surface contract.
|
|
142
|
+
|
|
37
143
|
## Install
|
|
38
144
|
|
|
39
145
|
```bash
|
|
@@ -213,11 +319,19 @@ Thanks goes to these wonderful people:
|
|
|
213
319
|
</tr>
|
|
214
320
|
<tr>
|
|
215
321
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/pppobear"><img src="https://avatars.githubusercontent.com/u/21952175?v=4" width="100px;" alt=""/><br /><sub><b>pppobear</b></sub></a><br /><a href="#bug-pppobear" title="Bug reports">🐛</a></td>
|
|
322
|
+
<td align="center" valign="top" width="14.28%"><a href="https://github.com/bcachet"><img src="https://avatars.githubusercontent.com/u/45542?v=4" width="100px;" alt=""/><br /><sub><b>Bertrand Cachet</b></sub></a><br /><a href="#code-bcachet" title="Code">💻</a></td>
|
|
323
|
+
<td align="center" valign="top" width="14.28%"><a href="https://github.com/EarthChen"><img src="https://avatars.githubusercontent.com/u/20179425?v=4" width="100px;" alt=""/><br /><sub><b>earthchen</b></sub></a><br /><a href="#code-EarthChen" title="Code">💻</a></td>
|
|
324
|
+
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Don-Yin"><img src="https://avatars.githubusercontent.com/u/65135356?v=4" width="100px;" alt=""/><br /><sub><b>Don Yin</b></sub></a><br /><a href="#code-Don-Yin" title="Code">💻</a></td>
|
|
325
|
+
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ELA718"><img src="https://avatars.githubusercontent.com/u/193304463?v=4" width="100px;" alt=""/><br /><sub><b>ELA718</b></sub></a><br /><a href="#doc-ELA718" title="Documentation">📖</a></td>
|
|
326
|
+
<td align="center" valign="top" width="14.28%"><a href="https://github.com/sujeito-operator/pilot"><img src="https://avatars.githubusercontent.com/u/313599463?v=4" width="100px;" alt=""/><br /><sub><b>Sujeito Operator</b></sub></a><br /><a href="#code-sujeito-operator" title="Code">💻</a></td>
|
|
327
|
+
<td align="center" valign="top" width="14.28%"><a href="http://www.blahs.life/"><img src="https://avatars.githubusercontent.com/u/620336?v=4" width="100px;" alt=""/><br /><sub><b>Dan Blah</b></sub></a><br /><a href="#bug-danblah" title="Bug reports">🐛</a></td>
|
|
328
|
+
</tr>
|
|
329
|
+
<tr>
|
|
216
330
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/3choBoomer"><img src="https://avatars.githubusercontent.com/u/521828?v=4" width="100px;" alt=""/><br /><sub><b>Nathan Cooke</b></sub></a><br /><a href="#code-3choBoomer" title="Code">💻</a></td>
|
|
217
331
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/white-hat"><img src="https://avatars.githubusercontent.com/u/922988?v=4" width="100px;" alt=""/><br /><sub><b>Eli Stark</b></sub></a><br /><a href="#code-white-hat" title="Code">💻</a></td>
|
|
218
|
-
<td align="center" valign="top" width="14.28%"><a href="https://
|
|
219
|
-
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mjfaga"><img src="https://avatars.githubusercontent.com/u/7584015?v=4" width="100px;" alt=""/><br /><sub><b>Mark
|
|
220
|
-
<td align="center" valign="top" width="14.28%"><a href="https://
|
|
332
|
+
<td align="center" valign="top" width="14.28%"><a href="https://marvinaziz.de/"><img src="https://avatars.githubusercontent.com/u/33159023?v=4" width="100px;" alt=""/><br /><sub><b>Marvin Aziz</b></sub></a><br /><a href="#code-marvtub" title="Code">💻</a></td>
|
|
333
|
+
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mjfaga"><img src="https://avatars.githubusercontent.com/u/7584015?v=4" width="100px;" alt=""/><br /><sub><b>Mark</b></sub></a><br /><a href="#code-mjfaga" title="Code">💻</a></td>
|
|
334
|
+
<td align="center" valign="top" width="14.28%"><a href="https://aeturnal.io/"><img src="https://avatars.githubusercontent.com/u/219271200?v=4" width="100px;" alt=""/><br /><sub><b>aeturnal</b></sub></a><br /><a href="#code-aeturnal" title="Code">💻</a></td>
|
|
221
335
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/floatGray"><img src="https://avatars.githubusercontent.com/u/44295302?v=4" width="100px;" alt=""/><br /><sub><b>floatGray</b></sub></a><br /><a href="#code-floatGray" title="Code">💻</a></td>
|
|
222
336
|
</tr>
|
|
223
337
|
</tbody>
|
|
@@ -16,10 +16,52 @@ select = [
|
|
|
16
16
|
"SIM", # flake8-simplify (simplifiable constructs)
|
|
17
17
|
"C4", # flake8-comprehensions (unnecessary comprehension patterns)
|
|
18
18
|
"PIE", # flake8-pie (misc lints)
|
|
19
|
+
"S", # flake8-bandit (Bandit-equivalent security checks; refs #1757)
|
|
19
20
|
]
|
|
20
21
|
|
|
22
|
+
# C90 (mccabe cyclomatic complexity) — considered and NOT enabled (refs #1757).
|
|
23
|
+
# Measured against `requests` (mature, well-styled: 2 hits over the default
|
|
24
|
+
# threshold of 10, both genuinely complex) and `pandas` (379 hits) — the
|
|
25
|
+
# signal is real complexity, not false positives, but the volume on a large
|
|
26
|
+
# pre-existing codebase would drown the security signal `S` adds in the same
|
|
27
|
+
# pass. C90 is a maintainability metric, not a Bandit-equivalent security
|
|
28
|
+
# check, so it stays out of scope for this issue. Revisit as its own opt-in
|
|
29
|
+
# if pi-lens grows a "code health" ruleset.
|
|
30
|
+
|
|
31
|
+
# S sub-rules excluded below were triaged by running `ruff check --select S`
|
|
32
|
+
# against tests/fixtures/real-bugs/python/silent-and-security.py (this repo's
|
|
33
|
+
# own security fixture — 3/3 true positives: S110, S105, S307) and against the
|
|
34
|
+
# `requests` and `pip` packages installed under a local Python 3.11 (394
|
|
35
|
+
# combined S findings across two mature, widely-audited real-world
|
|
36
|
+
# codebases) — chosen as the "2-3 real fixtures" because pi-lens's own repo
|
|
37
|
+
# only has ~15 Python files, too small to expose over-firing sub-rules.
|
|
21
38
|
ignore = [
|
|
22
39
|
"E501", # line too long — formatter handles this
|
|
23
40
|
"B008", # function call in default argument — common FastAPI/typer pattern
|
|
24
41
|
"SIM108", # ternary operator — readability is subjective
|
|
42
|
+
|
|
43
|
+
# S101 assert: 354 of 394 S hits (90%) across requests+pip were bare
|
|
44
|
+
# `assert` statements — the risk `S101` warns about (asserts stripped under
|
|
45
|
+
# `python -O`) is real only for security-enforcement code, not general
|
|
46
|
+
# application or test code, where `assert` is idiomatic (pytest). Pure
|
|
47
|
+
# noise at this volume.
|
|
48
|
+
"S101",
|
|
49
|
+
# S311 suspicious-non-cryptographic-random-usage: every hit observed
|
|
50
|
+
# (e.g. pip/_internal/utils/filesystem.py building a temp-file suffix) was
|
|
51
|
+
# a non-security use of `random` — file names, jitter, sampling. Ruff
|
|
52
|
+
# cannot distinguish security-sensitive randomness from ordinary use.
|
|
53
|
+
"S311",
|
|
54
|
+
# S603 subprocess-without-shell-equals-true: fires on every list-argument
|
|
55
|
+
# `subprocess.run(...)`/`Popen(...)` call regardless of whether the
|
|
56
|
+
# arguments are attacker-controlled — this is the RECOMMENDED safe form
|
|
57
|
+
# (no shell=True), yet it was the rule's only trigger condition in every
|
|
58
|
+
# one of the 10 hits observed in pip. Bandit's own docs note this rule's
|
|
59
|
+
# high false-positive rate; excluded for the same reason upstream projects
|
|
60
|
+
# commonly disable it.
|
|
61
|
+
"S603",
|
|
62
|
+
# S607 start-process-with-partial-path: fires whenever a subprocess call
|
|
63
|
+
# names its executable by PATH lookup (`["rustc", "--version"]`) instead of
|
|
64
|
+
# an absolute path — standard practice for any CLI-wrapping code, and both
|
|
65
|
+
# observed hits in pip were exactly that pattern, not a real vulnerability.
|
|
66
|
+
"S607",
|
|
25
67
|
]
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import * as fs from "node:fs";
|
|
3
3
|
import * as path from "node:path";
|
|
4
|
+
import { hashText, normalizeMessage, stableFindingId, } from "./finding-identity.js";
|
|
4
5
|
import { applyWorkspaceEdit } from "./lsp/edits.js";
|
|
5
6
|
import { getLSPService } from "./lsp/index.js";
|
|
6
7
|
import { normalizeMapKey } from "./path-utils.js";
|
|
@@ -14,19 +15,47 @@ let beforeWarningStateLockForTests = null;
|
|
|
14
15
|
export function _setBeforeWarningStateLockForTests(hook) {
|
|
15
16
|
beforeWarningStateLockForTests = hook;
|
|
16
17
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const rel = path.relative(cwd, filePath).replace(/\\/g, "/");
|
|
25
|
-
return rel && !rel.startsWith("..") ? rel : normalizeMapKey(filePath);
|
|
26
|
-
}
|
|
18
|
+
/** #1816: was a local `relativeFile|tool|source|code|rule|normalizedMessage|
|
|
19
|
+
* line` hash, hand-rolled independently of `diagnostic-dispositions.ts`'s
|
|
20
|
+
* canonicalizing version — this is now the shared `finding-identity.js`
|
|
21
|
+
* builder (which DOES canonicalize both `cwd` and `filePath` through
|
|
22
|
+
* `normalizeMapKey` before relativizing, and hashes to 12 chars, matching
|
|
23
|
+
* dispositions). See `legacyActionableWarningId` below for the pre-#1816
|
|
24
|
+
* formula, kept only for on-disk suppression-store migration. */
|
|
27
25
|
export function createActionableWarningId(args) {
|
|
26
|
+
return stableFindingId("aw:", {
|
|
27
|
+
cwd: args.cwd,
|
|
28
|
+
filePath: args.filePath,
|
|
29
|
+
parts: [
|
|
30
|
+
args.tool,
|
|
31
|
+
args.source,
|
|
32
|
+
args.code,
|
|
33
|
+
args.rule,
|
|
34
|
+
normalizeMessage(args.message),
|
|
35
|
+
args.line,
|
|
36
|
+
],
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
/** PRE-#1816 id formula (raw, non-canonicalized `relativeFile`; 10-char
|
|
40
|
+
* hash). `actionable-warning-state.json` is a keyed, persisted store — a
|
|
41
|
+
* warning suppressed under the old formula must not silently reappear as
|
|
42
|
+
* unsuppressed just because this module unified onto the canonical,
|
|
43
|
+
* 12-char id. `suppressionFor`/`updateWarningState` use this ONLY to look up
|
|
44
|
+
* and migrate a still-pending old entry forward; nothing ever WRITES under
|
|
45
|
+
* this id. Do not canonicalize this function — that would make it identical
|
|
46
|
+
* to `createActionableWarningId` and silently defeat the migration lookup
|
|
47
|
+
* for every path that actually needed canonicalizing (the #533 class this
|
|
48
|
+
* whole item exists to fix). Review-round F3 (#1816): this guard is only
|
|
49
|
+
* provable under a MIS-CASED path fixture — a fixture whose raw and
|
|
50
|
+
* canonical forms coincide (a bare mkdtempSync path) makes canonicalizing
|
|
51
|
+
* this function a no-op, so the regression test must seed under a mis-cased
|
|
52
|
+
* segment (see `actionable-warnings.test.ts`'s migration describe block) or
|
|
53
|
+
* the guard passes vacuously either way. */
|
|
54
|
+
function legacyActionableWarningId(args) {
|
|
55
|
+
const rel = path.relative(args.cwd, args.filePath).replace(/\\/g, "/");
|
|
56
|
+
const legacyRelativeFile = rel && !rel.startsWith("..") ? rel : normalizeMapKey(args.filePath);
|
|
28
57
|
const parts = [
|
|
29
|
-
|
|
58
|
+
legacyRelativeFile,
|
|
30
59
|
args.tool ?? "",
|
|
31
60
|
args.source ?? "",
|
|
32
61
|
String(args.code ?? ""),
|
|
@@ -34,7 +63,7 @@ export function createActionableWarningId(args) {
|
|
|
34
63
|
normalizeMessage(args.message),
|
|
35
64
|
String(args.line ?? ""),
|
|
36
65
|
];
|
|
37
|
-
return `aw:${hashText(parts.join("|"))}`;
|
|
66
|
+
return `aw:${hashText(parts.join("|"), 10)}`;
|
|
38
67
|
}
|
|
39
68
|
function actionSafety(action) {
|
|
40
69
|
const kind = action.kind ?? "";
|
|
@@ -93,7 +122,28 @@ function updateWarningState(cwd, warnings) {
|
|
|
93
122
|
const now = new Date().toISOString();
|
|
94
123
|
state.warnings ??= {};
|
|
95
124
|
for (const warning of warnings) {
|
|
96
|
-
|
|
125
|
+
// #1816 migration: this warning may still be recorded under the
|
|
126
|
+
// pre-#1816 id (raw relativeFile, 10-char hash) from before this
|
|
127
|
+
// store unified onto the canonical id. Fold that entry forward
|
|
128
|
+
// onto the current id and drop the stale key, so a warning
|
|
129
|
+
// suppressed before the migration stays suppressed, and repeated
|
|
130
|
+
// re-encounters converge the store onto one id per warning
|
|
131
|
+
// instead of accumulating both forever.
|
|
132
|
+
//
|
|
133
|
+
// Review-round F1: this MUST read `warning.legacyId` — the value
|
|
134
|
+
// `suppressionFor` already computed from the exact identity args
|
|
135
|
+
// used at lookup time — and must NEVER re-derive a legacy id from
|
|
136
|
+
// `warning.rule`/`tool`/`source`/`code`. Those fields hold
|
|
137
|
+
// DISPLAY values that diverge from the id-construction args for
|
|
138
|
+
// LSP-origin records (see `ActionableWarningRecord.legacyId`'s
|
|
139
|
+
// doc comment), so a re-derivation here would compute a
|
|
140
|
+
// different legacy id than the one `suppressionFor` checked,
|
|
141
|
+
// permanently bifurcating the store.
|
|
142
|
+
const legacyId = warning.legacyId;
|
|
143
|
+
const legacyEntry = legacyId && legacyId !== warning.id
|
|
144
|
+
? state.warnings[legacyId]
|
|
145
|
+
: undefined;
|
|
146
|
+
const existing = state.warnings[warning.id] ?? legacyEntry ?? {};
|
|
97
147
|
state.warnings[warning.id] = {
|
|
98
148
|
...existing,
|
|
99
149
|
status: existing.status ?? "active",
|
|
@@ -101,6 +151,8 @@ function updateWarningState(cwd, warnings) {
|
|
|
101
151
|
lastSeenAt: now,
|
|
102
152
|
seenCount: (existing.seenCount ?? 0) + 1,
|
|
103
153
|
};
|
|
154
|
+
if (legacyEntry && legacyId)
|
|
155
|
+
delete state.warnings[legacyId];
|
|
104
156
|
}
|
|
105
157
|
return state;
|
|
106
158
|
},
|
|
@@ -115,36 +167,64 @@ function updateWarningState(cwd, warnings) {
|
|
|
115
167
|
}),
|
|
116
168
|
});
|
|
117
169
|
}
|
|
118
|
-
|
|
119
|
-
|
|
170
|
+
/** Looks up suppression under the current id, falling back to the pre-#1816
|
|
171
|
+
* id (see `legacyActionableWarningId`) so a warning suppressed before this
|
|
172
|
+
* migration doesn't silently reappear as unsuppressed. `args` is the exact
|
|
173
|
+
* identity shape both id builders take.
|
|
174
|
+
*
|
|
175
|
+
* Also RETURNS the `legacyId` it computed (review-round F1, #1816): the
|
|
176
|
+
* caller carries it onto the record's `legacyId` field so
|
|
177
|
+
* `updateWarningState` can migrate the SAME legacy id this lookup used,
|
|
178
|
+
* instead of re-deriving one from the record's own `rule`/`tool`/`source`/
|
|
179
|
+
* `code` fields later. Re-deriving is unsound for LSP-origin records —
|
|
180
|
+
* `recordFromLspDiagnostic` passes no `rule` into this function (LSP
|
|
181
|
+
* diagnostics don't have one), then sets `record.rule` afterward to
|
|
182
|
+
* `${source}:${code}` purely for display. Recomputing from that display
|
|
183
|
+
* value would silently compute a DIFFERENT legacy id than the one actually
|
|
184
|
+
* checked here, permanently bifurcating the store: a suppression written
|
|
185
|
+
* this turn under the current id would never be found again next turn. */
|
|
186
|
+
function suppressionFor(cwd, id, args) {
|
|
187
|
+
const state = readSuppressionState(cwd);
|
|
188
|
+
const legacyId = legacyActionableWarningId({ cwd, ...args });
|
|
189
|
+
const entry = state.warnings?.[id] ??
|
|
190
|
+
(legacyId !== id ? state.warnings?.[legacyId] : undefined);
|
|
120
191
|
return {
|
|
121
192
|
suppressed: entry?.status === "suppressed",
|
|
122
193
|
reason: entry?.reason,
|
|
194
|
+
legacyId,
|
|
123
195
|
};
|
|
124
196
|
}
|
|
125
197
|
export function recordFromDispatchDiagnostic(diagnostic, cwd) {
|
|
126
|
-
if (diagnostic.semantic !== "warning"
|
|
198
|
+
if (diagnostic.semantic !== "warning")
|
|
199
|
+
return undefined;
|
|
200
|
+
// #1777: the old gate demanded `severity === "warning"` exactly, which was
|
|
201
|
+
// invisible while the ast-grep runner collapsed every non-error tier to
|
|
202
|
+
// "warning". Now that hint and info survive the dispatch path, admit them:
|
|
203
|
+
// a fix is a fix, and the tier governs how loudly a finding renders, not
|
|
204
|
+
// whether its fix is worth offering. `error` still routes to the blocking
|
|
205
|
+
// path, so it stays out even when a runner leaves `semantic` at "warning".
|
|
206
|
+
if (diagnostic.severity === "error")
|
|
127
207
|
return undefined;
|
|
128
208
|
if (!diagnostic.fixable && !diagnostic.fixSuggestion)
|
|
129
209
|
return undefined;
|
|
130
210
|
const filePath = path.resolve(cwd, diagnostic.filePath);
|
|
131
|
-
const
|
|
132
|
-
cwd,
|
|
211
|
+
const identityArgs = {
|
|
133
212
|
filePath,
|
|
134
213
|
tool: diagnostic.tool,
|
|
135
214
|
code: diagnostic.code,
|
|
136
215
|
rule: diagnostic.rule,
|
|
137
216
|
message: diagnostic.message,
|
|
138
217
|
line: diagnostic.line,
|
|
139
|
-
}
|
|
140
|
-
const
|
|
218
|
+
};
|
|
219
|
+
const id = createActionableWarningId({ cwd, ...identityArgs });
|
|
220
|
+
const suppression = suppressionFor(cwd, id, identityArgs);
|
|
141
221
|
return {
|
|
142
222
|
id,
|
|
143
223
|
filePath,
|
|
144
224
|
displayPath: toRunnerDisplayPath(cwd, filePath),
|
|
145
225
|
line: diagnostic.line,
|
|
146
226
|
column: diagnostic.column,
|
|
147
|
-
severity:
|
|
227
|
+
severity: diagnostic.severity,
|
|
148
228
|
tool: diagnostic.tool,
|
|
149
229
|
code: diagnostic.code,
|
|
150
230
|
rule: diagnostic.rule,
|
|
@@ -155,6 +235,7 @@ export function recordFromDispatchDiagnostic(diagnostic, cwd) {
|
|
|
155
235
|
actions: [],
|
|
156
236
|
suppressed: suppression.suppressed,
|
|
157
237
|
suppressionReason: suppression.reason,
|
|
238
|
+
legacyId: suppression.legacyId,
|
|
158
239
|
origin: "dispatch",
|
|
159
240
|
};
|
|
160
241
|
}
|
|
@@ -170,16 +251,16 @@ function recordFromLspDiagnostic(diag, filePath, cwd) {
|
|
|
170
251
|
const column = diag.range.start.character + 1;
|
|
171
252
|
const source = diag.source ?? "lsp";
|
|
172
253
|
const code = diag.code === undefined ? undefined : String(diag.code);
|
|
173
|
-
const
|
|
174
|
-
cwd,
|
|
254
|
+
const identityArgs = {
|
|
175
255
|
filePath,
|
|
176
256
|
tool: "lsp",
|
|
177
257
|
source,
|
|
178
258
|
code,
|
|
179
259
|
message: diag.message,
|
|
180
260
|
line,
|
|
181
|
-
}
|
|
182
|
-
const
|
|
261
|
+
};
|
|
262
|
+
const id = createActionableWarningId({ cwd, ...identityArgs });
|
|
263
|
+
const suppression = suppressionFor(cwd, id, identityArgs);
|
|
183
264
|
return {
|
|
184
265
|
id,
|
|
185
266
|
filePath,
|
|
@@ -195,6 +276,7 @@ function recordFromLspDiagnostic(diag, filePath, cwd) {
|
|
|
195
276
|
actions: [],
|
|
196
277
|
suppressed: suppression.suppressed,
|
|
197
278
|
suppressionReason: suppression.reason,
|
|
279
|
+
legacyId: suppression.legacyId,
|
|
198
280
|
origin: "lsp",
|
|
199
281
|
};
|
|
200
282
|
}
|
|
@@ -329,8 +411,13 @@ export async function buildActionableWarningsReport(args) {
|
|
|
329
411
|
}
|
|
330
412
|
const merged = mergeWarnings(records);
|
|
331
413
|
updateWarningState(cwd, merged);
|
|
414
|
+
// legacyId is #1816 migration bookkeeping for updateWarningState above —
|
|
415
|
+
// strip it before the report leaves this function, so it never lands in
|
|
416
|
+
// the `.pi-lens/cache/actionable-warnings.json` cache file or any
|
|
417
|
+
// agent-facing rendering of a warning record.
|
|
418
|
+
const reportWarnings = merged.map(({ legacyId: _legacyId, ...rest }) => rest);
|
|
332
419
|
const byFile = new Map();
|
|
333
|
-
for (const warning of
|
|
420
|
+
for (const warning of reportWarnings) {
|
|
334
421
|
const arr = byFile.get(warning.filePath) ?? [];
|
|
335
422
|
arr.push(warning);
|
|
336
423
|
byFile.set(warning.filePath, arr);
|
|
@@ -342,9 +429,16 @@ export async function buildActionableWarningsReport(args) {
|
|
|
342
429
|
warnings,
|
|
343
430
|
}));
|
|
344
431
|
const allActions = merged.flatMap((warning) => warning.actions);
|
|
432
|
+
const unsuppressed = merged.filter((warning) => !warning.suppressed);
|
|
433
|
+
const countTier = (tier) => unsuppressed.filter((warning) => warning.severity === tier).length;
|
|
345
434
|
const summary = {
|
|
346
435
|
warnings: merged.length,
|
|
347
|
-
unsuppressed:
|
|
436
|
+
unsuppressed: unsuppressed.length,
|
|
437
|
+
byTier: {
|
|
438
|
+
warning: countTier("warning"),
|
|
439
|
+
info: countTier("info"),
|
|
440
|
+
hint: countTier("hint"),
|
|
441
|
+
},
|
|
348
442
|
suppressed: merged.filter((warning) => warning.suppressed).length,
|
|
349
443
|
files: files.length,
|
|
350
444
|
actions: allActions.length,
|
|
@@ -586,8 +680,17 @@ export function formatActionableWarningsAdvisory(report) {
|
|
|
586
680
|
const safe = report.summary.autoFixEligible > 0
|
|
587
681
|
? ` ${report.summary.autoFixEligible} appear to have conservative preferred quickfixes.`
|
|
588
682
|
: "";
|
|
683
|
+
// #1777: hint and info are style opinions, so say how much of the count is
|
|
684
|
+
// opinion. The line appears only when a quiet tier is actually present —
|
|
685
|
+
// an all-warning turn already says everything in the count above.
|
|
686
|
+
const byTier = report.summary.byTier;
|
|
687
|
+
const quiet = byTier ? byTier.hint + byTier.info : 0;
|
|
688
|
+
const tierLine = quiet > 0
|
|
689
|
+
? `${quiet} of those are hint/info tier — style opinions, worth fixing only while you are already in that code.`
|
|
690
|
+
: undefined;
|
|
589
691
|
return [
|
|
590
692
|
`🟡 Fixable warnings introduced this turn: ${report.summary.unsuppressed}.${safe}`,
|
|
693
|
+
tierLine,
|
|
591
694
|
`Details written to .pi-lens/cache/actionable-warnings.json`,
|
|
592
695
|
fileList ? `Files:\n${fileList}${more}` : undefined,
|
|
593
696
|
"If continuing in these files, read that JSON and resolve warnings that are safe and relevant. Do not apply broad refactors unless requested.",
|