@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
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import * as nodeFs from "node:fs";
|
|
15
15
|
import * as path from "node:path";
|
|
16
|
-
import { findNearestContaining } from "./path-utils.js";
|
|
16
|
+
import { findNearestContaining, normalizeEphemeralMapKey } from "./path-utils.js";
|
|
17
17
|
import { recordFromDispatchDiagnostic, } from "./actionable-warnings.js";
|
|
18
18
|
import { recordFromCodeQualityDiagnostic, } from "./code-quality-warnings.js";
|
|
19
19
|
import { recordDiagnostics } from "./widget-state.js";
|
|
@@ -21,7 +21,7 @@ import { getDiagnosticLogger } from "./diagnostic-logger.js";
|
|
|
21
21
|
import { getDiagnosticTracker } from "./diagnostic-tracker.js";
|
|
22
22
|
import { loadDispatchIntegration } from "./dispatch/lazy.js";
|
|
23
23
|
import { toRunnerDisplayPath } from "./dispatch/runner-context.js";
|
|
24
|
-
import { createAvailabilityChecker, resolveAvailableOrInstall, resolveCommandArgsWithInstallFallback, resolveToolCommand, resolveToolCommandWithInstallFallback, } from "./dispatch/runners/utils/runner-helpers.js";
|
|
24
|
+
import { classifyProbeFailure, createAvailabilityChecker, createAvailabilityLatch, describeProbeEvidence, logAvailabilityDecision, startHostStallSampler, resolveAvailableOrInstall, resolveCommandArgsWithInstallFallback, resolveToolCommand, resolveToolCommandWithInstallFallback, } from "./dispatch/runners/utils/runner-helpers.js";
|
|
25
25
|
import { findDetektConfig } from "./dispatch/runners/detekt.js";
|
|
26
26
|
import { detectFileKind, getFileKindLabel } from "./file-kinds.js";
|
|
27
27
|
import { detectFileChangedAfterCommand, getProjectIgnoreMatcher, isExcludedDirName, } from "./file-utils.js";
|
|
@@ -178,6 +178,13 @@ function createPhaseTracker(toolName, filePath) {
|
|
|
178
178
|
}
|
|
179
179
|
// --- ESLint autofix helpers ---
|
|
180
180
|
export { hasEslintConfig, hasRubocopConfig, hasSqlfluffConfig, hasStylelintConfig, };
|
|
181
|
+
/**
|
|
182
|
+
* eslint autofix availability, per cwd + PATH. The verdict is owned by the
|
|
183
|
+
* shared availability latch (#1494): a `missing` / `non-installable` outcome
|
|
184
|
+
* sticks for the session, a timeout expires on a cooldown and is re-probed, so
|
|
185
|
+
* one stalled probe cannot silently stop autofixing a project's JS/TS.
|
|
186
|
+
*/
|
|
187
|
+
const ESLINT_FIX_PROBE_BUDGET_MS = 5000;
|
|
181
188
|
const _eslintCache = new BoundedLruCache(32);
|
|
182
189
|
/**
|
|
183
190
|
* Run eslint --fix on a file. Runs a single spawn and diffs the file before/after,
|
|
@@ -196,18 +203,70 @@ async function tryEslintFix(filePath, cwd) {
|
|
|
196
203
|
const cacheKey = `${path.resolve(cwd)}|${process.env.PATH ?? ""}`;
|
|
197
204
|
let cached = _eslintCache.get(cacheKey);
|
|
198
205
|
if (!cached) {
|
|
199
|
-
|
|
200
|
-
const check = await safeSpawnAsync(candidate, ["--version"], {
|
|
201
|
-
timeout: 5000,
|
|
202
|
-
cwd,
|
|
203
|
-
});
|
|
204
|
-
cached = {
|
|
205
|
-
available: !check.error && check.status === 0,
|
|
206
|
-
bin: !check.error && check.status === 0 ? candidate : null,
|
|
207
|
-
};
|
|
206
|
+
cached = { latch: createAvailabilityLatch(), bin: null };
|
|
208
207
|
_eslintCache.set(cacheKey, cached);
|
|
209
208
|
}
|
|
210
|
-
if (
|
|
209
|
+
if (cached.latch.read() === null) {
|
|
210
|
+
const candidate = resolveToolCommand(cwd, "eslint") ?? "eslint";
|
|
211
|
+
// The budget is enforced by a HOST-side timer, so a stalled event loop
|
|
212
|
+
// expires it while eslint is still healthy. Measure the overlapping stall
|
|
213
|
+
// and hand it to the classifier, exactly like the runner path: without it a
|
|
214
|
+
// host-stall timeout is re-caused as `probe-timeout` and gets the escalating
|
|
215
|
+
// 30s→300s cooldown instead of the 5s host-stall one (#1467).
|
|
216
|
+
const stallSampler = startHostStallSampler();
|
|
217
|
+
const startedAt = Date.now();
|
|
218
|
+
let check;
|
|
219
|
+
let hostStallMs;
|
|
220
|
+
try {
|
|
221
|
+
check = await safeSpawnAsync(candidate, ["--version"], {
|
|
222
|
+
timeout: ESLINT_FIX_PROBE_BUDGET_MS,
|
|
223
|
+
cwd,
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
finally {
|
|
227
|
+
hostStallMs = stallSampler.stop();
|
|
228
|
+
}
|
|
229
|
+
const elapsedMs = Date.now() - startedAt;
|
|
230
|
+
const decisionCwd = path.resolve(cwd);
|
|
231
|
+
if (!check.error && check.status === 0) {
|
|
232
|
+
cached.bin = candidate;
|
|
233
|
+
cached.latch.noteAvailable();
|
|
234
|
+
logAvailabilityDecision({
|
|
235
|
+
tool: "eslint",
|
|
236
|
+
verdict: "available",
|
|
237
|
+
outcome: "success",
|
|
238
|
+
cause: "ok",
|
|
239
|
+
elapsedMs,
|
|
240
|
+
latched: true,
|
|
241
|
+
hostStallMs,
|
|
242
|
+
budgetMs: ESLINT_FIX_PROBE_BUDGET_MS,
|
|
243
|
+
classifiedBy: "probe",
|
|
244
|
+
evidence: describeProbeEvidence(check, "eslint"),
|
|
245
|
+
}, decisionCwd);
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
cached.bin = null;
|
|
249
|
+
const { outcome, cause, evidence } = classifyProbeFailure(check, {
|
|
250
|
+
hostStallMs,
|
|
251
|
+
command: "eslint",
|
|
252
|
+
});
|
|
253
|
+
const retryAfterMs = cached.latch.noteUnavailable(outcome, cause);
|
|
254
|
+
logAvailabilityDecision({
|
|
255
|
+
tool: "eslint",
|
|
256
|
+
verdict: "unavailable",
|
|
257
|
+
outcome,
|
|
258
|
+
cause,
|
|
259
|
+
elapsedMs,
|
|
260
|
+
latched: retryAfterMs === 0,
|
|
261
|
+
hostStallMs,
|
|
262
|
+
...(retryAfterMs > 0 && { retryAfterMs }),
|
|
263
|
+
budgetMs: ESLINT_FIX_PROBE_BUDGET_MS,
|
|
264
|
+
classifiedBy: "probe",
|
|
265
|
+
evidence,
|
|
266
|
+
}, decisionCwd);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
if (cached.latch.read() !== true || !cached.bin)
|
|
211
270
|
return 0;
|
|
212
271
|
const cmd = cached.bin;
|
|
213
272
|
return detectFileChangedAfterCommand(filePath, cmd, ["--fix", "--no-error-on-unmatched-pattern", filePath], cwd, [1]);
|
|
@@ -650,6 +709,24 @@ export async function resyncLspFile(filePath, fileContent, needsContentRefresh,
|
|
|
650
709
|
if (outcome === "bailed") {
|
|
651
710
|
// Abandon the still-pending write; the edit continues. Log it so this
|
|
652
711
|
// stall — previously an invisible hang — is queryable in latency.log.
|
|
712
|
+
//
|
|
713
|
+
// #1766: a resync deadline can expire while the target server's FIRST
|
|
714
|
+
// spawn is still in flight (cold spawn > budget). That is not the same
|
|
715
|
+
// state as a running server that stalled on a write — the server the
|
|
716
|
+
// old wording blamed as "slow/wedged" did not exist yet. Distinguish
|
|
717
|
+
// the two via a fresh, synchronous inFlight lookup so the record keeps
|
|
718
|
+
// the discriminating identity (which server, which lifecycle state).
|
|
719
|
+
// Guarded: a test double or future service shape lacking the method
|
|
720
|
+
// must degrade to the old "timeout"/slow-wedged wording, not throw
|
|
721
|
+
// into the catch below and suppress this record entirely (#1766 F3).
|
|
722
|
+
const spawnInFlight = !abort?.aborted &&
|
|
723
|
+
typeof lspService.isSpawnInFlight === "function" &&
|
|
724
|
+
lspService.isSpawnInFlight(filePath);
|
|
725
|
+
const reason = abort?.aborted
|
|
726
|
+
? "aborted"
|
|
727
|
+
: spawnInFlight
|
|
728
|
+
? "spawn-in-flight"
|
|
729
|
+
: "timeout";
|
|
653
730
|
logLatency({
|
|
654
731
|
type: "phase",
|
|
655
732
|
phase: "lsp_sync_abandoned",
|
|
@@ -657,11 +734,16 @@ export async function resyncLspFile(filePath, fileContent, needsContentRefresh,
|
|
|
657
734
|
durationMs: Date.now() - startedAt,
|
|
658
735
|
metadata: {
|
|
659
736
|
source: "lsp_sync",
|
|
660
|
-
reason
|
|
737
|
+
reason,
|
|
661
738
|
budgetMs,
|
|
662
739
|
},
|
|
663
740
|
});
|
|
664
|
-
|
|
741
|
+
const cause = abort?.aborted
|
|
742
|
+
? "aborted (Escape)"
|
|
743
|
+
: spawnInFlight
|
|
744
|
+
? `timed out after ${budgetMs}ms; reason: spawn-in-flight (server still cold-spawning)`
|
|
745
|
+
: `timed out after ${budgetMs}ms; server slow/wedged`;
|
|
746
|
+
dbg(`LSP resync ${cause} for ${filePath}`);
|
|
665
747
|
}
|
|
666
748
|
}
|
|
667
749
|
}
|
|
@@ -1007,24 +1089,16 @@ export async function runPipeline(ctx, deps) {
|
|
|
1007
1089
|
: "";
|
|
1008
1090
|
output += `\n\n⚠️ Auto-format failed: ${details}${suffix}`;
|
|
1009
1091
|
}
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
? "\nModified files:\n" + topFiles + overflow
|
|
1021
|
-
: "";
|
|
1022
|
-
const targetHasAuthoritativeAttachment = ctx.autofixMode !== "deferred" &&
|
|
1023
|
-
autofixChangedFiles.some((changedFile) => path.resolve(changedFile) === path.resolve(filePath));
|
|
1024
|
-
output += targetHasAuthoritativeAttachment
|
|
1025
|
-
? `\n\n⚠️ **The attached full content for ${toRunnerDisplayPath(cwd, filePath)} is authoritative after autofix. You MUST re-read any other modified side-effect files before editing them.**${fileList}`
|
|
1026
|
-
: `\n\n⚠️ **File was modified by auto-format/fix. You MUST re-read modified file(s) before making any further edits — the content on disk has changed (whitespace, indentation, quotes, or code). Editing from memory will produce mismatches.**${fileList}`;
|
|
1027
|
-
}
|
|
1092
|
+
// #1590: the notice sentence itself is NOT rendered here. This layer cannot
|
|
1093
|
+
// see the attachment cap or the aggregate budget, so it hands the display
|
|
1094
|
+
// paths to `handleToolResult`, which owns the decision and renders the one
|
|
1095
|
+
// sentence with `renderPostAutofixNotice`.
|
|
1096
|
+
const postAutofixNotice = formatChanged || fixedCount > 0
|
|
1097
|
+
? {
|
|
1098
|
+
targetPath: toRunnerDisplayPath(cwd, filePath),
|
|
1099
|
+
changedFiles: [...piChangedFiles].map((changedFile) => toRunnerDisplayPath(cwd, changedFile)),
|
|
1100
|
+
}
|
|
1101
|
+
: undefined;
|
|
1028
1102
|
phase.end("dispatch_lint", {
|
|
1029
1103
|
hasOutput: !!dispatchResult.output,
|
|
1030
1104
|
diagnosticCount: dispatchResult.diagnostics.length,
|
|
@@ -1048,6 +1122,7 @@ export async function runPipeline(ctx, deps) {
|
|
|
1048
1122
|
turnSeq: ctx.telemetry?.turnIndex,
|
|
1049
1123
|
writeSeq: ctx.telemetry?.writeIndex,
|
|
1050
1124
|
seqState: ctx.seqState,
|
|
1125
|
+
turnEndCascadeSettleStart: ctx.turnEndCascadeSettleStart,
|
|
1051
1126
|
fileContent,
|
|
1052
1127
|
wordIndex: ctx.wordIndex,
|
|
1053
1128
|
onWordIndexUpdated: ctx.onWordIndexUpdated,
|
|
@@ -1072,7 +1147,10 @@ export async function runPipeline(ctx, deps) {
|
|
|
1072
1147
|
});
|
|
1073
1148
|
// --- Final timing + all-clear ---
|
|
1074
1149
|
const elapsed = Date.now() - pipelineStart;
|
|
1075
|
-
|
|
1150
|
+
// #1590: `postAutofixNotice` is output this run produces, just rendered a
|
|
1151
|
+
// layer up. Treat it as output here, or a format-only change would newly
|
|
1152
|
+
// gain an "all clear" line it never had while the sentence lived inline.
|
|
1153
|
+
if (!output && !postAutofixNotice) {
|
|
1076
1154
|
output = buildAllClearOutput(dispatchResult, elapsed, filePath);
|
|
1077
1155
|
}
|
|
1078
1156
|
phase.end("total", { hasOutput: !!output });
|
|
@@ -1106,12 +1184,55 @@ export async function runPipeline(ctx, deps) {
|
|
|
1106
1184
|
inlineBlockerSummary: dispatchResult.hasBlockers
|
|
1107
1185
|
? dispatchResult.blockerOutput.trim() || undefined
|
|
1108
1186
|
: undefined,
|
|
1187
|
+
// #1561 F1: taken from the very diagnostics `blockerOutput` was rendered
|
|
1188
|
+
// from, so the provenance can never disagree with the text it guards. An
|
|
1189
|
+
// untagged diagnostic contributes the literal "unknown", which no verdict
|
|
1190
|
+
// claims coverage for — it pins the entry rather than silently widening
|
|
1191
|
+
// what an LSP check is allowed to clear.
|
|
1192
|
+
inlineBlockerSources: dispatchResult.hasBlockers
|
|
1193
|
+
? [
|
|
1194
|
+
...new Set(dispatchResult.blockers.map((d) => d.tool?.trim() || "unknown")),
|
|
1195
|
+
]
|
|
1196
|
+
: undefined,
|
|
1197
|
+
inlineBlockerLines: dispatchResult.hasBlockers
|
|
1198
|
+
? dispatchResult.blockers
|
|
1199
|
+
// #1641 review F2: `dispatchResult.blockers` is NOT guaranteed to be
|
|
1200
|
+
// scoped to THIS file — a chart-wide runner (helm-lint, helm-render)
|
|
1201
|
+
// reports blocking diagnostics against other files in the chart
|
|
1202
|
+
// (e.g. `values.yaml`) alongside `ctx.filePath`. The precedent every
|
|
1203
|
+
// per-file runner already follows (dotnet-build.ts, javac.ts) is to
|
|
1204
|
+
// drop cross-file rows before they reach a per-file record; this is
|
|
1205
|
+
// that same filter applied at the aggregation point instead, since
|
|
1206
|
+
// `blockers` is pooled across every runner dispatched for this file.
|
|
1207
|
+
// Without it, a cross-file line count gets attributed to THIS
|
|
1208
|
+
// file's past-EOF check and can demote an in-bounds, fully valid
|
|
1209
|
+
// blocker for content the diagnostic never described.
|
|
1210
|
+
//
|
|
1211
|
+
// #1641 review round 2 (LOW): `path.resolve` equality doesn't fold
|
|
1212
|
+
// case, and an LSP-sourced diagnostic's `filePath` is stamped with
|
|
1213
|
+
// realpath canonical casing (dispatch/runners/lsp.ts ->
|
|
1214
|
+
// normalizeMapKey) while `ctx.filePath` can arrive lowercase-drive
|
|
1215
|
+
// on Windows — the drive-letter class from #1139/#1150. A bare
|
|
1216
|
+
// `path.resolve` equality then drops EVERY LSP blocker line and
|
|
1217
|
+
// this record silently skips the past-EOF gate (fail-open, but
|
|
1218
|
+
// exactly the pre-fix behavior on the surface #1641 targets).
|
|
1219
|
+
// `normalizeEphemeralMapKey` slash-folds and (on win32)
|
|
1220
|
+
// lowercase-folds both sides with no filesystem I/O — cheap enough
|
|
1221
|
+
// for this per-blocker hot-path filter. `pathsEqual` was
|
|
1222
|
+
// deliberately NOT used here: it calls `realpathSync` per
|
|
1223
|
+
// comparison, which this filter cannot afford per blocker.
|
|
1224
|
+
.filter((d) => normalizeEphemeralMapKey(d.filePath) ===
|
|
1225
|
+
normalizeEphemeralMapKey(filePath))
|
|
1226
|
+
.map((d) => d.line)
|
|
1227
|
+
.filter((line) => typeof line === "number")
|
|
1228
|
+
: undefined,
|
|
1109
1229
|
actionableWarnings,
|
|
1110
1230
|
codeQualityWarnings,
|
|
1111
1231
|
diagnostics: dispatchResult.diagnostics,
|
|
1112
1232
|
formattersUsed,
|
|
1113
1233
|
fixedCount,
|
|
1114
1234
|
autofixTools,
|
|
1235
|
+
postAutofixNotice,
|
|
1115
1236
|
postMutation: ctx.autofixMode !== "deferred" && autofixChangedFiles.some((f) => path.resolve(f) === path.resolve(filePath)) && fileContent !== undefined
|
|
1116
1237
|
? { filePath: path.resolve(filePath), content: fileContent, source: "autofix" }
|
|
1117
1238
|
: undefined,
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The single post-autofix instruction about a written file (#1590).
|
|
3
|
+
*
|
|
4
|
+
* Two layers used to phrase this. `clients/pipeline.ts` claimed "the attached
|
|
5
|
+
* full content is authoritative" from changed-file membership alone, and
|
|
6
|
+
* `clients/runtime-tool-result.ts` — the only layer that sees the per-file
|
|
7
|
+
* attachment cap and the per-command aggregate budget — appended "too large to
|
|
8
|
+
* attach" for the same file. On a size-capped write the agent got both.
|
|
9
|
+
*
|
|
10
|
+
* The wording now lives here, and `handleToolResult` is the only caller: the
|
|
11
|
+
* pipeline supplies the data (display paths it already resolved) and the layer
|
|
12
|
+
* that made the attachment decision picks the sentence. Keeping the renderer
|
|
13
|
+
* out of `pipeline.ts` also keeps it real in tests that mock the pipeline away.
|
|
14
|
+
*/
|
|
15
|
+
/** Render the ONE post-autofix instruction for `decision`. */
|
|
16
|
+
export function renderPostAutofixNotice(notice, decision) {
|
|
17
|
+
const topFiles = notice.changedFiles
|
|
18
|
+
.slice(0, 8)
|
|
19
|
+
.map((f) => " - " + f)
|
|
20
|
+
.join("\n");
|
|
21
|
+
const overflow = notice.changedFiles.length > 8
|
|
22
|
+
? "\n - ... and " + (notice.changedFiles.length - 8) + " more"
|
|
23
|
+
: "";
|
|
24
|
+
const fileList = notice.changedFiles.length
|
|
25
|
+
? "\nModified files:\n" + topFiles + overflow
|
|
26
|
+
: "";
|
|
27
|
+
switch (decision) {
|
|
28
|
+
case "attached":
|
|
29
|
+
return `⚠️ **The attached full content for ${notice.targetPath} is authoritative after autofix. You MUST re-read any other modified side-effect files before editing them.**${fileList}`;
|
|
30
|
+
case "size-capped":
|
|
31
|
+
return `⚠️ **File was modified by auto-format/fix. You MUST re-read ${notice.targetPath} before making any further edits — the authoritative content is too large to attach.**${fileList}`;
|
|
32
|
+
case "aggregate-budget-degraded":
|
|
33
|
+
return `⚠️ **File was modified by auto-format/fix. You MUST re-read ${notice.targetPath} before making any further edits — the aggregate authoritative content for this command is too large to attach.**${fileList}`;
|
|
34
|
+
default:
|
|
35
|
+
return `⚠️ **File was modified by auto-format/fix. You MUST re-read modified file(s) before making any further edits — the content on disk has changed (whitespace, indentation, quotes, or code). Editing from memory will produce mismatches.**${fileList}`;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -3,6 +3,7 @@ import * as path from "node:path";
|
|
|
3
3
|
import { getProjectDataDir } from "../file-utils.js";
|
|
4
4
|
import { writeFileAtomic } from "../atomic-write.js";
|
|
5
5
|
import { readJsonCache } from "../json-cache-read.js";
|
|
6
|
+
import { MTIME_DRIFT_TOLERANCE_MS } from "../blocker-freshness.js";
|
|
6
7
|
// v2: cheap-tier scan now also runs ast-grep-napi (#308); invalidate older
|
|
7
8
|
// snapshots so a pre-ast-grep cache isn't served as complete via refreshRunners=cached.
|
|
8
9
|
export const PROJECT_DIAGNOSTICS_CACHE_VERSION = 2;
|
|
@@ -47,7 +48,8 @@ export function writeProjectDiagnosticsDeltaReport(cwd, report) {
|
|
|
47
48
|
}
|
|
48
49
|
/**
|
|
49
50
|
* Drop diagnostics whose underlying file changed on disk after the snapshot was
|
|
50
|
-
* taken (`mtimeMs > scannedAt`) or no longer
|
|
51
|
+
* taken (`mtimeMs > scannedAt + MTIME_DRIFT_TOLERANCE_MS`) or no longer
|
|
52
|
+
* exists. The persisted snapshot is a
|
|
51
53
|
* cross-session cache served by `lens_diagnostics mode=full refreshRunners=cached`;
|
|
52
54
|
* without this it replays diagnostics the agent has since fixed or for files that
|
|
53
55
|
* were deleted (#298 — "the cache needs to be cleaned before running diagnostics
|
|
@@ -56,6 +58,15 @@ export function writeProjectDiagnosticsDeltaReport(cwd, report) {
|
|
|
56
58
|
* stays a pure reader. Synchronous (a `statSync` per *distinct* file, memoised),
|
|
57
59
|
* since the cached full-mode path is already off the typing hot loop.
|
|
58
60
|
*
|
|
61
|
+
* The boundary is `mtime > scannedAt + MTIME_DRIFT_TOLERANCE_MS`
|
|
62
|
+
* (`blocker-freshness.ts`), not a bare `mtime > scannedAt`: #1711 found this
|
|
63
|
+
* consumer's old +1ms slack did not cover the measured Windows host skew
|
|
64
|
+
* between a file's mtime and the `Date.now()` read that produces `scannedAt`
|
|
65
|
+
* (up to ~11.4ms, #1491/#1498) — a same-tick write-then-scan silently
|
|
66
|
+
* dropped a live finding here, worse than `findingPathFreshness`'s sibling
|
|
67
|
+
* gate (#1708) since this arm DROPS rather than demotes. Reusing the shared
|
|
68
|
+
* constant keeps one source of truth for the measured skew.
|
|
69
|
+
*
|
|
59
70
|
* Fail-safe on an unparseable `scannedAt`: return the snapshot untouched rather
|
|
60
71
|
* than risk dropping live findings on a clock/format anomaly.
|
|
61
72
|
*/
|
|
@@ -70,8 +81,11 @@ export function reconcileProjectDiagnosticsSnapshot(snapshot) {
|
|
|
70
81
|
return cached;
|
|
71
82
|
let stale;
|
|
72
83
|
try {
|
|
73
|
-
//
|
|
74
|
-
|
|
84
|
+
// MTIME_DRIFT_TOLERANCE_MS: a file scanned at scannedAt, or written
|
|
85
|
+
// within the tolerance window of the scan timestamp being captured,
|
|
86
|
+
// has mtime <= scannedAt + MTIME_DRIFT_TOLERANCE_MS.
|
|
87
|
+
stale =
|
|
88
|
+
fs.statSync(filePath).mtimeMs > scannedAtMs + MTIME_DRIFT_TOLERANCE_MS;
|
|
75
89
|
}
|
|
76
90
|
catch {
|
|
77
91
|
stale = true; // deleted / unreadable → drop
|
|
@@ -1,25 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Provenance metadata for the heavyweight project analyzers surfaced in
|
|
3
|
-
* `lens_diagnostics mode=full`.
|
|
4
|
-
*
|
|
5
|
-
* NOTE (#585 regression cleanup): this module USED to also own
|
|
6
|
-
* `extractCachedProjectDiagnostics` — a CACHE-ONLY reader that adapted each
|
|
7
|
-
* analyzer's cached result to `ProjectDiagnostic[]` via a parallel `EXTRACTORS`
|
|
8
|
-
* registry. #585 replaced that reader in production with
|
|
9
|
-
* `fetchFreshProjectDiagnostics` (./fresh-fetch.ts), which triggers-or-joins a
|
|
10
|
-
* fresh run instead of settling for a possibly-hours-stale session_start
|
|
11
|
-
* snapshot. The old reader lingered here wired only to a test — a SECOND,
|
|
12
|
-
* dead surfacing path whose registry could (and did) silently diverge from
|
|
13
|
-
* fresh-fetch's `ANALYZER_IDS`: opengrep was registered here but missing there,
|
|
14
|
-
* so opengrep scanned+cached yet never reached the agent (the exact #585-class
|
|
15
|
-
* regression this cleanup removes). The parallel registry is gone; fresh-fetch
|
|
16
|
-
* is the single source of truth (#883).
|
|
17
|
-
*
|
|
18
|
-
* What survives is the honesty metadata (#533): given an analyzer id that
|
|
19
|
-
* fresh-fetch reported `cold` (not applicable / unavailable this run),
|
|
20
|
-
* `warmTriggerFor` names what WOULD warm it, so the rendered note is actionable
|
|
21
|
-
* rather than a bare "not run".
|
|
22
|
-
*/
|
|
23
1
|
/**
|
|
24
2
|
* #533: which trigger warms each analyzer, surfaced in the "cold" honesty note
|
|
25
3
|
* so the note is actionable (names what to do), matching the #511/#514 house
|
|
@@ -40,3 +18,92 @@ const WARM_TRIGGER = {
|
|
|
40
18
|
export function warmTriggerFor(analyzerId) {
|
|
41
19
|
return WARM_TRIGGER[analyzerId] ?? "runs at session-start";
|
|
42
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* #1623: single formatter for a "not run" lane entry — reused by every
|
|
23
|
+
* caller that renders `fetchFreshProjectDiagnostics`'s `cold` list (today,
|
|
24
|
+
* `tools/lens-diagnostics.ts`'s mode=full) so the wording can't drift
|
|
25
|
+
* per-caller. Prefers the SPECIFIC reason captured at the decision point
|
|
26
|
+
* (`coldReasons`, ./fresh-fetch.ts) over the generic `warmTriggerFor` guess —
|
|
27
|
+
* the latter only remains a fallback for a `cold` id this map doesn't cover.
|
|
28
|
+
*/
|
|
29
|
+
export function formatNotRunEntry(analyzerId, coldReasons) {
|
|
30
|
+
const reason = coldReasons?.[analyzerId];
|
|
31
|
+
return reason
|
|
32
|
+
? `${analyzerId} — not run (${reason})`
|
|
33
|
+
: `${analyzerId} — not run (${warmTriggerFor(analyzerId)})`;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* #1623: human-readable age, for a lane whose result was served from cache
|
|
37
|
+
* rather than executed fresh this call (see `cachedAgeMs`, ./fresh-fetch.ts).
|
|
38
|
+
* Mirrors the granularity an agent actually needs to judge staleness — exact
|
|
39
|
+
* seconds don't matter, "12m" vs "3h" does.
|
|
40
|
+
*/
|
|
41
|
+
export function formatCacheAge(ms) {
|
|
42
|
+
// #1623 fix-round F4: `CacheManager.readCache` accepts a missing/corrupt
|
|
43
|
+
// `meta.timestamp` as a HIT (the timestamp only gates staleness, not
|
|
44
|
+
// validity), so `Date.now() - new Date(badTimestamp).getTime()` reaches
|
|
45
|
+
// here as NaN. Rendering "NaNh old" is a worse honesty gap than the one
|
|
46
|
+
// this whole module exists to close — say the age is unknown instead of
|
|
47
|
+
// fabricating one. Mirrors the sibling `Number.isFinite` guard in
|
|
48
|
+
// `./cache.ts`'s `reconcileProjectDiagnosticsSnapshot` (fail-safe on an
|
|
49
|
+
// unparseable timestamp rather than propagate NaN).
|
|
50
|
+
if (!Number.isFinite(ms))
|
|
51
|
+
return "age unknown";
|
|
52
|
+
if (ms < 0)
|
|
53
|
+
return "0m";
|
|
54
|
+
const totalMinutes = Math.round(ms / 60_000);
|
|
55
|
+
if (totalMinutes < 1)
|
|
56
|
+
return "under 1m";
|
|
57
|
+
if (totalMinutes < 60)
|
|
58
|
+
return `${totalMinutes}m`;
|
|
59
|
+
const hours = Math.floor(totalMinutes / 60);
|
|
60
|
+
const minutes = totalMinutes % 60;
|
|
61
|
+
return minutes > 0 ? `${hours}h${minutes}m` : `${hours}h`;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* #1623 fix-round F5: the full "<age> old" phrase for a cache-read lane.
|
|
65
|
+
* Every render call site used to append the literal word " old" after
|
|
66
|
+
* `formatCacheAge` itself, so a corrupt/missing timestamp's "age unknown"
|
|
67
|
+
* came out as the ungrammatical "age unknown old" — the exact residual the
|
|
68
|
+
* issue's tracking comment named. "Old" only makes sense once an age is
|
|
69
|
+
* actually known, so this is the single place that decides whether to say
|
|
70
|
+
* it, instead of every caller repeating (and occasionally forgetting) the
|
|
71
|
+
* same guard.
|
|
72
|
+
*/
|
|
73
|
+
export function formatCacheAgeOld(ms) {
|
|
74
|
+
const age = formatCacheAge(ms);
|
|
75
|
+
return Number.isFinite(ms) ? `${age} old` : age;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* #1623 fix-round F1: a "cold" reason for an analyzer whose `ensureAvailable()`
|
|
79
|
+
* returned false, built from the SAME `AvailabilityOutcome`/`AvailabilityCause`
|
|
80
|
+
* taxonomy every dispatch-side unavailability message already uses
|
|
81
|
+
* (`describeUnavailability`, availability-policy.ts) — not a re-guessed
|
|
82
|
+
* "binary unavailable" for every failure shape.
|
|
83
|
+
*
|
|
84
|
+
* `ensureAvailable() === false` collapses at least three distinct causes: a
|
|
85
|
+
* durable absence (`missing`), a transient probe under an active retry
|
|
86
|
+
* cooldown (`transient`), and — for govulncheck specifically — a project-trust
|
|
87
|
+
* install denial the latch never even records (`assertInstallAllowed` returns
|
|
88
|
+
* before touching it, project-trust.ts). fresh-fetch.ts's govulncheck task
|
|
89
|
+
* checks trust denial itself, via `projectTrustDenialReason()`, before
|
|
90
|
+
* falling back to this function. Wording a cooldown as "unavailable" would
|
|
91
|
+
* repeat, one layer up, exactly the dispatch-layer defect #1467 fixed.
|
|
92
|
+
*/
|
|
93
|
+
export function reasonFromAvailabilityVerdict(tool, verdict) {
|
|
94
|
+
if (!verdict || verdict.outcome === null)
|
|
95
|
+
return `${tool} binary unavailable`;
|
|
96
|
+
const { outcome, cause } = verdict;
|
|
97
|
+
if (outcome === "transient") {
|
|
98
|
+
if (cause === "install-retry-exhausted") {
|
|
99
|
+
return `${tool} install kept timing out and hit its retry ceiling this session (not reported missing)`;
|
|
100
|
+
}
|
|
101
|
+
const remainingMs = verdict.retryAtMs - Date.now();
|
|
102
|
+
const remainingS = remainingMs > 0 ? Math.round(remainingMs / 1000) : 0;
|
|
103
|
+
return `${tool} availability probe — retry cooldown (${remainingS}s), not a missing install`;
|
|
104
|
+
}
|
|
105
|
+
if (outcome === "non-installable") {
|
|
106
|
+
return `${tool} unavailable on this host (non-installable)`;
|
|
107
|
+
}
|
|
108
|
+
return `${tool} binary unavailable`;
|
|
109
|
+
}
|