pi-lens 4.1.2 → 4.1.4
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/CHANGELOG.md +1308 -0
- package/README.md +3 -0
- package/config/biome/core.jsonc +11 -2
- package/config/dependency-cruiser-eager-allowlist.json +91 -0
- package/dist/clients/actionable-warnings-logger.js +18 -3
- package/dist/clients/actionable-warnings.js +927 -80
- package/dist/clients/agent-behavior-client.js +13 -4
- package/dist/clients/ast-grep-client.js +136 -9
- package/dist/clients/ast-grep-rule-manager.js +60 -5
- package/dist/clients/ast-grep-tool-logger.js +2 -2
- package/dist/clients/availability-probe-flight.js +12 -0
- package/dist/clients/bash-file-access.js +1 -3
- package/dist/clients/biome-client.js +16 -2
- package/dist/clients/blocker-freshness.js +34 -0
- package/dist/clients/bootstrap.js +509 -73
- package/dist/clients/bounded-cache.js +152 -12
- package/dist/clients/bounded-telemetry.js +115 -23
- package/dist/clients/build-identity.js +95 -0
- package/dist/clients/bundled-resource-health.js +113 -0
- package/dist/clients/bus-events-logger.js +2 -2
- package/dist/clients/bus-publish.js +3 -0
- package/dist/clients/cache/rule-cache.js +33 -5
- package/dist/clients/cache-manager.js +105 -6
- package/dist/clients/cache-observability.js +46 -19
- package/dist/clients/cargo-manifest.js +422 -0
- package/dist/clients/cascade-logger.js +17 -3
- package/dist/clients/code-quality-warnings.js +13 -3
- package/dist/clients/complexity-client.js +16 -5
- package/dist/clients/config-core/deny.js +221 -0
- package/dist/clients/config-core/index.js +47 -0
- package/dist/clients/config-core/merge.js +357 -0
- package/dist/clients/config-core/normalize.js +340 -0
- package/dist/clients/config-core/process-spec.js +248 -0
- package/dist/clients/config-core/provenance.js +171 -0
- package/dist/clients/config-core/records.js +218 -0
- package/dist/clients/config-core/resolve.js +125 -0
- package/dist/clients/config-core/safe-object.js +78 -0
- package/dist/clients/config-core/schema.js +167 -0
- package/dist/clients/config-diagnostic-codes.js +281 -0
- package/dist/clients/config-locations.js +160 -0
- package/dist/clients/config-resolve.js +789 -0
- package/dist/clients/config-schema.js +197 -0
- package/dist/clients/config-warn.js +407 -0
- package/dist/clients/dead-code-client.js +33 -25
- package/dist/clients/dead-code-logger.js +2 -2
- package/dist/clients/deadline-utils.js +178 -0
- package/dist/clients/debug-handles.js +2 -2
- package/dist/clients/debug-heap.js +3 -3
- package/dist/clients/deferred-lsp-work.js +106 -0
- package/dist/clients/degradation-ledger.js +166 -8
- package/dist/clients/demoted-finding-render.js +14 -0
- package/dist/clients/dependency-checker.js +28 -22
- package/dist/clients/deps/minimatch.js +1 -1
- package/dist/clients/diagnostic-line-freshness.js +12 -9
- package/dist/clients/diagnostic-logger.js +14 -4
- package/dist/clients/dispatch/collect-later-tier.js +39 -0
- package/dist/clients/dispatch/dispatcher.js +304 -19
- package/dist/clients/dispatch/fact-store.js +328 -9
- package/dist/clients/dispatch/integration.js +214 -107
- package/dist/clients/dispatch/pending-runner-findings.js +87 -0
- package/dist/clients/dispatch/plan.js +21 -5
- package/dist/clients/dispatch/runners/actionlint.js +0 -1
- package/dist/clients/dispatch/runners/ast-grep-napi.js +550 -77
- package/dist/clients/dispatch/runners/biome-check.js +0 -1
- package/dist/clients/dispatch/runners/cpp-check.js +0 -1
- package/dist/clients/dispatch/runners/credo.js +0 -1
- package/dist/clients/dispatch/runners/cue-vet.js +0 -1
- package/dist/clients/dispatch/runners/dart-analyze.js +0 -1
- package/dist/clients/dispatch/runners/detekt.js +0 -1
- package/dist/clients/dispatch/runners/dotnet-build.js +0 -1
- package/dist/clients/dispatch/runners/elixir-check.js +0 -1
- package/dist/clients/dispatch/runners/eslint.js +5 -2
- package/dist/clients/dispatch/runners/fact-rules.js +0 -1
- package/dist/clients/dispatch/runners/fish-indent.js +0 -1
- package/dist/clients/dispatch/runners/gleam-check.js +0 -1
- package/dist/clients/dispatch/runners/go-vet.js +1 -3
- package/dist/clients/dispatch/runners/golangci-lint.js +0 -1
- package/dist/clients/dispatch/runners/hadolint.js +0 -1
- package/dist/clients/dispatch/runners/helm-lint.js +16 -4
- package/dist/clients/dispatch/runners/helm-render.js +54 -10
- package/dist/clients/dispatch/runners/htmlhint.js +0 -1
- package/dist/clients/dispatch/runners/index.js +1 -3
- package/dist/clients/dispatch/runners/javac.js +0 -1
- package/dist/clients/dispatch/runners/ktlint.js +0 -1
- package/dist/clients/dispatch/runners/lsp.js +37 -2
- package/dist/clients/dispatch/runners/markdownlint.js +4 -2
- package/dist/clients/dispatch/runners/mypy.js +0 -1
- package/dist/clients/dispatch/runners/oxlint.js +24 -22
- package/dist/clients/dispatch/runners/php-lint.js +0 -1
- package/dist/clients/dispatch/runners/phpstan.js +0 -1
- package/dist/clients/dispatch/runners/prisma-validate.js +0 -1
- package/dist/clients/dispatch/runners/psscriptanalyzer.js +4 -1
- package/dist/clients/dispatch/runners/pyright.js +7 -4
- package/dist/clients/dispatch/runners/rubocop.js +0 -1
- package/dist/clients/dispatch/runners/ruff.js +0 -1
- package/dist/clients/dispatch/runners/rust-clippy.js +9 -6
- package/dist/clients/dispatch/runners/shellcheck.js +0 -1
- package/dist/clients/dispatch/runners/shfmt.js +0 -1
- package/dist/clients/dispatch/runners/spellcheck.js +0 -1
- package/dist/clients/dispatch/runners/spotbugs.js +0 -1
- package/dist/clients/dispatch/runners/sqlfluff.js +0 -1
- package/dist/clients/dispatch/runners/stylelint.js +0 -1
- package/dist/clients/dispatch/runners/swiftlint.js +0 -1
- package/dist/clients/dispatch/runners/taplo.js +0 -1
- package/dist/clients/dispatch/runners/terragrunt.js +0 -1
- package/dist/clients/dispatch/runners/tflint.js +0 -1
- package/dist/clients/dispatch/runners/tree-sitter.js +0 -1
- package/dist/clients/dispatch/runners/trivy-config.js +0 -1
- package/dist/clients/dispatch/runners/utils/availability-policy.js +3 -0
- package/dist/clients/dispatch/runners/utils/diagnostic-parsers.js +3 -4
- package/dist/clients/dispatch/runners/utils/runner-helpers.js +270 -105
- package/dist/clients/dispatch/runners/utils/spawn-outcome.js +4 -0
- package/dist/clients/dispatch/runners/utils/tool-failure.js +19 -7
- package/dist/clients/dispatch/runners/utils/toolchain-availability.js +89 -26
- package/dist/clients/dispatch/runners/vale.js +0 -1
- package/dist/clients/dispatch/runners/yaml-rule-parser.js +51 -17
- package/dist/clients/dispatch/runners/yamllint.js +0 -1
- package/dist/clients/dispatch/runners/zig-check.js +0 -1
- package/dist/clients/disposition-logger.js +3 -3
- package/dist/clients/effective-config.js +403 -0
- package/dist/clients/error-class.js +23 -0
- package/dist/clients/event-loop-hold.js +274 -0
- package/dist/clients/event-loop-monitor.js +66 -1
- package/dist/clients/extension-log.js +2 -2
- package/dist/clients/feature-hints.js +2 -1
- package/dist/clients/file-time.js +6 -1
- package/dist/clients/file-utils.js +266 -13
- package/dist/clients/finding-delivery-gate.js +55 -13
- package/dist/clients/format-service.js +6 -1
- package/dist/clients/formatters.js +303 -104
- package/dist/clients/freshness-cadence.js +17 -0
- package/dist/clients/generated-artifacts.js +114 -19
- package/dist/clients/generation-guard.js +4 -9
- package/dist/clients/git-guard.js +198 -48
- package/dist/clients/git-tracked-ignore.js +32 -1
- package/dist/clients/go-client.js +39 -0
- package/dist/clients/govulncheck-client.js +5 -1
- package/dist/clients/gradle-ktfmt-style.js +252 -0
- package/dist/clients/gzip-stage-write.js +7 -0
- package/dist/clients/hashline-anchor.js +424 -0
- package/dist/clients/hook-budgets.js +76 -0
- package/dist/clients/host-edit-normalize.js +5 -2
- package/dist/clients/host-ports.js +1 -1
- package/dist/clients/installer/index.js +200 -84
- package/dist/clients/installer/managed-tool-refresh.js +3 -1
- package/dist/clients/instance-reaper.js +108 -243
- package/dist/clients/instance-registry-lock.js +145 -0
- package/dist/clients/instance-registry.js +435 -122
- package/dist/clients/jscpd-client.js +6 -1
- package/dist/clients/language-profile.js +4 -2
- package/dist/clients/language-registry.js +595 -0
- package/dist/clients/latency-logger.js +179 -3
- package/dist/clients/ledger-bounds.js +13 -0
- package/dist/clients/lens-config.js +141 -30
- package/dist/clients/lens-engine.js +30 -37
- package/dist/clients/lens-flag-registry.js +67 -6
- package/dist/clients/lens-map.js +3 -1
- package/dist/clients/log-cleanup.js +2 -2
- package/dist/clients/lsp/aggregation.js +3 -1
- package/dist/clients/lsp/cascade-tier.js +4 -0
- package/dist/clients/lsp/client.js +672 -49
- package/dist/clients/lsp/config.js +504 -156
- package/dist/clients/lsp/diagnostic-binding.js +10 -5
- package/dist/clients/lsp/edits.js +15 -2
- package/dist/clients/lsp/index.js +1179 -247
- package/dist/clients/lsp/jvm-runtime.js +5 -0
- package/dist/clients/lsp/language.js +18 -169
- package/dist/clients/lsp/launch.js +38 -9
- package/dist/clients/lsp/pending-aux-coverage.js +113 -12
- package/dist/clients/lsp/server.js +426 -160
- package/dist/clients/lsp/session-roots.js +192 -0
- package/dist/clients/lsp/spawn-history.js +2 -7
- package/dist/clients/lsp/tsserver-sync.js +9 -2
- package/dist/clients/lsp/workspace-diagnostics-cache.js +17 -7
- package/dist/clients/lsp/workspace-sweep-hold.js +32 -23
- package/dist/clients/lsp-mutation.js +179 -23
- package/dist/clients/map-with-concurrency.js +36 -0
- package/dist/clients/mcp/analyze.js +45 -10
- package/dist/clients/mcp/session.js +19 -17
- package/dist/clients/memory-sampler.js +28 -1
- package/dist/clients/message-end-attribution.js +30 -0
- package/dist/clients/metrics-history.js +21 -4
- package/dist/clients/middle-man-analysis.js +2 -4
- package/dist/clients/module-report.js +20 -45
- package/dist/clients/mutating-tool.js +651 -0
- package/dist/clients/mutation-attribution.js +368 -0
- package/dist/clients/mutation-bridge.js +240 -0
- package/dist/clients/ndjson-logger.js +247 -20
- package/dist/clients/observed-mutation-sources.js +101 -0
- package/dist/clients/observed-mutation.js +1215 -0
- package/dist/clients/opaque-mutation-scan.js +300 -40
- package/dist/clients/opengrep-config.js +4 -0
- package/dist/clients/package-manager.js +201 -44
- package/dist/clients/partial-edit-apply.js +359 -80
- package/dist/clients/path-attribution-telemetry.js +23 -7
- package/dist/clients/path-keyed-map.js +35 -3
- package/dist/clients/path-utils.js +460 -13
- package/dist/clients/persist-debounce.js +8 -1
- package/dist/clients/php-cs-fixer-config.js +114 -0
- package/dist/clients/pipeline.js +77 -24
- package/dist/clients/probe-home-state.js +228 -0
- package/dist/clients/process-bridge.js +66 -0
- package/dist/clients/process-singletons.js +210 -0
- package/dist/clients/process-snapshot.js +68 -0
- package/dist/clients/project-diagnostics/fresh-fetch.js +4 -3
- package/dist/clients/project-diagnostics/runner-adapters/madge.js +2 -1
- package/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +27 -3
- package/dist/clients/project-diagnostics/scanner.js +61 -24
- package/dist/clients/project-lens-config.js +393 -122
- package/dist/clients/project-snapshot.js +85 -35
- package/dist/clients/python-environment.js +217 -0
- package/dist/clients/python-provenance.js +639 -0
- package/dist/clients/quiet-window.js +6 -1
- package/dist/clients/read-bridge.js +13 -21
- package/dist/clients/read-expansion.js +9 -46
- package/dist/clients/read-guard-logger.js +39 -6
- package/dist/clients/read-guard-tool-lines.js +364 -212
- package/dist/clients/read-guard.js +95 -7
- package/dist/clients/recent-touches.js +17 -5
- package/dist/clients/resource-sampler.js +195 -96
- package/dist/clients/review-graph/builder.js +752 -132
- package/dist/clients/review-graph/service.js +55 -3
- package/dist/clients/review-graph/shared-extraction-ir.js +7 -15
- package/dist/clients/review-graph/tsconfig-paths.js +5 -1
- package/dist/clients/review-graph/workspace-modules.js +10 -74
- package/dist/clients/review-graph-logger.js +30 -4
- package/dist/clients/runtime-agent-end.js +18 -2
- package/dist/clients/runtime-context.js +49 -16
- package/dist/clients/runtime-coordinator.js +93 -6
- package/dist/clients/runtime-session.js +169 -34
- package/dist/clients/runtime-tool-call.js +183 -35
- package/dist/clients/runtime-tool-result.js +894 -241
- package/dist/clients/runtime-turn.js +1264 -74
- package/dist/clients/rust-client.js +31 -0
- package/dist/clients/safe-spawn.js +191 -28
- package/dist/clients/sanitize.js +7 -1
- package/dist/clients/scratch-tree-policy.js +1 -3
- package/dist/clients/security-scan-client.js +51 -17
- package/dist/clients/session-lifecycle.js +238 -42
- package/dist/clients/session-start-observability.js +79 -0
- package/dist/clients/sessionstart-logger.js +12 -3
- package/dist/clients/sg-runner.js +27 -15
- package/dist/clients/sgconfig.js +6 -1
- package/dist/clients/shared-checkout-guard.js +338 -0
- package/dist/clients/skills-resolver.js +105 -0
- package/dist/clients/smells-rollup.js +2 -2
- package/dist/clients/spawn-output-cap.js +37 -0
- package/dist/clients/spawn-timeout-cooldown.js +15 -1
- package/dist/clients/startup-scan.js +6 -7
- package/dist/clients/startup-timing.js +69 -4
- package/dist/clients/string-utils.js +33 -0
- package/dist/clients/subagent-mode.js +17 -4
- package/dist/clients/test-runner-client.js +586 -118
- package/dist/clients/test-runner-delivery.js +239 -0
- package/dist/clients/tool-definition.js +41 -1
- package/dist/clients/tool-policy.js +92 -22
- package/dist/clients/tree-sitter-cache.js +40 -40
- package/dist/clients/tree-sitter-client.js +97 -53
- package/dist/clients/tree-sitter-logger.js +19 -3
- package/dist/clients/tree-sitter-query-loader.js +81 -1
- package/dist/clients/tree-sitter-shared.js +51 -46
- package/dist/clients/tree-sitter-symbol-extractor.js +28 -0
- package/dist/clients/typos-config.js +5 -0
- package/dist/clients/user-notify.js +6 -2
- package/dist/clients/warm-attach.js +8 -10
- package/dist/clients/widget-state.js +191 -26
- package/dist/clients/word-index-logger.js +15 -3
- package/dist/clients/word-index-store.js +463 -0
- package/dist/clients/word-index.js +815 -125
- package/dist/clients/workspace-topology.js +25 -1
- package/dist/clients/zizmor-config.js +29 -6
- package/dist/index.js +68577 -53950
- package/dist/mcp/analyze-cli.js +3 -1
- package/dist/mcp/build-staleness.js +8 -7
- package/dist/mcp/cli.js +3 -1
- package/dist/mcp/server.js +133 -6
- package/dist/scripts/lib/process-scan.mjs +583 -0
- package/dist/scripts/lib/skills-predicate.mjs +129 -0
- package/dist/tools/effective-config.js +89 -0
- package/dist/tools/lens-diagnostics.js +99 -24
- package/dist/tools/lsp-diagnostics.js +81 -85
- package/dist/tools/lsp-navigation.js +40 -17
- package/dist/tools/shared.js +0 -1
- package/docs/agent-guide.md +68 -3
- package/docs/ast-grep_rules_catalog.md +41 -10
- package/docs/astplayground.md +26 -17
- package/docs/configuration.md +222 -0
- package/docs/dependencies.md +3 -3
- package/docs/features.md +44 -5
- package/docs/language-coverage.md +2 -2
- package/docs/pi-lens-fixer.md +25 -0
- package/docs/pi-lens-investigator.md +25 -0
- package/docs/pi-lens-reviewer.md +27 -0
- package/docs/pi-lens-subagent.md +38 -0
- package/docs/pi-lens-warden.md +55 -0
- package/docs/public-api-stability.md +359 -0
- package/docs/release-qa-baseline.md +182 -0
- package/docs/subagent-compat.md +110 -30
- package/docs/tree-sitter_rules_catalog.md +2 -2
- package/package.json +17 -21
- package/rules/ast-grep-rules/rule-tests/c-no-malloc-free-test.yml +20 -0
- package/rules/ast-grep-rules/rule-tests/cpp-no-malloc-free-test.yml +25 -0
- package/rules/ast-grep-rules/rule-tests/cpp-no-printf-test.yml +19 -0
- package/rules/ast-grep-rules/rule-tests/go-no-fmt-println-test.yml +19 -0
- package/rules/ast-grep-rules/rule-tests/go-no-panic-in-lib-test.yml +17 -0
- package/rules/ast-grep-rules/rule-tests/go-no-underscore-func-name-test.yml +18 -0
- package/rules/ast-grep-rules/rule-tests/go-prefer-errors-is-test.yml +15 -0
- package/rules/ast-grep-rules/rule-tests/go-prefer-string-builder-test.yml +21 -0
- package/rules/ast-grep-rules/rule-tests/hyphenated-svg-attribute-test.yml +11 -0
- package/rules/ast-grep-rules/rule-tests/kotlin-no-lateinit-test.yml +17 -0
- package/rules/ast-grep-rules/rule-tests/kotlin-no-nullable-boolean-test.yml +15 -0
- package/rules/ast-grep-rules/rule-tests/kotlin-no-println-test.yml +19 -0
- package/rules/ast-grep-rules/rule-tests/kotlin-no-unnecessary-let-test.yml +7 -0
- package/rules/ast-grep-rules/rule-tests/kotlin-no-unsafe-cast-test.yml +7 -0
- package/rules/ast-grep-rules/rule-tests/kotlin-no-var-test.yml +7 -0
- package/rules/ast-grep-rules/rule-tests/kotlin-prefer-data-class-test.yml +25 -0
- package/rules/ast-grep-rules/rule-tests/kotlin-prefer-is-empty-test.yml +11 -0
- package/rules/ast-grep-rules/rule-tests/no-important-test.yml +21 -0
- package/rules/ast-grep-rules/rule-tests/no-raw-types-test.yml +30 -0
- package/rules/ast-grep-rules/rule-tests/no-string-concat-in-loop-test.yml +100 -0
- package/rules/ast-grep-rules/rule-tests/no-system-out-println-test.yml +7 -0
- package/rules/ast-grep-rules/rule-tests/prefer-string-is-empty-test.yml +7 -0
- package/rules/ast-grep-rules/rule-tests/python-optional-type-test.yml +9 -0
- package/rules/ast-grep-rules/rule-tests/reducible-list-comprehension-test.yml +11 -0
- package/rules/ast-grep-rules/rule-tests/ruby-symbol-to-proc-candidate-test.yml +10 -0
- package/rules/ast-grep-rules/rule-tests/rust-no-chars-enumerate-test.yml +7 -0
- package/rules/ast-grep-rules/rules/c-no-malloc-free.yml +39 -0
- package/rules/ast-grep-rules/rules/cpp-no-malloc-free.yml +45 -0
- package/rules/ast-grep-rules/rules/cpp-no-printf.yml +41 -0
- package/rules/ast-grep-rules/rules/go-no-fmt-println.yml +43 -0
- package/rules/ast-grep-rules/rules/go-no-panic-in-lib.yml +41 -0
- package/rules/ast-grep-rules/rules/go-no-underscore-func-name.yml +35 -0
- package/rules/ast-grep-rules/rules/go-prefer-errors-is.yml +40 -0
- package/rules/ast-grep-rules/rules/go-prefer-string-builder.yml +43 -0
- package/rules/ast-grep-rules/rules/hyphenated-svg-attribute.yml +32 -0
- package/rules/ast-grep-rules/rules/kotlin-no-lateinit.yml +37 -0
- package/rules/ast-grep-rules/rules/kotlin-no-nullable-boolean.yml +33 -0
- package/rules/ast-grep-rules/rules/kotlin-no-println.yml +42 -0
- package/rules/ast-grep-rules/rules/kotlin-no-unnecessary-let.yml +28 -0
- package/rules/ast-grep-rules/rules/kotlin-no-unsafe-cast.yml +28 -0
- package/rules/ast-grep-rules/rules/kotlin-no-var.yml +35 -0
- package/rules/ast-grep-rules/rules/kotlin-prefer-data-class.yml +66 -0
- package/rules/ast-grep-rules/rules/kotlin-prefer-is-empty.yml +35 -0
- package/rules/ast-grep-rules/rules/no-important.yml +21 -0
- package/rules/ast-grep-rules/rules/no-raw-types.yml +33 -0
- package/rules/ast-grep-rules/rules/no-string-concat-in-loop.yml +90 -0
- package/rules/ast-grep-rules/rules/no-system-out-println.yml +16 -0
- package/rules/ast-grep-rules/rules/prefer-string-is-empty.yml +11 -0
- package/rules/ast-grep-rules/rules/python-optional-type.yml +22 -0
- package/rules/ast-grep-rules/rules/reducible-list-comprehension.yml +29 -0
- package/rules/ast-grep-rules/rules/ruby-symbol-to-proc-candidate.yml +25 -0
- package/rules/ast-grep-rules/rules/rust-no-chars-enumerate.yml +19 -0
- package/rules/tree-sitter-queries/python/python-cross-language-method.yml +3 -3
- package/rules/tree-sitter-queries/python/python-hallucinated-import.yml +2 -2
- package/rules/tree-sitter-queries/python/python-sql-injection.yml +12 -2
- package/scripts/analyze-pi-lens-logs.mjs +192 -1
- package/scripts/install-selftest.mjs +58 -2
- package/scripts/lib/skills-predicate.mjs +129 -0
- package/scripts/rpc-load-check.mjs +3 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as net from "node:net";
|
|
3
3
|
import * as path from "node:path";
|
|
4
|
-
import { readInstanceRegistry, } from "./instance-registry.js";
|
|
5
|
-
import { realIsPidAlive
|
|
4
|
+
import { readInstanceRegistry, selectLivePeerInstances, } from "./instance-registry.js";
|
|
5
|
+
import { realIsPidAlive } from "./instance-reaper.js";
|
|
6
6
|
import { logLatency } from "./latency-logger.js";
|
|
7
7
|
import { touchCoverageGap } from "./lsp/diagnostic-binding.js";
|
|
8
8
|
import { loadLspService } from "./lsp-lazy.js";
|
|
@@ -18,15 +18,13 @@ function record(event, cwd, reason, pid, source) {
|
|
|
18
18
|
metadata: { event, reason, incumbentPid: pid, source },
|
|
19
19
|
});
|
|
20
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* The oldest live peer on this root, if any. The liveness rule itself lives
|
|
23
|
+
* in `selectLivePeerInstances` (#2007) so warm-attach and the shared-checkout
|
|
24
|
+
* guard cannot drift apart about what "another session is here" means.
|
|
25
|
+
*/
|
|
21
26
|
export function selectWarmAttachIncumbent(entries, cwd, now = Date.now(), isPidAlive = realIsPidAlive) {
|
|
22
|
-
|
|
23
|
-
return entries
|
|
24
|
-
.filter((entry) => entry.pid !== process.pid &&
|
|
25
|
-
entry.projectRoot === root &&
|
|
26
|
-
isPidAlive(entry.pid) &&
|
|
27
|
-
Number.isFinite(Date.parse(entry.heartbeatAt)) &&
|
|
28
|
-
now - Date.parse(entry.heartbeatAt) <= STALE_HEARTBEAT_MS)
|
|
29
|
-
.sort((a, b) => Date.parse(a.startedAt) - Date.parse(b.startedAt))[0];
|
|
27
|
+
return selectLivePeerInstances(entries, cwd, now, isPidAlive)[0];
|
|
30
28
|
}
|
|
31
29
|
async function serveRequest(req) {
|
|
32
30
|
if (req.route === "code-actions") {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { stat } from "node:fs/promises";
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
import { pathToFileURL } from "node:url";
|
|
4
|
+
import { BoundedFifoMap } from "./bounded-cache.js";
|
|
4
5
|
import { demotePastEofDiagnostics, } from "./diagnostic-line-freshness.js";
|
|
5
6
|
import { visibleWidth } from "./deps/pi-tui.js";
|
|
6
7
|
import { normalizeEphemeralMapKey, normalizeMapKey } from "./path-utils.js";
|
|
@@ -58,7 +59,6 @@ export function isBlocking(d) {
|
|
|
58
59
|
}
|
|
59
60
|
// ── Module state ─────────────────────────────────────────────────────────────
|
|
60
61
|
const files = new Map();
|
|
61
|
-
const lspServers = new Map();
|
|
62
62
|
let sessionLanguages = [];
|
|
63
63
|
let requestRenderFn = null;
|
|
64
64
|
/**
|
|
@@ -81,7 +81,8 @@ const runnerWriteGuard = new WriteOrderingGuard();
|
|
|
81
81
|
const MAX_STORED_DIAGNOSTICS_PER_FILE = 12;
|
|
82
82
|
const MAX_INACTIVE_FILE_RECORDS = 1024;
|
|
83
83
|
const ACTIVE_FILE_IDLE_MS = 30 * 60_000;
|
|
84
|
-
const MAX_LSP_SERVER_RECORDS = 128;
|
|
84
|
+
export const MAX_LSP_SERVER_RECORDS = 128;
|
|
85
|
+
const lspServers = new BoundedFifoMap(MAX_LSP_SERVER_RECORDS);
|
|
85
86
|
// Pruning is a cold-size-boundary operation. Do not walk the whole file map
|
|
86
87
|
// for every record in a large diagnostics reconciliation; the full-scan path
|
|
87
88
|
// can legitimately create thousands of records in one synchronous batch.
|
|
@@ -110,8 +111,23 @@ function maybePruneInactiveFileRecords() {
|
|
|
110
111
|
export function setRenderCallback(fn) {
|
|
111
112
|
requestRenderFn = fn;
|
|
112
113
|
}
|
|
114
|
+
/**
|
|
115
|
+
* #2275 review F1: files whose dependency-drift-demoted rows the footer has
|
|
116
|
+
* ACTUALLY DRAWN since the last turn end — the delivery population
|
|
117
|
+
* `runtime-turn.ts`'s cap step drains.
|
|
118
|
+
*
|
|
119
|
+
* The footer is not a broadcast of the whole store: `renderWidget` picks ONE
|
|
120
|
+
* record (`withBlocking[0]`) and its first five qualifying entries, and it
|
|
121
|
+
* may not be drawn at all (headless, or a turn with no repaint). Counting a
|
|
122
|
+
* delivery per turn end therefore charged the cap for rows the agent never
|
|
123
|
+
* saw, and retired them a delivery early. A Set (not a counter) is the right
|
|
124
|
+
* shape: the widget repaints many times per turn, and all of those repaints
|
|
125
|
+
* are the SAME one delivery.
|
|
126
|
+
*/
|
|
127
|
+
const renderedDependencyDriftFiles = new Set();
|
|
113
128
|
export function clearWidgetState() {
|
|
114
129
|
files.clear();
|
|
130
|
+
renderedDependencyDriftFiles.clear();
|
|
115
131
|
lspServers.clear();
|
|
116
132
|
sessionLanguages = [];
|
|
117
133
|
requestRenderFn = null;
|
|
@@ -174,7 +190,19 @@ export function exportWidgetState() {
|
|
|
174
190
|
*/
|
|
175
191
|
function migrateEntryStamps(entries, recordTouchedAt) {
|
|
176
192
|
return (entries ?? []).map((d) => {
|
|
177
|
-
|
|
193
|
+
// #2275: strip staleDeliveryCount and footerRetired alongside stale — a
|
|
194
|
+
// delivery count (and the footer-hide it earned) without the demotion
|
|
195
|
+
// it counts is meaningless, and a resumed session re-evaluates
|
|
196
|
+
// dependency-drift from scratch (#1631 review F3) same as the `stale`
|
|
197
|
+
// bit itself. A restored footer has shown the row zero times.
|
|
198
|
+
// Fix-round 3 (#2275 review F2): `staleReason` left the round trip
|
|
199
|
+
// unstripped, so a resumed row could carry `staleReason:
|
|
200
|
+
// "dependency-drift"` with `stale` gone — `isDependencyDriftDemoted`
|
|
201
|
+
// reads `stale === true`, so that combination reads as clean today, but
|
|
202
|
+
// the stray reason is still a demotion label with no demotion behind
|
|
203
|
+
// it, the same "meaningless without the bit it counts" shape as the
|
|
204
|
+
// other three fields. Strip it alongside them.
|
|
205
|
+
const { stale: _stale, staleDeliveryCount: _staleDeliveryCount, footerRetired: _footerRetired, staleReason: _staleReason, ...rest } = d;
|
|
178
206
|
return rest.observedAt == null
|
|
179
207
|
? { ...rest, observedAt: recordTouchedAt }
|
|
180
208
|
: rest;
|
|
@@ -271,9 +299,9 @@ export function getFailedLspServerIds() {
|
|
|
271
299
|
}
|
|
272
300
|
return ids;
|
|
273
301
|
}
|
|
274
|
-
export function recordFormatter(filePath, formatter, changed, success) {
|
|
302
|
+
export function recordFormatter(filePath, formatter, changed, success, outcome) {
|
|
275
303
|
const rec = getOrCreate(filePath);
|
|
276
|
-
rec.formatters.set(formatter, { changed, success });
|
|
304
|
+
rec.formatters.set(formatter, { changed, success, outcome });
|
|
277
305
|
rec.touchedAt = Date.now();
|
|
278
306
|
files.set(fileMapKey(filePath), rec);
|
|
279
307
|
requestRender();
|
|
@@ -381,7 +409,19 @@ function commitDiagnostics(rec, filePath, normalized, observedAt, key = fileMapK
|
|
|
381
409
|
files.set(key, rec);
|
|
382
410
|
requestRender();
|
|
383
411
|
}
|
|
384
|
-
|
|
412
|
+
export function classifyDiagnosticTier(d) {
|
|
413
|
+
if (d.severity === "error")
|
|
414
|
+
return "error";
|
|
415
|
+
if (d.severity === "warning")
|
|
416
|
+
return "warning";
|
|
417
|
+
if (d.severity === "hint" || d.severity === "info")
|
|
418
|
+
return "advisory";
|
|
419
|
+
return undefined;
|
|
420
|
+
}
|
|
421
|
+
/** Recompute the {blocking, errors, warnings} tally for a diagnostic set.
|
|
422
|
+
* `hint`/`info` tier findings are tallied separately — see
|
|
423
|
+
* {@link classifyDiagnosticTier} and {@link countAdvisories} — and never
|
|
424
|
+
* inflate `warnings` (#2414). */
|
|
385
425
|
function countDiagnostics(diags) {
|
|
386
426
|
let blocking = 0;
|
|
387
427
|
let errors = 0;
|
|
@@ -398,22 +438,34 @@ function countDiagnostics(diags) {
|
|
|
398
438
|
if (diagnostic.stale &&
|
|
399
439
|
(diagnostic.staleReason ?? "past-eof") === "past-eof")
|
|
400
440
|
continue;
|
|
401
|
-
|
|
441
|
+
const tier = classifyDiagnosticTier(diagnostic);
|
|
442
|
+
if (tier === "error")
|
|
402
443
|
errors++;
|
|
403
|
-
|
|
404
|
-
// now preserves all four ast-grep tiers; before, the runner collapsed
|
|
405
|
-
// them to "warning" here. An exact `=== "warning"` test would drop those
|
|
406
|
-
// findings out of the footer entirely, so a file with real findings would
|
|
407
|
-
// render clean. The footer stays a blocking/error/warning summary on
|
|
408
|
-
// purpose — the tier distinction is rendered by the code-quality-warnings
|
|
409
|
-
// advisory, not by these counters.
|
|
410
|
-
else if (diagnostic.severity === "warning" ||
|
|
411
|
-
diagnostic.severity === "hint" ||
|
|
412
|
-
diagnostic.severity === "info")
|
|
444
|
+
else if (tier === "warning")
|
|
413
445
|
warnings++;
|
|
446
|
+
// tier === "advisory" (hint/info): intentionally excluded from the
|
|
447
|
+
// footer's warning tally (#2414) — see `countAdvisories` for the
|
|
448
|
+
// parallel count `getFileDiagnosticSummaries` exposes to
|
|
449
|
+
// `lens_diagnostics` so a hint-only file still shows up as "has issues".
|
|
414
450
|
}
|
|
415
451
|
return { blocking, errors, warnings };
|
|
416
452
|
}
|
|
453
|
+
/** Count `hint`/`info` tier findings using the same past-EOF exclusion as
|
|
454
|
+
* {@link countDiagnostics} (#2414). Kept as a standalone accessor rather than
|
|
455
|
+
* a new `FileRecord.diagnosticCounts` field — the footer never renders this
|
|
456
|
+
* number, only `getFileDiagnosticSummaries` (mode=all) needs it, to keep a
|
|
457
|
+
* hint-only file from being silently dropped from a detailed listing. */
|
|
458
|
+
function countAdvisories(diags) {
|
|
459
|
+
let advisories = 0;
|
|
460
|
+
for (const diagnostic of diags) {
|
|
461
|
+
if (diagnostic.stale &&
|
|
462
|
+
(diagnostic.staleReason ?? "past-eof") === "past-eof")
|
|
463
|
+
continue;
|
|
464
|
+
if (classifyDiagnosticTier(diagnostic) === "advisory")
|
|
465
|
+
advisories++;
|
|
466
|
+
}
|
|
467
|
+
return advisories;
|
|
468
|
+
}
|
|
417
469
|
/**
|
|
418
470
|
* Apply the #1641 past-EOF gate to `rec` in place: demote (never drop) any
|
|
419
471
|
* stored diagnostic whose cited line exceeds the file's CURRENT on-disk line
|
|
@@ -804,6 +856,102 @@ export function markWidgetFileBlockersStale(filePath, reason) {
|
|
|
804
856
|
}
|
|
805
857
|
return changed;
|
|
806
858
|
}
|
|
859
|
+
/**
|
|
860
|
+
* #2275: a dependency-drift demotion the footer is still allowed to draw —
|
|
861
|
+
* the one predicate the render marker, the delivery counter and the
|
|
862
|
+
* footer-hide all ask, so "which rows does this cap govern" cannot drift
|
|
863
|
+
* apart between them.
|
|
864
|
+
*/
|
|
865
|
+
function isDependencyDriftDemoted(d) {
|
|
866
|
+
return (d.stale === true &&
|
|
867
|
+
d.staleReason === "dependency-drift" &&
|
|
868
|
+
d.footerRetired !== true);
|
|
869
|
+
}
|
|
870
|
+
/**
|
|
871
|
+
* #2275 review F1: take (and clear) the files whose dependency-drift
|
|
872
|
+
* demotions the footer actually RENDERED since the last call — the delivery
|
|
873
|
+
* population `runtime-turn.ts`'s per-turn cap step walks at turn end.
|
|
874
|
+
*
|
|
875
|
+
* Deliberately NOT a store-wide query over everything currently demoted.
|
|
876
|
+
* `renderWidget` serves one record per pass, so a store-wide walk charged a
|
|
877
|
+
* delivery to every demoted file every turn — including files the footer had
|
|
878
|
+
* never shown and one demoted moments earlier by the same turn end, which
|
|
879
|
+
* also made the ledger's "capped after N deliveries" overstate N by one.
|
|
880
|
+
* Draining here is what makes many repaints within one turn count as the one
|
|
881
|
+
* delivery they are, and a turn with no repaint count as none.
|
|
882
|
+
*/
|
|
883
|
+
export function drainRenderedDependencyDriftFilePaths() {
|
|
884
|
+
const out = [...renderedDependencyDriftFiles];
|
|
885
|
+
renderedDependencyDriftFiles.clear();
|
|
886
|
+
return out;
|
|
887
|
+
}
|
|
888
|
+
/**
|
|
889
|
+
* #2275: commit one more RENDERED delivery of `filePath`'s
|
|
890
|
+
* dependency-drift-demoted diagnostics. Every qualifying entry on the record
|
|
891
|
+
* advances together — `markWidgetFileBlockersStale` demotes them as one
|
|
892
|
+
* batch per file, so they share one delivery history, mirroring that
|
|
893
|
+
* write's own file-level scope. Returns the new count, or 0 when the file
|
|
894
|
+
* has nothing this cap governs (never demoted, or already footer-retired —
|
|
895
|
+
* a hidden row is delivered no more, so it must stop advancing).
|
|
896
|
+
*/
|
|
897
|
+
export function incrementWidgetDependencyDriftDelivery(filePath) {
|
|
898
|
+
const rec = files.get(fileMapKey(filePath));
|
|
899
|
+
if (!rec)
|
|
900
|
+
return 0;
|
|
901
|
+
let next = 0;
|
|
902
|
+
for (const d of rec.allDiagnostics) {
|
|
903
|
+
if (isDependencyDriftDemoted(d)) {
|
|
904
|
+
next = (d.staleDeliveryCount ?? 0) + 1;
|
|
905
|
+
d.staleDeliveryCount = next;
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
return next;
|
|
909
|
+
}
|
|
910
|
+
/**
|
|
911
|
+
* #2275 review F2: retire every dependency-drift-demoted diagnostic on
|
|
912
|
+
* `filePath` once its delivery cap is reached — by HIDING it from the
|
|
913
|
+
* footer, not by dropping it.
|
|
914
|
+
*
|
|
915
|
+
* `RuntimeCoordinator.retireDemotedDependencyDriftBlocker` can delete its
|
|
916
|
+
* whole `_pendingInlineBlockers` record because that store backs exactly one
|
|
917
|
+
* surface (the turn-end advisory text). This store does not: `allDiagnostics`
|
|
918
|
+
* is also what `getFileDiagnosticSummaries` serves to `lens_diagnostics
|
|
919
|
+
* mode=all` and what `lens_diagnostic_mark` cross-checks to reanchor. Removing
|
|
920
|
+
* the entry there turned an unconfirmed LSP error into a CLEAN read and took
|
|
921
|
+
* it out of the error tally #1631 requires it to stay in. So the cap marks
|
|
922
|
+
* `footerRetired` and leaves everything else — severity, counts, the
|
|
923
|
+
* `stale`/`dependency-drift` demotion — exactly as it was; mode=all carries
|
|
924
|
+
* the "capped, still confirmable" wording in its own note. Returns true iff
|
|
925
|
+
* something changed (idempotent on a second call).
|
|
926
|
+
*/
|
|
927
|
+
export function retireWidgetDependencyDriftBlockers(filePath) {
|
|
928
|
+
const rec = files.get(fileMapKey(filePath));
|
|
929
|
+
if (!rec)
|
|
930
|
+
return false;
|
|
931
|
+
let changed = false;
|
|
932
|
+
for (const d of rec.allDiagnostics) {
|
|
933
|
+
if (isDependencyDriftDemoted(d)) {
|
|
934
|
+
d.footerRetired = true;
|
|
935
|
+
changed = true;
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
if (!changed)
|
|
939
|
+
return false;
|
|
940
|
+
// The record's severity tallies are unchanged by design (the finding is
|
|
941
|
+
// still an error, still non-blocking) — only what the footer draws moves.
|
|
942
|
+
// Fix-round 3 (#2275 review F1): this delete is live only for the
|
|
943
|
+
// multi-file drain re-render case — `drainRenderedDependencyDriftFilePaths`
|
|
944
|
+
// already clears the whole Set before this loop starts, so by the time a
|
|
945
|
+
// given `wPath` reaches this call its own entry is normally long gone. It
|
|
946
|
+
// only does something when a render for a DIFFERENT file interleaves
|
|
947
|
+
// between the drain and this retire (adding `rec.filePath` back to the
|
|
948
|
+
// Set mid-loop) or a render fires between retirement and the caller's next
|
|
949
|
+
// drain — either way, defensive: it keeps a just-retired file from being
|
|
950
|
+
// double-drained (and double-charged) on the next pass.
|
|
951
|
+
renderedDependencyDriftFiles.delete(rec.filePath);
|
|
952
|
+
requestRenderFn?.();
|
|
953
|
+
return true;
|
|
954
|
+
}
|
|
807
955
|
/**
|
|
808
956
|
* Keep the TUI honest (#298 follow-up). `reconcileStaleWidgetFiles` drops
|
|
809
957
|
* widget entries whose file changed on disk after they were last recorded
|
|
@@ -840,6 +988,7 @@ export function getFileDiagnosticSummaries() {
|
|
|
840
988
|
blocking: rec.diagnosticCounts.blocking,
|
|
841
989
|
errors: rec.diagnosticCounts.errors,
|
|
842
990
|
warnings: rec.diagnosticCounts.warnings,
|
|
991
|
+
advisories: countAdvisories(rec.allDiagnostics),
|
|
843
992
|
hasFinalSnapshot: rec.hasFinalDiagnosticsSnapshot,
|
|
844
993
|
diagnostics: rec.allDiagnostics.map((d) => ({ ...d })),
|
|
845
994
|
};
|
|
@@ -893,12 +1042,6 @@ export function recordLsp(serverId, root, status, durationMs) {
|
|
|
893
1042
|
? "ready"
|
|
894
1043
|
: "failed";
|
|
895
1044
|
lspServers.set(key, { serverId, root, status: mapped, durationMs });
|
|
896
|
-
while (lspServers.size > MAX_LSP_SERVER_RECORDS) {
|
|
897
|
-
const oldest = lspServers.keys().next().value;
|
|
898
|
-
if (oldest === undefined)
|
|
899
|
-
break;
|
|
900
|
-
lspServers.delete(oldest);
|
|
901
|
-
}
|
|
902
1045
|
requestRender();
|
|
903
1046
|
}
|
|
904
1047
|
// ── Render ────────────────────────────────────────────────────────────────────
|
|
@@ -961,7 +1104,12 @@ export function renderWidget(width, theme) {
|
|
|
961
1104
|
// the footer entirely instead of demoting visibly. `isBlockingOrDemoted` keeps
|
|
962
1105
|
// it in the list; the per-entry render below distinguishes the two with a
|
|
963
1106
|
// dimmed marker instead of the red dot.
|
|
964
|
-
|
|
1107
|
+
//
|
|
1108
|
+
// #2275: a demotion that reached its delivery cap is hidden from THIS
|
|
1109
|
+
// surface only (`footerRetired`) — it stays in `allDiagnostics` for
|
|
1110
|
+
// mode=all and lens_diagnostic_mark, which is where the agent is told it
|
|
1111
|
+
// was capped and can still be confirmed by a re-run.
|
|
1112
|
+
const isBlockingOrDemoted = (d) => (isBlocking(d) || d.stale === true) && d.footerRetired !== true;
|
|
965
1113
|
const withBlocking = recencySorted.filter((r) => r.diagnostics.some(isBlockingOrDemoted));
|
|
966
1114
|
if (withBlocking.length > 0) {
|
|
967
1115
|
const rec = withBlocking[0];
|
|
@@ -979,6 +1127,18 @@ export function renderWidget(width, theme) {
|
|
|
979
1127
|
lines.push(fitLine(` ${dim(path.basename(rec.filePath))}`, w));
|
|
980
1128
|
}
|
|
981
1129
|
const blockers = rec.diagnostics.filter(isBlockingOrDemoted).slice(0, 5);
|
|
1130
|
+
// #2275 review F1: THIS is the point where a demoted row is delivered to
|
|
1131
|
+
// a human — after the `withBlocking[0]` pick and the top-five slice, not
|
|
1132
|
+
// before them. Mark the file so the next turn end can charge exactly one
|
|
1133
|
+
// delivery against its cap. File-level, matching
|
|
1134
|
+
// `markWidgetFileBlockersStale`'s own file-level demotion batch (all of a
|
|
1135
|
+
// file's drift demotions share one delivery history); a file holding more
|
|
1136
|
+
// than five demoted rows delivers the visible ones and counts the batch,
|
|
1137
|
+
// which is the conservative direction — it retires no LATER than the rows
|
|
1138
|
+
// the agent actually read.
|
|
1139
|
+
if (blockers.some(isDependencyDriftDemoted)) {
|
|
1140
|
+
renderedDependencyDriftFiles.add(rec.filePath);
|
|
1141
|
+
}
|
|
982
1142
|
for (const d of blockers) {
|
|
983
1143
|
// A past-EOF demotion's coordinate is untrustworthy — render the
|
|
984
1144
|
// marker instead of the line (#1641); drift demotions keep theirs.
|
|
@@ -1062,7 +1222,10 @@ function formatFileRowVertical(rec, theme) {
|
|
|
1062
1222
|
.filter(([, f]) => f.changed && f.success)
|
|
1063
1223
|
.map(([name]) => name);
|
|
1064
1224
|
const failedFormatters = [...rec.formatters.entries()]
|
|
1065
|
-
|
|
1225
|
+
// An `unavailable` tool is not a code failure (#2413): it never earns a red
|
|
1226
|
+
// `fmt-failed` marker. Its result already carries success:true, so this
|
|
1227
|
+
// guard is a belt that keeps the intent explicit at the render seam.
|
|
1228
|
+
.filter(([, f]) => !f.success && f.outcome !== "unavailable")
|
|
1066
1229
|
.map(([name]) => name);
|
|
1067
1230
|
const formatMark = (failedFormatters.length > 0
|
|
1068
1231
|
? red(` fmt-failed:${failedFormatters.join(",")}`)
|
|
@@ -1205,7 +1368,9 @@ function hasChangedFormatter(rec) {
|
|
|
1205
1368
|
return [...rec.formatters.values()].some((f) => f.changed && f.success);
|
|
1206
1369
|
}
|
|
1207
1370
|
function hasFailedFormatter(rec) {
|
|
1208
|
-
|
|
1371
|
+
// `unavailable` (#2413) is success:true and must never count as a failure —
|
|
1372
|
+
// the explicit guard keeps that true even if a future path mislabels it.
|
|
1373
|
+
return [...rec.formatters.values()].some((f) => !f.success && f.outcome !== "unavailable");
|
|
1209
1374
|
}
|
|
1210
1375
|
function shouldRenderFile(rec) {
|
|
1211
1376
|
return (rec.hasFinalDiagnosticsSnapshot ||
|
|
@@ -21,19 +21,31 @@
|
|
|
21
21
|
*/
|
|
22
22
|
import * as path from "node:path";
|
|
23
23
|
import { isTestMode } from "./env-utils.js";
|
|
24
|
-
import {
|
|
24
|
+
import { getGlobalPiLensLogDir } from "./probe-home-state.js";
|
|
25
25
|
import { getMaxLogSizeMB } from "./log-cleanup.js";
|
|
26
26
|
import { createNdjsonLogger } from "./ndjson-logger.js";
|
|
27
|
-
|
|
27
|
+
import { normalizeFilePath } from "./path-utils.js";
|
|
28
|
+
const WORD_INDEX_LOG_FILE = path.join(getGlobalPiLensLogDir(), "word-index.log");
|
|
28
29
|
const writer = createNdjsonLogger({
|
|
29
30
|
filePath: WORD_INDEX_LOG_FILE,
|
|
30
31
|
maxBytes: getMaxLogSizeMB() * 1024 * 1024,
|
|
31
32
|
});
|
|
33
|
+
/**
|
|
34
|
+
* #2141 class sweep: mirrors review-graph-logger.ts's `cwd` normalization.
|
|
35
|
+
* Call sites here feed both raw roots (`snapshotRoot`, `path.resolve(cwd)`)
|
|
36
|
+
* and pre-normalized cache keys (`key`), so the same root could show up in
|
|
37
|
+
* two path forms. Normalizing once at this shared emit seam closes that for
|
|
38
|
+
* every call site, present and future.
|
|
39
|
+
*/
|
|
32
40
|
export function logWordIndex(entry) {
|
|
33
41
|
if (isTestMode()) {
|
|
34
42
|
return;
|
|
35
43
|
}
|
|
36
|
-
writer.log({
|
|
44
|
+
writer.log({
|
|
45
|
+
ts: new Date().toISOString(),
|
|
46
|
+
...entry,
|
|
47
|
+
cwd: normalizeFilePath(entry.cwd),
|
|
48
|
+
});
|
|
37
49
|
}
|
|
38
50
|
export function getWordIndexLogPath() {
|
|
39
51
|
return WORD_INDEX_LOG_FILE;
|