@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
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { randomBytes } from "node:crypto";
|
|
2
|
+
import * as fs from "node:fs";
|
|
2
3
|
import * as path from "node:path";
|
|
4
|
+
import { logCascade } from "./cascade-logger.js";
|
|
3
5
|
import { normalizeMapKey } from "./path-utils.js";
|
|
6
|
+
import { PathKeyedMap } from "./path-keyed-map.js";
|
|
4
7
|
import { ReadGuard } from "./read-guard.js";
|
|
5
8
|
import { RUNTIME_CONFIG } from "./runtime-config.js";
|
|
6
9
|
import { TurnSummaryCollector } from "./turn-summary.js";
|
|
10
|
+
import { deriveProviderFromModelId } from "./model-provider.js";
|
|
7
11
|
export class RuntimeCoordinator {
|
|
8
12
|
_projectRoot = normalizeMapKey(process.cwd());
|
|
9
13
|
_sessionGeneration = 0;
|
|
@@ -23,7 +27,9 @@ export class RuntimeCoordinator {
|
|
|
23
27
|
coldSnapshotTouches: 0,
|
|
24
28
|
};
|
|
25
29
|
_complexityBaselines = new Map();
|
|
26
|
-
_fixedThisTurn = new
|
|
30
|
+
_fixedThisTurn = new PathKeyedMap(normalizeMapKey);
|
|
31
|
+
_writtenThisTurn = new PathKeyedMap(normalizeMapKey);
|
|
32
|
+
_autofixDemotedThisTurn = new PathKeyedMap(normalizeMapKey);
|
|
27
33
|
_reportedThisTurn = new Set();
|
|
28
34
|
_projectRulesScan = {
|
|
29
35
|
rules: [],
|
|
@@ -33,6 +39,19 @@ export class RuntimeCoordinator {
|
|
|
33
39
|
_lifecycleReason;
|
|
34
40
|
_hasStableSessionId = false;
|
|
35
41
|
_telemetryModel = "unknown";
|
|
42
|
+
// Raw model/provider identity, separate from the combined `provider/model`
|
|
43
|
+
// display string above — worklog/disposition attribution (#1448) wants the
|
|
44
|
+
// two fields apart, blank when the host never supplied them. `_telemetryProvider`
|
|
45
|
+
// is the explicit host value when given, else derived from the model id
|
|
46
|
+
// (deriveProviderFromModelId, blank on ambiguity — never guessed).
|
|
47
|
+
_telemetryModelId = "";
|
|
48
|
+
_telemetryProvider = "";
|
|
49
|
+
// True once a host has supplied an explicit provider this session. An
|
|
50
|
+
// explicit provider is never downgraded by a derivation from a later
|
|
51
|
+
// model-only call; a DERIVED provider, by contrast, is re-derived on
|
|
52
|
+
// every model-only call so a mid-session model switch (e.g. gpt-5-mini →
|
|
53
|
+
// claude-sonnet-4-5) doesn't leave a stale provider from the old model.
|
|
54
|
+
_telemetryProviderIsExplicit = false;
|
|
36
55
|
_turnIndex = 0;
|
|
37
56
|
_writeIndex = 0;
|
|
38
57
|
_projectSeq = 0;
|
|
@@ -45,12 +64,13 @@ export class RuntimeCoordinator {
|
|
|
45
64
|
_fileLastProjectSeq = new Map();
|
|
46
65
|
_gitGuardHasBlockers = false;
|
|
47
66
|
_gitGuardSummary = "";
|
|
67
|
+
_gitGuardCacheUnknownReason;
|
|
48
68
|
callGraph = null;
|
|
49
69
|
wordIndex = null;
|
|
50
70
|
_readGuard = null;
|
|
51
|
-
|
|
71
|
+
_pendingDeferredMutations = new PathKeyedMap(normalizeMapKey);
|
|
52
72
|
_lspReadWarmState = new Map();
|
|
53
|
-
_pendingInlineBlockers = new
|
|
73
|
+
_pendingInlineBlockers = new PathKeyedMap(normalizeMapKey);
|
|
54
74
|
_actionableWarningsThisTurn = new Map();
|
|
55
75
|
_codeQualityWarningsThisTurn = new Map();
|
|
56
76
|
// #484: opt-in per-RUN summary of diagnostics/autofixes/formats,
|
|
@@ -75,10 +95,15 @@ export class RuntimeCoordinator {
|
|
|
75
95
|
coldSnapshotTouches: 0,
|
|
76
96
|
};
|
|
77
97
|
this._fixedThisTurn.clear();
|
|
98
|
+
this._writtenThisTurn.clear();
|
|
99
|
+
this._autofixDemotedThisTurn.clear();
|
|
78
100
|
this._reportedThisTurn.clear();
|
|
79
101
|
this._telemetrySessionId = `lens-${Date.now().toString(36)}-${randomBytes(4).toString("hex")}`;
|
|
80
102
|
this._hasStableSessionId = false;
|
|
81
103
|
this._telemetryModel = "unknown";
|
|
104
|
+
this._telemetryModelId = "";
|
|
105
|
+
this._telemetryProvider = "";
|
|
106
|
+
this._telemetryProviderIsExplicit = false;
|
|
82
107
|
this._turnIndex = 0;
|
|
83
108
|
this._writeIndex = 0;
|
|
84
109
|
this._projectSeq = 0;
|
|
@@ -87,8 +112,9 @@ export class RuntimeCoordinator {
|
|
|
87
112
|
this._fileLastProjectSeq.clear();
|
|
88
113
|
this._gitGuardHasBlockers = false;
|
|
89
114
|
this._gitGuardSummary = "";
|
|
115
|
+
this._gitGuardCacheUnknownReason = undefined;
|
|
90
116
|
this._readGuard = null;
|
|
91
|
-
this.
|
|
117
|
+
this._pendingDeferredMutations.clear();
|
|
92
118
|
this._lspReadWarmState.clear();
|
|
93
119
|
this._pendingInlineBlockers.clear();
|
|
94
120
|
this._actionableWarningsThisTurn.clear();
|
|
@@ -107,8 +133,12 @@ export class RuntimeCoordinator {
|
|
|
107
133
|
this._cascadeSessionStats.coldSnapshotTouches += coldSnapshotTouches;
|
|
108
134
|
}
|
|
109
135
|
updateGitGuardStatus(hasBlockers, output) {
|
|
110
|
-
|
|
111
|
-
|
|
136
|
+
// The status is an aggregate over the current per-file map. A clean B
|
|
137
|
+
// result must not erase an unresolved A result; the pipeline records/clears
|
|
138
|
+
// the edited file immediately before this method runs.
|
|
139
|
+
this._gitGuardHasBlockers =
|
|
140
|
+
hasBlockers || this.getInlineBlockersSnapshot().length > 0;
|
|
141
|
+
if (!this._gitGuardHasBlockers) {
|
|
112
142
|
this._gitGuardSummary = "";
|
|
113
143
|
return;
|
|
114
144
|
}
|
|
@@ -116,7 +146,10 @@ export class RuntimeCoordinator {
|
|
|
116
146
|
.split("\n")
|
|
117
147
|
.map((line) => line.trim())
|
|
118
148
|
.find((line) => line.length > 0);
|
|
119
|
-
|
|
149
|
+
const summaries = this.getInlineBlockersSnapshot()
|
|
150
|
+
.map((entry) => entry.summary.trim())
|
|
151
|
+
.filter(Boolean);
|
|
152
|
+
this._gitGuardSummary = (summaries[0] ?? firstLine ?? "Unresolved blockers detected").slice(0, 160);
|
|
120
153
|
}
|
|
121
154
|
get gitGuardHasBlockers() {
|
|
122
155
|
return this._gitGuardHasBlockers;
|
|
@@ -124,14 +157,48 @@ export class RuntimeCoordinator {
|
|
|
124
157
|
get gitGuardSummary() {
|
|
125
158
|
return this._gitGuardSummary;
|
|
126
159
|
}
|
|
160
|
+
markGitGuardCacheUnknown(reason) {
|
|
161
|
+
this._gitGuardCacheUnknownReason = reason;
|
|
162
|
+
}
|
|
163
|
+
clearGitGuardCacheUnknown() {
|
|
164
|
+
this._gitGuardCacheUnknownReason = undefined;
|
|
165
|
+
}
|
|
166
|
+
get gitGuardCacheUnknownReason() {
|
|
167
|
+
return this._gitGuardCacheUnknownReason;
|
|
168
|
+
}
|
|
127
169
|
beginTurn() {
|
|
128
|
-
|
|
170
|
+
// #1443: runs sitting here at turn_start were appended AFTER the last
|
|
171
|
+
// turn_end drained them (consumeCascadeRuns) — the quiet-window reconcile's
|
|
172
|
+
// late re-injection (`onResolvedFound`, clients/lsp/cascade-tier.ts) lands
|
|
173
|
+
// in exactly that window. Wiping them dead-ended that delivery path: the
|
|
174
|
+
// finding was computed, formatted, appended, and then deleted before any
|
|
175
|
+
// turn_end could render it. Carry them into THIS turn instead, exactly
|
|
176
|
+
// once: `carriedTurns` is stamped on the way through and a run that the
|
|
177
|
+
// next turn_end still did not consume is dropped here with a log line
|
|
178
|
+
// rather than queued forever (a stale finding must not outlive the state
|
|
179
|
+
// it describes, and an unbounded queue would replay it every turn).
|
|
180
|
+
this._cascadeRuns = this._cascadeRuns.flatMap((run) => {
|
|
181
|
+
const carriedTurns = (run.carriedTurns ?? 0) + 1;
|
|
182
|
+
if (carriedTurns > 1) {
|
|
183
|
+
logCascade({
|
|
184
|
+
phase: "cascade_carry_over_drop",
|
|
185
|
+
filePath: run.filePath,
|
|
186
|
+
neighborCount: run.neighborCount,
|
|
187
|
+
diagnosticCount: run.diagnosticCount,
|
|
188
|
+
metadata: { carriedTurns, turnIndex: this._turnIndex },
|
|
189
|
+
});
|
|
190
|
+
return [];
|
|
191
|
+
}
|
|
192
|
+
return [{ ...run, carriedTurns }];
|
|
193
|
+
});
|
|
129
194
|
// _pendingCascadeRuns is deliberately NOT cleared here: a cascade compute
|
|
130
195
|
// still in flight past last turn_end's settle cap (fresh graph builds have
|
|
131
196
|
// measured up to ~19s) must surface on the NEXT turn_end, not be dropped —
|
|
132
197
|
// pre-#450 those findings were always awaited, never lost. Session reset
|
|
133
198
|
// still clears it.
|
|
134
|
-
|
|
199
|
+
// Inline blockers are session-scoped per-file state. They are cleared only
|
|
200
|
+
// when that file is re-analyzed clean or the session resets; a new turn must
|
|
201
|
+
// not let a clean unrelated file erase an unresolved blocker.
|
|
135
202
|
this._actionableWarningsThisTurn.clear();
|
|
136
203
|
this._codeQualityWarningsThisTurn.clear();
|
|
137
204
|
// _turnSummary is deliberately NOT cleared here (#484 rework): the
|
|
@@ -144,6 +211,25 @@ export class RuntimeCoordinator {
|
|
|
144
211
|
this._turnIndex += 1;
|
|
145
212
|
this._writeIndex = 0;
|
|
146
213
|
this._reportedThisTurn.clear();
|
|
214
|
+
this._writtenThisTurn.clear();
|
|
215
|
+
this._autofixDemotedThisTurn.clear();
|
|
216
|
+
}
|
|
217
|
+
/** Atomically records write/edit ordering before debounce can coalesce it. */
|
|
218
|
+
recordMutationToolReceipt(filePath, toolName) {
|
|
219
|
+
if (toolName === "write") {
|
|
220
|
+
this._writtenThisTurn.set(filePath, true);
|
|
221
|
+
}
|
|
222
|
+
else if (this._writtenThisTurn.has(filePath)) {
|
|
223
|
+
this._autofixDemotedThisTurn.set(filePath, true);
|
|
224
|
+
// A later edit establishes a new final state that must be eligible for
|
|
225
|
+
// the deferred pass even if the preceding write was fixed immediately.
|
|
226
|
+
this._fixedThisTurn.delete(filePath);
|
|
227
|
+
}
|
|
228
|
+
return {
|
|
229
|
+
autofixMode: toolName === "edit" || this._autofixDemotedThisTurn.has(filePath)
|
|
230
|
+
? "deferred"
|
|
231
|
+
: "immediate",
|
|
232
|
+
};
|
|
147
233
|
}
|
|
148
234
|
get reportedThisTurn() {
|
|
149
235
|
return this._reportedThisTurn;
|
|
@@ -170,6 +256,23 @@ export class RuntimeCoordinator {
|
|
|
170
256
|
else if (provider) {
|
|
171
257
|
this._telemetryModel = provider;
|
|
172
258
|
}
|
|
259
|
+
if (model)
|
|
260
|
+
this._telemetryModelId = model;
|
|
261
|
+
if (provider) {
|
|
262
|
+
this._telemetryProvider = provider;
|
|
263
|
+
this._telemetryProviderIsExplicit = true;
|
|
264
|
+
}
|
|
265
|
+
else if (model && !this._telemetryProviderIsExplicit) {
|
|
266
|
+
// No explicit provider has ever been reported this session, so the
|
|
267
|
+
// provider is (still) a derivation — re-derive it from the CURRENT
|
|
268
|
+
// model id every time. Without this, a stale derived provider from
|
|
269
|
+
// an earlier model would survive a mid-session model switch (e.g.
|
|
270
|
+
// gpt-5-mini → claude-sonnet-4-5 with no explicit provider on
|
|
271
|
+
// either call) because the old "has any provider ever been set"
|
|
272
|
+
// guard treated the derived value as sticky. An explicit provider,
|
|
273
|
+
// once set, is never touched here regardless of later model calls.
|
|
274
|
+
this._telemetryProvider = deriveProviderFromModelId(model);
|
|
275
|
+
}
|
|
173
276
|
}
|
|
174
277
|
get telemetrySessionId() {
|
|
175
278
|
return this._telemetrySessionId;
|
|
@@ -198,6 +301,17 @@ export class RuntimeCoordinator {
|
|
|
198
301
|
get telemetryModel() {
|
|
199
302
|
return this._telemetryModel;
|
|
200
303
|
}
|
|
304
|
+
/** Raw model id (never the combined `provider/model` display string), blank
|
|
305
|
+
* when the host hasn't reported one this session. Worklog/disposition
|
|
306
|
+
* attribution (#1448) reads this, not {@link telemetryModel}. */
|
|
307
|
+
get telemetryModelId() {
|
|
308
|
+
return this._telemetryModelId;
|
|
309
|
+
}
|
|
310
|
+
/** Explicit host-reported provider, or a conservative derivation from the
|
|
311
|
+
* model id (see clients/model-provider.ts), blank when neither is known. */
|
|
312
|
+
get telemetryProviderId() {
|
|
313
|
+
return this._telemetryProvider;
|
|
314
|
+
}
|
|
201
315
|
get turnIndex() {
|
|
202
316
|
return this._turnIndex;
|
|
203
317
|
}
|
|
@@ -356,6 +470,26 @@ export class RuntimeCoordinator {
|
|
|
356
470
|
this._cascadeRuns = [];
|
|
357
471
|
return runs;
|
|
358
472
|
}
|
|
473
|
+
/**
|
|
474
|
+
* R1 (#1443 follow-up): non-destructive peek used by turn_end's read-only
|
|
475
|
+
* fast path. A carried cascade run (or one still in flight) represents a
|
|
476
|
+
* DELIVERY OPPORTUNITY, not turn activity — an agent that answers a question
|
|
477
|
+
* without editing anything must still get yesterday's late finding. Before
|
|
478
|
+
* this, the files-empty early return skipped `settleCascadeRuns` /
|
|
479
|
+
* `consumeCascadeRuns` entirely on a read-only turn, so `beginTurn`'s next
|
|
480
|
+
* carry pass saw the run as having survived a turn_start with no offsetting
|
|
481
|
+
* drain and dropped it — burning the one-turn carry allowance on a turn that
|
|
482
|
+
* never had a chance to deliver.
|
|
483
|
+
*/
|
|
484
|
+
hasCascadeRuns() {
|
|
485
|
+
// Carried, ALREADY-BUILT runs only. Pending (still-settling) computes are
|
|
486
|
+
// deliberately excluded: a read-only turn that fell through for a pending
|
|
487
|
+
// run would block on the full settle cap — every turn, forever, when the
|
|
488
|
+
// compute never resolves (re-review finding F1). A pending run loses
|
|
489
|
+
// nothing by waiting: settleCascadeRuns re-parks it and the next turn
|
|
490
|
+
// that actually settles it delivers it.
|
|
491
|
+
return this._cascadeRuns.length > 0;
|
|
492
|
+
}
|
|
359
493
|
recordInlineBlockers(filePath, summary) {
|
|
360
494
|
this._pendingInlineBlockers.set(path.resolve(filePath), {
|
|
361
495
|
filePath,
|
|
@@ -365,8 +499,45 @@ export class RuntimeCoordinator {
|
|
|
365
499
|
clearInlineBlockers(filePath) {
|
|
366
500
|
this._pendingInlineBlockers.delete(path.resolve(filePath));
|
|
367
501
|
}
|
|
502
|
+
reconcileInlineBlockers() {
|
|
503
|
+
// Rebuild, never delete-in-place: `PathKeyedMap.delete()` re-normalizes
|
|
504
|
+
// the key, and `normalizeMapKey` realpaths a live file but lowercases
|
|
505
|
+
// the tail of a deleted one — so on Windows a mixed-case filename gets
|
|
506
|
+
// a DIFFERENT delete-time key than its set-time key and the delete
|
|
507
|
+
// misses (#1245, verified live: `MyCase.ts` survived reconcile).
|
|
508
|
+
// Existence-checking the display path and rebuilding survivors avoids
|
|
509
|
+
// the key-mismatch entirely; live survivors re-set to identical keys
|
|
510
|
+
// (both realpath), so only the stale entries are dropped.
|
|
511
|
+
const survivors = [];
|
|
512
|
+
for (const [displayPath, value] of this._pendingInlineBlockers.entries()) {
|
|
513
|
+
if (fs.existsSync(displayPath))
|
|
514
|
+
survivors.push([displayPath, value]);
|
|
515
|
+
}
|
|
516
|
+
if (survivors.length !== this._pendingInlineBlockers.size) {
|
|
517
|
+
this._pendingInlineBlockers.clear();
|
|
518
|
+
for (const [displayPath, value] of survivors) {
|
|
519
|
+
this._pendingInlineBlockers.set(displayPath, value);
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
/**
|
|
524
|
+
* Stale-entry reconcile (#1245): a blocker recorded for a file that has
|
|
525
|
+
* since been deleted can never be cleared — `clearInlineBlockers` fires
|
|
526
|
+
* only on a LATER dispatch of the same path, which a deleted file never
|
|
527
|
+
* gets. Every read of the blocker map (turn_end injection, git-guard
|
|
528
|
+
* size/summary, `syncGitGuardRecord`) therefore drops entries whose file no
|
|
529
|
+
* longer exists on disk: a blocker for a deleted file is stale by
|
|
530
|
+
* definition (the agent cannot fix it), so it must not re-surface every
|
|
531
|
+
* turn or gate a commit. The map is tiny (per-turn blockers) and reads are
|
|
532
|
+
* bounded (once per turn_end / tool_result), so the probe cost is
|
|
533
|
+
* negligible.
|
|
534
|
+
*/
|
|
535
|
+
getInlineBlockersSnapshot() {
|
|
536
|
+
this.reconcileInlineBlockers();
|
|
537
|
+
return [...this._pendingInlineBlockers.values()];
|
|
538
|
+
}
|
|
368
539
|
consumeInlineBlockers() {
|
|
369
|
-
const entries =
|
|
540
|
+
const entries = this.getInlineBlockersSnapshot();
|
|
370
541
|
this._pendingInlineBlockers.clear();
|
|
371
542
|
return entries;
|
|
372
543
|
}
|
|
@@ -403,7 +574,19 @@ export class RuntimeCoordinator {
|
|
|
403
574
|
return this._complexityBaselines;
|
|
404
575
|
}
|
|
405
576
|
get fixedThisTurn() {
|
|
406
|
-
|
|
577
|
+
// Self-referencing local so chained add() returns the same facade
|
|
578
|
+
// instead of re-entering this getter and allocating a new one per call
|
|
579
|
+
// (sonar S7725).
|
|
580
|
+
const facade = {
|
|
581
|
+
add: (filePath) => {
|
|
582
|
+
this._fixedThisTurn.set(filePath, true);
|
|
583
|
+
return facade;
|
|
584
|
+
},
|
|
585
|
+
has: (filePath) => this._fixedThisTurn.has(filePath),
|
|
586
|
+
delete: (filePath) => this._fixedThisTurn.delete(filePath),
|
|
587
|
+
clear: () => this._fixedThisTurn.clear(),
|
|
588
|
+
};
|
|
589
|
+
return facade;
|
|
407
590
|
}
|
|
408
591
|
get projectRulesScan() {
|
|
409
592
|
return this._projectRulesScan;
|
|
@@ -416,39 +599,47 @@ export class RuntimeCoordinator {
|
|
|
416
599
|
return this._readGuard;
|
|
417
600
|
}
|
|
418
601
|
/**
|
|
419
|
-
* Queue `filePath`
|
|
420
|
-
* when this call created a
|
|
421
|
-
*
|
|
422
|
-
*
|
|
423
|
-
* the same already-queued file before `agent_end` don't spam the bus.
|
|
602
|
+
* Queue one mutation kind for `filePath` at `agent_end`. Returns `true`
|
|
603
|
+
* when this call created a pending entry or added a new kind, and `false`
|
|
604
|
+
* for a same-kind re-touch. Callers publish each kind's first transition
|
|
605
|
+
* without spamming repeated edits before `agent_end`.
|
|
424
606
|
*/
|
|
425
|
-
|
|
607
|
+
deferMutation(filePath, cwd, toolName, turnStateCwd, kind, ownerSessionId) {
|
|
426
608
|
const key = path.resolve(filePath);
|
|
427
609
|
const now = Date.now();
|
|
428
|
-
const existing = this.
|
|
610
|
+
const existing = this._pendingDeferredMutations.get(key);
|
|
429
611
|
if (existing) {
|
|
612
|
+
const addedKind = !existing.kinds.has(kind);
|
|
430
613
|
existing.lastTouchedAt = now;
|
|
431
614
|
existing.cwd = cwd;
|
|
432
615
|
existing.turnStateCwd = turnStateCwd;
|
|
433
616
|
existing.toolNames.add(toolName);
|
|
617
|
+
existing.kinds.add(kind);
|
|
434
618
|
existing.queuedTurnIndex = this._turnIndex;
|
|
435
619
|
existing.ownerSessionId = ownerSessionId;
|
|
436
|
-
return
|
|
620
|
+
return addedKind;
|
|
437
621
|
}
|
|
438
|
-
this.
|
|
622
|
+
this._pendingDeferredMutations.set(key, {
|
|
439
623
|
filePath: key,
|
|
440
624
|
cwd,
|
|
441
625
|
turnStateCwd,
|
|
442
626
|
firstTouchedAt: now,
|
|
443
627
|
lastTouchedAt: now,
|
|
444
628
|
toolNames: new Set([toolName]),
|
|
629
|
+
kinds: new Set([kind]),
|
|
445
630
|
queuedTurnIndex: this._turnIndex,
|
|
446
631
|
ownerSessionId,
|
|
447
632
|
});
|
|
448
633
|
return true;
|
|
449
634
|
}
|
|
635
|
+
deferFormat(filePath, cwd, toolName, turnStateCwd, ownerSessionId) {
|
|
636
|
+
return this.deferMutation(filePath, cwd, toolName, turnStateCwd, "format", ownerSessionId);
|
|
637
|
+
}
|
|
450
638
|
get pendingDeferredFormatCount() {
|
|
451
|
-
return this.
|
|
639
|
+
return this._pendingDeferredMutations.size;
|
|
640
|
+
}
|
|
641
|
+
get pendingDeferredMutationCount() {
|
|
642
|
+
return this._pendingDeferredMutations.size;
|
|
452
643
|
}
|
|
453
644
|
/**
|
|
454
645
|
* Legacy unconditional drain — still exposed for any caller that
|
|
@@ -456,8 +647,8 @@ export class RuntimeCoordinator {
|
|
|
456
647
|
* flush call sites should prefer {@link claimDeferredFormatFiles}.
|
|
457
648
|
*/
|
|
458
649
|
consumeDeferredFormatFiles() {
|
|
459
|
-
const records = [...this.
|
|
460
|
-
this.
|
|
650
|
+
const records = [...this._pendingDeferredMutations.values()];
|
|
651
|
+
this._pendingDeferredMutations.clear();
|
|
461
652
|
return records;
|
|
462
653
|
}
|
|
463
654
|
/**
|
|
@@ -481,25 +672,50 @@ export class RuntimeCoordinator {
|
|
|
481
672
|
const claimed = [];
|
|
482
673
|
const staleClaimed = [];
|
|
483
674
|
const deferredToOwner = [];
|
|
484
|
-
for (const [key, record] of this.
|
|
675
|
+
for (const [key, record] of this._pendingDeferredMutations) {
|
|
485
676
|
const sameSession = record.ownerSessionId === undefined ||
|
|
486
677
|
currentSessionId === undefined ||
|
|
487
678
|
record.ownerSessionId === currentSessionId;
|
|
488
679
|
if (sameSession) {
|
|
489
680
|
claimed.push(record);
|
|
490
|
-
this.
|
|
681
|
+
this._pendingDeferredMutations.delete(key);
|
|
491
682
|
continue;
|
|
492
683
|
}
|
|
493
684
|
const age = now - record.lastTouchedAt;
|
|
494
685
|
if (age > staleAfterMs) {
|
|
495
686
|
staleClaimed.push(record);
|
|
496
|
-
this.
|
|
687
|
+
this._pendingDeferredMutations.delete(key);
|
|
497
688
|
continue;
|
|
498
689
|
}
|
|
499
690
|
deferredToOwner.push(record);
|
|
500
691
|
}
|
|
501
692
|
return { claimed, staleClaimed, deferredToOwner };
|
|
502
693
|
}
|
|
694
|
+
/** Return claimed records that were never started by an aborted drain. */
|
|
695
|
+
requeueDeferredFormatFiles(records) {
|
|
696
|
+
for (const record of records) {
|
|
697
|
+
const key = path.resolve(record.filePath);
|
|
698
|
+
const existing = this._pendingDeferredMutations.get(key);
|
|
699
|
+
if (existing) {
|
|
700
|
+
for (const kind of record.kinds)
|
|
701
|
+
existing.kinds.add(kind);
|
|
702
|
+
for (const toolName of record.toolNames)
|
|
703
|
+
existing.toolNames.add(toolName);
|
|
704
|
+
continue;
|
|
705
|
+
}
|
|
706
|
+
this._pendingDeferredMutations.set(key, {
|
|
707
|
+
...record,
|
|
708
|
+
kinds: new Set(record.kinds),
|
|
709
|
+
toolNames: new Set(record.toolNames),
|
|
710
|
+
});
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
claimDeferredMutations(currentSessionId, now, staleAfterMs) {
|
|
714
|
+
return this.claimDeferredFormatFiles(currentSessionId, now, staleAfterMs);
|
|
715
|
+
}
|
|
716
|
+
requeueDeferredMutations(records) {
|
|
717
|
+
this.requeueDeferredFormatFiles(records);
|
|
718
|
+
}
|
|
503
719
|
shouldWarmLspOnRead(filePath, maxAgeMs = 120_000) {
|
|
504
720
|
const state = this._lspReadWarmState.get(path.resolve(filePath));
|
|
505
721
|
if (!state)
|