Added
- CUE code formatting support
- CUE tree-sitter grammar
- CUE Language Server support
- CUE symbol and import extraction (refs #1522, #1519)
cue vetauxiliary runner for CUE evaluation errors (refs #1522, #1519)- Rendered-manifest validation for Helm charts, opt-in (refs #1283)
- ast-grep rule: ban bare
objectparameter annotations (Refs #1597) - Ported anti-slop's AI-authorship rules into the shipped ast-grep catalog (refs #1718)
- One primitive for "at most one execution per key" replaces ten hand-rolled copies (closes #1753)
- Merge-train warden (refs #1844)
- Add autofixes for mechanical ast-grep rules (refs #1850)
- Record host-ready delay (refs #1859)
- Three CI smoke lanes for the lifecycle/scope defect classes of the 2026-08 arc (refs #1605)
- State-machine property tests for the availability latch (refs #1609)
- Reset-interleaving test explorer (refs #1840)
Changed
- Anti-slop rules: one promotion to
error, six deliberate holds (refs #1727, refs #1777) - Credit external contributors ahead of v4.1.0
- Docs: agent-guide reflects the stale-secrets ACTION NEEDED tier (refs #1522)
- Codified live-binary discipline in AGENTS.md, per maintainer directive
- Ast-grep authoring skills now teach the
stopByboundary idiom, the four-tier severity policy, and suppression-fixture discipline - Added the 2026-08-17 through 2026-08-20 recurring defect shapes to the agent catalog
- docs: language-coverage lists mypy in the Python row
- AGENTS.md: six new PR-discipline rules from the v4.1.0 review arc
- One helper for bounded telemetry, and a sweep that keeps failure paths on it (refs #1743)
- One generation guard instead of four hand-rolled ones
- Consolidated three duplicated test-fixture families onto shared support helpers (refs #1816)
- Workspace-scope LSP queries identify their serving client (refs #1854)
- Turn-end madge circular-dependency check is opt-in, default off (closes #766)
- Narrow
no-non-null-assertionfalse positives (refs #1777) - A cascade that a slow prelude pushed out of the turn-end window now shortens its neighbour walk to land on time, when shortening it actually helps (refs #1462)
- Promote laundering, unknown-return, and Reflect rules to errors (refs #1856)
- Consolidate the registered-or-fail sweep machinery
- Turn-simulation harness and a session-state lifecycle registry (refs #1635)
- Test fixtures now match the real host's
session_start/tool_resultevent shape (refs #1681) - Pinned trivy's dependency-CVE disposition filter with a regression test (refs #1813)
Fixed
- Reach never-swept monorepo caches on workspace refresh (closes #1707)
- LSP navigation verifies capabilities at the client boundary (closes #1826)
- Distinguish a slow LSP warm spawn from no clients (closes #1875)
- Avoid doomed waits for historically slow LSP spawns (refs #1884)
- Re-arm direct-LSP and installer availability caches (closes #1897)
- Bound the cascade tier-3 reconcile backlog and drop the dead neighbour-touch cache (closes #1899)
- Avoid false read-guard blocks after formatter writes (closes #1903)
- Credit search hits with the lines the search actually showed (closes #1904)
- A size-capped write no longer says both "attached" and "too large to attach" (closes #1590)
- Preserve biome's info/hint severity in dispatch
- cuelsp's silent clean-open no longer reads as inconclusive (refs #1522, #1519)
- Preserve ast-grep rule severity tiers through dispatch
- Persist degradation-ledger decisions in
latency.log - A write that already handed back its post-fix content no longer also tells you to re-read it (closes #1464)
- Knip's per-turn delta no longer reads a shifted finding as newly unused (#1483)
- A stalled PowerShell check no longer disables PSScriptAnalyzer for the rest of the session (closes #1490)
- A silent auxiliary no longer reads as confirmed clean (closes #1493)
- A stalled version check no longer disables eslint, credo or clippy for the rest of the session (closes #1494)
- A stalled PATH lookup no longer disables a formatter until you edit a config file (closes #1495)
- A stalled package-manager check no longer downgrades pi-lens's own managed installs to npm (closes #1496)
- A repeatedly timing-out
go installno longer re-compiles govulncheck every few minutes forever (closes #1497) - Tool-availability records now show what actually failed, and a failed auto-install is no longer a silent verdict (closes #1500)
- Transient security-scanner probe records now carry their retry schedule (closes #1501)
- Venv-resolved tool paths are no longer wrapped in literal quotes (closes #1508)
- Auxiliary diagnostic waits and their outcome rows are now decided per file (closes #1531)
- A silent auxiliary no longer reads as confirmed clean on batch scans either (closes #1533)
- A failed grammar download no longer disables a language for the rest of the session (closes #1536)
- A lazy install that dies on a network blip is retried instead of skipped for the session (closes #1537)
- A stalled PATH probe no longer hands your project to its second-choice formatter for the session (closes #1539)
- An execution-policy-blocked PSScriptAnalyzer run no longer reports the file as clean (closes #1540)
- Fish had no LSP runner in the registry, and 21 extensions had no language id, because two seams were hand-copies of the language registry (closes #1545)
biome-client-dedupetest now isolates the in-flight probe dedupe from package-manager spawn count (refs #1546)- A captive portal can no longer poison a grammar file permanently (closes #1548)
- A workspace sweep no longer speaks for a scanner that missed its deadline (refs #1549)
- One slow scanner no longer discards every good answer in a cascade sweep (refs #1549)
- Cascade "could not compute impact" records now name the file that actually caused it (closes #1550)
- The availability-policy coverage gate no longer waves through a verdict that dodges the word "boolean" (refs #1552)
- A resolved blocker no longer re-appears as "Unresolved from this turn" after pi-lens has confirmed the file clean (refs #1561)
- A truncated grammar download no longer poisons the file permanently (#1564)
- Tests no longer reset a duplicate copy of the module state they are guarding (closes #1565)
- The availability-policy coverage gate no longer inherits routing from a memo that merely mentions a policy handle's name (refs #1566)
- The ast-grep native-addon load no longer starves a concurrent caller or latches across sessions (refs #1567)
- A stalled ast-grep binary no longer pins the whole session to
npx(closes #1568) - A tool tier degraded by a transient stall no longer survives 24h across process restarts (#1569)
- A failed lazy-module load or classic-tsserver repair no longer stays broken for the rest of the process (closes #1570)
- Formatter config-file cache now sees files created mid-session, for several formatters that previously missed it (refs #1572)
psscriptanalyzer-formatcan now be selected for.ps1/.psm1/.psd1files, and honors its settings file (closes #1572)- npm-global tool discovery now flags a stalled package-manager probe as transient (refs #1585)
- A scanner that answered while its resync sat queued is no longer reported as a blackout (refs #1586)
TreeSitterClient.init()no longer replays a deadimport()on every file parse (refs #1592)- The retained-winner arm no longer re-serves an ast-grep command this same sweep just proved gone
- Basename-classified files (
Makefile,Dockerfile.<suffix>) reacheddidOpenas plaintext, invisible to the #1545 extension-seam guards (refs #1594) - Seven more config-gated formatters were unselectable under any project configuration (refs #1595)
- An exit-0 PSScriptAnalyzer run with empty or malformed stdout no longer reports the file as clean (refs #1598, refs #1540)
BiomeClient's in-flight leak guard could not fail (refs #1601)- PSScriptAnalyzer's execution-policy regex tightening now has regression tests (refs #1604)
- Security scanners log a compensating
availablerow when auto-install recovers a failed probe (refs #1606) - agent_end no longer misreads a disabled feature as a missing cache (closes #1607)
language: TypeScriptast-grep rules now run on.tsxfiles- Several installer writes and two persisted-state read paths did not survive a hard kill cleanly (refs #1609)
- ~16 CLI runners now log recovery when auto-install fixes a failed tool probe (closes #1612)
- Marking a secrets/security finding false-positive or won't-fix now sticks, on every reporting lane (refs #1617)
- Idle-reset timer no longer destroys the LSP service mid-sweep (closes #1618)
- LSP teardown no longer hangs on a wedged server, leaking the process (refs #1620, #1459)
- LSP teardown: live-wedged proof, precise failure attribution, and safe idempotent shutdown (refs #1620)
- Rename propagation no longer hangs on a wedged LSP server (refs #1621, #1620)
- Cached secret findings no longer replay pre-edit line numbers (refs #1622)
- Fix "age unknown old" grammar in lens_diagnostics cache-age notes (refs #1623)
- lens_diagnostics now names every lane that did not run, instead of rendering silence as clean (refs #1623)
- A blocking secrets finding can no longer be silenced by a loosely-matched mark (refs #1617)
- Trivy secret findings now honor dispositions (closes #1628)
instance-reaper-prune-concurrencyno longer times out flakily under CI contention (closes #1629)- knip no longer reports an export as unused after a new test imports it (refs #1630)
- Cached cross-file blockers no longer replay for the whole session after the cause is fixed in a dependency (closes #1631)
- Dependency-drift blocker freshness gate: review-round hardening (refs #1631)
- Every agent-facing finding surface now either routes through the shared freshness/disposition gate stack or explicitly states its cache age — no more silent third state (refs #1634)
- markdownlint and 14 other CLI runners now log recovery when the install-fallback helpers fix a failed probe (closes #1636)
createVenvFindernow checks the managed tools dir before falling back to PATH (closes #1638)- TypeScript diagnostic-sequence records now report a real settle duration, a real version, and a distinct source for every settle shape (closes #1639)
- TypeScript diagnostics on files outside every tsconfig no longer block
- Diagnostics no longer cite lines past the file's current EOF (refs #1641)
- Past-EOF diagnostic gate review round (refs #1641)
- Verify round: line-count memo keyed on size too (refs #1641)
- Turn-end inline blockers now gate on past-EOF lines too (closes #1641)
- A gitignored worktree edit could dirty the parent checkout (refs #1642)
- The #1605 lifecycle-smoke lane's phase 5 now genuinely exercises an absent
gh, andsafeSpawnAsyncdecides a never-started spawn from thecloseevent's own shape (refs #1651) - Package-manager availability latches re-arm at
session_start(closes #1653) - Deferred format/autofix drain no longer runs mid-run on auto-retry or overflow-compaction (refs #1654)
- Hardened pi-lens against five pi host-contract facts it mishandled (refs #1655)
safeSpawnAsync's post-exit pipe-idle wait no longer pays out its full 100ms grace window on every call (refs #1656)safeSpawnAsync's post-exit pipe-idle wait no longer lets a late, unrelated error steal an already-decided healthy verdict (refs #1656)safeSpawnAsyncno longer hangs forever on a daemonized descendant that inherits its stdout/stderr pipe (refs #1656)- A compensating
availablerow that corrected nothing no longer silences the real one - Pull diagnostics no longer miss whole categories on multi-source servers
- LSP servers now learn about files a bash command deleted, even though pi-lens never sends
workspace/didChangeWatchedFilestype 3 anywhere (refs #1668) - LSP client answers
workspace/diagnostic/refreshand honors Incremental text sync (refs #1669) - Monorepo Cargo and Maven projects no longer spawn one heavy LSP server per crate or module (refs #1671)
- Path-attribution follow-ups: bounded orphan degradation, documented id-fallback assumption, pinned reclaim test (refs #1678, #1642, #1648)
- Bound the playground rule verifier's child-process wait (closes #1679)
- The secrets and govulncheck gates' disposition filters are now proven, not just present (closes #1694)
- Give
findingPathFreshnessthe same mtime-skew tolerance its sibling freshness gates carry (closes #1708) - Give
reconcileProjectDiagnosticsSnapshotthe shared mtime-skew tolerance, not a bare +1ms (closes #1711) - Pull-diagnostic timeouts are observable again (refs #1713)
- Full-scan sweeps no longer out-run an auxiliary scanner (refs #1714)
navRequesttimeouts are observable again (refs #1716)- The ast-grep self-scan now actually runs (closes #1718)
- A cascade's neighbor re-check no longer notifies auxiliary scanners
- Knip now runs the project's own knip (refs #1721)
loop_blocknow names a synchronous block still in progressloop_blocknow records every block over the floor, not only the session's biggest (refs #1723)- A forced LSP shutdown could leave the dead pid registered in
instances.jsonfor the rest of the session (refs #1724) - Sweep the remaining author-machine paths baked into scripts/ and package.json (closes #1728)
- Managed tools now refresh instead of drifting stale (refs #1730)
- taplo, biome, stylua, and vulture now prefer the project's own binary and config over pi-lens's managed copy (refs #1731)
- Runner exit codes now gate clean vs. errored (refs #1736)
- Managed tools from GitHub releases, pip, gem, archives and Maven now refresh too (refs #1747)
- ruff
Ssecurity rules now run by default; the IaC misconfig lane now actually scans (refs #1757) - Tree-sitter grammar wasms now refresh when the pinned version moves (refs #1760)
- LSP resync timeout no longer blames a server still spawning (closes #1766)
runtime-session.test.tsno longer flakes under CI contention (closes #1767)- Genuine pull timeouts now count in the degradation ledger (#1771)
index-loop-block-wiringcase (a) no longer times out flakily under load (closes #1772)- Diagnostic pulls no longer dispatch once the caller's budget is exhausted (#1773)
- A pull timeout's abandoned request now traces server rejections, not just late answers (#1774)
- Two more
index-*-wiringtest files budget their cold import (closes #1778) session_startself-heals cachedExports after a starved sequence read (closes #1785)workspace/symbolno longer goes to LSP servers that never advertised it (refs #1789)blocker_freshness_sweep's population excludes cache-served diagnostic rows (closes #1790)- Clean workspace-diagnostics cache entries no longer replay across a dependency edit on a cold session
lens_diagnosticsno longer double-counts error findings (closes #1799)callHierarchy/incomingCallsandoutgoingCallsno longer go to servers that never advertisedcallHierarchyProvider(closes #1803)- Biome findings can now reach actionable warnings
workspaceSymbol's no-filePathbranch now picks a client that actually supports it (refs #1812)- A warm session's dependency index no longer vacuously clears files it never scanned
- Actionable-warning and code-quality-warning ids now canonicalize the file path like disposition anchors already did
- Session-state conformance coverage catches a new latch landing inside an already-registered file (refs #1817)
- ast-grep-napi LSP supersede gate B tests now pin the gate, not the fallback (closes #1830)
require-safety-comment-for-as-unknown-as'sSAFETY:valve no longer exempts every later cast in the same block (closes #1834)- Workspace-wide capability checks now describe every live client, not just the first (closes #1846)
require-safety-comment-for-as-unknown-as'sSAFETY:valve now accepts a comment above an exported, class-field, or enum-member cast (closes #1847)- Resource sampling distinguishes failed process-table queries from empty samples (closes #1863)
- Ignore zero-byte freshness reads (refs #1865)
- Reuse knip results for unchanged project content
- Identify TypeScript diagnostic sequence records
- Accept SAFETY comments on object-literal members (refs #1870)
- javac fallback skips classpath-less compiles inside Maven/Gradle projects (closes #1877)
- Tally verified relative-path attribution guesses instead of logging one record per read (refs #1884)
- Keep context-free compiler findings non-blocking (closes #1885)
- Unverified path guesses remain visible (refs #1886)
- The widget count now includes project self-scan findings
- Formatter PATH availability re-arms at session start (closes #1895)
- Coverage-marker dedupe key sorts with an explicit code-unit comparator.
- Stale workspace-diagnostics cache entries now expire
- A clean re-answer now clears a cached diagnostics entry
- Surface silent LSP scanners to the agent (refs #1867)
- Heal the LSP view after an untracked disk edit
no-non-null-assertionnarrows two more idiom shapesno-unknown-returnsdrops its callback/type-alias arm- Orphan backstop: off the session-start critical path, with verified kills (closes #1857)
- Preserve pyright's information severity and fix its diagnostic positions in dispatch (closes #1802)
- Eight ast-grep rules stop flagging correct code
- Seven linters no longer report a clean file after a failed run
- Project snapshot misses now name the rejecting gate (refs #1858)
- Tree-sitter cache now spans a full-project scan
- Two error-tier ast-grep rules now run in the CI self-scan
Security
- A cascade sweep no longer blacks out the security scanner, and a blackout no longer reads as clean (closes #1459)
- A stalled
gh auth tokenprobe no longer disables zizmor's online audits for the session (closes #1535) - Directory-scanning security lanes no longer scan pi-ecosystem scratch trees, and gitleaks recognizes placeholder secrets (closes #1562)
🙏 Thanks
Thanks to the external contributors in this release: