@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,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cascade neighbour-budget sizing (#1462).
|
|
3
|
+
*
|
|
4
|
+
* The flat neighbour cap (40) and the turn-end settle wait (5000 ms) were set in
|
|
5
|
+
* two different files with nothing relating them. Dogfood 2026-08-15 measured
|
|
6
|
+
* what that costs: n=50 cascades, median 30 ms, max 3.88 s at nbr=40 — and with
|
|
7
|
+
* a `reverse_deps_cache` refresh ahead of the graph build (2046 ms for
|
|
8
|
+
* `logger.ts`) the run overran the turn_end cap, so `cascade_settle_wait`
|
|
9
|
+
* returned `settled: 0` and the finding arrived a turn late.
|
|
10
|
+
*
|
|
11
|
+
* ## What a slow run actually costs
|
|
12
|
+
*
|
|
13
|
+
* It is NOT lost. `RuntimeCoordinator.settleCascadeRuns` re-parks a promise
|
|
14
|
+
* still in flight at the cap, `agent_settled` gives it a second and more
|
|
15
|
+
* generous drain (`cascade_carry_over_settle`, `quietWindowWaitMs`, 15 000 ms),
|
|
16
|
+
* and `beginTurn` deliberately keeps `_pendingCascadeRuns` so anything still
|
|
17
|
+
* running surfaces at a later turn_end — that is #1443, and pre-#450 these
|
|
18
|
+
* findings were always awaited. So the real trade is:
|
|
19
|
+
*
|
|
20
|
+
* full neighbour set, one turn late vs. a narrowed set, on time,
|
|
21
|
+
* with the remainder lost for good
|
|
22
|
+
*
|
|
23
|
+
* Narrowing is therefore only worth paying for when it genuinely converts a
|
|
24
|
+
* late run into an on-time one. That gives three zones, and the derivation
|
|
25
|
+
* below is exactly those three:
|
|
26
|
+
*
|
|
27
|
+
* fits the full walk still fits the on-time window — nothing to do
|
|
28
|
+
* narrowed the RESCUE BAND: the full walk no longer fits but a shorter
|
|
29
|
+
* one does, so trading the tail for on-time delivery buys
|
|
30
|
+
* something real
|
|
31
|
+
* past-rescue not even a floor-sized walk fits any more, so narrowing would
|
|
32
|
+
* drop neighbours permanently AND still miss the window. Keep
|
|
33
|
+
* the full budget and let the carry-over deliver it complete.
|
|
34
|
+
* This is the cold-session case: a fresh graph build measures up
|
|
35
|
+
* to ~19 s (see `runtime-coordinator.ts`'s carry-over note), and
|
|
36
|
+
* a floor-sized stub there is strictly worse than pre-#1462.
|
|
37
|
+
*
|
|
38
|
+
* One more guard, for the same reason. If the on-time window could not fit a
|
|
39
|
+
* full walk even at zero prelude, there is no LATE run to rescue — every
|
|
40
|
+
* cascade would be permanently downsized because a *wait* was configured small.
|
|
41
|
+
* That is a budget change wearing a timeout's clothes, so the derivation stands
|
|
42
|
+
* down entirely (`no-rescue-window`) and the flat cap applies. This is what
|
|
43
|
+
* keeps `PI_LENS_CASCADE_SETTLE_WAIT_MS` from doubling as a neighbour-count
|
|
44
|
+
* knob: at the 5000/100/40 defaults the band is a prelude of 1.0–4.5 s, and
|
|
45
|
+
* shrinking the wait to 1000 ms disables narrowing rather than capping every
|
|
46
|
+
* cascade at ~10 neighbours.
|
|
47
|
+
*/
|
|
48
|
+
import { recordDegradationOnce } from "./degradation-ledger.js";
|
|
49
|
+
import { toPositiveFinite } from "./env-utils.js";
|
|
50
|
+
// The knobs only, never the scheduler — this module is arithmetic and has no
|
|
51
|
+
// business depending on a task registry to read two numbers (#1462 review N4).
|
|
52
|
+
// Note it buys nothing at load time: `runtime-config.js` below already reaches
|
|
53
|
+
// `pidusage` via `lens-config.js`.
|
|
54
|
+
import { isQuietWindowEnabled, quietWindowWaitMs, } from "./quiet-window-config.js";
|
|
55
|
+
import { RUNTIME_CONFIG } from "./runtime-config.js";
|
|
56
|
+
/**
|
|
57
|
+
* Bounded wait for the turn's deferred cascade computes (#450) to settle before
|
|
58
|
+
* they are merged at turn_end. A late compute is carried over, never dropped.
|
|
59
|
+
*
|
|
60
|
+
* `0` is a meaningful setting (never block turn_end), so this deliberately does
|
|
61
|
+
* NOT use `lazyEnvNumber` — that helper treats 0 as "unset" and would silently
|
|
62
|
+
* restore the 5000 ms default.
|
|
63
|
+
*/
|
|
64
|
+
export function cascadeSettleWaitMs() {
|
|
65
|
+
const raw = Number(process.env.PI_LENS_CASCADE_SETTLE_WAIT_MS);
|
|
66
|
+
return Number.isFinite(raw) && raw >= 0 ? raw : 5000;
|
|
67
|
+
}
|
|
68
|
+
/** The budget floor, and the minimum any env override of the cap can produce. */
|
|
69
|
+
const MIN_NEIGHBOUR_BUDGET = RUNTIME_CONFIG.pipeline.cascadeMaxFiles;
|
|
70
|
+
/**
|
|
71
|
+
* The flat per-run cap: the most neighbours a cascade walks. Still the ceiling
|
|
72
|
+
* — the derivation below only ever narrows it, and only inside the rescue band.
|
|
73
|
+
*/
|
|
74
|
+
const DEFAULT_NEIGHBOUR_BUDGET = 40;
|
|
75
|
+
export const CASCADE_NEIGHBOUR_BUDGET = Math.max(MIN_NEIGHBOUR_BUDGET, Number.parseInt(process.env.PI_LENS_CASCADE_NEIGHBOUR_BUDGET ?? "40", 10) ||
|
|
76
|
+
DEFAULT_NEIGHBOUR_BUDGET);
|
|
77
|
+
/**
|
|
78
|
+
* True when `PI_LENS_CASCADE_NEIGHBOUR_BUDGET` moved the ceiling away from the
|
|
79
|
+
* default (#1462 review F-E). Raising it far enough can push
|
|
80
|
+
* `ceiling * perNeighbourMs` past the settle window, so EVERY cascade reads
|
|
81
|
+
* `no-rescue-window` — the whole derivation disarmed by a cap change nobody
|
|
82
|
+
* meant as a timeout change. Read once at load, same lifetime as the constant
|
|
83
|
+
* it describes.
|
|
84
|
+
*/
|
|
85
|
+
const NEIGHBOUR_BUDGET_OVERRIDDEN = process.env.PI_LENS_CASCADE_NEIGHBOUR_BUDGET !== undefined &&
|
|
86
|
+
CASCADE_NEIGHBOUR_BUDGET !== DEFAULT_NEIGHBOUR_BUDGET;
|
|
87
|
+
/**
|
|
88
|
+
* Marginal wall-clock cost of one more neighbour in the walk, in ms. Calibrated
|
|
89
|
+
* on the 2026-08-15 dogfood tail: 3.88 s at nbr=40 and 3.71 s at nbr=38, both
|
|
90
|
+
* ~97 ms per neighbour. Touches fan out in parallel, so this is the observed
|
|
91
|
+
* marginal cost under LSP contention, not one touch's own latency.
|
|
92
|
+
*
|
|
93
|
+
* It is an ESTIMATE, and the derivation is sensitive to it: if the true cost is
|
|
94
|
+
* materially above this, a walk sized against it still overruns (the rescue
|
|
95
|
+
* fails and the tail was dropped for nothing). `scripts/bench-cascade-budget.mjs
|
|
96
|
+
* --true-cost-ms=<n>` measures that sensitivity directly. Rounded UP from the
|
|
97
|
+
* measurement so the estimate errs toward narrowing less.
|
|
98
|
+
*/
|
|
99
|
+
const DEFAULT_NEIGHBOUR_COST_MS = 100;
|
|
100
|
+
/** Read per call — sized once per cascade run, never on a hot path. */
|
|
101
|
+
function neighbourCostMs() {
|
|
102
|
+
return (toPositiveFinite(process.env.PI_LENS_CASCADE_NEIGHBOUR_COST_MS) ||
|
|
103
|
+
DEFAULT_NEIGHBOUR_COST_MS);
|
|
104
|
+
}
|
|
105
|
+
function neighbourFloor() {
|
|
106
|
+
return (toPositiveFinite(process.env.PI_LENS_CASCADE_NEIGHBOUR_FLOOR) ||
|
|
107
|
+
MIN_NEIGHBOUR_BUDGET);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Size one run's neighbour walk against the on-time window supplied by its
|
|
111
|
+
* caller.
|
|
112
|
+
*
|
|
113
|
+
* `elapsedMs` is arithmetic input, not an observation made by this function.
|
|
114
|
+
* The production caller measures it against the active turn_end settle window
|
|
115
|
+
* and passes that elapsed time here. When that boundary is unavailable, the
|
|
116
|
+
* caller passes zero to preserve the flat cap. Legacy callers may still pass
|
|
117
|
+
* deferred run age for compatibility.
|
|
118
|
+
*
|
|
119
|
+
* Every override exists so the derivation can be tested and benchmarked as a
|
|
120
|
+
* pure function; the function itself does not observe a deferred run's age.
|
|
121
|
+
*/
|
|
122
|
+
export function deriveCascadeNeighbourBudget(options) {
|
|
123
|
+
const ceiling = options.ceiling ?? CASCADE_NEIGHBOUR_BUDGET;
|
|
124
|
+
// The floor can never exceed the ceiling — a floor above the cap would make
|
|
125
|
+
// the derived budget LARGER than the flat one it exists to bound.
|
|
126
|
+
const floor = Math.min(ceiling, options.floor ?? neighbourFloor());
|
|
127
|
+
const onTimeMs = options.settleWaitMs ?? cascadeSettleWaitMs();
|
|
128
|
+
const perNeighbourMs = options.perNeighbourMs ?? neighbourCostMs();
|
|
129
|
+
const elapsedMs = toPositiveFinite(options.elapsedMs);
|
|
130
|
+
const remainingMs = onTimeMs - elapsedMs;
|
|
131
|
+
const deliveryWindowMs = onTimeMs +
|
|
132
|
+
(options.quietDrainMs ??
|
|
133
|
+
(isQuietWindowEnabled() ? quietWindowWaitMs() : 0));
|
|
134
|
+
const full = { budget: ceiling, ceiling, remainingMs, deliveryWindowMs };
|
|
135
|
+
// No on-time window at all, or one too small to ever fit a full walk. There
|
|
136
|
+
// is no late run to rescue here, only every run to shrink — stand down.
|
|
137
|
+
//
|
|
138
|
+
// Boundary, acknowledged rather than special-cased: at exactly
|
|
139
|
+
// `onTimeMs === ceiling * perNeighbourMs` this does not fire and the `fits`
|
|
140
|
+
// zone has zero width, so ANY prelude narrows. Not slightly, either — at
|
|
141
|
+
// 4000/100/40 a 2 s prelude gives 20 and a 3.5 s prelude gives the floor.
|
|
142
|
+
// Left alone because the narrowing is honest at that setting: with the
|
|
143
|
+
// window sized to exactly one full walk, a run that has spent any of it
|
|
144
|
+
// really would miss, so every one of those cuts is a genuine rescue rather
|
|
145
|
+
// than the `no-rescue-window` case this guard exists to catch. What it does
|
|
146
|
+
// cost is headroom — see the divisor bands in the bench's `--sweep` text.
|
|
147
|
+
if (onTimeMs <= 0 || onTimeMs < ceiling * perNeighbourMs) {
|
|
148
|
+
// #1462 review F-E: name the override, once per session, when it is the
|
|
149
|
+
// REASON the derivation stood down — not when a caller under test asked
|
|
150
|
+
// for a specific ceiling, and not on every one of the cascades this
|
|
151
|
+
// disarms for the rest of the session.
|
|
152
|
+
if (options.ceiling === undefined && NEIGHBOUR_BUDGET_OVERRIDDEN) {
|
|
153
|
+
recordDegradationOnce({
|
|
154
|
+
kind: "cascade-budget-override-disarmed",
|
|
155
|
+
subject: "cascade-neighbour-budget",
|
|
156
|
+
reason: `PI_LENS_CASCADE_NEIGHBOUR_BUDGET=${CASCADE_NEIGHBOUR_BUDGET} needs ` +
|
|
157
|
+
`${ceiling * perNeighbourMs}ms to walk the full cap, which exceeds ` +
|
|
158
|
+
`the ${onTimeMs}ms settle window — the rescue band is disarmed and ` +
|
|
159
|
+
`every cascade keeps the flat (overridden) cap`,
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
return { ...full, zone: "no-rescue-window" };
|
|
163
|
+
}
|
|
164
|
+
// The full walk still fits. Nothing to buy.
|
|
165
|
+
if (remainingMs >= ceiling * perNeighbourMs) {
|
|
166
|
+
return { ...full, zone: "fits" };
|
|
167
|
+
}
|
|
168
|
+
// Past rescue: not even a floor-sized walk fits, so narrowing would drop the
|
|
169
|
+
// tail permanently and still miss the window. The carry-over delivers the
|
|
170
|
+
// whole set one turn later instead.
|
|
171
|
+
//
|
|
172
|
+
// #1462 review F-B, kept rather than shrunk: one dogfood log measured this
|
|
173
|
+
// zone at 0/1090 cascades, and asked whether a 3-zone module earns its keep
|
|
174
|
+
// at that frequency. It was measured against the WRITE-relative clock this
|
|
175
|
+
// same round fixed, which charges elapsed time no cascade actually spent
|
|
176
|
+
// waiting — so it under-counts how often a genuinely slow compute (a cold
|
|
177
|
+
// graph build, ~19 s) overlaps an already-running settle window, which is
|
|
178
|
+
// exactly what this zone exists to catch (F3, a real regression the first
|
|
179
|
+
// review round found: a floor-sized stub on that cold-start case is
|
|
180
|
+
// strictly worse than pre-#1462). Reachability under the corrected clock
|
|
181
|
+
// has not been re-measured; shrinking on a stale sample would trade a
|
|
182
|
+
// cheap, already-tested guard against a proven regression for a paper
|
|
183
|
+
// simplification. Revisit if a post-fix dogfood window confirms it still
|
|
184
|
+
// never fires.
|
|
185
|
+
if (remainingMs < floor * perNeighbourMs) {
|
|
186
|
+
return { ...full, zone: "past-rescue" };
|
|
187
|
+
}
|
|
188
|
+
// The rescue band: a shorter walk lands on time.
|
|
189
|
+
return {
|
|
190
|
+
budget: Math.min(ceiling, Math.max(floor, Math.floor(remainingMs / perNeighbourMs))),
|
|
191
|
+
ceiling,
|
|
192
|
+
remainingMs,
|
|
193
|
+
deliveryWindowMs,
|
|
194
|
+
zone: "narrowed",
|
|
195
|
+
};
|
|
196
|
+
}
|
|
@@ -3,8 +3,18 @@ import { toRunnerDisplayPath } from "./dispatch/runner-context.js";
|
|
|
3
3
|
export function formatCascadeNeighborDiagnostics(cwd, neighbors, options = {}) {
|
|
4
4
|
const withErrors = neighbors.filter((n) => n.diagnostics.length > 0);
|
|
5
5
|
const inconclusive = neighbors.filter((n) => n.inconclusive === true && n.diagnostics.length === 0);
|
|
6
|
-
|
|
6
|
+
// #1459: a neighbour whose scanner never looked at it is not a clean leaf. It
|
|
7
|
+
// is also not `inconclusive` — the language server answered — so it gets its
|
|
8
|
+
// own honest line instead of being folded into either bucket. Only the
|
|
9
|
+
// zero-diagnostic case needs saying: a neighbour with findings already renders.
|
|
10
|
+
const uncovered = neighbors.filter((n) => n.diagnostics.length === 0 &&
|
|
11
|
+
n.inconclusive !== true &&
|
|
12
|
+
(n.unconfirmedServerIds?.length ?? 0) > 0);
|
|
13
|
+
if (withErrors.length === 0 &&
|
|
14
|
+
inconclusive.length === 0 &&
|
|
15
|
+
uncovered.length === 0) {
|
|
7
16
|
return "";
|
|
17
|
+
}
|
|
8
18
|
const noun = options.noun ?? "neighbor";
|
|
9
19
|
let out = withErrors.length > 0
|
|
10
20
|
? `📐 Cascade errors in ${withErrors.length} ${noun} file(s) — fix before finishing turn:`
|
|
@@ -29,6 +39,15 @@ export function formatCascadeNeighborDiagnostics(cwd, neighbors, options = {}) {
|
|
|
29
39
|
out += `\n ${toRunnerDisplayPath(cwd, neighbor.filePath)}`;
|
|
30
40
|
}
|
|
31
41
|
}
|
|
42
|
+
if (uncovered.length > 0) {
|
|
43
|
+
if (out)
|
|
44
|
+
out += "\n";
|
|
45
|
+
out += `⚠️ Cascade scanners did not cover ${uncovered.length} ${noun} file(s) — no findings does NOT mean clean here:`;
|
|
46
|
+
for (const neighbor of uncovered) {
|
|
47
|
+
const servers = (neighbor.unconfirmedServerIds ?? []).join(", ");
|
|
48
|
+
out += `\n ${toRunnerDisplayPath(cwd, neighbor.filePath)} (not scanned by ${servers})`;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
32
51
|
return out;
|
|
33
52
|
}
|
|
34
53
|
/**
|
|
@@ -1 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* How long a cascade neighbour's diagnostics stay usable (#1816).
|
|
3
|
+
*
|
|
4
|
+
* One constant for two consumers that each declared their own `240_000`:
|
|
5
|
+
* `clients/lsp/index.ts` (the neighbour-diagnostics cache) and
|
|
6
|
+
* `clients/dispatch/integration.ts` (the cascade turn scope). They must move
|
|
7
|
+
* together — a split pair reads as two independent policies and drifts.
|
|
8
|
+
*/
|
|
9
|
+
export const CASCADE_DIAGNOSTICS_TTL_MS = 240_000;
|
|
@@ -60,13 +60,24 @@ export function unrefChildAndPipes(child) {
|
|
|
60
60
|
* here already has).
|
|
61
61
|
*/
|
|
62
62
|
export function spawnCollectStdout(command, args, options) {
|
|
63
|
+
return spawnCollectStdoutResult(command, args, options).then((result) => result.stdout);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* `spawnCollectStdout` plus the reason the output is what it is. Same spawn,
|
|
67
|
+
* unref, collect, settle plumbing; the only additions are an optional hard
|
|
68
|
+
* timeout and a status discriminator. Never rejects.
|
|
69
|
+
*/
|
|
70
|
+
export function spawnCollectStdoutResult(command, args, options, collectOptions = {}) {
|
|
63
71
|
return new Promise((resolve) => {
|
|
64
72
|
let settled = false;
|
|
65
|
-
|
|
73
|
+
let timer;
|
|
74
|
+
const settle = (result) => {
|
|
66
75
|
if (settled)
|
|
67
76
|
return;
|
|
68
77
|
settled = true;
|
|
69
|
-
|
|
78
|
+
if (timer)
|
|
79
|
+
clearTimeout(timer);
|
|
80
|
+
resolve(result);
|
|
70
81
|
};
|
|
71
82
|
try {
|
|
72
83
|
const child = nodeSpawn(command, args, options);
|
|
@@ -75,11 +86,48 @@ export function spawnCollectStdout(command, args, options) {
|
|
|
75
86
|
child.stdout?.on("data", (chunk) => {
|
|
76
87
|
out += chunk.toString();
|
|
77
88
|
});
|
|
78
|
-
child.once("error", () => settle(""));
|
|
79
|
-
child.once("close", () => settle(
|
|
89
|
+
child.once("error", (error) => settle({ stdout: "", status: "spawn-error", error }));
|
|
90
|
+
child.once("close", (code, signal) => settle(code === 0 && signal === null
|
|
91
|
+
? { stdout: out, status: "ok" }
|
|
92
|
+
: {
|
|
93
|
+
stdout: "",
|
|
94
|
+
status: "exit-error",
|
|
95
|
+
exitCode: code,
|
|
96
|
+
exitSignal: signal,
|
|
97
|
+
}));
|
|
98
|
+
const timeoutMs = collectOptions.timeoutMs;
|
|
99
|
+
if (typeof timeoutMs === "number" && timeoutMs > 0) {
|
|
100
|
+
timer = setTimeout(() => {
|
|
101
|
+
// Settle only AFTER the child's fate is known. Killing and
|
|
102
|
+
// resolving in the same tick bounds the caller and abandons the
|
|
103
|
+
// child, which is the leak this timeout exists to prevent.
|
|
104
|
+
void terminateTimedOutChild(child, collectOptions.onTimeout).then((timeoutKill) => settle({ stdout: out, status: "timeout", timeoutKill }));
|
|
105
|
+
}, timeoutMs);
|
|
106
|
+
timer.unref();
|
|
107
|
+
}
|
|
80
108
|
}
|
|
81
|
-
catch {
|
|
82
|
-
settle("");
|
|
109
|
+
catch (error) {
|
|
110
|
+
settle({ stdout: "", status: "spawn-error", error });
|
|
83
111
|
}
|
|
84
112
|
});
|
|
85
113
|
}
|
|
114
|
+
/** Run the caller's termination handler, or the bare-signal default, and
|
|
115
|
+
* never let either throw out of the timeout path. */
|
|
116
|
+
async function terminateTimedOutChild(child, onTimeout) {
|
|
117
|
+
if (onTimeout) {
|
|
118
|
+
try {
|
|
119
|
+
return await onTimeout(child);
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
// A handler that threw did not verify anything.
|
|
123
|
+
return "unverified";
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
try {
|
|
127
|
+
child.kill();
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
// best-effort — the child may already be gone
|
|
131
|
+
}
|
|
132
|
+
return "unverified";
|
|
133
|
+
}
|
|
@@ -1,29 +1,47 @@
|
|
|
1
|
-
import { createHash } from "node:crypto";
|
|
2
1
|
import * as fs from "node:fs";
|
|
3
2
|
import * as path from "node:path";
|
|
4
3
|
import { toRunnerDisplayPath } from "./dispatch/runner-context.js";
|
|
5
4
|
import { getProjectDataDir } from "./file-utils.js";
|
|
5
|
+
import { normalizeMessage, stableFindingId } from "./finding-identity.js";
|
|
6
6
|
import { normalizeMapKey } from "./path-utils.js";
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Report-budget precedence (#1777). A hint is an opinion; a warning is a
|
|
9
|
+
* finding. When the report is capped, warnings must be spent first, or an
|
|
10
|
+
* alphabetically-early file's hints can push every real warning out of the
|
|
11
|
+
* agent's view — the exact "hints dominate the stream" failure the hint tier
|
|
12
|
+
* exists to prevent.
|
|
13
|
+
*/
|
|
14
|
+
const TIER_BUDGET_ORDER = [
|
|
15
|
+
"warning",
|
|
16
|
+
"info",
|
|
17
|
+
"hint",
|
|
18
|
+
];
|
|
19
|
+
/** #1816: was a local `relativeFile|tool|rule|code|normalizedMessage|line`
|
|
20
|
+
* hash (raw, non-canonicalized `relativeFile`, 10-char hash), independently
|
|
21
|
+
* hand-rolled from `actionable-warnings.ts`'s twin and
|
|
22
|
+
* `diagnostic-dispositions.ts`'s canonicalizing original. Now the shared
|
|
23
|
+
* `finding-identity.js` builder (canonicalizes `cwd`/`filePath` through
|
|
24
|
+
* `normalizeMapKey`, hashes to 12 chars). No back-compat migration needed
|
|
25
|
+
* here: `cq:` ids are never a keyed lookup — `buildCodeQualityWarningsReport`
|
|
26
|
+
* regenerates the whole report fresh every turn, callers only ever cache and
|
|
27
|
+
* replay the report wholesale (`tools/lens-diagnostics.ts` reads it via
|
|
28
|
+
* `cacheManager.readCache<CodeQualityWarningsReport>`, never by `id`), and
|
|
29
|
+
* `appendCodeQualityWarningsHistory` just append-only-logs the id for
|
|
30
|
+
* observability, never look it back up. Contrast `actionable-warnings.ts`,
|
|
31
|
+
* whose `actionable-warning-state.json` DOES key a persisted suppression
|
|
32
|
+
* store on `aw:` — that one migrates. */
|
|
17
33
|
function createCodeQualityWarningId(args) {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
args.
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
34
|
+
return stableFindingId("cq:", {
|
|
35
|
+
cwd: args.cwd,
|
|
36
|
+
filePath: args.filePath,
|
|
37
|
+
parts: [
|
|
38
|
+
args.tool,
|
|
39
|
+
args.rule,
|
|
40
|
+
args.code,
|
|
41
|
+
normalizeMessage(args.message),
|
|
42
|
+
args.line,
|
|
43
|
+
],
|
|
44
|
+
});
|
|
27
45
|
}
|
|
28
46
|
function categorize(diagnostic) {
|
|
29
47
|
const haystack = `${diagnostic.tool} ${diagnostic.rule ?? ""} ${diagnostic.code ?? ""} ${diagnostic.message}`.toLowerCase();
|
|
@@ -93,11 +111,22 @@ export function buildCodeQualityWarningsReport(args) {
|
|
|
93
111
|
continue;
|
|
94
112
|
byId.set(warning.id, warning);
|
|
95
113
|
}
|
|
96
|
-
const
|
|
97
|
-
.sort((a, b) => a.displayPath.localeCompare(b.displayPath) ||
|
|
114
|
+
const byDisplayOrder = (a, b) => a.displayPath.localeCompare(b.displayPath) ||
|
|
98
115
|
(a.line ?? 0) - (b.line ?? 0) ||
|
|
99
|
-
a.message.localeCompare(b.message)
|
|
100
|
-
|
|
116
|
+
a.message.localeCompare(b.message);
|
|
117
|
+
// Spend the budget tier by tier (see TIER_BUDGET_ORDER), then restore
|
|
118
|
+
// display order so the report still reads file by file, line by line.
|
|
119
|
+
const candidates = [...byId.values()].sort(byDisplayOrder);
|
|
120
|
+
const merged = [];
|
|
121
|
+
for (const tier of TIER_BUDGET_ORDER) {
|
|
122
|
+
for (const warning of candidates) {
|
|
123
|
+
if (merged.length >= maxWarnings)
|
|
124
|
+
break;
|
|
125
|
+
if (warning.severity === tier)
|
|
126
|
+
merged.push(warning);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
merged.sort(byDisplayOrder);
|
|
101
130
|
const byFile = new Map();
|
|
102
131
|
for (const warning of merged) {
|
|
103
132
|
const arr = byFile.get(warning.filePath) ?? [];
|
|
@@ -131,6 +160,11 @@ export function buildCodeQualityWarningsReport(args) {
|
|
|
131
160
|
summary: {
|
|
132
161
|
warnings: merged.length,
|
|
133
162
|
files: files.length,
|
|
163
|
+
byTier: {
|
|
164
|
+
warning: merged.filter((w) => w.severity === "warning").length,
|
|
165
|
+
info: merged.filter((w) => w.severity === "info").length,
|
|
166
|
+
hint: merged.filter((w) => w.severity === "hint").length,
|
|
167
|
+
},
|
|
134
168
|
topRules,
|
|
135
169
|
},
|
|
136
170
|
};
|
|
@@ -205,8 +239,26 @@ export function formatCodeQualityWarningsAdvisory(report) {
|
|
|
205
239
|
.slice(0, 3)
|
|
206
240
|
.map((entry) => `${entry.rule}×${entry.count}`)
|
|
207
241
|
.join(", ");
|
|
242
|
+
// #1777: name the tiers, in the same descending-loudness order the on-demand
|
|
243
|
+
// ast-grep surface uses (`formatDiagnostics`, clients/ast-grep-client.ts).
|
|
244
|
+
// A tier with no findings is omitted rather than printed as zero.
|
|
245
|
+
const byTier = report.summary.byTier ?? { warning: 0, info: 0, hint: 0 };
|
|
246
|
+
// The line is worth its space only when a quiet tier is present; an
|
|
247
|
+
// all-warning turn already says everything in the count above.
|
|
248
|
+
const tiers = byTier.hint || byTier.info
|
|
249
|
+
? [
|
|
250
|
+
byTier.warning ? `${byTier.warning} warning` : undefined,
|
|
251
|
+
byTier.info ? `${byTier.info} info` : undefined,
|
|
252
|
+
byTier.hint ? `${byTier.hint} hint` : undefined,
|
|
253
|
+
]
|
|
254
|
+
.filter(Boolean)
|
|
255
|
+
.join(", ")
|
|
256
|
+
: "";
|
|
208
257
|
return [
|
|
209
258
|
`Code-quality warnings introduced/touched this turn: ${report.summary.warnings} across ${report.summary.files} file(s).`,
|
|
259
|
+
tiers
|
|
260
|
+
? `By tier: ${tiers}. Hint and info are style opinions, not defects.`
|
|
261
|
+
: undefined,
|
|
210
262
|
topRules ? `Top rules: ${topRules}` : undefined,
|
|
211
263
|
"Details written to .pi-lens/cache/code-quality-warnings.json",
|
|
212
264
|
"No action required unless you are already refactoring these areas.",
|