pi-lens 4.2.1 → 4.4.0
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 +1562 -0
- package/README.md +157 -24
- package/config/dependency-cruiser-eager-allowlist.json +6 -2
- package/dist/chunk-22AVIGXS.js +560 -0
- package/dist/chunk-27BBHSZC.js +106 -0
- package/dist/chunk-2BEMIWEW.js +51 -0
- package/dist/chunk-2EECBNC5.js +89 -0
- package/dist/chunk-34U7PLGE.js +23 -0
- package/dist/chunk-3I5QFT3N.js +181 -0
- package/dist/chunk-3MED75HT.js +37 -0
- package/dist/chunk-47D2BO4S.js +87 -0
- package/dist/chunk-4RERDEXR.js +348 -0
- package/dist/chunk-4W2PLC4J.js +27 -0
- package/dist/chunk-52H5B5TC.js +202 -0
- package/dist/chunk-54B42YRX.js +27 -0
- package/dist/chunk-5RXBNSW2.js +266 -0
- package/dist/chunk-5THXD6X5.js +201 -0
- package/dist/chunk-5W3R6LFT.js +24 -0
- package/dist/chunk-5ZEJHV35.js +341 -0
- package/dist/chunk-6P62QVEA.js +118 -0
- package/dist/chunk-6QIUX4EP.js +459 -0
- package/dist/chunk-6VCD4VKZ.js +78 -0
- package/dist/chunk-7F72PXY2.js +326 -0
- package/dist/chunk-7FBF7NPR.js +998 -0
- package/dist/chunk-7U2IDNXN.js +37 -0
- package/dist/chunk-ABBOA7UD.js +157 -0
- package/dist/chunk-AHDW3GPE.js +50 -0
- package/dist/chunk-AJ3QXTRQ.js +756 -0
- package/dist/chunk-AJVLWNFN.js +1610 -0
- package/dist/chunk-AJXODZY6.js +112 -0
- package/dist/chunk-ARFCXG7S.js +84 -0
- package/dist/chunk-AS44CFQ4.js +708 -0
- package/dist/chunk-AWE5TMPO.js +38 -0
- package/dist/chunk-B3I2UUT4.js +4692 -0
- package/dist/chunk-BRJKOBZP.js +331 -0
- package/dist/chunk-BW5KFIQC.js +59 -0
- package/dist/chunk-C2AUYXQH.js +149 -0
- package/dist/chunk-CGGAIP7J.js +29 -0
- package/dist/chunk-D6QS3U6M.js +30 -0
- package/dist/chunk-DFVMIKMQ.js +349 -0
- package/dist/chunk-DIULIWKU.js +169 -0
- package/dist/chunk-DQ2NZ7C4.js +2317 -0
- package/dist/chunk-E2WFBRHM.js +213 -0
- package/dist/chunk-E4MAEDPM.js +50 -0
- package/dist/chunk-EOKRQ3SA.js +30 -0
- package/dist/chunk-F3AU2TMM.js +2626 -0
- package/dist/chunk-F3P7VQ7H.js +170 -0
- package/dist/chunk-FC4RP4I2.js +12 -0
- package/dist/chunk-FJNKANOS.js +32 -0
- package/dist/chunk-GUOGVTCQ.js +146 -0
- package/dist/chunk-GVXA6CCE.js +18 -0
- package/dist/chunk-HHYAELLJ.js +2334 -0
- package/dist/chunk-HMFXILPV.js +83 -0
- package/dist/chunk-HVUZXSWK.js +421 -0
- package/dist/chunk-HWBZIGMJ.js +62 -0
- package/dist/chunk-I3R7GKDR.js +17 -0
- package/dist/chunk-I7SPGOWI.js +55 -0
- package/dist/chunk-IIXOAGHR.js +38 -0
- package/dist/chunk-IVP5KAB7.js +2250 -0
- package/dist/chunk-IXEBJSUE.js +22 -0
- package/dist/chunk-JOLITGCC.js +27 -0
- package/dist/chunk-K6VYLB2U.js +145 -0
- package/dist/chunk-LJDODBBZ.js +78 -0
- package/dist/chunk-LNAKEO63.js +78 -0
- package/dist/chunk-LSMJ6KBE.js +4139 -0
- package/dist/chunk-LW6XKDZQ.js +5565 -0
- package/dist/chunk-N3YQJI6O.js +899 -0
- package/dist/chunk-NABLC7W3.js +148 -0
- package/dist/chunk-NKOUFPQF.js +659 -0
- package/dist/chunk-NL5GLMFI.js +211 -0
- package/dist/chunk-NMABWBZN.js +327 -0
- package/dist/chunk-NTHH2J74.js +27 -0
- package/dist/chunk-NTUJEGDZ.js +59 -0
- package/dist/chunk-NXL4FFQQ.js +47 -0
- package/dist/chunk-NXPS2L6U.js +466 -0
- package/dist/chunk-O5WILGMI.js +42 -0
- package/dist/chunk-O6TQT6RI.js +48 -0
- package/dist/chunk-OAXNDZJ7.js +323 -0
- package/dist/chunk-ODEEOXPH.js +44 -0
- package/dist/chunk-OQGFCZJ4.js +4533 -0
- package/dist/chunk-ORTMY4Q4.js +282 -0
- package/dist/chunk-OS32RNR2.js +442 -0
- package/dist/chunk-PAK6IDME.js +189 -0
- package/dist/chunk-PWFHBTSF.js +406 -0
- package/dist/chunk-Q5U6FMDI.js +2352 -0
- package/dist/chunk-QOZXJ4NA.js +3364 -0
- package/dist/chunk-QYF5S6P6.js +45 -0
- package/dist/chunk-RIISMHKN.js +36 -0
- package/dist/chunk-RPD4ZSB7.js +25 -0
- package/dist/chunk-RPD5K5NC.js +79 -0
- package/dist/chunk-RUOG5D2C.js +262 -0
- package/dist/chunk-T4ERT73Y.js +599 -0
- package/dist/chunk-T6D4Q4AQ.js +54 -0
- package/dist/chunk-TGPXLY2J.js +391 -0
- package/dist/chunk-TLGFBM3F.js +12116 -0
- package/dist/chunk-TO6WL3GM.js +88 -0
- package/dist/chunk-TT22N74J.js +517 -0
- package/dist/chunk-TVN5N6GY.js +21216 -0
- package/dist/chunk-U3VGR4VU.js +308 -0
- package/dist/chunk-UK3CMEAL.js +1250 -0
- package/dist/chunk-UOPVJQ4N.js +103 -0
- package/dist/chunk-UXVNL3D7.js +23 -0
- package/dist/chunk-UY752QSN.js +45 -0
- package/dist/chunk-V5PXFSZK.js +188 -0
- package/dist/chunk-V7R425XG.js +398 -0
- package/dist/chunk-VCSRSYLF.js +81 -0
- package/dist/chunk-VD4JQCQC.js +162 -0
- package/dist/chunk-VDBPVIKD.js +62 -0
- package/dist/chunk-VHQLPIRJ.js +114 -0
- package/dist/chunk-VN2AXLEX.js +5414 -0
- package/dist/chunk-VNMT7C64.js +478 -0
- package/dist/chunk-WONERJTP.js +309 -0
- package/dist/chunk-XECLWQZN.js +85 -0
- package/dist/chunk-XIMYZ3JA.js +27 -0
- package/dist/chunk-XK4CIILI.js +144 -0
- package/dist/chunk-Y4T27COV.js +562 -0
- package/dist/chunk-YGVYKNSN.js +1860 -0
- package/dist/chunk-YLF3PPT5.js +308 -0
- package/dist/chunk-YSNFMJKN.js +14 -0
- package/dist/chunk-Z3CCVDUB.js +76 -0
- package/dist/chunk-Z54ZSOBZ.js +61 -0
- package/dist/chunk-ZAWW3AF6.js +97 -0
- package/dist/chunk-ZMOL6RQC.js +167 -0
- package/dist/index.js +19039 -8956
- package/dist/mcp/analyze-cli.js +186 -228
- package/dist/mcp/cli.js +137 -98
- package/dist/mcp/server.js +22592 -1564
- package/dist/mcp/worker.js +97 -38
- package/dist/probes/installer.js +135 -0
- package/dist/workers/project-snapshot-persist-worker.js +22 -0
- package/dist/workers/review-graph-persist-worker.js +15 -0
- package/docs/adr/0001-stale-advisory-live-arm.md +29 -0
- package/docs/adr/0002-workspace-hash-rendezvous.md +30 -0
- package/docs/adr/0003-git-guard-latch-writer.md +203 -0
- package/docs/adr/0004-disposition-policy-seam.md +38 -0
- package/docs/adr/0005-tool-availability-enforcement-seam.md +29 -0
- package/docs/adr/0006-derived-state-benchmark-first.md +31 -0
- package/docs/adr/0007-end-to-end-witness-per-seam-slice.md +38 -0
- package/docs/adr/0008-turn-end-lane-interface.md +165 -0
- package/docs/adr/0009-reported-path-attribution.md +114 -0
- package/docs/adr/README.md +26 -0
- package/docs/agent-guide.md +13 -4
- package/docs/agent-tools.md +60 -1
- package/docs/ast-grep_rules_catalog.md +6 -4
- package/docs/configuration.md +75 -2
- package/docs/engineering-principles.md +202 -0
- package/docs/environment-variables.md +113 -6
- package/docs/features.md +10 -6
- package/docs/globalconfig.md +7 -1
- package/docs/io-bridge-v2-migration.md +94 -0
- package/docs/language-coverage.md +17 -0
- package/docs/lsp-capability-matrix.md +131 -32
- package/docs/lsp-idle-eviction.md +124 -0
- package/docs/mcp.md +21 -5
- package/docs/merge-queue-rollout.md +77 -0
- package/docs/pi-lens-fixer.md +161 -39
- package/docs/pi-lens-investigator.md +77 -20
- package/docs/pi-lens-merge-policy.md +694 -0
- package/docs/pi-lens-monitor.md +73 -7
- package/docs/pi-lens-retro.md +6 -4
- package/docs/pi-lens-reviewer.md +190 -34
- package/docs/pi-lens-subagent.md +247 -37
- package/docs/pi-lens-warden.md +18 -7
- package/docs/public-api-stability.md +56 -0
- package/docs/release-qa-baseline.md +86 -17
- package/docs/rfcs/3654-unified-io-bridge-v2.md +316 -0
- package/docs/servercapabilities.md +66 -52
- package/docs/settings.md +13 -3
- package/docs/subagent-compat.md +1 -1
- package/docs/usage.md +5 -1
- package/grammars/tree-sitter-bash.wasm +0 -0
- package/grammars/tree-sitter-bash.wasm.json +3 -3
- package/package.json +23 -9
- package/rules/ast-grep-rules/rule-tests/advisory-registry-subset-test.yml +41 -0
- package/rules/ast-grep-rules/rule-tests/no-assert-tuple-test.yml +13 -0
- package/rules/ast-grep-rules/rule-tests/no-boolean-in-except-test.yml +26 -0
- package/rules/ast-grep-rules/rule-tests/no-http-headers-bracket-access-test.yml +10 -0
- package/rules/ast-grep-rules/rule-tests/unchecked-numeric-parse-python-test.yml +18 -0
- package/rules/ast-grep-rules/rule-tests/unchecked-throwing-call-python-test.yml +4 -3
- package/rules/ast-grep-rules/rules/advisory-registry-subset.yml +50 -0
- package/rules/ast-grep-rules/rules/go-no-fmt-println.yml +2 -2
- package/rules/ast-grep-rules/rules/no-assert-tuple.yml +23 -13
- package/rules/ast-grep-rules/rules/no-boolean-in-except.yml +7 -3
- package/rules/ast-grep-rules/rules/no-console-except-error-js.yml +2 -2
- package/rules/ast-grep-rules/rules/no-console-except-error.yml +2 -2
- package/rules/ast-grep-rules/rules/no-http-headers-bracket-access.yml +12 -7
- package/rules/ast-grep-rules/rules/unchecked-numeric-parse-python.yml +44 -0
- package/rules/ast-grep-rules/rules/unchecked-throwing-call-python.yml +5 -3
- package/rules/tree-sitter-queries/typescript/console-statement.yml +2 -2
- package/scripts/analyze-pi-lens-logs.mjs +1275 -62
- package/scripts/download-grammars.js +5 -0
- package/scripts/grammars.lock.json +6 -1
- package/scripts/install-selftest.mjs +38 -35
- package/scripts/lib/host-provided-deps.mjs +13 -4
- package/scripts/lib/web-tree-sitter-dir.mjs +141 -0
- package/dist/clients/actionable-warnings-logger.js +0 -35
- package/dist/clients/actionable-warnings.js +0 -1594
- package/dist/clients/advisory-provenance.js +0 -457
- package/dist/clients/agent-behavior-client.js +0 -147
- package/dist/clients/agent-nudge.js +0 -325
- package/dist/clients/analysed-root.js +0 -1
- package/dist/clients/ast-grep-client.js +0 -731
- package/dist/clients/ast-grep-rule-manager.js +0 -146
- package/dist/clients/ast-grep-tool-logger.js +0 -118
- package/dist/clients/ast-grep-types.js +0 -10
- package/dist/clients/ast-grep-yaml-synth.js +0 -154
- package/dist/clients/atomic-write-staging.js +0 -75
- package/dist/clients/atomic-write.js +0 -189
- package/dist/clients/availability-probe-flight.js +0 -12
- package/dist/clients/bash-file-access.js +0 -1056
- package/dist/clients/biome-client.js +0 -357
- package/dist/clients/blocker-freshness.js +0 -837
- package/dist/clients/blocker-past-eof.js +0 -129
- package/dist/clients/bootstrap.js +0 -569
- package/dist/clients/bounded-cache.js +0 -190
- package/dist/clients/bounded-pid-file-lock.js +0 -202
- package/dist/clients/bounded-telemetry.js +0 -295
- package/dist/clients/build-identity.js +0 -95
- package/dist/clients/bundled-resource-health.js +0 -113
- package/dist/clients/bus-events-logger.js +0 -105
- package/dist/clients/bus-publish.js +0 -171
- package/dist/clients/cache/rule-cache.js +0 -190
- package/dist/clients/cache-manager.js +0 -465
- package/dist/clients/cache-observability.js +0 -1313
- package/dist/clients/call-graph.js +0 -852
- package/dist/clients/cargo-manifest.js +0 -422
- package/dist/clients/cascade-budget.js +0 -196
- package/dist/clients/cascade-format.js +0 -315
- package/dist/clients/cascade-logger.js +0 -31
- package/dist/clients/cascade-types.js +0 -9
- package/dist/clients/child-unref.js +0 -115
- package/dist/clients/code-quality-warnings.js +0 -286
- package/dist/clients/codebase-model.js +0 -173
- package/dist/clients/collateral-test-role.js +0 -40
- package/dist/clients/complexity-client.js +0 -462
- package/dist/clients/config-core/deny.js +0 -221
- package/dist/clients/config-core/index.js +0 -50
- package/dist/clients/config-core/merge.js +0 -357
- package/dist/clients/config-core/normalize.js +0 -340
- package/dist/clients/config-core/process-spec.js +0 -248
- package/dist/clients/config-core/provenance.js +0 -164
- package/dist/clients/config-core/records.js +0 -218
- package/dist/clients/config-core/resolve.js +0 -125
- package/dist/clients/config-core/safe-object.js +0 -78
- package/dist/clients/config-core/schema.js +0 -165
- package/dist/clients/config-diagnostic-codes.js +0 -283
- package/dist/clients/config-locations.js +0 -160
- package/dist/clients/config-resolve.js +0 -792
- package/dist/clients/config-schema.js +0 -251
- package/dist/clients/config-warn.js +0 -407
- package/dist/clients/console-guard-install.js +0 -26
- package/dist/clients/cooperative-budget.js +0 -42
- package/dist/clients/dead-code-client.js +0 -510
- package/dist/clients/dead-code-logger.js +0 -30
- package/dist/clients/deadline-utils.js +0 -280
- package/dist/clients/debug-handles.js +0 -211
- package/dist/clients/debug-heap.js +0 -174
- package/dist/clients/deferred-lsp-work.js +0 -106
- package/dist/clients/degradation-ledger.js +0 -396
- package/dist/clients/demoted-finding-render.js +0 -169
- package/dist/clients/dependency-checker.js +0 -862
- package/dist/clients/deps/ast-grep-napi.js +0 -22
- package/dist/clients/deps/js-yaml.js +0 -9
- package/dist/clients/deps/minimatch.js +0 -4
- package/dist/clients/deps/pi-tui.js +0 -14
- package/dist/clients/deps/typebox.js +0 -14
- package/dist/clients/deps/vscode-jsonrpc.js +0 -1
- package/dist/clients/deps/web-tree-sitter.js +0 -24
- package/dist/clients/diagnostic-dispositions.js +0 -594
- package/dist/clients/diagnostic-line-freshness.js +0 -305
- package/dist/clients/diagnostic-logger.js +0 -73
- package/dist/clients/diagnostic-tracker.js +0 -105
- package/dist/clients/diagnostics-publish.js +0 -230
- package/dist/clients/dispatch/ast-grep-catalog.js +0 -65
- package/dist/clients/dispatch/auxiliary-lsp.js +0 -343
- package/dist/clients/dispatch/collect-later-tier.js +0 -35
- package/dist/clients/dispatch/diagnostic-taxonomy.js +0 -66
- package/dist/clients/dispatch/dispatcher.js +0 -1269
- package/dist/clients/dispatch/fact-provider-types.js +0 -1
- package/dist/clients/dispatch/fact-rule-runner.js +0 -17
- package/dist/clients/dispatch/fact-runner.js +0 -30
- package/dist/clients/dispatch/fact-scheduler.js +0 -68
- package/dist/clients/dispatch/fact-store.js +0 -377
- package/dist/clients/dispatch/facts/comment-facts.js +0 -22
- package/dist/clients/dispatch/facts/file-content.js +0 -19
- package/dist/clients/dispatch/facts/function-facts.js +0 -348
- package/dist/clients/dispatch/facts/import-facts.js +0 -204
- package/dist/clients/dispatch/facts/tree-sitter-facts.js +0 -34
- package/dist/clients/dispatch/facts/try-catch-facts.js +0 -119
- package/dist/clients/dispatch/finding-policy.js +0 -222
- package/dist/clients/dispatch/indent-detect.js +0 -411
- package/dist/clients/dispatch/inline-suppressions.js +0 -70
- package/dist/clients/dispatch/integration.js +0 -2377
- package/dist/clients/dispatch/lazy.js +0 -11
- package/dist/clients/dispatch/pending-runner-findings.js +0 -87
- package/dist/clients/dispatch/plan.js +0 -278
- package/dist/clients/dispatch/priorities.js +0 -20
- package/dist/clients/dispatch/rule-id-normalize.js +0 -50
- package/dist/clients/dispatch/rule-ignores.js +0 -62
- package/dist/clients/dispatch/rule-policy.js +0 -135
- package/dist/clients/dispatch/rules/async-noise.js +0 -40
- package/dist/clients/dispatch/rules/async-unnecessary-wrapper.js +0 -27
- package/dist/clients/dispatch/rules/cors-wildcard.js +0 -54
- package/dist/clients/dispatch/rules/error-obscuring.js +0 -32
- package/dist/clients/dispatch/rules/error-swallowing.js +0 -31
- package/dist/clients/dispatch/rules/framework-call-noise.js +0 -67
- package/dist/clients/dispatch/rules/high-complexity.js +0 -72
- package/dist/clients/dispatch/rules/high-fan-out.js +0 -74
- package/dist/clients/dispatch/rules/high-import-coupling.js +0 -37
- package/dist/clients/dispatch/rules/missing-error-propagation.js +0 -62
- package/dist/clients/dispatch/rules/no-commented-credentials.js +0 -52
- package/dist/clients/dispatch/rules/pass-through-wrappers.js +0 -42
- package/dist/clients/dispatch/rules/placeholder-comments.js +0 -40
- package/dist/clients/dispatch/rules/unsafe-boundary.js +0 -126
- package/dist/clients/dispatch/runner-context.js +0 -52
- package/dist/clients/dispatch/runners/actionlint.js +0 -113
- package/dist/clients/dispatch/runners/ast-grep-napi.js +0 -1196
- package/dist/clients/dispatch/runners/biome-check.js +0 -283
- package/dist/clients/dispatch/runners/cpp-check.js +0 -236
- package/dist/clients/dispatch/runners/credo.js +0 -80
- package/dist/clients/dispatch/runners/cue-vet.js +0 -398
- package/dist/clients/dispatch/runners/dart-analyze.js +0 -202
- package/dist/clients/dispatch/runners/detekt.js +0 -169
- package/dist/clients/dispatch/runners/dotnet-build.js +0 -159
- package/dist/clients/dispatch/runners/elixir-check.js +0 -210
- package/dist/clients/dispatch/runners/eslint.js +0 -154
- package/dist/clients/dispatch/runners/fact-rules.js +0 -29
- package/dist/clients/dispatch/runners/fish-indent.js +0 -69
- package/dist/clients/dispatch/runners/gleam-check.js +0 -87
- package/dist/clients/dispatch/runners/go-vet.js +0 -90
- package/dist/clients/dispatch/runners/golangci-lint.js +0 -120
- package/dist/clients/dispatch/runners/hadolint.js +0 -79
- package/dist/clients/dispatch/runners/helm-lint.js +0 -171
- package/dist/clients/dispatch/runners/helm-render.js +0 -940
- package/dist/clients/dispatch/runners/htmlhint.js +0 -108
- package/dist/clients/dispatch/runners/index.js +0 -108
- package/dist/clients/dispatch/runners/javac.js +0 -89
- package/dist/clients/dispatch/runners/ktlint.js +0 -136
- package/dist/clients/dispatch/runners/lsp.js +0 -378
- package/dist/clients/dispatch/runners/markdownlint.js +0 -160
- package/dist/clients/dispatch/runners/mypy.js +0 -101
- package/dist/clients/dispatch/runners/oxlint.js +0 -398
- package/dist/clients/dispatch/runners/php-lint.js +0 -62
- package/dist/clients/dispatch/runners/phpstan.js +0 -120
- package/dist/clients/dispatch/runners/prisma-validate.js +0 -62
- package/dist/clients/dispatch/runners/psscriptanalyzer.js +0 -445
- package/dist/clients/dispatch/runners/pyright.js +0 -169
- package/dist/clients/dispatch/runners/rubocop.js +0 -90
- package/dist/clients/dispatch/runners/ruff.js +0 -89
- package/dist/clients/dispatch/runners/rust-clippy.js +0 -251
- package/dist/clients/dispatch/runners/shellcheck.js +0 -169
- package/dist/clients/dispatch/runners/shfmt.js +0 -102
- package/dist/clients/dispatch/runners/spellcheck.js +0 -121
- package/dist/clients/dispatch/runners/spotbugs.js +0 -259
- package/dist/clients/dispatch/runners/sqlfluff.js +0 -174
- package/dist/clients/dispatch/runners/stylelint.js +0 -158
- package/dist/clients/dispatch/runners/swiftlint.js +0 -154
- package/dist/clients/dispatch/runners/taplo.js +0 -168
- package/dist/clients/dispatch/runners/terragrunt.js +0 -168
- package/dist/clients/dispatch/runners/tflint.js +0 -110
- package/dist/clients/dispatch/runners/tree-sitter.js +0 -620
- package/dist/clients/dispatch/runners/trivy-config.js +0 -247
- package/dist/clients/dispatch/runners/utils/availability-policy.js +0 -496
- package/dist/clients/dispatch/runners/utils/candidate-probe.js +0 -90
- package/dist/clients/dispatch/runners/utils/diagnostic-parsers.js +0 -85
- package/dist/clients/dispatch/runners/utils/lazy-installer.js +0 -274
- package/dist/clients/dispatch/runners/utils/runner-helpers.js +0 -1701
- package/dist/clients/dispatch/runners/utils/spawn-outcome.js +0 -101
- package/dist/clients/dispatch/runners/utils/tool-failure.js +0 -235
- package/dist/clients/dispatch/runners/utils/toolchain-availability.js +0 -169
- package/dist/clients/dispatch/runners/utils.js +0 -15
- package/dist/clients/dispatch/runners/vale.js +0 -116
- package/dist/clients/dispatch/runners/yaml-rule-parser.js +0 -242
- package/dist/clients/dispatch/runners/yamllint.js +0 -85
- package/dist/clients/dispatch/runners/zig-check.js +0 -91
- package/dist/clients/dispatch/suppress-writer.js +0 -69
- package/dist/clients/dispatch/tool-profile.js +0 -30
- package/dist/clients/dispatch/types.js +0 -21
- package/dist/clients/dispatch/utils/format-utils.js +0 -45
- package/dist/clients/dispatch/utils/lsp-diagnostics.js +0 -35
- package/dist/clients/disposition-logger.js +0 -32
- package/dist/clients/disposition-publish.js +0 -124
- package/dist/clients/durable-store.js +0 -97
- package/dist/clients/effective-config.js +0 -413
- package/dist/clients/env-utils.js +0 -83
- package/dist/clients/error-class.js +0 -23
- package/dist/clients/eval-timestamp.js +0 -17
- package/dist/clients/event-loop-hold.js +0 -274
- package/dist/clients/event-loop-monitor.js +0 -250
- package/dist/clients/extension-log.js +0 -504
- package/dist/clients/extension-mode.js +0 -73
- package/dist/clients/feature-hints.js +0 -103
- package/dist/clients/file-kinds.js +0 -412
- package/dist/clients/file-role.js +0 -134
- package/dist/clients/file-time.js +0 -160
- package/dist/clients/file-utils.js +0 -1032
- package/dist/clients/finding-delivery-gate.js +0 -463
- package/dist/clients/finding-identity.js +0 -88
- package/dist/clients/fix-worklog.js +0 -103
- package/dist/clients/format-events-publish.js +0 -343
- package/dist/clients/format-service.js +0 -222
- package/dist/clients/formatters-lazy.js +0 -9
- package/dist/clients/formatters.js +0 -1994
- package/dist/clients/freshness-cadence.js +0 -17
- package/dist/clients/freshness.js +0 -38
- package/dist/clients/generated-artifacts.js +0 -394
- package/dist/clients/generation-guard.js +0 -215
- package/dist/clients/git-guard.js +0 -923
- package/dist/clients/git-tracked-ignore.js +0 -243
- package/dist/clients/gitleaks-client.js +0 -509
- package/dist/clients/go-client.js +0 -104
- package/dist/clients/govulncheck-client.js +0 -605
- package/dist/clients/gradle-ktfmt-style.js +0 -252
- package/dist/clients/grammar-source.js +0 -465
- package/dist/clients/gzip-stage-write.js +0 -135
- package/dist/clients/hashline-anchor.js +0 -424
- package/dist/clients/hook-budgets.js +0 -76
- package/dist/clients/host-edit-normalize.js +0 -140
- package/dist/clients/host-ports.js +0 -39
- package/dist/clients/indent-retarget.js +0 -154
- package/dist/clients/install-diagnostics.js +0 -143
- package/dist/clients/installer/index.js +0 -5167
- package/dist/clients/installer/managed-tool-refresh-session.js +0 -58
- package/dist/clients/installer/managed-tool-refresh.js +0 -783
- package/dist/clients/instance-reaper-state.js +0 -7
- package/dist/clients/instance-reaper.js +0 -1137
- package/dist/clients/instance-registry-lock.js +0 -145
- package/dist/clients/instance-registry.js +0 -773
- package/dist/clients/jscpd-client.js +0 -370
- package/dist/clients/json-cache-read.js +0 -65
- package/dist/clients/knip-client.js +0 -788
- package/dist/clients/language-policy.js +0 -252
- package/dist/clients/language-profile.js +0 -361
- package/dist/clients/language-registry.js +0 -603
- package/dist/clients/latency-logger.js +0 -719
- package/dist/clients/lazy-import.js +0 -21
- package/dist/clients/ledger-bounds.js +0 -54
- package/dist/clients/lens-config.js +0 -346
- package/dist/clients/lens-engine.js +0 -358
- package/dist/clients/lens-events.js +0 -125
- package/dist/clients/lens-flag-registry.js +0 -467
- package/dist/clients/lens-map.js +0 -1156
- package/dist/clients/live-bus-emitter.js +0 -74
- package/dist/clients/log-cleanup.js +0 -222
- package/dist/clients/lsp/aggregation.js +0 -178
- package/dist/clients/lsp/cascade-tier.js +0 -421
- package/dist/clients/lsp/client.js +0 -4465
- package/dist/clients/lsp/config.js +0 -689
- package/dist/clients/lsp/diagnostic-binding.js +0 -225
- package/dist/clients/lsp/document-drift.js +0 -467
- package/dist/clients/lsp/edits.js +0 -1219
- package/dist/clients/lsp/index.js +0 -8305
- package/dist/clients/lsp/inferred-project.js +0 -216
- package/dist/clients/lsp/jvm-runtime.js +0 -298
- package/dist/clients/lsp/language.js +0 -63
- package/dist/clients/lsp/launch.js +0 -725
- package/dist/clients/lsp/lombok.js +0 -158
- package/dist/clients/lsp/path-utils.js +0 -5
- package/dist/clients/lsp/pending-aux-coverage.js +0 -251
- package/dist/clients/lsp/position-encoding.js +0 -61
- package/dist/clients/lsp/ruby-drive-dirs.js +0 -83
- package/dist/clients/lsp/server.js +0 -3209
- package/dist/clients/lsp/session-roots.js +0 -192
- package/dist/clients/lsp/spawn-history.js +0 -17
- package/dist/clients/lsp/sync-kind.js +0 -42
- package/dist/clients/lsp/tsserver-sync.js +0 -332
- package/dist/clients/lsp/wait-policy/capability-snapshot.js +0 -1
- package/dist/clients/lsp/wait-policy/classification.js +0 -85
- package/dist/clients/lsp/wait-policy/index.js +0 -10
- package/dist/clients/lsp/wait-policy/strategies.js +0 -303
- package/dist/clients/lsp/watch-queue.js +0 -61
- package/dist/clients/lsp/workspace-diagnostics-cache.js +0 -639
- package/dist/clients/lsp/workspace-diagnostics-session.js +0 -30
- package/dist/clients/lsp/workspace-sweep-hold.js +0 -184
- package/dist/clients/lsp-budget.js +0 -186
- package/dist/clients/lsp-document-symbols.js +0 -110
- package/dist/clients/lsp-lazy.js +0 -9
- package/dist/clients/lsp-mutation.js +0 -396
- package/dist/clients/lsp-status.js +0 -59
- package/dist/clients/map-with-concurrency.js +0 -40
- package/dist/clients/mcp/analyze.js +0 -420
- package/dist/clients/mcp/host-shim.js +0 -31
- package/dist/clients/mcp/ipc.js +0 -335
- package/dist/clients/mcp/review.js +0 -151
- package/dist/clients/mcp/session.js +0 -412
- package/dist/clients/memory-sampler.js +0 -208
- package/dist/clients/message-end-attribution.js +0 -30
- package/dist/clients/metrics-client.js +0 -107
- package/dist/clients/metrics-history.js +0 -327
- package/dist/clients/middle-man-analysis.js +0 -263
- package/dist/clients/model-provider.js +0 -53
- package/dist/clients/module-report-lsp.js +0 -189
- package/dist/clients/module-report.js +0 -2150
- package/dist/clients/mutating-tool.js +0 -651
- package/dist/clients/mutation-attribution.js +0 -368
- package/dist/clients/mutation-bridge.js +0 -240
- package/dist/clients/ndjson-logger.js +0 -734
- package/dist/clients/observed-mutation-sources.js +0 -101
- package/dist/clients/observed-mutation.js +0 -1253
- package/dist/clients/oldtext-autopatch.js +0 -128
- package/dist/clients/opaque-mutation-scan.js +0 -496
- package/dist/clients/opengrep-client.js +0 -328
- package/dist/clients/opengrep-config.js +0 -76
- package/dist/clients/package-manager.js +0 -607
- package/dist/clients/package-root.js +0 -38
- package/dist/clients/partial-edit-apply.js +0 -439
- package/dist/clients/path-attribution-telemetry.js +0 -43
- package/dist/clients/path-keyed-map.js +0 -108
- package/dist/clients/path-utils.js +0 -1244
- package/dist/clients/performance-report.js +0 -331
- package/dist/clients/persist-debounce.js +0 -70
- package/dist/clients/persistent-reverify.js +0 -271
- package/dist/clients/php-cs-fixer-config.js +0 -119
- package/dist/clients/pipeline.js +0 -1425
- package/dist/clients/post-autofix-notice.js +0 -37
- package/dist/clients/print-mode.js +0 -21
- package/dist/clients/probe-home-state.js +0 -228
- package/dist/clients/process-bridge.js +0 -66
- package/dist/clients/process-singletons.js +0 -210
- package/dist/clients/process-snapshot.js +0 -68
- package/dist/clients/project-changes.js +0 -181
- package/dist/clients/project-conventions.js +0 -171
- package/dist/clients/project-diagnostics/cache.js +0 -137
- package/dist/clients/project-diagnostics/extractors.js +0 -109
- package/dist/clients/project-diagnostics/fresh-fetch.js +0 -650
- package/dist/clients/project-diagnostics/runner-adapters/call-graph-impact.js +0 -118
- package/dist/clients/project-diagnostics/runner-adapters/dead-code.js +0 -47
- package/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +0 -40
- package/dist/clients/project-diagnostics/runner-adapters/govulncheck.js +0 -34
- package/dist/clients/project-diagnostics/runner-adapters/jscpd.js +0 -38
- package/dist/clients/project-diagnostics/runner-adapters/knip.js +0 -47
- package/dist/clients/project-diagnostics/runner-adapters/madge.js +0 -48
- package/dist/clients/project-diagnostics/runner-adapters/opengrep.js +0 -40
- package/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +0 -127
- package/dist/clients/project-diagnostics/runner-adapters/trivy.js +0 -81
- package/dist/clients/project-diagnostics/scanner.js +0 -520
- package/dist/clients/project-diagnostics/types.js +0 -1
- package/dist/clients/project-lens-config.js +0 -799
- package/dist/clients/project-report.js +0 -701
- package/dist/clients/project-scale.js +0 -237
- package/dist/clients/project-scan-policy.js +0 -11
- package/dist/clients/project-snapshot-fingerprint.js +0 -48
- package/dist/clients/project-snapshot-persist-worker.js +0 -20
- package/dist/clients/project-snapshot.js +0 -1653
- package/dist/clients/project-trust.js +0 -181
- package/dist/clients/python-environment.js +0 -217
- package/dist/clients/python-provenance.js +0 -639
- package/dist/clients/quiet-window-config.js +0 -47
- package/dist/clients/quiet-window.js +0 -236
- package/dist/clients/read-bridge.js +0 -139
- package/dist/clients/read-expansion.js +0 -266
- package/dist/clients/read-guard-logger.js +0 -251
- package/dist/clients/read-guard-tool-lines.js +0 -1306
- package/dist/clients/read-guard.js +0 -1561
- package/dist/clients/recent-touches.js +0 -240
- package/dist/clients/redact/secrets.js +0 -449
- package/dist/clients/resource-sampler.js +0 -628
- package/dist/clients/reverse-deps.js +0 -270
- package/dist/clients/review-graph/builder.js +0 -5118
- package/dist/clients/review-graph/format.js +0 -33
- package/dist/clients/review-graph/git-identity.js +0 -157
- package/dist/clients/review-graph/import-resolvers.js +0 -481
- package/dist/clients/review-graph/persist-worker.js +0 -10
- package/dist/clients/review-graph/query.js +0 -244
- package/dist/clients/review-graph/revision-drift.js +0 -21
- package/dist/clients/review-graph/service.js +0 -96
- package/dist/clients/review-graph/shared-extraction-ir.js +0 -82
- package/dist/clients/review-graph/symbol-id.js +0 -103
- package/dist/clients/review-graph/tsconfig-paths.js +0 -299
- package/dist/clients/review-graph/types.js +0 -1
- package/dist/clients/review-graph/workspace-modules.js +0 -449
- package/dist/clients/review-graph-logger.js +0 -81
- package/dist/clients/ruff-client.js +0 -152
- package/dist/clients/rules-scanner.js +0 -131
- package/dist/clients/run-duration.js +0 -55
- package/dist/clients/runtime-agent-end.js +0 -746
- package/dist/clients/runtime-config.js +0 -77
- package/dist/clients/runtime-context.js +0 -211
- package/dist/clients/runtime-coordinator.js +0 -1290
- package/dist/clients/runtime-session.js +0 -2485
- package/dist/clients/runtime-tool-call.js +0 -1284
- package/dist/clients/runtime-tool-result.js +0 -2034
- package/dist/clients/runtime-turn.js +0 -3600
- package/dist/clients/rust-client.js +0 -97
- package/dist/clients/safe-spawn.js +0 -2166
- package/dist/clients/sanitize.js +0 -286
- package/dist/clients/scan-utils.js +0 -25
- package/dist/clients/scratch-tree-policy.js +0 -165
- package/dist/clients/search-read-registration.js +0 -94
- package/dist/clients/secret-findings.js +0 -114
- package/dist/clients/security-scan-client.js +0 -352
- package/dist/clients/session-event-guard.js +0 -297
- package/dist/clients/session-lifecycle.js +0 -484
- package/dist/clients/session-start-observability.js +0 -94
- package/dist/clients/session-state-store.js +0 -101
- package/dist/clients/session-summary.js +0 -15
- package/dist/clients/sessionstart-logger.js +0 -27
- package/dist/clients/sg-runner.js +0 -876
- package/dist/clients/sgconfig.js +0 -347
- package/dist/clients/shared-checkout-guard.js +0 -338
- package/dist/clients/single-flight.js +0 -158
- package/dist/clients/situational-tool-telemetry.js +0 -108
- package/dist/clients/skills-resolver.js +0 -141
- package/dist/clients/slow-fs.js +0 -138
- package/dist/clients/smells-rollup.js +0 -231
- package/dist/clients/source-filter.js +0 -596
- package/dist/clients/source-walker.js +0 -211
- package/dist/clients/spawn-output-cap.js +0 -37
- package/dist/clients/spawn-timeout-cooldown.js +0 -110
- package/dist/clients/stale-marker.js +0 -17
- package/dist/clients/startup-scan.js +0 -400
- package/dist/clients/startup-timing.js +0 -130
- package/dist/clients/string-utils.js +0 -33
- package/dist/clients/subagent-mode.js +0 -111
- package/dist/clients/symbol-containment.js +0 -24
- package/dist/clients/symbol-types.js +0 -5
- package/dist/clients/test-runner-client.js +0 -2507
- package/dist/clients/test-runner-delivery.js +0 -287
- package/dist/clients/todo-scanner.js +0 -229
- package/dist/clients/tool-agreement.js +0 -423
- package/dist/clients/tool-config.js +0 -249
- package/dist/clients/tool-cwd.js +0 -270
- package/dist/clients/tool-definition.js +0 -47
- package/dist/clients/tool-event.js +0 -105
- package/dist/clients/tool-policy.js +0 -2755
- package/dist/clients/tool-probe.js +0 -53
- package/dist/clients/tool-render.js +0 -156
- package/dist/clients/tool-set-policy.js +0 -118
- package/dist/clients/tree-sitter-cache.js +0 -364
- package/dist/clients/tree-sitter-client.js +0 -4134
- package/dist/clients/tree-sitter-logger.js +0 -100
- package/dist/clients/tree-sitter-navigator.js +0 -269
- package/dist/clients/tree-sitter-query-loader.js +0 -569
- package/dist/clients/tree-sitter-shared.js +0 -158
- package/dist/clients/tree-sitter-symbol-extractor.js +0 -1265
- package/dist/clients/trivy-client.js +0 -467
- package/dist/clients/tui-fit.js +0 -50
- package/dist/clients/turn-context.js +0 -52
- package/dist/clients/turn-summary-render.js +0 -72
- package/dist/clients/turn-summary.js +0 -132
- package/dist/clients/typos-config.js +0 -29
- package/dist/clients/user-notify.js +0 -51
- package/dist/clients/vanished-instance-marker.js +0 -57
- package/dist/clients/warm-attach.js +0 -246
- package/dist/clients/widget-state.js +0 -1677
- package/dist/clients/word-index-logger.js +0 -49
- package/dist/clients/word-index-store.js +0 -459
- package/dist/clients/word-index.js +0 -2080
- package/dist/clients/workspace-topology.js +0 -389
- package/dist/clients/write-ordering-guard.js +0 -65
- package/dist/clients/zizmor-config.js +0 -327
- package/dist/i18n.js +0 -69
- package/dist/mcp/build-staleness.js +0 -124
- package/dist/scripts/lib/process-scan.mjs +0 -583
- package/dist/scripts/lib/skills-predicate.mjs +0 -129
- package/dist/tools/activate-tools.js +0 -87
- package/dist/tools/ast-grep-outline.js +0 -137
- package/dist/tools/ast-grep-replace.js +0 -244
- package/dist/tools/ast-grep-search.js +0 -762
- package/dist/tools/effective-config.js +0 -90
- package/dist/tools/lens-diagnostic-mark.js +0 -375
- package/dist/tools/lens-diagnostics.js +0 -2544
- package/dist/tools/lsp-diagnostics.js +0 -1634
- package/dist/tools/lsp-navigation.js +0 -1367
- package/dist/tools/lsp-structured-output.js +0 -294
- package/dist/tools/module-report.js +0 -382
- package/dist/tools/project-report.js +0 -86
- package/dist/tools/render-compact.js +0 -374
- package/dist/tools/scan-progress.js +0 -53
- package/dist/tools/shared.js +0 -29
- package/dist/tools/symbol-search.js +0 -155
|
@@ -0,0 +1,1610 @@
|
|
|
1
|
+
import { createRequire as __pilensCreateRequire } from "node:module"; const require = __pilensCreateRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
deserializeWordIndex,
|
|
4
|
+
recordPersistedWordIndexWireBytes,
|
|
5
|
+
serializeWordIndex
|
|
6
|
+
} from "./chunk-YGVYKNSN.js";
|
|
7
|
+
import {
|
|
8
|
+
fingerprintProjectSnapshotJson
|
|
9
|
+
} from "./chunk-2BEMIWEW.js";
|
|
10
|
+
import {
|
|
11
|
+
getProjectDataDir,
|
|
12
|
+
isStaleStageFile,
|
|
13
|
+
withGenerationLockSync
|
|
14
|
+
} from "./chunk-VN2AXLEX.js";
|
|
15
|
+
import {
|
|
16
|
+
writeFileAtomic
|
|
17
|
+
} from "./chunk-2EECBNC5.js";
|
|
18
|
+
import {
|
|
19
|
+
incrementDegradationCount
|
|
20
|
+
} from "./chunk-N3YQJI6O.js";
|
|
21
|
+
import {
|
|
22
|
+
logLatency
|
|
23
|
+
} from "./chunk-5THXD6X5.js";
|
|
24
|
+
import {
|
|
25
|
+
BoundedFifoMap
|
|
26
|
+
} from "./chunk-ABBOA7UD.js";
|
|
27
|
+
import {
|
|
28
|
+
normalizeMapKey
|
|
29
|
+
} from "./chunk-Q5U6FMDI.js";
|
|
30
|
+
|
|
31
|
+
// dist/clients/project-snapshot.js
|
|
32
|
+
import * as fs3 from "node:fs";
|
|
33
|
+
import * as path2 from "node:path";
|
|
34
|
+
import { fileURLToPath } from "node:url";
|
|
35
|
+
import { Worker } from "node:worker_threads";
|
|
36
|
+
import { gunzipSync, gzipSync } from "node:zlib";
|
|
37
|
+
|
|
38
|
+
// dist/clients/json-cache-read.js
|
|
39
|
+
import * as fs from "node:fs";
|
|
40
|
+
import { promises as fsPromises } from "node:fs";
|
|
41
|
+
function readJsonCache(path3, validate, onError) {
|
|
42
|
+
try {
|
|
43
|
+
const parsed = JSON.parse(fs.readFileSync(path3, "utf-8"));
|
|
44
|
+
return validate(parsed);
|
|
45
|
+
} catch (err) {
|
|
46
|
+
try {
|
|
47
|
+
onError?.(err);
|
|
48
|
+
} catch {
|
|
49
|
+
}
|
|
50
|
+
return void 0;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
async function readJsonCacheAsync(path3, validate, onError) {
|
|
54
|
+
try {
|
|
55
|
+
const raw = await fsPromises.readFile(path3, "utf-8");
|
|
56
|
+
const parsed = JSON.parse(raw);
|
|
57
|
+
return validate(parsed);
|
|
58
|
+
} catch (err) {
|
|
59
|
+
try {
|
|
60
|
+
onError?.(err);
|
|
61
|
+
} catch {
|
|
62
|
+
}
|
|
63
|
+
return void 0;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// dist/clients/project-conventions.js
|
|
68
|
+
import * as fs2 from "node:fs";
|
|
69
|
+
import * as path from "node:path";
|
|
70
|
+
function readPackageJson(cwd) {
|
|
71
|
+
const pkgPath = path.join(cwd, "package.json");
|
|
72
|
+
try {
|
|
73
|
+
const raw = fs2.readFileSync(pkgPath, "utf-8");
|
|
74
|
+
return JSON.parse(raw);
|
|
75
|
+
} catch {
|
|
76
|
+
return void 0;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function hasDep(pkg, name) {
|
|
80
|
+
if (!pkg)
|
|
81
|
+
return false;
|
|
82
|
+
return Boolean(pkg.dependencies?.[name] ?? pkg.devDependencies?.[name] ?? pkg.peerDependencies?.[name]);
|
|
83
|
+
}
|
|
84
|
+
function fileExists(cwd, ...segments) {
|
|
85
|
+
try {
|
|
86
|
+
return fs2.existsSync(path.join(cwd, ...segments));
|
|
87
|
+
} catch {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function dirExists(cwd, ...segments) {
|
|
92
|
+
try {
|
|
93
|
+
const target = path.join(cwd, ...segments);
|
|
94
|
+
const stat = fs2.statSync(target);
|
|
95
|
+
return stat.isDirectory();
|
|
96
|
+
} catch {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function detectReact(_cwd, pkg) {
|
|
101
|
+
const signals = [];
|
|
102
|
+
if (hasDep(pkg, "react"))
|
|
103
|
+
signals.push("package.json:dependencies.react");
|
|
104
|
+
if (hasDep(pkg, "react-dom"))
|
|
105
|
+
signals.push("package.json:dependencies.react-dom");
|
|
106
|
+
if (hasDep(pkg, "@types/react"))
|
|
107
|
+
signals.push("package.json:devDependencies.@types/react");
|
|
108
|
+
if (signals.length === 0)
|
|
109
|
+
return void 0;
|
|
110
|
+
const confidence = hasDep(pkg, "react-dom") ? "high" : "medium";
|
|
111
|
+
return { id: "react", confidence, signals };
|
|
112
|
+
}
|
|
113
|
+
function detectNext(cwd, pkg) {
|
|
114
|
+
const signals = [];
|
|
115
|
+
if (hasDep(pkg, "next"))
|
|
116
|
+
signals.push("package.json:dependencies.next");
|
|
117
|
+
for (const candidate of [
|
|
118
|
+
"next.config.js",
|
|
119
|
+
"next.config.mjs",
|
|
120
|
+
"next.config.ts"
|
|
121
|
+
]) {
|
|
122
|
+
if (fileExists(cwd, candidate))
|
|
123
|
+
signals.push(candidate);
|
|
124
|
+
}
|
|
125
|
+
if (dirExists(cwd, "src", "pages"))
|
|
126
|
+
signals.push("src/pages/");
|
|
127
|
+
else if (dirExists(cwd, "pages"))
|
|
128
|
+
signals.push("pages/");
|
|
129
|
+
if (dirExists(cwd, "src", "app"))
|
|
130
|
+
signals.push("src/app/");
|
|
131
|
+
else if (dirExists(cwd, "app"))
|
|
132
|
+
signals.push("app/");
|
|
133
|
+
if (signals.length === 0)
|
|
134
|
+
return void 0;
|
|
135
|
+
const confidence = hasDep(pkg, "next") && signals.some((s) => s.startsWith("next.config.")) ? "high" : hasDep(pkg, "next") ? "medium" : "low";
|
|
136
|
+
return { id: "next", confidence, signals };
|
|
137
|
+
}
|
|
138
|
+
function detectVite(cwd, pkg) {
|
|
139
|
+
const signals = [];
|
|
140
|
+
if (hasDep(pkg, "vite"))
|
|
141
|
+
signals.push("package.json:devDependencies.vite");
|
|
142
|
+
for (const candidate of [
|
|
143
|
+
"vite.config.ts",
|
|
144
|
+
"vite.config.js",
|
|
145
|
+
"vite.config.mjs",
|
|
146
|
+
"vite.config.mts"
|
|
147
|
+
]) {
|
|
148
|
+
if (fileExists(cwd, candidate))
|
|
149
|
+
signals.push(candidate);
|
|
150
|
+
}
|
|
151
|
+
if (signals.length === 0)
|
|
152
|
+
return void 0;
|
|
153
|
+
const confidence = hasDep(pkg, "vite") && signals.some((s) => s.startsWith("vite.config.")) ? "high" : "medium";
|
|
154
|
+
return { id: "vite", confidence, signals };
|
|
155
|
+
}
|
|
156
|
+
function detectVitest(cwd, pkg) {
|
|
157
|
+
const signals = [];
|
|
158
|
+
if (hasDep(pkg, "vitest"))
|
|
159
|
+
signals.push("package.json:devDependencies.vitest");
|
|
160
|
+
for (const candidate of [
|
|
161
|
+
"vitest.config.ts",
|
|
162
|
+
"vitest.config.js",
|
|
163
|
+
"vitest.config.mjs",
|
|
164
|
+
"vitest.config.mts"
|
|
165
|
+
]) {
|
|
166
|
+
if (fileExists(cwd, candidate))
|
|
167
|
+
signals.push(candidate);
|
|
168
|
+
}
|
|
169
|
+
if (signals.length === 0)
|
|
170
|
+
return void 0;
|
|
171
|
+
const confidence = hasDep(pkg, "vitest") ? "high" : "medium";
|
|
172
|
+
return { id: "vitest", confidence, signals };
|
|
173
|
+
}
|
|
174
|
+
var AGENT_DOC_CANDIDATES = [
|
|
175
|
+
"AGENTS.md",
|
|
176
|
+
"CLAUDE.md",
|
|
177
|
+
".cursorrules"
|
|
178
|
+
];
|
|
179
|
+
function summarizeAgentDocs(cwd) {
|
|
180
|
+
const docs = [];
|
|
181
|
+
for (const candidate of AGENT_DOC_CANDIDATES) {
|
|
182
|
+
const abs = path.join(cwd, candidate);
|
|
183
|
+
try {
|
|
184
|
+
const raw = fs2.readFileSync(abs, "utf-8");
|
|
185
|
+
const lineCount = raw.split(/\r?\n/).length;
|
|
186
|
+
docs.push({ filePath: candidate, lineCount });
|
|
187
|
+
} catch {
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return docs;
|
|
191
|
+
}
|
|
192
|
+
function detectProjectConventions(cwd) {
|
|
193
|
+
let cwdExists = false;
|
|
194
|
+
try {
|
|
195
|
+
cwdExists = fs2.statSync(cwd).isDirectory();
|
|
196
|
+
} catch {
|
|
197
|
+
cwdExists = false;
|
|
198
|
+
}
|
|
199
|
+
if (!cwdExists) {
|
|
200
|
+
return { frameworks: [], testRunners: [], buildTools: [], agentDocs: [] };
|
|
201
|
+
}
|
|
202
|
+
const pkg = readPackageJson(cwd);
|
|
203
|
+
const detectors = [detectReact, detectNext, detectVite, detectVitest];
|
|
204
|
+
const frameworks = [];
|
|
205
|
+
for (const detector of detectors) {
|
|
206
|
+
const detection = detector(cwd, pkg);
|
|
207
|
+
if (detection)
|
|
208
|
+
frameworks.push(detection);
|
|
209
|
+
}
|
|
210
|
+
const testRunners = [];
|
|
211
|
+
if (frameworks.some((f) => f.id === "vitest"))
|
|
212
|
+
testRunners.push("vitest");
|
|
213
|
+
const buildTools = [];
|
|
214
|
+
if (frameworks.some((f) => f.id === "vite"))
|
|
215
|
+
buildTools.push("vite");
|
|
216
|
+
if (frameworks.some((f) => f.id === "next"))
|
|
217
|
+
buildTools.push("next");
|
|
218
|
+
const agentDocs = summarizeAgentDocs(cwd);
|
|
219
|
+
return { frameworks, testRunners, buildTools, agentDocs };
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// dist/clients/persist-worker-stats.js
|
|
223
|
+
async function readWorkerHeapStatistics(worker) {
|
|
224
|
+
const stats = await worker.getHeapStatistics();
|
|
225
|
+
return {
|
|
226
|
+
heapUsedBytes: stats.used_heap_size,
|
|
227
|
+
heapTotalBytes: stats.total_heap_size,
|
|
228
|
+
heapSizeLimitBytes: stats.heap_size_limit
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// dist/clients/project-snapshot.js
|
|
233
|
+
var PROJECT_SNAPSHOT_VERSION = 2;
|
|
234
|
+
function parseSequenceIndex(value) {
|
|
235
|
+
if (!value || typeof value !== "object")
|
|
236
|
+
return void 0;
|
|
237
|
+
const index = value;
|
|
238
|
+
if (typeof index.projectSeq !== "number")
|
|
239
|
+
return void 0;
|
|
240
|
+
if (!Array.isArray(index.fileSeqByPath))
|
|
241
|
+
return void 0;
|
|
242
|
+
const fileSeqByPath = index.fileSeqByPath.filter((entry) => Array.isArray(entry) && typeof entry[0] === "string" && typeof entry[1] === "number");
|
|
243
|
+
return { projectSeq: index.projectSeq, fileSeqByPath };
|
|
244
|
+
}
|
|
245
|
+
function getProjectSnapshotPath(cwd) {
|
|
246
|
+
return path2.join(getProjectDataDir(cwd), "cache", "project-snapshot.json.gz");
|
|
247
|
+
}
|
|
248
|
+
function getProjectSnapshotLegacyPath(cwd) {
|
|
249
|
+
return path2.join(getProjectDataDir(cwd), "cache", "project-snapshot.json");
|
|
250
|
+
}
|
|
251
|
+
function getProjectSnapshotMetaPath(cwd) {
|
|
252
|
+
return path2.join(getProjectDataDir(cwd), "cache", "project-snapshot.meta.json");
|
|
253
|
+
}
|
|
254
|
+
var INCOMPLETE_STORED_SEQ = -2;
|
|
255
|
+
function storedSeq(snapshot) {
|
|
256
|
+
return snapshot.incomplete ? { seq: INCOMPLETE_STORED_SEQ, incompleteSeq: snapshot.seq } : { seq: snapshot.seq };
|
|
257
|
+
}
|
|
258
|
+
function storedSnapshot(snapshot) {
|
|
259
|
+
if (!snapshot.incomplete)
|
|
260
|
+
return snapshot;
|
|
261
|
+
const stored = { ...snapshot };
|
|
262
|
+
delete stored.incomplete;
|
|
263
|
+
return { ...stored, ...storedSeq(snapshot) };
|
|
264
|
+
}
|
|
265
|
+
function readStoredSeq(stored) {
|
|
266
|
+
if (typeof stored.incompleteSeq === "number") {
|
|
267
|
+
return { seq: stored.incompleteSeq, incomplete: true };
|
|
268
|
+
}
|
|
269
|
+
return typeof stored.seq === "number" ? { seq: stored.seq } : null;
|
|
270
|
+
}
|
|
271
|
+
function isProjectSnapshotFresh(snapshot, currentProjectSeq, unlockedThrough = 0) {
|
|
272
|
+
return !!snapshot && snapshot.version === PROJECT_SNAPSHOT_VERSION && !snapshot.incomplete && (snapshot.logEntries ?? 0) >= unlockedThrough && snapshot.seq === currentProjectSeq;
|
|
273
|
+
}
|
|
274
|
+
function parseSnapshot(value) {
|
|
275
|
+
if (!value || typeof value !== "object")
|
|
276
|
+
return null;
|
|
277
|
+
const snapshot = value;
|
|
278
|
+
if (snapshot.version !== PROJECT_SNAPSHOT_VERSION)
|
|
279
|
+
return null;
|
|
280
|
+
if (typeof snapshot.projectRoot !== "string")
|
|
281
|
+
return null;
|
|
282
|
+
if (typeof snapshot.generatedAt !== "string")
|
|
283
|
+
return null;
|
|
284
|
+
const stored = readStoredSeq(value);
|
|
285
|
+
if (!stored)
|
|
286
|
+
return null;
|
|
287
|
+
if (!Array.isArray(snapshot.cachedExports))
|
|
288
|
+
return null;
|
|
289
|
+
return {
|
|
290
|
+
version: PROJECT_SNAPSHOT_VERSION,
|
|
291
|
+
projectRoot: snapshot.projectRoot,
|
|
292
|
+
generatedAt: snapshot.generatedAt,
|
|
293
|
+
seq: stored.seq,
|
|
294
|
+
files: snapshot.files ?? {},
|
|
295
|
+
symbols: snapshot.symbols ?? {},
|
|
296
|
+
reverseDeps: snapshot.reverseDeps ?? {},
|
|
297
|
+
cachedExports: snapshot.cachedExports.filter((entry) => Array.isArray(entry) && typeof entry[0] === "string" && typeof entry[1] === "string"),
|
|
298
|
+
...stored.incomplete ? { incomplete: true } : {},
|
|
299
|
+
logEntries: typeof snapshot.logEntries === "number" ? snapshot.logEntries : void 0,
|
|
300
|
+
sequenceIndex: parseSequenceIndex(snapshot.sequenceIndex),
|
|
301
|
+
wordIndex: snapshot.wordIndex,
|
|
302
|
+
projectRulesScan: snapshot.projectRulesScan,
|
|
303
|
+
startupScan: snapshot.startupScan,
|
|
304
|
+
languageProfile: snapshot.languageProfile,
|
|
305
|
+
conventions: snapshot.conventions
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
function parseSnapshotMeta(value) {
|
|
309
|
+
if (!value || typeof value !== "object")
|
|
310
|
+
return null;
|
|
311
|
+
const meta = value;
|
|
312
|
+
if (typeof meta.version !== "number")
|
|
313
|
+
return null;
|
|
314
|
+
const stored = readStoredSeq(value);
|
|
315
|
+
if (!stored)
|
|
316
|
+
return null;
|
|
317
|
+
return {
|
|
318
|
+
timestamp: typeof meta.timestamp === "string" ? meta.timestamp : "",
|
|
319
|
+
version: meta.version,
|
|
320
|
+
seq: stored.seq,
|
|
321
|
+
fingerprint: typeof meta.fingerprint === "string" && /^[a-f0-9]{64}$/.test(meta.fingerprint) ? meta.fingerprint : void 0,
|
|
322
|
+
gzBytes: typeof meta.gzBytes === "number" && Number.isInteger(meta.gzBytes) && meta.gzBytes > 0 ? meta.gzBytes : void 0,
|
|
323
|
+
...stored.incomplete ? { incomplete: true } : {},
|
|
324
|
+
logEntries: typeof meta.logEntries === "number" ? meta.logEntries : void 0,
|
|
325
|
+
sequenceIndex: parseSequenceIndex(meta.sequenceIndex)
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
function readProjectSnapshotMeta(cwd) {
|
|
329
|
+
const meta = readJsonCache(getProjectSnapshotMetaPath(cwd), (parsed) => parseSnapshotMeta(parsed) ?? void 0);
|
|
330
|
+
return meta ?? null;
|
|
331
|
+
}
|
|
332
|
+
function isProjectSnapshotMetaStale(meta, currentProjectSeq, unlockedThrough = 0) {
|
|
333
|
+
return meta.version !== PROJECT_SNAPSHOT_VERSION || meta.incomplete === true || (meta.logEntries ?? 0) < unlockedThrough || meta.seq !== currentProjectSeq;
|
|
334
|
+
}
|
|
335
|
+
var SNAPSHOT_PARSE_CACHE_MAX = 4;
|
|
336
|
+
var SNAPSHOT_PARSE_CACHE_MAX_BYTES = 24 * 1024 * 1024;
|
|
337
|
+
var snapshotParseCache = new BoundedFifoMap(SNAPSHOT_PARSE_CACHE_MAX);
|
|
338
|
+
function withoutWordIndex(snapshot) {
|
|
339
|
+
if (!snapshot?.wordIndex)
|
|
340
|
+
return snapshot;
|
|
341
|
+
const { wordIndex: _releasedPostings, ...stripped } = snapshot;
|
|
342
|
+
return stripped;
|
|
343
|
+
}
|
|
344
|
+
function cacheParsedSnapshot(snapshotPath, entry) {
|
|
345
|
+
snapshotParseCache.delete(snapshotPath);
|
|
346
|
+
snapshotParseCache.set(snapshotPath, entry);
|
|
347
|
+
}
|
|
348
|
+
var authoritativeSnapshots = /* @__PURE__ */ new Map();
|
|
349
|
+
var PROJECT_SNAPSHOT_MAX_WARM_ROOTS = 8;
|
|
350
|
+
var PROJECT_SNAPSHOT_IDLE_EVICT_MS_DEFAULT = 20 * 6e4;
|
|
351
|
+
function projectSnapshotIdleEvictMs() {
|
|
352
|
+
const value = Number.parseInt(process.env.PI_LENS_PROJECT_SNAPSHOT_IDLE_EVICT_MS ?? "", 10);
|
|
353
|
+
return Number.isSafeInteger(value) && value > 0 ? value : PROJECT_SNAPSHOT_IDLE_EVICT_MS_DEFAULT;
|
|
354
|
+
}
|
|
355
|
+
function clearAuthoritativeSnapshotTimer(entry) {
|
|
356
|
+
if (entry.idleTimer)
|
|
357
|
+
clearTimeout(entry.idleTimer);
|
|
358
|
+
entry.idleTimer = void 0;
|
|
359
|
+
}
|
|
360
|
+
function deleteAuthoritativeSnapshot(key) {
|
|
361
|
+
const entry = authoritativeSnapshots.get(key);
|
|
362
|
+
if (entry)
|
|
363
|
+
clearAuthoritativeSnapshotTimer(entry);
|
|
364
|
+
authoritativeSnapshots.delete(key);
|
|
365
|
+
}
|
|
366
|
+
function scheduleAuthoritativeSnapshotEviction(key, entry) {
|
|
367
|
+
clearAuthoritativeSnapshotTimer(entry);
|
|
368
|
+
const generation = entry.lastUsedAt;
|
|
369
|
+
entry.idleTimer = setTimeout(() => {
|
|
370
|
+
entry.idleTimer = void 0;
|
|
371
|
+
if (authoritativeSnapshots.get(key) !== entry || entry.lastUsedAt !== generation)
|
|
372
|
+
return;
|
|
373
|
+
deleteAuthoritativeSnapshot(key);
|
|
374
|
+
}, projectSnapshotIdleEvictMs());
|
|
375
|
+
entry.idleTimer.unref?.();
|
|
376
|
+
}
|
|
377
|
+
function touchAuthoritativeSnapshot(key, entry) {
|
|
378
|
+
entry.lastUsedAt = Date.now();
|
|
379
|
+
scheduleAuthoritativeSnapshotEviction(key, entry);
|
|
380
|
+
}
|
|
381
|
+
function enforceAuthoritativeSnapshotCap() {
|
|
382
|
+
while (authoritativeSnapshots.size > PROJECT_SNAPSHOT_MAX_WARM_ROOTS) {
|
|
383
|
+
const victim = [...authoritativeSnapshots.entries()].sort(([, a], [, b]) => a.lastUsedAt - b.lastUsedAt)[0];
|
|
384
|
+
if (!victim)
|
|
385
|
+
return;
|
|
386
|
+
clearAuthoritativeSnapshotTimer(victim[1]);
|
|
387
|
+
deleteAuthoritativeSnapshot(victim[0]);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
function _getAuthoritativeSnapshotCacheKeysForTests() {
|
|
391
|
+
return [...authoritativeSnapshots.entries()].sort(([, a], [, b]) => a.lastUsedAt - b.lastUsedAt).map(([key]) => key);
|
|
392
|
+
}
|
|
393
|
+
function _resetProjectSnapshotParseCacheForTests() {
|
|
394
|
+
snapshotParseCache.clear();
|
|
395
|
+
for (const entry of authoritativeSnapshots.values())
|
|
396
|
+
clearAuthoritativeSnapshotTimer(entry);
|
|
397
|
+
authoritativeSnapshots.clear();
|
|
398
|
+
}
|
|
399
|
+
function _projectSnapshotParseCacheRetainsWordIndexForTests() {
|
|
400
|
+
return [...snapshotParseCache.values()].some((entry) => entry.snapshot?.wordIndex !== void 0);
|
|
401
|
+
}
|
|
402
|
+
function resolveSnapshotBodyPath(cwd) {
|
|
403
|
+
const gzPath = getProjectSnapshotPath(cwd);
|
|
404
|
+
try {
|
|
405
|
+
const stat = fs3.statSync(gzPath);
|
|
406
|
+
return { path: gzPath, gz: true, mtimeMs: stat.mtimeMs, size: stat.size };
|
|
407
|
+
} catch {
|
|
408
|
+
}
|
|
409
|
+
const legacyPath = getProjectSnapshotLegacyPath(cwd);
|
|
410
|
+
try {
|
|
411
|
+
const stat = fs3.statSync(legacyPath);
|
|
412
|
+
return {
|
|
413
|
+
path: legacyPath,
|
|
414
|
+
gz: false,
|
|
415
|
+
mtimeMs: stat.mtimeMs,
|
|
416
|
+
size: stat.size
|
|
417
|
+
};
|
|
418
|
+
} catch {
|
|
419
|
+
return null;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
var _snapshotBodyReadCountForTests = 0;
|
|
423
|
+
function getSnapshotBodyReadCountForTests() {
|
|
424
|
+
return _snapshotBodyReadCountForTests;
|
|
425
|
+
}
|
|
426
|
+
function resetSnapshotBodyReadCountForTests() {
|
|
427
|
+
_snapshotBodyReadCountForTests = 0;
|
|
428
|
+
}
|
|
429
|
+
function readSnapshotBody(bodyPath, gz) {
|
|
430
|
+
_snapshotBodyReadCountForTests++;
|
|
431
|
+
if (!gz) {
|
|
432
|
+
const snapshot = readJsonCache(bodyPath, (parsed) => parseSnapshot(parsed) ?? void 0) ?? null;
|
|
433
|
+
let rawBytes = 0;
|
|
434
|
+
try {
|
|
435
|
+
rawBytes = fs3.statSync(bodyPath).size;
|
|
436
|
+
} catch {
|
|
437
|
+
}
|
|
438
|
+
return { snapshot, rawBytes };
|
|
439
|
+
}
|
|
440
|
+
try {
|
|
441
|
+
const json = gunzipSync(fs3.readFileSync(bodyPath)).toString("utf-8");
|
|
442
|
+
const snapshot = parseSnapshot(JSON.parse(json)) ?? null;
|
|
443
|
+
return { snapshot, rawBytes: Buffer.byteLength(json) };
|
|
444
|
+
} catch (err) {
|
|
445
|
+
logLatency({
|
|
446
|
+
type: "phase",
|
|
447
|
+
phase: "project_snapshot_body_corrupt",
|
|
448
|
+
filePath: bodyPath,
|
|
449
|
+
durationMs: 0,
|
|
450
|
+
metadata: { error: err instanceof Error ? err.message : String(err) }
|
|
451
|
+
});
|
|
452
|
+
return { snapshot: null, rawBytes: 0 };
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
function skipJsonValue(text, start) {
|
|
456
|
+
let i = start;
|
|
457
|
+
while (i < text.length && /\s/.test(text[i]))
|
|
458
|
+
i++;
|
|
459
|
+
const ch = text[i];
|
|
460
|
+
if (ch === '"') {
|
|
461
|
+
i++;
|
|
462
|
+
while (i < text.length) {
|
|
463
|
+
if (text[i] === "\\") {
|
|
464
|
+
i += 2;
|
|
465
|
+
continue;
|
|
466
|
+
}
|
|
467
|
+
if (text[i] === '"') {
|
|
468
|
+
i++;
|
|
469
|
+
break;
|
|
470
|
+
}
|
|
471
|
+
i++;
|
|
472
|
+
}
|
|
473
|
+
return i;
|
|
474
|
+
}
|
|
475
|
+
if (ch === "{" || ch === "[") {
|
|
476
|
+
const open = ch;
|
|
477
|
+
const close = open === "{" ? "}" : "]";
|
|
478
|
+
let depth = 0;
|
|
479
|
+
let inString = false;
|
|
480
|
+
for (; i < text.length; i++) {
|
|
481
|
+
const c = text[i];
|
|
482
|
+
if (inString) {
|
|
483
|
+
if (c === "\\") {
|
|
484
|
+
i++;
|
|
485
|
+
continue;
|
|
486
|
+
}
|
|
487
|
+
if (c === '"')
|
|
488
|
+
inString = false;
|
|
489
|
+
continue;
|
|
490
|
+
}
|
|
491
|
+
if (c === '"') {
|
|
492
|
+
inString = true;
|
|
493
|
+
continue;
|
|
494
|
+
}
|
|
495
|
+
if (c === open)
|
|
496
|
+
depth++;
|
|
497
|
+
else if (c === close) {
|
|
498
|
+
depth--;
|
|
499
|
+
if (depth === 0) {
|
|
500
|
+
i++;
|
|
501
|
+
break;
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
return i;
|
|
506
|
+
}
|
|
507
|
+
while (i < text.length && !",}]".includes(text[i]))
|
|
508
|
+
i++;
|
|
509
|
+
return i;
|
|
510
|
+
}
|
|
511
|
+
function stripTopLevelJsonKeys(text, keysToStrip) {
|
|
512
|
+
const objStart = text.indexOf("{");
|
|
513
|
+
if (objStart === -1)
|
|
514
|
+
return text;
|
|
515
|
+
let out = text.slice(0, objStart + 1);
|
|
516
|
+
let i = objStart + 1;
|
|
517
|
+
let wroteField = false;
|
|
518
|
+
while (i < text.length) {
|
|
519
|
+
while (i < text.length && /\s/.test(text[i]))
|
|
520
|
+
i++;
|
|
521
|
+
if (text[i] === "}" || i >= text.length) {
|
|
522
|
+
out += text.slice(i);
|
|
523
|
+
break;
|
|
524
|
+
}
|
|
525
|
+
if (text[i] === ",") {
|
|
526
|
+
i++;
|
|
527
|
+
continue;
|
|
528
|
+
}
|
|
529
|
+
const keyStart = i;
|
|
530
|
+
const keyTextEnd = skipJsonValue(text, keyStart);
|
|
531
|
+
let key;
|
|
532
|
+
try {
|
|
533
|
+
key = JSON.parse(text.slice(keyStart, keyTextEnd));
|
|
534
|
+
} catch {
|
|
535
|
+
return text;
|
|
536
|
+
}
|
|
537
|
+
let j = keyTextEnd;
|
|
538
|
+
while (j < text.length && /\s/.test(text[j]))
|
|
539
|
+
j++;
|
|
540
|
+
const valueStart = j + 1;
|
|
541
|
+
const valueEnd = skipJsonValue(text, valueStart);
|
|
542
|
+
if (!keysToStrip.has(key)) {
|
|
543
|
+
out += (wroteField ? "," : "") + text.slice(keyStart, valueEnd);
|
|
544
|
+
wroteField = true;
|
|
545
|
+
}
|
|
546
|
+
i = valueEnd;
|
|
547
|
+
}
|
|
548
|
+
return out;
|
|
549
|
+
}
|
|
550
|
+
function _stripTopLevelJsonKeysForTests(text, keysToStrip) {
|
|
551
|
+
return stripTopLevelJsonKeys(text, new Set(keysToStrip));
|
|
552
|
+
}
|
|
553
|
+
var HEAVY_SNAPSHOT_KEYS = /* @__PURE__ */ new Set([
|
|
554
|
+
"wordIndex",
|
|
555
|
+
"files",
|
|
556
|
+
"symbols",
|
|
557
|
+
"reverseDeps"
|
|
558
|
+
]);
|
|
559
|
+
var NARROW_DIGEST_HEAVY_KEY_LITERALS = [
|
|
560
|
+
"wordIndex",
|
|
561
|
+
"files",
|
|
562
|
+
"symbols",
|
|
563
|
+
"reverseDeps"
|
|
564
|
+
];
|
|
565
|
+
var _lastNarrowParseDigestForTests;
|
|
566
|
+
function getLastNarrowParseDigestForTests() {
|
|
567
|
+
return _lastNarrowParseDigestForTests;
|
|
568
|
+
}
|
|
569
|
+
function resetLastNarrowParseDigestForTests() {
|
|
570
|
+
_lastNarrowParseDigestForTests = void 0;
|
|
571
|
+
}
|
|
572
|
+
function parseExportsAndRulesOnly(json) {
|
|
573
|
+
const narrowed = stripTopLevelJsonKeys(json, HEAVY_SNAPSHOT_KEYS);
|
|
574
|
+
_lastNarrowParseDigestForTests = {
|
|
575
|
+
length: narrowed.length,
|
|
576
|
+
containsHeavyKey: NARROW_DIGEST_HEAVY_KEY_LITERALS.some((key) => narrowed.includes(`"${key}":`))
|
|
577
|
+
};
|
|
578
|
+
const parsed = JSON.parse(narrowed);
|
|
579
|
+
if (parsed.version !== PROJECT_SNAPSHOT_VERSION)
|
|
580
|
+
return null;
|
|
581
|
+
const stored = readStoredSeq(parsed);
|
|
582
|
+
if (!stored)
|
|
583
|
+
return null;
|
|
584
|
+
if (!Array.isArray(parsed.cachedExports))
|
|
585
|
+
return null;
|
|
586
|
+
return {
|
|
587
|
+
version: PROJECT_SNAPSHOT_VERSION,
|
|
588
|
+
seq: stored.seq,
|
|
589
|
+
...stored.incomplete ? { incomplete: true } : {},
|
|
590
|
+
logEntries: typeof parsed.logEntries === "number" ? parsed.logEntries : void 0,
|
|
591
|
+
cachedExports: parsed.cachedExports.filter((entry) => Array.isArray(entry) && typeof entry[0] === "string" && typeof entry[1] === "string"),
|
|
592
|
+
projectRulesScan: parsed.projectRulesScan
|
|
593
|
+
};
|
|
594
|
+
}
|
|
595
|
+
function readSnapshotExportsAndRulesBody(bodyPath, gz) {
|
|
596
|
+
try {
|
|
597
|
+
const json = gz ? gunzipSync(fs3.readFileSync(bodyPath)).toString("utf-8") : fs3.readFileSync(bodyPath, "utf-8");
|
|
598
|
+
return parseExportsAndRulesOnly(json);
|
|
599
|
+
} catch (err) {
|
|
600
|
+
logLatency({
|
|
601
|
+
type: "phase",
|
|
602
|
+
phase: "project_snapshot_body_corrupt",
|
|
603
|
+
filePath: bodyPath,
|
|
604
|
+
durationMs: 0,
|
|
605
|
+
metadata: {
|
|
606
|
+
error: err instanceof Error ? err.message : String(err),
|
|
607
|
+
narrow: true
|
|
608
|
+
}
|
|
609
|
+
});
|
|
610
|
+
return null;
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
function loadProjectSnapshotExportsAndRules(cwd) {
|
|
614
|
+
const key = normalizeMapKey(cwd);
|
|
615
|
+
const body = resolveSnapshotBodyPath(cwd);
|
|
616
|
+
const authoritative = authoritativeSnapshots.get(key);
|
|
617
|
+
if (authoritative) {
|
|
618
|
+
const notSuperseded = body === null || body.mtimeMs <= authoritative.knownMtime && body.size === authoritative.knownSize;
|
|
619
|
+
if (notSuperseded) {
|
|
620
|
+
const { version, seq, incomplete, logEntries, cachedExports, projectRulesScan } = authoritative.snapshot;
|
|
621
|
+
return {
|
|
622
|
+
version,
|
|
623
|
+
seq,
|
|
624
|
+
...incomplete ? { incomplete } : {},
|
|
625
|
+
logEntries,
|
|
626
|
+
cachedExports,
|
|
627
|
+
projectRulesScan
|
|
628
|
+
};
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
if (!body)
|
|
632
|
+
return null;
|
|
633
|
+
return readSnapshotExportsAndRulesBody(body.path, body.gz);
|
|
634
|
+
}
|
|
635
|
+
function loadProjectSnapshotInternal(cwd, requireWordIndex) {
|
|
636
|
+
const key = normalizeMapKey(cwd);
|
|
637
|
+
const body = resolveSnapshotBodyPath(cwd);
|
|
638
|
+
const authoritative = authoritativeSnapshots.get(key);
|
|
639
|
+
if (authoritative) {
|
|
640
|
+
const notSuperseded = body === null || body.mtimeMs <= authoritative.knownMtime && body.size === authoritative.knownSize;
|
|
641
|
+
if (notSuperseded) {
|
|
642
|
+
touchAuthoritativeSnapshot(key, authoritative);
|
|
643
|
+
return authoritative.snapshot;
|
|
644
|
+
}
|
|
645
|
+
deleteAuthoritativeSnapshot(key);
|
|
646
|
+
}
|
|
647
|
+
if (!body) {
|
|
648
|
+
snapshotParseCache.delete(getProjectSnapshotPath(cwd));
|
|
649
|
+
return null;
|
|
650
|
+
}
|
|
651
|
+
const cacheKey = body.path;
|
|
652
|
+
const cached = snapshotParseCache.get(cacheKey);
|
|
653
|
+
if (cached && cached.mtimeMs === body.mtimeMs && cached.size === body.size) {
|
|
654
|
+
if (!requireWordIndex || !cached.snapshot || cached.snapshot.wordIndex) {
|
|
655
|
+
return cached.snapshot;
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
const { snapshot, rawBytes } = readSnapshotBody(body.path, body.gz);
|
|
659
|
+
const cacheSnapshot = withoutWordIndex(snapshot);
|
|
660
|
+
if (rawBytes > 0 && (rawBytes <= SNAPSHOT_PARSE_CACHE_MAX_BYTES || snapshot?.wordIndex)) {
|
|
661
|
+
cacheParsedSnapshot(cacheKey, {
|
|
662
|
+
mtimeMs: body.mtimeMs,
|
|
663
|
+
size: body.size,
|
|
664
|
+
snapshot: cacheSnapshot
|
|
665
|
+
});
|
|
666
|
+
} else {
|
|
667
|
+
snapshotParseCache.delete(cacheKey);
|
|
668
|
+
}
|
|
669
|
+
return snapshot;
|
|
670
|
+
}
|
|
671
|
+
function loadProjectSnapshot(cwd) {
|
|
672
|
+
return loadProjectSnapshotInternal(cwd, true);
|
|
673
|
+
}
|
|
674
|
+
function loadProjectSnapshotWithoutWordIndex(cwd) {
|
|
675
|
+
return loadProjectSnapshotInternal(cwd, false);
|
|
676
|
+
}
|
|
677
|
+
var _snapshotGenerationStates = /* @__PURE__ */ new Map();
|
|
678
|
+
var _successfulSnapshotPersists = new BoundedFifoMap(PROJECT_SNAPSHOT_MAX_WARM_ROOTS);
|
|
679
|
+
var _failedSnapshotPersists = new BoundedFifoMap(PROJECT_SNAPSHOT_MAX_WARM_ROOTS);
|
|
680
|
+
var _activeSnapshotPersists = /* @__PURE__ */ new Map();
|
|
681
|
+
var _queuedSnapshotPersists = /* @__PURE__ */ new Map();
|
|
682
|
+
var _snapshotWorkerRequests = /* @__PURE__ */ new Map();
|
|
683
|
+
var _snapshotPersistWorker;
|
|
684
|
+
var _snapshotWorkerRequestId = 0;
|
|
685
|
+
var _snapshotWorkerDisabled = false;
|
|
686
|
+
var _snapshotGenerationGateEnabledForTests = true;
|
|
687
|
+
var _snapshotPromotionSeamForTests;
|
|
688
|
+
var _lastSnapshotPersistErrorForTests;
|
|
689
|
+
var _snapshotExiting = false;
|
|
690
|
+
var _snapshotWorkerBodyWritesForTests = 0;
|
|
691
|
+
var _snapshotPersistWorkerHeapStatistics = null;
|
|
692
|
+
function refreshProjectSnapshotPersistWorkerHeapStatistics() {
|
|
693
|
+
const worker = _snapshotPersistWorker;
|
|
694
|
+
if (!worker || typeof worker.getHeapStatistics !== "function") {
|
|
695
|
+
return Promise.resolve();
|
|
696
|
+
}
|
|
697
|
+
return readWorkerHeapStatistics(worker).then((stats) => {
|
|
698
|
+
if (_snapshotPersistWorker === worker)
|
|
699
|
+
_snapshotPersistWorkerHeapStatistics = stats;
|
|
700
|
+
}).catch(() => {
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
function getProjectSnapshotPersistWorkerHeapStatistics() {
|
|
704
|
+
return _snapshotPersistWorkerHeapStatistics;
|
|
705
|
+
}
|
|
706
|
+
function snapshotWorkerEnabled() {
|
|
707
|
+
const raw = process.env.PI_LENS_SNAPSHOT_PERSIST_SYNC;
|
|
708
|
+
return !(raw === "1" || raw === "true");
|
|
709
|
+
}
|
|
710
|
+
function pendingSnapshotIsCurrent(pending) {
|
|
711
|
+
return !_snapshotGenerationGateEnabledForTests || _snapshotGenerationStates.get(pending.key)?.generation === pending.generation;
|
|
712
|
+
}
|
|
713
|
+
function rememberSuccessfulSnapshotPersist(key, record) {
|
|
714
|
+
_successfulSnapshotPersists.delete(key);
|
|
715
|
+
_successfulSnapshotPersists.set(key, record);
|
|
716
|
+
}
|
|
717
|
+
function assessSnapshotBodyIntegrity(meta, body) {
|
|
718
|
+
if (meta.gzBytes === void 0) {
|
|
719
|
+
return { outcome: "legacy-meta", actualBytes: body.size };
|
|
720
|
+
}
|
|
721
|
+
if (!body.gz || body.size !== meta.gzBytes) {
|
|
722
|
+
return {
|
|
723
|
+
outcome: "size-mismatch",
|
|
724
|
+
expectedGzBytes: meta.gzBytes,
|
|
725
|
+
actualBytes: body.size
|
|
726
|
+
};
|
|
727
|
+
}
|
|
728
|
+
return {
|
|
729
|
+
outcome: "ok",
|
|
730
|
+
expectedGzBytes: meta.gzBytes,
|
|
731
|
+
actualBytes: body.size
|
|
732
|
+
};
|
|
733
|
+
}
|
|
734
|
+
function noteSnapshotBodyIntegrityWithheld(args) {
|
|
735
|
+
incrementDegradationCount({
|
|
736
|
+
kind: "snapshot-integrity",
|
|
737
|
+
subject: args.gzPath,
|
|
738
|
+
reason: args.verdict
|
|
739
|
+
});
|
|
740
|
+
logLatency({
|
|
741
|
+
type: "phase",
|
|
742
|
+
phase: "project_snapshot_body_integrity",
|
|
743
|
+
filePath: args.gzPath,
|
|
744
|
+
durationMs: 0,
|
|
745
|
+
metadata: {
|
|
746
|
+
outcome: "dedupe_withheld",
|
|
747
|
+
reason: args.verdict,
|
|
748
|
+
...args.seq !== void 0 ? { seq: args.seq } : {},
|
|
749
|
+
...args.expectedGzBytes === void 0 ? {} : { expectedGzBytes: args.expectedGzBytes },
|
|
750
|
+
actualBytes: args.actualBytes
|
|
751
|
+
}
|
|
752
|
+
});
|
|
753
|
+
}
|
|
754
|
+
function noteSnapshotSkipRefused(args) {
|
|
755
|
+
logLatency({
|
|
756
|
+
type: "phase",
|
|
757
|
+
phase: "project_snapshot_body_integrity",
|
|
758
|
+
filePath: args.gzPath,
|
|
759
|
+
durationMs: 0,
|
|
760
|
+
metadata: {
|
|
761
|
+
outcome: "skip_refused_rewrite",
|
|
762
|
+
reason: args.verdict,
|
|
763
|
+
seq: args.seq
|
|
764
|
+
}
|
|
765
|
+
});
|
|
766
|
+
}
|
|
767
|
+
function snapshotPersistBaselinesFor(cwd, key) {
|
|
768
|
+
const local = _successfulSnapshotPersists.get(key);
|
|
769
|
+
const meta = readProjectSnapshotMeta(cwd);
|
|
770
|
+
const body = resolveSnapshotBodyPath(cwd);
|
|
771
|
+
if (!meta?.fingerprint || !body) {
|
|
772
|
+
if (!body)
|
|
773
|
+
_successfulSnapshotPersists.delete(key);
|
|
774
|
+
return { fingerprints: [] };
|
|
775
|
+
}
|
|
776
|
+
const integrity = assessSnapshotBodyIntegrity(meta, body);
|
|
777
|
+
if (integrity.outcome !== "ok") {
|
|
778
|
+
noteSnapshotBodyIntegrityWithheld({
|
|
779
|
+
gzPath: getProjectSnapshotPath(cwd),
|
|
780
|
+
verdict: integrity.outcome,
|
|
781
|
+
seq: meta.seq,
|
|
782
|
+
expectedGzBytes: integrity.expectedGzBytes,
|
|
783
|
+
actualBytes: integrity.actualBytes
|
|
784
|
+
});
|
|
785
|
+
return { fingerprints: [] };
|
|
786
|
+
}
|
|
787
|
+
const durable = {
|
|
788
|
+
seq: meta.seq,
|
|
789
|
+
fingerprint: meta.fingerprint,
|
|
790
|
+
generatedAt: meta.timestamp,
|
|
791
|
+
generation: _snapshotGenerationStates.get(key)?.generation ?? 0,
|
|
792
|
+
gzBytes: meta.gzBytes
|
|
793
|
+
};
|
|
794
|
+
const fingerprints = [durable.fingerprint];
|
|
795
|
+
if (local && local.fingerprint !== durable.fingerprint) {
|
|
796
|
+
fingerprints.push(local.fingerprint);
|
|
797
|
+
}
|
|
798
|
+
return { durable, fingerprints, integrity: "ok" };
|
|
799
|
+
}
|
|
800
|
+
function seedSnapshotPersistBaselineFromDurable(key, durable) {
|
|
801
|
+
if (!durable || _successfulSnapshotPersists.has(key))
|
|
802
|
+
return;
|
|
803
|
+
rememberSuccessfulSnapshotPersist(key, durable);
|
|
804
|
+
}
|
|
805
|
+
function writeProjectSnapshotMeta(metaPath, snapshot, bodyRecord) {
|
|
806
|
+
writeFileAtomic(metaPath, JSON.stringify({
|
|
807
|
+
timestamp: bodyRecord?.generatedAt ?? snapshot.generatedAt,
|
|
808
|
+
version: snapshot.version,
|
|
809
|
+
...storedSeq(snapshot),
|
|
810
|
+
...bodyRecord ? {
|
|
811
|
+
fingerprint: bodyRecord.fingerprint,
|
|
812
|
+
...bodyRecord.gzBytes === void 0 ? {} : { gzBytes: bodyRecord.gzBytes }
|
|
813
|
+
} : {},
|
|
814
|
+
logEntries: snapshot.logEntries,
|
|
815
|
+
...snapshot.sequenceIndex ? { sequenceIndex: snapshot.sequenceIndex } : {}
|
|
816
|
+
}), { bestEffort: false });
|
|
817
|
+
}
|
|
818
|
+
function recordSnapshotPersistFailure(pending, error, bodyPersisted = false) {
|
|
819
|
+
_lastSnapshotPersistErrorForTests = error;
|
|
820
|
+
_failedSnapshotPersists.set(pending.key, {
|
|
821
|
+
seq: pending.snapshot.seq,
|
|
822
|
+
generation: pending.generation
|
|
823
|
+
});
|
|
824
|
+
deleteAuthoritativeSnapshot(pending.key);
|
|
825
|
+
logLatency({
|
|
826
|
+
type: "phase",
|
|
827
|
+
phase: "project_snapshot_persist_failed",
|
|
828
|
+
filePath: pending.gzPath,
|
|
829
|
+
durationMs: 0,
|
|
830
|
+
metadata: {
|
|
831
|
+
error,
|
|
832
|
+
seq: pending.snapshot.seq,
|
|
833
|
+
outcome: bodyPersisted ? "metadata_repair_required" : "failed",
|
|
834
|
+
...bodyPersisted ? { bodyPersisted: true } : {}
|
|
835
|
+
}
|
|
836
|
+
});
|
|
837
|
+
}
|
|
838
|
+
function logSnapshotPersistSuccess(pending, fingerprint, stats) {
|
|
839
|
+
rememberSuccessfulSnapshotPersist(pending.key, {
|
|
840
|
+
seq: pending.snapshot.seq,
|
|
841
|
+
fingerprint,
|
|
842
|
+
generatedAt: pending.snapshot.generatedAt,
|
|
843
|
+
generation: pending.generation,
|
|
844
|
+
rawBytes: stats.rawBytes,
|
|
845
|
+
gzBytes: stats.gzBytes
|
|
846
|
+
});
|
|
847
|
+
_failedSnapshotPersists.delete(pending.key);
|
|
848
|
+
logLatency({
|
|
849
|
+
type: "phase",
|
|
850
|
+
phase: "project_snapshot_persist",
|
|
851
|
+
filePath: pending.gzPath,
|
|
852
|
+
durationMs: stats.serializeMs + stats.writeMs,
|
|
853
|
+
metadata: { seq: pending.snapshot.seq, outcome: "executed", ...stats }
|
|
854
|
+
});
|
|
855
|
+
}
|
|
856
|
+
function logSnapshotPersistDecision(args) {
|
|
857
|
+
logLatency({
|
|
858
|
+
type: "phase",
|
|
859
|
+
phase: "project_snapshot_persist_decision",
|
|
860
|
+
filePath: getProjectSnapshotPath(args.cwd),
|
|
861
|
+
durationMs: 0,
|
|
862
|
+
metadata: {
|
|
863
|
+
seq: args.seq,
|
|
864
|
+
decision: args.decision,
|
|
865
|
+
...args.fingerprint ? { fingerprint: args.fingerprint.slice(0, 12) } : {},
|
|
866
|
+
...args.avoidedRawBytes === void 0 ? {} : { avoidedRawBytes: args.avoidedRawBytes },
|
|
867
|
+
...args.avoidedGzipBytes === void 0 ? {} : { avoidedGzipBytes: args.avoidedGzipBytes },
|
|
868
|
+
...args.diskSeq === void 0 ? {} : { diskSeq: args.diskSeq }
|
|
869
|
+
}
|
|
870
|
+
});
|
|
871
|
+
}
|
|
872
|
+
function reconcileAuthoritativeAfterWrite(pending, rawBytes) {
|
|
873
|
+
const entry = authoritativeSnapshots.get(pending.key);
|
|
874
|
+
if (!entry || entry.snapshot !== pending.snapshot)
|
|
875
|
+
return;
|
|
876
|
+
if (pending.snapshot.wordIndex) {
|
|
877
|
+
try {
|
|
878
|
+
const stat = fs3.statSync(pending.gzPath);
|
|
879
|
+
cacheParsedSnapshot(pending.gzPath, {
|
|
880
|
+
mtimeMs: stat.mtimeMs,
|
|
881
|
+
size: stat.size,
|
|
882
|
+
snapshot: withoutWordIndex(pending.snapshot)
|
|
883
|
+
});
|
|
884
|
+
} catch {
|
|
885
|
+
}
|
|
886
|
+
deleteAuthoritativeSnapshot(pending.key);
|
|
887
|
+
logLatency({
|
|
888
|
+
type: "phase",
|
|
889
|
+
phase: "project_snapshot_word_index_released",
|
|
890
|
+
filePath: pending.gzPath,
|
|
891
|
+
durationMs: 0,
|
|
892
|
+
metadata: { rawBytes }
|
|
893
|
+
});
|
|
894
|
+
return;
|
|
895
|
+
}
|
|
896
|
+
if (rawBytes > SNAPSHOT_PARSE_CACHE_MAX_BYTES) {
|
|
897
|
+
logLatency({
|
|
898
|
+
type: "phase",
|
|
899
|
+
phase: "project_snapshot_authoritative_dropped_oversized",
|
|
900
|
+
filePath: pending.gzPath,
|
|
901
|
+
durationMs: 0,
|
|
902
|
+
metadata: { rawBytes, maxBytes: SNAPSHOT_PARSE_CACHE_MAX_BYTES }
|
|
903
|
+
});
|
|
904
|
+
deleteAuthoritativeSnapshot(pending.key);
|
|
905
|
+
return;
|
|
906
|
+
}
|
|
907
|
+
try {
|
|
908
|
+
const stat = fs3.statSync(pending.gzPath);
|
|
909
|
+
entry.knownMtime = stat.mtimeMs;
|
|
910
|
+
entry.knownSize = stat.size;
|
|
911
|
+
} catch {
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
function finalizeProjectSnapshotMeta(pending, record) {
|
|
915
|
+
try {
|
|
916
|
+
writeProjectSnapshotMeta(getProjectSnapshotMetaPath(pending.cwd), pending.snapshot, record);
|
|
917
|
+
return true;
|
|
918
|
+
} catch (err) {
|
|
919
|
+
recordSnapshotPersistFailure(pending, err instanceof Error ? err.message : String(err), true);
|
|
920
|
+
return false;
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
function completeSnapshotPersist(pending) {
|
|
924
|
+
if (_activeSnapshotPersists.get(pending.key) !== pending)
|
|
925
|
+
return;
|
|
926
|
+
_activeSnapshotPersists.delete(pending.key);
|
|
927
|
+
if (_snapshotExiting)
|
|
928
|
+
return;
|
|
929
|
+
const queued = _queuedSnapshotPersists.get(pending.key);
|
|
930
|
+
if (!queued)
|
|
931
|
+
return;
|
|
932
|
+
_queuedSnapshotPersists.delete(pending.key);
|
|
933
|
+
dispatchSnapshotPersist(queued);
|
|
934
|
+
}
|
|
935
|
+
var SNAPSHOT_CACHE_LOCK = { staleMs: 5e3, waitMs: 500 };
|
|
936
|
+
function withSnapshotCacheLock(gzPath, purpose, op) {
|
|
937
|
+
const result = withGenerationLockSync(`${gzPath}.locks`, SNAPSHOT_CACHE_LOCK, op);
|
|
938
|
+
if (!result.held) {
|
|
939
|
+
const code = result.cause?.code;
|
|
940
|
+
incrementDegradationCount({
|
|
941
|
+
kind: "project-snapshot-lock-unavailable",
|
|
942
|
+
subject: gzPath,
|
|
943
|
+
reason: `${purpose} skipped: ${code ? `lock failed (${code})` : "lock wait ran out"}`
|
|
944
|
+
});
|
|
945
|
+
}
|
|
946
|
+
return result;
|
|
947
|
+
}
|
|
948
|
+
function promoteSnapshotBody(pending, body, record) {
|
|
949
|
+
const dropStage = () => {
|
|
950
|
+
if ("stagePath" in body)
|
|
951
|
+
fs3.rmSync(body.stagePath, { force: true });
|
|
952
|
+
};
|
|
953
|
+
const locked = withSnapshotCacheLock(pending.gzPath, "body promotion", () => {
|
|
954
|
+
const onDisk = readProjectSnapshotMeta(pending.cwd);
|
|
955
|
+
if (onDisk && onDisk.seq > pending.snapshot.seq) {
|
|
956
|
+
dropStage();
|
|
957
|
+
return onDisk.seq;
|
|
958
|
+
}
|
|
959
|
+
if ("stagePath" in body)
|
|
960
|
+
fs3.renameSync(body.stagePath, pending.gzPath);
|
|
961
|
+
else
|
|
962
|
+
writeFileAtomic(pending.gzPath, body.gzip, { bestEffort: false });
|
|
963
|
+
fs3.rmSync(pending.legacyPath, { force: true });
|
|
964
|
+
return finalizeProjectSnapshotMeta(pending, record);
|
|
965
|
+
});
|
|
966
|
+
if (!locked.held) {
|
|
967
|
+
dropStage();
|
|
968
|
+
recordSnapshotPersistFailure(pending, "project snapshot cache lock unavailable");
|
|
969
|
+
return false;
|
|
970
|
+
}
|
|
971
|
+
if (typeof locked.value === "boolean")
|
|
972
|
+
return locked.value;
|
|
973
|
+
deleteAuthoritativeSnapshot(pending.key);
|
|
974
|
+
logSnapshotPersistDecision({
|
|
975
|
+
cwd: pending.cwd,
|
|
976
|
+
seq: pending.snapshot.seq,
|
|
977
|
+
decision: "superseded_on_disk",
|
|
978
|
+
diskSeq: locked.value
|
|
979
|
+
});
|
|
980
|
+
return false;
|
|
981
|
+
}
|
|
982
|
+
function serializeSnapshotBody(snapshot) {
|
|
983
|
+
const started = performance.now();
|
|
984
|
+
const stored = storedSnapshot(snapshot);
|
|
985
|
+
const spliced = stored.wordIndex === void 0 ? void 0 : spliceWordIndexBody(stored);
|
|
986
|
+
const bytes = spliced?.bytes ?? new TextEncoder().encode(JSON.stringify(stored));
|
|
987
|
+
return {
|
|
988
|
+
bytes,
|
|
989
|
+
serializeMs: performance.now() - started,
|
|
990
|
+
wordIndexWireBytes: spliced?.wordIndexWireBytes
|
|
991
|
+
};
|
|
992
|
+
}
|
|
993
|
+
var WORD_INDEX_PLACEHOLDER = `\0pi-lens-word-index-${process.pid}-${Date.now()}\0`;
|
|
994
|
+
var WORD_INDEX_KEY_JSON = '"wordIndex":';
|
|
995
|
+
var WORD_INDEX_PLACEHOLDER_JSON = `${WORD_INDEX_KEY_JSON}${JSON.stringify(WORD_INDEX_PLACEHOLDER)}`;
|
|
996
|
+
function spliceWordIndexBody(stored) {
|
|
997
|
+
const marker = WORD_INDEX_PLACEHOLDER_JSON;
|
|
998
|
+
const head = JSON.stringify({ ...stored, wordIndex: WORD_INDEX_PLACEHOLDER });
|
|
999
|
+
const at = head.indexOf(marker);
|
|
1000
|
+
if (at < 0)
|
|
1001
|
+
return void 0;
|
|
1002
|
+
const prefix = head.slice(0, at + WORD_INDEX_KEY_JSON.length);
|
|
1003
|
+
const suffix = head.slice(at + marker.length);
|
|
1004
|
+
const wordIndex = JSON.stringify(stored.wordIndex);
|
|
1005
|
+
const prefixBytes = Buffer.byteLength(prefix);
|
|
1006
|
+
const wordIndexWireBytes = Buffer.byteLength(wordIndex);
|
|
1007
|
+
const bytes = new Uint8Array(prefixBytes + wordIndexWireBytes + Buffer.byteLength(suffix));
|
|
1008
|
+
const encoder = new TextEncoder();
|
|
1009
|
+
encoder.encodeInto(prefix, bytes.subarray(0, prefixBytes));
|
|
1010
|
+
encoder.encodeInto(wordIndex, bytes.subarray(prefixBytes, prefixBytes + wordIndexWireBytes));
|
|
1011
|
+
encoder.encodeInto(suffix, bytes.subarray(prefixBytes + wordIndexWireBytes));
|
|
1012
|
+
return { bytes, wordIndexWireBytes };
|
|
1013
|
+
}
|
|
1014
|
+
function writeSnapshotBodyOnMainThread(pending, reason) {
|
|
1015
|
+
if (!pendingSnapshotIsCurrent(pending)) {
|
|
1016
|
+
completeSnapshotPersist(pending);
|
|
1017
|
+
return;
|
|
1018
|
+
}
|
|
1019
|
+
if (reason) {
|
|
1020
|
+
logLatency({
|
|
1021
|
+
type: "phase",
|
|
1022
|
+
phase: "project_snapshot_worker_fallback",
|
|
1023
|
+
filePath: pending.gzPath,
|
|
1024
|
+
durationMs: 0,
|
|
1025
|
+
metadata: {
|
|
1026
|
+
reason,
|
|
1027
|
+
seq: pending.snapshot.seq,
|
|
1028
|
+
degraded: reason !== "exit_hook"
|
|
1029
|
+
}
|
|
1030
|
+
});
|
|
1031
|
+
}
|
|
1032
|
+
try {
|
|
1033
|
+
const { bytes, serializeMs, wordIndexWireBytes } = serializeSnapshotBody(pending.snapshot);
|
|
1034
|
+
pending.wordIndexWireBytes = wordIndexWireBytes;
|
|
1035
|
+
const rawBytes = bytes.byteLength;
|
|
1036
|
+
const fingerprint = fingerprintProjectSnapshotJson(bytes, pending.snapshot.generatedAt);
|
|
1037
|
+
if (pending.dedupeFingerprints.includes(fingerprint)) {
|
|
1038
|
+
const current = snapshotPersistBaselinesFor(pending.cwd, pending.key);
|
|
1039
|
+
if (current.integrity === "ok") {
|
|
1040
|
+
const prior = current.durable ?? pending.durablePersist;
|
|
1041
|
+
if (authoritativeSnapshots.get(pending.key)?.snapshot === pending.snapshot) {
|
|
1042
|
+
deleteAuthoritativeSnapshot(pending.key);
|
|
1043
|
+
}
|
|
1044
|
+
logSnapshotPersistDecision({
|
|
1045
|
+
cwd: pending.cwd,
|
|
1046
|
+
seq: pending.snapshot.seq,
|
|
1047
|
+
fingerprint,
|
|
1048
|
+
decision: "skipped_unchanged",
|
|
1049
|
+
avoidedRawBytes: rawBytes,
|
|
1050
|
+
avoidedGzipBytes: prior?.gzBytes
|
|
1051
|
+
});
|
|
1052
|
+
return;
|
|
1053
|
+
}
|
|
1054
|
+
if (current.integrity !== void 0) {
|
|
1055
|
+
noteSnapshotSkipRefused({
|
|
1056
|
+
gzPath: pending.gzPath,
|
|
1057
|
+
verdict: current.integrity,
|
|
1058
|
+
seq: pending.snapshot.seq
|
|
1059
|
+
});
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
const writeStarted = performance.now();
|
|
1063
|
+
const gzip = gzipSync(bytes);
|
|
1064
|
+
fs3.mkdirSync(path2.dirname(pending.gzPath), { recursive: true });
|
|
1065
|
+
const promoted = promoteSnapshotBody(pending, { gzip }, {
|
|
1066
|
+
fingerprint,
|
|
1067
|
+
generatedAt: pending.snapshot.generatedAt,
|
|
1068
|
+
gzBytes: gzip.byteLength
|
|
1069
|
+
});
|
|
1070
|
+
if (!promoted)
|
|
1071
|
+
return;
|
|
1072
|
+
recordPersistedWordIndexWireBytes(pending.snapshot.wordIndex, pending.wordIndexWireBytes);
|
|
1073
|
+
reconcileAuthoritativeAfterWrite(pending, rawBytes);
|
|
1074
|
+
logSnapshotPersistSuccess(pending, fingerprint, {
|
|
1075
|
+
rawBytes,
|
|
1076
|
+
gzBytes: gzip.byteLength,
|
|
1077
|
+
serializeMs,
|
|
1078
|
+
writeMs: performance.now() - writeStarted,
|
|
1079
|
+
offloaded: false
|
|
1080
|
+
});
|
|
1081
|
+
if (reason)
|
|
1082
|
+
_lastSnapshotPersistErrorForTests = reason;
|
|
1083
|
+
} catch (err) {
|
|
1084
|
+
recordSnapshotPersistFailure(pending, err instanceof Error ? err.message : String(err));
|
|
1085
|
+
} finally {
|
|
1086
|
+
completeSnapshotPersist(pending);
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
function dispatchMainThreadWriteThroughSeam(pending, reason) {
|
|
1090
|
+
if (_snapshotPromotionSeamForTests) {
|
|
1091
|
+
void _snapshotPromotionSeamForTests().then(() => writeSnapshotBodyOnMainThread(pending, reason));
|
|
1092
|
+
return;
|
|
1093
|
+
}
|
|
1094
|
+
writeSnapshotBodyOnMainThread(pending, reason);
|
|
1095
|
+
}
|
|
1096
|
+
function handleSnapshotWorkerResult(result) {
|
|
1097
|
+
const pending = _snapshotWorkerRequests.get(result.id);
|
|
1098
|
+
if (!pending) {
|
|
1099
|
+
fs3.rmSync(result.stagePath, { force: true });
|
|
1100
|
+
return;
|
|
1101
|
+
}
|
|
1102
|
+
_snapshotWorkerRequests.delete(result.id);
|
|
1103
|
+
if (result.error || result.rawBytes === void 0 || result.gzBytes === void 0 || result.serializeMs === void 0 || result.writeMs === void 0 || result.semanticFingerprint === void 0) {
|
|
1104
|
+
fs3.rmSync(result.stagePath, { force: true });
|
|
1105
|
+
dispatchMainThreadWriteThroughSeam(pending, result.error ?? "invalid worker result");
|
|
1106
|
+
return;
|
|
1107
|
+
}
|
|
1108
|
+
if (!result.skippedUnchanged)
|
|
1109
|
+
_snapshotWorkerBodyWritesForTests++;
|
|
1110
|
+
if (_snapshotGenerationGateEnabledForTests && _snapshotGenerationStates.get(pending.key)?.generation !== result.generation) {
|
|
1111
|
+
fs3.rmSync(result.stagePath, { force: true });
|
|
1112
|
+
completeSnapshotPersist(pending);
|
|
1113
|
+
return;
|
|
1114
|
+
}
|
|
1115
|
+
if (result.skippedUnchanged) {
|
|
1116
|
+
const baselines = snapshotPersistBaselinesFor(pending.cwd, pending.key);
|
|
1117
|
+
if (baselines.integrity !== "ok") {
|
|
1118
|
+
if (baselines.integrity !== void 0) {
|
|
1119
|
+
noteSnapshotSkipRefused({
|
|
1120
|
+
gzPath: pending.gzPath,
|
|
1121
|
+
verdict: baselines.integrity,
|
|
1122
|
+
seq: pending.snapshot.seq
|
|
1123
|
+
});
|
|
1124
|
+
}
|
|
1125
|
+
dispatchMainThreadWriteThroughSeam(pending, "snapshot body integrity regressed");
|
|
1126
|
+
return;
|
|
1127
|
+
}
|
|
1128
|
+
const prior = baselines.durable ?? pending.durablePersist;
|
|
1129
|
+
if (authoritativeSnapshots.get(pending.key)?.snapshot === pending.snapshot) {
|
|
1130
|
+
deleteAuthoritativeSnapshot(pending.key);
|
|
1131
|
+
}
|
|
1132
|
+
logSnapshotPersistDecision({
|
|
1133
|
+
cwd: pending.cwd,
|
|
1134
|
+
seq: pending.snapshot.seq,
|
|
1135
|
+
fingerprint: result.semanticFingerprint,
|
|
1136
|
+
decision: "skipped_unchanged",
|
|
1137
|
+
avoidedRawBytes: result.rawBytes,
|
|
1138
|
+
avoidedGzipBytes: prior?.gzBytes
|
|
1139
|
+
});
|
|
1140
|
+
completeSnapshotPersist(pending);
|
|
1141
|
+
return;
|
|
1142
|
+
}
|
|
1143
|
+
try {
|
|
1144
|
+
const promoted = promoteSnapshotBody(pending, { stagePath: result.stagePath }, {
|
|
1145
|
+
fingerprint: result.semanticFingerprint,
|
|
1146
|
+
generatedAt: pending.snapshot.generatedAt,
|
|
1147
|
+
gzBytes: result.gzBytes
|
|
1148
|
+
});
|
|
1149
|
+
if (!promoted) {
|
|
1150
|
+
completeSnapshotPersist(pending);
|
|
1151
|
+
return;
|
|
1152
|
+
}
|
|
1153
|
+
recordPersistedWordIndexWireBytes(pending.snapshot.wordIndex, pending.wordIndexWireBytes);
|
|
1154
|
+
reconcileAuthoritativeAfterWrite(pending, result.rawBytes);
|
|
1155
|
+
logSnapshotPersistSuccess(pending, result.semanticFingerprint, {
|
|
1156
|
+
rawBytes: result.rawBytes,
|
|
1157
|
+
gzBytes: result.gzBytes,
|
|
1158
|
+
serializeMs: pending.serializeMs ?? result.serializeMs,
|
|
1159
|
+
writeMs: result.writeMs,
|
|
1160
|
+
offloaded: true
|
|
1161
|
+
});
|
|
1162
|
+
completeSnapshotPersist(pending);
|
|
1163
|
+
} catch (err) {
|
|
1164
|
+
fs3.rm(result.stagePath, { force: true }, () => {
|
|
1165
|
+
});
|
|
1166
|
+
dispatchMainThreadWriteThroughSeam(pending, err instanceof Error ? err.message : String(err));
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
function dispatchSnapshotPersist(pending) {
|
|
1170
|
+
const baselines = snapshotPersistBaselinesFor(pending.cwd, pending.key);
|
|
1171
|
+
pending.durablePersist = baselines.durable;
|
|
1172
|
+
pending.dedupeFingerprints = baselines.fingerprints;
|
|
1173
|
+
seedSnapshotPersistBaselineFromDurable(pending.key, baselines.durable);
|
|
1174
|
+
_activeSnapshotPersists.set(pending.key, pending);
|
|
1175
|
+
if (!snapshotWorkerEnabled()) {
|
|
1176
|
+
dispatchMainThreadWriteThroughSeam(pending, void 0);
|
|
1177
|
+
return;
|
|
1178
|
+
}
|
|
1179
|
+
const worker = getSnapshotPersistWorker();
|
|
1180
|
+
if (!worker) {
|
|
1181
|
+
dispatchMainThreadWriteThroughSeam(pending, "persist worker unavailable");
|
|
1182
|
+
return;
|
|
1183
|
+
}
|
|
1184
|
+
let serialized;
|
|
1185
|
+
try {
|
|
1186
|
+
serialized = serializeSnapshotBody(pending.snapshot);
|
|
1187
|
+
} catch (err) {
|
|
1188
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
1189
|
+
incrementDegradationCount({
|
|
1190
|
+
kind: "project-snapshot-serialize-failed",
|
|
1191
|
+
subject: pending.gzPath,
|
|
1192
|
+
reason: `snapshot body serialization failed: ${message}`
|
|
1193
|
+
});
|
|
1194
|
+
recordSnapshotPersistFailure(pending, message);
|
|
1195
|
+
completeSnapshotPersist(pending);
|
|
1196
|
+
return;
|
|
1197
|
+
}
|
|
1198
|
+
pending.serializeMs = serialized.serializeMs;
|
|
1199
|
+
pending.wordIndexWireBytes = serialized.wordIndexWireBytes;
|
|
1200
|
+
const id = ++_snapshotWorkerRequestId;
|
|
1201
|
+
_snapshotWorkerRequests.set(id, pending);
|
|
1202
|
+
const request = {
|
|
1203
|
+
id,
|
|
1204
|
+
generation: pending.generation,
|
|
1205
|
+
stagePath: pending.stagePath,
|
|
1206
|
+
data: serialized.bytes,
|
|
1207
|
+
generatedAt: pending.snapshot.generatedAt,
|
|
1208
|
+
priorFingerprints: pending.dedupeFingerprints,
|
|
1209
|
+
testDelayMs: process.env.NODE_ENV === "test" ? Number(process.env.PI_LENS_TEST_SNAPSHOT_PERSIST_WORKER_DELAY_MS) || void 0 : void 0
|
|
1210
|
+
};
|
|
1211
|
+
try {
|
|
1212
|
+
worker.postMessage(request, [serialized.bytes.buffer]);
|
|
1213
|
+
} catch (err) {
|
|
1214
|
+
_snapshotWorkerRequests.delete(id);
|
|
1215
|
+
dispatchMainThreadWriteThroughSeam(pending, err instanceof Error ? err.message : String(err));
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
function handleSnapshotWorkerDeath(reason) {
|
|
1219
|
+
_snapshotPersistWorker = void 0;
|
|
1220
|
+
_snapshotPersistWorkerHeapStatistics = null;
|
|
1221
|
+
_snapshotWorkerDisabled = true;
|
|
1222
|
+
const requests = [..._snapshotWorkerRequests.values()];
|
|
1223
|
+
_snapshotWorkerRequests.clear();
|
|
1224
|
+
for (const pending of requests)
|
|
1225
|
+
dispatchMainThreadWriteThroughSeam(pending, reason);
|
|
1226
|
+
}
|
|
1227
|
+
function resolveSnapshotPersistWorkerPath() {
|
|
1228
|
+
const candidates = [
|
|
1229
|
+
new URL("./project-snapshot-persist-worker.js", import.meta.url),
|
|
1230
|
+
new URL("./workers/project-snapshot-persist-worker.js", import.meta.url),
|
|
1231
|
+
new URL("../workers/project-snapshot-persist-worker.js", import.meta.url)
|
|
1232
|
+
];
|
|
1233
|
+
for (const url of candidates) {
|
|
1234
|
+
try {
|
|
1235
|
+
const resolved = fileURLToPath(url);
|
|
1236
|
+
if (fs3.existsSync(resolved))
|
|
1237
|
+
return resolved;
|
|
1238
|
+
} catch {
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
return void 0;
|
|
1242
|
+
}
|
|
1243
|
+
function getSnapshotPersistWorker() {
|
|
1244
|
+
if (_snapshotWorkerDisabled)
|
|
1245
|
+
return void 0;
|
|
1246
|
+
if (_snapshotPersistWorker)
|
|
1247
|
+
return _snapshotPersistWorker;
|
|
1248
|
+
try {
|
|
1249
|
+
const workerPath = resolveSnapshotPersistWorkerPath();
|
|
1250
|
+
if (workerPath === void 0) {
|
|
1251
|
+
handleSnapshotWorkerDeath("persist worker script not found in any layout");
|
|
1252
|
+
return void 0;
|
|
1253
|
+
}
|
|
1254
|
+
const worker = new Worker(workerPath);
|
|
1255
|
+
worker.on("message", (result) => {
|
|
1256
|
+
if (_snapshotPromotionSeamForTests) {
|
|
1257
|
+
void _snapshotPromotionSeamForTests().then(() => handleSnapshotWorkerResult(result));
|
|
1258
|
+
return;
|
|
1259
|
+
}
|
|
1260
|
+
handleSnapshotWorkerResult(result);
|
|
1261
|
+
});
|
|
1262
|
+
worker.on("error", (err) => handleSnapshotWorkerDeath(err.message));
|
|
1263
|
+
worker.on("exit", (code) => {
|
|
1264
|
+
if (_snapshotPersistWorker === worker) {
|
|
1265
|
+
_snapshotPersistWorker = void 0;
|
|
1266
|
+
_snapshotPersistWorkerHeapStatistics = null;
|
|
1267
|
+
}
|
|
1268
|
+
const stranded = [..._snapshotWorkerRequests.values()];
|
|
1269
|
+
if (stranded.length > 0) {
|
|
1270
|
+
_snapshotWorkerRequests.clear();
|
|
1271
|
+
for (const pending of stranded) {
|
|
1272
|
+
dispatchMainThreadWriteThroughSeam(pending, `persist worker exited with code ${code}`);
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
if (code !== 0)
|
|
1276
|
+
_snapshotWorkerDisabled = true;
|
|
1277
|
+
});
|
|
1278
|
+
worker.unref();
|
|
1279
|
+
_snapshotPersistWorker = worker;
|
|
1280
|
+
return worker;
|
|
1281
|
+
} catch (err) {
|
|
1282
|
+
handleSnapshotWorkerDeath(err instanceof Error ? err.message : String(err));
|
|
1283
|
+
return void 0;
|
|
1284
|
+
}
|
|
1285
|
+
}
|
|
1286
|
+
var _sweptSnapshotStageDirs = /* @__PURE__ */ new Set();
|
|
1287
|
+
function sweepStaleSnapshotStageFiles(cacheDir) {
|
|
1288
|
+
if (_sweptSnapshotStageDirs.has(cacheDir))
|
|
1289
|
+
return;
|
|
1290
|
+
_sweptSnapshotStageDirs.add(cacheDir);
|
|
1291
|
+
fs3.readdir(cacheDir, (err, entries) => {
|
|
1292
|
+
if (err)
|
|
1293
|
+
return;
|
|
1294
|
+
for (const entry of entries) {
|
|
1295
|
+
if (!isStaleStageFile(entry, "project-snapshot.json.gz.stage-"))
|
|
1296
|
+
continue;
|
|
1297
|
+
fs3.rm(path2.join(cacheDir, entry), { force: true }, () => {
|
|
1298
|
+
});
|
|
1299
|
+
}
|
|
1300
|
+
});
|
|
1301
|
+
}
|
|
1302
|
+
function flushSnapshotPersistsAtExit() {
|
|
1303
|
+
_snapshotExiting = true;
|
|
1304
|
+
const latestByKey = /* @__PURE__ */ new Map();
|
|
1305
|
+
for (const pending of _snapshotWorkerRequests.values()) {
|
|
1306
|
+
latestByKey.set(pending.key, pending);
|
|
1307
|
+
}
|
|
1308
|
+
for (const pending of _queuedSnapshotPersists.values()) {
|
|
1309
|
+
const prior = latestByKey.get(pending.key);
|
|
1310
|
+
if (!prior || prior.generation <= pending.generation) {
|
|
1311
|
+
latestByKey.set(pending.key, pending);
|
|
1312
|
+
}
|
|
1313
|
+
}
|
|
1314
|
+
_snapshotWorkerRequests.clear();
|
|
1315
|
+
_queuedSnapshotPersists.clear();
|
|
1316
|
+
_activeSnapshotPersists.clear();
|
|
1317
|
+
for (const pending of latestByKey.values()) {
|
|
1318
|
+
writeSnapshotBodyOnMainThread(pending, "exit_hook");
|
|
1319
|
+
}
|
|
1320
|
+
void _snapshotPersistWorker?.terminate();
|
|
1321
|
+
}
|
|
1322
|
+
var _snapshotExitHookInstalled = false;
|
|
1323
|
+
function ensureSnapshotPersistExitHook() {
|
|
1324
|
+
if (_snapshotExitHookInstalled)
|
|
1325
|
+
return;
|
|
1326
|
+
_snapshotExitHookInstalled = true;
|
|
1327
|
+
process.once("exit", flushSnapshotPersistsAtExit);
|
|
1328
|
+
}
|
|
1329
|
+
function runSnapshotPersistExitFlushForTests() {
|
|
1330
|
+
flushSnapshotPersistsAtExit();
|
|
1331
|
+
}
|
|
1332
|
+
function saveProjectSnapshot(cwd, snapshot) {
|
|
1333
|
+
const gzPath = getProjectSnapshotPath(cwd);
|
|
1334
|
+
const legacyPath = getProjectSnapshotLegacyPath(cwd);
|
|
1335
|
+
const metaPath = getProjectSnapshotMetaPath(cwd);
|
|
1336
|
+
const cacheDir = path2.dirname(gzPath);
|
|
1337
|
+
const key = normalizeMapKey(cwd);
|
|
1338
|
+
fs3.mkdirSync(cacheDir, { recursive: true });
|
|
1339
|
+
const baselines = snapshotPersistBaselinesFor(cwd, key);
|
|
1340
|
+
const priorPersist = baselines.durable;
|
|
1341
|
+
logSnapshotPersistDecision({
|
|
1342
|
+
cwd,
|
|
1343
|
+
seq: snapshot.seq,
|
|
1344
|
+
decision: "requested"
|
|
1345
|
+
});
|
|
1346
|
+
if (_failedSnapshotPersists.delete(key)) {
|
|
1347
|
+
logSnapshotPersistDecision({ cwd, seq: snapshot.seq, decision: "retry" });
|
|
1348
|
+
}
|
|
1349
|
+
withSnapshotCacheLock(gzPath, "admission meta write", () => {
|
|
1350
|
+
const onDisk = readProjectSnapshotMeta(cwd);
|
|
1351
|
+
if (!onDisk || onDisk.seq < snapshot.seq) {
|
|
1352
|
+
writeProjectSnapshotMeta(metaPath, snapshot);
|
|
1353
|
+
}
|
|
1354
|
+
});
|
|
1355
|
+
const priorBody = resolveSnapshotBodyPath(cwd);
|
|
1356
|
+
const knownMtime = priorBody ? priorBody.mtimeMs : Number.NEGATIVE_INFINITY;
|
|
1357
|
+
const knownSize = priorBody ? priorBody.size : Number.NEGATIVE_INFINITY;
|
|
1358
|
+
const authoritativeEntry = {
|
|
1359
|
+
snapshot,
|
|
1360
|
+
knownMtime,
|
|
1361
|
+
knownSize,
|
|
1362
|
+
lastUsedAt: Date.now()
|
|
1363
|
+
};
|
|
1364
|
+
const previousAuthoritativeEntry = authoritativeSnapshots.get(key);
|
|
1365
|
+
if (previousAuthoritativeEntry)
|
|
1366
|
+
clearAuthoritativeSnapshotTimer(previousAuthoritativeEntry);
|
|
1367
|
+
authoritativeSnapshots.set(key, authoritativeEntry);
|
|
1368
|
+
scheduleAuthoritativeSnapshotEviction(key, authoritativeEntry);
|
|
1369
|
+
enforceAuthoritativeSnapshotCap();
|
|
1370
|
+
snapshotParseCache.delete(gzPath);
|
|
1371
|
+
const generationState = _snapshotGenerationStates.get(key);
|
|
1372
|
+
const generation = generationState?.seq === snapshot.seq ? generationState.generation : (generationState?.generation ?? 0) + 1;
|
|
1373
|
+
_snapshotGenerationStates.set(key, { generation, seq: snapshot.seq });
|
|
1374
|
+
const stagePath = `${gzPath}.stage-${process.pid}-${generation}`;
|
|
1375
|
+
const pending = {
|
|
1376
|
+
key,
|
|
1377
|
+
cwd,
|
|
1378
|
+
gzPath,
|
|
1379
|
+
legacyPath,
|
|
1380
|
+
stagePath,
|
|
1381
|
+
snapshot,
|
|
1382
|
+
generation,
|
|
1383
|
+
durablePersist: priorPersist,
|
|
1384
|
+
dedupeFingerprints: baselines.fingerprints
|
|
1385
|
+
};
|
|
1386
|
+
sweepStaleSnapshotStageFiles(cacheDir);
|
|
1387
|
+
ensureSnapshotPersistExitHook();
|
|
1388
|
+
if (_activeSnapshotPersists.has(key)) {
|
|
1389
|
+
_queuedSnapshotPersists.set(key, pending);
|
|
1390
|
+
logSnapshotPersistDecision({
|
|
1391
|
+
cwd,
|
|
1392
|
+
seq: snapshot.seq,
|
|
1393
|
+
decision: "coalesced"
|
|
1394
|
+
});
|
|
1395
|
+
return;
|
|
1396
|
+
}
|
|
1397
|
+
dispatchSnapshotPersist(pending);
|
|
1398
|
+
}
|
|
1399
|
+
async function waitForProjectSnapshotPersistsForTests() {
|
|
1400
|
+
for (let attempts = 0; attempts < 200 && (_snapshotWorkerRequests.size > 0 || _activeSnapshotPersists.size > 0 || _queuedSnapshotPersists.size > 0); attempts++) {
|
|
1401
|
+
await new Promise((resolve2) => setTimeout(resolve2, 10));
|
|
1402
|
+
}
|
|
1403
|
+
}
|
|
1404
|
+
function flushProjectSnapshotPersistsForTests() {
|
|
1405
|
+
const requests = [..._snapshotWorkerRequests.values()];
|
|
1406
|
+
_snapshotWorkerRequests.clear();
|
|
1407
|
+
for (const pending of requests) {
|
|
1408
|
+
dispatchMainThreadWriteThroughSeam(pending, void 0);
|
|
1409
|
+
}
|
|
1410
|
+
}
|
|
1411
|
+
async function terminateProjectSnapshotPersistWorkerForTests() {
|
|
1412
|
+
const worker = _snapshotPersistWorker;
|
|
1413
|
+
if (worker)
|
|
1414
|
+
await worker.terminate();
|
|
1415
|
+
}
|
|
1416
|
+
function resetProjectSnapshotPersistWorkerForTests() {
|
|
1417
|
+
_snapshotWorkerDisabled = false;
|
|
1418
|
+
_snapshotGenerationGateEnabledForTests = true;
|
|
1419
|
+
_snapshotPromotionSeamForTests = void 0;
|
|
1420
|
+
_snapshotPersistWorker = void 0;
|
|
1421
|
+
_snapshotPersistWorkerHeapStatistics = null;
|
|
1422
|
+
_snapshotWorkerRequests.clear();
|
|
1423
|
+
_snapshotGenerationStates.clear();
|
|
1424
|
+
_successfulSnapshotPersists.clear();
|
|
1425
|
+
_failedSnapshotPersists.clear();
|
|
1426
|
+
_activeSnapshotPersists.clear();
|
|
1427
|
+
_queuedSnapshotPersists.clear();
|
|
1428
|
+
_snapshotExiting = false;
|
|
1429
|
+
_snapshotWorkerBodyWritesForTests = 0;
|
|
1430
|
+
_lastSnapshotPersistErrorForTests = void 0;
|
|
1431
|
+
}
|
|
1432
|
+
function getProjectSnapshotPersistStateForTests(cwd) {
|
|
1433
|
+
const key = normalizeMapKey(cwd);
|
|
1434
|
+
return {
|
|
1435
|
+
active: _activeSnapshotPersists.has(key),
|
|
1436
|
+
queued: _queuedSnapshotPersists.has(key),
|
|
1437
|
+
successfulFingerprint: _successfulSnapshotPersists.get(key)?.fingerprint,
|
|
1438
|
+
workerBodyWrites: _snapshotWorkerBodyWritesForTests
|
|
1439
|
+
};
|
|
1440
|
+
}
|
|
1441
|
+
function setProjectSnapshotGenerationGateForTests(enabled) {
|
|
1442
|
+
_snapshotGenerationGateEnabledForTests = enabled;
|
|
1443
|
+
}
|
|
1444
|
+
function setProjectSnapshotPromotionSeamForTests(seam) {
|
|
1445
|
+
_snapshotPromotionSeamForTests = seam;
|
|
1446
|
+
}
|
|
1447
|
+
function getProjectSnapshotPersistErrorForTests() {
|
|
1448
|
+
return _lastSnapshotPersistErrorForTests;
|
|
1449
|
+
}
|
|
1450
|
+
function _seedSnapshotParseCacheForTests(key, entry) {
|
|
1451
|
+
cacheParsedSnapshot(key, entry);
|
|
1452
|
+
}
|
|
1453
|
+
function _snapshotParseCacheKeysForTests() {
|
|
1454
|
+
return [...snapshotParseCache.keys()];
|
|
1455
|
+
}
|
|
1456
|
+
function _snapshotParseCacheGetForTests(key) {
|
|
1457
|
+
return snapshotParseCache.get(key) !== void 0;
|
|
1458
|
+
}
|
|
1459
|
+
function _seedSuccessfulSnapshotPersistForTests(key, record) {
|
|
1460
|
+
rememberSuccessfulSnapshotPersist(key, record);
|
|
1461
|
+
}
|
|
1462
|
+
function _successfulSnapshotPersistKeysForTests() {
|
|
1463
|
+
return [..._successfulSnapshotPersists.keys()];
|
|
1464
|
+
}
|
|
1465
|
+
function _successfulSnapshotPersistGetForTests(key) {
|
|
1466
|
+
return _successfulSnapshotPersists.get(key) !== void 0;
|
|
1467
|
+
}
|
|
1468
|
+
function _seedFailedSnapshotPersistForTests(key, record) {
|
|
1469
|
+
_failedSnapshotPersists.set(key, record);
|
|
1470
|
+
}
|
|
1471
|
+
function _failedSnapshotPersistKeysForTests() {
|
|
1472
|
+
return [..._failedSnapshotPersists.keys()];
|
|
1473
|
+
}
|
|
1474
|
+
function buildProjectSnapshotFromRuntime(args) {
|
|
1475
|
+
const incomplete = args.runtime.viewMissesLoggedEntries;
|
|
1476
|
+
return {
|
|
1477
|
+
version: PROJECT_SNAPSHOT_VERSION,
|
|
1478
|
+
projectRoot: normalizeMapKey(path2.resolve(args.cwd)),
|
|
1479
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1480
|
+
seq: args.runtime.projectSeq,
|
|
1481
|
+
...incomplete ? { incomplete: true } : {},
|
|
1482
|
+
logEntries: args.runtime.viewLogEntries,
|
|
1483
|
+
files: {},
|
|
1484
|
+
symbols: {},
|
|
1485
|
+
reverseDeps: {},
|
|
1486
|
+
cachedExports: [...args.runtime.cachedExports.entries()].sort((a, b) => a[0].localeCompare(b[0])),
|
|
1487
|
+
// #1019: capture the runtime's live sequence index AT this seq. The runtime
|
|
1488
|
+
// is seeded from the change log at session start and bumped in lockstep with
|
|
1489
|
+
// every append, so `getFileSeqEntries()` IS the fold of the log up to
|
|
1490
|
+
// `projectSeq` — and its keys are already `normalizeMapKey(path.resolve())`,
|
|
1491
|
+
// the exact form the change-log replay produces.
|
|
1492
|
+
sequenceIndex: incomplete ? void 0 : {
|
|
1493
|
+
projectSeq: args.runtime.projectSeq,
|
|
1494
|
+
fileSeqByPath: args.runtime.getFileSeqEntries()
|
|
1495
|
+
},
|
|
1496
|
+
wordIndex: args.runtime.wordIndex ? serializeWordIndex(args.runtime.wordIndex) : void 0,
|
|
1497
|
+
projectRulesScan: args.runtime.projectRulesScan,
|
|
1498
|
+
startupScan: args.startupScan,
|
|
1499
|
+
languageProfile: args.languageProfile,
|
|
1500
|
+
conventions: args.conventions
|
|
1501
|
+
};
|
|
1502
|
+
}
|
|
1503
|
+
function hydrateRuntimeFromProjectSnapshot(runtime, snapshot) {
|
|
1504
|
+
runtime.cachedExports.clear();
|
|
1505
|
+
for (const [name, filePath] of snapshot.cachedExports) {
|
|
1506
|
+
runtime.cachedExports.set(name, filePath);
|
|
1507
|
+
}
|
|
1508
|
+
if (snapshot.projectRulesScan) {
|
|
1509
|
+
runtime.projectRulesScan = snapshot.projectRulesScan;
|
|
1510
|
+
}
|
|
1511
|
+
runtime.wordIndex = deserializeWordIndex(snapshot.wordIndex);
|
|
1512
|
+
}
|
|
1513
|
+
function hydrateRuntimeFromProjectSnapshotIfIdle(runtime, snapshot) {
|
|
1514
|
+
let hydratedAnything = false;
|
|
1515
|
+
if (runtime.cachedExports.size === 0 && snapshot.cachedExports.length > 0) {
|
|
1516
|
+
runtime.cachedExports.clear();
|
|
1517
|
+
for (const [name, filePath] of snapshot.cachedExports) {
|
|
1518
|
+
runtime.cachedExports.set(name, filePath);
|
|
1519
|
+
}
|
|
1520
|
+
hydratedAnything = true;
|
|
1521
|
+
}
|
|
1522
|
+
if (!runtime.projectRulesScan.hasCustomRules && runtime.projectRulesScan.rules.length === 0 && snapshot.projectRulesScan) {
|
|
1523
|
+
runtime.projectRulesScan = snapshot.projectRulesScan;
|
|
1524
|
+
hydratedAnything = true;
|
|
1525
|
+
}
|
|
1526
|
+
return hydratedAnything;
|
|
1527
|
+
}
|
|
1528
|
+
function saveRuntimeProjectSnapshot(args) {
|
|
1529
|
+
try {
|
|
1530
|
+
if (typeof args.runtime.projectSeq !== "number")
|
|
1531
|
+
return;
|
|
1532
|
+
const existing = loadProjectSnapshot(args.cwd);
|
|
1533
|
+
let conventions = args.conventions ?? existing?.conventions;
|
|
1534
|
+
if (!conventions) {
|
|
1535
|
+
try {
|
|
1536
|
+
conventions = detectProjectConventions(args.cwd);
|
|
1537
|
+
} catch (err) {
|
|
1538
|
+
args.dbg?.(`project_snapshot: convention detection failed: ${err}`);
|
|
1539
|
+
}
|
|
1540
|
+
}
|
|
1541
|
+
const snapshot = buildProjectSnapshotFromRuntime({
|
|
1542
|
+
...args,
|
|
1543
|
+
startupScan: args.startupScan ?? existing?.startupScan,
|
|
1544
|
+
languageProfile: args.languageProfile ?? existing?.languageProfile,
|
|
1545
|
+
conventions
|
|
1546
|
+
});
|
|
1547
|
+
if (existing) {
|
|
1548
|
+
snapshot.files = existing.files ?? {};
|
|
1549
|
+
snapshot.symbols = existing.symbols ?? {};
|
|
1550
|
+
snapshot.reverseDeps = existing.reverseDeps ?? {};
|
|
1551
|
+
if (!snapshot.wordIndex && existing.wordIndex && existing.seq === snapshot.seq && (snapshot.incomplete || !existing.incomplete)) {
|
|
1552
|
+
snapshot.wordIndex = existing.wordIndex;
|
|
1553
|
+
}
|
|
1554
|
+
}
|
|
1555
|
+
saveProjectSnapshot(args.cwd, snapshot);
|
|
1556
|
+
args.dbg?.(`project_snapshot: saved seq=${snapshot.seq} exports=${snapshot.cachedExports.length}`);
|
|
1557
|
+
} catch (err) {
|
|
1558
|
+
args.dbg?.(`project_snapshot: save failed: ${err}`);
|
|
1559
|
+
}
|
|
1560
|
+
}
|
|
1561
|
+
|
|
1562
|
+
export {
|
|
1563
|
+
readJsonCache,
|
|
1564
|
+
readJsonCacheAsync,
|
|
1565
|
+
readWorkerHeapStatistics,
|
|
1566
|
+
PROJECT_SNAPSHOT_VERSION,
|
|
1567
|
+
getProjectSnapshotPath,
|
|
1568
|
+
getProjectSnapshotLegacyPath,
|
|
1569
|
+
getProjectSnapshotMetaPath,
|
|
1570
|
+
isProjectSnapshotFresh,
|
|
1571
|
+
readProjectSnapshotMeta,
|
|
1572
|
+
isProjectSnapshotMetaStale,
|
|
1573
|
+
SNAPSHOT_PARSE_CACHE_MAX,
|
|
1574
|
+
PROJECT_SNAPSHOT_MAX_WARM_ROOTS,
|
|
1575
|
+
_getAuthoritativeSnapshotCacheKeysForTests,
|
|
1576
|
+
_resetProjectSnapshotParseCacheForTests,
|
|
1577
|
+
_projectSnapshotParseCacheRetainsWordIndexForTests,
|
|
1578
|
+
getSnapshotBodyReadCountForTests,
|
|
1579
|
+
resetSnapshotBodyReadCountForTests,
|
|
1580
|
+
_stripTopLevelJsonKeysForTests,
|
|
1581
|
+
getLastNarrowParseDigestForTests,
|
|
1582
|
+
resetLastNarrowParseDigestForTests,
|
|
1583
|
+
loadProjectSnapshotExportsAndRules,
|
|
1584
|
+
loadProjectSnapshot,
|
|
1585
|
+
loadProjectSnapshotWithoutWordIndex,
|
|
1586
|
+
refreshProjectSnapshotPersistWorkerHeapStatistics,
|
|
1587
|
+
getProjectSnapshotPersistWorkerHeapStatistics,
|
|
1588
|
+
runSnapshotPersistExitFlushForTests,
|
|
1589
|
+
saveProjectSnapshot,
|
|
1590
|
+
waitForProjectSnapshotPersistsForTests,
|
|
1591
|
+
flushProjectSnapshotPersistsForTests,
|
|
1592
|
+
terminateProjectSnapshotPersistWorkerForTests,
|
|
1593
|
+
resetProjectSnapshotPersistWorkerForTests,
|
|
1594
|
+
getProjectSnapshotPersistStateForTests,
|
|
1595
|
+
setProjectSnapshotGenerationGateForTests,
|
|
1596
|
+
setProjectSnapshotPromotionSeamForTests,
|
|
1597
|
+
getProjectSnapshotPersistErrorForTests,
|
|
1598
|
+
_seedSnapshotParseCacheForTests,
|
|
1599
|
+
_snapshotParseCacheKeysForTests,
|
|
1600
|
+
_snapshotParseCacheGetForTests,
|
|
1601
|
+
_seedSuccessfulSnapshotPersistForTests,
|
|
1602
|
+
_successfulSnapshotPersistKeysForTests,
|
|
1603
|
+
_successfulSnapshotPersistGetForTests,
|
|
1604
|
+
_seedFailedSnapshotPersistForTests,
|
|
1605
|
+
_failedSnapshotPersistKeysForTests,
|
|
1606
|
+
buildProjectSnapshotFromRuntime,
|
|
1607
|
+
hydrateRuntimeFromProjectSnapshot,
|
|
1608
|
+
hydrateRuntimeFromProjectSnapshotIfIdle,
|
|
1609
|
+
saveRuntimeProjectSnapshot
|
|
1610
|
+
};
|