@herbertgao/pi-extensions 2026.8.6 → 2026.8.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +1 -1
- package/node_modules/@herbertgao/pi-cc-extensions/README.md +1 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +19 -7
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +30 -9
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/compact-thinking.ts +272 -22
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +94 -77
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/message-display.ts +1 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/hover.ts +14 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +55 -17
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/layout.ts +41 -2
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-renderer.ts +75 -6
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/types.ts +7 -3
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +64 -1
- package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
- package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +6 -0
- package/node_modules/@herbertgao/pi-subagents/README.md +30 -22
- package/node_modules/@herbertgao/pi-subagents/examples/agent-tool-description.md +5 -5
- package/node_modules/@herbertgao/pi-subagents/package.json +7 -7
- package/node_modules/@herbertgao/pi-subagents/src/agent-file-toggle.ts +7 -1
- package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +48 -19
- package/node_modules/@herbertgao/pi-subagents/src/agent-runner.ts +17 -13
- package/node_modules/@herbertgao/pi-subagents/src/custom-agents.ts +26 -2
- package/node_modules/@herbertgao/pi-subagents/src/index.ts +219 -40
- package/node_modules/@herbertgao/pi-subagents/src/invocation-config.ts +101 -3
- package/node_modules/@herbertgao/pi-subagents/src/nested-tools.ts +18 -4
- package/node_modules/@herbertgao/pi-subagents/src/settings.ts +99 -0
- package/node_modules/@herbertgao/pi-subagents/src/types.ts +22 -3
- package/node_modules/@herbertgao/pi-subagents/src/ui/agent-widget.ts +51 -3
- package/node_modules/@herbertgao/pi-subagents/src/ui/conversation-viewer.ts +20 -2
- package/node_modules/@herbertgao/pi-subagents/src/ui/fleet-list.ts +21 -6
- package/node_modules/@herbertgao/pi-subagents/src/usage.ts +129 -1
- package/node_modules/@herbertgao/pi-subagents/src/worktree.ts +20 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/README.md +1 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/ask-user-question.ts +26 -10
- package/node_modules/@juicesharp/rpiv-ask-user-question/config.ts +25 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/configuration.md +13 -4
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/hosts.md +2 -1
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/localization.md +3 -1
- package/node_modules/@juicesharp/rpiv-ask-user-question/locales/en.json +2 -2
- package/node_modules/@juicesharp/rpiv-ask-user-question/locales/zh.json +2 -2
- package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +3 -2
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/build-questionnaire.ts +10 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/key-router.ts +3 -1
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/questionnaire-session.ts +30 -7
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/state.ts +14 -6
- package/node_modules/@juicesharp/rpiv-ask-user-question/view/dialog-builder.ts +30 -4
- package/node_modules/@juicesharp/rpiv-ask-user-question/view/tab-content-strategy.ts +26 -5
- package/node_modules/@narumitw/pi-btw/README.md +120 -111
- package/node_modules/@narumitw/pi-btw/dist/index.ts +2898 -0
- package/node_modules/@narumitw/pi-btw/dist/index.ts.map +7 -0
- package/node_modules/@narumitw/pi-btw/package.json +10 -6
- package/node_modules/@narumitw/pi-btw/src/btw.ts +36 -40
- package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +55 -10
- package/node_modules/@narumitw/pi-btw/src/main-tree-picker.ts +390 -0
- package/node_modules/@narumitw/pi-btw/src/menu.ts +45 -2
- package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +136 -45
- package/node_modules/pi-lens/CHANGELOG.md +909 -0
- package/node_modules/pi-lens/README.md +11 -3
- package/node_modules/pi-lens/config/ruff/core.toml +42 -0
- package/node_modules/pi-lens/dist/clients/actionable-warnings.js +130 -27
- package/node_modules/pi-lens/dist/clients/advisory-provenance.js +126 -13
- package/node_modules/pi-lens/dist/clients/agent-nudge.js +67 -11
- package/node_modules/pi-lens/dist/clients/ast-grep-client.js +9 -3
- package/node_modules/pi-lens/dist/clients/atomic-write.js +9 -3
- package/node_modules/pi-lens/dist/clients/bash-file-access.js +285 -8
- package/node_modules/pi-lens/dist/clients/biome-client.js +61 -30
- package/node_modules/pi-lens/dist/clients/blocker-freshness.js +428 -0
- package/node_modules/pi-lens/dist/clients/blocker-past-eof.js +119 -0
- package/node_modules/pi-lens/dist/clients/bootstrap.js +12 -1
- package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +12 -3
- package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +192 -0
- package/node_modules/pi-lens/dist/clients/cascade-budget.js +196 -0
- package/node_modules/pi-lens/dist/clients/cascade-format.js +20 -1
- package/node_modules/pi-lens/dist/clients/cascade-types.js +9 -1
- package/node_modules/pi-lens/dist/clients/child-unref.js +54 -6
- package/node_modules/pi-lens/dist/clients/code-quality-warnings.js +76 -24
- package/node_modules/pi-lens/dist/clients/dead-code-client.js +123 -31
- package/node_modules/pi-lens/dist/clients/deadline-utils.js +8 -1
- package/node_modules/pi-lens/dist/clients/debug-handles.js +5 -0
- package/node_modules/pi-lens/dist/clients/degradation-ledger.js +62 -13
- package/node_modules/pi-lens/dist/clients/dependency-checker.js +25 -3
- package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +147 -33
- package/node_modules/pi-lens/dist/clients/diagnostic-line-freshness.js +298 -0
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +52 -2
- package/node_modules/pi-lens/dist/clients/dispatch/integration.js +256 -88
- package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +7 -4
- package/node_modules/pi-lens/dist/clients/dispatch/plan.js +5 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +234 -18
- package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +187 -19
- package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +6 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/credo.js +11 -9
- package/node_modules/pi-lens/dist/clients/dispatch/runners/cue-vet.js +398 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +11 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +12 -7
- package/node_modules/pi-lens/dist/clients/dispatch/runners/go-vet.js +18 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +895 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/index.js +4 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +16 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +60 -53
- package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +16 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +23 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +331 -55
- package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +38 -5
- package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +97 -19
- package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +14 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +20 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +22 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.js +10 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +18 -6
- package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +73 -12
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +275 -13
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +21 -6
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/lazy-installer.js +260 -27
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +734 -64
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +86 -11
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/tool-failure.js +72 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +9 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +9 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +18 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +4 -2
- package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +28 -5
- package/node_modules/pi-lens/dist/clients/extension-log.js +22 -1
- package/node_modules/pi-lens/dist/clients/file-kinds.js +8 -2
- package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +294 -0
- package/node_modules/pi-lens/dist/clients/finding-identity.js +88 -0
- package/node_modules/pi-lens/dist/clients/formatters-lazy.js +3 -2
- package/node_modules/pi-lens/dist/clients/formatters.js +500 -115
- package/node_modules/pi-lens/dist/clients/generation-guard.js +216 -0
- package/node_modules/pi-lens/dist/clients/git-guard.js +31 -0
- package/node_modules/pi-lens/dist/clients/gitleaks-client.js +181 -8
- package/node_modules/pi-lens/dist/clients/govulncheck-client.js +109 -9
- package/node_modules/pi-lens/dist/clients/grammar-source.js +333 -10
- package/node_modules/pi-lens/dist/clients/host-ports.js +8 -0
- package/node_modules/pi-lens/dist/clients/installer/index.js +1114 -100
- package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh-session.js +58 -0
- package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh.js +715 -0
- package/node_modules/pi-lens/dist/clients/instance-reaper.js +643 -97
- package/node_modules/pi-lens/dist/clients/instance-registry.js +87 -17
- package/node_modules/pi-lens/dist/clients/jscpd-client.js +82 -6
- package/node_modules/pi-lens/dist/clients/knip-client.js +310 -10
- package/node_modules/pi-lens/dist/clients/language-policy.js +8 -2
- package/node_modules/pi-lens/dist/clients/language-profile.js +2 -0
- package/node_modules/pi-lens/dist/clients/latency-logger.js +440 -11
- package/node_modules/pi-lens/dist/clients/lazy-import.js +21 -0
- package/node_modules/pi-lens/dist/clients/ledger-bounds.js +21 -0
- package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +8 -0
- package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +102 -7
- package/node_modules/pi-lens/dist/clients/lsp/client.js +1516 -159
- package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +83 -1
- package/node_modules/pi-lens/dist/clients/lsp/document-drift.js +389 -0
- package/node_modules/pi-lens/dist/clients/lsp/index.js +2274 -147
- package/node_modules/pi-lens/dist/clients/lsp/inferred-project.js +215 -0
- package/node_modules/pi-lens/dist/clients/lsp/jvm-runtime.js +146 -14
- package/node_modules/pi-lens/dist/clients/lsp/language.js +48 -4
- package/node_modules/pi-lens/dist/clients/lsp/server.js +277 -16
- package/node_modules/pi-lens/dist/clients/lsp/spawn-history.js +22 -0
- package/node_modules/pi-lens/dist/clients/lsp/sync-kind.js +43 -0
- package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +79 -3
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +43 -0
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +422 -28
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-session.js +30 -0
- package/node_modules/pi-lens/dist/clients/lsp/workspace-sweep-hold.js +175 -0
- package/node_modules/pi-lens/dist/clients/lsp-lazy.js +3 -2
- package/node_modules/pi-lens/dist/clients/mcp/session.js +10 -2
- package/node_modules/pi-lens/dist/clients/module-report.js +8 -0
- package/node_modules/pi-lens/dist/clients/opengrep-client.js +15 -1
- package/node_modules/pi-lens/dist/clients/package-manager.js +170 -14
- package/node_modules/pi-lens/dist/clients/path-attribution-telemetry.js +27 -0
- package/node_modules/pi-lens/dist/clients/path-utils.js +160 -0
- package/node_modules/pi-lens/dist/clients/pipeline.js +154 -33
- package/node_modules/pi-lens/dist/clients/post-autofix-notice.js +37 -0
- package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +17 -3
- package/node_modules/pi-lens/dist/clients/project-diagnostics/extractors.js +89 -22
- package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +84 -14
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +15 -3
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/trivy.js +50 -2
- package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +5 -0
- package/node_modules/pi-lens/dist/clients/project-lens-config.js +3 -0
- package/node_modules/pi-lens/dist/clients/project-snapshot.js +299 -0
- package/node_modules/pi-lens/dist/clients/quiet-window-config.js +47 -0
- package/node_modules/pi-lens/dist/clients/quiet-window.js +11 -25
- package/node_modules/pi-lens/dist/clients/read-guard-logger.js +1 -1
- package/node_modules/pi-lens/dist/clients/read-guard.js +184 -10
- package/node_modules/pi-lens/dist/clients/resource-sampler.js +49 -17
- package/node_modules/pi-lens/dist/clients/reverse-deps.js +50 -11
- package/node_modules/pi-lens/dist/clients/review-graph/query.js +52 -4
- package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +96 -7
- package/node_modules/pi-lens/dist/clients/runtime-context.js +8 -1
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +308 -45
- package/node_modules/pi-lens/dist/clients/runtime-session.js +332 -9
- package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +217 -22
- package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +212 -79
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +575 -67
- package/node_modules/pi-lens/dist/clients/safe-spawn.js +220 -7
- package/node_modules/pi-lens/dist/clients/scratch-tree-policy.js +161 -0
- package/node_modules/pi-lens/dist/clients/search-read-registration.js +34 -6
- package/node_modules/pi-lens/dist/clients/security-scan-client.js +157 -24
- package/node_modules/pi-lens/dist/clients/sg-runner.js +116 -22
- package/node_modules/pi-lens/dist/clients/single-flight.js +158 -0
- package/node_modules/pi-lens/dist/clients/stale-marker.js +17 -0
- package/node_modules/pi-lens/dist/clients/startup-timing.js +19 -1
- package/node_modules/pi-lens/dist/clients/test-runner-client.js +151 -16
- package/node_modules/pi-lens/dist/clients/tool-event.js +56 -5
- package/node_modules/pi-lens/dist/clients/tool-policy.js +125 -20
- package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +75 -1
- package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +769 -64
- package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +11 -0
- package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +90 -0
- package/node_modules/pi-lens/dist/clients/trivy-client.js +19 -1
- package/node_modules/pi-lens/dist/clients/widget-state.js +336 -36
- package/node_modules/pi-lens/dist/clients/zizmor-config.js +214 -14
- package/node_modules/pi-lens/dist/index.js +67738 -55739
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +466 -54
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +132 -43
- package/node_modules/pi-lens/dist/tools/lsp-navigation.js +46 -7
- package/node_modules/pi-lens/docs/agent-guide.md +6 -1
- package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +515 -506
- package/node_modules/pi-lens/docs/dispositions.md +21 -0
- package/node_modules/pi-lens/docs/features.md +19 -5
- package/node_modules/pi-lens/docs/globalconfig.md +3 -0
- package/node_modules/pi-lens/docs/language-coverage.md +71 -5
- package/node_modules/pi-lens/docs/mcp.md +2 -2
- package/node_modules/pi-lens/docs/servercapabilities.md +4 -1
- package/node_modules/pi-lens/docs/settings.md +19 -1
- package/node_modules/pi-lens/docs/usage.md +1 -0
- package/node_modules/pi-lens/package.json +10 -6
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/no-reflect-get-js-snapshot.yml +23 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/no-reflect-get-snapshot.yml +23 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/ts-void-zero-snapshot.yml +23 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-bare-object-param-test.yml +16 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-chained-type-assertions-test.yml +15 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-compile-call-test.yml +29 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-dupe-class-members-test.yml +33 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-inner-html-js-test.yml +7 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-inner-html-test.yml +7 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-known-value-widening-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-non-null-assertion-test.yml +216 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-js-test.yml +2 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-test.yml +2 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-js-test.yml +2 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-test.yml +2 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-return-value-in-generator-test.yml +12 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-runtime-typeof-test.yml +33 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-server-bind-wildcard-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-shape-in-symbol-names-test.yml +13 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-sql-in-code-js-test.yml +5 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-sql-in-code-test.yml +5 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-parameters-test.yml +12 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-returns-test.yml +16 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unsafe-dictionary-any-test.yml +10 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unsafe-dictionary-unknown-test.yml +8 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/redundant-unsafe-function-test.yml +35 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/require-safety-comment-for-as-unknown-as-test.yml +177 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/ts-void-zero-test.yml +1 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-await-expression-member-js.yml +13 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-await-expression-member.yml +13 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-host-path-in-win32-branch.yml +2 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-object-param.yml +60 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-chained-type-assertions.yml +57 -12
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-compile-call.yml +63 -5
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-dupe-class-members.yml +52 -8
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-inner-html-js.yml +27 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-inner-html.yml +27 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-known-value-widening.yml +71 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-non-null-assertion.yml +316 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-raw-json-store-write.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply-js.yml +22 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply.yml +23 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get-js.yml +33 -5
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get.yml +34 -8
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-return-value-in-generator.yml +22 -5
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-runtime-typeof.yml +121 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-server-bind-wildcard.yml +23 -7
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-shape-in-symbol-names.yml +68 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-sql-in-code-js.yml +41 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-sql-in-code.yml +41 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-laundering.yml +6 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-parameters.yml +67 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-returns.yml +106 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unsafe-dictionary-any.yml +50 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unsafe-dictionary-unknown.yml +56 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-win32-isabsolute-for-qualification.yml +2 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/redundant-unsafe-function.yml +32 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/require-safety-comment-for-as-unknown-as.yml +184 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/ts-void-zero.yml +5 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/self-scan-baseline.json +5 -0
- package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +53 -1
- package/node_modules/pi-lens/scripts/download-grammars.js +25 -0
- package/node_modules/pi-lens/scripts/grammars.lock.json +9 -0
- package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +2 -0
- package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/SKILL.md +80 -3
- package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/reference.md +41 -0
- package/node_modules/pi-lens/vendor/grammars/tree-sitter-cue.wasm +0 -0
- package/node_modules/pi-mcp-adapter/CHANGELOG.md +36 -0
- package/node_modules/pi-mcp-adapter/README.md +47 -5
- package/node_modules/pi-mcp-adapter/cli.js +163 -1
- package/node_modules/pi-mcp-adapter/commands.ts +128 -22
- package/node_modules/pi-mcp-adapter/config.ts +25 -7
- package/node_modules/pi-mcp-adapter/direct-tools.ts +5 -4
- package/node_modules/pi-mcp-adapter/index.ts +219 -32
- package/node_modules/pi-mcp-adapter/init.ts +36 -4
- package/node_modules/pi-mcp-adapter/lifecycle.ts +315 -24
- package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +39 -6
- package/node_modules/pi-mcp-adapter/mcp-bearer-store.ts +387 -0
- package/node_modules/pi-mcp-adapter/mcp-callback-server.ts +27 -3
- package/node_modules/pi-mcp-adapter/mcp-code.ts +4 -0
- package/node_modules/pi-mcp-adapter/mcp-panel.ts +42 -13
- package/node_modules/pi-mcp-adapter/metadata-cache.ts +32 -21
- package/node_modules/pi-mcp-adapter/package-mcp-loader.ts +168 -0
- package/node_modules/pi-mcp-adapter/package.json +3 -1
- package/node_modules/pi-mcp-adapter/proxy-modes.ts +5 -4
- package/node_modules/pi-mcp-adapter/request-headers-command.ts +31 -37
- package/node_modules/pi-mcp-adapter/search-ranking.ts +92 -22
- package/node_modules/pi-mcp-adapter/server-manager.ts +140 -2
- package/node_modules/pi-mcp-adapter/session-recovery.ts +7 -0
- package/node_modules/pi-mcp-adapter/tool-approval.ts +15 -2
- package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +44 -4
- package/node_modules/pi-mcp-adapter/types.ts +2 -0
- package/node_modules/pi-mcp-adapter/ui-server.ts +18 -16
- package/node_modules/pi-mcp-adapter/utils.ts +70 -0
- package/node_modules/pi-web-access/CHANGELOG.md +23 -0
- package/node_modules/pi-web-access/README.md +27 -9
- package/node_modules/pi-web-access/anysearch.ts +4 -2
- package/node_modules/pi-web-access/brave.ts +16 -4
- package/node_modules/pi-web-access/curator-page.ts +6 -3
- package/node_modules/pi-web-access/curator-server.ts +4 -1
- package/node_modules/pi-web-access/exa.ts +18 -7
- package/node_modules/pi-web-access/extract.ts +28 -3
- package/node_modules/pi-web-access/gemini-search.ts +16 -4
- package/node_modules/pi-web-access/index.ts +41 -57
- package/node_modules/pi-web-access/package.json +1 -1
- package/node_modules/pi-web-access/page-query.ts +4 -2
- package/node_modules/pi-web-access/parallel-mcp.ts +249 -0
- package/node_modules/pi-web-access/parallel.ts +2 -2
- package/node_modules/pi-web-access/query-rewrite.ts +51 -0
- package/node_modules/pi-web-access/serper.ts +211 -0
- package/node_modules/pi-web-access/summary-model-scope.ts +12 -4
- package/node_modules/pi-web-access/summary-review.ts +44 -22
- package/node_modules/pi-web-access/tavily.ts +16 -4
- package/node_modules/pi-web-access/utils.ts +87 -0
- package/node_modules/pi-web-access/valyu.ts +199 -0
- package/package.json +13 -13
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import * as nodeFs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
+
import { resetBoundedTelemetry } from "./bounded-telemetry.js";
|
|
3
4
|
import { createDeadline, yieldIfOverBudget } from "./cooperative-budget.js";
|
|
4
5
|
import { deadCodeIssueCount } from "./dead-code-client.js";
|
|
5
6
|
import { logDeadCodeScan } from "./dead-code-logger.js";
|
|
6
|
-
import { resetDegradationLedger } from "./degradation-ledger.js";
|
|
7
|
+
import { incrementDegradationCount, resetDegradationLedger, } from "./degradation-ledger.js";
|
|
7
8
|
import { getDiagnosticTracker } from "./diagnostic-tracker.js";
|
|
9
|
+
import { resetPsScriptAnalyzerAvailability } from "./dispatch/runners/psscriptanalyzer.js";
|
|
10
|
+
import { resetInstallRetryLatches } from "./dispatch/runners/utils/availability-policy.js";
|
|
11
|
+
import { resetLazyInstallAttempts } from "./dispatch/runners/utils/lazy-installer.js";
|
|
8
12
|
import { resetDispatchAvailabilityState } from "./dispatch/runners/utils/runner-helpers.js";
|
|
9
13
|
import { clearAllSessions as clearFileTimeSessions } from "./file-time.js";
|
|
10
14
|
import { getGlobalPiLensDir, getKnipIgnorePatterns, getProjectDataDir, } from "./file-utils.js";
|
|
@@ -16,11 +20,17 @@ import { detectProjectLanguageProfile, getDefaultStartupTools, } from "./languag
|
|
|
16
20
|
import { logLatency } from "./latency-logger.js";
|
|
17
21
|
import { runLogCleanup } from "./log-cleanup.js";
|
|
18
22
|
import { initLSPConfig, loadLSPConfig } from "./lsp/config.js";
|
|
23
|
+
import { resetWorkspaceDiagnosticsCacheSession } from "./lsp/workspace-diagnostics-session.js";
|
|
24
|
+
import { resetDirectLspCommandAvailability } from "./lsp/server.js";
|
|
19
25
|
import { loadLspService } from "./lsp-lazy.js";
|
|
26
|
+
import { resetManagedToolRefreshSession } from "./installer/managed-tool-refresh-session.js";
|
|
27
|
+
import { resetResolvedPathCache } from "./installer/index.js";
|
|
28
|
+
import { _resetPackageManagerCache } from "./package-manager.js";
|
|
29
|
+
import { clearFormatterCache } from "./formatters.js";
|
|
20
30
|
import { isAtOrAboveHomeDir } from "./path-utils.js";
|
|
21
31
|
import { isPrintMode } from "./print-mode.js";
|
|
22
32
|
import { readLatestProjectSequence, readLatestProjectSequenceAsync, } from "./project-changes.js";
|
|
23
|
-
import { getProjectSnapshotPath, hydrateRuntimeFromProjectSnapshot, isProjectSnapshotFresh, isProjectSnapshotMetaStale, loadProjectSnapshot, PROJECT_SNAPSHOT_VERSION, readProjectSnapshotMeta, saveRuntimeProjectSnapshot, } from "./project-snapshot.js";
|
|
33
|
+
import { getProjectSnapshotPath, getProjectSnapshotLegacyPath, hydrateRuntimeFromProjectSnapshot, hydrateRuntimeFromProjectSnapshotIfIdle, isProjectSnapshotFresh, isProjectSnapshotMetaStale, loadProjectSnapshot, loadProjectSnapshotExportsAndRules, PROJECT_SNAPSHOT_VERSION, readProjectSnapshotMeta, saveRuntimeProjectSnapshot, } from "./project-snapshot.js";
|
|
24
34
|
import { clearTsconfigPathsCache } from "./review-graph/tsconfig-paths.js";
|
|
25
35
|
import { scanProjectRules } from "./rules-scanner.js";
|
|
26
36
|
import { resetSafeSpawnWindowsCommandCache } from "./safe-spawn.js";
|
|
@@ -33,6 +43,27 @@ import { isWarmAttached } from "./warm-attach.js";
|
|
|
33
43
|
import { setSessionLanguages } from "./widget-state.js";
|
|
34
44
|
import { logWordIndex } from "./word-index-logger.js";
|
|
35
45
|
import { resetWorkspaceTopology } from "./workspace-topology.js";
|
|
46
|
+
import { resetZizmorTokenAvailability } from "./zizmor-config.js";
|
|
47
|
+
const HOST_STALL_THRESHOLD_MS = 30_000;
|
|
48
|
+
function logHostReadyDelay(deps, cwd) {
|
|
49
|
+
if (!deps.emitHostReadyDelay ||
|
|
50
|
+
deps.sessionStartMonotonicAt === undefined ||
|
|
51
|
+
deps.extensionLoadedAt === undefined) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const durationMs = Math.max(0, deps.sessionStartMonotonicAt - deps.extensionLoadedAt);
|
|
55
|
+
logLatency({
|
|
56
|
+
type: "phase",
|
|
57
|
+
filePath: cwd,
|
|
58
|
+
phase: "host_ready_delay",
|
|
59
|
+
durationMs,
|
|
60
|
+
metadata: {
|
|
61
|
+
hostStallSuspected: durationMs > HOST_STALL_THRESHOLD_MS,
|
|
62
|
+
sessionStart: "first-process-session",
|
|
63
|
+
reason: deps.sessionReason,
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
}
|
|
36
67
|
function resolveSnapshotRoot(cwd) {
|
|
37
68
|
const resolvedCwd = path.resolve(cwd);
|
|
38
69
|
const nearest = findNearestProjectRoot(resolvedCwd);
|
|
@@ -79,6 +110,91 @@ function snapshotSequenceBase(root) {
|
|
|
79
110
|
sinceSeq: meta.seq,
|
|
80
111
|
};
|
|
81
112
|
}
|
|
113
|
+
/**
|
|
114
|
+
* #1785: one bounded ledger record per timed-out sequence read, so a real
|
|
115
|
+
* occurrence is diagnosable from the ledger alone rather than only from a
|
|
116
|
+
* `dbg` line that most hosts never surface. Carries the project root and the
|
|
117
|
+
* on-disk snapshot's age/size (when one exists) — the identity AC1 asks for:
|
|
118
|
+
* which project, how stale/large the snapshot that got skipped was.
|
|
119
|
+
*/
|
|
120
|
+
function recordSnapshotSequenceTimeout(args) {
|
|
121
|
+
let reason = "sequence read timed out; no snapshot on disk";
|
|
122
|
+
try {
|
|
123
|
+
const stat = nodeFs.statSync(args.snapshotPath);
|
|
124
|
+
reason = `sequence read timed out; snapshot age=${Math.round(Date.now() - stat.mtimeMs)}ms size=${stat.size}b`;
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
// No snapshot on disk yet — the reason above already covers it.
|
|
128
|
+
}
|
|
129
|
+
incrementDegradationCount({
|
|
130
|
+
kind: "snapshot-sequence-read-timeout",
|
|
131
|
+
subject: args.snapshotRoot,
|
|
132
|
+
reason,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* #1785: the synchronous freshness check made a conservative call with the
|
|
137
|
+
* `UNKNOWN_PROJECT_SEQ` sentinel (never hydrate when the real sequence is
|
|
138
|
+
* unknown). Once the deferred read resolves — a deterministic completion
|
|
139
|
+
* signal, not a sleep — this re-checks freshness against the now-known
|
|
140
|
+
* sequence and hydrates late when the snapshot really was current, instead of
|
|
141
|
+
* leaving the runtime without `cachedExports`/`projectRulesScan` for the rest
|
|
142
|
+
* of the session.
|
|
143
|
+
*
|
|
144
|
+
* #1785 review round F5 (design (a), replacing rounds 1-3's synchronous
|
|
145
|
+
* capture entirely): quick mode's own cold-start warmup ALREADY loads the
|
|
146
|
+
* on-disk snapshot for its own purposes — `cachedSnapshot` at the top of the
|
|
147
|
+
* warmup body, used to reuse a still-fresh `startupScan` verdict — strictly
|
|
148
|
+
* BEFORE the warmup's own possible save (`saveRuntimeProjectSnapshot`, only
|
|
149
|
+
* reached when that verdict was NOT fresh). Reusing THAT already-loaded
|
|
150
|
+
* value costs nothing new: the read was always going to happen regardless of
|
|
151
|
+
* this fix, and it is guaranteed to predate any overwrite the SAME warmup
|
|
152
|
+
* invocation might go on to make — a read-before-write invariant of the
|
|
153
|
+
* warmup's own code, not something this function has to defend against with
|
|
154
|
+
* a race window of its own. `getWarmupOwnSnapshotRead` is a closure over a
|
|
155
|
+
* per-`handleSessionStart`-call LOCAL variable (never module-scope — #1785
|
|
156
|
+
* F6 is exactly the class of bug a module-scope holder here would
|
|
157
|
+
* reintroduce) that the warmup publishes into once its own read completes.
|
|
158
|
+
*
|
|
159
|
+
* When the getter still returns `undefined` — the deferred read resolved
|
|
160
|
+
* before the warmup got that far (or no warmup was ever armed by this call:
|
|
161
|
+
* a later quick-mode call in the same process, print mode, full mode) —
|
|
162
|
+
* there is nothing published yet, so this falls back to a live re-load via
|
|
163
|
+
* `loadProjectSnapshotExportsAndRules`. That fallback is exactly as safe as
|
|
164
|
+
* the primary path: if the warmup hasn't reached its own read yet, it
|
|
165
|
+
* certainly hasn't saved yet either (same invariant), so disk still holds
|
|
166
|
+
* whatever was there before any warmup activity.
|
|
167
|
+
*
|
|
168
|
+
* Both the published value and the fallback re-load are the narrow,
|
|
169
|
+
* postings-free `ProjectSnapshotExportsAndRules` shape — never the full
|
|
170
|
+
* `loadProjectSnapshot`. This path only ever hydrates
|
|
171
|
+
* `cachedExports`/`projectRulesScan`; it can NOT hydrate `wordIndex` even
|
|
172
|
+
* when the underlying snapshot would otherwise have one, because the narrow
|
|
173
|
+
* type never carries it. That is intentional, not a regression: F2's hazard
|
|
174
|
+
* was this exact path nulling a `wordIndex` that quick mode's warmup had, in
|
|
175
|
+
* the meantime, built for real — the warmup remains the sole source of a
|
|
176
|
+
* late-arriving `wordIndex` for the interactive path.
|
|
177
|
+
*/
|
|
178
|
+
function retroactivelyHydrateAfterDeferredSequence(args) {
|
|
179
|
+
return (latestSeq) => {
|
|
180
|
+
const published = args.getWarmupOwnSnapshotRead();
|
|
181
|
+
const snapshot = published !== undefined
|
|
182
|
+
? published
|
|
183
|
+
: loadProjectSnapshotExportsAndRules(args.snapshotRoot);
|
|
184
|
+
if (!snapshot ||
|
|
185
|
+
snapshot.version !== PROJECT_SNAPSHOT_VERSION ||
|
|
186
|
+
snapshot.seq !== latestSeq.projectSeq) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
const hydrated = hydrateRuntimeFromProjectSnapshotIfIdle(args.runtime, snapshot);
|
|
190
|
+
if (hydrated) {
|
|
191
|
+
args.dbg(`session_start: deferred sequence read confirmed snapshot freshness — hydrating cachedExports/projectRulesScan late (seq=${snapshot.seq})`);
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
args.dbg(`session_start: deferred sequence read confirmed snapshot freshness (seq=${snapshot.seq}), but the runtime already has live state (warmup or another task got there first) — skipping late hydration to avoid clobbering it`);
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
}
|
|
82
198
|
function loadSnapshotBodyUnlessStale(args) {
|
|
83
199
|
const meta = readProjectSnapshotMeta(args.root);
|
|
84
200
|
if (meta && isProjectSnapshotMetaStale(meta, args.currentProjectSeq)) {
|
|
@@ -90,12 +206,17 @@ function loadSnapshotBodyUnlessStale(args) {
|
|
|
90
206
|
skippedStale: false,
|
|
91
207
|
};
|
|
92
208
|
}
|
|
93
|
-
function describeSnapshotMiss(snapshot, currentProjectSeq) {
|
|
209
|
+
function describeSnapshotMiss(snapshot, currentProjectSeq, args) {
|
|
210
|
+
if (args.skippedStale)
|
|
211
|
+
return "stale-meta-gate";
|
|
94
212
|
if (!snapshot)
|
|
95
|
-
return "missing";
|
|
213
|
+
return args.bodyPresent ? "invalid-body" : "missing";
|
|
96
214
|
if (snapshot.seq !== currentProjectSeq) {
|
|
97
215
|
return `stale(seq=${snapshot.seq}, current=${currentProjectSeq})`;
|
|
98
216
|
}
|
|
217
|
+
// Defensive-only arm: parseSnapshot rejects incompatible versions, and a
|
|
218
|
+
// same-sequence parsed snapshot is fresh. Keep this classification explicit
|
|
219
|
+
// so a future loader change cannot collapse it into a generic miss.
|
|
99
220
|
return "incompatible";
|
|
100
221
|
}
|
|
101
222
|
function logProjectSnapshotProbe(args) {
|
|
@@ -104,7 +225,7 @@ function logProjectSnapshotProbe(args) {
|
|
|
104
225
|
args.dbg(`project_snapshot: loaded seq=${args.snapshot.seq} exports=${args.snapshot.cachedExports.length} files=${Object.keys(args.snapshot.files ?? {}).length} reverseDeps=${Object.keys(args.snapshot.reverseDeps ?? {}).length} startupScan=${Boolean(args.snapshot.startupScan)} languageProfile=${Boolean(args.snapshot.languageProfile)}`);
|
|
105
226
|
}
|
|
106
227
|
else {
|
|
107
|
-
args.dbg(`project_snapshot: miss reason=${
|
|
228
|
+
args.dbg(`project_snapshot: miss reason=${args.missReason}`);
|
|
108
229
|
}
|
|
109
230
|
}
|
|
110
231
|
function resolveStartupMode() {
|
|
@@ -171,7 +292,7 @@ const UNKNOWN_PROJECT_SEQ = -1;
|
|
|
171
292
|
* logs its own `session_start_sequence_read_deferred_reseed` phase.
|
|
172
293
|
*/
|
|
173
294
|
async function readSequenceWithBudget(args) {
|
|
174
|
-
const { snapshotRoot, base, cwd, runtime, sessionGeneration, dbg } = args;
|
|
295
|
+
const { snapshotRoot, base, cwd, runtime, sessionGeneration, dbg, onDeferredSequenceResolved, } = args;
|
|
175
296
|
const readPromise = readLatestProjectSequenceAsync(snapshotRoot, base);
|
|
176
297
|
let timeoutHandle;
|
|
177
298
|
const timeoutPromise = new Promise((resolve) => {
|
|
@@ -224,6 +345,7 @@ async function readSequenceWithBudget(args) {
|
|
|
224
345
|
metadata: { entries: latestSeq.fileSeqByPath.size, deferred: true },
|
|
225
346
|
});
|
|
226
347
|
dbg(`session_start: deferred sequence read completed — reseeded projectSeq=${latestSeq.projectSeq} fileSeqEntries=${latestSeq.fileSeqByPath.size}`);
|
|
348
|
+
onDeferredSequenceResolved?.(latestSeq);
|
|
227
349
|
})
|
|
228
350
|
.catch((err) => {
|
|
229
351
|
dbg(`session_start: deferred sequence read failed: ${err}`);
|
|
@@ -375,6 +497,47 @@ function firePreinstallDefaults(ensureTool, dbg, startupDefaults) {
|
|
|
375
497
|
});
|
|
376
498
|
}
|
|
377
499
|
}
|
|
500
|
+
/**
|
|
501
|
+
* Default delay before the managed-tool version refresh runs (#1730). Long
|
|
502
|
+
* enough that `session_start`, the startup scans, and the tool preinstalls have
|
|
503
|
+
* all settled — the refresh may spawn one `npm update`, and that must never
|
|
504
|
+
* compete with the work the user is waiting on.
|
|
505
|
+
*/
|
|
506
|
+
const MANAGED_TOOL_REFRESH_DELAY_MS = 30_000;
|
|
507
|
+
/**
|
|
508
|
+
* Schedule the periodic managed-tool refresh (#1730) on an unref'd background
|
|
509
|
+
* timer.
|
|
510
|
+
*
|
|
511
|
+
* `session_start`'s own cost here is a single `setTimeout` registration: the
|
|
512
|
+
* refresh module is not even imported until the timer fires. The timer is
|
|
513
|
+
* unref'd so a one-shot process exits without waiting for it, matching the
|
|
514
|
+
* warmup timer above. Whether a refresh actually runs is decided inside
|
|
515
|
+
* `runManagedToolRefresh` against a PERSISTED per-tool stamp, so a launch loop
|
|
516
|
+
* cannot escalate the weekly cadence.
|
|
517
|
+
*/
|
|
518
|
+
function scheduleManagedToolRefresh(dbg) {
|
|
519
|
+
const delayMs = Number(process.env.PI_LENS_TOOL_REFRESH_DELAY_MS ?? MANAGED_TOOL_REFRESH_DELAY_MS);
|
|
520
|
+
const timer = setTimeout(() => {
|
|
521
|
+
void (async () => {
|
|
522
|
+
try {
|
|
523
|
+
const refresh = await import("./installer/managed-tool-refresh.js");
|
|
524
|
+
const outcome = await refresh.runManagedToolRefresh();
|
|
525
|
+
if (outcome.skipped) {
|
|
526
|
+
dbg(`session_start tool-refresh: skipped (${outcome.skipped})`);
|
|
527
|
+
return;
|
|
528
|
+
}
|
|
529
|
+
for (const result of outcome.refreshed) {
|
|
530
|
+
dbg(`session_start tool-refresh: ${result.toolId} ${result.ok ? "ok" : "failed"}` +
|
|
531
|
+
`${result.changed ? ` ${result.previousVersion ?? "unknown"} → ${result.currentVersion}` : " (unchanged)"}`);
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
catch (err) {
|
|
535
|
+
dbg(`session_start tool-refresh: error ${err}`);
|
|
536
|
+
}
|
|
537
|
+
})();
|
|
538
|
+
}, Number.isFinite(delayMs) ? delayMs : MANAGED_TOOL_REFRESH_DELAY_MS);
|
|
539
|
+
timer.unref?.();
|
|
540
|
+
}
|
|
378
541
|
async function probePrettierInstall(ensureTool, dbg, analysisRoot) {
|
|
379
542
|
const pkgPath = path.join(analysisRoot, "package.json");
|
|
380
543
|
try {
|
|
@@ -715,7 +878,7 @@ function scheduleStartupScans(deps, runtime, sessionGeneration, analysisRoot, sn
|
|
|
715
878
|
// KnipClient skips before probing/installing when analysisRoot is not a real
|
|
716
879
|
// JS/Knip project. This avoids running knip from Unity/C#/generic repos.
|
|
717
880
|
const startMs = Date.now();
|
|
718
|
-
const knipResult = await knipClient.analyze(analysisRoot, getKnipIgnorePatterns());
|
|
881
|
+
const knipResult = await knipClient.analyze(analysisRoot, getKnipIgnorePatterns(), { projectSeq: runtime.projectSeq });
|
|
719
882
|
if (!runtime.isCurrentSession(sessionGeneration))
|
|
720
883
|
return;
|
|
721
884
|
if (knipResult.success) {
|
|
@@ -1121,6 +1284,12 @@ export const SESSION_START_GUIDANCE = [
|
|
|
1121
1284
|
];
|
|
1122
1285
|
export async function handleSessionStart(deps) {
|
|
1123
1286
|
resetDegradationLedger();
|
|
1287
|
+
// #1743: the bounded-telemetry per-turn counters. The rising-edge state is
|
|
1288
|
+
// NOT here — it is the ledger's own tally, reset on the line above. These
|
|
1289
|
+
// counters are keyed by turn index, and a new session restarts turn
|
|
1290
|
+
// numbering at 0, so without this a stale count could survive a session
|
|
1291
|
+
// boundary that happened to land on the same index.
|
|
1292
|
+
resetBoundedTelemetry();
|
|
1124
1293
|
const handlerEnteredAt = Date.now();
|
|
1125
1294
|
const sessionStartMs = deps.sessionStartFiredAt ?? handlerEnteredAt;
|
|
1126
1295
|
const cwdForTelemetry = deps.ctxCwd ?? process.cwd();
|
|
@@ -1175,6 +1344,11 @@ export async function handleSessionStart(deps) {
|
|
|
1175
1344
|
// (an explicit env var still takes highest precedence).
|
|
1176
1345
|
// Tunable: PI_LENS_WARMUP_DELAY_MS adjusts the warmup delay.
|
|
1177
1346
|
let startupMode = resolveStartupMode();
|
|
1347
|
+
// SAFETY: these two flags are process-lifetime state pi-lens stashes on
|
|
1348
|
+
// `globalThis` so a second extension instance in the same process sees the
|
|
1349
|
+
// first one's warmup. There is no ambient declaration for them, and adding
|
|
1350
|
+
// one would let any module write them. Both are declared OPTIONAL here, so
|
|
1351
|
+
// the reads below are `undefined`-safe on a process where nothing set them.
|
|
1178
1352
|
const processGlobals = globalThis;
|
|
1179
1353
|
const isFirstSessionOfProcess = !processGlobals.__piLensFirstSessionDone;
|
|
1180
1354
|
if (isFirstSessionOfProcess &&
|
|
@@ -1185,6 +1359,20 @@ export async function handleSessionStart(deps) {
|
|
|
1185
1359
|
startupMode = deps.startupModeOverride ?? "quick";
|
|
1186
1360
|
}
|
|
1187
1361
|
processGlobals.__piLensFirstSessionDone = true;
|
|
1362
|
+
// #1785 F5 (round 4, design (a)): the warmup timer body below ALREADY
|
|
1363
|
+
// loads the on-disk snapshot for its own purposes (`cachedSnapshot`,
|
|
1364
|
+
// reused for the `startupScan` verdict cache) strictly BEFORE any save it
|
|
1365
|
+
// might go on to make. This LOCAL variable — per-`handleSessionStart`-call,
|
|
1366
|
+
// deliberately NOT module-scope (see #1785 F6) — lets the warmup publish
|
|
1367
|
+
// that already-loaded read (narrowed to exports+rules, never the full
|
|
1368
|
+
// object with `wordIndex`) for `retroactivelyHydrateAfterDeferredSequence`
|
|
1369
|
+
// to reuse at zero additional cost, instead of this call paying for its
|
|
1370
|
+
// own separate synchronous capture (rounds 1-3's approach, reverted here:
|
|
1371
|
+
// see that function's doc comment for the full history). `undefined`
|
|
1372
|
+
// means the warmup hasn't reached its own read yet (or was never armed by
|
|
1373
|
+
// this call at all) — the quick-mode block's retroactive-hydration
|
|
1374
|
+
// callback then falls back to a live re-load instead.
|
|
1375
|
+
let warmupOwnSnapshotRead;
|
|
1188
1376
|
// #1154: quick mode is entered on BOTH `pi -p`/`--print` (a one-shot that
|
|
1189
1377
|
// exits right after this turn) and an interactive process's first
|
|
1190
1378
|
// session_start (forced quick to protect keystroke latency, then warms
|
|
@@ -1232,6 +1420,23 @@ export async function handleSessionStart(deps) {
|
|
|
1232
1420
|
// reuse it instead of re-walking a possibly huge tree from
|
|
1233
1421
|
// scratch on every single startup.
|
|
1234
1422
|
const cachedSnapshot = loadProjectSnapshot(warmupSnapshotRoot);
|
|
1423
|
+
// #1785 F5 (round 4): publish this ALREADY-loaded read — narrowed
|
|
1424
|
+
// to exports+rules, never a reference to `cachedSnapshot` itself
|
|
1425
|
+
// (which carries `wordIndex`/`files`/`symbols`/`reverseDeps`) — for
|
|
1426
|
+
// `retroactivelyHydrateAfterDeferredSequence` to reuse. This read
|
|
1427
|
+
// strictly precedes the warmup's own possible save a few lines
|
|
1428
|
+
// below, so it is guaranteed to reflect disk as it stood before
|
|
1429
|
+
// THIS warmup could have touched it. Zero marginal cost: this read
|
|
1430
|
+
// already happens unconditionally for the `startupScan` verdict
|
|
1431
|
+
// cache below, with or without this fix.
|
|
1432
|
+
warmupOwnSnapshotRead = cachedSnapshot
|
|
1433
|
+
? {
|
|
1434
|
+
version: cachedSnapshot.version,
|
|
1435
|
+
seq: cachedSnapshot.seq,
|
|
1436
|
+
cachedExports: cachedSnapshot.cachedExports,
|
|
1437
|
+
projectRulesScan: cachedSnapshot.projectRulesScan,
|
|
1438
|
+
}
|
|
1439
|
+
: null;
|
|
1235
1440
|
const cachedVerdict = cachedSnapshot?.startupScan;
|
|
1236
1441
|
let scan;
|
|
1237
1442
|
if (cachedVerdict &&
|
|
@@ -1381,7 +1586,7 @@ export async function handleSessionStart(deps) {
|
|
|
1381
1586
|
}
|
|
1382
1587
|
const allowBootstrapTasks = startupMode === "full";
|
|
1383
1588
|
const quickMode = startupMode === "quick";
|
|
1384
|
-
const { ctxCwd, getFlag, notify, dbg, log, runtime, metricsClient, cacheManager, testRunnerClient, goClient, rustClient, ensureTool, cleanStaleTsBuildInfo, resetDispatchBaselines, resetLSPService, } = deps;
|
|
1589
|
+
const { ctxCwd, getFlag, notify, dbg, log, runtime, metricsClient, knipClient, cacheManager, testRunnerClient, goClient, rustClient, ensureTool, cleanStaleTsBuildInfo, resetDispatchBaselines, resetLSPService, } = deps;
|
|
1385
1590
|
// Lightweight phase timer — resets after each call so each log line shows
|
|
1386
1591
|
// the cost of that phase alone, not cumulative time from session start.
|
|
1387
1592
|
let _phaseT = Date.now();
|
|
@@ -1415,9 +1620,66 @@ export async function handleSessionStart(deps) {
|
|
|
1415
1620
|
// the tool for the rest of the process lifetime. Clear it here, same
|
|
1416
1621
|
// boundary as the other per-session caches on this line.
|
|
1417
1622
|
resetDispatchAvailabilityState();
|
|
1623
|
+
// #1895: formatter PATH verdicts are session-scoped, but they live in
|
|
1624
|
+
// formatters.ts and are not covered by the dispatch generation. Re-arm them
|
|
1625
|
+
// here so a formatter installed or removed between sessions is observed by
|
|
1626
|
+
// the next session. `clearFormatterCache` drops the per-cwd selection cache
|
|
1627
|
+
// as well as the which latches, which is what a real re-probe needs: the
|
|
1628
|
+
// selection cache answers a same-cwd lookup before any probe runs, so
|
|
1629
|
+
// clearing the latches alone would leave the stale verdict standing in the
|
|
1630
|
+
// one directory the user is working in.
|
|
1631
|
+
clearFormatterCache();
|
|
1632
|
+
// #1535: same #1266 pattern, one caller earlier — the `gh auth token` latch
|
|
1633
|
+
// zizmor's spawn reads is process-lived storage whose durability contract is
|
|
1634
|
+
// per SESSION, not per process. Without this, a user who runs `gh auth
|
|
1635
|
+
// login` and starts a fresh session still reads the previous session's
|
|
1636
|
+
// stale "no token" verdict until the cooldown (if any) happens to expire.
|
|
1637
|
+
resetZizmorTokenAvailability();
|
|
1638
|
+
// psscriptanalyzer's three latches (interpreter, module, -File exec) are
|
|
1639
|
+
// module-local, so the generation counter above does not reach them
|
|
1640
|
+
// (#1490, #1540).
|
|
1641
|
+
resetPsScriptAnalyzerAvailability();
|
|
1642
|
+
// #1497: the install-class retry ceiling is terminal for a SESSION, but the
|
|
1643
|
+
// latches holding it live on process-lived client instances (bootstrap builds
|
|
1644
|
+
// them once). Same #1266/#1490/#1535 shape — without this line "terminal for
|
|
1645
|
+
// the session" is terminal for the process, and a repaired network never
|
|
1646
|
+
// re-earns its `go install`.
|
|
1647
|
+
resetInstallRetryLatches();
|
|
1648
|
+
// #1537: the lazy-install seam's hold (`gem install rubocop`, `rustup
|
|
1649
|
+
// component add`) is durable for a SESSION. Its map is module-local, so the
|
|
1650
|
+
// generation counter above does not reach it — same #1490/#1497 shape. It
|
|
1651
|
+
// belongs on THIS line and not on the turn_end path: the first cut cleared it
|
|
1652
|
+
// from `clearFormatterRuntimeState()`, which runs every turn, so a failing
|
|
1653
|
+
// install re-spawned every turn instead of once per session.
|
|
1654
|
+
resetLazyInstallAttempts();
|
|
1655
|
+
// #1897: direct-LSP negative availability and bare installer paths are
|
|
1656
|
+
// session facts. A command or PATH entry can appear between sessions.
|
|
1657
|
+
resetDirectLspCommandAvailability();
|
|
1658
|
+
resetResolvedPathCache();
|
|
1659
|
+
// #1653: pnpm/yarn/bun/npm's availability latches (package-manager.ts) are
|
|
1660
|
+
// module-local, same #1490/#1535 shape as the two lines above — the
|
|
1661
|
+
// generation counter above does not reach them. Without this line, a
|
|
1662
|
+
// pnpm/yarn/bun install done mid-day stayed invisible: a genuine "missing"
|
|
1663
|
+
// verdict from one session latched into the next until a process restart.
|
|
1664
|
+
_resetPackageManagerCache();
|
|
1665
|
+
// #1730: the managed-tool refresh budget is a per-SESSION allowance (at most
|
|
1666
|
+
// one `npm update` per session). Left process-lived, one long-running pi
|
|
1667
|
+
// would refresh a single tool at launch and never look at the other 21
|
|
1668
|
+
// again — the same latch shape as the two lines above. The weekly cadence
|
|
1669
|
+
// itself is NOT reset here: it lives in the persisted per-tool stamp, so
|
|
1670
|
+
// re-arming the budget only restores the session's right to ask.
|
|
1671
|
+
resetManagedToolRefreshSession();
|
|
1418
1672
|
// #1123 item 3: a fresh session can re-report smells that a prior session
|
|
1419
1673
|
// already surfaced once (see `checkSmellsAndNoteOnce`'s once-per-session gate).
|
|
1420
1674
|
resetSmellsSessionState();
|
|
1675
|
+
// #1782: re-arm the workspace-diagnostics cache session clock. Entries
|
|
1676
|
+
// written before this instant assert findings from a session that is over,
|
|
1677
|
+
// so they must revalidate before they can be served as current again.
|
|
1678
|
+
resetWorkspaceDiagnosticsCacheSession(sessionStartMs);
|
|
1679
|
+
// Some embedders inject a capability-shaped Knip client rather than the
|
|
1680
|
+
// concrete KnipClient. Session reset is an optional lifecycle capability;
|
|
1681
|
+
// its absence must not make session_start fail.
|
|
1682
|
+
knipClient.resetSessionState?.();
|
|
1421
1683
|
runtime.resetForSession(sessionStartMs);
|
|
1422
1684
|
logLatency({
|
|
1423
1685
|
type: "phase",
|
|
@@ -1471,11 +1733,21 @@ export async function handleSessionStart(deps) {
|
|
|
1471
1733
|
// project data roots and machine-global registry root once per session start;
|
|
1472
1734
|
// this is fire-and-forget and bounded so it never delays startup.
|
|
1473
1735
|
const projectDataDir = getProjectDataDir(cwd);
|
|
1736
|
+
// #1609 review F1: sweepOwnStagingFiles does not recurse, so the installer's
|
|
1737
|
+
// bin/ and tools/ subdirectories (clients/installer/index.ts's
|
|
1738
|
+
// GITHUB_BIN_DIR / TOOLS_DIR, now atomic-write.js writers too) need their
|
|
1739
|
+
// own entries — otherwise an orphaned staging file from a kill mid-install
|
|
1740
|
+
// (this PR's own motivating scenario) never gets reaped, and unique
|
|
1741
|
+
// pid-thread-seq staging names mean repeated kills ACCUMULATE full-size
|
|
1742
|
+
// orphan binaries instead of being cleaned up.
|
|
1743
|
+
const globalDir = getGlobalPiLensDir();
|
|
1474
1744
|
void sweepAtomicWriteStages([
|
|
1475
1745
|
projectDataDir,
|
|
1476
1746
|
path.join(projectDataDir, "cache"),
|
|
1477
1747
|
path.join(projectDataDir, "sessions"),
|
|
1478
|
-
|
|
1748
|
+
globalDir,
|
|
1749
|
+
path.join(globalDir, "bin"),
|
|
1750
|
+
path.join(globalDir, "tools"),
|
|
1479
1751
|
]).catch(() => {
|
|
1480
1752
|
// best-effort lifecycle cleanup — never fail session_start
|
|
1481
1753
|
});
|
|
@@ -1483,6 +1755,12 @@ export async function handleSessionStart(deps) {
|
|
|
1483
1755
|
runtime.projectRoot = cwd;
|
|
1484
1756
|
const sequenceReadStartedAt = Date.now();
|
|
1485
1757
|
const snapshotRoot = resolveSnapshotRoot(cwd);
|
|
1758
|
+
// #1785 F5 (round 4): the getter closes over `warmupOwnSnapshotRead`
|
|
1759
|
+
// directly (a `let` in this same `handleSessionStart` invocation's
|
|
1760
|
+
// scope), so it reads whatever value is current AT DEFERRED-RESOLVE
|
|
1761
|
+
// TIME — not whatever it was at this wiring instant. See
|
|
1762
|
+
// `retroactivelyHydrateAfterDeferredSequence`'s doc comment for the
|
|
1763
|
+
// full design.
|
|
1486
1764
|
const { latestSeq, timedOut } = await readSequenceWithBudget({
|
|
1487
1765
|
snapshotRoot,
|
|
1488
1766
|
base: snapshotSequenceBase(snapshotRoot),
|
|
@@ -1490,6 +1768,12 @@ export async function handleSessionStart(deps) {
|
|
|
1490
1768
|
runtime,
|
|
1491
1769
|
sessionGeneration: runtime.sessionGeneration,
|
|
1492
1770
|
dbg,
|
|
1771
|
+
onDeferredSequenceResolved: retroactivelyHydrateAfterDeferredSequence({
|
|
1772
|
+
getWarmupOwnSnapshotRead: () => warmupOwnSnapshotRead,
|
|
1773
|
+
snapshotRoot,
|
|
1774
|
+
runtime,
|
|
1775
|
+
dbg,
|
|
1776
|
+
}),
|
|
1493
1777
|
});
|
|
1494
1778
|
logLatency({
|
|
1495
1779
|
type: "phase",
|
|
@@ -1499,6 +1783,12 @@ export async function handleSessionStart(deps) {
|
|
|
1499
1783
|
durationMs: Date.now() - sequenceReadStartedAt,
|
|
1500
1784
|
metadata: { entries: latestSeq.fileSeqByPath.size, timedOut },
|
|
1501
1785
|
});
|
|
1786
|
+
if (timedOut) {
|
|
1787
|
+
recordSnapshotSequenceTimeout({
|
|
1788
|
+
snapshotRoot,
|
|
1789
|
+
snapshotPath: getProjectSnapshotPath(snapshotRoot),
|
|
1790
|
+
});
|
|
1791
|
+
}
|
|
1502
1792
|
runtime.seedProjectSequence?.(latestSeq.projectSeq, latestSeq.fileSeqByPath);
|
|
1503
1793
|
const effectiveSeq = runtime.projectSeq ?? latestSeq.projectSeq;
|
|
1504
1794
|
dbg(`session_start sequence: projectSeq=${effectiveSeq} fileSeqEntries=${latestSeq.fileSeqByPath.size}`);
|
|
@@ -1522,6 +1812,8 @@ export async function handleSessionStart(deps) {
|
|
|
1522
1812
|
catch {
|
|
1523
1813
|
// Missing snapshots are the normal cold-start case.
|
|
1524
1814
|
}
|
|
1815
|
+
const snapshotBodyPresent = nodeFs.existsSync(snapshotPath) ||
|
|
1816
|
+
nodeFs.existsSync(getProjectSnapshotLegacyPath(snapshotRoot));
|
|
1525
1817
|
const snapshotGate = loadSnapshotBodyUnlessStale({
|
|
1526
1818
|
root: snapshotRoot,
|
|
1527
1819
|
currentProjectSeq: freshnessSeq,
|
|
@@ -1529,6 +1821,10 @@ export async function handleSessionStart(deps) {
|
|
|
1529
1821
|
});
|
|
1530
1822
|
const snapshot = snapshotGate.snapshot;
|
|
1531
1823
|
const snapshotFresh = isProjectSnapshotFresh(snapshot, freshnessSeq);
|
|
1824
|
+
const snapshotMissReason = describeSnapshotMiss(snapshot, freshnessSeq, {
|
|
1825
|
+
skippedStale: snapshotGate.skippedStale,
|
|
1826
|
+
bodyPresent: snapshotBodyPresent,
|
|
1827
|
+
});
|
|
1532
1828
|
logLatency({
|
|
1533
1829
|
type: "phase",
|
|
1534
1830
|
phase: "session_start_snapshot_load",
|
|
@@ -1539,6 +1835,7 @@ export async function handleSessionStart(deps) {
|
|
|
1539
1835
|
bytes: snapshotBytes,
|
|
1540
1836
|
fresh: snapshotFresh,
|
|
1541
1837
|
seq: snapshot?.seq ?? null,
|
|
1838
|
+
reason: snapshotFresh ? undefined : snapshotMissReason,
|
|
1542
1839
|
...(snapshotGate.skippedStale ? { skippedStale: true } : {}),
|
|
1543
1840
|
...(timedOut ? { sequenceUnknown: true } : {}),
|
|
1544
1841
|
},
|
|
@@ -1548,6 +1845,7 @@ export async function handleSessionStart(deps) {
|
|
|
1548
1845
|
root: snapshotRoot,
|
|
1549
1846
|
currentProjectSeq: freshnessSeq,
|
|
1550
1847
|
snapshot,
|
|
1848
|
+
missReason: snapshotMissReason,
|
|
1551
1849
|
});
|
|
1552
1850
|
if (snapshotFresh) {
|
|
1553
1851
|
hydrateRuntimeFromProjectSnapshot(runtime, snapshot);
|
|
@@ -1569,6 +1867,7 @@ export async function handleSessionStart(deps) {
|
|
|
1569
1867
|
durationMs: totalDurationMs,
|
|
1570
1868
|
metadata: { mode: startupMode, reason: deps.sessionReason },
|
|
1571
1869
|
});
|
|
1870
|
+
logHostReadyDelay(deps, cwd);
|
|
1572
1871
|
emitSmellsSessionStartLine(dbg, sessionStartMs);
|
|
1573
1872
|
return;
|
|
1574
1873
|
}
|
|
@@ -1605,6 +1904,20 @@ export async function handleSessionStart(deps) {
|
|
|
1605
1904
|
durationMs: Date.now() - sequenceReadStartedAt,
|
|
1606
1905
|
metadata: { entries: latestSeq.fileSeqByPath.size, timedOut },
|
|
1607
1906
|
});
|
|
1907
|
+
if (timedOut) {
|
|
1908
|
+
// #1785: instrumentation only here, deliberately no
|
|
1909
|
+
// `onDeferredSequenceResolved` — unlike quick mode's cold path (which
|
|
1910
|
+
// does nothing when the snapshot isn't trusted), full mode's cold path
|
|
1911
|
+
// actively kicks off a real rescan below to rebuild this same state.
|
|
1912
|
+
// Retroactively hydrating from the on-disk snapshot once the deferred
|
|
1913
|
+
// read lands could overwrite that fresher, actively-computed state with
|
|
1914
|
+
// the stale disk copy — a regression, not a fix. See the PR body for the
|
|
1915
|
+
// full reasoning.
|
|
1916
|
+
recordSnapshotSequenceTimeout({
|
|
1917
|
+
snapshotRoot,
|
|
1918
|
+
snapshotPath: getProjectSnapshotPath(snapshotRoot),
|
|
1919
|
+
});
|
|
1920
|
+
}
|
|
1608
1921
|
runtime.seedProjectSequence?.(latestSeq.projectSeq, latestSeq.fileSeqByPath);
|
|
1609
1922
|
const effectiveSeq = runtime.projectSeq ?? latestSeq.projectSeq;
|
|
1610
1923
|
dbg(`session_start sequence: projectSeq=${effectiveSeq} fileSeqEntries=${latestSeq.fileSeqByPath.size}`);
|
|
@@ -1624,6 +1937,8 @@ export async function handleSessionStart(deps) {
|
|
|
1624
1937
|
catch {
|
|
1625
1938
|
// Missing snapshots are the normal cold-start case.
|
|
1626
1939
|
}
|
|
1940
|
+
const snapshotBodyPresent = nodeFs.existsSync(snapshotPath) ||
|
|
1941
|
+
nodeFs.existsSync(getProjectSnapshotLegacyPath(snapshotRoot));
|
|
1627
1942
|
const snapshotGate = loadSnapshotBodyUnlessStale({
|
|
1628
1943
|
root: snapshotRoot,
|
|
1629
1944
|
currentProjectSeq: freshnessSeq,
|
|
@@ -1631,6 +1946,10 @@ export async function handleSessionStart(deps) {
|
|
|
1631
1946
|
});
|
|
1632
1947
|
const snapshot = snapshotGate.snapshot;
|
|
1633
1948
|
const snapshotFresh = isProjectSnapshotFresh(snapshot, freshnessSeq);
|
|
1949
|
+
const snapshotMissReason = describeSnapshotMiss(snapshot, freshnessSeq, {
|
|
1950
|
+
skippedStale: snapshotGate.skippedStale,
|
|
1951
|
+
bodyPresent: snapshotBodyPresent,
|
|
1952
|
+
});
|
|
1634
1953
|
logLatency({
|
|
1635
1954
|
type: "phase",
|
|
1636
1955
|
phase: "session_start_snapshot_load",
|
|
@@ -1641,6 +1960,7 @@ export async function handleSessionStart(deps) {
|
|
|
1641
1960
|
bytes: snapshotBytes,
|
|
1642
1961
|
fresh: snapshotFresh,
|
|
1643
1962
|
seq: snapshot?.seq ?? null,
|
|
1963
|
+
reason: snapshotFresh ? undefined : snapshotMissReason,
|
|
1644
1964
|
...(snapshotGate.skippedStale ? { skippedStale: true } : {}),
|
|
1645
1965
|
...(timedOut ? { sequenceUnknown: true } : {}),
|
|
1646
1966
|
},
|
|
@@ -1650,6 +1970,7 @@ export async function handleSessionStart(deps) {
|
|
|
1650
1970
|
root: snapshotRoot,
|
|
1651
1971
|
currentProjectSeq: freshnessSeq,
|
|
1652
1972
|
snapshot,
|
|
1973
|
+
missReason: snapshotMissReason,
|
|
1653
1974
|
});
|
|
1654
1975
|
const freshSnapshot = snapshotFresh ? snapshot : null;
|
|
1655
1976
|
if (freshSnapshot) {
|
|
@@ -1777,6 +2098,7 @@ export async function handleSessionStart(deps) {
|
|
|
1777
2098
|
const jstsHeavyScansWillRun = startupScansWillRun && canRunStartupHeavyScans(languageProfile, "jsts");
|
|
1778
2099
|
if (allowBootstrapTasks) {
|
|
1779
2100
|
scheduleDeferredToolProbes(deps, languageProfile, startupDefaults, jstsHeavyScansWillRun, dbg);
|
|
2101
|
+
scheduleManagedToolRefresh(dbg);
|
|
1780
2102
|
}
|
|
1781
2103
|
if (allowBootstrapTasks) {
|
|
1782
2104
|
// Fire-and-forget like other tool probes
|
|
@@ -1889,6 +2211,7 @@ export async function handleSessionStart(deps) {
|
|
|
1889
2211
|
durationMs: totalDurationMs,
|
|
1890
2212
|
metadata: { mode: startupMode, reason: deps.sessionReason },
|
|
1891
2213
|
});
|
|
2214
|
+
logHostReadyDelay(deps, cwd);
|
|
1892
2215
|
emitSmellsSessionStartLine(dbg, sessionStartMs);
|
|
1893
2216
|
}
|
|
1894
2217
|
/**
|