@herbertgao/pi-extensions 2026.8.4 â 2026.8.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +11 -3
- package/node_modules/@herbertgao/pi-cc-extensions/README.md +11 -3
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +24 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +91 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/compact-thinking.ts +7 -3
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +74 -5
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/index.ts +7 -6
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +21 -12
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/default-mode.ts +4 -5
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/markdown-enhance.ts +53 -14
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +22 -12
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/result.ts +2 -4
- package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
- package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +18 -0
- package/node_modules/@herbertgao/pi-subagents/package.json +8 -4
- package/node_modules/@herbertgao/pi-subagents/src/agent-color.ts +72 -67
- package/node_modules/@herbertgao/pi-subagents/src/agent-file-toggle.ts +255 -0
- package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +191 -3
- package/node_modules/@herbertgao/pi-subagents/src/agent-runner.ts +20 -4
- package/node_modules/@herbertgao/pi-subagents/src/index.ts +289 -113
- package/node_modules/@herbertgao/pi-subagents/src/output-file.ts +24 -1
- package/node_modules/@herbertgao/pi-subagents/src/ui/agent-widget.ts +24 -2
- package/node_modules/@herbertgao/pi-subagents/src/ui/fleet-list.ts +15 -6
- package/node_modules/@herbertgao/pi-subagents/src/ui/schedule-menu.ts +9 -8
- package/node_modules/@herbertgao/pi-subagents/src/ui/select-item.ts +48 -0
- package/node_modules/@herbertgao/pi-subagents/src/worktree.ts +9 -5
- package/node_modules/@juicesharp/rpiv-ask-user-question/README.md +2 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/ask-user-question.ts +20 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/hosts.md +6 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/keyboard.md +7 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +2 -2
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/build-questionnaire.ts +7 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/key-router.ts +16 -5
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/questionnaire-session.ts +4 -2
- package/node_modules/@narumitw/pi-btw/README.md +32 -24
- package/node_modules/@narumitw/pi-btw/package.json +6 -6
- package/node_modules/@narumitw/pi-btw/src/btw.ts +4 -2
- package/node_modules/@narumitw/pi-btw/src/menu.ts +34 -13
- package/node_modules/@narumitw/pi-btw/src/settings.ts +22 -2
- package/node_modules/pi-lens/CHANGELOG.md +2535 -954
- package/node_modules/pi-lens/README.md +13 -0
- package/node_modules/pi-lens/dist/clients/actionable-warnings.js +73 -18
- package/node_modules/pi-lens/dist/clients/advisory-provenance.js +314 -0
- package/node_modules/pi-lens/dist/clients/agent-behavior-client.js +21 -4
- package/node_modules/pi-lens/dist/clients/agent-nudge.js +14 -7
- package/node_modules/pi-lens/dist/clients/ast-grep-client.js +68 -16
- package/node_modules/pi-lens/dist/clients/ast-grep-types.js +0 -1
- package/node_modules/pi-lens/dist/clients/ast-grep-yaml-synth.js +37 -10
- package/node_modules/pi-lens/dist/clients/atomic-write-staging.js +63 -0
- package/node_modules/pi-lens/dist/clients/atomic-write.js +114 -14
- package/node_modules/pi-lens/dist/clients/bash-file-access.js +193 -23
- package/node_modules/pi-lens/dist/clients/biome-client.js +136 -24
- package/node_modules/pi-lens/dist/clients/bootstrap.js +11 -2
- package/node_modules/pi-lens/dist/clients/bounded-cache.js +34 -0
- package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +192 -0
- package/node_modules/pi-lens/dist/clients/bus-events-logger.js +62 -6
- package/node_modules/pi-lens/dist/clients/bus-publish.js +19 -4
- package/node_modules/pi-lens/dist/clients/cache/rule-cache.js +47 -5
- package/node_modules/pi-lens/dist/clients/cache-manager.js +97 -9
- package/node_modules/pi-lens/dist/clients/cache-observability.js +301 -14
- package/node_modules/pi-lens/dist/clients/call-graph.js +449 -117
- package/node_modules/pi-lens/dist/clients/cascade-format.js +57 -2
- package/node_modules/pi-lens/dist/clients/child-unref.js +85 -0
- package/node_modules/pi-lens/dist/clients/codebase-model.js +52 -23
- package/node_modules/pi-lens/dist/clients/collateral-test-role.js +40 -0
- package/node_modules/pi-lens/dist/clients/complexity-client.js +2 -1
- package/node_modules/pi-lens/dist/clients/console-guard-install.js +26 -0
- package/node_modules/pi-lens/dist/clients/cooperative-budget.js +42 -0
- package/node_modules/pi-lens/dist/clients/dead-code-client.js +137 -31
- package/node_modules/pi-lens/dist/clients/debug-handles.js +206 -0
- package/node_modules/pi-lens/dist/clients/debug-heap.js +167 -0
- package/node_modules/pi-lens/dist/clients/degradation-ledger.js +153 -0
- package/node_modules/pi-lens/dist/clients/dependency-checker.js +361 -77
- package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +65 -13
- package/node_modules/pi-lens/dist/clients/diagnostics-publish.js +18 -4
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +176 -29
- package/node_modules/pi-lens/dist/clients/dispatch/facts/function-facts.js +23 -7
- package/node_modules/pi-lens/dist/clients/dispatch/facts/import-facts.js +8 -18
- package/node_modules/pi-lens/dist/clients/dispatch/facts/tree-sitter-facts.js +8 -5
- package/node_modules/pi-lens/dist/clients/dispatch/indent-detect.js +35 -0
- package/node_modules/pi-lens/dist/clients/dispatch/inline-suppressions.js +17 -8
- package/node_modules/pi-lens/dist/clients/dispatch/integration.js +1172 -683
- package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +14 -0
- package/node_modules/pi-lens/dist/clients/dispatch/plan.js +11 -1
- package/node_modules/pi-lens/dist/clients/dispatch/rule-id-normalize.js +50 -0
- package/node_modules/pi-lens/dist/clients/dispatch/rule-policy.js +135 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +23 -5
- package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +5 -9
- package/node_modules/pi-lens/dist/clients/dispatch/runners/detekt.js +3 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-lint.js +154 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +3 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/index.js +5 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +47 -6
- package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +4 -9
- package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +9 -5
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ruff.js +4 -8
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shellcheck.js +2 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shfmt.js +2 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/spotbugs.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/terragrunt.js +163 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +37 -5
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tree-sitter.js +3 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +13 -7
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +226 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +69 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/lazy-installer.js +3 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +473 -42
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +22 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +97 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yaml-rule-parser.js +5 -4
- package/node_modules/pi-lens/dist/clients/disposition-publish.js +18 -4
- package/node_modules/pi-lens/dist/clients/durable-store.js +97 -0
- package/node_modules/pi-lens/dist/clients/eval-timestamp.js +17 -0
- package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +94 -3
- package/node_modules/pi-lens/dist/clients/extension-log.js +432 -0
- package/node_modules/pi-lens/dist/clients/extension-mode.js +73 -0
- package/node_modules/pi-lens/dist/clients/file-kinds.js +57 -0
- package/node_modules/pi-lens/dist/clients/file-role.js +18 -3
- package/node_modules/pi-lens/dist/clients/file-utils.js +56 -34
- package/node_modules/pi-lens/dist/clients/fix-worklog.js +5 -1
- package/node_modules/pi-lens/dist/clients/format-events-publish.js +51 -7
- package/node_modules/pi-lens/dist/clients/format-service.js +24 -8
- package/node_modules/pi-lens/dist/clients/formatters-lazy.js +8 -0
- package/node_modules/pi-lens/dist/clients/formatters.js +358 -61
- package/node_modules/pi-lens/dist/clients/generated-artifacts.js +148 -15
- package/node_modules/pi-lens/dist/clients/git-guard.js +678 -11
- package/node_modules/pi-lens/dist/clients/git-tracked-ignore.js +4 -0
- package/node_modules/pi-lens/dist/clients/go-client.js +23 -40
- package/node_modules/pi-lens/dist/clients/govulncheck-client.js +124 -7
- package/node_modules/pi-lens/dist/clients/grammar-source.js +12 -4
- package/node_modules/pi-lens/dist/clients/gzip-stage-write.js +21 -3
- package/node_modules/pi-lens/dist/clients/host-ports.js +31 -0
- package/node_modules/pi-lens/dist/clients/installer/index.js +395 -100
- package/node_modules/pi-lens/dist/clients/instance-reaper.js +142 -172
- package/node_modules/pi-lens/dist/clients/jscpd-client.js +27 -55
- package/node_modules/pi-lens/dist/clients/knip-client.js +58 -42
- package/node_modules/pi-lens/dist/clients/language-policy.js +14 -2
- package/node_modules/pi-lens/dist/clients/language-profile.js +13 -7
- package/node_modules/pi-lens/dist/clients/latency-logger.js +72 -1
- package/node_modules/pi-lens/dist/clients/lens-config.js +12 -1
- package/node_modules/pi-lens/dist/clients/lens-engine.js +86 -17
- package/node_modules/pi-lens/dist/clients/lens-events.js +63 -9
- package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +16 -0
- package/node_modules/pi-lens/dist/clients/lens-map.js +94 -19
- package/node_modules/pi-lens/dist/clients/live-bus-emitter.js +73 -0
- package/node_modules/pi-lens/dist/clients/log-cleanup.js +2 -1
- package/node_modules/pi-lens/dist/clients/lsp/aggregation.js +30 -4
- package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +59 -14
- package/node_modules/pi-lens/dist/clients/lsp/client.js +662 -56
- package/node_modules/pi-lens/dist/clients/lsp/config.js +13 -2
- package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +115 -0
- package/node_modules/pi-lens/dist/clients/lsp/edits.js +1012 -121
- package/node_modules/pi-lens/dist/clients/lsp/index.js +2025 -800
- package/node_modules/pi-lens/dist/clients/lsp/launch.js +32 -26
- package/node_modules/pi-lens/dist/clients/lsp/path-utils.js +1 -1
- package/node_modules/pi-lens/dist/clients/lsp/ruby-drive-dirs.js +83 -0
- package/node_modules/pi-lens/dist/clients/lsp/server.js +437 -86
- package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +96 -0
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/classification.js +21 -5
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +18 -3
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +28 -4
- package/node_modules/pi-lens/dist/clients/lsp-lazy.js +8 -0
- package/node_modules/pi-lens/dist/clients/lsp-mutation.js +248 -0
- package/node_modules/pi-lens/dist/clients/mcp/analyze.js +127 -32
- package/node_modules/pi-lens/dist/clients/mcp/ipc.js +157 -24
- package/node_modules/pi-lens/dist/clients/mcp/session.js +235 -14
- package/node_modules/pi-lens/dist/clients/memory-sampler.js +115 -0
- package/node_modules/pi-lens/dist/clients/metrics-client.js +2 -1
- package/node_modules/pi-lens/dist/clients/metrics-history.js +2 -1
- package/node_modules/pi-lens/dist/clients/model-provider.js +53 -0
- package/node_modules/pi-lens/dist/clients/module-report-lsp.js +5 -0
- package/node_modules/pi-lens/dist/clients/module-report.js +168 -3
- package/node_modules/pi-lens/dist/clients/ndjson-logger.js +319 -118
- package/node_modules/pi-lens/dist/clients/opengrep-client.js +1 -1
- package/node_modules/pi-lens/dist/clients/partial-edit-apply.js +120 -5
- package/node_modules/pi-lens/dist/clients/path-utils.js +110 -9
- package/node_modules/pi-lens/dist/clients/pipeline.js +76 -15
- package/node_modules/pi-lens/dist/clients/print-mode.js +21 -0
- package/node_modules/pi-lens/dist/clients/project-changes.js +40 -0
- package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +3 -2
- package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +1 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/call-graph-impact.js +8 -0
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +23 -2
- package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +21 -1
- package/node_modules/pi-lens/dist/clients/project-lens-config.js +86 -9
- package/node_modules/pi-lens/dist/clients/project-report.js +27 -13
- package/node_modules/pi-lens/dist/clients/project-snapshot.js +175 -20
- package/node_modules/pi-lens/dist/clients/project-trust.js +181 -0
- package/node_modules/pi-lens/dist/clients/quiet-window.js +18 -4
- package/node_modules/pi-lens/dist/clients/read-bridge.js +147 -0
- package/node_modules/pi-lens/dist/clients/read-guard-logger.js +159 -1
- package/node_modules/pi-lens/dist/clients/read-guard-tool-lines.js +150 -29
- package/node_modules/pi-lens/dist/clients/read-guard.js +185 -4
- package/node_modules/pi-lens/dist/clients/resource-sampler.js +70 -84
- package/node_modules/pi-lens/dist/clients/review-graph/builder.js +1122 -221
- package/node_modules/pi-lens/dist/clients/review-graph/git-identity.js +2 -1
- package/node_modules/pi-lens/dist/clients/review-graph/import-resolvers.js +21 -10
- package/node_modules/pi-lens/dist/clients/review-graph/query.js +24 -0
- package/node_modules/pi-lens/dist/clients/review-graph/symbol-id.js +46 -0
- package/node_modules/pi-lens/dist/clients/review-graph/tsconfig-paths.js +57 -6
- package/node_modules/pi-lens/dist/clients/review-graph/workspace-modules.js +51 -3
- package/node_modules/pi-lens/dist/clients/review-graph-logger.js +30 -1
- package/node_modules/pi-lens/dist/clients/ruff-client.js +27 -44
- package/node_modules/pi-lens/dist/clients/run-duration.js +55 -0
- package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +257 -77
- package/node_modules/pi-lens/dist/clients/runtime-context.js +129 -12
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +242 -26
- package/node_modules/pi-lens/dist/clients/runtime-session.js +428 -117
- package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +71 -48
- package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +342 -33
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +619 -93
- package/node_modules/pi-lens/dist/clients/rust-client.js +23 -38
- package/node_modules/pi-lens/dist/clients/safe-spawn.js +777 -62
- package/node_modules/pi-lens/dist/clients/security-scan-client.js +90 -6
- package/node_modules/pi-lens/dist/clients/session-state-store.js +3 -2
- package/node_modules/pi-lens/dist/clients/sg-runner.js +424 -196
- package/node_modules/pi-lens/dist/clients/slow-fs.js +2 -1
- package/node_modules/pi-lens/dist/clients/smells-rollup.js +231 -0
- package/node_modules/pi-lens/dist/clients/source-filter.js +184 -20
- package/node_modules/pi-lens/dist/clients/source-walker.js +66 -10
- package/node_modules/pi-lens/dist/clients/startup-scan.js +15 -16
- package/node_modules/pi-lens/dist/clients/startup-timing.js +7 -1
- package/node_modules/pi-lens/dist/clients/test-runner-client.js +469 -32
- package/node_modules/pi-lens/dist/clients/tool-event.js +35 -0
- package/node_modules/pi-lens/dist/clients/tool-policy.js +390 -39
- package/node_modules/pi-lens/dist/clients/tool-render.js +155 -0
- package/node_modules/pi-lens/dist/clients/tool-set-policy.js +76 -0
- package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +6 -1
- package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +419 -50
- package/node_modules/pi-lens/dist/clients/tree-sitter-logger.js +21 -0
- package/node_modules/pi-lens/dist/clients/tree-sitter-query-loader.js +7 -1
- package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +7 -2
- package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +44 -7
- package/node_modules/pi-lens/dist/clients/user-notify.js +51 -0
- package/node_modules/pi-lens/dist/clients/vanished-instance-marker.js +57 -0
- package/node_modules/pi-lens/dist/clients/warm-attach.js +50 -13
- package/node_modules/pi-lens/dist/clients/widget-state.js +300 -43
- package/node_modules/pi-lens/dist/clients/word-index.js +680 -81
- package/node_modules/pi-lens/dist/clients/workspace-topology.js +89 -6
- package/node_modules/pi-lens/dist/index.js +51785 -36118
- package/node_modules/pi-lens/dist/mcp/analyze-cli.js +182 -29
- package/node_modules/pi-lens/dist/mcp/server.js +219 -46
- package/node_modules/pi-lens/dist/tools/activate-tools.js +17 -5
- package/node_modules/pi-lens/dist/tools/ast-grep-replace.js +9 -4
- package/node_modules/pi-lens/dist/tools/ast-grep-search.js +93 -27
- package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +5 -2
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +203 -38
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +210 -42
- package/node_modules/pi-lens/dist/tools/lsp-navigation.js +46 -3
- package/node_modules/pi-lens/dist/tools/module-report.js +9 -0
- package/node_modules/pi-lens/dist/tools/symbol-search.js +1 -1
- package/node_modules/pi-lens/docs/agent-guide.md +40 -15
- package/node_modules/pi-lens/docs/agent-tools.md +21 -10
- package/node_modules/pi-lens/docs/analysisall.md +192 -0
- package/node_modules/pi-lens/docs/api-ports-inventory.md +165 -0
- package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +14 -3
- package/node_modules/pi-lens/docs/durable-store-audit-1202.md +32 -0
- package/node_modules/pi-lens/docs/environment-variables.md +44 -0
- package/node_modules/pi-lens/docs/fable.md +27 -0
- package/node_modules/pi-lens/docs/features.md +45 -3
- package/node_modules/pi-lens/docs/globalconfig.md +56 -1
- package/node_modules/pi-lens/docs/language-coverage.md +4 -3
- package/node_modules/pi-lens/docs/lsp-capability-matrix.md +2 -2
- package/node_modules/pi-lens/docs/mcp.md +37 -4
- package/node_modules/pi-lens/docs/servercapabilities.md +3 -3
- package/node_modules/pi-lens/docs/settings.md +18 -1
- package/node_modules/pi-lens/docs/tools.md +4 -1
- package/node_modules/pi-lens/docs/usage.md +41 -5
- package/node_modules/pi-lens/docs/word-index.md +35 -0
- package/node_modules/pi-lens/package.json +10 -10
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-bare-except-test.yml +49 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-bare-host-path-in-win32-branch-test.yml +87 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-chained-type-assertions-test.yml +8 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-conditional-empty-object-spread-js-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-conditional-empty-object-spread-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-nested-links-test.yml +11 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-raw-json-store-write-test.yml +17 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-js-test.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-test.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-js-test.yml +8 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-test.yml +8 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-laundering-test.yml +11 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-win32-isabsolute-for-qualification-test.yml +16 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-except.yml +3 -15
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-host-path-in-win32-branch.yml +25 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-chained-type-assertions.yml +21 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-conditional-empty-object-spread-js.yml +21 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-conditional-empty-object-spread.yml +29 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-nested-links.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-raw-json-store-write.yml +30 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply-js.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get-js.yml +13 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get.yml +16 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-laundering.yml +27 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-win32-isabsolute-for-qualification.yml +23 -0
- package/node_modules/pi-lens/rules/tree-sitter-queries/tsx/no-nested-links.yml +4 -6
- package/node_modules/pi-lens/rules/tree-sitter-queries/typescript/duplicate-function-arg.yml +2 -2
- package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +134 -2
- package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +10 -11
- package/node_modules/pi-lens/skills/pi-lens-lsp-navigation/SKILL.md +22 -22
- package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/SKILL.md +8 -114
- package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/reference.md +129 -0
- package/node_modules/pi-lens/skills/pi-lens-write-tree-sitter-rule/SKILL.md +3 -1
- package/node_modules/pi-mcp-adapter/CHANGELOG.md +38 -0
- package/node_modules/pi-mcp-adapter/README.md +38 -4
- package/node_modules/pi-mcp-adapter/agent-dir.ts +12 -4
- package/node_modules/pi-mcp-adapter/agent-plugin-loader.ts +1 -1
- package/node_modules/pi-mcp-adapter/cli.js +25 -4
- package/node_modules/pi-mcp-adapter/commands.ts +15 -7
- package/node_modules/pi-mcp-adapter/config.ts +4 -4
- package/node_modules/pi-mcp-adapter/direct-tools.ts +58 -8
- package/node_modules/pi-mcp-adapter/host-html-template.ts +0 -8
- package/node_modules/pi-mcp-adapter/index.ts +8 -3
- package/node_modules/pi-mcp-adapter/init.ts +29 -5
- package/node_modules/pi-mcp-adapter/lifecycle.ts +0 -4
- package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +1 -2
- package/node_modules/pi-mcp-adapter/mcp-auth.ts +60 -2
- package/node_modules/pi-mcp-adapter/mcp-panel.ts +45 -9
- package/node_modules/pi-mcp-adapter/mcp-script-worker.mjs +22 -20
- package/node_modules/pi-mcp-adapter/mcp-setup-panel.ts +2 -1
- package/node_modules/pi-mcp-adapter/metadata-cache.ts +37 -4
- package/node_modules/pi-mcp-adapter/npx-resolver.ts +81 -26
- package/node_modules/pi-mcp-adapter/package.json +4 -3
- package/node_modules/pi-mcp-adapter/proxy-modes.ts +108 -26
- package/node_modules/pi-mcp-adapter/request-headers-command.ts +336 -0
- package/node_modules/pi-mcp-adapter/search-ranking.ts +86 -7
- package/node_modules/pi-mcp-adapter/server-manager.ts +41 -7
- package/node_modules/pi-mcp-adapter/session-recovery.ts +8 -2
- package/node_modules/pi-mcp-adapter/tool-approval.ts +48 -7
- package/node_modules/pi-mcp-adapter/tool-metadata.ts +62 -4
- package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +138 -12
- package/node_modules/pi-mcp-adapter/types.ts +176 -27
- package/node_modules/pi-mcp-adapter/ui-server.ts +20 -1
- package/node_modules/pi-web-access/CHANGELOG.md +14 -0
- package/node_modules/pi-web-access/README.md +18 -12
- package/node_modules/pi-web-access/auth-fetch.ts +148 -0
- package/node_modules/pi-web-access/chrome-cookies.ts +110 -23
- package/node_modules/pi-web-access/curator-page.ts +5 -3
- package/node_modules/pi-web-access/curator-server.ts +2 -1
- package/node_modules/pi-web-access/extract.ts +106 -34
- package/node_modules/pi-web-access/fetch-params.ts +17 -3
- package/node_modules/pi-web-access/firecrawl.ts +172 -12
- package/node_modules/pi-web-access/gemini-search.ts +18 -4
- package/node_modules/pi-web-access/index.ts +120 -48
- package/node_modules/pi-web-access/package.json +2 -2
- package/node_modules/pi-web-access/summary-review.ts +11 -5
- package/node_modules/pi-web-access/youtube-extract.ts +2 -2
- package/package.json +12 -13
- package/node_modules/pi-lens/dist/clients/ast-grep-parser.js +0 -86
- package/node_modules/pi-lens/dist/clients/lsp/interactive-install.js +0 -367
- package/node_modules/pi-lens/dist/clients/lsp/lsp-index.js +0 -10
- package/node_modules/pi-lens/dist/clients/lsp/server-strategies.js +0 -5
- package/node_modules/pi-lens/dist/clients/project-metadata.js +0 -690
- package/node_modules/pi-lens/dist/clients/source-groups.js +0 -96
- package/node_modules/pi-lens/dist/clients/startup-marker.js +0 -6
- package/node_modules/pi-lens/dist/clients/types.js +0 -11
|
@@ -4,9 +4,13 @@ import { applyConservativeActionableWarningFixes, checkActionableWarningsReportF
|
|
|
4
4
|
import { publishFilesTouched } from "./bus-publish.js";
|
|
5
5
|
import { publishAutofixStart, publishFormatStart, } from "./format-events-publish.js";
|
|
6
6
|
import { logLatency } from "./latency-logger.js";
|
|
7
|
+
import { isPathIgnoredByProject } from "./file-utils.js";
|
|
8
|
+
import { newLspMutationCorrelationId } from "./lsp-mutation.js";
|
|
7
9
|
import { getGlobalActionableWarningMaxFixes, } from "./lens-config.js";
|
|
8
|
-
import { resyncLspFile, runFormatPhase } from "./pipeline.js";
|
|
10
|
+
import { resyncLspFile, runAutofix, runFormatPhase } from "./pipeline.js";
|
|
11
|
+
import { getAmbientAbortSignal } from "./safe-spawn.js";
|
|
9
12
|
import { appendProjectChange, } from "./project-changes.js";
|
|
13
|
+
import { getAutofixPolicyForFile, hasBiomeConfig, hasDetektConfig, hasEslintConfig, hasGolangciConfig, hasKtfmtConfig, hasKtlintConfig, hasOxlintConfig, hasRubocopConfig, hasSqlfluffConfig, hasStylelintConfig, } from "./tool-policy.js";
|
|
10
14
|
/**
|
|
11
15
|
* A queued file is claimed by any flush once it has sat unclaimed by its own
|
|
12
16
|
* owning session for this long â recovery for an orphaned record whose
|
|
@@ -16,6 +20,7 @@ import { appendProjectChange, } from "./project-changes.js";
|
|
|
16
20
|
* extra staleness for guaranteed eventual formatting. (#791)
|
|
17
21
|
*/
|
|
18
22
|
export const DEFERRED_FORMAT_STALE_AFTER_MS = 10 * 60_000;
|
|
23
|
+
const DEFERRED_FORMAT_CONCURRENCY = 3;
|
|
19
24
|
function recordProjectChange(args) {
|
|
20
25
|
const bump = args.runtime.bumpFileSeq;
|
|
21
26
|
if (!bump)
|
|
@@ -36,13 +41,49 @@ function recordProjectChange(args) {
|
|
|
36
41
|
args.dbg(`project change log append failed for ${args.filePath}: ${err}`);
|
|
37
42
|
}
|
|
38
43
|
}
|
|
39
|
-
export async function handleAgentEnd({ ctxCwd, getFlag, getFlagSource, notify, dbg, runtime, cacheManager, getFormatService, currentSessionId, staleAfterMs = DEFERRED_FORMAT_STALE_AFTER_MS, }) {
|
|
44
|
+
export async function handleAgentEnd({ ctxCwd, getFlag, getFlagSource, notify, dbg, runtime, cacheManager, getFormatService, biomeClient, ruffClient, getAutofixClients, currentSessionId, staleAfterMs = DEFERRED_FORMAT_STALE_AFTER_MS, }) {
|
|
40
45
|
// #791: ownership-filtered drain â records queued by a DIFFERENT known
|
|
41
46
|
// session (e.g. a concurrent in-process secondary/subagent) stay queued
|
|
42
47
|
// for their owner's own agent_end, unless they've been stale long enough
|
|
43
48
|
// to fall back to "claim as orphaned" (see claimDeferredFormatFiles).
|
|
44
|
-
const { claimed, staleClaimed, deferredToOwner } = runtime.
|
|
49
|
+
const { claimed, staleClaimed, deferredToOwner } = runtime.claimDeferredMutations(currentSessionId, Date.now(), staleAfterMs);
|
|
45
50
|
const records = [...claimed, ...staleClaimed];
|
|
51
|
+
const requeuedKinds = new Set();
|
|
52
|
+
// S2d (gap 4, #1432 review): the aggregate `agent_end_deferred_mutation_drain`
|
|
53
|
+
// row only carried a coalesced `requeuedKinds` set with no reason, per-call
|
|
54
|
+
// file count, or tool provenance â every requeue (abort mid-drain, missing
|
|
55
|
+
// autofix clients, an autofix/format failure) collapsed into one
|
|
56
|
+
// indistinguishable bucket. Log one bounded record PER requeue call instead,
|
|
57
|
+
// so a real incident can tell "aborted with N files still queued" apart
|
|
58
|
+
// from "M files failed to format".
|
|
59
|
+
const requeue = (pending, reason) => {
|
|
60
|
+
if (pending.length === 0)
|
|
61
|
+
return;
|
|
62
|
+
const kinds = new Set();
|
|
63
|
+
const toolNames = new Set();
|
|
64
|
+
for (const record of pending) {
|
|
65
|
+
for (const kind of record.kinds) {
|
|
66
|
+
requeuedKinds.add(kind);
|
|
67
|
+
kinds.add(kind);
|
|
68
|
+
}
|
|
69
|
+
for (const toolName of record.toolNames)
|
|
70
|
+
toolNames.add(toolName);
|
|
71
|
+
}
|
|
72
|
+
logLatency({
|
|
73
|
+
type: "phase",
|
|
74
|
+
toolName: "agent_end",
|
|
75
|
+
filePath: ctxCwd ?? runtime.projectRoot,
|
|
76
|
+
phase: "agent_end_deferred_mutation_requeue",
|
|
77
|
+
durationMs: 0,
|
|
78
|
+
metadata: {
|
|
79
|
+
reason,
|
|
80
|
+
kinds: [...kinds].sort((a, b) => (a < b ? -1 : a > b ? 1 : 0)),
|
|
81
|
+
fileCount: pending.length,
|
|
82
|
+
toolNames: [...toolNames].sort((a, b) => (a < b ? -1 : a > b ? 1 : 0)),
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
runtime.requeueDeferredMutations(pending);
|
|
86
|
+
};
|
|
46
87
|
const rootActionableAutofixEnabled = !!getFlag("lens-actionable-warning-autofix");
|
|
47
88
|
// A path-aware source resolver signals that nested configs may re-enable
|
|
48
89
|
// actionable autofix even when the root default is off. Legacy/test hosts
|
|
@@ -93,6 +134,86 @@ export async function handleAgentEnd({ ctxCwd, getFlag, getFlagSource, notify, d
|
|
|
93
134
|
// publishFilesTouched call so consumers can tell "pi-lens formatted this"
|
|
94
135
|
// from an agent edit.
|
|
95
136
|
const deferredFormatFixes = [];
|
|
137
|
+
const deferredAutofixFixes = [];
|
|
138
|
+
const deferredAutofixChanged = new Set();
|
|
139
|
+
// Mutation ordering is intentional: lint --write may disturb wrapping, so
|
|
140
|
+
// autofix reaches the final edited state first and formatting stabilizes it.
|
|
141
|
+
const ambientSignal = getAmbientAbortSignal();
|
|
142
|
+
const executedAutofixScopes = new Set();
|
|
143
|
+
const autofixRecords = records.filter((candidate) => candidate.kinds.has("autofix"));
|
|
144
|
+
if (autofixRecords.length > 0 && (!biomeClient || !ruffClient) && getAutofixClients) {
|
|
145
|
+
({ biomeClient, ruffClient } = await getAutofixClients());
|
|
146
|
+
}
|
|
147
|
+
for (let autofixIndex = 0; autofixIndex < autofixRecords.length; autofixIndex++) {
|
|
148
|
+
const record = autofixRecords[autofixIndex];
|
|
149
|
+
if (ambientSignal?.aborted) {
|
|
150
|
+
requeue(autofixRecords.slice(autofixIndex).map((pending) => ({
|
|
151
|
+
...pending,
|
|
152
|
+
kinds: new Set(["autofix"]),
|
|
153
|
+
toolNames: new Set(pending.toolNames),
|
|
154
|
+
})), "abort");
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
const filePath = path.resolve(record.filePath);
|
|
158
|
+
if (!nodeFs.existsSync(filePath)) {
|
|
159
|
+
summary.skipped.push({ filePath, reason: "missing" });
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
if (!biomeClient || !ruffClient) {
|
|
163
|
+
dbg(`agent_end deferred_autofix: clients unavailable for ${filePath}`);
|
|
164
|
+
requeue([{ ...record, kinds: new Set(["autofix"]), toolNames: new Set(record.toolNames) }], "clients-unavailable");
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
const policy = getAutofixPolicyForFile(filePath, {
|
|
168
|
+
hasEslintConfig: hasEslintConfig(record.cwd),
|
|
169
|
+
hasStylelintConfig: hasStylelintConfig(record.cwd),
|
|
170
|
+
hasSqlfluffConfig: hasSqlfluffConfig(record.cwd),
|
|
171
|
+
hasRubocopConfig: hasRubocopConfig(record.cwd),
|
|
172
|
+
hasBiomeConfig: hasBiomeConfig(record.cwd),
|
|
173
|
+
hasGolangciConfig: hasGolangciConfig(record.cwd),
|
|
174
|
+
hasDetektConfig: hasDetektConfig(record.cwd),
|
|
175
|
+
hasOxlintConfig: hasOxlintConfig(record.cwd),
|
|
176
|
+
hasKtfmtConfig: hasKtfmtConfig(record.cwd),
|
|
177
|
+
hasKtlintConfig: hasKtlintConfig(record.cwd),
|
|
178
|
+
});
|
|
179
|
+
const scopeKey = policy?.scope && policy.scope !== "file"
|
|
180
|
+
? `${policy.defaultTool ?? "unknown"}:${path.resolve(record.cwd)}`
|
|
181
|
+
: `${policy?.defaultTool ?? "unknown"}:${filePath}`;
|
|
182
|
+
if (executedAutofixScopes.has(scopeKey))
|
|
183
|
+
continue;
|
|
184
|
+
executedAutofixScopes.add(scopeKey);
|
|
185
|
+
try {
|
|
186
|
+
const result = await runAutofix(filePath, record.cwd, getFlag, dbg, { biomeClient, ruffClient, fixedThisTurn: runtime.fixedThisTurn }, getFlagSource);
|
|
187
|
+
const tools = result.autofixTools.map((label) => label.split(":")[0]);
|
|
188
|
+
for (const changed of result.changedFiles) {
|
|
189
|
+
const changedPath = path.resolve(changed);
|
|
190
|
+
deferredAutofixChanged.add(changedPath);
|
|
191
|
+
for (const tool of tools)
|
|
192
|
+
deferredAutofixFixes.push({ path: changedPath, tool, kind: "autofix" });
|
|
193
|
+
if (!nodeFs.existsSync(changedPath))
|
|
194
|
+
continue;
|
|
195
|
+
recordProjectChange({ runtime, cwd: record.turnStateCwd, filePath: changedPath, source: "autofix", dbg });
|
|
196
|
+
if (!getFlag("no-read-guard"))
|
|
197
|
+
runtime.readGuard.recordWritten(changedPath);
|
|
198
|
+
const content = nodeFs.readFileSync(changedPath, "utf-8");
|
|
199
|
+
cacheManager.addModifiedRange(changedPath, { start: 1, end: content.split("\n").length }, /^import\s/m.test(content), record.turnStateCwd, currentSessionId ?? runtime.telemetrySessionId, "pi");
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
catch (err) {
|
|
203
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
204
|
+
summary.failed.push({ filePath, errors: [message] });
|
|
205
|
+
requeue([{ ...record, kinds: new Set(["autofix"]), toolNames: new Set(record.toolNames) }], "autofix-failed");
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
if (deferredAutofixFixes.length > 0) {
|
|
209
|
+
publishFilesTouched({
|
|
210
|
+
reason: "autofix",
|
|
211
|
+
paths: [...new Set(deferredAutofixFixes.map((fix) => fix.path))],
|
|
212
|
+
cwd: ctxCwd ?? runtime.projectRoot,
|
|
213
|
+
dbg,
|
|
214
|
+
fixes: deferredAutofixFixes,
|
|
215
|
+
});
|
|
216
|
+
}
|
|
96
217
|
dbg(`agent_end deferred_format: ${records.length} file(s)`);
|
|
97
218
|
logLatency({
|
|
98
219
|
type: "phase",
|
|
@@ -123,9 +244,10 @@ export async function handleAgentEnd({ ctxCwd, getFlag, getFlagSource, notify, d
|
|
|
123
244
|
cwd: ctxCwd ?? runtime.projectRoot,
|
|
124
245
|
paths: records.map((r) => r.filePath),
|
|
125
246
|
dbg,
|
|
247
|
+
kinds: [...new Set(records.flatMap((record) => [...record.kinds]))],
|
|
126
248
|
});
|
|
127
249
|
}
|
|
128
|
-
const formatRecords = records.filter((record) => {
|
|
250
|
+
const formatRecords = records.filter((record) => record.kinds.has("format")).filter((record) => {
|
|
129
251
|
const disabled = !!getFlag("no-autoformat", record.filePath);
|
|
130
252
|
if (disabled) {
|
|
131
253
|
const source = getFlagSource?.("no-autoformat", record.filePath);
|
|
@@ -138,46 +260,73 @@ export async function handleAgentEnd({ ctxCwd, getFlag, getFlagSource, notify, d
|
|
|
138
260
|
return !disabled;
|
|
139
261
|
});
|
|
140
262
|
if (formatRecords.length > 0) {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
const
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
263
|
+
const work = new Array(formatRecords.length);
|
|
264
|
+
const started = new Set();
|
|
265
|
+
let nextIndex = 0;
|
|
266
|
+
const worker = async () => {
|
|
267
|
+
while (nextIndex < formatRecords.length) {
|
|
268
|
+
const index = nextIndex++;
|
|
269
|
+
if (ambientSignal?.aborted)
|
|
270
|
+
return;
|
|
271
|
+
const record = formatRecords[index];
|
|
272
|
+
const fileStart = Date.now();
|
|
273
|
+
const filePath = path.resolve(record.filePath);
|
|
274
|
+
started.add(index);
|
|
275
|
+
if (!nodeFs.existsSync(filePath)) {
|
|
276
|
+
work[index] = { record, filePath, fileStart, missing: true };
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
279
|
+
try {
|
|
280
|
+
work[index] = {
|
|
281
|
+
record,
|
|
282
|
+
filePath,
|
|
283
|
+
fileStart,
|
|
284
|
+
result: await runFormatPhase(filePath, getFormatService, dbg),
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
catch (err) {
|
|
288
|
+
work[index] = {
|
|
289
|
+
record,
|
|
290
|
+
filePath,
|
|
291
|
+
fileStart,
|
|
292
|
+
error: err instanceof Error ? err.message : String(err),
|
|
293
|
+
};
|
|
294
|
+
}
|
|
158
295
|
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
296
|
+
};
|
|
297
|
+
await Promise.all(Array.from({ length: Math.min(DEFERRED_FORMAT_CONCURRENCY, formatRecords.length) }, () => worker()));
|
|
298
|
+
if (ambientSignal?.aborted) {
|
|
299
|
+
requeue(formatRecords.filter((_, index) => !started.has(index)).map((record) => ({
|
|
300
|
+
...record,
|
|
301
|
+
kinds: new Set(["format"]),
|
|
302
|
+
toolNames: new Set(record.toolNames),
|
|
303
|
+
})), "abort");
|
|
304
|
+
}
|
|
305
|
+
for (const entry of work) {
|
|
306
|
+
if (!entry)
|
|
307
|
+
continue;
|
|
308
|
+
await new Promise((resolve) => setImmediate(resolve));
|
|
309
|
+
const { record, filePath, fileStart } = entry;
|
|
310
|
+
if (entry.missing) {
|
|
311
|
+
dbg(`agent_end deferred_format skipped missing file: ${filePath}`);
|
|
312
|
+
if (!summary.skipped.some((item) => item.filePath === filePath && item.reason === "missing")) {
|
|
313
|
+
summary.skipped.push({ filePath, reason: "missing" });
|
|
314
|
+
}
|
|
168
315
|
continue;
|
|
169
316
|
}
|
|
170
|
-
if (
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
});
|
|
317
|
+
if (entry.error) {
|
|
318
|
+
dbg(`agent_end deferred_format failed for ${filePath}: ${entry.error}`);
|
|
319
|
+
summary.failed.push({ filePath, errors: [entry.error] });
|
|
320
|
+
requeue([{ ...record, kinds: new Set(["format"]), toolNames: new Set(record.toolNames) }], "format-failed");
|
|
175
321
|
continue;
|
|
176
322
|
}
|
|
177
|
-
const
|
|
323
|
+
const result = entry.result;
|
|
324
|
+
if (!result)
|
|
325
|
+
continue;
|
|
178
326
|
summary.formatted++;
|
|
179
327
|
if (result.formatFailures.length > 0) {
|
|
180
328
|
summary.failed.push({ filePath, errors: result.formatFailures });
|
|
329
|
+
requeue([{ ...record, kinds: new Set(["format"]), toolNames: new Set(record.toolNames) }], "format-failed");
|
|
181
330
|
}
|
|
182
331
|
if (result.formatChanged) {
|
|
183
332
|
summary.changed.push(filePath);
|
|
@@ -202,7 +351,7 @@ export async function handleAgentEnd({ ctxCwd, getFlag, getFlagSource, notify, d
|
|
|
202
351
|
const content = nodeFs.readFileSync(filePath, "utf-8");
|
|
203
352
|
const lineCount = content.split("\n").length;
|
|
204
353
|
const hasImports = /^import\s/m.test(content);
|
|
205
|
-
cacheManager.addModifiedRange(filePath, { start: 1, end: lineCount }, hasImports, bookkeepingCwd);
|
|
354
|
+
cacheManager.addModifiedRange(filePath, { start: 1, end: lineCount }, hasImports, bookkeepingCwd, currentSessionId ?? runtime.telemetrySessionId, "pi");
|
|
206
355
|
}
|
|
207
356
|
catch (err) {
|
|
208
357
|
dbg(`agent_end deferred_format modified-range tracking failed for ${filePath}: ${err}`);
|
|
@@ -244,6 +393,14 @@ export async function handleAgentEnd({ ctxCwd, getFlag, getFlagSource, notify, d
|
|
|
244
393
|
});
|
|
245
394
|
}
|
|
246
395
|
}
|
|
396
|
+
// LSP sees only authoritative content after both mutation phases. In
|
|
397
|
+
// particular, never publish the autofix intermediate state before format.
|
|
398
|
+
for (const changedPath of deferredAutofixChanged) {
|
|
399
|
+
if (!nodeFs.existsSync(changedPath))
|
|
400
|
+
continue;
|
|
401
|
+
const content = nodeFs.readFileSync(changedPath, "utf-8");
|
|
402
|
+
await resyncLspFile(changedPath, content, true, false, getFlag, dbg);
|
|
403
|
+
}
|
|
247
404
|
if (inspectActionableReport) {
|
|
248
405
|
const actionReport = cacheManager.readCache("actionable-warnings", ctxCwd ?? runtime.projectRoot, 10 * 60_000);
|
|
249
406
|
if (!actionReport?.data) {
|
|
@@ -251,6 +408,14 @@ export async function handleAgentEnd({ ctxCwd, getFlag, getFlagSource, notify, d
|
|
|
251
408
|
}
|
|
252
409
|
else {
|
|
253
410
|
const enabledFiles = actionReport.data.files.filter((file) => {
|
|
411
|
+
// #1247: the per-edit dispatch surface gates ignored files before
|
|
412
|
+
// running; the turn-end autofix must apply the same filter or a
|
|
413
|
+
// `.pi-lens.json` `ignore` entry cannot protect a prose file
|
|
414
|
+
// (CHANGELOG.md / AGENTS.md) from being rewritten here.
|
|
415
|
+
if (isPathIgnoredByProject(file.filePath, ctxCwd ?? runtime.projectRoot)) {
|
|
416
|
+
dbg(`agent_end actionable_warnings_autofix: skipped ${file.filePath} (ignored by project)`);
|
|
417
|
+
return false;
|
|
418
|
+
}
|
|
254
419
|
const enabled = !!getFlag("lens-actionable-warning-autofix", file.filePath);
|
|
255
420
|
if (!enabled) {
|
|
256
421
|
const source = getFlagSource?.("lens-actionable-warning-autofix", file.filePath);
|
|
@@ -281,49 +446,42 @@ export async function handleAgentEnd({ ctxCwd, getFlag, getFlagSource, notify, d
|
|
|
281
446
|
if (!freshness.fresh) {
|
|
282
447
|
dbg(`agent_end actionable_warnings_autofix: stale report (${freshness.reason}; reportProjectSeqEnd=${freshness.reportProjectSeqEnd ?? "missing"}; currentProjectSeq=${freshness.currentProjectSeq}${freshness.filePath ? `; file=${freshness.filePath}; reportFileSeq=${freshness.reportFileSeq}; currentFileSeq=${freshness.currentFileSeq}` : ""}), skipping fixes`);
|
|
283
448
|
}
|
|
284
|
-
else {
|
|
449
|
+
else if (eligibleReport.summary.autoFixEligible > 0) {
|
|
285
450
|
// #684: same "genuine work about to happen" gate as
|
|
286
451
|
// publishFormatStart â only fires when the report is fresh AND
|
|
287
452
|
// has at least one autofix-eligible warning, right before
|
|
288
453
|
// applyConservativeActionableWarningFixes actually starts.
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
});
|
|
299
|
-
}
|
|
454
|
+
publishAutofixStart({
|
|
455
|
+
cwd: ctxCwd ?? runtime.projectRoot,
|
|
456
|
+
paths: eligibleReport.files
|
|
457
|
+
.filter((file) => file.warnings.some((warning) => !warning.suppressed &&
|
|
458
|
+
warning.actions.some((action) => action.autoFixEligible)))
|
|
459
|
+
.map((file) => file.filePath),
|
|
460
|
+
eligibleCount: eligibleReport.summary.autoFixEligible,
|
|
461
|
+
dbg,
|
|
462
|
+
});
|
|
300
463
|
const fixStart = Date.now();
|
|
464
|
+
const fixCwd = ctxCwd ?? runtime.projectRoot;
|
|
465
|
+
const mutationContext = {
|
|
466
|
+
cwd: fixCwd,
|
|
467
|
+
correlationId: newLspMutationCorrelationId(),
|
|
468
|
+
tool: "lsp-quickfix",
|
|
469
|
+
source: "autofix",
|
|
470
|
+
runtime,
|
|
471
|
+
cacheManager,
|
|
472
|
+
readGuard: getFlag("no-read-guard") ? undefined : runtime.readGuard,
|
|
473
|
+
recordAutofix: getFlag("lens-turn-summary")
|
|
474
|
+
? (filePath) => runtime.turnSummary.recordAutofix(filePath, { tool: "lsp-quickfix" })
|
|
475
|
+
: undefined,
|
|
476
|
+
dbg,
|
|
477
|
+
};
|
|
301
478
|
const fixSummary = await applyConservativeActionableWarningFixes({
|
|
302
|
-
cwd:
|
|
479
|
+
cwd: fixCwd,
|
|
303
480
|
report: eligibleReport,
|
|
304
481
|
maxFixes: getGlobalActionableWarningMaxFixes(),
|
|
305
482
|
dbg,
|
|
483
|
+
mutationContext,
|
|
306
484
|
});
|
|
307
|
-
for (const changedFile of fixSummary.changedFiles) {
|
|
308
|
-
if (!nodeFs.existsSync(changedFile))
|
|
309
|
-
continue;
|
|
310
|
-
recordProjectChange({
|
|
311
|
-
runtime,
|
|
312
|
-
cwd: ctxCwd ?? runtime.projectRoot,
|
|
313
|
-
filePath: changedFile,
|
|
314
|
-
source: "autofix",
|
|
315
|
-
dbg,
|
|
316
|
-
});
|
|
317
|
-
if (!getFlag("no-read-guard"))
|
|
318
|
-
runtime.readGuard.recordWritten(changedFile);
|
|
319
|
-
try {
|
|
320
|
-
const content = nodeFs.readFileSync(changedFile, "utf-8");
|
|
321
|
-
cacheManager.addModifiedRange(changedFile, { start: 1, end: content.split("\n").length }, /^import\s/m.test(content), ctxCwd ?? runtime.projectRoot);
|
|
322
|
-
}
|
|
323
|
-
catch (err) {
|
|
324
|
-
dbg(`agent_end actionable warning changed-file tracking failed for ${changedFile}: ${err}`);
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
485
|
if (fixSummary.changedFiles.length > 0) {
|
|
328
486
|
publishFilesTouched({
|
|
329
487
|
reason: "autofix",
|
|
@@ -336,13 +494,6 @@ export async function handleAgentEnd({ ctxCwd, getFlag, getFlagSource, notify, d
|
|
|
336
494
|
kind: "autofix",
|
|
337
495
|
})),
|
|
338
496
|
});
|
|
339
|
-
if (getFlag("lens-turn-summary")) {
|
|
340
|
-
for (const changedFile of fixSummary.changedFiles) {
|
|
341
|
-
runtime.turnSummary.recordAutofix(changedFile, {
|
|
342
|
-
tool: "lsp-quickfix",
|
|
343
|
-
});
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
497
|
}
|
|
347
498
|
logLatency({
|
|
348
499
|
type: "phase",
|
|
@@ -361,8 +512,24 @@ export async function handleAgentEnd({ ctxCwd, getFlag, getFlagSource, notify, d
|
|
|
361
512
|
notify(`pi-lens applied ${fixSummary.applied} conservative LSP warning quickfix(es)`, "info");
|
|
362
513
|
}
|
|
363
514
|
}
|
|
515
|
+
else {
|
|
516
|
+
dbg("agent_end actionable_warnings_autofix: fresh report, 0 autofix-eligible warnings, skipping");
|
|
517
|
+
}
|
|
364
518
|
}
|
|
365
519
|
}
|
|
520
|
+
logLatency({
|
|
521
|
+
type: "phase",
|
|
522
|
+
toolName: "agent_end",
|
|
523
|
+
filePath: ctxCwd ?? runtime.projectRoot,
|
|
524
|
+
phase: "agent_end_deferred_mutation_drain",
|
|
525
|
+
durationMs: Date.now() - startedAt,
|
|
526
|
+
metadata: {
|
|
527
|
+
autofixRecords: autofixRecords.length,
|
|
528
|
+
formatRecords: formatRecords.length,
|
|
529
|
+
coalescedPaths: records.length,
|
|
530
|
+
requeuedKinds: [...requeuedKinds].sort((a, b) => (a < b ? -1 : a > b ? 1 : 0)),
|
|
531
|
+
},
|
|
532
|
+
});
|
|
366
533
|
logLatency({
|
|
367
534
|
type: "tool_result",
|
|
368
535
|
toolName: "agent_end",
|
|
@@ -377,6 +544,19 @@ export async function handleAgentEnd({ ctxCwd, getFlag, getFlagSource, notify, d
|
|
|
377
544
|
skipped: summary.skipped.length,
|
|
378
545
|
},
|
|
379
546
|
});
|
|
547
|
+
logLatency({
|
|
548
|
+
type: "phase",
|
|
549
|
+
toolName: "agent_end",
|
|
550
|
+
filePath: ctxCwd ?? runtime.projectRoot,
|
|
551
|
+
phase: "agent_end_deferred_format_done",
|
|
552
|
+
durationMs: Date.now() - startedAt,
|
|
553
|
+
metadata: {
|
|
554
|
+
formatted: summary.formatted,
|
|
555
|
+
changed: summary.changed.length,
|
|
556
|
+
failed: summary.failed.length,
|
|
557
|
+
skipped: summary.skipped.length,
|
|
558
|
+
},
|
|
559
|
+
});
|
|
380
560
|
dbg(`agent_end deferred_format complete: formatted=${summary.formatted} changed=${summary.changed.length} failed=${summary.failed.length} skipped=${summary.skipped.length}`);
|
|
381
561
|
if (summary.failed.length > 0) {
|
|
382
562
|
notify(`pi-lens deferred format: ${summary.changed.length} changed, ${summary.failed.length} failed`, "warning");
|
|
@@ -1,31 +1,148 @@
|
|
|
1
|
-
|
|
1
|
+
import { provenanceStamp, validateAdvisoryProvenance, } from "./advisory-provenance.js";
|
|
2
|
+
import { logLatency } from "./latency-logger.js";
|
|
3
|
+
// Exported so the Stop-hook bin strips exactly what these bridges prepend.
|
|
4
|
+
export const AUTOMATION_FRAMING = "[pi-lens automated check â not a user request] ";
|
|
5
|
+
// #1432 review (S3b): a multi-file bash write can carry hundreds of changed
|
|
6
|
+
// paths, one `reasons` entry apiece â logging all of them shrinks the
|
|
7
|
+
// smells-rollup tail window (a fixed-size ring) to a handful of these
|
|
8
|
+
// records. Cap what this decision row carries; the full list is never
|
|
9
|
+
// needed for triage, only "how many and roughly what kind".
|
|
10
|
+
const MAX_LOGGED_REASONS = 8;
|
|
11
|
+
function boundedReasons(reasons) {
|
|
12
|
+
if (reasons.length <= MAX_LOGGED_REASONS)
|
|
13
|
+
return reasons;
|
|
14
|
+
return [
|
|
15
|
+
...reasons.slice(0, MAX_LOGGED_REASONS),
|
|
16
|
+
`+${reasons.length - MAX_LOGGED_REASONS} more`,
|
|
17
|
+
];
|
|
18
|
+
}
|
|
19
|
+
function logProvenanceDecision(validation, provenance, advisoryKind, cwd) {
|
|
20
|
+
logLatency({
|
|
21
|
+
type: "phase",
|
|
22
|
+
phase: "advisory_provenance_decision",
|
|
23
|
+
filePath: cwd,
|
|
24
|
+
durationMs: 0,
|
|
25
|
+
metadata: {
|
|
26
|
+
decision: validation.status === "current" ? "current" : "historical",
|
|
27
|
+
reasons: boundedReasons(validation.reasons),
|
|
28
|
+
changedPathCount: validation.changedPathCount,
|
|
29
|
+
provenanceStamp: provenanceStamp(provenance),
|
|
30
|
+
advisoryKind,
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
function historicalPrefix(provenance) {
|
|
35
|
+
return `Historical finding; workspace changed since capture; re-run to confirm. (${provenanceStamp(provenance)})`;
|
|
36
|
+
}
|
|
37
|
+
function historicalTestContent(content, provenance) {
|
|
38
|
+
return content.startsWith("[from a prior turn")
|
|
39
|
+
? content
|
|
40
|
+
: `${historicalPrefix(provenance)}\n\n${content}`;
|
|
41
|
+
}
|
|
42
|
+
function turnEndMessage(content, current, provenance) {
|
|
43
|
+
return {
|
|
44
|
+
role: "user",
|
|
45
|
+
content: current
|
|
46
|
+
? `${AUTOMATION_FRAMING}Address đ´ blockers before continuing; âšī¸ advisories are informational only.\n\n${content}`
|
|
47
|
+
: `${AUTOMATION_FRAMING}${historicalPrefix(provenance)}\n\n${content}`,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/** Read a turn-end finding without changing its durable delivery state. */
|
|
51
|
+
export function peekTurnEndFindings(cacheManager, cwd, runtime, logDelivery = false) {
|
|
2
52
|
const findings = cacheManager.readCache("turn-end-findings", cwd);
|
|
3
|
-
if (!findings?.data?.content)
|
|
53
|
+
if (!findings?.data?.content || findings.data.consumed === true)
|
|
54
|
+
return;
|
|
55
|
+
const validation = validateAdvisoryProvenance(findings.data, cwd, runtime);
|
|
56
|
+
if (logDelivery)
|
|
57
|
+
logProvenanceDecision(validation, findings.data.provenance, "turn-end", cwd);
|
|
58
|
+
if (validation.allFilesDeleted)
|
|
4
59
|
return;
|
|
5
|
-
cacheManager.writeCache("turn-end-findings", null, cwd);
|
|
6
60
|
return {
|
|
7
|
-
messages: [
|
|
8
|
-
{
|
|
9
|
-
role: "user",
|
|
10
|
-
content: `[pi-lens automated check â not a user request] Address đ´ blockers before continuing; âšī¸ advisories are informational only.\n\n${findings.data.content}`,
|
|
11
|
-
},
|
|
12
|
-
],
|
|
61
|
+
messages: [turnEndMessage(findings.data.content, validation.status === "current", findings.data.provenance)],
|
|
13
62
|
};
|
|
14
63
|
}
|
|
15
|
-
export function
|
|
64
|
+
export function consumeTurnEndFindings(cacheManager, cwd, runtime) {
|
|
65
|
+
const findings = cacheManager.readCache("turn-end-findings", cwd);
|
|
66
|
+
if (!findings?.data?.content || findings.data.consumed === true)
|
|
67
|
+
return;
|
|
68
|
+
const validation = validateAdvisoryProvenance(findings.data, cwd, runtime);
|
|
69
|
+
logProvenanceDecision(validation, findings.data.provenance, "turn-end", cwd);
|
|
70
|
+
// A blocker record is also the opt-in commit gate's durable state. Mark the
|
|
71
|
+
// context message consumed without deleting the record; clean/advisory-only
|
|
72
|
+
// records retain the historical consume-and-clear behavior.
|
|
73
|
+
if (findings.data.hasBlockers === true &&
|
|
74
|
+
typeof findings.data.sessionId === "string") {
|
|
75
|
+
cacheManager.writeCache("turn-end-findings", { ...findings.data, consumed: true }, cwd);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
cacheManager.clearCache("turn-end-findings", cwd);
|
|
79
|
+
}
|
|
80
|
+
if (validation.allFilesDeleted)
|
|
81
|
+
return;
|
|
82
|
+
return {
|
|
83
|
+
messages: [turnEndMessage(findings.data.content, validation.status === "current", findings.data.provenance)],
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
/** Read test findings without consuming them; used by acknowledged IPC delivery. */
|
|
87
|
+
export function peekTestFindings(cacheManager, cwd, runtime, logDelivery = false) {
|
|
16
88
|
const findings = cacheManager.readCache("test-runner-findings", cwd);
|
|
17
89
|
if (!findings?.data?.content)
|
|
18
90
|
return;
|
|
19
|
-
|
|
91
|
+
const validation = validateAdvisoryProvenance(findings.data, cwd, runtime);
|
|
92
|
+
if (logDelivery)
|
|
93
|
+
logProvenanceDecision(validation, findings.data.provenance, "test-findings", cwd);
|
|
94
|
+
if (validation.allFilesDeleted)
|
|
95
|
+
return;
|
|
96
|
+
const current = validation.status === "current";
|
|
20
97
|
return {
|
|
21
98
|
messages: [
|
|
22
99
|
{
|
|
23
100
|
role: "user",
|
|
24
|
-
content:
|
|
101
|
+
content: current
|
|
102
|
+
? `${AUTOMATION_FRAMING}Test failures detected last turn â fix before continuing:\n\n${findings.data.content}`
|
|
103
|
+
: `${AUTOMATION_FRAMING}${historicalTestContent(findings.data.content, findings.data.provenance)}`,
|
|
25
104
|
},
|
|
26
105
|
],
|
|
27
106
|
};
|
|
28
107
|
}
|
|
108
|
+
export function consumeTestFindings(cacheManager, cwd, runtime) {
|
|
109
|
+
const record = cacheManager.readCache("test-runner-findings", cwd);
|
|
110
|
+
if (!record?.data?.content)
|
|
111
|
+
return;
|
|
112
|
+
const findings = peekTestFindings(cacheManager, cwd, runtime, true);
|
|
113
|
+
if (!findings)
|
|
114
|
+
return;
|
|
115
|
+
// Retire the content but PRESERVE the generation high-water mark: nulling
|
|
116
|
+
// the whole slot would let a still-in-flight OLDER batch see `undefined`,
|
|
117
|
+
// pass the strictly-greater suppression check, and resurrect a consumed
|
|
118
|
+
// one-shot advisory with stale results. An empty-content record peeks as
|
|
119
|
+
// undelivered while keeping late-generation ordering intact.
|
|
120
|
+
const priorGeneration = cacheManager.readCache("test-runner-findings", cwd)?.data?.testRunGeneration;
|
|
121
|
+
cacheManager.writeCache("test-runner-findings", { content: "", testRunGeneration: priorGeneration }, cwd);
|
|
122
|
+
return findings;
|
|
123
|
+
}
|
|
124
|
+
/** Complete an acknowledged MCP delivery without re-validating or re-rendering it. */
|
|
125
|
+
export function acknowledgeTurnEndFindings(cacheManager, cwd) {
|
|
126
|
+
const findings = cacheManager.readCache("turn-end-findings", cwd);
|
|
127
|
+
if (!findings?.data?.content || findings.data.consumed === true)
|
|
128
|
+
return;
|
|
129
|
+
if (findings.data.hasBlockers === true && typeof findings.data.sessionId === "string") {
|
|
130
|
+
cacheManager.writeCache("turn-end-findings", { ...findings.data, consumed: true }, cwd);
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
cacheManager.clearCache("turn-end-findings", cwd);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
export function acknowledgeTestFindings(cacheManager, cwd) {
|
|
137
|
+
const findings = cacheManager.readCache("test-runner-findings", cwd);
|
|
138
|
+
if (!findings?.data?.content)
|
|
139
|
+
return;
|
|
140
|
+
// Same high-water-mark preservation as consumeTestFindings.
|
|
141
|
+
cacheManager.writeCache("test-runner-findings", {
|
|
142
|
+
content: "",
|
|
143
|
+
testRunGeneration: findings.data.testRunGeneration,
|
|
144
|
+
}, cwd);
|
|
145
|
+
}
|
|
29
146
|
export function consumeSessionStartGuidance(cacheManager, cwd) {
|
|
30
147
|
const guidance = cacheManager.readCache("session-start-guidance", cwd);
|
|
31
148
|
if (!guidance?.data?.content)
|