Added
- Deliver test-runner failures after the agent settles (refs #2366)
- Shared config core (refs #2425).
pilens_effective_config/effective_configanswer "why is X running" (closes #2427)- pi-lens now learns which third-party tools edit files by watching (closes #2430)
- Agent worktree and orphan-process hygiene (closes #2435)
BoundedFifoMap<K,V>sibling ofBoundedLruCache(refs #2442)bounded()and a governance guard for hook awaits (refs #2523)- Config resolution now proves it happened (closes #2526)
scripts/ci-verdict.mjs: one REST read of Unit tests + Lint & type-check conclusions on an exact head SHA (closes #2539)- Add a flake-shape ratchet over every
*.test.tsundertests/(closes #2547) - Release-readiness QA pass: a witnessed feature × modality matrix against a real pi (refs #2606)
- Roll up declined concurrent session starts (refs #2130, closes #2249)
- install-smoke gains a PR-gating host-range lane and a nightly
@latestadvisory lane (closes #2613)
Changed
- Exercise the per-server touch verdict with two auxiliaries, so a sibling scanner's findings must survive a slow scanner's lapsed … (#1549)
- Bound a multi-file review-graph rebuild's edge removal (refs #2074)
- Registered-or-fail sweep for topology-derived caches (closes #2294)
- Exercise workspace-diagnostics sweep attribution and error-path closure through a pull-advertising server on the real JSON-RPC … (#2332)
- Exercise full session-start topology re-derivation through the live path (closes #2333)
- Govern lsp-spawn-heavy lane membership (refs #2344).
- A broken LSP config now warns once per problem, not once per load attempt (refs #2418)
- Cross-file staleness now works for the languages the registry reconnected (refs #2424)
- One canonical language registry behind LSP, tree-sitter, dispatch, read expansion and the review graph (closes #2424)
symbol_search'slangfilter answers from the registry (refs #2424)- One canonical config file, one documented lookup order (refs #2426)
- A globally disabled language server can no longer be re-enabled by a repository (refs #2427)
- One shared registration helper for the read and mutation bridges (refs #2437, refs #2423)
- One process-table seam replaces five hand-rolled snapshotters (closes #2443)
BoundedSetsibling inclients/bounded-cache.ts; four hand-rolled membership-Set caps migrated (refs #2460)- Analyzer bootstrap clients load on demand, not at session start (closes #2467)
- Every "deadline AND abort signal" bound now goes through one primitive (refs #2523)
escapeRegExpfolded onto one runtime export (refs #2558)- One dialect-parameterized workspace-member glob matcher (closes #2591)
- Migrated the last 18 hand-rolled
LSPServicetest doubles (17 files) onto - Test names state behavior, not hope (closes #2602)
- One fixture-workspace bootstrap for the five LSP dev-harness scripts, home-pinned (closes #2670, closes #2658)
- CI production-dependency audit is bounded and retried
tools/lsp-diagnostics.ts's directory-scan language table is now a registry projection (refs #2434)- Config parse errors keep
line L col Clocality for every V8SyntaxErrorshape, derived from the source text instead of the message (refs #2451) tests/config/bounded-eviction-idiom-sweep.test.ts's exemptions are keyed by content, not line number (closes #2475)effective_config/pilens_effective_configreject afileoutsidecwdinstead of silently answering from a foreign tree (closes #2520)- Turn-end test runner: integration/e2e targets excluded, and an unfinished batch is deferred instead of reported clean (closes #2522)
- Consolidate LSP service test doubles (refs #2582)
- LSP
- Pinned that
git initis never worktree-mutating, and that an ephemeral test fixture is never a shared checkout (refs #2345)
Deprecated
- Deprecation windows for the legacy LSP config surfaces (refs #2418)
- The legacy config locations now say so, once per setting (refs #2426)
Fixed
- Bound re-raised auxiliary coverage-gap detail (#2356)
- Formatter config-signature lookup is warm-path cached (closes #1603)
- Keep word-index persists incremental after a session reload (refs #2068)
- The availability probe consults pi-lens's own managed bin dir, not just PATH (closes #2140)
- Normalize escaped-newline flattened PR bodies for checking (refs #2145)
- Stop starving auxiliary LSP resyncs behind a cold primary spawn (closes #2239)
- Bound per-file session-fact growth in dispatch's
FactStore(refs #2282) - The ast-grep napi fallback now reports at the LSP's severity floor (closes #2336)
- Classify machine-emitted text as generated by content shape (refs #2346)
- Restore embedded-
<script>ast-grep coverage under the napi fallback: HTML script bodies are now scanned with `language: … (#2347) - Honor runner language scope inside dispatch groups (closes #2353)
- Remove the unused runner default declaration (closes #2354)
- Run review-graph changed-symbols and entity snapshots under one normalized key per file (refs #2355)
- Re-arm late auxiliary coverage after notify-stall teardown (refs #2356)
- Coalesce superseded LSP document notifications (refs #2357)
- The LSP breaker's CPU-liveness verdict reads its own sample window (closes #2358)
- Make the #2358 CPU-liveness regression proof clock-boundary safe (refs #2358).
- Preserve unknown root identity in
session_start_total(refs #2129). - Replay exact-SHA master validation after merge-train merges (closes #2380)
- Approve the installed ast-grep CLI lifecycle script (refs #2401)
- Recognize already-applied edits instead of re-applying them on retry (closes #2402)
- An unavailable formatter no longer reads as a code failure (closes #2413)
- Model-facing analyze counts no longer fold hint/info findings into warnings (closes #2420)
- File mutations from any tool now reach the analysis pipeline (refs #2423)
- Config notices now name only settings pi-lens recognizes, and one file can no longer flood you with them (refs #2426)
- A truncated config-notice list now says how much it truncated, and stops calling a valid file invalid (refs #2426)
- A legacy config file's notices are bounded whichever loader reads it, and a warm config load no longer pays for the enumeration twice (refs #2426)
- "None of this config is in effect" is never one of the notices the bound suppresses (refs #2426)
- A malformed
~/.pi-lens/config.jsonnow says so, as a global-config problem (closes #2445) - Separate the mutation bridge's recordability from
--no-read-guard(closes #2465) recordEntitySnapshotDiffenforces its absolute-filePathinvariant (closes #2477)- A nested
executeCommandno longer strips the outer LSP call mutation receipt (closes #2479) - The SubagentStop hook now reaps the stopped agent's worktree (closes #2486)
- Stop cross-project delta-baseline contamination on the warm MCP server (closes #2489)
turn_endno longer blocks the terminal on a stale worklist (closes #2504)- NDJSON log sinks bound themselves mid-session, not only at session start (closes #2505)
- Send a stray probe's LOGS to a scratch dir instead of the real
~/.pi-lens, without moving its tools or registry (closes #2506) - A headless pi child no longer exits 0 in the middle of a tool call (closes #2507)
- Deflaked four shared-slot-contention test races (closes #2512, closes #2495)
- Close out the #2508/#2511 ndjson-logger and log-dir leftovers (refs #2515, refs #2516)
- Turn-end advisories name the resolved cache path, not a hardcoded
.pi-lens/one (closes #2521) - LSP wait and sweep-warm-up records name only rooted candidates (closes #2525)
lens_diagnostics mode=fulland--lens-guardnow treat a test RUNNER error as advisory, matching the turn-end message (closes #2532)- Overlap auxiliary LSP warmup with primary server during resync (closes #2540)
- Label-manifest governance test now derives its full requirement, and
prune: trueis explicit where it lives (refs #2553) - Label syncer no longer deletes the priority labels on every merge-train lane merge (refs #2553)
- compat-smoke Layer A resolves each pinned contract's source file independently (refs #2581)
peerDependencies["@earendil-works/pi-tui"]no longer excludes pi 0.85.x (closes #2586)pi.skillsno longer escapes the published package (closes #2587)- Merge gate no longer false-fails on a concurrency-superseded cancelled check-run (closes #2632)
ci-verdict.mjs's absent-required-checks reason now says why (refs #2664)- Use project Python environments without shell activation (closes #2407, refs #1513)
- Memoize package-manager global bin dirs (closes #1602)
- Log session-start classification alongside
mode(closes #2129) - Emit availability_decision telemetry on the LSP-launch managed-bin fast path (refs #2140)
- Cap the widget footer's dependency-drift re-serves (refs #2275, sibling of #1950)
- The #2117 arena-recompaction regression test no longer flakes on a scheduling accident (closes #2293)
- Session-state sweep flags process-singleton-backed state and accepts closure-located resets (refs #2319)
- Rule tooling handles mixed-case language tags (closes #2331)
- Enforce ast-grep-napi's skipTestFiles on the write-group dispatch path (refs #2337)
- Breaker teardown tells dead from busy (#2358).
- Isolate post-agent test delivery (refs #2366)
- Nightly tool-smoke
- Unconfigured HTML and YAML files no longer auto-format with Prettier (closes #2384)
- Biome lint and autofix no longer produce import-type rewrites for projects without a Biome config (refs #2385)
- Keep alternate language servers as fallbacks during all-scope diagnostics (closes #2400)
- Bound post-merge reconciliation by its time window (refs #2405)
- Parse pytest counts only from its terminal summary (closes #2408)
- Stop presenting hint/info findings as code warnings (refs #2414)
- Stop leaking config file contents into diagnostics on a JSON parse error (refs #2431)
tests/fixtures/fake-lsp-server.mjscan no longer outlive a killed parent (refs #2436)- Wire oxlint into
npm run lintand CI for plain.mjs/.cjs/.jsfiles (refs #2439) - LSP-applied edits (rename,
workspace/executeCommand) now always bookkeep through the existing LSP mutation seam, and name the specific operation (closes #2450) - Extend
npm run lint:js(oxlint--deny-warnings) toclients/,tools/,mcp/, and rootindex.tsTypeScript (refs #2439, #2454, #2462) - Session-state sweep detector no longer hard-codes container class names, no longer gates on a
clear()/delete()method name, and no longer misses an exported container (refs #2442, #2455) - Analyse every observed (unclassified-tool) mutation — the tool's FIRST call included — and apply the post-pipeline post-conditions on that path (#2464)
- rustfmt now carries the Cargo package edition (closes #2466)
- ktfmt now carries the project's Gradle
ktfmt { }style selection (closes #2468) - Wait for the persisted snapshot instead of racing it in
word-index-lifecycle.test.ts's absent-snapshot test (closes #2471) - php-cs-fixer now carries its detected ancestor config into
--config(closes #2472) - Monorepo module-graph crate names are now read from
[package]only (closes #2473) - Project-config discovery with no config file anywhere is bearing-scoped, not $HOME-wide (refs #2426, closes #2483)
- Rust workspace-root hoisting reads
[workspace]presence through the shared Cargo.toml reader, not a second hand-rolled regex (closes #2498) tests/support/sweep-kit.ts'sstripSourcetracks${nesting depth in template literals, including nested templates inside the expression (closes #2502)- A formatter installed only at your home directory is no longer used as a project's formatter (closes #2514)
prune-agent-worktrees.test.ts's R2 gitlink-corruption case no longer races a wall clock (closes #2519), and the SubagentStop orphan sweep'srestrictToPathscoping is now covered end to end (closes #2501)- Resource-sampler scanner timeouts are recorded under their own kind, not the orphan backstop's (closes #2524)
- Compat-smoke Layer B reads the latency log it actually wrote (fixes #2570)
- Reject literal control bytes in tracked source (closes #2571)
- Deflake
hook-await-fold-boundsby settling its abandoned bootstrap loads (closes #2574) - Extend Python SQL-rule safe-builder recognition with same-file provenance (fixes #2576)
- Run pytest in uv-managed project environments (closes #2580)
- Resolve
bundle:dist's esbuild independent of the project tree (closes #2590) build:distnow avoids a network fetch for tsc when the local pinned version is already installed, while still isolating the fallback path from #2590's collision (refs #2590)- Workspace-member globs no longer wedge a turn on an interleaved `
ci-verdict.mjsgates on every check-run, not just Unit tests/Lint (closes #2609)- Skills
package.jsonnow declaresengines.node, and the managed installer no longer resolvestypescript-language-serverunpinned (closes #2633)tests/packaging-pack-manifest.test.tsno longer writes into the developer's real~/.pi-lens/install.log(closes #2634)- ast-grep / tree-sitter rules
- Managed CSS/HTML Language Server installs no longer target dead or mismatched npm packages, and a genuine install failure is no longer silently folded into "toolchain absent" (refs #2638)
- Infra-kill auto-rerun now covers master pushes and bot merges, not only PRs (closes #2668)
- Tests
- Tests
- Install
Security
- Scope workflow permissions per job (closes #2403)
- An operator's LSP denial survives traffic to other project roots (closes #2518)
🙏 Thanks
Thanks to the external contributors in this release: