@herbertgao/pi-extensions 2026.9.6 → 2026.9.8
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 +3 -8
- package/THIRD_PARTY_NOTICES.md +0 -4
- package/node_modules/@narumitw/pi-btw/README.md +2 -0
- package/node_modules/@narumitw/pi-btw/dist/index.ts +284 -365
- package/node_modules/@narumitw/pi-btw/dist/index.ts.map +3 -3
- package/node_modules/@narumitw/pi-btw/package.json +52 -53
- package/node_modules/@narumitw/pi-btw/src/bring-to-main.ts +494 -547
- package/node_modules/@narumitw/pi-btw/src/btw.ts +814 -856
- package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +673 -674
- package/node_modules/@narumitw/pi-btw/src/keybindings.ts +228 -270
- package/node_modules/@narumitw/pi-btw/src/main-tree-picker.ts +309 -318
- package/node_modules/@narumitw/pi-btw/src/menu.ts +416 -454
- package/node_modules/@narumitw/pi-btw/src/settings.ts +203 -219
- package/node_modules/@narumitw/pi-btw/src/side-thread.ts +173 -201
- package/node_modules/@narumitw/pi-btw/src/text.ts +21 -23
- package/node_modules/@narumitw/pi-btw/src/transcript-markdown.ts +65 -0
- package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +611 -662
- package/node_modules/grok-mermaid/CHANGELOG.md +46 -0
- package/node_modules/grok-mermaid/LICENSE +205 -0
- package/node_modules/grok-mermaid/README.md +191 -0
- package/node_modules/grok-mermaid/dist/ansi.d.ts +16 -0
- package/node_modules/grok-mermaid/dist/ansi.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/ansi.js +23 -0
- package/node_modules/grok-mermaid/dist/ansi.js.map +1 -0
- package/node_modules/grok-mermaid/dist/canvas.d.ts +87 -0
- package/node_modules/grok-mermaid/dist/canvas.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/canvas.js +366 -0
- package/node_modules/grok-mermaid/dist/canvas.js.map +1 -0
- package/node_modules/grok-mermaid/dist/graph.d.ts +74 -0
- package/node_modules/grok-mermaid/dist/graph.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/graph.js +91 -0
- package/node_modules/grok-mermaid/dist/graph.js.map +1 -0
- package/node_modules/grok-mermaid/dist/index.d.ts +32 -0
- package/node_modules/grok-mermaid/dist/index.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/index.js +100 -0
- package/node_modules/grok-mermaid/dist/index.js.map +1 -0
- package/node_modules/grok-mermaid/dist/labels.d.ts +62 -0
- package/node_modules/grok-mermaid/dist/labels.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/labels.js +324 -0
- package/node_modules/grok-mermaid/dist/labels.js.map +1 -0
- package/node_modules/grok-mermaid/dist/layout-seq.d.ts +12 -0
- package/node_modules/grok-mermaid/dist/layout-seq.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/layout-seq.js +194 -0
- package/node_modules/grok-mermaid/dist/layout-seq.js.map +1 -0
- package/node_modules/grok-mermaid/dist/layout.d.ts +87 -0
- package/node_modules/grok-mermaid/dist/layout.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/layout.js +881 -0
- package/node_modules/grok-mermaid/dist/layout.js.map +1 -0
- package/node_modules/grok-mermaid/dist/parse.d.ts +83 -0
- package/node_modules/grok-mermaid/dist/parse.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/parse.js +1151 -0
- package/node_modules/grok-mermaid/dist/parse.js.map +1 -0
- package/node_modules/grok-mermaid/dist/source-box.d.ts +18 -0
- package/node_modules/grok-mermaid/dist/source-box.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/source-box.js +78 -0
- package/node_modules/grok-mermaid/dist/source-box.js.map +1 -0
- package/node_modules/grok-mermaid/dist/types.d.ts +42 -0
- package/node_modules/grok-mermaid/dist/types.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/types.js +1 -0
- package/node_modules/grok-mermaid/dist/types.js.map +1 -0
- package/node_modules/grok-mermaid/dist/width-data.d.ts +2 -0
- package/node_modules/grok-mermaid/dist/width-data.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/width-data.js +994 -0
- package/node_modules/grok-mermaid/dist/width-data.js.map +1 -0
- package/node_modules/grok-mermaid/dist/width.d.ts +18 -0
- package/node_modules/grok-mermaid/dist/width.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/width.js +76 -0
- package/node_modules/grok-mermaid/dist/width.js.map +1 -0
- package/node_modules/grok-mermaid/package.json +49 -0
- package/node_modules/grok-mermaid/src/ansi.ts +34 -0
- package/node_modules/grok-mermaid/src/canvas.ts +373 -0
- package/node_modules/grok-mermaid/src/graph.ts +142 -0
- package/node_modules/grok-mermaid/src/index.ts +104 -0
- package/node_modules/grok-mermaid/src/labels.ts +326 -0
- package/node_modules/grok-mermaid/src/layout-seq.ts +203 -0
- package/node_modules/grok-mermaid/src/layout.ts +1015 -0
- package/node_modules/grok-mermaid/src/parse.ts +1189 -0
- package/node_modules/grok-mermaid/src/source-box.ts +89 -0
- package/node_modules/grok-mermaid/src/types.ts +43 -0
- package/node_modules/grok-mermaid/src/width-data.ts +993 -0
- package/node_modules/grok-mermaid/src/width.ts +74 -0
- package/node_modules/pi-lens/CHANGELOG.md +239 -0
- package/node_modules/pi-lens/config/dependency-cruiser-eager-allowlist.json +3 -0
- package/node_modules/pi-lens/dist/clients/actionable-warnings.js +30 -4
- package/node_modules/pi-lens/dist/clients/agent-behavior-client.js +2 -0
- package/node_modules/pi-lens/dist/clients/bash-file-access.js +26 -0
- package/node_modules/pi-lens/dist/clients/biome-client.js +1 -1
- package/node_modules/pi-lens/dist/clients/blocker-freshness.js +403 -35
- package/node_modules/pi-lens/dist/clients/bootstrap.js +6 -1
- package/node_modules/pi-lens/dist/clients/cascade-format.js +200 -4
- package/node_modules/pi-lens/dist/clients/code-quality-warnings.js +10 -2
- package/node_modules/pi-lens/dist/clients/degradation-ledger.js +16 -1
- package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +12 -1
- package/node_modules/pi-lens/dist/clients/dispatch/ast-grep-catalog.js +65 -0
- package/node_modules/pi-lens/dist/clients/dispatch/auxiliary-lsp.js +28 -0
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +9 -2
- package/node_modules/pi-lens/dist/clients/dispatch/finding-policy.js +222 -0
- package/node_modules/pi-lens/dist/clients/dispatch/indent-detect.js +389 -13
- package/node_modules/pi-lens/dist/clients/dispatch/integration.js +175 -25
- package/node_modules/pi-lens/dist/clients/dispatch/rule-ignores.js +62 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +21 -41
- package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +6 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +7 -7
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shfmt.js +2 -12
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tree-sitter.js +2 -21
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/types.js +4 -1
- package/node_modules/pi-lens/dist/clients/disposition-publish.js +1 -0
- package/node_modules/pi-lens/dist/clients/effective-config.js +1 -1
- package/node_modules/pi-lens/dist/clients/file-kinds.js +26 -1
- package/node_modules/pi-lens/dist/clients/file-role.js +21 -21
- package/node_modules/pi-lens/dist/clients/file-utils.js +156 -10
- package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +56 -9
- package/node_modules/pi-lens/dist/clients/format-service.js +39 -21
- package/node_modules/pi-lens/dist/clients/formatters.js +60 -13
- package/node_modules/pi-lens/dist/clients/generation-guard.js +2 -2
- package/node_modules/pi-lens/dist/clients/git-guard.js +11 -3
- package/node_modules/pi-lens/dist/clients/indent-retarget.js +78 -8
- package/node_modules/pi-lens/dist/clients/installer/index.js +333 -114
- package/node_modules/pi-lens/dist/clients/instance-reaper-state.js +7 -0
- package/node_modules/pi-lens/dist/clients/instance-reaper.js +20 -10
- package/node_modules/pi-lens/dist/clients/language-profile.js +23 -1
- package/node_modules/pi-lens/dist/clients/language-registry.js +5 -1
- package/node_modules/pi-lens/dist/clients/latency-logger.js +4 -1
- package/node_modules/pi-lens/dist/clients/lens-engine.js +12 -3
- package/node_modules/pi-lens/dist/clients/lens-events.js +2 -1
- package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +79 -0
- package/node_modules/pi-lens/dist/clients/live-bus-emitter.js +2 -1
- package/node_modules/pi-lens/dist/clients/lsp/client.js +25 -21
- package/node_modules/pi-lens/dist/clients/lsp/config.js +2 -2
- package/node_modules/pi-lens/dist/clients/lsp/index.js +7 -0
- package/node_modules/pi-lens/dist/clients/lsp/launch.js +16 -4
- package/node_modules/pi-lens/dist/clients/lsp/server.js +19 -2
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +2 -1
- package/node_modules/pi-lens/dist/clients/lsp-mutation.js +5 -3
- package/node_modules/pi-lens/dist/clients/map-with-concurrency.js +12 -8
- package/node_modules/pi-lens/dist/clients/mcp/session.js +36 -4
- package/node_modules/pi-lens/dist/clients/ndjson-logger.js +24 -7
- package/node_modules/pi-lens/dist/clients/observed-mutation.js +40 -2
- package/node_modules/pi-lens/dist/clients/opaque-mutation-scan.js +23 -3
- package/node_modules/pi-lens/dist/clients/opengrep-client.js +110 -15
- package/node_modules/pi-lens/dist/clients/path-utils.js +123 -3
- package/node_modules/pi-lens/dist/clients/performance-report.js +5 -1
- package/node_modules/pi-lens/dist/clients/php-cs-fixer-config.js +1 -1
- package/node_modules/pi-lens/dist/clients/pipeline.js +74 -5
- package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +37 -5
- package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +145 -18
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/dead-code.js +4 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +59 -3
- package/node_modules/pi-lens/dist/clients/project-lens-config.js +45 -2
- package/node_modules/pi-lens/dist/clients/read-guard.js +70 -11
- package/node_modules/pi-lens/dist/clients/resource-sampler.js +147 -9
- package/node_modules/pi-lens/dist/clients/ruff-client.js +1 -1
- package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +33 -5
- package/node_modules/pi-lens/dist/clients/runtime-context.js +6 -2
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +77 -7
- package/node_modules/pi-lens/dist/clients/runtime-session.js +21 -2
- package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +43 -12
- package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +330 -85
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +147 -17
- package/node_modules/pi-lens/dist/clients/safe-spawn.js +258 -5
- package/node_modules/pi-lens/dist/clients/scratch-tree-policy.js +6 -0
- package/node_modules/pi-lens/dist/clients/session-event-guard.js +50 -5
- package/node_modules/pi-lens/dist/clients/sg-runner.js +23 -11
- package/node_modules/pi-lens/dist/clients/sgconfig.js +79 -2
- package/node_modules/pi-lens/dist/clients/test-runner-client.js +6 -41
- package/node_modules/pi-lens/dist/clients/test-runner-delivery.js +43 -0
- package/node_modules/pi-lens/dist/clients/tool-agreement.js +423 -0
- package/node_modules/pi-lens/dist/clients/tool-config.js +50 -0
- package/node_modules/pi-lens/dist/clients/tool-cwd.js +47 -76
- package/node_modules/pi-lens/dist/clients/tool-policy.js +163 -7
- package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +120 -0
- package/node_modules/pi-lens/dist/clients/tree-sitter-query-loader.js +127 -189
- package/node_modules/pi-lens/dist/clients/widget-state.js +98 -0
- package/node_modules/pi-lens/dist/clients/word-index.js +5 -2
- package/node_modules/pi-lens/dist/clients/write-ordering-guard.js +7 -0
- package/node_modules/pi-lens/dist/index.js +27416 -24153
- package/node_modules/pi-lens/dist/mcp/server.js +5 -2
- package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +7 -1
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +168 -53
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +244 -72
- package/node_modules/pi-lens/docs/audit1.md +5 -5
- package/node_modules/pi-lens/docs/dependencies.md +11 -0
- package/node_modules/pi-lens/docs/dispositions.md +52 -0
- package/node_modules/pi-lens/docs/environment-variables.md +2 -2
- package/node_modules/pi-lens/docs/features.md +4 -4
- package/node_modules/pi-lens/docs/globalconfig.md +3 -1
- package/node_modules/pi-lens/docs/language-coverage.md +1 -0
- package/node_modules/pi-lens/docs/pi-lens-fixer.md +53 -94
- package/node_modules/pi-lens/docs/pi-lens-investigator.md +43 -38
- package/node_modules/pi-lens/docs/pi-lens-retro.md +97 -0
- package/node_modules/pi-lens/docs/pi-lens-reviewer.md +53 -66
- package/node_modules/pi-lens/docs/release-qa-baseline.md +22 -0
- package/node_modules/pi-lens/docs/settings.md +7 -4
- package/node_modules/pi-lens/docs/tree-sitter_rules_catalog.md +1 -1
- package/node_modules/pi-lens/docs/usage.md +2 -0
- package/node_modules/pi-lens/package.json +1 -1
- package/node_modules/pi-lens/rules/tree-sitter-queries/typescript/sql-injection.yml +24 -12
- package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +40 -0
- package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +15 -0
- package/node_modules/pi-lens/skills/pi-lens-lsp-navigation/SKILL.md +7 -0
- package/package.json +6 -11
- package/node_modules/@luxusai/pi-hindsight/CHANGELOG.md +0 -376
- package/node_modules/@luxusai/pi-hindsight/README.md +0 -92
- package/node_modules/@luxusai/pi-hindsight/docs/adr/001-memory-lifecycle-and-scope.md +0 -56
- package/node_modules/@luxusai/pi-hindsight/docs/adr/002-explicit-routing-strategy-seam.md +0 -169
- package/node_modules/@luxusai/pi-hindsight/docs/adr/003-tui-memory-mode-vocabulary.md +0 -107
- package/node_modules/@luxusai/pi-hindsight/docs/adr/004-lifeos-dual-bank-design.md +0 -89
- package/node_modules/@luxusai/pi-hindsight/docs/adr/005-domain-banks-and-agent-first-surface.md +0 -189
- package/node_modules/@luxusai/pi-hindsight/docs/assets/logos/pi-hindsight-logo-dark.webp +0 -0
- package/node_modules/@luxusai/pi-hindsight/docs/assets/logos/pi-hindsight-logo-dark@2x.webp +0 -0
- package/node_modules/@luxusai/pi-hindsight/docs/coding-memory-evaluation.md +0 -54
- package/node_modules/@luxusai/pi-hindsight/docs/compatibility.md +0 -75
- package/node_modules/@luxusai/pi-hindsight/docs/hindsight-core-functions.md +0 -300
- package/node_modules/@luxusai/pi-hindsight/docs/mission-and-mental-model-quality.md +0 -158
- package/node_modules/@luxusai/pi-hindsight/docs/next-opt-out-design.md +0 -164
- package/node_modules/@luxusai/pi-hindsight/docs/risky-memory-modes.md +0 -139
- package/node_modules/@luxusai/pi-hindsight/docs/starter-mental-model-suggestions.md +0 -74
- package/node_modules/@luxusai/pi-hindsight/docs/surface-reference.md +0 -261
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-operations.ts +0 -151
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-selection.ts +0 -18
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-settings-presenter.ts +0 -46
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-templates.ts +0 -383
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/banking.ts +0 -240
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/knowledge-page-seed.ts +0 -176
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/retain-strategies.ts +0 -178
- package/node_modules/@luxusai/pi-hindsight/extensions/client/client-retry.ts +0 -41
- package/node_modules/@luxusai/pi-hindsight/extensions/client/client.ts +0 -386
- package/node_modules/@luxusai/pi-hindsight/extensions/client/fetch-compat.ts +0 -39
- package/node_modules/@luxusai/pi-hindsight/extensions/client/timeout.ts +0 -34
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-defaults.ts +0 -140
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-editing-model.ts +0 -61
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-editing-registry.ts +0 -925
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-field-paths.ts +0 -247
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-normalize.ts +0 -547
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-writer.ts +0 -480
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config.ts +0 -182
- package/node_modules/@luxusai/pi-hindsight/extensions/config/setup-gate.ts +0 -86
- package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-execute.ts +0 -1010
- package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-parse.ts +0 -175
- package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-plan.ts +0 -425
- package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-presentation.ts +0 -210
- package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-sessions.ts +0 -817
- package/node_modules/@luxusai/pi-hindsight/extensions/index.ts +0 -25
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/git-seed.ts +0 -319
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle-recall.ts +0 -196
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle-retain.ts +0 -189
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle-runtime.ts +0 -65
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle.ts +0 -260
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/mental-models.ts +0 -244
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/observation-scopes.ts +0 -59
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/recall-cleanup.ts +0 -82
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/recall-visibility.ts +0 -45
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/recall.ts +0 -331
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain-cursor.ts +0 -354
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain-job-builder.ts +0 -66
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain-receipts.ts +0 -132
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain.ts +0 -228
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-bank-template-operations.ts +0 -74
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-config-operations.ts +0 -16
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-control-operations.ts +0 -648
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-diagnostics-operations.ts +0 -105
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-identity.ts +0 -68
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-operation-service.ts +0 -71
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-operation-types.ts +0 -13
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-recall-operations.ts +0 -162
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-retain-operations.ts +0 -131
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-scope.ts +0 -104
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-session-operations.ts +0 -37
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/operation-catalog.ts +0 -893
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/reflect-presenter.ts +0 -35
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/scope-migrate.ts +0 -177
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/tools.ts +0 -7
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/flush-presenter.ts +0 -21
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/jsonl-queue-store.ts +0 -112
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue-delivery.ts +0 -111
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue-lock.ts +0 -214
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue-operations.ts +0 -70
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue.ts +0 -392
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/bank-template-presentation.ts +0 -45
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/commands.ts +0 -9
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/guided-setup.ts +0 -860
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/prefill-input.ts +0 -105
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-flow.ts +0 -189
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-server-probe.ts +0 -299
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-actions.ts +0 -201
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-facts.ts +0 -47
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-render.ts +0 -239
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-types.ts +0 -50
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui.ts +0 -259
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/tool-presenters.ts +0 -77
- package/node_modules/@luxusai/pi-hindsight/extensions/types.ts +0 -534
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/diagnostics.ts +0 -319
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/messages.ts +0 -325
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/sanitize.ts +0 -42
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/session-memory-meta.ts +0 -244
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/session-operations.ts +0 -56
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/session.ts +0 -50
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/status-fields.ts +0 -167
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/status-health.ts +0 -207
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/status.ts +0 -120
- package/node_modules/@luxusai/pi-hindsight/extensions/version.ts +0 -8
- package/node_modules/@luxusai/pi-hindsight/package.json +0 -118
- package/node_modules/@luxusai/pi-hindsight/skills/hindsight-memory-doctor/SKILL.md +0 -75
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { WIDTHS } from './width-data.ts'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Display width, measured in grapheme clusters.
|
|
5
|
+
*
|
|
6
|
+
* A cluster is the unit both of measuring and of painting, so a box is always
|
|
7
|
+
* sized for exactly what gets drawn into it. Splitting those two — sizing by
|
|
8
|
+
* cluster but painting by code point — is what makes `👨👩👧` overflow its
|
|
9
|
+
* border in the Rust original.
|
|
10
|
+
*
|
|
11
|
+
* Clustering comes from `Intl.Segmenter` (UAX #29), which already handles ZWJ
|
|
12
|
+
* sequences, skin-tone modifiers, variation selectors, keycaps, flags and
|
|
13
|
+
* Hangul. Per-code-point widths are generated from the `unicode-width` crate.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const segmenter = new Intl.Segmenter('en', { granularity: 'grapheme' })
|
|
17
|
+
|
|
18
|
+
const VS16 = 0xfe0f
|
|
19
|
+
const isRegionalIndicator = (cp: number): boolean => cp >= 0x1f1e6 && cp <= 0x1f1ff
|
|
20
|
+
|
|
21
|
+
/** Width of one code point; the table covers the whole code point space. */
|
|
22
|
+
function codePointWidth(cp: number): number {
|
|
23
|
+
let lo = 0
|
|
24
|
+
let hi = WIDTHS.length - 1
|
|
25
|
+
while (lo <= hi) {
|
|
26
|
+
const mid = (lo + hi) >> 1
|
|
27
|
+
const run = WIDTHS[mid]
|
|
28
|
+
if (cp < run[0]) hi = mid - 1
|
|
29
|
+
else if (cp > run[1]) lo = mid + 1
|
|
30
|
+
else return run[2]
|
|
31
|
+
}
|
|
32
|
+
return 1
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Columns occupied by one grapheme cluster.
|
|
37
|
+
*
|
|
38
|
+
* The widest code point wins, so a base plus its combining marks measures as
|
|
39
|
+
* the base. Two adjustments: a variation selector requesting emoji
|
|
40
|
+
* presentation forces two columns, as does a regional indicator pair (a flag).
|
|
41
|
+
*
|
|
42
|
+
* Zero is a real answer — a soft hyphen or zero-width space occupies nothing,
|
|
43
|
+
* and callers skip painting such a cluster rather than reserving a cell.
|
|
44
|
+
*/
|
|
45
|
+
export function clusterWidth(cluster: string): number {
|
|
46
|
+
let w = 0
|
|
47
|
+
let vs16 = false
|
|
48
|
+
let regional = 0
|
|
49
|
+
for (const ch of cluster) {
|
|
50
|
+
const cp = ch.codePointAt(0) as number
|
|
51
|
+
if (cp === VS16) vs16 = true
|
|
52
|
+
if (isRegionalIndicator(cp)) regional++
|
|
53
|
+
const cw = codePointWidth(cp)
|
|
54
|
+
if (cw > w) w = cw
|
|
55
|
+
}
|
|
56
|
+
return vs16 || regional >= 2 ? 2 : w
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** Iterate grapheme clusters, so no loop can split one. */
|
|
60
|
+
export function* clusters(s: string): Generator<string> {
|
|
61
|
+
for (const { segment } of segmenter.segment(s)) yield segment
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Iterate clusters paired with their display width. */
|
|
65
|
+
export function* measured(s: string): Generator<[string, number]> {
|
|
66
|
+
for (const { segment } of segmenter.segment(s)) yield [segment, clusterWidth(segment)]
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Display columns of a string. */
|
|
70
|
+
export function stringWidth(s: string): number {
|
|
71
|
+
let w = 0
|
|
72
|
+
for (const { segment } of segmenter.segment(s)) w += clusterWidth(segment)
|
|
73
|
+
return w
|
|
74
|
+
}
|
|
@@ -16,6 +16,245 @@ All notable changes to pi-lens will be documented in this file.
|
|
|
16
16
|
|
|
17
17
|
### Security
|
|
18
18
|
|
|
19
|
+
## [4.2.0] - 2026-09-16
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
|
|
23
|
+
- **Add Typst language support (refs #3037)** — Tinymist provides LSP diagnostics and typstyle provides formatting for `.typ` and `.typc`, with managed GitHub-release installation for both tools.
|
|
24
|
+
|
|
25
|
+
- **Opt-in compact LSP status line (`ui.compactLspStatus`, `--lens-compact-lsp-status`) (refs #3099)** — the `pi-lens-lsp` footer status can now render one state glyph per group (`LSP ✓` green, `LSP ✗` red, dim `LSP ✗` when nothing is warm) instead of the active server names (#267). Default off: the published string is byte-identical when the flag is unset. Server ids stay reachable through `/lens-tools` and `lens_health`.
|
|
26
|
+
|
|
27
|
+
- **Opt-in off mode for the LSP status line (`ui.hideLspStatus`, `--lens-hide-lsp-status`) (closes #3099)** — the `pi-lens-lsp` footer status can now be suppressed entirely: `updateLspStatus` publishes `undefined` instead of any text, so a host that renders extension statuses stops showing the key at all. Outranks `ui.compactLspStatus` when both are set (nothing to render compactly once the key itself is gone). Default off: unset, the published string is unchanged. Server ids stay reachable through `/lens-tools` and `lens_health`.
|
|
28
|
+
|
|
29
|
+
- **Allow an explicit analysis root below the home ceiling (closes #2053)** — `lens_diagnostics mode=full` can run heavyweight analyzers for a named, existing project directory when the session cwd is `$HOME` or higher, while retaining the #749 refusal for unsafe roots.
|
|
30
|
+
|
|
31
|
+
- **Detect tests that drive the registry against the run-shared `PI_LENS_HOME` (refs #3042, #3050)** — `tests/clients/pi-lens-home-hermeticity.test.ts` now walks `clients/` for best-effort-locked `getGlobalPiLensDir()` writers and `tests/` for files that call one of their hazardous exports (or reach a producer's target file directly) without pinning their own home or mocking the writer away; it caught `tests/clients/instance-reaper-backstop.test.ts` racing the shared `orphan-backstop.json`/`.lock` on a stale per-worker-isolation assumption, fixed in the same change.
|
|
32
|
+
|
|
33
|
+
- **Opt Typst (tinymist) into the nightly LSP clean-gate (refs #3037, #3164)** — `tests/fixtures/tool-smoke/typst/main.typ` now carries a deliberate `#undefined_function(answer)` call and the `typst` `LSP_FIXTURES` entry in `scripts/smoke-tools.mjs` sets `lspGate: true` with `lspGateMarker: "#undefined_function"`, following the typescript entry's shape; `--lsp-gate typst` now proves tinymist surfaces a real primary diagnostic instead of only handshaking, and `tests/scripts/smoke-tools-lsp-gate-fixtures.test.ts` was updated for the seven-fixture gated population.
|
|
34
|
+
|
|
35
|
+
### Changed
|
|
36
|
+
|
|
37
|
+
- **Auto-rerun the second infra kill on one head, and sweep master-only workflow lanes (refs #2042, #3043)** — the infra-kill rerun lane now classifies attempts 1 and 2 (`run_attempt <= 2`) and keys its once-per-head rerun guard on sha *and* run attempt with a two-rerun cap, so a runner that 137-kills the same head twice no longer needs a hand-pressed attempt 3; `finalize-rerun` moves to the terminal attempt. A new registered-or-fail sweep over every `.github/workflows/*.yml` fails any job whose `if:` no pull_request context can satisfy unless it is registered with a reason, and `install-smoke`'s `smoke` and `mise-repro` each gain one pull_request cell instead of their master-only gate.
|
|
38
|
+
|
|
39
|
+
- **Record per-cgroup memory/PID/PSI samples and a 200ms watch cadence in CI (refs #2042)** — the Unit-tests job now writes a bounded on-disk tail of `memory.current`/`memory.peak`/`pids.current` and PSI stall totals every 200ms, read back by an `if: always()` step so a killed run still yields its last ~60s of samples; the `Runner capacity` step now resolves its own cgroup for `memory.max` instead of the unpopulated root.
|
|
40
|
+
|
|
41
|
+
- **Clarify merge-time defect-shape catalog allocation and add two contract screens (refs #2996)** — Keep concurrent documentation lanes from creating invalid numbered-list gaps, and record retry-list and fallback-direction failure shapes for future reviews.
|
|
42
|
+
|
|
43
|
+
- **Merge-train and reviewer contracts gain five rules from the 2026-09-12 train (refs #2996)** — catalog numbers are reserved at dispatch instead of discovered at write time; `action_required` on a fork PR is distinguished from an absent check; advisory rows are read before merge even though they never gate; a verify probes the inverted direction whenever a round retunes a threshold or tier; and a clean local run is recorded as "did not reproduce", not "fixed", when a deferred producer or another worker is involved.
|
|
44
|
+
|
|
45
|
+
- **External reports are assessed against the code and their load-bearing questions answered before dispatch (refs #3001)** — AGENTS.md's issue-triage rule now requires verifying a report's claims in the source, asking the facts that would change the design, not dispatching work that depends on an unanswered one, mirroring the answer on the issue so a worker can verify it, and citing the reporter's reasoning as authority rather than paraphrasing it.
|
|
46
|
+
|
|
47
|
+
- **Deny `TMPDIR=.probe-home` in the Bash guard hook and forbid raw commit-ish Git spawns under `tests/` (refs #3026, #3050)** — `scripts/hooks/guard-bash.mjs` gains a fifth deny rule (`tmpdirCollision`) that rejects a `TMPDIR`/`TMP`/`TEMP` assignment aimed at the vitest harness's own `PI_LENS_HOME`, the mistake that produced a false "16 suites red on origin/master" report; `tests/config/git-fixture-governance.test.ts` gains a row that fails any `tests/` Git spawn naming a commit from this repository's history, which CI's depth-1 checkout cannot reach.
|
|
48
|
+
|
|
49
|
+
- **Skip unchanged PR-body lint on synchronize (refs #3030)** — the advisory PR-body validator now runs on body-relevant pull-request events instead of every source-code update.
|
|
50
|
+
|
|
51
|
+
- **Fold the ast-grep catalog source-walk onto one effective-catalog helper (refs #3053)** — The NAPI runner and the LSP-seam rule-ignore matcher now both read `buildEffectiveAstGrepCatalog`, replacing two independent copies of the same source-walk and precedence resolution that had already drifted once (#3046).
|
|
52
|
+
|
|
53
|
+
- **Fold the tree-sitter query loader onto `js-yaml` (refs #3054)** — replace the hand-rolled line-regex YAML scanner in `clients/tree-sitter-query-loader.ts` with `yaml.load`, the same real parser `clients/dispatch/runners/yaml-rule-parser.ts` already uses for ast-grep rules, removing the duplicated inline-array/multi-line-list/nested-object branches that caused #3046's `ignore_paths` quoting bug.
|
|
54
|
+
|
|
55
|
+
- **Cut the two heaviest test files' peak memory by 8.4 GB and gate the budget (refs #3058)** — `bounded-container-guard` re-parsed and re-walked each source up to six times per container occurrence (9,207 → 812 MB peak RSS) and the `vi.mock` export detector re-parsed production modules once per call site (5,646 → 1,800 MB); the `[mem-file]` hook now fails any file that exceeds `WORKER_PEAK_RSS_BUDGET_MB` without a measured admission.
|
|
56
|
+
|
|
57
|
+
- **Enforce the DegradationKind union against every emitted kind (refs #3071)** — a new governance sweep (`tests/config/degradation-kind-coverage.test.ts`) scans every `recordDegradationOnce` / `incrementDegradationCount` / `logDurableDegradation` call site for its `kind:` literal and fails if it is not a declared `DegradationKind` union member; `clients/degradation-ledger.ts` now declares the 15 kinds that were emitted in production without a union member (`actionable-warnings-cap`, `gitleaks_classification_timeout`, `gradle-ktlint-scan-budget-exceeded`, `instance-registry-identity-fallback`, `instance-registry-lock-timeout`, `instance-registry-registration-missing`, `lsp-document-drift`, `lsp-probe-finding-policy`, `managed-tool-install`, `pipeline-post-write-hash-unavailable`, `review-graph-memory-cap`, `review-graph-memory-cap-floor`, `sgconfig-baseline-cap-evict`, `test-runner-batch-capped`, `tree-sitter-query-parse-failed`).
|
|
58
|
+
|
|
59
|
+
- **Bound the Unit tests job with `timeout-minutes` (refs #3111)** — `test` (Unit tests) in `.github/workflows/ci.yml` carried no `timeout-minutes`, so a reader that is alive but never drains (e.g. an unbounded stdout stall in the mem-watch wrapper, #3106) could hold the runner for GitHub's 360-minute default; the job now caps at 26 minutes, sized at 2x the measured longest Unit run (12m42s) across 9 successful master runs.
|
|
60
|
+
|
|
61
|
+
- **Bound every remaining workflow job with a measured `timeout-minutes` (refs #3111, closes #3123)** — the ~50 jobs across 18 workflow files left unbounded by #3111's `test` (Unit tests) fix now each carry a `timeout-minutes` sized from the job's own measured history (last 10 successful runs, `~2x max + margin`, floored at 10 minutes), so a stalled-but-alive job can no longer hold a runner for GitHub's 360-minute default; a job with no successful run in the search window (a `pull_request`/`repository_dispatch`-gated job that the master-branch sample structurally excludes, or one that has never once succeeded) gets a stated default with the reason recorded in a YAML comment above the line.
|
|
62
|
+
|
|
63
|
+
- **Close two gaps in the DegradationKind coverage sweep (refs #3071, #3138, closes #3140)** — `clients/degradation-ledger.ts` now declares `process-singleton-reset` (live at `getDegradationSummary()`'s read-time fold since #2146, previously undeclared); `tests/config/degradation-kind-coverage.test.ts` now also walks that same read-time fold's own `summary.push({ kind: ... })` emitters in `degradation-ledger.ts`, and resolves a bare-identifier `kind:` value (`TRUST_REFUSAL_KIND` at `clients/config-core/process-spec.ts`) against a same-file `const` binding rather than silently returning `[]` — an identifier the scan still cannot resolve now fails loud as `"<file>:<line> kind: <identifier> is unresolvable"` unless the site is named in the new `AUDITED_IDENTIFIER_KIND_SITES` list.
|
|
64
|
+
|
|
65
|
+
- **Check PR-body claims with Markdown-aware sentence units (refs #2904)** — Block-level Markdown and bounded source evidence keep citations and master-red claims tied to the text they describe.
|
|
66
|
+
|
|
67
|
+
- **Verify PR-body code citations (refs #2904)** — Check cited source lines, offered evidence, lexer-derived test identifiers, and master-red transcripts against the head tree. Reject backwards citation ranges before source resolution, keep valid-table master claims outside transcript checks, shield regex literals at every expression-start boundary, reuse only immutable HEAD-tree corpora within a bounded cache, and rebuild working-tree corpora so mutable trees cannot launder removed or fabricated titles.
|
|
68
|
+
|
|
69
|
+
- **Recognise PR test references by shape and placement (refs #2904)** — Test IDs, test paths, citations, and titles are checked only where their Markdown placement identifies them as test evidence. Malformed pipe blocks remain visible Markdown, while valid tables retain column-specific filtering. Local body lint tolerates shallow or single-commit histories by requiring Test assessment when changed-file scope is unavailable.
|
|
70
|
+
|
|
71
|
+
- **Keep PR-body fixture setup in process (refs #3016)** — short-ID coverage uses the existing Git callback seam without adding real child processes to the checker test.
|
|
72
|
+
|
|
73
|
+
- **Contracts from the 2026-09-10 merge train.** AGENTS.md catalog shapes 46 (a parser fed by a double whose shape the tool never emits), 47 (a detector whose corpus includes its own fixtures), 48 (check-then-act on a shared durable directory) and test screen 13 (a detector pinned only in the accept direction); the fixer contract adds "authority words are claims", "facts about master come from a fetched origin/master", "never assert CI", "a detector test has two directions", "tool output is a fixture, not a guess"; the merge-train skill adds five mistake rows (design question left to the fixer; guessed branch names; the ignored-path exclude in `git add`; `ci-verdict` exit 70 on API outages; a registry-membership guard changing other lanes' requirements). (refs #2900, #2913, #2921, #2924, #2929, #2930)
|
|
74
|
+
|
|
75
|
+
- **Retro 2026-09-15 outputs**: eleven mistake rows in the merge-train skill, a reviewer rule for net-count folds, a routing rule for governance-sweep briefs, and five steering lines deleted from the role contracts and `AGENTS.md` because they had an occasion this session and changed no decision (record in `HISTORY.md`).
|
|
76
|
+
|
|
77
|
+
- **Retrospective contract**: `docs/pi-lens-retro.md` and the `retro` skill turn a session, an incident, or a merged bug fix into environment changes — checks with a red transcript for mechanical mistakes, one contract line for judgement calls, deletion for steering lines that changed no decision — and `AGENTS.md` names the triggers.
|
|
78
|
+
|
|
79
|
+
- **Keep incomplete observation evidence separate from mutation attribution (refs #2984)** — hashless observational captures, including size-only changes, remain visible as unverifiable and never enter mutation replay, attribution, or the clean-observation latch.
|
|
80
|
+
|
|
81
|
+
- Pin the availability gate's three known text-anchoring blind spots.
|
|
82
|
+
|
|
83
|
+
### Removed
|
|
84
|
+
|
|
85
|
+
- **`decideClassifierAction` in `ci-failure-classifier.mjs` (refs #3086)** — a pure duplicate of `runClassifier`'s carry-forward rule (rerun eligibility, `rerunState`, which run attempt a carried-forward marker belongs to) with no production caller; #3079 had needed a twin test case to keep both writers honest after a mutation on `runClassifier`'s copy alone stayed green. `runClassifier` is now the sole writer of the rule, and its existing test covers the mutation on its own.
|
|
86
|
+
|
|
87
|
+
### Fixed
|
|
88
|
+
|
|
89
|
+
- **Never signal a pid pi-lens does not own (refs #2042)** — `safeSpawnAsync` verified nothing before putting a child's pid into the process-wide lifetime registry, so a `node:child_process` test double's invented pid (`2468`) was registered, never removed, and SIGKILLed at host exit; on ~10 % of CI runners that pid belonged to the job itself, which is where the unexplained exit-137 "infra kills" came from. One ownership predicate (`isOwnLiveChild`) now gates registration, the timeout process-group kill, and the LSP POSIX/Windows tree kills — folding away three sibling sign/exited guards — reading `/proc/<pid>/status` on Linux and requiring `PPid` to be this process; a live pid under another parent is refused and recorded once per call site in the degradation ledger.
|
|
90
|
+
|
|
91
|
+
- **Bind cached project findings to the bytes they were scanned from (refs #2154)** — a cheap-tier finding whose file changed while the scan was running used to be served as a current blocking error in every later session; rows now carry the size and hash of the content the rules read, so a second session sees the finding retired instead.
|
|
92
|
+
|
|
93
|
+
- **Keep advisory tool names host-aware (refs #2535)** — Agent-facing diagnostics and guidance use callable pi or MCP tool names, including generated-skip and quick-mode notices.
|
|
94
|
+
|
|
95
|
+
- **Add explicit fake LSP pull/push ordering controls (refs #2824)** — LSP tests can drive push ordering, document versions, pull outcomes, and completion through the real fixture wire.
|
|
96
|
+
|
|
97
|
+
- **Scope project-diagnostics runner retirement by analyzed file coverage (refs #2887)** — opengrep findings retire only when the retained file appears in its reported `paths.scanned` set; other runners keep the conservative runner-id fallback.
|
|
98
|
+
|
|
99
|
+
- **Isolate registry consumers and restore probe-home state (refs #2912)** — prevent later tests from inheriting the #2992 probe registry and keep PID-scoped root assertions independent of worker history.
|
|
100
|
+
|
|
101
|
+
- **Drain and track lens-map fixtures (refs #2912)** — route lens-map temporary roots through the shared environment registry so deferred graph writes cannot recreate an untracked `/tmp` root after teardown.
|
|
102
|
+
|
|
103
|
+
- **Handle PEP 668 pip hosts (closes #2916)** — pip-backed tools use pipx, a pi-lens-owned venv, or a private user base before falling back to a normal user install.
|
|
104
|
+
|
|
105
|
+
- **Complete slice-2 session guard cleanup (refs #2939)** — tool-result edit classification uses one predicate, and stale-handler crash forwarding no longer carries dead options.
|
|
106
|
+
|
|
107
|
+
- **Guard long-lived containers against unbounded growth (refs #2981, refs #2988)** — add an AST-backed registered-or-fail inventory with nested-root coverage, content-keyed exemptions, and honest key-axis classification.
|
|
108
|
+
|
|
109
|
+
- **Keep bridge bookkeeping alive across session transitions (closes #2992)** — stale extension contexts no longer make read or mutation bridge flag checks throw or drop their records.
|
|
110
|
+
|
|
111
|
+
- **Discover monorepo-root ESLint and Oxlint configs across nested `package.json` boundaries (refs #3017)** — flat `eslint.config.{js,mjs,cjs,ts,mts,cts}` files and Oxlint configs now resolve from every ancestor directory like the tools themselves, so the jsts lint lane defers Biome with the machine-readable `configured-non-biome-linter` skip reason instead of running the smart default; legacy `.eslintrc.*` and `package.json#eslintConfig` keep per-package semantics.
|
|
112
|
+
|
|
113
|
+
- **Install managed archive tools with format-aware extraction (refs #3020)** — ZIP-based clangd and PowerShell bundles, plus platform-varying Lua archives, now use the matching extractor while failed replacements preserve the installed tree.
|
|
114
|
+
|
|
115
|
+
- **Make the formatter's no-config indentation fallback stable (refs #3038)** — infer the unit from structural lines only (block-comment interiors are alignment, not nesting), decline ambiguous nested-only evidence, and honor ancestor `.editorconfig` files, so repeated formatting neither amplifies nor shrinks a file's indentation.
|
|
116
|
+
|
|
117
|
+
- **Honor a rule's own `ignores` paths over LSP (refs #3041)** — `lens_diagnostics` with `source: "lsp"` or `mode: "full"` no longer re-surfaces ast-grep findings on paths the rule's own YAML carves out, and a stored disposition now matches an auxiliary finding in `mode: "full"`.
|
|
118
|
+
|
|
119
|
+
- Fixed `tests/index-vanished-instance-wiring.test.ts` reddening in the CI Unit
|
|
120
|
+
lane on unrelated pull-request heads. The test drove the run-shared
|
|
121
|
+
`PI_LENS_HOME` registry, so the reaper's best-effort prune had to win a 500 ms
|
|
122
|
+
`withInstanceRegistryLock` deadline against every other concurrently running
|
|
123
|
+
test file; losing it is silent, left the seeded dead-pid entry in place, and
|
|
124
|
+
leaked it into the next case. Each case now runs against its own
|
|
125
|
+
`PI_LENS_HOME` (refs #3042).
|
|
126
|
+
|
|
127
|
+
- **Stop indent-retarget from basing deeper nesting on a block comment's alignment (closes #3052)** — the edit-tool indentation-mismatch autopatch no longer picks its extrapolation base unit from a JSDoc/block-comment continuation line; it now excludes comment interiors from that pick with the same lexer `indent-detect.ts` uses (#3039), so a comment's alignment ratio can no longer silently mis-scale a deeper-nested replacement. A comment-interior indent still resolves by direct lookup when a replacement reintroduces it.
|
|
128
|
+
|
|
129
|
+
- **Exclude template-literal interiors from the formatter's indentation fallback (closes #3059)** — a multi-line template literal's interior lines (a help-text string, say) were still counted as indentation evidence after #3039 excluded block-comment interiors for the same alignment-not-nesting shape, so a 4-space file whose template literal happened to be 2-space indented got re-indented to 2 on its first format. `indent-detect.ts` now excludes template interiors with the same lexical discipline as the block-comment rule, tracking `${ … }` nesting and escaped backticks so neither closes the tracked template early.
|
|
130
|
+
|
|
131
|
+
- **Re-arm the tree-sitter query parse-failure record every session (refs #3070)** — `TreeSitterQueryLoader.loadQueries` short-circuited on its `loaded`/`loadedRoot` memo before re-parsing, so a broken custom rule's `tree-sitter-query-parse-failed` degradation record only ever reached the first session that parsed it; the shared loader instance is deliberately kept across sessions, so every later session's `resetDegradationLedger()` silently dropped the row to zero. Per-file parse failures are now remembered and replayed once per ledger generation on a memoized reload, and cleared whenever a rule is actually re-parsed so a fix on disk stops replaying a stale failure. Also adds regression coverage for the existing `str()` guard against a mapping-valued `message` field, which had none.
|
|
132
|
+
|
|
133
|
+
- **Governance sweeps no longer race a scratch test file written into `tests/` (closes #3082, closes #3092)** — the `#3050` registry-isolation detector's red-first proof wrote a real `tests/scratch-3050-pre-3048-vanished-wiring.test.ts` into the repo's own test tree for the length of one assertion, so any sibling sweep that was mid-enumeration died with `ENOENT` on a file that exists on no branch (`sweep-floor-coverage`, `vacuous-skip-coverage`, `latency-logger-mock-shape` and `lsp-spawn-heavy-coverage` took the hit on rotating runs). The proof now walks a private `mkdtemp` root through the same walker and options; every walk-then-read over the `tests/` tree goes through sweep-kit's new `readWalkedFile`, which drops a path that vanished between the walk and the read, records it once, and never counts it as a finding; and a recursive-watch guard installed from `globalSetup` (once per activated Vitest project, not per test-file fork) fails the run, naming the path, if any test creates a source file inside `tests/` again.
|
|
134
|
+
|
|
135
|
+
- **Isolate test orphan-backstop state (refs #3083)** — pin the backstop lock and cooldown stamp once in the test harness so real session-start timers cannot contaminate the run-shared home, while preserving explicit test homes and production machine-wide coordination.
|
|
136
|
+
|
|
137
|
+
- **`lens_diagnostics source=lsp` honors your marks, rule policy and inline ignores (closes #3088, closes #3041, refs #3047)** — the probe lane behind `source: "lsp"`, the legacy `lsp_diagnostics` tool and the MCP `pilens_lsp_diagnostics` shim returned raw LSP findings with no stored-disposition filter, no `.pi-lens.json` `rules.<id>.disable`/`select` policy and no inline `pi-lens-ignore` suppression, while `mode=delta` and `mode=full` applied all three — so a finding an agent marked `false-positive` was hidden everywhere except the lane `skills/pi-lens-lsp-navigation` steers agents to as PRIMARY, and the probe's footer reconcile then overwrote the mark-time demotion on every check. `mode=full`'s three open-coded filter calls are folded onto one shared `clients/dispatch/finding-policy.ts` stack that the probe lane now calls once per file, for the rendered text, the counts and the widget footer alike. A mark converges whichever surface it was made from (the probe renders `[source] (code)` where the footer renders the canonical `tool`/`rule`), a `blocking` finding still drops only on a strict content-bound match, cache replays filter exactly like fresh probes, and every drop is stated as a `suppressed by disposition: N` count instead of reading as clean.
|
|
138
|
+
|
|
139
|
+
- **Drain stdin to EOF in the guard-bash PreToolUse hook instead of a single `readFileSync(0)` (#3089)** — `spawnSync`'s own `input` pump sets the child's stdin pipe non-blocking, so a `read(2)` issued before the next chunk lands can throw `EAGAIN`; `readFileSync(0, "utf8")` does not retry that, the throw was swallowed as "no payload", and the hook failed OPEN (exit 0) on a command — like `git stash` — it would otherwise have denied, measured reproducible from ~500 KB of JSON payload. `readStdin` now loops `fs.readSync` into a buffer list, retrying `EAGAIN` with an `Atomics.wait` park (the same mechanism `scripts/with-memory-watch.mjs` uses on its write side) and stopping only on a true EOF (`bytesRead === 0`); a read error or a genuinely empty stream is still "no payload".
|
|
140
|
+
|
|
141
|
+
- **`with-memory-watch` survives a full stdout pipe instead of dying on it (closes #3097)** — the wrapper writes every record with `fs.writeSync` so `process.exit` cannot discard it, but fd 1 is not reliably blocking: `stdio: "inherit"` shares one open file description with the wrapped command, and libuv sets `O_NONBLOCK` on it as soon as that child initialises its own `process.stdout` on a pipe. A sampler tick that landed while a slow log reader held the 64 KB pipe full then threw `EAGAIN` out of the `setInterval` callback with nothing to catch it, and the wrapper exited 1 under exactly the backpressure it exists to survive (CI run 35067086859). `emit` now retries on `EAGAIN`, parking 5 ms per attempt, which is what a blocking write would have done; any other write error is permanent, so it is recorded once on stderr and the child's exit code is still forwarded.
|
|
142
|
+
|
|
143
|
+
- **A mis-cased path and a normalized read now share one anchor on POSIX (refs #3098, refs #3090)** — `normalizeFilePath` canonicalized casing only on Windows, so on a case-insensitive POSIX filesystem (macOS APFS, `nocase` vfat/ntfs3/cifs) a raw mis-cased `lens_diagnostic_mark` write and the dispatcher's `normalizeMapKey` read derived two anchors for one file and the agent's own false-positive/flagged mark silently never applied — the #1024 defect, live on every macOS install. The POSIX arm now adopts the on-disk casing `realpath(3)` reports for the trailing segments of an existing path, stopping at the first segment that differs by more than case, so casing is fixed while a symlinked prefix (macOS's `/var/folders` tmpdir, a symlinked monorepo package) is still never resolved; a path that does not exist stays case-preserving, because on a case-sensitive filesystem `SUB/a.ts` and `sub/a.ts` are two different files. A rewrite is adopted only once the filesystem confirms it still names the file the caller held, so a symlink whose name is a case variant of its target's (`node_modules/Foo` → `../pkgs/foo`) keeps its own spelling rather than keying under a sibling — or under nothing. The #1024 regression test now runs unskipped on the Linux CI lane instead of skipping there and failing on macOS.
|
|
144
|
+
|
|
145
|
+
- **The turn-end late-auxiliary advisory and the cold-neighbour cascade run honor a disposition mark (#3102)** — both rendered LSP findings straight to the agent with no stored-disposition filter, no `.pi-lens.json` `rules.<id>.disable`/`select` policy and no inline `pi-lens-ignore`, so a finding marked `false-positive` came back on every turn that drained a late auxiliary pair and on every quiet-window cascade reconcile. Both now take the same `clients/dispatch/finding-policy.ts` stack the per-edit dispatcher, `mode=full` and the `source=lsp` probe lane apply, after their own freshness gate and over the canonical identity (`convertLspDiagnostics` + `retagAuxiliaryDiagnostics`) every other surface anchors a mark against — so an auxiliary finding is filtered under its real tool id instead of a hardcoded `lsp`, and its own native `# nosemgrep`-style suppression is honored here too. Each lane reads the cited file once per delivery, only when there is something to render; an unreadable file degrades to the content-free half rather than hiding a finding. Drops are counted in the `late_auxiliary_findings` and `cascade_finding_policy` latency records, and a delivery that still has findings states `suppressed by disposition: N finding(s)`.
|
|
146
|
+
|
|
147
|
+
- **Vanished-file diagnostic reaches the run log on a passing suite (refs #3107)** — `tests/support/sweep-kit.ts`'s `readWalkedFile` and its `scripts/lib/win32-gate-population.mjs` twin recorded a walked file that vanished between list and read with `console.warn`, but Vitest's default reporter (every `npm test` script uses it) intercepts and can drop a worker's `console.warn` on a green run, so the record never actually reached CI's job log despite the docstring's claim that it does. Both sites now emit through a raw `process.stderr.write`, matching the same interception fix already documented at `tests/support/vitest-setup.ts`'s peak-RSS reporting. The `.mjs` twin's hand-rolled `Set` with `clear()`-on-overflow eviction — which its own parity comment falsely claimed was "identical" to the TypeScript seam — now shares the TypeScript seam's `BoundedSet` (oldest-first eviction), making the claim true.
|
|
148
|
+
|
|
149
|
+
- **Reclaim stale `tmp-hygiene-baseline-<run>.json` files on the existing backstop stale arm (refs #3109, #2912, #3100)** — the #2912 hygiene owner writes one baseline record per run and only ever removed the one it wrote itself, so every owner-less (targeted) run in a persistent dev-box checkout left its own file behind for ever; `removeRunBackstopDirs` now reclaims a `tmp-hygiene-baseline-*` file older than the same six-hour `BACKSTOP_STALE_MS` window it already used for abandoned backstop directories and root-level `orphan-backstop*` residue, leaving the active run's own file untouched until the owner consumes it.
|
|
150
|
+
|
|
151
|
+
- **Retry the mem-watch write-failure note through the same channel that retries every other line, with a bound of its own (closes #3110, closes #3115)** — `noteWriteFailureOnce` used to write its once-only stderr note with a raw, un-retried `fs.writeSync` in a bare catch, so a stdout that had died (EPIPE) alongside a stderr that was merely full (EAGAIN, a slow reader) dropped the note for good; it now goes through the wrapper's own retrying `emit()`, capped at 400ms for the note only (the verdict line keeps its unbounded retry) so a stderr that never drains at all degrades the note instead of hanging the wrapper and losing the wrapped command's exit code, when the wrapped command outlives the retry window (a command that exits inside it still blocks on the inherited fd; see #3141). `tests/scripts/with-memory-watch.test.ts`'s `runWrapper` helper also pins `PI_LENS_MEM_WATCH_SAMPLE_FILE` to a scratch path by default, so the file's cases stop leaking the wrapper's shared `pi-lens-mem-watch-samples.log` fallback into TMPDIR and redding `tmp-fixture-hygiene` in a shared batch.
|
|
152
|
+
|
|
153
|
+
- **Nested agent-data trees no longer cost a project its startup scan, and a project-scope `tools.<name>.enabled` is no longer called invalid (fixes #3112)** — `.omp` (the same coding agent's rebranded config directory: pi derives its config-dir name as `pkg.piConfig?.configDir || ".pi"`, so `.omp/agent/sessions` is the history `.pi/agent/sessions` holds) joins the shared scan-exclusion list, so a project-local session history is no longer walked entry-by-entry against the startup entry budget — a small source tree beside one came back `too-many-entries` and never warmed its caches. Excluding it by NAME during recursion leaves a `.omp` directory chosen as the workspace root scanned as usual, and an ordinary oversized tree keeps its `too-many-entries`/`too-many-source-files` verdict. Separately, the project-config loader derived its accepted top-level keys from the flag registry alone, so the documented project-scope `tools.<name>.enabled` override was announced as `"tools" is a global-only pi-lens setting … ignored` (`PILENS_CFG_0001`) on every load; `tools` is now a recognized project section, and the one genuinely global key under it (`tools.lazy`, `--no-lazy-tools`) is still reported at project scope by a registry-derived mixed-scope sub-key scan rather than being dropped in silence.
|
|
154
|
+
|
|
155
|
+
- **Stop indent-retarget from basing deeper nesting on a template literal's alignment (closes #3116)** — the edit-tool indentation-mismatch autopatch no longer picks its extrapolation base unit from a multi-line template literal's interior line; it now excludes template interiors from that pick with the same lexer `indent-detect.ts` uses (#3059), so a template literal's own alignment ratio can no longer silently mis-scale a deeper-nested replacement, the same way #3052 fixed the analogous block-comment case. A template-interior indent still resolves by direct lookup when a replacement reintroduces it.
|
|
156
|
+
|
|
157
|
+
- **Recognise regex literals in the indentation template-lexer's conservative state (refs #3120)** — `advanceTemplateState` had no notion of a regex literal, so a backtick inside one (`` /`/ ``) opened a phantom template frame and a `/*` inside one (`` /[/*]/ ``) pushed a phantom block frame that never finds its closing `*/`; both silently disabled template-interior masking for the rest of the file. `/` is now recognised as a regex opener only in unambiguous grammar positions (after `(`, `,`, `=`, `:`, `[`, `!`, `&`, `|`, `?`, a `return`/`typeof`/`case` keyword, or line start — `{`, `}`, `;` were tried and dropped as vacuous, `}` additionally grammatically unsound) and skipped whole to a closing `/` that is itself followed by an unescaped `` ` ``-honouring, `[...]`-honouring scan and then zero or more regex flag letters and a non-identifier terminator — division stays division everywhere else, unchanged from before. A 25,553-file corpus re-run (own tree plus `node_modules`, every extension biome/prettier/ruff/shfmt format) shows zero files newly declined and no new `width 1` verdicts; the `decline` count falls from 7 to 4 and 9 files change verdict overall — 8 of those lose all surviving indentation evidence to now-correctly-recognised regex/template spans and fall through to the existing hardcoded default, and one in-tree file (`clients/ast-grep-client.ts`) is a genuine correction from a stray-regex-corrupted `space/2` to its real `space/4`.
|
|
158
|
+
|
|
159
|
+
- **A global-only `actionableWarnings.autoFix.maxFixes` written in a project `.pi-lens.json` is no longer dropped in silence (fixes #3131)** — `#3112`'s mixed-scope sub-key scan derived its population from the flag registry alone (`LENS_FLAGS`, booleans only), so a global-only setting with no CLI flag counterpart — `actionableWarnings.autoFix.maxFixes`, documented global, read only through `getGlobalActionableWarningMaxFixes()` — was invisible to it even though its section (`actionableWarnings`) is recognized at project scope for its sibling `autoFix.enabled`. A new single-source registry, `GLOBAL_ONLY_NON_FLAG_KEYS` beside `LENS_FLAGS` in `clients/lens-flag-registry.ts`, names non-flag global-only dotted keys the same way the flag registry names flag ones; the scan now derives its full population from both, so a project file setting `maxFixes` gets the same one-time `PILENS_CFG_0001` global-only notice `tools.lazy` does, and the value still is not honored at project scope.
|
|
160
|
+
|
|
161
|
+
- **The in-lane per-edit cascade block honors a disposition mark (#3157)** — the four sites that build the agent-facing cascade neighbour list in `clients/dispatch/integration.ts` (passive cold snapshot, fresh in-lane touch, touch-error fallback, degraded fallback) rendered raw language-server findings: no inline `pi-lens-ignore`, no stored disposition, no `.pi-lens.json` `rules.<id>.disable`/`select` policy, and no auxiliary re-tag. So a neighbour ERROR the agent had marked `false-positive` was hidden by `mode=delta`/`mode=full`/the per-edit dispatcher/the probe lane/the quiet-window cascade run (#3102) and still came back on every edit that cascaded to that neighbour. All four now route through one shared `applyCascadeDisplayPolicy` seam — the same `clients/dispatch/finding-policy.ts` stack over the canonical `convertLspDiagnostics` + `retagAuxiliaryDiagnostics` identity — which the quiet-window cascade run now shares too, so the two cascade lanes agree on auxiliary findings as well: both honor the profile's own native `# nosemgrep`-style suppression and `skipTestFiles` gate instead of one lane rendering what the other drops. The disposition store and the rule policy are read from the PROJECT root rather than the cascade's language root, so a mark still applies in a monorepo. The per-neighbour display cap now applies to the SURVIVORS rather than to the raw list, so a suppressed finding can no longer consume a display slot — before this, a neighbour whose first 20 errors were all marked rendered nothing at all while genuine unmarked errors sat below the cap. The neighbour is read once, and only when it actually has an ERROR to render (measured: 0.14 ms per delivering neighbour with no marks in the store, 1.3 ms with marks, worst case 4.7 ms at the bounded input of 80 findings, against the cascade's ~100 ms-per-neighbour walk budget); an unreadable neighbour degrades to the content-free half rather than hiding a finding. Drops are counted in one `cascade_finding_policy` latency row per cascade run, and a block that still has findings states `suppressed by disposition: N finding(s)`. When the per-neighbour policy input bound leaves findings unevaluated, the cascade block says so to the agent (`⚠️ Cascade did not evaluate N finding(s) … no findings does NOT mean clean here`) instead of rendering an empty block that reads as a clean verdict — a single `.pi-lens.json` rule disable over a neighbour with many findings of that rule was enough to reach it.
|
|
162
|
+
|
|
163
|
+
- **A file created under a spelling the filesystem re-cases keeps its write record (refs #3163)** — the read guard announced a pending creation while the file was still absent and looked the announcement up after it landed, both times through `normalizeFilePath`, whose answer depends on that very existence. Any spelling whose key moved as the file appeared (on Windows every new file with an upper-case letter in its name; on POSIX a parent directory reached through a case-variant symlink) orphaned the announcement, so the synthetic creation read was never injected and the just-written file lost the outstanding-read protection that keeps it editable across an idle session. The announcement is now keyed by the existence-independent syntactic spelling the guard already uses for its post-delete index.
|
|
164
|
+
|
|
165
|
+
- **The release workflow's publish toolchain is now exercised before a release (closes #2940)** — `release.yml`'s publish job runs npm through the version pinned in `package.json`'s `packageManager`; since the pin moved to `npx`, a bare `npm publish` silently used the runner's bundled npm, which has no OIDC trusted-publishing support, and the v4.1.6 release created its tag and GitHub release before the registry answered E404. The publish job now asserts the pinned npm's version in the step immediately before publishing, `prepare`'s dry-run publish goes through the same pinned invocation, a governance test reds on any bare `npm <verb>` in either job, and the release-QA matrix gained a `publish-toolchain-pinned` row that runs that toolchain against the candidate before a tag exists. The row treats npm's already-published response as a toolchain witness, records registry-unreachable failures as inconclusive, and reports the underlying npm cause instead of its log path. Round 3 records that the existing `npm()` and `pinnedNpm()` wrappers cannot be folded without changing `execFileSync` buffering: only the pinned wrapper sets `maxBuffer: 10 * 1024 * 1024` (refs #2963).
|
|
166
|
+
|
|
167
|
+
- **PR-body test-reference check stops flagging commands, output, and prose (closes #3013)** — Recognise test references positively instead of treating every backticked phrase as one.
|
|
168
|
+
|
|
169
|
+
- **Keep fork pull requests out of token-capped CI writes (closes #2993)** — stale verdict-label cleanup is advisory and skips fork heads; merged-PR close-keyword comments use the uncapped target trigger.
|
|
170
|
+
|
|
171
|
+
- **Widget disposition reconciliation is admission-ordered (refs #1616)** — Marking a diagnostic disposition immediately reconciles the widget counts and retains suppressed findings as a visible bucket. Reconciliation now shares the same admission-ordered write tokens as dispatch, so a dispatch that was already in flight can no longer commit its pre-mark counts afterwards.
|
|
172
|
+
|
|
173
|
+
- **Share explicit analysis-root validation across heavyweight diagnostics consumers (refs #2053).**
|
|
174
|
+
|
|
175
|
+
- **Preserve the analysed file state across concurrent writes (refs #2499)** — The dispatch latch now records the state the pipeline actually analysed. The LSP batch pool preserves its abort contract: unstarted files do not add placeholder outcomes to aggregate diagnostics.
|
|
176
|
+
|
|
177
|
+
- **Directory-target observed codemods are analysed over rewritten files (closes #2500)** — Dispatch same-turn pipeline analysis for the recorded files inside a directory, with a bounded fan-out and visible truncation counts.
|
|
178
|
+
|
|
179
|
+
- **Measure stale async test-runner verdicts (refs #2542)** — delivered verdicts record their run and delivery file sequences, and the log analyzer reports known-verdict stale rates with unknown counts per session.
|
|
180
|
+
|
|
181
|
+
- **Pin backstop assertions to their sweep row (closes #2669)** — Grace retries no longer make the orphan backstop regression test read metadata from a later sweep.
|
|
182
|
+
|
|
183
|
+
- **Register only the read range the host delivered (refs #2802)** — Read-guard registration now uses the lines the host actually returned, including output-cap and EOF-clamped reads. A native read's provisional record is replaced by correlated tool-call identity rather than by position, so two reads of one file no longer leave the wider requested span behind and an unrelated search credit is never consumed. A delivered file that has disappeared no longer aborts the rest of the result chain, and an opaque write that leaves content identical no longer marks the file agent-authored. When bash observation evidence is unavailable, synthetic writes preserve authoritative content handling without granting read-guard authorship or edit permission.
|
|
184
|
+
|
|
185
|
+
- **Keep CI verdict labels fresh across pushes (refs #2856)** — Clear verdict labels when a pull-request head changes, explicitly scope checkout-free `gh` calls to the repository, and ignore incidental exit-137 log text as test-failure evidence.
|
|
186
|
+
|
|
187
|
+
- **Project data directory slug carries a path hash (closes #2874)** — Projects whose paths differ only in separator placement versus a hyphen no longer share one data directory; on first use after upgrade, the existing directory is renamed once so caches and session state carry over.
|
|
188
|
+
|
|
189
|
+
- **Require a SQL sink signal for TypeScript SQL injection findings (closes #2909)** — Ignore unrelated child-process and task-runner template calls while retaining blocking diagnostics for imported database clients and SQL-leading templates.
|
|
190
|
+
|
|
191
|
+
- **Marker-root freshness (refs #2922)** — Resolve the nearest marker with one synchronous walk per lookup, preserving visibility of nearer, created, and deleted markers without charging a redundant positive-cache rewalk.
|
|
192
|
+
|
|
193
|
+
- **Unify test filename classification (refs #2928)** — Apply the shared classifier to runner skip gates and word-index relevance, including Go, PHP and Ruby test names. Preserve vendor penalties and fixture/mock skip rules; recognize direct children of `__tests__`. `isTestFile` (secrets scanner, dispatcher, tree-sitter runner, and the pass-through-wrappers/async-noise/placeholder-comments rule gates) now also applies file-role's directory policy — `/spec/`, `/specs/`, and a bare `test`/`tests`/`spec`/`specs` directory segment (`my-test/`, `integration-test/`, `e2e_tests/`), case-insensitively — which its own deleted arms never covered.
|
|
194
|
+
|
|
195
|
+
- **Opengrep scan refusal reporting (closes #2943)** — Canonicalize symlinked workspace roots, preserve findings from partial-parsing warnings, classify every report and spawn failure once, and surface refused scans as cold diagnostics with machine-readable reasons. The outcome matrix now pins clean non-zero exits, every report discriminator, and the cached empty-coverage shape.
|
|
196
|
+
|
|
197
|
+
- **Anchor the test-runner child on the module its command runs in (refs #2944)** — every runner's spawn-cwd markers must name one of the runner's own manifests or the launcher its command actually invokes; the contract is now derived and tested over the whole runner table, and the stale claim that Maven's `mvn` command anchors on its `mvnw` wrapper is corrected. The Maven anchor itself landed with the #2965 marker-seam fix.
|
|
198
|
+
|
|
199
|
+
- **Keep side-effect autofixes out of target identity (refs #2957)** — Pipeline results no longer claim a post-write hash for the target when an autofix changed only another file.
|
|
200
|
+
|
|
201
|
+
- **Harden backstop retry regression coverage (refs #2958)** — Seed prior latency rows and await the unref'd grace retry through a bounded completion seam.
|
|
202
|
+
|
|
203
|
+
- **Keep findings when a partial scan has no coverage paths (refs #2962)** — a warning-level partial Opengrep report remains visible with an incomplete-coverage note and never retires retained findings as if it were a clean empty scan.
|
|
204
|
+
|
|
205
|
+
- **Share language markers across runner cwd resolution (closes #2965, closes #2966, closes #2964)** — runner fallbacks use the language marker vocabulary, cwd resolution returns its anchoring marker, and one dispatch pass reuses only its `.git` fallback.
|
|
206
|
+
|
|
207
|
+
- **Bound the spawn usage sampler's concurrency, rate and lifetime (refs #2968)** — a poll tick no longer starts while the previous one is still querying the process table, the interval backs off once a child outlives the short-lived window, and polling stops at a cap derived from the spawn's own deadline; on Windows this ends the `powershell.exe`/`taskkill.exe` pile-up behind a child that never exits, and skipped ticks and capped samplers are counted on the degradation ledger.
|
|
208
|
+
|
|
209
|
+
- **Classify CUDA/HIP `.cuh` headers (refs #2986)** — Route community-standard `.cuh` headers through the C++ language, grammar, file kind, and clangd server projections.
|
|
210
|
+
|
|
211
|
+
- **Decline ktlint autofix when project agreement is unavailable (refs #3000)** — when pi-lens cannot establish agreement with a Gradle- or Spotless-managed CLI, including convention plugins in `buildSrc` or included builds, it leaves the file unchanged and records one bounded session notice. The Gradle convention-plugin ownership walk stops at 10,000 directory entries; an exceeded scan is an indeterminate ownership result, declines before command resolution, and records one `gradle-ktlint-scan-budget-exceeded` notice per session.
|
|
212
|
+
|
|
213
|
+
- **Require project tool agreement before autonomous writes (refs #3005)** — autofix, formatting, and deferred LSP quickfixes use one cached agreement seam and a complete declarative tool population. Node agreement follows each resolver's package identity, including markdownlint-cli2. Missing, unreadable, unparseable, and unsupported project evidence declines conservatively, with bounded degradation records. Lockfile evidence declines with distinct reasons when a version is unparseable or a legal shape is unsupported. LSP quickfix agreement preserves the diagnostic producer from `source`, falling back to `serverId`, while unsupported identities remain fail-closed.
|
|
214
|
+
|
|
215
|
+
- **Confirm same-size all-LSP blocker rewrites (refs #3011)** — all-LSP blocker baselines now use content hashes even when a rewrite does not advance the recorded mtime.
|
|
216
|
+
|
|
217
|
+
- **Adopt NDJSON rotation bounds across extension reloads (closes #3012)** — an older unbounded writer adopts incoming bounds during module-graph re-evaluation, while conflicting bounded policies retain first-writer ownership and emit one bounded health record.
|
|
218
|
+
|
|
219
|
+
- **Compile against `@types/node` 26.5.1 (refs #3026)** — `node:perf_hooks` no longer exports the `IntervalHistogram` type, which broke `tsc` (TS2305) and with it every CI lane that builds. The event-loop monitor now infers the histogram type from `monitorEventLoopDelay`; emitted JavaScript and runtime behaviour are unchanged.
|
|
220
|
+
|
|
221
|
+
- **Require chart topology for Helm YAML classification (refs #3034)** — YAML files under `templates/` remain ordinary YAML unless an ancestor contains `Chart.yaml`; explicit `.tpl` helpers retain their Helm classification.
|
|
222
|
+
|
|
223
|
+
- **Stale inline blockers from non-LSP analyzers (closes #2982)** — The turn-end freshness sweep skipped every record whose provenance was not all-`lsp`, so a tree-sitter or ast-grep blocker was never checked against its own file. Combined with a retire path that can only claim coverage for registered language servers, such a record could not be cleared by any number of clean diagnostics runs and re-served every turn for the rest of the session. The sweep now checks the record's own file for any entry that carries provenance, keeping the forward-import walk for LSP-sourced records only; records with no recorded sources stay fail-closed. The check is confirmed against content at two tiers, size then a content hash, so a `touch`, a checkout restoring identical bytes, or a no-op formatter pass no longer demotes a finding while a same-length edit still does. It re-arms, so bytes that come back un-demote the record, and self-drift demotions sit outside the repeated-delivery cap that retires dependency-drift records, which keeps a security finding from being retired out of turn-end rendering. The content baseline is carried beside the inline-blocker evidence from the pipeline's existing file read and stamped synchronously with the record. All sweep filesystem work is bounded by the turn-end hook's own signal. Missing baselines and expired bounds emit bounded, file-identified ledger records, while aggregate hash-budget exhaustion stays sweep metadata. A demoted record still gates a commit, unchanged.
|
|
224
|
+
|
|
225
|
+
- **Classify YAML files under Helm `templates/` directories as Helm templates** — pi-lens no longer sends raw Helm Go templates to the YAML language server, eliminating cascading false-positive YAML parse diagnostics while retaining Helm lint and render validation.
|
|
226
|
+
|
|
227
|
+
- Put pnpm 11's resolved global bin directory (`$PNPM_HOME/bin`) on PATH in
|
|
228
|
+
install-smoke's pnpm setup, and run one `pi-load` pnpm-global cell on
|
|
229
|
+
pull requests so the lane cannot ship untested again.
|
|
230
|
+
|
|
231
|
+
- Fix install-smoke's pnpm global-bin setup for pnpm 11 projects declaring npm by writing the setting globally in both pi-load and mise-repro.
|
|
232
|
+
|
|
233
|
+
- Restrict install-smoke pull-request runs to the `master` base branch and
|
|
234
|
+
keep the parsed workflow contract aligned with that gate.
|
|
235
|
+
|
|
236
|
+
- Fix per-hook tool-result budget classification, formatter attribution, and deferred-format delivery.
|
|
237
|
+
|
|
238
|
+
- **Keep lifecycle hooks within per-hook wall budgets (refs #2523)** — bound aggregate formatter work and preserve unfinished diagnostics through off-hook delivery.
|
|
239
|
+
|
|
240
|
+
- **Keep latency-logger test mocks faithful to production exports (refs #2281)** — latency-logger mocks preserve the real module surface, and a conformance sweep catches omitted exports.
|
|
241
|
+
|
|
242
|
+
- **vi-mock export sweep reads `importOriginal<T>()` as a pass-through** (closes #2881) — a `vi.mock` factory spreading `await importOriginal<typeof import("…")>()` no longer reports every export as dropped; the parser also recognises `as`/`satisfies` casts, parenthesised spreads, and the two-statement `const actual = await importOriginal<T>()` binding as the same complete pass-through.
|
|
243
|
+
|
|
244
|
+
- **Stop the /lens-perf occupancy guard flaking under CI contention (closes #2886)** — The wall-clock occupancy assertion moves into the serialized `wall-clock-budget` lane with the flake-shape ratchet's admission, and a deterministic yield-count assertion is added beside it: the count pins the parser's cadence, the lane keeps the real measurement honest.
|
|
245
|
+
|
|
246
|
+
- **Keep deferred fixture roots tracked until their final drained cleanup pass (refs #2912)** — shared per-family cleanup drains deferred producers before untracking roots.
|
|
247
|
+
|
|
248
|
+
- **Drain deferred jscpd fixture cleanup (refs #2912)** — jscpd test teardown keeps the shared `pi-lens-jscpd-` owner stem registered across bounded macrotask drains, covering every jscpd output-root prefix in the suite.
|
|
249
|
+
|
|
250
|
+
- **Remove test scratch directories on exit (refs #2912)** — the generic process-wide fixture sweep was attempted twice and reverted after broad suite breakage; proven per-family sweeps remain, and unresolved prefixes enter an environment-independent prefix-set ratchet with named producers. The serialized hygiene owner records and removes newly-created `pi-lens-*` fixtures, the MCP harness removes IPC endpoints after child exit, release-QA accepts an owned `--scratch-root` with signal cleanup, ast-grep baseline scratch is bounded, generated ast-grep scan directories are collision-proof with preparation cleanup on partial setup failure, reverse-deps and agent-end summary fixtures drain several macrotasks before cleanup, and the session-start full-mode producer remains explicitly admitted.
|
|
251
|
+
|
|
252
|
+
- **Spawn-cwd scanner derives one vocabulary from the seam and freezes (closes #2927)** — the scan's site rule and the sweep's population predicate both derive from the `SPAWN_NAMES` / seven-name `NODE_SPAWN_NAMES` tuples, with per-name parity tests; the `// cwd-exempt:` channel is deleted with its self-tests after #2911 removed its last production tags; the scanner header states the simplify-not-extend freeze policy.
|
|
253
|
+
|
|
254
|
+
- **Keep the #2992 regression probe out of system temp (refs #2912)** — the read-bridge lifecycle test stores its ledger home under the ignored worktree-local `.probe-home` directory, so asynchronous bookkeeping cannot recreate a leaked top-level `/tmp` fixture.
|
|
255
|
+
|
|
256
|
+
- **Isolate `instance-reaper-unref` from the run-shared `PI_LENS_HOME` (refs #3050)** — `sweepUntrackedOrphans` takes `<PI_LENS_HOME>/orphan-backstop.lock` and reads the 30-minute `orphan-backstop.json` cooldown stamp before it enumerates anything, so a sibling Vitest fork's real `session_start` (`tests/index-integration.test.ts` arms 37 `scheduleUntrackedOrphanSweep()` timers through `index.js`) left a fresh stamp and the unref test's sweep returned `cooldown` with zero spawns — master 038e28b's only Unit failure. Each case now pins its own `mkdtemp` home, and `#3050`'s detector, which had recorded a two-character body for every declaration with a braced default parameter value and so never saw `sweepUntrackedOrphans`, now finds a body brace past the parameter list.
|
|
257
|
+
|
|
19
258
|
## [4.1.6] - 2026-09-10
|
|
20
259
|
|
|
21
260
|
### Added
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
[
|
|
2
2
|
"./clients/agent-nudge.js",
|
|
3
3
|
"./clients/ast-grep-client.js",
|
|
4
|
+
"./clients/bash-file-access.js",
|
|
4
5
|
"./clients/bootstrap.js",
|
|
5
6
|
"./clients/bounded-cache.js",
|
|
6
7
|
"./clients/bounded-telemetry.js",
|
|
@@ -11,6 +12,7 @@
|
|
|
11
12
|
"./clients/cache-observability.js",
|
|
12
13
|
"./clients/cascade-format.js",
|
|
13
14
|
"./clients/console-guard-install.js",
|
|
15
|
+
"./clients/deadline-utils.js",
|
|
14
16
|
"./clients/debug-handles.js",
|
|
15
17
|
"./clients/debug-heap.js",
|
|
16
18
|
"./clients/degradation-ledger.js",
|
|
@@ -26,6 +28,7 @@
|
|
|
26
28
|
"./clients/format-events-publish.js",
|
|
27
29
|
"./clients/format-service.js",
|
|
28
30
|
"./clients/formatters-lazy.js",
|
|
31
|
+
"./clients/hook-budgets.js",
|
|
29
32
|
"./clients/host-ports.js",
|
|
30
33
|
"./clients/installer/index.js",
|
|
31
34
|
"./clients/instance-reaper.js",
|
|
@@ -13,6 +13,8 @@ import { toRunnerDisplayPath } from "./dispatch/runner-context.js";
|
|
|
13
13
|
import { logActionableWarningsEvent } from "./actionable-warnings-logger.js";
|
|
14
14
|
import { displayProjectDataPath, getProjectDataDir } from "./file-utils.js";
|
|
15
15
|
import { commitDurableStore } from "./durable-store.js";
|
|
16
|
+
import { establishToolAgreement } from "./tool-agreement.js";
|
|
17
|
+
import { resolveLensToolName } from "./tool-config.js";
|
|
16
18
|
let beforeWarningStateLockForTests = null;
|
|
17
19
|
/** Test seam for a sibling process commit immediately before lock acquisition. */
|
|
18
20
|
export function _setBeforeWarningStateLockForTests(hook) {
|
|
@@ -252,11 +254,15 @@ function lineInModifiedRanges(line, ranges) {
|
|
|
252
254
|
function recordFromLspDiagnostic(diag, filePath, cwd) {
|
|
253
255
|
const line = diag.range.start.line + 1;
|
|
254
256
|
const column = diag.range.start.character + 1;
|
|
257
|
+
// Keep agreement keyed to the producer that supplied the diagnostic. The
|
|
258
|
+
// generic `lsp` label is only a last-resort identity: treating it as a
|
|
259
|
+
// registered writer would establish every LSP quickfix without evidence.
|
|
260
|
+
const producer = diag.source && diag.source !== "lsp" ? diag.source : diag.serverId;
|
|
255
261
|
const source = diag.source ?? "lsp";
|
|
256
262
|
const code = diag.code === undefined ? undefined : String(diag.code);
|
|
257
263
|
const identityArgs = {
|
|
258
264
|
filePath,
|
|
259
|
-
tool: "lsp",
|
|
265
|
+
tool: producer ?? "lsp",
|
|
260
266
|
source,
|
|
261
267
|
code,
|
|
262
268
|
message: diag.message,
|
|
@@ -271,7 +277,7 @@ function recordFromLspDiagnostic(diag, filePath, cwd) {
|
|
|
271
277
|
line,
|
|
272
278
|
column,
|
|
273
279
|
severity: "warning",
|
|
274
|
-
tool: "lsp",
|
|
280
|
+
tool: producer ?? "lsp",
|
|
275
281
|
source,
|
|
276
282
|
code,
|
|
277
283
|
rule: code ? `${source}:${code}` : source,
|
|
@@ -1428,6 +1434,19 @@ export async function applyConservativeActionableWarningFixes(args) {
|
|
|
1428
1434
|
continue;
|
|
1429
1435
|
}
|
|
1430
1436
|
summary.considered++;
|
|
1437
|
+
const agreement = establishToolAgreement(warning.tool, args.cwd);
|
|
1438
|
+
if (agreement.decision === "decline") {
|
|
1439
|
+
recordDegradationOnce({
|
|
1440
|
+
kind: "autofix-agreement-unavailable",
|
|
1441
|
+
subject: agreement.subject,
|
|
1442
|
+
reason: agreement.reason,
|
|
1443
|
+
});
|
|
1444
|
+
summary.skipped.push({
|
|
1445
|
+
id: warning.id,
|
|
1446
|
+
reason: "tool_agreement_unavailable",
|
|
1447
|
+
});
|
|
1448
|
+
continue;
|
|
1449
|
+
}
|
|
1431
1450
|
if (!warning.line || !warning.column) {
|
|
1432
1451
|
summary.skipped.push({ id: warning.id, reason: "missing_position" });
|
|
1433
1452
|
continue;
|
|
@@ -1516,7 +1535,7 @@ export async function applyConservativeActionableWarningFixes(args) {
|
|
|
1516
1535
|
* unread under `~/.pi-lens/projects/<slug>/cache/`. An OPTIONAL `cwd` would
|
|
1517
1536
|
* have kept that bug alive behind a default, so callers must pass it.
|
|
1518
1537
|
*/
|
|
1519
|
-
export function formatActionableWarningsAdvisory(report, cwd) {
|
|
1538
|
+
export function formatActionableWarningsAdvisory(report, cwd, host = "pi") {
|
|
1520
1539
|
if (report.summary.unsuppressed === 0)
|
|
1521
1540
|
return undefined;
|
|
1522
1541
|
const files = report.files.filter((file) => file.warnings.some((warning) => !warning.suppressed));
|
|
@@ -1543,10 +1562,17 @@ export function formatActionableWarningsAdvisory(report, cwd) {
|
|
|
1543
1562
|
// reading the transcript, rendered through the one helper that cannot
|
|
1544
1563
|
// disagree with the writer.
|
|
1545
1564
|
const reportPath = displayProjectDataPath(cwd, "cache", "actionable-warnings.json");
|
|
1565
|
+
// #2535 F3: a known tool with no mapping on this host resolves to
|
|
1566
|
+
// undefined — omit the instruction rather than naming a dead tool.
|
|
1567
|
+
// `lens_diagnostics` is pinned available on both hosts, so this is
|
|
1568
|
+
// defensive only.
|
|
1569
|
+
const diagnosticsTool = resolveLensToolName("lens_diagnostics", host);
|
|
1546
1570
|
return [
|
|
1547
1571
|
`🟡 Fixable warnings introduced this turn: ${report.summary.unsuppressed}.${safe}`,
|
|
1548
1572
|
tierLine,
|
|
1549
|
-
|
|
1573
|
+
diagnosticsTool
|
|
1574
|
+
? `Use ${diagnosticsTool} with mode=delta to inspect these warnings.`
|
|
1575
|
+
: undefined,
|
|
1550
1576
|
fileList ? `Files:\n${fileList}${more}` : undefined,
|
|
1551
1577
|
"If continuing in these files, resolve warnings that are safe and relevant. Do not apply broad refactors unless requested.",
|
|
1552
1578
|
`Raw report (only if you need the JSON): ${reportPath}`,
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
import * as nodeFs from "node:fs";
|
|
18
18
|
import * as path from "node:path";
|
|
19
19
|
import { isReadableSourceFile } from "./file-kinds.js";
|
|
20
|
+
import { classifyMutatingTool } from "./mutating-tool.js";
|
|
20
21
|
import { countFileLines } from "./read-guard-tool-lines.js";
|
|
21
22
|
import { stripAnsi } from "./sanitize.js";
|
|
22
23
|
function stripQuotes(token) {
|
|
@@ -1028,3 +1029,28 @@ export function extractDeletedPathsFromCommand(command, cwd) {
|
|
|
1028
1029
|
}
|
|
1029
1030
|
return Array.from(out);
|
|
1030
1031
|
}
|
|
1032
|
+
/**
|
|
1033
|
+
* One edit-class predicate for the `tool_result` path (#2939 F3).
|
|
1034
|
+
*
|
|
1035
|
+
* `index.ts` used to answer "is this an edit-class result" twice — once in
|
|
1036
|
+
* the handler body (gated on `toolName === "bash"`) and once in the
|
|
1037
|
+
* `budgetKey` callback (no tool gate) — and the copies disagreed on the
|
|
1038
|
+
* first third-party case tried (`mcp__acme__shell` with `input.command`:
|
|
1039
|
+
* wrapper said edit, handler said read-only). Both call sites now share
|
|
1040
|
+
* this function, so the answer is written once — but the call sites
|
|
1041
|
+
* themselves are not yet pinned (W4/M8, #2939), so a future tool-name gate
|
|
1042
|
+
* re-introduced at one of them would still pass the suite.
|
|
1043
|
+
*
|
|
1044
|
+
* A result is edit-class when the mutation seam classifies it, or when its
|
|
1045
|
+
* `input.command` names written files. The command half carries no tool-name
|
|
1046
|
+
* gate on purpose: a shell that wrote files runs the same pipeline whatever
|
|
1047
|
+
* its tool is named, and the edit budget must cover that work.
|
|
1048
|
+
*/
|
|
1049
|
+
export function isEditClassToolResult(event, cwd) {
|
|
1050
|
+
if (classifyMutatingTool(event, { recognizeOnly: true }) !== undefined) {
|
|
1051
|
+
return true;
|
|
1052
|
+
}
|
|
1053
|
+
const command = event?.input?.command;
|
|
1054
|
+
return (typeof command === "string" &&
|
|
1055
|
+
extractWrittenPathsFromCommand(command, cwd).length > 0);
|
|
1056
|
+
}
|
|
@@ -325,7 +325,7 @@ export class BiomeClient {
|
|
|
325
325
|
const before = await fs.promises.readFile(absolutePath, "utf-8");
|
|
326
326
|
const configCwd = resolveToolCwd("runner", "biome", absolutePath, {
|
|
327
327
|
...(cwd !== undefined && { cwd }),
|
|
328
|
-
});
|
|
328
|
+
}).cwd;
|
|
329
329
|
// Shared config-args seam (#1247): the lint runner consumes the same
|
|
330
330
|
// builder, so `lint --write` can never drift to biome's default
|
|
331
331
|
// config when a user config or the package fallback exists.
|