Skip to content

feat(log-viewer): inspector, grid ownership and VS Code web support - #7

Closed
lukecotter wants to merge 61 commits into
mainfrom
refactor-inspector-tab-controller
Closed

lukecotter wants to merge 61 commits into
mainfrom
refactor-inspector-tab-controller

Conversation

@lukecotter

Copy link
Copy Markdown
Owner

📝 PR Overview

The inspector work and everything that landed alongside it: 61 commits, 268 files. Pushed and opened for review as a whole, rather than left only on a laptop.

Written up from the commit history — worth a read-through before merging, since the branch spans several concerns.

🛠️ Changes made

Inspector

  • Variables in scope at the selected frame, a class instance opened in place, and a comparison across a merged row's calls.
  • Sections arranged and sized; one wiring call per tab; the inspector's mark and the tab it points at kept in step.
  • A pick marks every row it names, not just the rendered ones, and points at one row rather than the chain above it.

Timeline

  • A selected frame is outlined instead of the chart being dimmed; the frame the inspector picks is brought into view.
  • The chart spans the whole log; resizes are smooth; governor limits come only from the log.

Grids

  • One owner for the columns, one helper for a grid's body, the located row styled once instead of in six grids.
  • Search highlights kept in step with the rows on screen; a row marked without a rebuild.

Lifecycle

  • The find bus, the inspector wiring and document/window listeners all tied to the connected lifetime, with a controller for the listeners.
  • The call tree rebuilt after a re-attach; a visibility wait releases its listener.

Performance

  • Call Tree grids 24% faster; the minimap skyline built once per log rather than once per pixel; no grid header re-render on every row selection.

VS Code web

  • A web entrypoint, the extension bundled as a single file, browser log viewer assets embedded, and URI-safe file access through workspace.fs.

🧩 Type of change (check all applicable)

  • 🐛 Bug fix - something not working as expected
  • ✨ New feature – adds new functionality
  • ♻️ Refactor - internal changes with no user impact
  • ⚡ Performance Improvement

🔗 Related Issues

See the individual commits; several carry their own issue references.

✅ Tests added?

  • 👍 yes

📚 Docs updated?

  • 🔖 CHANGELOG.md

Anything else we need to know? [optional]

PR #6 stacks on this branch with two fixes for faults introduced here: the find-result panel on the Timeline, and a highlighted frame that could be lost on some themes. Merge this one first.

lukecotter and others added 30 commits August 28, 2026 13:21
…ry (certinia#972)

# 📝 PR Overview

After certinia#970 the interned keys sat on `LogStore` while the paths they step
through sat in `KeyPathIds`. Nothing tied a cached key id to the table
that minted it, a stack id could be stepped into a path that means
nothing, and a test double had to mirror three coupled facts to work at
all.

One object now owns the keys, their per-event memo, the stack keys and
the paths, and states the invariant its callers rely on: a row's id is
the interned chain of the frames the row holds. Tidying it also dropped
work and memory.

| 100MB log (864k lines, 431k calls) | Before | After |
| --- | --- | --- |
| Bottom-Up build | 508ms | **458ms** |
| Aggregated build | 124ms | **121ms** |
| Mark a 42,433-occurrence pick | 75ms | **61ms** |
| Per-event key cache | 2 arrays, 3.4MB, filled up front | **1 array,
1.7MB, filled on use** |

## 🛠️ Changes made

- A bucket key (`type|namespace|text`) holds its stack key
(`namespace|text`), so a stack id is derived from a key id and kept per
signature rather than per event. That removes the second per-event
array, and the two id spaces are separate by construction.
- Cache slots hold `id + 1`, so an unset slot reads as 0 and a
zero-initialised array costs nothing until a frame is asked about.
- The mark walks the frames and composes their ids inside the table, so
neither chain direction builds an intermediate array; `prefixesOf` is
deleted rather than left with no caller.
- The scoped aggregation carries one map where it carried three,
dropping an array per recursion level and a lookup per row.
- `eventKeyChain` joins its only dependency in `core/log/eventKeys.ts`,
so `bucketRows` takes one import for one vocabulary.

## 🧩 Type of change (check all applicable)

- [ ] 🐛 Bug fix - something not working as expected
- [ ] ✨ New feature – adds new functionality
- [x] ♻️ Refactor - internal changes with no user impact
- [x] ⚡ Performance Improvement
- [ ] 📝 Documentation - README or documentation site changes
- [ ] 🔧 Chore - dev tooling, CI, config
- [ ] 💥 Breaking change

## 📷 Screenshots / gifs / video [optional]

N/A — nothing changes on screen.

## 🔗 Related Issues

related certinia#113
related certinia#373

## ✅ Tests added?

- [x] 👍 yes

The key, stack-key and both path directions are now tested on the class
that owns them: one id per signature rather than per frame, the stack
key reading through the entry type where the bucket key does not, and a
frame naming one top-down row but one row per caller depth in bottom-up.

## 📚 Docs updated?

- [x] 🙅 not needed

Unreleased inspector work already described by the certinia#113 and certinia#373
entries.

## Anything else we need to know? [optional]

A `WeakMap` keyed by the event was measured as the alternative to the
dense array: 542ms against 458ms for the build and 16MB more held, so
the array stays.

Two fixtures failed during this and it was the fixtures, not the code:
the scoped-tree test double shared one intern table across tests while
its fixtures reuse `eventIndex` values for different frames, so one
test's key was read back for another. A table is per log in production,
so the double now takes a fresh one per test.

Follow-up, unchanged by this: the Call Tree grid still interns its keys
per build (`toBottomUpTree`) or groups by string
(`toAggregatedCallTree`, 335ms), and recovers a row's path by walking
Tabulator tree parents and its occurrences by splitting key strings.
Adopting this vocabulary there retires `bottomUpOccurrences.ts` and
`rowCallChain`.
…llows your row (certinia#973)

# 📝 PR Overview

A merged call-tree row was identified by joining its bucket keys into a
string, which was most of the cost of the grid builds. Separately, a
bottom-up caller row reported the calls it counts rather than the frames
it is, so every caller depth highlighted the same leaf frames however
deep you picked.

The grids now group on the interned key ids the inspector already uses,
and a row now reports the frames it stands for, so stepping down the
callers walks the highlight up the stack. Three navigation bugs found
while walking that change are fixed here too.

## 🛠️ Changes made

- **Grid builds on interned key ids** — both builders take the log's
`KeyPathIds` and group on integers instead of joined key strings. On a
95MB log (864,216 lines, 431,307 calls) `toBottomUpTree` goes 497ms →
377ms and `toAggregatedCallTree` 337ms → 308ms. Medians of four runs;
run-to-run variance on this log is about 50ms, so read the second figure
as directional.
- **A frame outside the log's own index is keyed but not cached** —
`keyIdOf` wrote past the end of its `Int32Array`, which lands as an
ordinary property, so every frame built rather than parsed read back the
first one's id.
- **The Analysis reveal reads no occurrence** — it found its bucket by
scanning the 431,307 occurrences the root buckets hold between them,
then listed every active row again to test one filter. One key compare
over the top-level rows and one boolean read now do it.
- **A bottom-up row highlights its own frames** — `frameEventIndexes`
climbs the row's own path depth from each counted call and dedupes, so
the flame chart and call tree point at the frames the row is. Details
still describes the calls it counts, which ride on a field of their own.
- **The keyboard survives a tree-control click** — the control is not
focusable, so clicking it dropped focus, and the key bindings only
answer while the table body holds it: the arrows scrolled the table
instead of moving through it. Focus now returns on every pointer expand
and collapse, not only the first one before any row is selected.
- **A bucket descent waits for the render it needs** — the descent
skipped the wait entirely for any row already open, so it read empty
children and fell back to that row: picking a deep inspector row landed
on one of its callers and needed a second click. It now waits for any
row whose children have not arrived.
- **Analysis moves to a picked inspector row** — it marked the bucket
but never scrolled to it, because only a finding click revealed. It now
reveals on a sticky locate and then marks, as the Call Tree does.

## 🧩 Type of change (check all applicable)

- [x] 🐛 Bug fix - something not working as expected
- [ ] ✨ New feature – adds new functionality
- [ ] ♻️ Refactor - internal changes with no user impact
- [x] ⚡ Performance Improvement
- [ ] 📝 Documentation - README or documentation site changes
- [ ] 🔧 Chore - dev tooling, CI, config
- [ ] 💥 Breaking change

## 📷 Screenshots / gifs / video [optional]

N/A. Nothing new appears on screen: what changes is build timing and
which frames light up.

## 🔗 Related Issues

None.

## ✅ Tests added?

- [x] 👍 yes
- [ ] 🙅 no, not needed
- [ ] 🙋 no, I need help

## 📚 Docs updated?

- [ ] 🔖 README.md
- [x] 🔖 CHANGELOG.md
- [ ] 📖 help site
- [ ] 🧪 Marked any pre-release-only features
- [ ] 🙅 not needed

Two entries, for the keyboard and navigation fixes. The highlight and
Analysis fixes correct the Inspector, which is unreleased, so they
belong to its existing entry rather than a new one.

## Anything else we need to know? [optional]

**Where to start.** `log-viewer/src/core/log/keyPathIds.ts` carries the
vocabulary; read its class doc first. The two id spaces matter: the
aggregated build composes outermost-first and the bottom-up build
innermost-first, so ids from the two directions must never be compared.

**Two questions, two accessors.** `locatableEventIndexes` is the calls a
row counts, which its totals describe. `frameEventIndexes` is the frames
the row is, which a highlight points at. They differ only for a
bottom-up caller row.

**Test plan.**

- `pnpm lint` and `pnpm test`.
- Call Tree, Bottom Up: expand a method to its callers. Totals and call
counts read as before. Hover depths 2, 3 and 4: the lit frames walk up
the stack a level at a time, and `Called by` names the row hovered.
- Click a row's expand arrow, then press the up and down arrows: the
selection moves and the table does not scroll on its own.
- Aggregated: pick a deep row from the inspector's call tree. It lands
on that row first time, not on one of its callers.
- Analysis: pick a row in the inspector's call tree. The grid scrolls to
the bucket and selects it. Picking a bucket the Show Details filter
hides turns that filter off, as a finding click already did.
- Both themes, and the Inspector docked at the side and at the bottom.

**Known unrelated failure locally.**
`lana/src/services/__tests__/servicesRuntime.test.ts` cannot resolve
`effect` in a worktree that has not been installed since certinia#951. No `lana`
file is touched here.

**Reverted during review.** A first attempt routed that wait through
`RowNavigation`'s pending-render flag. Tabulator dispatches
`renderStarted` and `renderComplete` in one synchronous call, so the
flag always read false where the wait was awaited and the indirection
bought nothing, while its one live branch could only be entered by a
`renderStarted` whose `renderComplete` never came — which one throwing
subscriber causes, since `_dispatch` has no try/catch and five modules
subscribe. The wait would then never settle. The inline wait is back.

**Follow-ups, not in this PR.**

- The reverse direction still marks on the old rule: hovering a frame
marks the rows whose leaf it is, rather than the rows whose own frame it
is. Doing it properly needs a walk of that frame's subtree.
- The reveal-then-mark handler is now shared in shape by four views but
copied in two. `DatabaseView` and `ApexLogTimeline` mark without
revealing, so "does a pick move this view" deserves to be an argument
rather than a property of which handler was copied last.
…step (certinia#974)

# 📝 PR Overview

Picking a row in the inspector's call tree moves the tab's grid to the
bucket it names, and the move re-renders the rows the mark sits on, so
the mark has to be applied after it. The Call Tree applied the mark it
had read *before* the move. Dropping the pick while the move ran cleared
the mark, and the move then put it back with nothing picked; hovering
another row instead had that hover's own mark stripped and never
re-applied, leaving the grid unmarked until the pointer moved again.

The mark now reads what the inspector is pointing at when the move
settles, which is the emphasis the view already keeps, so there is no
second copy of that truth to fall out of step. The same handler was
written four times, once per tab, with the defect in two of the copies;
all four now share one.

## 🛠️ Changes made

- **One handler for four tabs** — `inspectorLocateHandler` in
`log-viewer/src/components/inspectorLocate.ts` replaces the hand-written
`inspector:locate` handlers in `CalltreeView`, `AnalysisView`,
`DatabaseView` and `ApexLogTimeline`. Whether a pick moves a view is now
an argument rather than a property of which handler was copied last.
- **The mark is read, not restored** — the deferred mark takes
`InspectorEmphasis.current()` when the move settles, so a report that
arrived during the move wins and a dropped pick stays dropped. `Escape`
reaches a view as `selection:clear`, which never passes through this
handler, so anything that tracked reports here rather than on the
emphasis would have missed it.
- **A failed move no longer leaks** — the move is awaited in a `try`,
and the mark goes on either way: it says where the frames are whether
the view reached them or not. Previously a rejection surfaced as an
unhandled rejection.
- **`EventDetail<K>`** — exported from `EventBus.ts` so a shared handler
can be typed against one event's payload without lifting that payload
out of `EventMap`, which stays where each event is described.

## 🧩 Type of change (check all applicable)

- [x] 🐛 Bug fix - something not working as expected
- [ ] ✨ New feature – adds new functionality
- [x] ♻️ Refactor - internal changes with no user impact
- [ ] ⚡ Performance Improvement
- [ ] 📝 Documentation - README or documentation site changes
- [ ] 🔧 Chore - dev tooling, CI, config
- [ ] 💥 Breaking change

## 📷 Screenshots / gifs / video [optional]

N/A. What changes is whether a mark is still on screen after a pick
moves the grid.

## 🔗 Related Issues

None.

## ✅ Tests added?

- [x] 👍 yes
- [ ] 🙅 no, not needed
- [ ] 🙋 no, I need help

## 📚 Docs updated?

- [ ] 🔖 README.md
- [x] 🔖 CHANGELOG.md
- [ ] 📖 help site
- [ ] 🧪 Marked any pre-release-only features
- [ ] 🙅 not needed

No entry: the Inspector is unreleased, so this belongs to its existing
entry rather than a new one. The box is ticked to record that it was
considered.

## Anything else we need to know? [optional]

**Where to start.** `log-viewer/src/components/inspectorLocate.ts` is
the whole of it, 46 lines.
`log-viewer/src/components/inspectorEmphasis.ts` is deliberately
untouched: it stays pure state, and the new module composes it.

**Test plan.**

- \`pnpm lint\` and \`pnpm test\`.
- Call Tree tab, inspector Call Tree → Bottom Up. Click a caller row,
then press \`Escape\` before the scroll settles: the mark must stay
gone.
- Same again, but hover a different inspector row instead of pressing
\`Escape\`: the hovered row's frames must be marked once the move
settles, not the picked row's, and the grid must not be left unmarked.
- Timeline: hover and pick inspector rows. The chart dims around them
and must not pan.
- Database: hover and pick. Statement rows mark, and the grid must not
scroll.
- Analysis: pick moves the grid and marks. Hover marks only.
- \`Escape\` on each tab clears the selection and any held mark.

**Known unrelated failure locally.**
\`lana/src/services/__tests__/servicesRuntime.test.ts\` cannot resolve
\`effect\` in a worktree not installed since certinia#951. No \`lana\` file is
touched here, and it passes in CI.

**Follow-ups, not in this PR.**

- **The grid mark is a one-shot DOM sweep.** \`LocatedRowMarker.mark\`
adds a class to the rows present at that instant, and the row formatters
stamp the row id but never re-apply the class, so scrolling a grid while
a picked inspector row is lit loses the mark. Making the marker hold the
wanted id set and having the formatter apply the class would fix that
and delete the await-then-mark ordering this PR gets right by hand.
- **The source filter is now in nine places.** Every
\`DetailSource\`-carrying event is filtered the same way in each view;
an \`eventBus.onSource\` would fold all nine, and with it the four
near-identical \`inspector:reveal\` handlers, so one gesture stops
needing two subscriptions per view.
- **A stale move is not abandoned.** Clicking two inspector rows quickly
lets the earlier move settle last and scroll away from the newer row.
The mark is now correct either way, but the scroll is not; a Tabulator
expand and scroll is not cancellable, so this needs its own approach.
- **Whether the Database grids and the flame chart should move on a
merged pick.** Both can. They do not today, and the shared handler makes
that an explicit argument rather than an accident, but changing it is a
product decision.
… rendered ones (certinia#975)

# 📝 PR Overview

The mark that shows where an inspector row's frames sit was a one-shot
DOM sweep over the rows a table had rendered. Tabulator builds a row's
element on its first render, so the sweep could not reach a row that had
never been on screen. Pick a row, then scroll down to a marked row below
the viewport or expand a tree row whose children are built afterwards,
and those rows arrive unmarked.

The mark now belongs to the table rather than to a list of elements: the
marker records the ids it wants, and the row formatter lights a row as
it stamps it. That also removes the reason a pick's mark had to wait for
the view to finish moving, so the handler certinia#974 added loses its ordering,
its awaits and three of its tests.

## 🛠️ Changes made

- **The mark is declarative** — `LocatedRowMarker` records the wanted
ids per table host, and `rowIndexStamper` / `stampRowPath` light a row
as they stamp it. Every `rowFormatter` in the app already routes through
one of those two, so no table factory needed a marker plumbed into it.
- **The sweep un-lights as well as lights** — it toggles rather than
adds. Tabulator re-uses a row's element rather than rebuilding it, so a
row can come back carrying a mark that has since moved, and a view that
switches tables no longer leaves the one it left marked.
- **Mark before moving** — `inspectorLocateHandler` marks, then asks the
view to move, and waits for nothing. A row the move renders lights
itself. Gone with the ordering: the async body, the emphasis read-back,
and the three tests that only covered which report won a race.
- **A failed move is still answered**, so a view that cannot reach a
frame leaves no unhandled rejection.

## 🧩 Type of change (check all applicable)

- [x] 🐛 Bug fix - something not working as expected
- [ ] ✨ New feature – adds new functionality
- [x] ♻️ Refactor - internal changes with no user impact
- [ ] ⚡ Performance Improvement
- [ ] 📝 Documentation - README or documentation site changes
- [ ] 🔧 Chore - dev tooling, CI, config
- [ ] 💥 Breaking change

## 📷 Screenshots / gifs / video [optional]

N/A. What changes is whether a row that was never on screen is marked
when you reach it.

## 🔗 Related Issues

Follows certinia#974, which added the shared handler this simplifies.

## ✅ Tests added?

- [x] 👍 yes
- [ ] 🙅 no, not needed
- [ ] 🙋 no, I need help

Four new `LocatedRowMarker` cases: a row arriving after the mark lights
itself, a re-used element loses a stale mark, a table nothing has marked
is left alone, and a table the mark has left stops lighting rows.

## 📚 Docs updated?

- [ ] 🔖 README.md
- [x] 🔖 CHANGELOG.md
- [ ] 📖 help site
- [ ] 🧪 Marked any pre-release-only features
- [ ] 🙅 not needed

No entry: the Inspector is unreleased, so this belongs to its existing
entry. Ticked to record that it was considered.

## Anything else we need to know? [optional]

**Where to start.** `log-viewer/src/components/locatedRow.ts` —
`wantedByHost`, `stamp` and `sweep` are the whole mechanism.
`inspectorLocate.ts` is what falls out of it, now 16 lines with no
async.

**What does not happen, since it reads as though it should.** A class on
a row element survives ordinary scrolling: `Row.create()` is guarded by
`this.created`, `Row.initialize()` deletes cells but re-uses the
element, `RowManager.styleRow` adds and removes parity classes rather
than assigning `className`, and our renderer only detaches and
re-attaches the element. The gap is the first render, not a later one.

**Why a walk up the DOM.** `stamp` finds its table by walking parents
until it meets a marked host. The alternative was threading the view's
marker through four table factories to reach the formatters. The walk is
a handful of nodes per row per render, against cell rendering that is
orders of magnitude more, and it keeps the change inside one file.

**Test plan.**

- \`pnpm lint\` and \`pnpm test\`.
- Call Tree tab, inspector Call Tree → Bottom Up. Pick a caller row,
then scroll the grid down past what was on screen: rows the pick names
are marked when you reach them. That is the fix.
- Expand a tree row under a marked row: the children it builds arrive
marked where they should be.
- Pick a row and press \`Escape\` quickly: the mark stays gone,
including on rows you scroll to afterwards.
- Pick a row, then hover a different one: the hovered row's frames end
up lit.
- Timeline dims without panning; the Database grids mark without
scrolling; Call Tree and Analysis move and mark.
- Both themes, Inspector docked at the side and at the bottom.

**Known unrelated failure locally.**
\`lana/src/services/__tests__/servicesRuntime.test.ts\` cannot resolve
\`effect\` in a worktree not installed since certinia#951. No \`lana\` file is
touched here, and it passes in CI.

**Follow-ups, not in this PR.**

- **The source filter is in nine places.** Every
\`DetailSource\`-carrying event is filtered the same way in each view;
an \`eventBus.onSource\` would fold all nine, and with it the four
near-identical \`inspector:reveal\` handlers, so one gesture stops
needing two subscriptions per view.
- **A stale move is not abandoned.** Clicking two inspector rows quickly
lets the earlier move settle last and scroll away from the newer row.
The mark is right either way; the scroll is not, and a Tabulator expand
and scroll is not cancellable.
- **Whether the Database grids and the flame chart should move on a
merged pick.** Both can. The shared handler makes that an explicit
argument rather than an accident, but changing it is a product decision.
# 📝 PR Overview

certinia#975 explained the row mark with a mechanism that does not exist: that
the renderer de-initialises a row scrolled out of view and rebuilds it,
dropping the class. A reader who trusts that comment would expect an
ordinary scroll to lose a mark, and would look in the wrong place when
the mark misbehaves.

What actually happens: `Row.create()` is guarded by `this.created`,
`Row.initialize()` deletes cells but re-uses the element,
`RowManager.styleRow` adds and removes parity classes rather than
assigning `className`, and our renderer only detaches and re-attaches
the element. A class on a row element survives scrolling. The gap the
declarative mark closes is the **first** render: a row that has never
been on screen has no element, so a sweep of what is rendered cannot
reach it.

## 🛠️ Changes made

- Correct the `wantedByHost` comment to name the real gap: a row below
the viewport, or a tree child built after the mark was set.
- Rename one test from "as a scroll back brings one" to "as scrolling to
a new one does", and correct its helper comment, so the test says which
case it guards.

## 🧩 Type of change (check all applicable)

- [ ] 🐛 Bug fix - something not working as expected
- [ ] ✨ New feature – adds new functionality
- [ ] ♻️ Refactor - internal changes with no user impact
- [ ] ⚡ Performance Improvement
- [x] 📝 Documentation - README or documentation site changes
- [ ] 🔧 Chore - dev tooling, CI, config
- [ ] 💥 Breaking change

## 📷 Screenshots / gifs / video [optional]

N/A.

## 🔗 Related Issues

Corrects comments added in certinia#975.

## ✅ Tests added?

- [ ] 👍 yes
- [x] 🙅 no, not needed
- [ ] 🙋 no, I need help

Comments and one test name. The nine `LocatedRowMarker` tests still pass
unchanged.

## 📚 Docs updated?

- [ ] 🔖 README.md
- [ ] 🔖 CHANGELOG.md
- [ ] 📖 help site
- [ ] 🧪 Marked any pre-release-only features
- [x] 🙅 not needed

Nothing user-visible changes.

## Anything else we need to know? [optional]

No code changes: 6 insertions and 6 deletions, all inside comments and
one `it` title.
…rtinia#977)

# 📝 PR Overview

Three events reach every tab's view and each view answered only its own,
so the same `detail.source === '<tab>'` test sat in nine places. Behind
that was a bigger repeat: all four views subscribe to the same three
events, hold three nullable unsubscribe fields, and undo them one at a
time in teardown. `ApexLogTimeline` spent twelve lines on it.

The bus gains `onSource(event, source, callback)`, which delivers only
what names a tab. On top of that, `wireInspectorTab` names the set of
three once and returns one unsubscribe, so a view supplies only what it
does differently. Net 90 insertions against 291 deletions.

## 🛠️ Changes made

- **`eventBus.onSource`** — a `SourcedEvent` type admits only the
payloads that name a tab, so the source test lives on the bus. No cast
is needed: `EventMap[K]` already resolves to the union of sourced
payloads.
- **`wireInspectorTab(source, emphasis, sync)`** — one call per view,
one unsubscribe. A view gives `mark`, `reveal`, `clear`, and
`movesToMergedPick` where a picked row that merges occurrences should
also move.
- **One `reveal` for both kinds of pick.** The Call Tree and Analysis
views were passing the same method twice, once for a single frame and
once for the first of several. `movesToMergedPick` now says *when* it
moves, and the helper catches a rejection, so no view needs `void` on a
promise.
- **`inspectorLocate.ts` is gone**, absorbed into `inspectorTab.ts`. Its
doc no longer has to ask the caller to subscribe it a particular way,
since the module does the subscribing.
- **Twelve unsubscribe fields become four**, and four teardown blocks
lose about thirty lines between them.

## 🧩 Type of change (check all applicable)

- [ ] 🐛 Bug fix - something not working as expected
- [ ] ✨ New feature – adds new functionality
- [x] ♻️ Refactor - internal changes with no user impact
- [ ] ⚡ Performance Improvement
- [ ] 📝 Documentation - README or documentation site changes
- [ ] 🔧 Chore - dev tooling, CI, config
- [ ] 💥 Breaking change

## 📷 Screenshots / gifs / video [optional]

N/A. Nothing changes on screen.

## 🔗 Related Issues

Follows certinia#974, certinia#975 and certinia#976, which built the inspector mark this wiring
carries.

## ✅ Tests added?

- [x] 👍 yes
- [ ] 🙅 no, not needed
- [ ] 🙋 no, I need help

Nine `wireInspectorTab` cases driven through the real bus, and three for
`onSource`. Three guards were proven by reverting the code they cover:
returning only the first unsubscribe, dropping the `movesToMergedPick`
gate, and swapping mark with move each fail a test. The last needed an
ordered log, since two separate lists cannot show order; the ordering
had no test before this.

## 📚 Docs updated?

- [ ] 🔖 README.md
- [ ] 🔖 CHANGELOG.md
- [ ] 📖 help site
- [ ] 🧪 Marked any pre-release-only features
- [x] 🙅 not needed

Nothing user-visible changes.

## Anything else we need to know? [optional]

**Where to start.** `log-viewer/src/components/inspectorTab.ts` is the
whole mechanism, then any one view to see what a caller now looks like.

**What was deliberately left.** `SourcedEvent` also admits
`detail:select`, `detail:view` and `detail:locate`. Those must **not**
be filtered by source: the inspector records every tab's selection, so
filtering would lose the tab it is not showing. The type's doc says so,
since the constraint belongs to the caller rather than the type.

**Test plan.**

- \`pnpm lint\` and \`pnpm test\`.
- In each of the four tabs, with the Inspector open: hover an inspector
row and the tab marks; pick one and the Call Tree and Analysis grids
also move, while the Database grids and the flame chart only mark.
- Pick a row, then \`Escape\`: the tab's own selection and the mark both
go.
- Switch tabs with a mark set: the tab you left stops marking, and the
one you arrive at answers.
- Both themes, Inspector docked at the side and at the bottom.

**Known unrelated failure locally.**
\`lana/src/services/__tests__/servicesRuntime.test.ts\` cannot resolve
\`effect\` in a worktree not installed since certinia#951. No \`lana\` file is
touched here, and it passes in CI.

**Follow-ups, not in this PR.**

- **Two subscriptions still carry no source.**
\`DatabaseTimeTree.ts:205\` and \`:210\` answer \`detail:locate\` and
\`selection:clear\` from every tab, so a Timeline hover marks rows in
the Database tab's time tree and Escape anywhere drops that table's
pick. \`onSource\` makes the fix one word, but narrowing it changes
behaviour, so it wants its own change.
- **All four views subscribe in the constructor and release in
\`disconnectedCallback\`**, so a Lit element that is detached and
re-attached comes back with dead subscriptions. Pre-existing, and
unchanged here.
- **A stale move is not abandoned.** Clicking two inspector rows quickly
lets the earlier move settle last and scroll away from the newer row.
On a log the size cap cut off, the header said 27.1s and the chart drew
10.8s. Three fixes follow from that one gap.

### Timeline length

The chart's width came from the last frame the log recorded, not the
log's own end. It now spans the whole log, so the truncation marker
shades the part the log never recorded.

### Hot spots

The log is a container, not code, but it holds unrecorded time as self
time — 16.3s on this log — which put it top of the Inspector's hot spots
and of the Analysis findings. It is now left out of both, as it already
was everywhere else.

### Governor limits strip

Where a log records nothing — the size cap, or skipped lines — the strip
carried its last reading across the gap as though it had been measured.

The gaps come from the log's own skip markers and ride on the metric
series, so the strip has one source for them. The area fills, the
over-100% band and the collapsed traffic light leave a gap blank, the
step line holds its last level, and the tooltip names the reason and the
range, such as `Max-Size-reached · 10.8s → 27.1s`.

The strip's marker bands now take the layout the chart and the minimap
share, so a point marker keeps a visible hairline and shading ends with
its own marker instead of running on to the next one.

### Testing

`pnpm lint` and `pnpm test` pass. New tests cover the range the
conversion reports, the log's exclusion from hot spots, gap derivation
from markers, the containment rule, and the area fill breaking at a gap
rather than ramping across it.

Closes certinia#828
…de (certinia#980)

> **Stacked on certinia#977.** Its commit shows in this diff until that merges.
Review from `be6412ea` onward.

# 📝 PR Overview

Two bugs in the inspector's row mark, both about which rows light up.

**A grid row told the inspector the wrong thing.** A row under the
pointer emitted every call it counts, so a Bottom Up caller row marked
the inspector rows for the leaf calls underneath it rather than for the
caller itself. The forward direction stopped doing that in certinia#973; the
reverse direction was still on the old rule, so the two disagreed
depending on which side you pointed at.

**A mark could come back after being dropped.** The sweep reaches only
the rows a table has attached. A row lit while on screen, then scrolled
out, kept the class when the mark moved away, and the renderer
re-attaches such a row without running the row formatter again, so the
stale highlight returned with it.

## 🛠️ Changes made

- **`rowFrames(row, root, direction)`** — a bottom-up caller row climbs
to its own depth, `depthOf(_pathId) - 1` hops above each call it counts.
A top-down row already sits at its frames' depth, so it climbs nothing.
- **`LogStore.framesAbove`** — the climb, next to `stackByEventIndex`,
which already owned this parent-pointer walk. The inspector's
`frameEventIndexes` now reads it too, so the two sides cannot drift.
- **The direction is read at hover time**, from
`directionOf(this.viewMode)`, which the sibling `_emitDetailSelection`
already uses. No new parameter and no second source of truth.
- **`litByHost`** — what each table's mark has lit, whichever half lit
it, so a new mark can un-light an element the renderer has since
detached.
- **The `detail:locate` doc** described the old rule; it now says what
the protocol carries.

## 🧩 Type of change (check all applicable)

- [x] 🐛 Bug fix - something not working as expected
- [x] ♻️ Refactor - internal changes with no user impact
- [ ] ✨ New feature – adds new functionality
- [ ] ⚡ Performance Improvement
- [ ] 📝 Documentation - README or documentation site changes
- [ ] 🔧 Chore - dev tooling, CI, config
- [ ] 💥 Breaking change

## 📷 Screenshots / gifs / video [optional]

N/A. What changes is which rows carry the highlight.

## 🔗 Related Issues

Follows certinia#973, which changed the forward direction, and certinia#975, which
shipped the mark mechanism the second fix corrects.

## ✅ Tests added?

- [x] 👍 yes
- [ ] 🙅 no, not needed
- [ ] 🙋 no, I need help

Three `rowFrames` cases and one for the detached row. Each guard was
proven by reverting the code it covers: dropping the direction check
makes a top-down row climb; removing the shared climb fails one
`rowFrames` test **and** two `frameEventIndexes` tests, which also shows
the inspector test runs the real method rather than a copy of it;
restoring the old clearing fails the detached-row test.

## 📚 Docs updated?

- [ ] 🔖 README.md
- [x] 🔖 CHANGELOG.md
- [ ] 📖 help site
- [ ] 🧪 Marked any pre-release-only features
- [ ] 🙅 not needed

No entry: both fixes correct the unreleased Inspector, so they belong to
its existing entry. Ticked to record that it was considered.

## Anything else we need to know? [optional]

**Where to start.** `LogStore.framesAbove` is the mechanism; `rowFrames`
is the grid's use of it and `frameEventIndexes` the inspector's.

**Why the mark has to remember what it lit.** Tabulator builds a row's
element once (`Row.create()` is guarded by \`this.created\`) and
\`Row.initialize()\` re-uses it, and both \`deinitialize()\` calls in
Tabulator are inside \`reinitializeRows()\`, a column-layout path. So an
ordinary scroll neither rebuilds the element nor re-runs the formatter:
the class persists, and clearing it has to reach elements the query
cannot see.

**On the dedupe.** A merged row aggregates distinct caller frames that
share a signature, so the climb is many-to-many and the answer can be as
long as what was asked about. It is not safe to climb from one call and
assume the rest agree.

**Test plan.**

- \`pnpm lint\` and \`pnpm test\`.
- Call Tree, **Bottom Up**, Inspector open. Hover a bucket row, then a
caller row one level down: the inspector mark moves up the stack with
you rather than staying on the leaf calls.
- Step two and three levels up: one frame per level.
- Analysis: same, hovering a row under a method bucket.
- **Aggregated** and **Time Order**: unchanged, since a row there
already sits at its own frames' depth.
- Hover an inspector row so a grid row lights, scroll that row out of
view, move the pointer off the inspector row, then scroll back: no
highlight. That is the second fix.
- Both themes, Inspector docked at the side and at the bottom.

**Known unrelated failure locally.**
\`lana/src/services/__tests__/servicesRuntime.test.ts\` cannot resolve
\`effect\` in a worktree not installed since certinia#951. It passes in CI.

**Follow-up, not in this PR.** `deriveCalls` already walks each call's
parents inside `chainReaches` and stops exactly at the frame the row is,
then keeps the index and throws the frame away, so `framesAbove`
re-walks the same edges. Fusing the two means having `chainReaches`
return the node it stopped at.
# PR overview

Stack 2 of 4. Depends on certinia#951. Makes log and workspace handling
URI-native so Lana can operate against local and virtual filesystems.

## Changes made

- Replace filesystem paths with VS Code Uri values or serialized URI
strings.
- Route reads, writes, existence checks, caching, and navigation through
URI-safe services.
- Support file, memfs, vscode-vfs, and other virtual workspace schemes.
- Update log analysis, language detection, providers, source lookup, and
workspace selection.
- Update URI mocks and affected unit tests.

## Type of change

- [x] Refactor

## Related issues

related W-23939830

## Validation

- pnpm typecheck
- Seven focused unit suites: 98 tests

---------

Co-authored-by: Luke Cotter <81575432+lcottercertinia@users.noreply.github.com>
Dragging the window or the panel edge made the Flame Chart flash, and
the chart trailed a
frame behind the drag. Four commits, one concern each.

**The flash.** `renderer.resize` assigns `canvas.width`, which wipes the
drawing buffer.
`resize()` cleared all three canvases and booked the repaint for the
*next* frame, so the
frame between composited three blank canvases. It now draws before it
returns.

**The lag.** Observer callbacks are delivered after a frame's animation
callbacks and after
layout, so a resize deferred to the next frame always sized the canvas
to the box the drag
had already left. Because depth 0 sits at the canvas bottom inside an
`overflow: hidden`
box, a fast shrink clipped the bottom frames away rather than merely
lagging. The observer
already coalesces to one delivery per rendering opportunity, so the
frame hop bought no
batching, and nothing inside the observed element can change that
element's height, so
resizing from the callback cannot loop.

**Two things that ran more than once.** A chevron toggle asked the host
to relayout — which
draws — and then asked it to draw again. And the minimap density cache,
which is keyed by
width, was cleared on every resize, so a height-only drag paid a full
recompute per step.

### Measured, 100MB log

| | before | after |
| --- | --- | --- |
| height drag | 23-25ms a step | **2-4ms** |
| chevron toggle | 2 full renders | 1 |
| load | a synchronous render inside `init()` | the booked render stands
|

A width drag is still 75-92ms: a new width is a genuine cache miss, and
`computeDensitySlidingWindow` pushes every frame into every bucket it
spans before
`resolveCategoryFromSkyline` sorts per bucket. That is a separate piece
of work and gets its
own issue.

### Verification

`tsc -b`, eslint and prettier clean; 1983 tests pass, and each commit
compiles on its own.
New `FlameChartResize.test.ts` (7) and `MetricStripToggle.test.ts`
cover: drawing before
returning, dropping a queued frame, re-booking one it could not draw,
skipping an unchanged
geometry, still drawing when only the minimap height moved, and
rendering once per toggle.
Each was checked by reverting its fix and confirming it fails.

Checked by hand in the dev host on a 100MB log: no blank frame at any
size, horizontal and
vertical drags smooth, no blink on the chevron.

Relates to certinia#373. Merge this before the other two timeline PRs — they
touch the same
`scheduleRender`/`render` block.
…g it (certinia#981)

# 📝 PR Overview

The inspector's row mark reached a row two ways: a sweep of the rows
attached when the mark moved, and the row formatter as a row is built.
Neither reaches a row that was built earlier, detached when it scrolled
out of view, and only then named by a mark. The renderer re-attaches
such a row without re-running the formatter, so it comes back with no
mark. Scroll to it, or sort with it just off screen, and the highlight
is simply missing.

The fix watches the arrival: a `MutationObserver` for `childList` on the
element the renderer attaches rows to. A row entering the table is a
child mutation, so a scroll and a structural render are one case, and a
table destroyed and rebuilt into the same container is watched again
rather than going quiet.

## 🛠️ Changes made

- **`watchRenders(host)`** — one observer per marked table, established
on the first non-empty mark. The callback re-sweeps only while a mark is
set, and touches nothing but a class, so it cannot report itself back.
- **Keyed on the row-holding element, not the container.** Several views
destroy the table and build another in the same element;
`CallStackDetail` does it on every event change. Keying on the container
would leave the watch pointing at a destroyed table, and the old
observer is disconnected when a new one takes over.

## 🧩 Type of change (check all applicable)

- [x] 🐛 Bug fix - something not working as expected
- [ ] ✨ New feature – adds new functionality
- [ ] ♻️ Refactor - internal changes with no user impact
- [ ] ⚡ Performance Improvement
- [ ] 📝 Documentation - README or documentation site changes
- [ ] 🔧 Chore - dev tooling, CI, config
- [ ] 💥 Breaking change

## 📷 Screenshots / gifs / video [optional]

N/A. What changes is whether a row carries its highlight when the grid
hands it back.

## 🔗 Related Issues

Completes the row mark from certinia#975 and certinia#980.

## ✅ Tests added?

- [x] 👍 yes
- [ ] 🙅 no, not needed
- [ ] 🙋 no, I need help

Two cases: a row named while detached, and a table rebuilt into the same
container. Each guard was proven by reverting the code it covers — no
watch fails both; watching the spacer's `style` rather than the arrival
fails both; keying so a rebuild is skipped fails the second.

## 📚 Docs updated?

- [ ] 🔖 README.md
- [x] 🔖 CHANGELOG.md
- [ ] 📖 help site
- [ ] 🧪 Marked any pre-release-only features
- [ ] 🙅 not needed

No entry: this corrects the unreleased Inspector, so it belongs to its
existing entry. Ticked to record that it was considered.

## Anything else we need to know? [optional]

**Why not the signals that look more natural.** Two were tried and
rejected with evidence:

- **A scroll listener.** A structural render — sort, filter, column
show/hide, a tree re-expand of children already built — re-attaches an
initialised row with no formatter run and fires no scroll event at all.
The renderer also documents \`scrollend\` as unreliable: "The RAF
stability check deliberately replaces \`scrollend\`, which never fires
while the scrollbar thumb is held still"
(\`VirtualVerticalRenderer.ts:430\`).
- **The virtual spacer paddings.** Reading their values is unsound,
because \`ScrollAnchor\` writes them too, so a value can return to one
already swept while the window has moved. Observing the write instead is
no better: a CSSOM write of an unchanged value queues no mutation record
at all, so a sort at the top of a table reports nothing.

**Cost.** The observer fires when rows enter or leave, which is exactly
when work is due, and only while a mark is set. A sweep reads what the
table has attached — the viewport plus at most \`OVERSCAN_MAX\` rows
each side — never the row count, and the renderer's idle prewarm builds
cells with \`inFragment: true\` so it does not widen that. The callback
runs in a microtask after the render, and touches only \`classList\`, so
it forces no layout.

**Test plan.**

- \`pnpm lint\` and \`pnpm test\`.
- Call Tree, Bottom Up, Inspector open. Click a caller row so grid rows
mark, then **sort a column while at the top of the table**: the marks
survive. That is the case a value-based signal missed.
- Filter and clear it; collapse and re-expand a marked row's parent.
- Scroll past rows never rendered and back. Then click a row, scroll a
lit row out of view, press \`Escape\`, scroll back: no stale highlight.
- Large log with a mark set: scroll hard and watch for jank.
- Both themes, Inspector docked at the side and at the bottom.

**Known unrelated failure locally.**
\`lana/src/services/__tests__/servicesRuntime.test.ts\` cannot resolve
\`effect\` in a worktree not installed since certinia#951. It passes in CI.

**Follow-up, not in this PR.** The renderer already knows which rows it
attached: \`allAttached\` is built in \`_attachRanges\`. Dispatching
that would make relighting O(rows attached) rather than O(rows
rendered), and passing the \`Tabulator\` to \`mark()\` instead of its
element — every one of the eight owners already holds it — would add
disposal on \`tableDestroyed\` and let \`Find\` drop its own scroll
listener onto the same event.
… screen (certinia#985)

# 📝 PR Overview

Search in the grids drifted from what the screen showed. Rows brought in
by a
scroll, a sort or a filter arrived with no highlight in them; expanding
or
collapsing a tree row cleared the search outright; hidden columns were
counted,
so the total led to matches nobody could reach; and the match you were
on read
the same as the rest.

The renderer now announces every attach and Find takes Tabulator's own
scroll
event, so every grid is covered whichever renderer it runs. The views
compare
the row order itself, and drop the search only where the match numbering
stops
describing the table.

## 🛠️ Changes made

- `VirtualVerticalRenderer` announces each attach, and `Find` rebuilds
once per frame — the rebuild reads every cell on screen.
- `Find` also takes Tabulator's `scrollVertical`, which the stock
renderer reports too, so the SOQL, DML and SOSL grids highlight on
scroll again.
- The search covers only the columns on show, and the highlights follow
the same set.
- New `onTableReshaped` helper: the row order is compared, so an expand
is not read as a sort. It reads `dataSorting`, not `dataSorted`, which
would make Tabulator build a row component per sorted row.
- The views drop the search on a real sort, a grouping either way round,
a filter change, or a column going on or off show.
- The current match takes `editor.findMatchBackground`, the rest
`editor.findMatchHighlightBackground`, foreground included.

## 🧩 Type of change (check all applicable)

- [x] 🐛 Bug fix - something not working as expected
- [ ] ✨ New feature – adds new functionality
- [ ] ♻️ Refactor - internal changes with no user impact
- [x] ⚡ Performance Improvement
- [ ] 📝 Documentation - README or documentation site changes
- [ ] 🔧 Chore - dev tooling, CI, config
- [ ] 💥 Breaking change

## 🔗 Related Issues

related #

## ✅ Tests added?

- [x] 👍 yes

`pnpm test`: 1582 tests, 131 suites. Each new test was proven by
removing its fix.

Manual, 19.7MB sample log: expand and collapse hold the count and light
the rows they open; a column view change and a grouping turned off both
clear the search; a hidden column contributes no match, and a shown one
does.

## 📚 Docs updated?

- [x] 🙅 not needed
…nia#983)

The governor limits strip lost its hover as soon as the pointer left the
canvas, so the
crosshair and the chevron highlight flickered along the strip's edges.
The gaps either side of
the strip are its own layout, not somewhere the hover should end.

**What changed.** The hover engages when the pointer is on the strip and
survives into the two
gaps. Each of the three boxes has its own listener, so the box that
heard the move is the whole
test — no rectangle maths, and no cached rect to go stale after a
resize.

`strip-pointer.ts` is now chevron-only: `holdsStripHover` and its
`HOVER_BAND` band went with
the cached rect, because a band that guesses where the strip ends is
exactly what the listener
already knows.

**The cursor.** A click centres the crosshair and the wheel zooms it,
and the toggle column
does neither, so the toggle column now reads as a pointer over its whole
width rather than a
crosshair that does nothing.

`canvasRect`, `getCanvasRect()`, `mouseX` and `mouseY` are gone; the
handlers read
`event.offsetX` directly, which the gaps can share because they sit on
the strip's left edge.

### Verification

`tsc -b`, eslint and prettier clean; 1980 tests pass.

By hand in the dev host: the crosshair holds along the whole strip
including the gaps, the
chevron highlights only over the chevron, and the pointer changes over
the toggle column.

Relates to certinia#373. Merge after the resize PR — both touch
`MetricStripOrchestrator`.
certinia#984)

Clicking a frame dimmed the rest of the chart, and the hover wash and
the tooltip went stale
whenever the frames moved under a still pointer. Chrome DevTools' Flame
Chart is the reference:
a select outlines, a hover washes, and dimming is reserved for a search
or an insight — the
cases where the chart is telling you a set of frames does not match.

**Select outlines.** A click now outlines the frame and leaves the rest
of the chart at full
strength. Dimming stays for the inspector's match sets, which is what it
is for.

**The wash follows the frames.** Panning, zooming and resizing all move
frames under a
stationary pointer, and the last hit answer expires the moment they do.
It is now re-derived
straight after culling — one rule that covers every viewport write,
instead of one per input.
The re-hit has to happen there: at the end of `render()` it sat inside
the animation frame, so
the repaint it asked for was swallowed by the frame already running.

**A drag points at nothing.** A held button means the pointer is
operating the view, not
pointing at a frame, so any drag — pan, measure, area zoom or minimap
resize — clears the wash
and the tooltip, and the first render after it ends washes whatever it
settled on. Wheel and
keyboard moves keep the hover live, because the pointer is still resting
on content.

This also fixes a mirror defect nobody had reported: a measure or
area-zoom drag used to freeze
a stale wash that then slid away from the pointer.

**One clear.** `pickEmphasis(undefined)` read as picking nothing; it is
now `clearEmphasis()`.
And `HoverHighlightRenderer` skips its `clear()` when no wash is on
screen, because PIXI marks
the `Graphics` dirty on every clear.

### Verification

`tsc -b`, eslint and prettier clean; 1993 tests pass. New
`HoverRehit.test.ts`,
`HoverTracker.test.ts` and `HoverWash.test.ts`;
`chart-select-dim.test.ts` rewritten to record
each emphasis call. The re-hit placement was proven by moving it back
and watching the suite
fail.

By hand in the dev host on a 100MB log: select outlines with no dim, the
wash tracks the frames
through a pan and a zoom, no wash or tooltip during any drag, and both
return on the first move
after it.

Relates to certinia#373. Merge last — it touches the same
`scheduleRender`/`render` block as the resize
PR, so it needs a rebase once that lands.
…ertinia#988)

# PR overview

Follow-up to certinia#952. Plain file I/O went through
`@salesforce/vscode-services`' `FsService`, which
throws until `initServices()` has run — and nothing runs it outside
`RetrieveLogFile`.

/cc @peternhale — raising this here rather than on certinia#952 so your stack
keeps moving. `certinia#953`'s
`"type": "module"` question (below) is still yours; it is not touched
here.

## The bug

`LogView.getFile()` read the extension's **own bundled
`out/index.html`** through `FsService`.
`getServicesApi()` throws `Salesforce Services is not initialized.`
unless `initServices()` has
run, and the only path to it is `ensureServicesAvailable()` from
`RetrieveLogFile.ts`. So
`createView` rejected and the analysis view never opened, in any session
where Retrieve Log had
not been run first.

`LogEventCache.getApexLog` hit the same throw and swallowed it in its
own `catch { return null }`,
silently disabling folding, document symbols, sticky scroll and the
cursor-line decoration.
`ShowLogAnalysis` and `RawLogNavigation` were affected too.

Why CI stayed green: every suite covering these paths `jest.mock`ed
`../../services/salesforceServices.js` — mocking out the module that
throws.

## Changes made

- Add `lana/src/fs/workspaceFs.ts` — `readFileText` / `writeFileText` /
`fileOrFolderExists` over
`workspace.fs`. URI-native, works unchanged in the web extension host,
needs no other extension
  and no initialisation. This is already the majority pattern from certinia#952
(`ApexLogLanguageDetector`, `SfdxProjectReader`); the service-based file
I/O was the outlier.
- Point `LogView`, `ShowLogAnalysis`, `RawLogNavigation` and
`LogEventCache` at it.
- `LogEventCache.getApexLog` now takes a `Uri` rather than a URI string,
since `workspace.fs`
needs one. The cache stays keyed on `uri.toString()`, so the four
callers just drop
  `.toString()`.
- Delete the now-unused `salesforceServices.readFile` and its probe in
`isSalesforceServicesApi`.
Salesforce Services keeps `listLogs`, `getLogBody` and the
`RetrieveLogFile` write, which are
  genuine org operations behind `ensureServicesAvailable()`.
- Stop mocking the file-I/O layer in the affected suites; they drive
`workspace.fs` instead, so
  reintroducing the dependency fails loudly.

`Main.ts` is unchanged — activation stays decoupled from Salesforce
Services, and is now correct
rather than broken.

## Type of change

- [x] Bug fix

## Related issues

related W-23939830

## Validation

- `tsc -b lana` clean; `eslint lana/src` clean
- 329 tests pass across 20 suites
- Regression proof: reverting `LogView.ts` and `salesforceServices.ts`
to their merged state makes
`LogView.test.ts` fail with `Salesforce Services is not initialized.`;
restoring them passes.
The suite now also asserts the webview HTML is actually rewritten, which
it never checked before.

## Deliberately not in scope

Kept to the one blocking defect so it can land quickly. To follow:

- The detector's `workspace.fs.readFile` reads the whole file to decode
4 KB (0.056ms -> 2.9ms and
a 163MB RSS peak on the 19.7MB sample, on every tab-change event) — the
thread on certinia#952 is still open.
- Dropping the `scheme: 'file'` selectors means `warmAndSignal` now
eagerly parses diff sides.
- The save dialog defaults into the extension's install directory when
no workspace folder is open.
- The webview still sends a now-ignored `openPath` payload.
- New suites for `RawLogNavigation` and `ShowLogAnalysis`, which have
none.
…above it (certinia#991)

# 📝 PR Overview

Pointing the inspector at one frame lit its bucket **and** one row per
caller
depth, so a single frame read as a whole chain selected. A move could
also land
on a row the pointer had already left, because a move waits on a render
and a
pointer crossing inspector rows asks for one per row.

A bottom-up row is the frame at its own depth, so a frame now marks the
rows its
own key heads: its bucket, and any caller row for it under another
bucket. The
wiring holds one move, and a new one abandons the one before it.

**Stacked on certinia#985 — merge that first.**

## 🛠️ Changes made

- `pathsEndingIn` names the rows a frame stands for; `pathIdsOf` becomes
`pathIdOf`, top-down only.
- The paths a key heads are indexed as they are minted, so the mark
costs what it returns rather than a scan of every path the log has
minted.
- One move at a time: `wireInspectorTab` holds an `AbortController`, and
the two views that await check it before they scroll. The mark is never
dropped, only the move.
- A caller row's calls and its frames come from one walk of its bucket,
held in one cache — the walk that decides membership already stands on
the row's own frame.
- `LogStore.framesAbove` keeps its remaining caller in the inspector's
scoped tree.

## 🧩 Type of change (check all applicable)

- [x] 🐛 Bug fix - something not working as expected
- [ ] ✨ New feature – adds new functionality
- [ ] ♻️ Refactor - internal changes with no user impact
- [x] ⚡ Performance Improvement
- [ ] 📝 Documentation - README or documentation site changes
- [ ] 🔧 Chore - dev tooling, CI, config
- [ ] 💥 Breaking change

## 🔗 Related Issues

related #

## ✅ Tests added?

- [x] 👍 yes

`pnpm test`: 1588 tests, 131 suites. Each new test was proven by
removing its fix.

Measured in a browser on the 19.7MB sample log, Bottom-Up with a bucket
expanded to four callers: hovering that bucket's frame marks 1 row,
hovering a caller frame marks its own 1 row, and a frame no rendered row
stands for marks none. Before, the first of those marked five.

## 📚 Docs updated?

- [x] 🙅 not needed
…tinia#969)

Follow-ups to certinia#951.

- Restore the full Apex log list. `ApexLogService.listLogs` needs an
explicit limit and the migration passed none, so the picker showed 25
logs.
- Stop loading Salesforce Services on shutdown. `deactivate()` imported
the services module to dispose it, so every window close pulled in a 129
KB chunk even when no log was retrieved.
- Open the log panel before retrieving the log. The panel appears at
once again, and a large log streams from disk instead of crossing the
webview message channel.
- Remove `docs/pr-951-952-review-findings.md`.

1982 tests pass; type check, lint and format are clean.
…ction (certinia#994)

# 📝 PR Overview

An arrow key and a row click both blocked the table's redraw around the
selection change. Selecting a row sets a class and reports the change,
while
restoring a blocked redraw re-aligns the header and re-renders every
column, so
each keystroke paid a write/read/write layout cycle per column plus a
renderer
resize — on grids of 500k rows and up to 14 columns.

The four key bindings that paid it also repeated the same preamble four
times,
so the rule they share now has one home.

**Stacked on certinia#991 — merge that first.**

## 🛠️ Changes made

- No redraw block around a selection change, on the keys or on a click:
nothing in the webview listens for the redraw-block events, so it only
bought that work.
- One `keyedTable` for "is this key mine": the option, and the body as
the event target. The rule is unchanged, and it now reads the option
through the table's own typed options, which drops the last
`@ts-expect-error` in the file and the todo that asked for it.
- `previousRow` and `nextRow` differed only in which way they step, so
they share a factory; the deselect, select and keep-in-view tail is one
call.
- Docs corrected: `takeFocusBack` said the bindings answer only while
the body is the target as its own justification, the class header
described a different module and an option that does not exist, and
`collapseRow` pointed at a comment `expandRow` did not have.

## 🧩 Type of change (check all applicable)

- [ ] 🐛 Bug fix - something not working as expected
- [ ] ✨ New feature – adds new functionality
- [x] ♻️ Refactor - internal changes with no user impact
- [x] ⚡ Performance Improvement
- [ ] 📝 Documentation - README or documentation site changes
- [ ] 🔧 Chore - dev tooling, CI, config
- [ ] 💥 Breaking change

## 🔗 Related Issues

related #

## ✅ Tests added?

- [x] 👍 yes

`pnpm test`: 1596 tests, 131 suites. The bindings had one test between
them and now have nine, covering both siblings, the option gate, a key
from the tree control, the `dataTree` guard, stepping into a child and
out to a parent, and the code-driven collapse. Two were proven by
removing the rule they pin.

## 📚 Docs updated?

- [x] 🙅 not needed

---------

Co-authored-by: Luke Cotter <81575432+lcottercertinia@users.noreply.github.com>
# PR overview

Stack 3 of 4. Depends on certinia#952. Adds the VS Code Web extension entrypoint
and browser bundles.

## Changes made

- Declare the browser entrypoint and virtual-workspace capabilities.
- Share activation and disposal behavior between desktop and browser
extension hosts.
- Add CommonJS browser bundles to Rollup and Rolldown.
- Preserve the existing desktop extension entrypoint and bundle.

## Type of change

- [x] Feature
- [x] Chore

## Related issues

related W-23939830

## Validation

- pnpm build
- Desktop and browser extension bundles generated successfully
# PR overview

Stack 4 of 4. Depends on certinia#953. Adds automated VS Code Web coverage and
local browser-host tooling.

## Changes made

- Add Playwright coverage that opens a sample log from Explorer in VS
Code Web.
- Verify the analysis webview and populated Call Tree render.
- Add the local headless VS Code Web server and serve:web workflow.
- Run the web E2E suite for pull requests and retain Playwright
diagnostics as CI artifacts.
- Keep Playwright output isolated from Jest, ESLint, and source control.

## Type of change

- [x] Test
- [x] Chore

## Related issues

related W-23939830

## Validation

- pnpm typecheck
- pnpm test:ci
- pnpm lint
- pnpm build
- pnpm test:e2e:web: 1 passed
- Fork CI: all six jobs passed
# PR overview

Follow-up to certinia#954. Fix web e2e + trims the job.

- Replace the e2e workspace log with a 28 line fixture, exempt from LFS.
- Upload the Playwright report and traces only when the e2e fails, and
keep them 7 days not 14.

## Why the e2e failed

`.gitattributes` keeps every `*.log` in LFS. The `e2e` job checks out
without `lfs: true`, so
`createLogWorkspace()` copied a 130 byte pointer into the test workspace
and not text e.g

```
version https://git-lfs.github.com/spec/v1
oid sha256:f5fbbb9b17e9b614ac08e0e1bfd48aeb227e6c5cfba197b882e5d34a939a3bd3
size 19739334
```

That is not an Apex log, so `lana.isApexLog` stayed false and `Log: Show
Apex Log Analysis`
never appeared in the command palette. All three attempts failed the
same way.

A fixture is better than `lfs: true`: no LFS bandwidth on every run, and
the job gets faster.
`sample-app/debug-logs/sample-log.log` is unchanged and still available
for manual work.

## The fixture

A slice of `sample-log.log`: header, `USER_INFO`, `EXECUTION_STARTED`,
`CODE_UNIT_STARTED`
and the `AccountService.getRevenue()` subtree. 19,739,334 bytes to
2,418.

It parses into a 14 node tree over 5 levels with no log issues, so the
Call Tree assertion has
plenty of rows:

```
LOG_ROOT
  EXECUTION_STARTED
    execute_anonymous_apex
      AccountService.AccountService()
      AccountService.createAccountsAndContacts()
        AccountService.getRevenue()
          AccountService.getDayValue(Date)
            System.Math.mod(Integer, Integer)
          ...
```

Drop `120_000` timeouts to `30_000` 


## Type of change

- [x] Bug fix
- [x] Test
- [x] Chore
…ectory with 9 updates (certinia#993)

Bumps the development-dependencies group with 9 updates in the /
directory:

| Package | From | To |
| --- | --- | --- |
|
[@swc/core](https://github.com/swc-project/swc/tree/HEAD/packages/core)
| `1.15.47` | `1.16.1` |
| [concurrently](https://github.com/open-cli-tools/concurrently) |
`10.0.4` | `10.0.5` |
| [eslint](https://github.com/eslint/eslint) | `10.8.0` | `10.9.1` |
| [lint-staged](https://github.com/lint-staged/lint-staged) | `17.2.0` |
`17.3.0` |
|
[rolldown](https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown)
| `1.2.1` | `1.2.6` |
| [rollup](https://github.com/rollup/rollup) | `4.62.3` | `4.63.0` |
|
[typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint)
| `8.65.0` | `8.68.0` |
|
[@salesforce/vscode-services](https://github.com/forcedotcom/salesforcedx-vscode)
| `67.13.3` | `67.15.0` |
| [sass](https://github.com/sass/dart-sass) | `1.102.0` | `1.103.1` |


Updates `@swc/core` from 1.15.47 to 1.16.1
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/swc-project/swc/blob/main/CHANGELOG.md">@​swc/core's
changelog</a>.</em></p>
<blockquote>
<h2>[1.16.1] - 2026-08-19</h2>
<h3>Bug Fixes</h3>
<ul>
<li>
<p><strong>(es/minifier)</strong> Preserve for init (<a
href="https://redirect.github.com/swc-project/swc/issues/12121">#12121</a>)
(<a
href="https://github.com/swc-project/swc/commit/0a1d4de3c6439770aa718b488d87ac9a29d3d92a">0a1d4de</a>)</p>
</li>
<li>
<p><strong>(es/modules)</strong> Preserve destructuring assignment
targets in SystemJS (<a
href="https://redirect.github.com/swc-project/swc/issues/12122">#12122</a>)
(<a
href="https://github.com/swc-project/swc/commit/557060b72a2138c37a76114a1a2862390246a500">557060b</a>)</p>
</li>
<li>
<p><strong>(es/react)</strong> Handle apos JSX entities (<a
href="https://redirect.github.com/swc-project/swc/issues/12125">#12125</a>)
(<a
href="https://github.com/swc-project/swc/commit/d09547fbd99915d1063e3513d1a99cd9e2aeda7e">d09547f</a>)</p>
</li>
</ul>
<h2>[1.16.0] - 2026-08-14</h2>
<h3>Bug Fixes</h3>
<ul>
<li>
<p><strong>(encoding)</strong> Fix incorrect fields count (<a
href="https://redirect.github.com/swc-project/swc/issues/11905">#11905</a>)
(<a
href="https://github.com/swc-project/swc/commit/6fb4ca16332f862e71f149f19da55147f12a0c80">6fb4ca1</a>)</p>
<ul>
<li><strong>BREAKING</strong>: Fix incorrect fields count (<a
href="https://redirect.github.com/swc-project/swc/issues/11905">#11905</a>)</li>
</ul>
</li>
<li>
<p><strong>(es/ast)</strong> Prevent mutable reference escape (<a
href="https://redirect.github.com/swc-project/swc/issues/12088">#12088</a>)
(<a
href="https://github.com/swc-project/swc/commit/592f559787e62f091cbe5c4c370b2ff30e4abd34">592f559</a>)</p>
</li>
<li>
<p><strong>(es/ast)</strong> Fix panic on JSX surrogate entities (<a
href="https://redirect.github.com/swc-project/swc/issues/11803">#11803</a>)
(<a
href="https://github.com/swc-project/swc/commit/d21de4761a5306be015b2b9021fbc3cc9d02f13b">d21de47</a>)</p>
<ul>
<li><strong>BREAKING</strong>: fix panic on JSX surrogate entities (<a
href="https://redirect.github.com/swc-project/swc/issues/11803">#11803</a>)</li>
</ul>
</li>
<li>
<p><strong>(es/es2015)</strong> Preserve this in static field parameters
(<a
href="https://redirect.github.com/swc-project/swc/issues/12085">#12085</a>)
(<a
href="https://github.com/swc-project/swc/commit/5b758ed173292dccf4d97d372a36a4086a820a7c">5b758ed</a>)</p>
</li>
<li>
<p><strong>(es/minifier)</strong> Remove unused variable initializer
cycles (<a
href="https://redirect.github.com/swc-project/swc/issues/12106">#12106</a>)
(<a
href="https://github.com/swc-project/swc/commit/0421534a522d3c7b4b5aeb71b44751bb8aa90979">0421534</a>)</p>
</li>
<li>
<p><strong>(es/minifier)</strong> Bound arguments parameter injection
(<a
href="https://redirect.github.com/swc-project/swc/issues/12053">#12053</a>)
(<a
href="https://github.com/swc-project/swc/commit/46d6f41ccec6ce9d97baad4e16c1bdc8e24d77db">46d6f41</a>)</p>
</li>
<li>
<p><strong>(es/preset-env)</strong> Lower unsupported async generators
(<a
href="https://redirect.github.com/swc-project/swc/issues/12086">#12086</a>)
(<a
href="https://github.com/swc-project/swc/commit/3a144b1caa98d48b0adcb4ca824ee7c22ad7f702">3a144b1</a>)</p>
</li>
<li>
<p><strong>(hstr)</strong> Avoid references to uninitialized bytes (<a
href="https://redirect.github.com/swc-project/swc/issues/12087">#12087</a>)
(<a
href="https://github.com/swc-project/swc/commit/68f0983877976a379cb0249c7af21898505313be">68f0983</a>)</p>
</li>
<li>
<p><strong>(plugin)</strong> Make raw byte reconstruction unsafe (<a
href="https://redirect.github.com/swc-project/swc/issues/12089">#12089</a>)
(<a
href="https://github.com/swc-project/swc/commit/83ab4ed6fd19782342f221bfaf05177508b73217">83ab4ed</a>)</p>
</li>
<li>
<p><strong>(plugin/runner)</strong> Write Wasmer cache atomically (<a
href="https://redirect.github.com/swc-project/swc/issues/12100">#12100</a>)
(<a
href="https://github.com/swc-project/swc/commit/3c4f404bb3f54fd8a25eb9399b84a86bb3fc26fe">3c4f404</a>)</p>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/swc-project/swc/commit/490c7d88ad15cf84ee410c69e19eef86f445d45b"><code>490c7d8</code></a>
chore: Publish <code>1.16.1</code> with <code>swc_core</code>
<code>v77.0.2</code></li>
<li><a
href="https://github.com/swc-project/swc/commit/7e4d7829cbee64fd2c27e409c48784e1cb025d5d"><code>7e4d782</code></a>
chore: Publish <code>1.16.1-nightly-20260819.1</code> with
<code>swc_core</code> <code>v77.0.2</code></li>
<li><a
href="https://github.com/swc-project/swc/commit/ae2117a27417015729ecd823486f23f2d6c8cce3"><code>ae2117a</code></a>
chore: Publish <code>1.16.0</code> with <code>swc_core</code>
<code>v77.0.0</code></li>
<li><a
href="https://github.com/swc-project/swc/commit/99671f1ae54274fedd03799ddf97e4817a6e917b"><code>99671f1</code></a>
chore: Publish <code>1.16.0-nightly-20260814.1</code> with
<code>swc_core</code> <code>v77.0.0</code></li>
<li><a
href="https://github.com/swc-project/swc/commit/394c7c926edd4f779d09ba00612f8b8baab4907a"><code>394c7c9</code></a>
refactor(es/ast)!: introduce FunctionBody (<a
href="https://github.com/swc-project/swc/tree/HEAD/packages/core/issues/12096">#12096</a>)</li>
<li><a
href="https://github.com/swc-project/swc/commit/9ae902e3fe9771c75c116546dc36ac90e481c316"><code>9ae902e</code></a>
refactor(es/ast)!: use Function for object accessors (<a
href="https://github.com/swc-project/swc/tree/HEAD/packages/core/issues/12077">#12077</a>)</li>
<li><a
href="https://github.com/swc-project/swc/commit/1687c0fbd2f22c563e02f5f3efa8d5e4f0772e12"><code>1687c0f</code></a>
refactor(es/ast)!: split TypeScript this parameters (<a
href="https://github.com/swc-project/swc/tree/HEAD/packages/core/issues/12075">#12075</a>)</li>
<li>See full diff in <a
href="https://github.com/swc-project/swc/commits/v1.16.1/packages/core">compare
view</a></li>
</ul>
</details>
<br />

Updates `concurrently` from 10.0.4 to 10.0.5
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/open-cli-tools/concurrently/releases">concurrently's
releases</a>.</em></p>
<blockquote>
<h2>v10.0.5</h2>
<h2>What's Changed</h2>
<ul>
<li>fix: correctly output non-ASCII text on Windows by <a
href="https://github.com/DanielC000"><code>@​DanielC000</code></a> in <a
href="https://redirect.github.com/open-cli-tools/concurrently/pull/604">open-cli-tools/concurrently#604</a></li>
<li>fix: expand wildcards from package.json5 when package.json is
missing by <a
href="https://github.com/DSeaStar"><code>@​DSeaStar</code></a> in <a
href="https://redirect.github.com/open-cli-tools/concurrently/pull/608">open-cli-tools/concurrently#608</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/DanielC000"><code>@​DanielC000</code></a> made
their first contribution in <a
href="https://redirect.github.com/open-cli-tools/concurrently/pull/604">open-cli-tools/concurrently#604</a></li>
<li><a href="https://github.com/DSeaStar"><code>@​DSeaStar</code></a>
made their first contribution in <a
href="https://redirect.github.com/open-cli-tools/concurrently/pull/608">open-cli-tools/concurrently#608</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/open-cli-tools/concurrently/compare/v10.0.4...v10.0.5">https://github.com/open-cli-tools/concurrently/compare/v10.0.4...v10.0.5</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/open-cli-tools/concurrently/commit/1b8cbeba87497e0c2a29097c828276919935a217"><code>1b8cbeb</code></a>
10.0.5</li>
<li><a
href="https://github.com/open-cli-tools/concurrently/commit/544dba0980e06405f7f20bc951526d3d82b0d13e"><code>544dba0</code></a>
docs: make linter happy</li>
<li><a
href="https://github.com/open-cli-tools/concurrently/commit/667b70177b3d07010cd560377ee0a062314d675e"><code>667b701</code></a>
deps: update several dev deps</li>
<li><a
href="https://github.com/open-cli-tools/concurrently/commit/f67c57c4f944bd8e4505c7c62b83959839ea460e"><code>f67c57c</code></a>
vscode: use installed TS version</li>
<li><a
href="https://github.com/open-cli-tools/concurrently/commit/dbb561721625efb6291063b6912b5600602238ee"><code>dbb5617</code></a>
fix: expand wildcards from package.json5 when package.json is missing
(<a
href="https://redirect.github.com/open-cli-tools/concurrently/issues/608">#608</a>)</li>
<li><a
href="https://github.com/open-cli-tools/concurrently/commit/9f90a1a349de205a0a6607cd91443ad90ac0bec6"><code>9f90a1a</code></a>
fix: correctly output non-ASCII text on Windows (<a
href="https://redirect.github.com/open-cli-tools/concurrently/issues/604">#604</a>)</li>
<li><a
href="https://github.com/open-cli-tools/concurrently/commit/94415cc1fab534fb94843f8973caaa34be188e6a"><code>94415cc</code></a>
ci: fix publishing to latest/backport</li>
<li>See full diff in <a
href="https://github.com/open-cli-tools/concurrently/compare/v10.0.4...v10.0.5">compare
view</a></li>
</ul>
</details>
<br />

Updates `eslint` from 10.8.0 to 10.9.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/eslint/eslint/releases">eslint's
releases</a>.</em></p>
<blockquote>
<h2>v10.9.1</h2>
<h2>Bug Fixes</h2>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/1e641c919fc1421493bf913feb607896982451a3"><code>1e641c9</code></a>
fix: no-loss-of-precision false positive with trailing decimal point (<a
href="https://redirect.github.com/eslint/eslint/issues/21251">#21251</a>)
(Aleksandr Shoronov)</li>
</ul>
<h2>Documentation</h2>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/ad74a8dada2aaa17bfd0b8cc7b4119ff7a8ac04b"><code>ad74a8d</code></a>
docs: add deprecation steps for EOL package versions (<a
href="https://redirect.github.com/eslint/eslint/issues/21248">#21248</a>)
(Francesco Trotta)</li>
</ul>
<h2>Chores</h2>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/3c3ae53a43721162f0db76c69665ebd9d752ea52"><code>3c3ae53</code></a>
chore: update ecosystem plugins (<a
href="https://redirect.github.com/eslint/eslint/issues/21249">#21249</a>)
(ESLint Bot)</li>
</ul>
<h2>v10.9.0</h2>
<h2>Features</h2>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/08de88e50294c4e01f6cae97eceeb578da55792b"><code>08de88e</code></a>
feat: handle underflow in no-loss-of-precision (<a
href="https://redirect.github.com/eslint/eslint/issues/21218">#21218</a>)
(Rithish S)</li>
<li><a
href="https://github.com/eslint/eslint/commit/55db4791120ae591d88089c43127b7b0e16866d4"><code>55db479</code></a>
feat: add checkConditionalExpressions to
<code>no-unmodified-loop-condition</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/21175">#21175</a>)
(sethamus)</li>
</ul>
<h2>Bug Fixes</h2>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/2ba302554e7a24e9909bbdd026fd0c2d1d0d8638"><code>2ba3025</code></a>
fix: prevent unsafe <code>no-var</code> autofix with hoisted functions
(<a
href="https://redirect.github.com/eslint/eslint/issues/21213">#21213</a>)
(sethamus)</li>
<li><a
href="https://github.com/eslint/eslint/commit/8e6962219a605c5f5add10953aa31027da839194"><code>8e69622</code></a>
fix: Prevent no-var autofix when var is shadowed by catch parameter (<a
href="https://redirect.github.com/eslint/eslint/issues/21204">#21204</a>)
(Yang Hyeonjong)</li>
<li><a
href="https://github.com/eslint/eslint/commit/684b57972e1ddf25e076fb36189c60bbcacee635"><code>684b579</code></a>
fix: prefer-template invalid autofix creates a tagged template call (<a
href="https://redirect.github.com/eslint/eslint/issues/21207">#21207</a>)
(김채영)</li>
</ul>
<h2>Documentation</h2>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/9ef407a3b051e74f50dc7fb8914e2bd89b3e5e53"><code>9ef407a</code></a>
docs: use eslint.config.* wherever config file names are listed (<a
href="https://redirect.github.com/eslint/eslint/issues/21216">#21216</a>)
(Marry (Subin Yang))</li>
<li><a
href="https://github.com/eslint/eslint/commit/87f66f4435c4df7f4f6815c939d153196ec03e3c"><code>87f66f4</code></a>
docs: Update README (GitHub Actions Bot)</li>
<li><a
href="https://github.com/eslint/eslint/commit/585ef37516c0dc29ddb91ce2a2cdcc46fdbbd610"><code>585ef37</code></a>
docs: update architecture documentation (<a
href="https://redirect.github.com/eslint/eslint/issues/21112">#21112</a>)
(Francesco Trotta)</li>
<li><a
href="https://github.com/eslint/eslint/commit/f3993b0547bace7370e9728ee7408af49d367d76"><code>f3993b0</code></a>
docs: Update README (GitHub Actions Bot)</li>
<li><a
href="https://github.com/eslint/eslint/commit/ffc87d6234b2aa4335eec069e5c4d6ac04832b9e"><code>ffc87d6</code></a>
docs: fix broken links in Further Reading sections (<a
href="https://redirect.github.com/eslint/eslint/issues/21203">#21203</a>)
(Minsu)</li>
<li><a
href="https://github.com/eslint/eslint/commit/1a761e1d11b011fcb6bee181231a51010c500e4d"><code>1a761e1</code></a>
docs: update moved JSX specification links (<a
href="https://redirect.github.com/eslint/eslint/issues/21198">#21198</a>)
(Imran Mustafa)</li>
<li><a
href="https://github.com/eslint/eslint/commit/4d00ca4064ae0d1a75b604a16c68ab9f386ad388"><code>4d00ca4</code></a>
docs: update ESLint peer dependency to <code>^10.0.0</code> in shareable
configs (<a
href="https://redirect.github.com/eslint/eslint/issues/21202">#21202</a>)
(lumir)</li>
<li><a
href="https://github.com/eslint/eslint/commit/510d1a2e87bc197219f42e195ddb638d2b183a5a"><code>510d1a2</code></a>
docs: Update README (GitHub Actions Bot)</li>
</ul>
<h2>Chores</h2>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/899dbf131ce12a194b394bb8d67307df23509d17"><code>899dbf1</code></a>
chore: update github/codeql-action action to v4.37.7 (<a
href="https://redirect.github.com/eslint/eslint/issues/21243">#21243</a>)
(renovate[bot])</li>
<li><a
href="https://github.com/eslint/eslint/commit/9aa38732177935bd1d7f1493732c0b67666be28a"><code>9aa3873</code></a>
chore: update ecosystem plugins (<a
href="https://redirect.github.com/eslint/eslint/issues/21235">#21235</a>)
(ESLint Bot)</li>
<li><a
href="https://github.com/eslint/eslint/commit/dc1e7a8416937edefe04cf836ee202a6fc03bedd"><code>dc1e7a8</code></a>
chore: update ecosystem plugins (<a
href="https://redirect.github.com/eslint/eslint/issues/21208">#21208</a>)
(ESLint Bot)</li>
<li><a
href="https://github.com/eslint/eslint/commit/f878d212e9622da9513bcd60d2aedb2e8bb4fc8b"><code>f878d21</code></a>
ci: bump pnpm/action-setup from 6.0.9 to 6.0.10 (<a
href="https://redirect.github.com/eslint/eslint/issues/21200">#21200</a>)
(dependabot[bot])</li>
<li><a
href="https://github.com/eslint/eslint/commit/4891e50aceadb0e886ad7d8ab5ae2beab563de85"><code>4891e50</code></a>
ci: bump github/codeql-action from 4.37.4 to 4.37.6 (<a
href="https://redirect.github.com/eslint/eslint/issues/21199">#21199</a>)
(dependabot[bot])</li>
</ul>
<h2>v10.8.1</h2>
<h2>Bug Fixes</h2>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/18eb0a7e787b9fac3049ef3dad0e845d2bd940a4"><code>18eb0a7</code></a>
fix: prevent ASI hazard in <code>no-unused-labels</code> autofix (<a
href="https://redirect.github.com/eslint/eslint/issues/21173">#21173</a>)
(dongkyu lee)</li>
<li><a
href="https://github.com/eslint/eslint/commit/151ba3f5834a0909e8b9b1736f4889ac694c0104"><code>151ba3f</code></a>
fix: false positives in <code>getter-return</code> and
<code>accessor-pairs</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/21163">#21163</a>)
(Grit)</li>
<li><a
href="https://github.com/eslint/eslint/commit/6898df9364639ee64b9448a4cb6b08a30c16bd37"><code>6898df9</code></a>
fix: ignore meta-property names in <code>id-denylist</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/21166">#21166</a>)
(Pixel)</li>
<li><a
href="https://github.com/eslint/eslint/commit/4d7db6628e2badf0857cb88734fe641c3874bce9"><code>4d7db66</code></a>
fix: ignore meta-property names in <code>id-match</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/21167">#21167</a>)
(Pixel)</li>
<li><a
href="https://github.com/eslint/eslint/commit/677214e7eea83d8bc6e4b79eea871577e1369d5f"><code>677214e</code></a>
fix: handle ASI hazards in no-unused-vars removeVar suggestion (<a
href="https://redirect.github.com/eslint/eslint/issues/20935">#20935</a>)
(kuldeep kumar)</li>
</ul>
<h2>Documentation</h2>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/7d0cbf81cfdb7526b5c4cb7b222ddc7f257db560"><code>7d0cbf8</code></a>
docs: Update README (GitHub Actions Bot)</li>
<li><a
href="https://github.com/eslint/eslint/commit/0a05812adb12598b32e85297b98df5ad14501d60"><code>0a05812</code></a>
docs: add missing backticks to <code>no-duplicate-imports.js</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/21183">#21183</a>)
(Lee Daeun)</li>
<li><a
href="https://github.com/eslint/eslint/commit/678c90b55da2889d4400cbf6e2584ab683faf202"><code>678c90b</code></a>
docs: Update README (GitHub Actions Bot)</li>
<li><a
href="https://github.com/eslint/eslint/commit/8a104242e8e1c5614940fab7324346974cff7d26"><code>8a10424</code></a>
docs: Update README (GitHub Actions Bot)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/5c8c2417b9ff462f2dc4e54a062c59135b45b845"><code>5c8c241</code></a>
10.9.1</li>
<li><a
href="https://github.com/eslint/eslint/commit/a7f3b7ddca7de8464995707d1bbac3ca91090015"><code>a7f3b7d</code></a>
Build: changelog update for 10.9.1</li>
<li><a
href="https://github.com/eslint/eslint/commit/1e641c919fc1421493bf913feb607896982451a3"><code>1e641c9</code></a>
fix: no-loss-of-precision false positive with trailing decimal point (<a
href="https://redirect.github.com/eslint/eslint/issues/21251">#21251</a>)</li>
<li><a
href="https://github.com/eslint/eslint/commit/ad74a8dada2aaa17bfd0b8cc7b4119ff7a8ac04b"><code>ad74a8d</code></a>
docs: add deprecation steps for EOL package versions (<a
href="https://redirect.github.com/eslint/eslint/issues/21248">#21248</a>)</li>
<li><a
href="https://github.com/eslint/eslint/commit/3c3ae53a43721162f0db76c69665ebd9d752ea52"><code>3c3ae53</code></a>
chore: update ecosystem plugins (<a
href="https://redirect.github.com/eslint/eslint/issues/21249">#21249</a>)</li>
<li><a
href="https://github.com/eslint/eslint/commit/c27bc926e496985eb7911c09eb60914b2e4b5d0f"><code>c27bc92</code></a>
10.9.0</li>
<li><a
href="https://github.com/eslint/eslint/commit/fa831d95b326e6d23671d9b2df1ea5dbc64f6f34"><code>fa831d9</code></a>
Build: changelog update for 10.9.0</li>
<li><a
href="https://github.com/eslint/eslint/commit/899dbf131ce12a194b394bb8d67307df23509d17"><code>899dbf1</code></a>
chore: update github/codeql-action action to v4.37.7 (<a
href="https://redirect.github.com/eslint/eslint/issues/21243">#21243</a>)</li>
<li><a
href="https://github.com/eslint/eslint/commit/08de88e50294c4e01f6cae97eceeb578da55792b"><code>08de88e</code></a>
feat: handle underflow in no-loss-of-precision (<a
href="https://redirect.github.com/eslint/eslint/issues/21218">#21218</a>)</li>
<li><a
href="https://github.com/eslint/eslint/commit/9ef407a3b051e74f50dc7fb8914e2bd89b3e5e53"><code>9ef407a</code></a>
docs: use eslint.config.* wherever config file names are listed (<a
href="https://redirect.github.com/eslint/eslint/issues/21216">#21216</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/eslint/eslint/compare/v10.8.0...v10.9.1">compare
view</a></li>
</ul>
</details>
<br />

Updates `lint-staged` from 17.2.0 to 17.3.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/lint-staged/lint-staged/releases">lint-staged's
releases</a>.</em></p>
<blockquote>
<h2>v17.3.0</h2>
<h3>Minor Changes</h3>
<ul>
<li>
<p><a
href="https://redirect.github.com/lint-staged/lint-staged/pull/1825">#1825</a>
<a
href="https://github.com/lint-staged/lint-staged/commit/16b3f74850e5d2811b5fbaea6c136733a71ad3e4"><code>16b3f74</code></a>
- It is now possible to run multiple tasks in parallel for a single glob
by configuring it with an array of tasks (which run sequentially), and
then placing another array inside it (where the tasks will run in
parallel). The following demonstrates the order tasks will start in:</p>
<pre lang="json"><code>{
&quot;*.ts&quot;: [&quot;first&quot;, &quot;second&quot;,
[&quot;third&quot;, &quot;third&quot;], &quot;fourth&quot;]
}
</code></pre>
<p>As a concrete example, <em>lint-staged</em>'s own configuration
is:</p>
<pre lang="js"><code>/** @type {import('./lib/index.js').Configuration}
*/
export default {
  &quot;*&quot;: [
    [
      &quot;oxfmt --check --no-error-on-unmatched-pattern&quot;,
      &quot;oxlint --no-error-on-unmatched-pattern&quot;,
    ],
  ],
  &quot;*.ts&quot;: () =&gt; &quot;tsc&quot;,
};
</code></pre>
<p>which means:</p>
<ol>
<li>for all staged files, run the two commands in parallel with staged
filenames appended, for example:
<ul>
<li><code>oxfmt --check --no-error-on-unmatched-pattern
lib/index.js</code></li>
<li><code>oxlint --no-error-on-unmatched-pattern
lib/index.js</code></li>
</ul>
</li>
<li>additionally, if any <code>*.ts</code> files are staged, run
<code>tsc</code> without appending any arguments</li>
<li>The two sets of commands also run in parallel</li>
</ol>
</li>
</ul>
<h3>Patch Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/lint-staged/lint-staged/pull/1829">#1829</a>
<a
href="https://github.com/lint-staged/lint-staged/commit/15f7e5314b4afe4702808d978758b22d42437f43"><code>15f7e53</code></a>
- During an in-progress merge, files that are unchanged from the branch
being merged are now skipped. Technically, files are only included if
there are staged changes against both <code>HEAD</code> and
<code>MERGE_HEAD</code>.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/lint-staged/lint-staged/blob/main/CHANGELOG.md">lint-staged's
changelog</a>.</em></p>
<blockquote>
<h2>17.3.0</h2>
<h3>Minor Changes</h3>
<ul>
<li>
<p><a
href="https://redirect.github.com/lint-staged/lint-staged/pull/1825">#1825</a>
<a
href="https://github.com/lint-staged/lint-staged/commit/16b3f74850e5d2811b5fbaea6c136733a71ad3e4"><code>16b3f74</code></a>
- It is now possible to run multiple tasks in parallel for a single glob
by configuring it with an array of tasks (which run sequentially), and
then placing another array inside it (where the tasks will run in
parallel). The following demonstrates the order tasks will start in:</p>
<pre lang="json"><code>{
&quot;*.ts&quot;: [&quot;first&quot;, &quot;second&quot;,
[&quot;third&quot;, &quot;third&quot;], &quot;fourth&quot;]
}
</code></pre>
<p>As a concrete example, <em>lint-staged</em>'s own configuration
is:</p>
<pre lang="js"><code>/** @type {import('./lib/index.js').Configuration}
*/
export default {
  '*': [
['oxfmt --check --no-error-on-unmatched-pattern', 'oxlint
--no-error-on-unmatched-pattern'],
  ],
  '*.ts': () =&gt; 'tsc',
}
</code></pre>
<p>which means:</p>
<ol>
<li>for all staged files, run the two commands in parallel with staged
filenames appended, for example:
<ul>
<li><code>oxfmt --check --no-error-on-unmatched-pattern
lib/index.js</code></li>
<li><code>oxlint --no-error-on-unmatched-pattern
lib/index.js</code></li>
</ul>
</li>
<li>additionally, if any <code>*.ts</code> files are staged, run
<code>tsc</code> without appending any arguments</li>
<li>The two sets of commands also run in parallel</li>
</ol>
</li>
</ul>
<h3>Patch Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/lint-staged/lint-staged/pull/1829">#1829</a>
<a
href="https://github.com/lint-staged/lint-staged/commit/15f7e5314b4afe4702808d978758b22d42437f43"><code>15f7e53</code></a>
- During an in-progress merge, files that are unchanged from the branch
being merged are now skipped. Technically, files are only included if
there are staged changes against both <code>HEAD</code> and
<code>MERGE_HEAD</code>.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/lint-staged/lint-staged/commit/d15344350d914f5ce24df2c85f3ffebb9b387f3b"><code>d153443</code></a>
Merge pull request <a
href="https://redirect.github.com/lint-staged/lint-staged/issues/1828">#1828</a>
from lint-staged/changeset-release/main</li>
<li><a
href="https://github.com/lint-staged/lint-staged/commit/5162c149bbfa09b8a5ad4d37c647d63946568ca8"><code>5162c14</code></a>
chore(changeset): release</li>
<li><a
href="https://github.com/lint-staged/lint-staged/commit/a4db9a4c32f108d1397436752be7e9dda956baa2"><code>a4db9a4</code></a>
Merge pull request <a
href="https://redirect.github.com/lint-staged/lint-staged/issues/1831">#1831</a>
from lint-staged/linter-updates</li>
<li><a
href="https://github.com/lint-staged/lint-staged/commit/ea96cab0109ab44a5b2562927b890648ee32b4cc"><code>ea96cab</code></a>
style: enable oxlint &quot;suspicious&quot; category</li>
<li><a
href="https://github.com/lint-staged/lint-staged/commit/2fae00778cea0c99da9bcb8bad4718dce08ea04e"><code>2fae007</code></a>
style: add <code>@e18e/eslint-plugin</code></li>
<li><a
href="https://github.com/lint-staged/lint-staged/commit/2280c38a09ff4ca4db60320b5879e0029527afaa"><code>2280c38</code></a>
Merge pull request <a
href="https://redirect.github.com/lint-staged/lint-staged/issues/1829">#1829</a>
from lint-staged/fix-merge-conflict-files</li>
<li><a
href="https://github.com/lint-staged/lint-staged/commit/1453ae6ae0e05275d714ad0cad7cd090885f504d"><code>1453ae6</code></a>
test: relax assertion so that it passes in worktree</li>
<li><a
href="https://github.com/lint-staged/lint-staged/commit/15f7e5314b4afe4702808d978758b22d42437f43"><code>15f7e53</code></a>
fix: lint only files changed against HEAD and MERGE_HEAD, during a
merge</li>
<li><a
href="https://github.com/lint-staged/lint-staged/commit/dedfc31007aed50e1c9c5591a11085cb485ba41c"><code>dedfc31</code></a>
Merge pull request <a
href="https://redirect.github.com/lint-staged/lint-staged/issues/1825">#1825</a>
from lint-staged/parallel-tasks-inside-sequence</li>
<li><a
href="https://github.com/lint-staged/lint-staged/commit/286e25cef9fde2fb6e77d2312fd91ac99020d69d"><code>286e25c</code></a>
feat: allow running parallel tasks by nesting arrays</li>
<li>Additional commits viewable in <a
href="https://github.com/lint-staged/lint-staged/compare/v17.2.0...v17.3.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `rolldown` from 1.2.1 to 1.2.6
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/rolldown/rolldown/releases">rolldown's
releases</a>.</em></p>
<blockquote>
<h2>v1.2.6</h2>
<h2>[1.2.6] - 2026-08-26</h2>
<h3>🚀 Features</h3>
<ul>
<li>minify: support property name mangling (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10374">#10374</a>)
by <a href="https://github.com/Dunqing"><code>@​Dunqing</code></a></li>
<li>add <code>tsconfig: string</code> option to <code>transform</code>
(<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10727">#10727</a>)
by <a
href="https://github.com/sapphi-red"><code>@​sapphi-red</code></a></li>
<li>rolldown_plugin_vite_transform: add <code>tsconfig</code> option (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10725">#10725</a>)
by <a
href="https://github.com/sapphi-red"><code>@​sapphi-red</code></a></li>
<li>rolldown_plugin_vite_resolve: add top-level <code>tsconfig</code>
option (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10724">#10724</a>)
by <a
href="https://github.com/sapphi-red"><code>@​sapphi-red</code></a></li>
<li>dev: expose module graph queries on the dev engine handle (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10716">#10716</a>)
by <a href="https://github.com/h-a-n-a"><code>@​h-a-n-a</code></a></li>
</ul>
<h3>🐛 Bug Fixes</h3>
<ul>
<li>dev: assign import bindings before initializing dependencies (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10783">#10783</a>)
by <a href="https://github.com/h-a-n-a"><code>@​h-a-n-a</code></a></li>
<li>dev: copy star re-exports before initializing dependencies (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10761">#10761</a>)
by <a href="https://github.com/h-a-n-a"><code>@​h-a-n-a</code></a></li>
<li>dev: register an empty exports object for a module without exports
(<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10772">#10772</a>)
by <a href="https://github.com/h-a-n-a"><code>@​h-a-n-a</code></a></li>
<li>name the module when a <code>codeSplitting</code> group callback
returns a wrong type (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10753">#10753</a>)
by <a
href="https://github.com/IWANABETHATGUY"><code>@​IWANABETHATGUY</code></a></li>
<li>dev: map dev rename events like build watch (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10758">#10758</a>)
by <a
href="https://github.com/shulaoda"><code>@​shulaoda</code></a></li>
<li>clear resolution cache when <code>TsconfigCache::clear</code> is
called (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10726">#10726</a>)
by <a
href="https://github.com/sapphi-red"><code>@​sapphi-red</code></a></li>
<li>dev: resolve in-flight <code>ensureLatestBuildOutput</code> when the
engine closes (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10730">#10730</a>)
by <a href="https://github.com/h-a-n-a"><code>@​h-a-n-a</code></a></li>
<li>binding: replace undeclared BindingErrorsOr with BindingResult in
hook types (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10717">#10717</a>)
by <a href="https://github.com/h-a-n-a"><code>@​h-a-n-a</code></a></li>
</ul>
<h3>🚜 Refactor</h3>
<ul>
<li>rolldown_fs_watcher: collapse fs-watcher backends behind a single
FsWatcher (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10735">#10735</a>)
by <a
href="https://github.com/shulaoda"><code>@​shulaoda</code></a></li>
<li>hoist invariants out of the <code>codeSplitting</code> group loop
(<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10744">#10744</a>)
by <a
href="https://github.com/IWANABETHATGUY"><code>@​IWANABETHATGUY</code></a></li>
</ul>
<h3>📚 Documentation</h3>
<ul>
<li>document shared notify rename mapping (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10759">#10759</a>)
by <a
href="https://github.com/shulaoda"><code>@​shulaoda</code></a></li>
<li>update watch-mode internals for unified FsWatcher (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10736">#10736</a>)
by <a
href="https://github.com/shulaoda"><code>@​shulaoda</code></a></li>
</ul>
<h3>⚡ Performance</h3>
<ul>
<li>batch <code>codeSplitting</code> group <code>test</code> /
<code>name</code> calls (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10745">#10745</a>)
by <a
href="https://github.com/IWANABETHATGUY"><code>@​IWANABETHATGUY</code></a></li>
<li>deduplicate used symbol ref readers (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10742">#10742</a>)
by <a href="https://github.com/Boshen"><code>@​Boshen</code></a></li>
<li>reduce release debug formatting (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10728">#10728</a>)
by <a href="https://github.com/Boshen"><code>@​Boshen</code></a></li>
<li>enable compiler cache via <code>module.enableCompileCache()</code>
(<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10678">#10678</a>)
by <a href="https://github.com/btea"><code>@​btea</code></a></li>
<li>deduplicate regress codegen (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10732">#10732</a>)
by <a href="https://github.com/Boshen"><code>@​Boshen</code></a></li>
</ul>
<h3>🧪 Testing</h3>
<ul>
<li>define: add expected failure for default parameter scope (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10780">#10780</a>)
by <a href="https://github.com/hyfdev"><code>@​hyfdev</code></a></li>
<li>use an absolute filename for transform tsconfig path (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10782">#10782</a>)
by <a
href="https://github.com/shulaoda"><code>@​shulaoda</code></a></li>
</ul>
<h3>⚙️ Miscellaneous Tasks</h3>
<ul>
<li>deps: upgrade oxc to 0.147.0 (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10767">#10767</a>)
by <a href="https://github.com/camc314"><code>@​camc314</code></a></li>
<li>deps: update resolver dependencies (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10766">#10766</a>)
by <a href="https://github.com/Boshen"><code>@​Boshen</code></a></li>
<li>deps: update rollup submodule for tests to v4.62.5 (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10770">#10770</a>)
by <a
href="https://github.com/rolldown-guard"><code>@​rolldown-guard</code></a>[bot]</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/rolldown/rolldown/blob/main/CHANGELOG.md">rolldown's
changelog</a>.</em></p>
<blockquote>
<h2>[1.2.6] - 2026-08-26</h2>
<h3>🚀 Features</h3>
<ul>
<li>minify: support property name mangling (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10374">#10374</a>)
by <a href="https://github.com/Dunqing"><code>@​Dunqing</code></a></li>
<li>add <code>tsconfig: string</code> option to <code>transform</code>
(<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10727">#10727</a>)
by <a
href="https://github.com/sapphi-red"><code>@​sapphi-red</code></a></li>
<li>rolldown_plugin_vite_transform: add <code>tsconfig</code> option (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10725">#10725</a>)
by <a
href="https://github.com/sapphi-red"><code>@​sapphi-red</code></a></li>
<li>rolldown_plugin_vite_resolve: add top-level <code>tsconfig</code>
option (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10724">#10724</a>)
by <a
href="https://github.com/sapphi-red"><code>@​sapphi-red</code></a></li>
<li>dev: expose module graph queries on the dev engine handle (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10716">#10716</a>)
by <a href="https://github.com/h-a-n-a"><code>@​h-a-n-a</code></a></li>
</ul>
<h3>🐛 Bug Fixes</h3>
<ul>
<li>dev: assign import bindings before initializing dependencies (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10783">#10783</a>)
by <a href="https://github.com/h-a-n-a"><code>@​h-a-n-a</code></a></li>
<li>dev: copy star re-exports before initializing dependencies (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10761">#10761</a>)
by <a href="https://github.com/h-a-n-a"><code>@​h-a-n-a</code></a></li>
<li>dev: register an empty exports object for a module without exports
(<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10772">#10772</a>)
by <a href="https://github.com/h-a-n-a"><code>@​h-a-n-a</code></a></li>
<li>name the module when a <code>codeSplitting</code> group callback
returns a wrong type (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10753">#10753</a>)
by <a
href="https://github.com/IWANABETHATGUY"><code>@​IWANABETHATGUY</code></a></li>
<li>dev: map dev rename events like build watch (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10758">#10758</a>)
by <a
href="https://github.com/shulaoda"><code>@​shulaoda</code></a></li>
<li>clear resolution cache when <code>TsconfigCache::clear</code> is
called (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10726">#10726</a>)
by <a
href="https://github.com/sapphi-red"><code>@​sapphi-red</code></a></li>
<li>dev: resolve in-flight <code>ensureLatestBuildOutput</code> when the
engine closes (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10730">#10730</a>)
by <a href="https://github.com/h-a-n-a"><code>@​h-a-n-a</code></a></li>
<li>binding: replace undeclared BindingErrorsOr with BindingResult in
hook types (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10717">#10717</a>)
by <a href="https://github.com/h-a-n-a"><code>@​h-a-n-a</code></a></li>
</ul>
<h3>🚜 Refactor</h3>
<ul>
<li>rolldown_fs_watcher: collapse fs-watcher backends behind a single
FsWatcher (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10735">#10735</a>)
by <a
href="https://github.com/shulaoda"><code>@​shulaoda</code></a></li>
<li>hoist invariants out of the <code>codeSplitting</code> group loop
(<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10744">#10744</a>)
by <a
href="https://github.com/IWANABETHATGUY"><code>@​IWANABETHATGUY</code></a></li>
</ul>
<h3>📚 Documentation</h3>
<ul>
<li>document shared notify rename mapping (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10759">#10759</a>)
by <a
href="https://github.com/shulaoda"><code>@​shulaoda</code></a></li>
<li>update watch-mode internals for unified FsWatcher (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10736">#10736</a>)
by <a
href="https://github.com/shulaoda"><code>@​shulaoda</code></a></li>
</ul>
<h3>⚡ Performance</h3>
<ul>
<li>batch <code>codeSplitting</code> group <code>test</code> /
<code>name</code> calls (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10745">#10745</a>)
by <a
href="https://github.com/IWANABETHATGUY"><code>@​IWANABETHATGUY</code></a></li>
<li>deduplicate used symbol ref readers (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10742">#10742</a>)
by <a href="https://github.com/Boshen"><code>@​Boshen</code></a></li>
<li>reduce release debug formatting (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10728">#10728</a>)
by <a href="https://github.com/Boshen"><code>@​Boshen</code></a></li>
<li>enable compiler cache via <code>module.enableCompileCache()</code>
(<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10678">#10678</a>)
by <a href="https://github.com/btea"><code>@​btea</code></a></li>
<li>deduplicate regress codegen (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10732">#10732</a>)
by <a href="https://github.com/Boshen"><code>@​Boshen</code></a></li>
</ul>
<h3>🧪 Testing</h3>
<ul>
<li>define: add expected failure for default parameter scope (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10780">#10780</a>)
by <a href="https://github.com/hyfdev"><code>@​hyfdev</code></a></li>
<li>use an absolute filename for transform tsconfig path (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10782">#10782</a>)
by <a
href="https://github.com/shulaoda"><code>@​shulaoda</code></a></li>
</ul>
<h3>⚙️ Miscellaneous Tasks</h3>
<ul>
<li>deps: upgrade oxc to 0.147.0 (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10767">#10767</a>)
by <a href="https://github.com/camc314"><code>@​camc314</code></a></li>
<li>deps: update resolver dependencies (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10766">#10766</a>)
by <a href="https://github.com/Boshen"><code>@​Boshen</code></a></li>
<li>deps: update rollup submodule for tests to v4.62.5 (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10770">#10770</a>)
by <a
href="https://github.com/rolldown-guard"><code>@​rolldown-guard</code></a>[bot]</li>
<li>deps: update dependency vite-plus to ^0.3.0 (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10757">#10757</a>)
by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot]</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/rolldown/rolldown/commit/5375362b36eeeaf514c67052ba65f3e97523dde5"><code>5375362</code></a>
release: v1.2.6 (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10784">#10784</a>)</li>
<li><a
href="https://github.com/rolldown/rolldown/commit/cba0a90661b46aed27185d27f1b12d35a99c3f61"><code>cba0a90</code></a>
test: use an absolute filename for transform tsconfig path (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10782">#10782</a>)</li>
<li><a
href="https://github.com/rolldown/rolldown/commit/2ba4bdfc1f167f2da3aec8a936db985e85273edf"><code>2ba4bdf</code></a>
feat(minify): support property name mangling (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10374">#10374</a>)</li>
<li><a
href="https://github.com/rolldown/rolldown/commit/224f40bd081f80b108026c07315ae741ac3baa84"><code>224f40b</code></a>
fix(dev): register an empty exports object for a module without exports
(<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10772">#10772</a>)</li>
<li><a
href="https://github.com/rolldown/rolldown/commit/4f052e4322f7f3bc33cd48fec1e3ef03bba7b820"><code>4f052e4</code></a>
fix: name the module when a <code>codeSplitting</code> group callback
returns a wrong ty...</li>
<li><a
href="https://github.com/rolldown/rolldown/commit/f86be54537e76a684a5ae311216dbd1aebaf8798"><code>f86be54</code></a>
perf: batch <code>codeSplitting</code> group <code>test</code> /
<code>name</code> calls (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10745">#10745</a>)</li>
<li><a
href="https://github.com/rolldown/rolldown/commit/4f810961e7af3877737bdb041b032e1dec288082"><code>4f81096</code></a>
perf: enable compiler cache via <code>module.enableCompileCache()</code>
(<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10678">#10678</a>)</li>
<li><a
href="https://github.com/rolldown/rolldown/commit/68e968bc0523c39b4ce917701f1b1d980552e94a"><code>68e968b</code></a>
feat: add <code>tsconfig: string</code> option to <code>transform</code>
(<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10727">#10727</a>)</li>
<li><a
href="https://github.com/rolldown/rolldown/commit/874bc9a2a3c761560222a6c3ef7a147cebf36882"><code>874bc9a</code></a>
fix: clear resolution cache when <code>TsconfigCache::clear</code> is
called (<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10726">#10726</a>)</li>
<li><a
href="https://github.com/rolldown/rolldown/commit/32d48659b5bf2330caeebacf58909621f06d4510"><code>32d4865</code></a>
feat(rolldown_plugin_vite_transform): add <code>tsconfig</code> option
(<a
href="https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown/issues/10725">#10725</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/rolldown/rolldown/commits/v1.2.6/packages/rolldown">compare
view</a></li>
</ul>
</details>
<br />

Updates `rollup` from 4.62.3 to 4.63.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/rollup/rollup/releases">rollup's
releases</a>.</em></p>
<blockquote>
<h2>v4.63.0</h2>
<h2>4.63.0</h2>
<p><em>2026-08-25</em></p>
<h3>Features</h3>
<ul>
<li>Allow to analyze function return values in many more cases (<a
href="https://redirect.github.com/rollup/rollup/issues/6065">#6065</a>)</li>
</ul>
<h3>Pull Requests</h3>
<ul>
<li><a
href="https://redirect.github.com/rollup/rollup/pull/6065">#6065</a>:
feat: improve function return value tracking (<a
href="https://github.com/cyyynthia"><code>@​cyyynthia</code></a>, <a
href="https://github.com/lukastaegert"><code>@​lukastaegert</code></a>)</li>
<li><a
href="https://redirect.github.com/rollup/rollup/pull/6482">#6482</a>:
Remove unused rendered module sources map (<a
href="https://github.com/yoominho91"><code>@​yoominho91</code></a>, <a
href="https://github.com/irontaek"><code>@​irontaek</code></a>, <a
href="https://github.com/lukastaegert"><code>@​lukastaegert</code></a>)</li>
<li><a
href="https://redirect.github.com/rollup/rollup/pull/6483">#6483</a>:
chore(deps): update minor/patch updates (<a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot])</li>
<li><a
href="https://redirect.github.com/rollup/rollup/pull/6484">#6484</a>:
fix(deps): update swc monorepo (major) (<a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot], <a
href="https://github.com/lukastaegert"><code>@​lukastaegert</code></a>)</li>
<li><a
href="https://redirect.github.com/rollup/rollup/pull/6485">#6485</a>:
chore(deps): lock file maintenance (<a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot], <a
href="https://github.com/lukastaegert"><code>@​lukastaegert</code></a>)</li>
<li><a
href="https://redirect.github.com/rollup/rollup/pull/6486">#6486</a>:
chore(deps): lock file maintenance (<a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot])</li>
</ul>
<h2>v4.62.5</h2>
<h2>4.62.5</h2>
<p><em>2026-08-20</em></p>
<h3>Bug Fixes</h3>
<ul>
<li>Resolve an issue where compact mode could result in invalid module
concatenations (<a
href="https://redirect.github.com/rollup/rollup/issues/6468">#6468</a>)</li>
</ul>
<h3>Pull Requests</h3>
<ul>
<li><a
href="https://redirect.github.com/rollup/rollup/pull/6468">#6468</a>:
Keep the semicolon added after a replaced default export (<a
href="https://github.com/Jaybhade"><code>@​Jaybhade</code></a>, <a
href="https://github.com/lukastaegert"><code>@​lukastaegert</code></a>)</li>
<li><a
href="https://redirect.github.com/rollup/rollup/pull/6469">#6469</a>:
fix(deps): update minor/patch updates (<a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot])</li>
<li><a
href="https://redirect.github.com/rollup/rollup/pull/6470">#6470</a>:
fix(deps): update swc monorepo (major) (<a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot])</li>
<li><a
href="https://redirect.github.com/rollup/rollup/pull/6471">#6471</a>:
chore(deps): lock file maintenance (<a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot])</li>
<li><a
href="https://redirect.github.com/rollup/rollup/pull/6472">#6472</a>:
chore(deps): update dependency eslint-plugin-unicorn to v73 (<a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot])</li>
<li><a
href="https://redirect.github.com/rollup/rollup/pull/6476">#6476</a>:
chore(deps): update dtolnay/rust-toolchain digest to 4360b52 (<a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot])</li>
<li><a
href="https://redirect.github.com/rollup/rollup/pull/6477">#6477</a>:
fix(deps): update minor/patch updates (<a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot])</li>
<li><a
href="https://redirect.github.com/rollup/rollup/pull/6478">#6478</a>:
chore(deps): lock file maintenance (<a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot])</li>
<li><a
href="https://redirect.github.com/rollup/rollup/pull/6479">#6479</a>:
chore(deps): lock file maintenance (<a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot])</li>
<li><a
href="https://redirect.github.com/rollup/rollup/pull/6480">#6480</a>:
chore(deps): lock file maintenance (<a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot])</li>
</ul>
<h2>v4.62.4</h2>
<h2>4.62.4</h2>
<p><em>2026-08-01</em></p>
<h3>Bug Fixes</h3>
<ul>
<li>Resolve a regression when using Rollup on older Linux distributions
(<a
href="https://redirect.github.com/rollup/rollup/issues/6467">#6467</a>)</li>
</ul>
<h3>Pull Requests</h3>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/rollup/rollup/blob/master/CHANGELOG.md">rollup's
changelog</a>.</em></p>
<blockquote>
<h2>4.63.0</h2>
<p><em>2026-08-25</em></p>
<h3>Features</h3>
<ul>
<li>Allow to analyze function return values in many more cases (<a
href="https://redirect.github.com/rollup/rollup/issues/6065">#6065</a>)</li>
</ul>
<h3>Pull Requests</h3>
<ul>
<li><a
href="https://redirect.github.com/rollup/rollup/pull/6065">#6065</a>:
feat: improve function return value tracking (<a
href="https://github.com/cyyynthia"><code>@​cyyynthia</code></a>, <a
href="https://github.com/lukastaegert"><code>@​lukastaegert</code></a>)</li>
<li><a
href="https://redirect.github.com/rollup/rollup/pull/6482">#6482</a>:
Remove unused rendered module sources map (<a
href="https://github.com/yoominho91"><code>@​yoominho91</code></a>, <a
href="https://github.com/irontaek"><code>@​irontaek</code></a>, <a
href="https://github.com/lukastaegert"><code>@​lukastaegert</code></a>)</li>
<li><a
href="https://redirect.github.com/rollup/rollup/pull/6483">#6483</a>:
chore(deps): update minor/patch updates (<a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot])</li>
<li><a
href="https://redirect.github.com/rollup/rollup/pull/6484">#6484</a>:
fix(deps): update swc monorepo (major) (<a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot], <a
href="https://github.com/lukastaegert"><code>@​lukastaegert</code></a>)</li>
<li><a
href="https://redirect.github.com/rollup/rollup/pull/6485">#6485</a>:
chore(deps): lock file maintenance (<a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot], <a
href="https://github.com/lukastaegert"><code>@​lukastaegert</code></a>)</li>
<li><a
href="https://redirect.github.com/rollup/rollup/pull/6486">#6486</a>:
chore(deps): lock file maintenance (<a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot])</li>
</ul>
<h2>4.62.5</h2>
<p><em>2026-08-20</em></p>
<h3>Bug Fixes</h3>
<ul>
<li>Resolve an issue where compact mode could result in invalid module
concatenations (<a
href="https://redirect.github.com/rollup/rollup/issues/6468">#6468</a>)</li>
</ul>
<h3>Pull Requests</h3>
<ul>
<li><a
href="https://redirect.github.com/rollup/rollup/pull/6468">#6468</a>:
Keep the semicolon added after a replaced default export (<a
href="https://github.com/Jaybhade"><code>@​Jaybhade</code></a>, <a
href="https://github.com/lukastaegert"><code>@​lukastaegert</code></a>)</li>
<li><a
href="https://redirect.github.com/rollup/rollup/pull/6469">#6469</a>:
fix(deps): update minor/patch updates (<a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot])</li>
<li><a
href="https://redirect.github.com/rollup/rollup/pull/6470">#6470</a>:
fix(deps): update swc monorepo (major) (<a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot])</li>
<li><a
href="https://redirect.github.com/rollup/rollup/pull/6471">#6471</a>:
chore(deps): lock file maintenance (<a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot])</li>
<li><a
href="https://redirect.github.com/rollup/rollup/pull/6472">#6472</a>:
chore(deps): update dependency eslint-plugin-unicorn to v73 (<a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot])</li>
<li><a
href="https://redirect.github.com/rollup/rollup/pull/6476">#6476</a>:
chore(deps): update dtolnay/rust-toolchain digest to 4360b52 (<a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot])</li>
<li><a
href="https://redirect.github.com/rollup/rollup/pull/6477">#6477</a>:
fix(deps): update minor/patch updates (<a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot])</li>
<li><a
href="https://redirect.github.com/rollup/rollup/pull/6478">#6478</a>:
chore(deps): lock file maintenance (<a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot])</li>
<li><a
href="https://redirect.github.com/rollup/rollup/pull/6479">#6479</a>:
chore(deps): lock file maintenance (<a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot])</li>
<li><a
href="https://redirect.github.com/rollup/rollup/pull/6480">#6480</a>:
chore(deps): lock file maintenance (<a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot])</li>
</ul>
<h2>4.62.4</h2>
<p><em>2026-08-01</em></p>
<h3>Bug Fixes</h3>
<ul>
<li>Resolve a regression when using Rollup on older Linux distributions
(<a
href="https://redirect.github.com/rollup/rollup/issues/6467">#6467</a>)</li>
</ul>
<h3>Pull Requests</h3>
<ul>
<li><a
href="https://redirect.github.com/rollup/rollup/pull/6463">#6463</a>:
docs: add llms.txt documentation index for LLMs and agents (<a
href="https://github.com/abyworkings-coder"><code>@​abyworkings-coder</code></a>,
<a
href="https://github.com/lukastaegert"><code>@​lukastaegert</code></a>)</li>
<li><a
href="https://redirect.github.com/rollup/rollup/pull/6464">#6464</a>:
fix(deps): update minor/patch updates (<a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot])</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/rollup/rollup/commit/34b8b924c815ec9413d7821f6fd54cc615584a51"><code>34b8b92</code></a>
4.63.0</li>
<li><a
href="https://github.com/rollup/rollup/commit/456b237dbfcc35c48d76c6be2060f881f440a532"><code>456b237</code></a>
feat: improve function return value tracking (<a
href="https://redirect.github.com/rollup/rollup/issues/6065">#6065</a>)</li>
<li><a
href="https://github.com/rollup/rollup/commit/21528bb381e0c5a5853f91e04d597fa2f45568fa"><code>21528bb</code></a>
fix(deps): update swc monorepo (major) (<a
href="https://redirect.github.com/rollup/rollup/issues/6484">#6484</a>)</li>
<li><a
href="https://github.com/rollup/rollup/commit/250b175b33b6a3ef96b54d509137f23db669ee9f"><code>250b175</code></a>
chore(deps): lock file maintenance (<a
href="https://redirect.github.com/rollup/rollup/issues/6486">#6486</a>)</li>
<li><a
href="https://github.com/rollup/rollup/commit/89bda2cd8e9def2ea037e7dbffaf392ce9f1ddcb"><code>89bda2c</code></a>
chore(deps): update minor/patch updates (<a
href="https://redirect.github.com/rollup/rollup/issues/6483">#6483</a>)</li>
<li><a
href="https://github.com/rollup/rollup/commit/f0b0413470667e1c4efe6e07ef9aecc144a2a950"><code>f0b0413</code></a>
chore(deps): lock file maintenance (<a
href="https://redirect.github.com/rollup/rollup/issues/6485">#6485</a>)</li>
<li><a
href="https://github.com/rollup/rollup/commit/a362d28d4cc01513c927678d068182f569954eba"><code>a362d28</code></a>
Remove unused rendered module sources map (<a
href="https://redirect.github.com/rollup/rollup/issues/6482">#6482</a>)</li>
<li><a
href="https://github.com/rollup/rollup/commit/c20402e2d4498a5861a4f49e00b2e7446c9900bb"><code>c20402e</code></a>
4.62.5</li>
<li><a
href="https://github.com/rollup/rollup/commit/e24957a6d37553bab48149ba0d7e20c476dfd294"><code>e24957a</code></a>
Keep the semicolon added after a replaced default export (<a
href="https://redirect.github.com/rollup/rollup/issues/6468">#6468</a>)</li>
<li><a
href="https://github.com/rollup/rollup/commit/4b6bc39ea71c5f7ce346da8151657d7fcaae926e"><code>4b6bc39</code></a>
chore(deps): update dtolnay/rust-toolchain digest to 4360b52 (<a
href="https://redirect.github.com/rollup/rollup/issues/6476">#6476</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/rollup/rollup/compare/v4.62.3...v4.63.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `typescript-eslint` from 8.65.0 to 8.68.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/typescript-eslint/typescript-eslint/releases">typescript-eslint's
releases</a>.</em></p>
<blockquote>
<h2>v8.68.0</h2>
<h2>8.68.0 (2026-08-24)</h2>
<h3>🚀 Features</h3>
<ul>
<li><strong>eslint-plugin:</strong> [strict-void-return] add fix
suggestions (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12086">#12086</a>)</li>
<li><strong>utils:</strong> support ESLint rule meta.languages (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12663">#12663</a>)</li>
</ul>
<h3>🩹 Fixes</h3>
<ul>
<li><strong>eslint-plugin:</strong> [unified-signatures] deduplicate
types in report (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12656">#12656</a>)</li>
<li><strong>eslint-plugin:</strong> [return-await] prevent autofix from
breaking code in arrow-functions (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12707">#12707</a>)</li>
<li><strong>eslint-plugin:</strong> [unified-signatures] report
identical signatures (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12678">#12678</a>)</li>
<li><strong>eslint-plugin:</strong> [no-unnecessary-type-assertion]
prevent stack overflow in recursive types (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12711">#12711</a>)</li>
<li><strong>eslint-plugin:</strong> [no-floating-promises] setting
<code>ignoreVoid: false</code> results in false negative in
ArrowFunctionExpression (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12646">#12646</a>)</li>
<li><strong>eslint-plugin:</strong> [no-empty-object-type] ignore
suggestions that result in invalid interfaces and export defaults (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12739">#12739</a>)</li>
<li><strong>website:</strong> playground crashes on <code>extends</code>
configs (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12608">#12608</a>)</li>
<li><strong>website:</strong> account for thanks.dev and out-of-band
donors in sponsors list (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12735">#12735</a>)</li>
</ul>
<h3>❤️ Thank You</h3>
<ul>
<li>Evyatar Daud <a
href="https://github.com/StyleShit"><code>@​StyleShit</code></a></li>
<li>Hugo <a
href="https://github.com/hugop95"><code>@​hugop95</code></a></li>
<li>Josh Goldberg ✨</li>
<li>Niki <a
href="https://github.com/phaux"><code>@​phaux</code></a></li>
<li>Thiago Barbosa</li>
<li>Younsang Na <a
href="https://github.com/nayounsang"><code>@​nayounsang</code></a></li>
</ul>
<p>See <a
href="https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.68.0">GitHub
Releases</a> for more information.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>v8.67.0</h2>
<h2>8.67.0 (2026-08-10)</h2>
<h3>🚀 Features</h3>
<ul>
<li><strong>typescript-eslint:</strong> export basic globs for using
tseslint (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12105">#12105</a>)</li>
</ul>
<h3>❤️ Thank You</h3>
<ul>
<li>Evyatar Daud <a
href="https://github.com/StyleShit"><code>@​StyleShit</code></a></li>
<li>Josh Goldberg ✨</li>
<li>Kirk Waiblinger <a
href="https://github.com/kirkwaiblinger"><code>@​kirkwaiblinger</code></a></li>
</ul>
<p>See <a
href="https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.67.0">GitHub
Releases</a> for more information.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>v8.66.0</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md">typescript-eslint's
changelog</a>.</em></p>
<blockquote>
<h2>8.68.0 (2026-08-24)</h2>
<p>This was a version bump only for typescript-eslint to align it with
other projects, there were no code changes.</p>
<p>See <a
href="https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.68.0">GitHub
Releases</a> for more information.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>8.67.0 (2026-08-10)</h2>
<h3>🚀 Features</h3>
<ul>
<li><strong>typescript-eslint:</strong> export basic globs for using
tseslint (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12105">#12105</a>)</li>
</ul>
<h3>❤️ Thank You</h3>
<ul>
<li>Claude Sonnet 5</li>
<li>Evyatar Daud <a
href="https://github.com/StyleShit"><code>@​StyleShit</code></a></li>
<li>Josh Goldberg</li>
<li>Josh Goldberg ✨</li>
<li>Kirk Waiblinger <a
href="https://github.com/kirkwaiblinger"><code>@​kirkwaiblinger</code></a></li>
</ul>
<p>See <a
href="https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.67.0">GitHub
Releases</a> for more information.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>8.66.0 (2026-08-03)</h2>
<p>This was a version bump only for typescript-eslint to align it with
other projects, there were no code changes.</p>
<p>See <a
href="https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.66.0">GitHub
Releases</a> for more information.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/8f4e00a4e8f3bdf93a5e5e8bc568ba1c15a4f896"><code>8f4e00a</code></a>
chore(release): publish 8.68.0</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/55f6d5d4ca39d2fab93db97ced497b956017878d"><code>55f6d5d</code></a>
chore: enable source maps (<a
href="https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint/issues/12677">#12677</a>)</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/20a261fb8e62351e88176b075090dc9276d26072"><code>20a261f</code></a>
chore(release): publish 8.67.0</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/c245fbb611d8cff3199ffa3a169df156d0e35928"><code>c245fbb</code></a>
feat(typescript-eslint): export basic globs for using tseslint (<a
href="https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint/issues/12105">#12105</a>)</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/3b155bb1344fd7ce83086cf2f864a7e8f3b4a217"><code>3b155bb</code></a>
chore: use typescript 7 for typechecking (<a
href="https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint/issues/12601">#12601</a>)</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/e51b11ba3ab31837762c675f62f0d4dcb1abc4fb"><code>e51b11b</code></a>
chore(release): publish 8.66.0</li>
<li>See full diff in <a
href="https://github.com/typescript-eslint/typescript-eslint/commits/v8.68.0/packages/typescript-eslint">compare
view</a></li>
</ul>
</details>
<br />

Updates `@salesforce/vscode-services` from 67.13.3 to 67.15.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/forcedotcom/salesforcedx-vscode/releases">@​salesforce/vscode-services's
releases</a>.</em></p>
<blockquote>
<h2>salesforcedx-vscode v67.15.0 (Nightly devel…
…y with 3 updates (certinia#990)

Bumps the production-dependencies group with 3 updates in the /
directory:
[@apexdevtools/apex-parser](https://github.com/apex-dev-tools/apex-parser),
[vscode-uri](https://github.com/microsoft/vscode-uri) and
[pixi.js](https://github.com/pixijs/pixijs).

Updates `@apexdevtools/apex-parser` from 5.1.0 to 5.2.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/apex-dev-tools/apex-parser/releases">@​apexdevtools/apex-parser's
releases</a>.</em></p>
<blockquote>
<h2>v5.2.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Build and publish with JDK 17 by <a
href="https://github.com/nawforce"><code>@​nawforce</code></a> in <a
href="https://redirect.github.com/apex-dev-tools/apex-parser/pull/139">apex-dev-tools/apex-parser#139</a></li>
<li>chore(deps): bump actions/setup-node from 6 to 7 in the actions
group by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/apex-dev-tools/apex-parser/pull/134">apex-dev-tools/apex-parser#134</a></li>
<li>chore(deps-dev): bump the npm-minor-patch group across 1 directory
with 3 updates by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/apex-dev-tools/apex-parser/pull/136">apex-dev-tools/apex-parser#136</a></li>
<li>chore(deps-dev): bump org.apache.maven.plugins:maven-jar-plugin from
3.5.0 to 3.5.1 in /jvm in the maven-minor-patch group by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/apex-dev-tools/apex-parser/pull/137">apex-dev-tools/apex-parser#137</a></li>
<li>chore(deps-dev): bump the npm-minor-patch group across 1 directory
with 3 updates by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/apex-dev-tools/apex-parser/pull/138">apex-dev-tools/apex-parser#138</a></li>
<li>chore(deps-dev): remediate npm dev-dependency security advisories by
<a href="https://github.com/nawforce"><code>@​nawforce</code></a> in <a
href="https://redirect.github.com/apex-dev-tools/apex-parser/pull/140">apex-dev-tools/apex-parser#140</a></li>
<li>chore(deps-dev): bump the npm-minor-patch group in /npm with 3
updates by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/apex-dev-tools/apex-parser/pull/143">apex-dev-tools/apex-parser#143</a></li>
<li>chore(deps-dev): bump lint-staged from 17.2.0 to 17.3.0 in the
npm-minor-patch group by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/apex-dev-tools/apex-parser/pull/144">apex-dev-tools/apex-parser#144</a></li>
<li>Fix dataCategoryName: close parenthesized data category list with
RPAREN by <a
href="https://github.com/rickroesler"><code>@​rickroesler</code></a> in
<a
href="https://redirect.github.com/apex-dev-tools/apex-parser/pull/142">apex-dev-tools/apex-parser#142</a></li>
<li>chore(deps-dev): bump the npm-minor-patch group in /npm with 3
updates by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/apex-dev-tools/apex-parser/pull/148">apex-dev-tools/apex-parser#148</a></li>
<li>feat: support SOSL WITH SPELL_CORRECTION and WITH HIGHLIGHT by <a
href="https://github.com/nawforce"><code>@​nawforce</code></a> in <a
href="https://redirect.github.com/apex-dev-tools/apex-parser/pull/147">apex-dev-tools/apex-parser#147</a></li>
<li>fix: reject annotation forms that are not legal Apex by <a
href="https://github.com/nawforce"><code>@​nawforce</code></a> in <a
href="https://redirect.github.com/apex-dev-tools/apex-parser/pull/149">apex-dev-tools/apex-parser#149</a></li>
<li>chore: release 5.2.0 by <a
href="https://github.com/nawforce"><code>@​nawforce</code></a> in <a
href="https://redirect.github.com/apex-dev-tools/apex-parser/pull/152">apex-dev-tools/apex-parser#152</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/rickroesler"><code>@​rickroesler</code></a>
made their first contribution in <a
href="https://redirect.github.com/apex-dev-tools/apex-parser/pull/142">apex-dev-tools/apex-parser#142</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/apex-dev-tools/apex-parser/compare/v5.1.0...v5.2.0">https://github.com/apex-dev-tools/apex-parser/compare/v5.1.0...v5.2.0</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/apex-dev-tools/apex-parser/blob/main/CHANGELOG.md">@​apexdevtools/apex-parser's
changelog</a>.</em></p>
<blockquote>
<h2>5.2.0 - 2026-08-21</h2>
<ul>
<li>Tighten the annotation grammar to reject constructs that are
inherited from Java but are not legal Apex
<ul>
<li><strong>(SOURCE BREAKING)</strong>
<code>ElementValueArrayInitializerContext</code> is no longer generated,
<code>AnnotationContext.qualifiedName()</code> becomes
<code>id()</code>, and <code>ElementValueContext</code> exposes only
<code>literal()</code>. Tree-walking consumers referencing these need
updating. This ships as a minor version, not a major one; grammar
changes of this kind are routine here and major bumps are reserved for
build-environment or large-scale changes</li>
<li><code>annotation</code> matches <code>id</code> in place of
<code>qualifiedName</code>; <code>@Schema.AuraEnabled</code> is now a
syntax error, matching the platform (<code>Unexpected token '.'</code>).
Apex has no user-defined annotations, so a namespace-qualified form has
never been legal</li>
<li><code>elementValue</code> matches <code>literal</code> in place of
<code>expression</code>, so a bare identifier value such as
<code>@AuraEnabled(cacheable=foo)</code> is now a syntax error, as it is
on the platform</li>
<li>Nested annotations and array initialiser values
(<code>label={'a','b'}</code>) are no longer accepted, and the
<code>elementValueArrayInitializer</code> rule is removed.
<code>elementValue</code> is now non-recursive</li>
<li>The optional <code>COMMA</code> separator between annotation
parameters is deliberately kept, and is now documented in the grammar as
the one exception. The platform separates parameters by whitespace
alone, but rejecting the comma form at parse time reproduces the
platform compiler's own failure mode, where a member-level annotation is
recovered as a constructor declaration and the rest of the file is lost
to cascading errors</li>
<li>Values the platform rejects for type reasons, such as
<code>@AuraEnabled(cacheable=0)</code> and <code>cacheable=null</code>,
still parse. That is intended, so a consumer can diagnose the value
precisely instead of losing the file to a syntax error</li>
<li>Add annotation parameter test coverage to both the maven and npm
targets</li>
</ul>
</li>
<li>Add <a
href="https://github.com/apex-dev-tools/apex-parser/blob/main/doc/SalesforceDifferences.md"><code>https://github.com/apex-dev-tools/apex-parser/blob/main/doc/SalesforceDifferences.md</code></a>,
recording deliberate differences between what this grammar accepts and
what the Salesforce platform compiler accepts, so they are not
mistakenly &quot;corrected&quot; later. The first entry is the
annotation parameter comma separator above</li>
<li>Support the SOSL <code>WITH SPELL_CORRECTION = { true | false
}</code> clause, e.g. <code>[FIND :term IN ALL FIELDS RETURNING Account
WITH SPELL_CORRECTION = false]</code>; an Apex bind variable
(<code>:expr</code>) is also accepted in place of the literal</li>
<li>Support the SOSL <code>WITH HIGHLIGHT</code> clause, e.g.
<code>[FIND 'salesforce' IN ALL FIELDS RETURNING Account(Name,
Description) WITH HIGHLIGHT]</code></li>
<li>New <code>HIGHLIGHT</code> and <code>SPELL_CORRECTION</code> lexer
tokens; both are also accepted as identifiers
(<code>id</code>/<code>anyId</code>), so existing code using them as
names is unaffected</li>
<li>Fix the <code>dataCategoryName</code> grammar rule so parenthesized
SOQL data category lists close with <code>RPAREN</code>; previously,
valid multi-category <code>WITH DATA CATEGORY</code> filters failed to
parse</li>
<li>Fix <code>WITH DATA CATEGORY</code> filters with more than one
selection. <code>filteringExpression</code> joined selections with the
<code>AND</code> token, which is the Java <code>&amp;&amp;</code>
operator, not the SOQL <code>and</code> keyword. In SOSL this was a
parse error; in SOQL the trailing selections were silently left
unconsumed</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/apex-dev-tools/apex-parser/commit/3c9d2a9a2caa64e1c53847859bc410db7aad0401"><code>3c9d2a9</code></a>
Merge pull request <a
href="https://redirect.github.com/apex-dev-tools/apex-parser/issues/152">#152</a>
from apex-dev-tools/ao/adt-45</li>
<li><a
href="https://github.com/apex-dev-tools/apex-parser/commit/1d1bcd3b561a8134b71eb883a9ffd5e6ff128db3"><code>1d1bcd3</code></a>
chore: release 5.2.0</li>
<li><a
href="https://github.com/apex-dev-tools/apex-parser/commit/30374e7d0a419e920c631c9dccc54327c22b8c5a"><code>30374e7</code></a>
Merge pull request <a
href="https://redirect.github.com/apex-dev-tools/apex-parser/issues/149">#149</a>
from apex-dev-tools/ao/adt-44</li>
<li><a
href="https://github.com/apex-dev-tools/apex-parser/commit/710f181d5335208380e65db1581e53054bae97b9"><code>710f181</code></a>
docs: record deliberate differences from platform behaviour</li>
<li><a
href="https://github.com/apex-dev-tools/apex-parser/commit/a6cfe935d48758c11f5aaa41ccb2d6bbb0b55040"><code>a6cfe93</code></a>
fix: reject annotation forms that are not legal Apex</li>
<li><a
href="https://github.com/apex-dev-tools/apex-parser/commit/6f7ff784cc428948d748f4fe5e3ed72ddd732d64"><code>6f7ff78</code></a>
Merge pull request <a
href="https://redirect.github.com/apex-dev-tools/apex-parser/issues/147">#147</a>
from apex-dev-tools/ao/adt-43</li>
<li><a
href="https://github.com/apex-dev-tools/apex-parser/commit/584c80ceee496f0f53ef845b6503747d97a73239"><code>584c80c</code></a>
Merge pull request <a
href="https://redirect.github.com/apex-dev-tools/apex-parser/issues/148">#148</a>
from apex-dev-tools/dependabot/npm_and_yarn/npm/npm-m...</li>
<li><a
href="https://github.com/apex-dev-tools/apex-parser/commit/eec9864274aa81fc8f71d1245d5deea890a3a3de"><code>eec9864</code></a>
chore(deps-dev): bump the npm-minor-patch group in /npm with 3
updates</li>
<li><a
href="https://github.com/apex-dev-tools/apex-parser/commit/7cd34514c906149f704a5e09ed40fd19505b04dc"><code>7cd3451</code></a>
feat: support SOSL WITH SPELL_CORRECTION and WITH HIGHLIGHT</li>
<li><a
href="https://github.com/apex-dev-tools/apex-parser/commit/3b02a35f17790e2ba53288f1d06fc566867da0fa"><code>3b02a35</code></a>
Merge pull request <a
href="https://redirect.github.com/apex-dev-tools/apex-parser/issues/142">#142</a>
from rickroesler/fix/data-category-name-rparen</li>
<li>Additional commits viewable in <a
href="https://github.com/apex-dev-tools/apex-parser/compare/v5.1.0...v5.2.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `vscode-uri` from 3.1.0 to 3.2.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/microsoft/vscode-uri/releases">vscode-uri's
releases</a>.</em></p>
<blockquote>
<h2>v3.2.0</h2>
<h2>Changes:</h2>
<ul>
<li><a
href="https://redirect.github.com/microsoft/vscode-uri/issues/65">#65</a>:
chore: bump minor version to 3.2.0</li>
<li><a
href="https://redirect.github.com/microsoft/vscode-uri/issues/59">#59</a>:
Restore the default export</li>
<li><a
href="https://redirect.github.com/microsoft/vscode-uri/issues/63">#63</a>:
Bump brace-expansion from 2.1.1 to 2.1.4</li>
<li><a
href="https://redirect.github.com/microsoft/vscode-uri/issues/64">#64</a>:
Bump js-yaml from 4.3.0 to 4.3.1</li>
<li><a
href="https://redirect.github.com/microsoft/vscode-uri/issues/62">#62</a>:
Bump fast-uri from 3.1.4 to 3.1.5</li>
<li><a
href="https://redirect.github.com/microsoft/vscode-uri/issues/61">#61</a>:
Bump js-yaml from 4.2.0 to 4.3.0</li>
<li><a
href="https://redirect.github.com/microsoft/vscode-uri/issues/60">#60</a>:
Bump fast-uri from 3.1.2 to 3.1.4</li>
<li><a
href="https://redirect.github.com/microsoft/vscode-uri/issues/58">#58</a>:
chore: bump patch version to 3.1.1</li>
<li><a
href="https://redirect.github.com/microsoft/vscode-uri/issues/57">#57</a>:
Use Yarn resolutions to resolve remaining mocha audit alerts</li>
<li><a
href="https://redirect.github.com/microsoft/vscode-uri/issues/56">#56</a>:
Bump fast-uri from 3.1.0 to 3.1.2</li>
</ul>
<!-- raw HTML omitted -->
<ul>
<li><a
href="https://redirect.github.com/microsoft/vscode-uri/issues/55">#55</a>:
Bump picomatch from 2.3.1 to 2.3.2</li>
<li><a
href="https://redirect.github.com/microsoft/vscode-uri/issues/54">#54</a>:
Bump webpack from 5.94.0 to 5.104.1</li>
<li><a
href="https://redirect.github.com/microsoft/vscode-uri/issues/52">#52</a>:
Bump glob from 10.3.10 to 10.5.0</li>
<li><a
href="https://redirect.github.com/microsoft/vscode-uri/issues/51">#51</a>:
Bump js-yaml from 4.1.0 to 4.1.1</li>
<li><a
href="https://redirect.github.com/microsoft/vscode-uri/issues/50">#50</a>:
chore: bump action and node versions</li>
<li><a
href="https://redirect.github.com/microsoft/vscode-uri/issues/49">#49</a>:
Bump serialize-javascript from 6.0.1 to 6.0.2</li>
</ul>
<p>This list of changes was <a
href="https://dev.azure.com/monacotools/Monaco/_build/results?buildId=467111&amp;view=logs">auto
generated</a>.<!-- raw HTML omitted --></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/microsoft/vscode-uri/commit/c22523764aa041c34841c42b815d280a694593b8"><code>c225237</code></a>
Merge pull request <a
href="https://redirect.github.com/microsoft/vscode-uri/issues/65">#65</a>
from microsoft/agents/version-bump-and-pr</li>
<li><a
href="https://github.com/microsoft/vscode-uri/commit/1524a350c93a0f6df9076671bb1d37cd6d8fd895"><code>1524a35</code></a>
chore: bump minor version to 3.2.0</li>
<li><a
href="https://github.com/microsoft/vscode-uri/commit/b402e950bba24343bc0f3979a300b1969abe9440"><code>b402e95</code></a>
Merge pull request <a
href="https://redirect.github.com/microsoft/vscode-uri/issues/59">#59</a>
from remcohaszing/restore-default-export</li>
<li><a
href="https://github.com/microsoft/vscode-uri/commit/67ce68fd2aa067c299edd03ab3271a842b51ca18"><code>67ce68f</code></a>
Fix the ESM emit</li>
<li><a
href="https://github.com/microsoft/vscode-uri/commit/f2623f241e58f33883c02823a24158d2f776009e"><code>f2623f2</code></a>
Bump brace-expansion from 2.1.1 to 2.1.4 (<a
href="https://redirect.github.com/microsoft/vscode-uri/issues/63">#63</a>)</li>
<li><a
href="https://github.com/microsoft/vscode-uri/commit/a34510828d23b072838c597e709e9436dfb5a22a"><code>a345108</code></a>
Bump js-yaml from 4.3.0 to 4.3.1 (<a
href="https://redirect.github.com/microsoft/vscode-uri/issues/64">#64</a>)</li>
<li><a
href="https://github.com/microsoft/vscode-uri/commit/fdb6abd89190b97fedf40e2a7f8e6a13551e4a9c"><code>fdb6abd</code></a>
Bump fast-uri from 3.1.4 to 3.1.5 (<a
href="https://redirect.github.com/microsoft/vscode-uri/issues/62">#62</a>)</li>
<li><a
href="https://github.com/microsoft/vscode-uri/commit/a8445fcdcf3766d5014a3ac6e32599f0ece5ebf5"><code>a8445fc</code></a>
Bump js-yaml from 4.2.0 to 4.3.0 (<a
href="https://redirect.github.com/microsoft/vscode-uri/issues/61">#61</a>)</li>
<li><a
href="https://github.com/microsoft/vscode-uri/commit/2b9a45a570c62085eae3e988a74aa9b59ac30d37"><code>2b9a45a</code></a>
Bump fast-uri from 3.1.2 to 3.1.4 (<a
href="https://redirect.github.com/microsoft/vscode-uri/issues/60">#60</a>)</li>
<li><a
href="https://github.com/microsoft/vscode-uri/commit/b24df9d17e4406e3e68c0630f4d5938228dc13e5"><code>b24df9d</code></a>
Restore the default export</li>
<li>Additional commits viewable in <a
href="https://github.com/microsoft/vscode-uri/compare/v3.1.0...v3.2.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `pixi.js` from 8.19.0 to 8.20.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/pixijs/pixijs/releases">pixi.js's
releases</a>.</em></p>
<blockquote>
<h2>v8.20.1</h2>
<h2>💾 Download</h2>
<p>Installation:</p>
<pre lang="bash"><code>npm install pixi.js@8.20.1
</code></pre>
<p>Development Build:</p>
<ul>
<li><a
href="https://cdn.jsdelivr.net/npm/pixi.js@8.20.1/dist/pixi.js">https://cdn.jsdelivr.net/npm/pixi.js@8.20.1/dist/pixi.js</a></li>
<li><a
href="https://cdn.jsdelivr.net/npm/pixi.js@8.20.1/dist/pixi.mjs">https://cdn.jsdelivr.net/npm/pixi.js@8.20.1/dist/pixi.mjs</a></li>
</ul>
<p>Production Build:</p>
<ul>
<li><a
href="https://cdn.jsdelivr.net/npm/pixi.js@8.20.1/dist/pixi.min.js">https://cdn.jsdelivr.net/npm/pixi.js@8.20.1/dist/pixi.min.js</a></li>
<li><a
href="https://cdn.jsdelivr.net/npm/pixi.js@8.20.1/dist/pixi.min.mjs">https://cdn.jsdelivr.net/npm/pixi.js@8.20.1/dist/pixi.min.mjs</a></li>
</ul>
<p>Documentation:</p>
<ul>
<li><a
href="https://pixijs.download/v8.20.1/docs/index.html">https://pixijs.download/v8.20.1/docs/index.html</a></li>
</ul>
<h2>Changed</h2>
<p><a
href="https://github.com/pixijs/pixijs/compare/v8.20.0...v8.20.1">https://github.com/pixijs/pixijs/compare/v8.20.0...v8.20.1</a></p>
<h3>🐛 Fixed</h3>
<ul>
<li>fix: preserve UBO offsets in unsafe-eval polyfill by <a
href="https://github.com/darkdi"><code>@​darkdi</code></a> in <a
href="https://redirect.github.com/pixijs/pixijs/pull/12154">pixijs/pixijs#12154</a></li>
<li>fix: svg radial gradients render as a linear gradient by <a
href="https://github.com/creativoma"><code>@​creativoma</code></a> in <a
href="https://redirect.github.com/pixijs/pixijs/pull/12156">pixijs/pixijs#12156</a></li>
<li>fix: detach from shared <code>TextStyle</code> on destroy by <a
href="https://github.com/qiao-coding"><code>@​qiao-coding</code></a> in
<a
href="https://redirect.github.com/pixijs/pixijs/pull/12159">pixijs/pixijs#12159</a></li>
</ul>
<h3>🧹 Chores</h3>
<ul>
<li>chore: bump <code>@xmldom/xmldom</code> to 0.8.15 by <a
href="https://github.com/Zyie"><code>@​Zyie</code></a> in <a
href="https://redirect.github.com/pixijs/pixijs/pull/12162">pixijs/pixijs#12162</a>
<ul>
<li>Removes the <code>npm warn deprecated @xmldom/xmldom@0.8.14</code>
warning printed when installing <code>pixi.js</code>.</li>
</ul>
</li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/darkdi"><code>@​darkdi</code></a> made
their first contribution in <a
href="https://redirect.github.com/pixijs/pixijs/pull/12154">pixijs/pixijs#12154</a></li>
<li><a
href="https://github.com/qiao-coding"><code>@​qiao-coding</code></a>
made their first contribution in <a
href="https://redirect.github.com/pixijs/pixijs/pull/12159">pixijs/pixijs#12159</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/pixijs/pixijs/compare/v8.20.0...v8.20.1">https://github.com/pixijs/pixijs/compare/v8.20.0...v8.20.1</a></p>
<h2>v8.20.0</h2>
<h2>💾 Download</h2>
<p>Installation:</p>
<pre lang="bash"><code>npm install pixi.js@8.20.0
</code></pre>
<p>Development Build:</p>
<ul>
<li><a
href="https://cdn.jsdelivr.net/npm/pixi.js@8.20.0/dist/pixi.js">https://cdn.jsdelivr.net/npm/pixi.js@8.20.0/dist/pixi.js</a></li>
<li><a
href="https://cdn.jsdelivr.net/npm/pixi.js@8.20.0/dist/pixi.mjs">https://cdn.jsdelivr.net/npm/pixi.js@8.20.0/dist/pixi.mjs</a></li>
</ul>
<p>Production Build:</p>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/pixijs/pixijs/commit/3b6b5635deb9edd09f3eafd548b1e82685853ea7"><code>3b6b563</code></a>
v8.20.1</li>
<li><a
href="https://github.com/pixijs/pixijs/commit/1f88cb462f175da9be5ced11e8e6b002d8483c9b"><code>1f88cb4</code></a>
chore: bump <code>@​xmldom/xmldom</code> to 0.8.15 (<a
href="https://redirect.github.com/pixijs/pixijs/issues/12162">#12162</a>)</li>
<li><a
href="https://github.com/pixijs/pixijs/commit/4b6211d732cfbc2c02befeddcd19f734c75b39f4"><code>4b6211d</code></a>
fix: detach from shared TextStyle on destroy (<a
href="https://redirect.github.com/pixijs/pixijs/issues/12049">#12049</a>)
(<a
href="https://redirect.github.com/pixijs/pixijs/issues/12159">#12159</a>)</li>
<li><a
href="https://github.com/pixijs/pixijs/commit/0cb1259f2c64d826a7c9a606fa1034da09533a85"><code>0cb1259</code></a>
fix(svg): parse radial gradients and percentage coordinates (<a
href="https://redirect.github.com/pixijs/pixijs/issues/12156">#12156</a>)</li>
<li><a
href="https://github.com/pixijs/pixijs/commit/e209f282f006b79e001da5305bd929bab383cd03"><code>e209f28</code></a>
fix: preserve UBO offsets in unsafe-eval polyfill (<a
href="https://redirect.github.com/pixijs/pixijs/issues/12154">#12154</a>)</li>
<li><a
href="https://github.com/pixijs/pixijs/commit/e4228cec9e6b432f81b7face6d7dd21ecf58e6dd"><code>e4228ce</code></a>
v8.20.0</li>
<li><a
href="https://github.com/pixijs/pixijs/commit/9ce96bef5a0748336cb1b2428c443502e504c84f"><code>9ce96be</code></a>
Apply render group world color and alpha to ParticleContainer (<a
href="https://redirect.github.com/pixijs/pixijs/issues/12132">#12132</a>)</li>
<li><a
href="https://github.com/pixijs/pixijs/commit/a58fe50d44b64c9b5d8eefc8b2a16740a785e6b1"><code>a58fe50</code></a>
fix: WebGPU ignores clockwiseFrontFace (<a
href="https://redirect.github.com/pixijs/pixijs/issues/12139">#12139</a>)</li>
<li><a
href="https://github.com/pixijs/pixijs/commit/bdf53b579e43b74c58b69608922747021f0c56f0"><code>bdf53b5</code></a>
fix: WebGPU sibling sprite masks rendering with each other's mask matrix
(<a
href="https://redirect.github.com/pixijs/pixijs/issues/12">#12</a>...</li>
<li><a
href="https://github.com/pixijs/pixijs/commit/42810dcef93f512b8addd8a53d2b5755641a071c"><code>42810dc</code></a>
feat(rendering): export GPU shader layout helpers for advanced users (<a
href="https://redirect.github.com/pixijs/pixijs/issues/12143">#12143</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/pixijs/pixijs/compare/v8.19.0...v8.20.1">compare
view</a></li>
</ul>
</details>
<br />

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…updates (certinia#927)

Bumps the github-actions group with 2 updates in the / directory:
[pnpm/action-setup](https://github.com/pnpm/action-setup) and
[github/codeql-action](https://github.com/github/codeql-action).

Updates `pnpm/action-setup` from 6.0.9 to 6.0.10
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/pnpm/action-setup/releases">pnpm/action-setup's
releases</a>.</em></p>
<blockquote>
<h2>v6.0.10</h2>
<h2>What's Changed</h2>
<ul>
<li>docs(README): point users to the successor pnpm/setup action by <a
href="https://github.com/BlackHole1"><code>@​BlackHole1</code></a> in <a
href="https://redirect.github.com/pnpm/action-setup/pull/282">pnpm/action-setup#282</a></li>
<li>refactor: introduce restore keys for cache by <a
href="https://github.com/SukkaW"><code>@​SukkaW</code></a> in <a
href="https://redirect.github.com/pnpm/action-setup/pull/280">pnpm/action-setup#280</a></li>
<li>ci: use pnpm 11 for <code>pr-check</code> by <a
href="https://github.com/jamietanna"><code>@​jamietanna</code></a> in <a
href="https://redirect.github.com/pnpm/action-setup/pull/284">pnpm/action-setup#284</a></li>
<li>fix: update pnpm to v11.19.0 by <a
href="https://github.com/jamietanna"><code>@​jamietanna</code></a> in <a
href="https://redirect.github.com/pnpm/action-setup/pull/283">pnpm/action-setup#283</a></li>
<li>docs: update README to include devEngines.packageManager by <a
href="https://github.com/nemchik"><code>@​nemchik</code></a> in <a
href="https://redirect.github.com/pnpm/action-setup/pull/273">pnpm/action-setup#273</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/jamietanna"><code>@​jamietanna</code></a> made
their first contribution in <a
href="https://redirect.github.com/pnpm/action-setup/pull/284">pnpm/action-setup#284</a></li>
<li><a href="https://github.com/nemchik"><code>@​nemchik</code></a> made
their first contribution in <a
href="https://redirect.github.com/pnpm/action-setup/pull/273">pnpm/action-setup#273</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/pnpm/action-setup/compare/v6...v6.0.10">https://github.com/pnpm/action-setup/compare/v6...v6.0.10</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/pnpm/action-setup/commit/0977fd99725f1db4007ccb2928dbb4e90d06cc86"><code>0977fd9</code></a>
docs: Update README to include devEngines.packageManager (<a
href="https://redirect.github.com/pnpm/action-setup/issues/273">#273</a>)</li>
<li><a
href="https://github.com/pnpm/action-setup/commit/48261aca053e825d84804e8ce05524d558249ac9"><code>48261ac</code></a>
fix: update pnpm to v11.19.0 (<a
href="https://redirect.github.com/pnpm/action-setup/issues/283">#283</a>)</li>
<li><a
href="https://github.com/pnpm/action-setup/commit/75677f717d48404e86ae8ee4891543f40de175aa"><code>75677f7</code></a>
ci: use pnpm 11 for <code>pr-check</code> (<a
href="https://redirect.github.com/pnpm/action-setup/issues/284">#284</a>)</li>
<li><a
href="https://github.com/pnpm/action-setup/commit/769ae71fb33e6e448a5dc92ad5da997c268eecec"><code>769ae71</code></a>
refactor: introduce restore keys for cache (<a
href="https://redirect.github.com/pnpm/action-setup/issues/280">#280</a>)</li>
<li><a
href="https://github.com/pnpm/action-setup/commit/6fed91f804570c1144bfe1911c348642cb986bd4"><code>6fed91f</code></a>
docs(README): point users to the successor pnpm/setup action (<a
href="https://redirect.github.com/pnpm/action-setup/issues/282">#282</a>)</li>
<li>See full diff in <a
href="https://github.com/pnpm/action-setup/compare/v6.0.9...v6.0.10">compare
view</a></li>
</ul>
</details>
<br />

Updates `github/codeql-action` from 4.37.4 to 4.37.9
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/github/codeql-action/releases">github/codeql-action's
releases</a>.</em></p>
<blockquote>
<h2>v4.37.9</h2>
<ul>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.26.4">2.26.4</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/4106">#4106</a></li>
</ul>
<h2>v4.37.8</h2>
<p>No user facing changes.</p>
<h2>v4.37.7</h2>
<ul>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.26.3">2.26.3</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/4085">#4085</a></li>
</ul>
<h2>v4.37.6</h2>
<ul>
<li>Changed the default filepath for the new remote file address format
that was introduced in CodeQL Action 4.37.0 / 3.37.0 to
<code>.github/codeql-config.yml</code> to align it with the suggested
path that is used elsewhere. <a
href="https://redirect.github.com/github/codeql-action/pull/4070">#4070</a></li>
</ul>
<h2>v4.37.5</h2>
<ul>
<li>Fixed a bug where a network error while streaming the download of
the CodeQL bundle could terminate the <code>init</code> Action instead
of falling back to downloading the bundle before extracting it. <a
href="https://redirect.github.com/github/codeql-action/pull/4061">#4061</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/github/codeql-action/blob/main/CHANGELOG.md">github/codeql-action's
changelog</a>.</em></p>
<blockquote>
<h2>4.37.9 - 26 Aug 2026</h2>
<ul>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.26.4">2.26.4</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/4106">#4106</a></li>
</ul>
<h2>4.37.8 - 21 Aug 2026</h2>
<p>No user facing changes.</p>
<h2>4.37.7 - 13 Aug 2026</h2>
<ul>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.26.3">2.26.3</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/4085">#4085</a></li>
</ul>
<h2>4.37.6 - 04 Aug 2026</h2>
<ul>
<li>Changed the default filepath for the new remote file address format
that was introduced in CodeQL Action 4.37.0 / 3.37.0 to
<code>.github/codeql-config.yml</code> to align it with the suggested
path that is used elsewhere. <a
href="https://redirect.github.com/github/codeql-action/pull/4070">#4070</a></li>
</ul>
<h2>4.37.5 - 03 Aug 2026</h2>
<ul>
<li>Fixed a bug where a network error while streaming the download of
the CodeQL bundle could terminate the <code>init</code> Action instead
of falling back to downloading the bundle before extracting it. <a
href="https://redirect.github.com/github/codeql-action/pull/4061">#4061</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/github/codeql-action/commit/cdf488f595d80d6e07e03d4674febd5ab45fa938"><code>cdf488f</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/4107">#4107</a>
from github/update-v4.37.9-920ba7cd1</li>
<li><a
href="https://github.com/github/codeql-action/commit/7243f38558d187dde99730d224bb47aa26a95306"><code>7243f38</code></a>
Update changelog for v4.37.9</li>
<li><a
href="https://github.com/github/codeql-action/commit/920ba7cd1596037e042122c00381eb16b397d68e"><code>920ba7c</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/4106">#4106</a>
from github/update-bundle/codeql-bundle-v2.26.4</li>
<li><a
href="https://github.com/github/codeql-action/commit/ecfa6e16817b8f490bc9a59baa391baf4fa3e3c2"><code>ecfa6e1</code></a>
Add changelog note</li>
<li><a
href="https://github.com/github/codeql-action/commit/adcdf4a70d247343cf9c29e0f7a6658b51c3a2b1"><code>adcdf4a</code></a>
Update default bundle to codeql-bundle-v2.26.4</li>
<li><a
href="https://github.com/github/codeql-action/commit/486fec2a3ea2626afcd8c7e9208b4f515078dd7e"><code>486fec2</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/4099">#4099</a>
from github/update-supported-enterprise-server-versions</li>
<li><a
href="https://github.com/github/codeql-action/commit/134624c67b20869c2aaa36dafa726375b78a5d76"><code>134624c</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/4101">#4101</a>
from github/dependabot/npm_and_yarn/npm-minor-457d82...</li>
<li><a
href="https://github.com/github/codeql-action/commit/ff43db8f982a368288f117354fb8d046e937124c"><code>ff43db8</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/4103">#4103</a>
from github/mergeback/v4.37.8-to-main-db488dde</li>
<li><a
href="https://github.com/github/codeql-action/commit/4605e03a74cf891614c4d76f82384a16c1c11816"><code>4605e03</code></a>
Rebuild</li>
<li><a
href="https://github.com/github/codeql-action/commit/099c869cad6bf3b88657154d4ae47ffed27e632d"><code>099c869</code></a>
Update changelog and version after v4.37.8</li>
<li>Additional commits viewable in <a
href="https://github.com/github/codeql-action/compare/v4.37.4...v4.37.9">compare
view</a></li>
</ul>
</details>
<br />

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps `actions/upload-artifact` from v4 to v7 in `ci.yml`. Dependabot
did not propose it: the steps landed yesterday in certinia#954, and the
`github-actions` schedule is weekly.

## Why

v4 runs on Node 20. The runners force it onto Node 24 and warn on every
run:

```
Node.js 20 is deprecated. The following actions target Node.js 20 but are being
forced to run on Node.js 24: actions/upload-artifact@v4
```

## Breaking changes across the three majors

| Version | Change | Effect here |
|---|---|---|
| v5 | Node 24 support | none |
| v6 | `runs.using: node24`, needs runner 2.327.1 or later | none,
`ubuntu-latest` has it |
| v7 | ESM; new opt-in `archive` input | none, see below |

v7 adds `archive`. With `archive: false` the action ignores `name` and
takes a single file only. Both steps upload a directory and keep the
default, so `name` still applies.

All four inputs (`name`, `path`, `if-no-files-found`, `retention-days`)
are unchanged and valid in v7.

`@v7` follows the style of the other `actions/*` entries, which float on
the major.

## Verify

`prettier --check .github/workflows/ci.yml` passes. Both steps run `if:
failure()`, so CI green on this PR does not exercise them; a red run
does.
Removes the `salesforce` group from `.github/dependabot.yml`. It guards
a coupling that no longer exists.

## Why

The group was added in certinia#907 for this reason:

> exception: `@salesforce/apex-node` majors require the matching
`@salesforce/core` major, so these move in lockstep incl. majors

certinia#951 (`refactor(lana): use Salesforce Services`) moved `lana` onto
`@salesforce/vscode-services`. Neither `@salesforce/core` nor
`@salesforce/apex-node` is a direct dependency now.
`@salesforce/core@9.1.7` is left in the lockfile only under
`@salesforce/vscode-services` -> `@salesforce/source-deploy-retrieve`,
and dependabot does not raise version updates for transitive
dependencies.

## What is left

Both remaining `@salesforce/*` packages are dev dependencies, and their
versions are independent:

| Package | Range | Where |
|---|---|---|
| `@salesforce/playwright-vscode-ext` | `^1.3.10` | root |
| `@salesforce/vscode-services` | `^67.15.0` | `lana/` |

`development-dependencies` already covers them.
`@salesforce/vscode-services` 67.12 -> 67.15 arrived there in certinia#993.

## Effect

`@salesforce/*` majors now arrive as their own PR, which is what the
comment above `groups:` already asks for:

> majors are deliberately left out of the minor/patch groups so each one
still arrives as its own PR

So this makes the file consistent rather than changing policy.

## Verify

`prettier --check .github/dependabot.yml` passes. Config-only, so CI
does not exercise it; the next scheduled dependabot run is the real
check.
# PR overview

Follow-up to certinia#953 and certinia#957. `Log: Retrieve Apex Log And Show Analysis`
cannot work in the web
extension host, because the web bundle is split across two files.

## The problem

The web extension host does not use Node's loader. It fetches the entry
point as text and wraps
it:

```js
initFn = new Function('module', 'exports', 'require', fullSource);
```

The `require` it supplies resolves only `'vscode'`. `importScripts` is
blocked, and `require`
and `define` are set to `undefined` in the worker. The docs say it
plainly: "Importing or
requiring other modules is not supported... the code must be packaged to
a single file."

Both web builds emitted two files:

```
lana/out/web/
  Main.web.cjs
  lana-salesforceServices.js
```

`RetrieveLogFile.ts:56` does `await
import('../services/salesforceServices.js')`, which rollup
lowers to `require("./lana-salesforceServices.js")`. That require throws
in the web host.

It sits in the lazy path near the end of the file, not at the top, so
the extension still
activates and only Retrieve is affected.

## Changes made

- `rollup.config.mjs`: `inlineDynamicImports: true` on the web output.
- `rolldown.config.ts`: `codeSplitting: false` on the web output.
Rolldown deprecates
  `inlineDynamicImports` in favour of this name, hence the difference.
- Drop `chunkFileNames` from both, now that neither emits a chunk.

## Type of change

- [x] Bug fix

## Validation

Built both paths, production mode:

| | before | after |
|---|---|---|
| rollup `lana/out/web/` | 2 files | **1 file**, `Main.web.cjs`, 806,071
bytes |
| rolldown `lana/out/web/` | 2 files | **1 file**, `Main.web.cjs` |
| requires in the entry | `require("vscode")` +
`require("./lana-salesforceServices.js")` | **`require("vscode")` only**
|

The desktop entry is unchanged and still ESM.

Not validated: I have not run this in a live web host, so the fix is
verified against the
emitted bundle and the documented loader, not observed. The web e2e in
CI exercises
`Log: Show Apex Log Analysis`, not Retrieve, so it will not catch this
either way.

## Related

Considered and rejected in the same area: dropping `nodePolyfills()`
from the web target. The
build succeeds without it, but 11 `process.` references survive, and
while most are guarded by
`typeof process`, `path.resolve()`'s shim calls a bare `process.cwd()`.
Removing the plugin
would turn a working shim into a latent `ReferenceError`, so it stays.
…#997)

# PR overview

The remaining findings from the certinia#952 review, after certinia#988 took the
blocking one.
Five independent commits; any can be dropped without affecting the
others.

## Changes made

**Stop reading the whole log to set the context key.** The tab fallback
only runs
when VS Code refused to open the file as a document, so sniffing it
pulled the
entire file through `workspace.fs`, which has no ranged read. Measured
on the
19.7MB sample log: **0.056ms to 2.9ms and a 163MB RSS peak, on every tab
event** —
and worse over the provider RPC in the web host, where a 100MB log
allocates
100MB inside a browser tab. It now decides from the `.log`/`.txt`
extension
there, which makes the branch synchronous and retires the generation
guards
added for the async read. Closes the thread left open on certinia#952.

**Only parse a log the user is viewing as a text tab.** Dropping the
`scheme: 'file'` selectors in certinia#952 was right and is not reverted here,
but it let
`warmAndSignal` parse either side of a diff — a full read and parse of a
log
being diffed, evicting real entries from the 10-item cache. New
`isOpenAsTextTab` gates the UI-driven callers (folding warm and
provider,
document symbols, the line decoration, the code lens). Explicit commands
stay
ungated since they can run with no tab open.

**Stop the save dialog defaulting to the extension directory.** With no
workspace
folder open it offered to save inside
`~/.vscode/extensions/financialforce.lana-*/`.

**Drop the ignored `openPath` payload.** The extension uses its captured
log URI,
not the display path the webview sends.

**Ban node builtins and Salesforce Services file I/O in `lana/src`.**
Both
failures are silent: the web bundle stubs node builtins to empty modules
so an
import only fails at runtime in the web host, and Salesforce Services
throws
until `ensureServicesAvailable()` has run — which `LogEventCache`
swallowed,
silently disabling folding, symbols, sticky scroll and the line
decoration until
certinia#988.

## Behaviour changes to be aware of

- The command is now offered on a very large `.txt`/`.log` that is not
an Apex
log, where it reports a parse error. That is the trade for never doing a
full read per tab event, and it only applies to files too big to open as
a
  document.
- The code lens no longer appears on either side of a diff. Clicking it
would
  have parsed the log, which is the work being avoided.
- Folding warms on `onDidChangeTabs` rather than
`onDidOpenTextDocument`, which
fires before the tab model updates and would make the gate reject a
legitimate
open. The tab change is also the repair path if a folding request loses
the
  race.

## Type of change

- [x] Bug fix
- [x] Performance

## Related issues

related W-23939830

## Validation

- `tsc -b lana` clean, `eslint` clean
- **2104 tests across 163 suites** pass
- New `TabState` suite covers the diff-side case in both directions and
pins that
the gate is not a scheme check, so a `memfs:` log in a normal tab still
works
- New detector case asserts `workspace.fs.readFile` is never called when
there is
  no text document
- The lint rule was verified against a probe file importing both banned
kinds

## Still needs a manual check

`DocumentSymbolProvider` has no change event, so it has no repair path
if a
symbols request ever loses the tab-model race. Opening a log fresh from
the
explorer in a cold window should populate the Outline and pin sticky
scroll.

---------

Co-authored-by: Luke Cotter <81575432+lcottercertinia@users.noreply.github.com>
…pment-dependencies group (certinia#1005)

Bumps the development-dependencies group with 1 update:
[lint-staged](https://github.com/lint-staged/lint-staged).

Updates `lint-staged` from 17.3.0 to 17.4.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/lint-staged/lint-staged/releases">lint-staged's
releases</a>.</em></p>
<blockquote>
<h2>v17.4.1</h2>
<h2>17.4.1</h2>
<h3>Patch Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/lint-staged/lint-staged/pull/1840">#1840</a>
<a
href="https://github.com/lint-staged/lint-staged/commit/efe5b63cc4961c80b6363fe40bac3c145e3ddbb2"><code>efe5b63</code></a>
- This is a version-bump-only release because the previous version
<code>17.4.0</code> was not published to npmjs.com due to problems with
GitHub Actions and Changesets.</li>
</ul>
<h2>17.4.0</h2>
<h3>Minor Changes</h3>
<ul>
<li>
<p><a
href="https://redirect.github.com/lint-staged/lint-staged/pull/1836">#1836</a>
<a
href="https://github.com/lint-staged/lint-staged/commit/90ec28245085343f56661ebc004e7b89304762dd"><code>90ec282</code></a>
- Added a new <code>defineConfig</code> helper for type-checking the
<em>lint-staged</em> configuration:</p>
<pre lang="ts"><code>// lint-staged.config.ts
<p>import { defineConfig } from 'lint-staged/config'</p>
<p>export default defineConfig({
'*.js': ['prettier --check', 'eslint'],
})
</code></pre></p>
</li>
<li>
<p><a
href="https://redirect.github.com/lint-staged/lint-staged/pull/1832">#1832</a>
<a
href="https://github.com/lint-staged/lint-staged/commit/510a27cac303990d71755aec203caed605b53caa"><code>510a27c</code></a>
- Added a new flag <code>--all</code> to make <em>lint-staged</em>
include all files tracked by Git, instead of only staged.</p>
<p>By default <em>lint-staged</em> only runs tasks on files that include
staged changes (hence the name). Use this flag to include all files
tracked in Git version control (standard exclusions apply). Using this
flag implies the <code>--no-stash</code> flag, disabling the automatic
backup, and the <code>--allow-empty</code> flag so that
<em>lint-staged</em> doesn't fail when there are no changes after
running. This makes it easier to run <code>npx lint-staged --all</code>
on a clean state, for example in CI.</p>
</li>
</ul>
<h3>Patch Changes</h3>
<ul>
<li>
<p><a
href="https://redirect.github.com/lint-staged/lint-staged/pull/1838">#1838</a>
<a
href="https://github.com/lint-staged/lint-staged/commit/69bec9930a73901bf908e3d0c0cdcafe5abf74b1"><code>69bec99</code></a>
- The behavior of the automatic backup stash has been improved when
running <em>lint-staged</em> in multiple worktrees in parallel. You
should still avoid running multiple instances of <em>lint-staged</em> in
parallel in the same tree, because some of the Git operations are
locking and might lead to data loss.</p>
</li>
<li>
<p><a
href="https://redirect.github.com/lint-staged/lint-staged/pull/1839">#1839</a>
<a
href="https://github.com/lint-staged/lint-staged/commit/5e5bdd29645063300256109bbbceb9dabcb014e4"><code>5e5bdd2</code></a>
- Parsing of <em>lint-staged</em> CLI flags and Node.js API options has
been rewritten to avoid inconsistent behavior between the two.</p>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/lint-staged/lint-staged/blob/main/CHANGELOG.md">lint-staged's
changelog</a>.</em></p>
<blockquote>
<h2>17.4.1</h2>
<h3>Patch Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/lint-staged/lint-staged/pull/1840">#1840</a>
<a
href="https://github.com/lint-staged/lint-staged/commit/efe5b63cc4961c80b6363fe40bac3c145e3ddbb2"><code>efe5b63</code></a>
- This is a version-bump-only release because the previous version
<code>17.4.0</code> was not published to npmjs.com due to problems with
GitHub Actions and Changesets.</li>
</ul>
<h2>17.4.0</h2>
<h3>Minor Changes</h3>
<ul>
<li>
<p><a
href="https://redirect.github.com/lint-staged/lint-staged/pull/1836">#1836</a>
<a
href="https://github.com/lint-staged/lint-staged/commit/90ec28245085343f56661ebc004e7b89304762dd"><code>90ec282</code></a>
- Added a new <code>defineConfig</code> helper for type-checking the
<em>lint-staged</em> configuration:</p>
<pre lang="ts"><code>// lint-staged.config.ts
<p>import { defineConfig } from 'lint-staged/config'</p>
<p>export default defineConfig({
'*.js': ['prettier --check', 'eslint'],
})
</code></pre></p>
</li>
<li>
<p><a
href="https://redirect.github.com/lint-staged/lint-staged/pull/1832">#1832</a>
<a
href="https://github.com/lint-staged/lint-staged/commit/510a27cac303990d71755aec203caed605b53caa"><code>510a27c</code></a>
- Added a new flag <code>--all</code> to make <em>lint-staged</em>
include all files tracked by Git, instead of only staged.</p>
<p>By default <em>lint-staged</em> only runs tasks on files that include
staged changes (hence the name). Use this flag to include all files
tracked in Git version control (standard exclusions apply). Using this
flag implies the <code>--no-stash</code> flag, disabling the automatic
backup, and the <code>--allow-empty</code> flag so that
<em>lint-staged</em> doesn't fail when there are no changes after
running. This makes it easier to run <code>npx lint-staged --all</code>
on a clean state, for example in CI.</p>
</li>
</ul>
<h3>Patch Changes</h3>
<ul>
<li>
<p><a
href="https://redirect.github.com/lint-staged/lint-staged/pull/1838">#1838</a>
<a
href="https://github.com/lint-staged/lint-staged/commit/69bec9930a73901bf908e3d0c0cdcafe5abf74b1"><code>69bec99</code></a>
- The behavior of the automatic backup stash has been improved when
running <em>lint-staged</em> in multiple worktrees in parallel. You
should still avoid running multiple instances of <em>lint-staged</em> in
parallel in the same tree, because some of the Git operations are
locking and might lead to data loss.</p>
</li>
<li>
<p><a
href="https://redirect.github.com/lint-staged/lint-staged/pull/1839">#1839</a>
<a
href="https://github.com/lint-staged/lint-staged/commit/5e5bdd29645063300256109bbbceb9dabcb014e4"><code>5e5bdd2</code></a>
- Parsing of <em>lint-staged</em> CLI flags and Node.js API options has
been rewritten to avoid inconsistent behavior between the two.</p>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/lint-staged/lint-staged/commit/d0c1517b61f4805a319ae416f50b1d5bdf3e137f"><code>d0c1517</code></a>
Merge pull request <a
href="https://redirect.github.com/lint-staged/lint-staged/issues/1841">#1841</a>
from lint-staged/changeset-release/main</li>
<li><a
href="https://github.com/lint-staged/lint-staged/commit/f06133573350dd650bd8fed42af06502d018b830"><code>f061335</code></a>
chore(changeset): release</li>
<li><a
href="https://github.com/lint-staged/lint-staged/commit/d2721af6d378c8c878005b01b557c95070449b11"><code>d2721af</code></a>
Merge pull request <a
href="https://redirect.github.com/lint-staged/lint-staged/issues/1840">#1840</a>
from lint-staged/updates</li>
<li><a
href="https://github.com/lint-staged/lint-staged/commit/efe5b63cc4961c80b6363fe40bac3c145e3ddbb2"><code>efe5b63</code></a>
ci: update Changesets action because it failed to publish</li>
<li><a
href="https://github.com/lint-staged/lint-staged/commit/cd76ce36648b794a477b60dc1852dc96641c03c3"><code>cd76ce3</code></a>
build: update dependencies</li>
<li><a
href="https://github.com/lint-staged/lint-staged/commit/ea195e1f17bb507ef6809a44d7f814fab1810270"><code>ea195e1</code></a>
Merge pull request <a
href="https://redirect.github.com/lint-staged/lint-staged/issues/1837">#1837</a>
from lint-staged/changeset-release/main</li>
<li><a
href="https://github.com/lint-staged/lint-staged/commit/a6a0d616b6eadb4ed464239001bf9afb826d13f2"><code>a6a0d61</code></a>
chore(changeset): release</li>
<li><a
href="https://github.com/lint-staged/lint-staged/commit/0a090981ef52a11fa4e4d90b6247f2310b5abc4f"><code>0a09098</code></a>
Merge pull request <a
href="https://redirect.github.com/lint-staged/lint-staged/issues/1832">#1832</a>
from lint-staged/add-all-flag</li>
<li><a
href="https://github.com/lint-staged/lint-staged/commit/7fd685b6de614335a432a81e383a73af4d431b3a"><code>7fd685b</code></a>
fix: further fix parsing options logic</li>
<li><a
href="https://github.com/lint-staged/lint-staged/commit/510a27cac303990d71755aec203caed605b53caa"><code>510a27c</code></a>
feat: add <code>--all</code> flag for including all files tracked by Git
instead of just...</li>
<li>Additional commits viewable in <a
href="https://github.com/lint-staged/lint-staged/compare/v17.3.0...v17.4.1">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=lint-staged&package-manager=npm_and_yarn&previous-version=17.3.0&new-version=17.4.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
lukecotter and others added 28 commits September 3, 2026 16:32
…r pixel (certinia#996)

Dragging the timeline's width cost **75-92ms a step** on a 95MB log, all
of it in
`MinimapDensityQuery`. A height-only drag was 2-4ms, because the density
cache is keyed by width
and hit.

The minimap paints one bar per pixel column, coloured by the category
that was **on top** longest
in that column — the log seen from above — weighted so `DML`/`SOQL` stay
visible under shallower
children. That semantic is unchanged. The cost was that "which frame is
on top at time *t*" was
recomputed **inside every bucket, on every width**, though it is a
property of the log and does not
depend on the minimap's width at all.

It is now built once per log as `MinimapSkylineIndex` — a stack sweep
into typed arrays — and every
width walks it.

## Results

95MB log, 431,297 frames, 862,567 segments:

| | before | after |
| --- | --- | --- |
| width-drag step, median | 100.40ms | **3.72ms** |
| width-drag step, worst | — | 9.04ms |
| whole 200px drag | 22.16s | **0.74s** |
| theme switch | full recompute | free |
| frame objects built at init | 431k (~73ms) | **0** |

19MB committed sample: 20.62ms → **0.84ms** a step.

One bucket per display pixel is unchanged, so a wider screen still shows
more detail.

## Proof the picture did not change

`pnpm measure minimap --digest` prints a CSV row per bucket
(`width,bucket,eventCount,maxDepth,
dominantCategory`) across five widths. Against the branch point it
differs in **0 of 5,035 rows**,
on the 19MB sample and on the 95MB log. Both logs also report **0
violations** and exactly **2.00
segments per frame**, so the sweep's containment guards never fire on
real data.

There is one deliberate behaviour change the digest does not show,
because neither log triggers it:
a frame ending exactly on a bucket boundary still counts toward that
bucket's opacity but no longer
contributes a segment there, so the bucket draws no bar. The old code
drew a full-height bar one
pixel past the frame's end.

## How it works

Segments **tile** the timeline — segment `i` spans `[segmentStarts[i],
segmentStarts[i+1])` — so a
walk needs no bounds test and no segment-end array. A stretch with
nothing running is a segment
with category id 0.

The sweep reads `PrecomputedRect` directly, so no per-event object is
allocated for it, and
`TemporalSegmentTree` carries no minimap state. It sweeps once into a
`2N + 2` bound (at most two
segments a frame, plus a trailing gap and a closer) and trims to views;
measured slack across four
real logs is 14 to 2,709 bytes.

## Measured trade-offs, recorded so they are not retried

- **Frame bounds are copied into typed arrays** (6.6MB) rather than read
off the rectangles.
Reading the scattered rectangles costs 10-15ms a call against 1ms, and
`countFrames` runs on
every width change — it would put a resize step inside the frame budget.
- **`subarray` views, not `slice`.** Retained slack is 311 bytes on the
95MB log; copying to exact
  arrays would peak 9MB higher to reclaim it.
- **Sorting** stays a plain `Array.sort`. Keyed indices measured
26-47ms, an explicit k-way merge
4-22ms, and the conversion's own traversal order 43ms, against 12ms
shipped — it is cheap because
each category group arrives time-ordered, so it merges a few runs.
Per-depth runs are *not*
  time-ordered (40% inversions), so a depth-run merge is invalid.
- **The `onTopOrder` scratch** costs 0.73ms a step and buys the
documented first-on-top tie-break.

## Also fixed here

Reviewing this branch surfaced a defect in the resize guard added by
certinia#982, so it is fixed in its
own commit with a regression test.

`resize`'s "nothing moved" guard read the main timeline height — the
container less the minimap,
the metric strip and their gaps — so a change *inside* that overhead hid
itself. The strip
appearing adds 15 + 4, and a container growing by the same 19px leaves
the difference unchanged;
the minimap's height is clamped at 60 below ~605px, so it does not move
either. Every value the
guard compared was equal while the layout had changed, so
`mainTimelineYOffset` kept the offset for
a layout without the strip and **every hit test and tooltip sat 19px
out** — 65px on
collapse/expand — until some unrelated resize. The next `ResizeObserver`
delivery compared equal
too, so it did not self-correct.

The overhead is now compared for itself, added as an extra term rather
than replacing the height
checks, so it can only apply a resize the old guard skipped and never
skip one it applied.

## Accepted cost

Building the skyline is ~73ms on the first minimap draw, over the 50ms
synchronous budget in
`.claude/rules/log-viewer.md`. Taken deliberately: it is paid once per
log, against the ~100ms it
used to cost on *every pixel* of a width drag. Recorded in the file
header so it is not read as an
oversight.

## Follow-ups, not in this PR

- One shared category id table: the same name→index map is built in
`MinimapSkylineIndex`,
`BucketColorResolver`, `TemporalSegmentTree` and per-call in
`HitDetector`.
- `resolveDominantCategory` duplicates `BucketColorResolver`'s priority
tie-break.
- `mergeManagedPackageEvents` can extend an event's `exitStamp` past a
sibling's, which is what the
sweep's `violations` counter exists to detect. Nothing surfaces it in
the app today.

## Testing

- `pnpm lint`, `pnpm test` — 2,107 tests, 163 suites, green.
- New `MinimapSkylineIndex` suite covering gaps, the tail after the last
frame, equal starts,
  containment, same-depth overlap, zero duration and an empty log.
- Checked by hand in the dev host, light and dark: same bands and
heights, colours track a slow
width drag without flicker, a height-only drag recomputes nothing, and a
theme switch recolours
  without changing shape.
…ertinia#1006)

# 📝 PR Overview

The inspector could say what a frame cost, not what it was working on. A
log captured with Apex Code at **FINEST** records every variable write,
and nothing read them.

The **Variables** section now lists what Apex could reach from the frame
you select: its **Local** variables, `this` and its fields, and the
**Static** variables assigned by that point, grouped by class. Every
value reads as it stood at the frame, so an earlier frame shows the
value it saw and not a later one.

## 🛠️ Changes made

- **Variables section** in the inspector on the Timeline, Call Tree,
Analysis and Database tabs. A statement owns no variables of its own, so
it answers from the Apex frame that ran it.
- **Values as the log wrote them.** An object opens one level, which is
all the log records; its properties are rows. A name the log declared
but never wrote reads `not assigned`. A value the log wrote as an
address reads as the object at that address, or `no value recorded`
where the log never wrote one.
- **A `this.field` line reports the object the field belongs to**, not
the value, so its address names an owner and never contributes a value.
`this` is shared between frames of one class only for the same instance.
- **Only a construction may name an object's class**, so a superclass
constructor cannot overwrite the concrete class of the object it runs
on.
- **One index per log** serves the whole section: tens of ms to build on
a large log, and a couple of ms for the worst frame snapshot, with no
measurable heap cost. It is built once, off the first render, and a
frame answers before it exists.
- **Keyboard**: the section is a tree — arrows walk and open, `*` opens
a level, and a note row is read rather than focused.

## 🧩 Type of change (check all applicable)

- [ ] 🐛 Bug fix - something not working as expected
- [x] ✨ New feature – adds new functionality
- [ ] ♻️ Refactor - internal changes with no user impact
- [ ] ⚡ Performance Improvement
- [ ] 📝 Documentation - README or documentation site changes
- [ ] 🔧 Chore - dev tooling, CI, config
- [ ] 💥 Breaking change

## 🔗 Related Issues

resolves certinia#373

## ✅ Tests added?

- [x] 👍 yes

`log-viewer`: 1782 tests, 143 suites, all passing. New suites cover the
line reader, the value scanner, the frame scope and index, the row
builder and the component, including a regression test for each rule
above.

## 📚 Docs updated?

- [x] 🔖 CHANGELOG.md
- [x] 📖 help site

## Anything else we need to know? [optional]

Needs the log captured with Apex Code at **FINEST**; the section says so
when a log was captured lower.
# PR overview

Every publish path installed its own tooling with `pnpm add --global
@vscode/vsce` and
`pnpm add --global ovsx`, which takes whatever the registry serves that
day. The pre-release
job runs unattended every Tuesday, so nobody sees what version it
picked.

- **vsce** is already a `lana` devDependency, so it is already in the
lockfile. Call it through
`pnpm exec` / the existing `build:vsix` script instead of a global
install.
- **ovsx** is not a dependency and does not need to be: it only uploads
at release time. Running
it as `pnpm dlx ovsx@1.1.1` pins the version without putting its native
keyring binaries into
  every CI job and every developer's install.

No `package.json` or lockfile change, so `pnpm install
--frozen-lockfile` is unaffected.

## Trade-off worth knowing

Dependabot cannot see a version inside a `run:` block, so the `ovsx` pin
will not be bumped
automatically the way `vsce` is. A stale pin fails loudly at
`verify-pat`, before anything is
published. The alternative — `ovsx` as a devDependency — costs 56 extra
packages
(`@napi-rs/keyring`, `@node-rs/crc32` and the inquirer tree) on every
install, for a tool used
twice a release.

## Type of change

- [x] Chore

## Validation

- `pnpm install --frozen-lockfile` passes against the unchanged
lockfile.
- `pnpm --filter lana exec vsce package --pre-release --no-dependencies`
runs in `lana/` with the
  flags passed through unchanged.
- `ovsx@1.1.1` is current latest and still takes `verify-pat`,
`--no-dependencies`,
  `--pre-release` and `--skip-duplicate`.
- The `dlx` fetch happens at `verify-pat`, before any upload, so a
download failure cannot land
  mid-publish.

## Known gap

`cd-prerelease.yml` still packages inline (`vsce package --pre-release`)
while `ci.yml` and
`publish.yml` call the `build:vsix` script, because `build:vsix` has no
`--pre-release` flag.
Unifying them needs a second script in `lana/package.json`; left out to
keep this PR to
workflows only.
…#1007)

# PR overview

Follow-up to certinia#997. Fixes an Outline regression that shipped there,
removes three
unreachable paths found while chasing it, and clears two small items
noted during
the certinia#952certinia#954 review.

## The Outline bug

certinia#997 gated the symbol provider on `isOpenAsTextTab` so that diffing a
log would not parse it.
That is right for folding and the cursor line decoration, which both
recover on the next tab
change through their own change events. It is wrong for symbols: VS Code
asks a
`DocumentSymbolProvider` once and has **no change event to ask again**.
When a symbol request
beats the tab model, the provider answers "empty" and the Outline stays
empty for the life of
the editor.

Reproduced on a cold open of
`lana/test/playwright/fixtures/apex-log.log`: folding, sticky
scroll, the cursor line timings and the code lens all worked, the
Outline was blank.

The gate stays exactly as certinia#997 wrote it. What is new is a repair path,
the same one
`RawLogFoldingProvider` already uses for the same race: remember that a
request was rejected,
and on the next tab or active-editor change re-register the provider,
which is the only way to
make VS Code ask again.

Re-registration is deliberately narrow. It happens only when the active
document is an Apex log
that is *now* in a text tab, so a log sitting on the side of a diff
never triggers one. The flag
is cleared only on an actual retry — a tab change that arrives before
the active editor settles
must not spend the repair that the editor event still needs.

An earlier attempt weakened the gate instead, to "skip only a confirmed
diff". That is worse:
`TabInputTextMultiDiff` is absent from `@types/vscode` ~1.102, so a log
inside a multi-file diff
matches no known tab kind and would have parsed on every request —
exactly the case certinia#997 skipped.

## Also in this PR

- **`RawLogHoverProvider` deleted** — `Context.ts` has never called its
`apply()`
(`git log -S'RawLogHoverProvider' -- lana/src/Context.ts` returns
nothing), so it has been dead
since it was written. `RawLogLineDecoration` builds the same hover from
the same
`buildMetricParts` helper and *is* wired. Its selector also covered the
whole line rather than
the end of it, so registering it merged our timings into the git blame
hover — the decoration's
  empty end-of-line range exists precisely to avoid that.
- **The string branch of `Display.showFile`** — both callers pass a
`Uri`, and `Uri.parse` on a
  Windows path reads `c:` as the scheme.
- **The `showError` case in `LogView`** — nothing in `log-viewer/` or
`lana/` sends it. Its
  `isTextPayload` guard went with it.
- **`capabilities.untrustedWorkspaces`** — dropped. Lana reads
`sfdx-project.json` and runs a
bundled webview, so claiming restricted-mode support was wrong.
`virtualWorkspaces: true` stays.
- **A stale comment in `SfdxProject.ts`** — it explained
`path.posix.basename`, which the code
  no longer calls.

## Type of change

- [x] Bug fix
- [x] Chore

## Validation

- 21 suites, 342 tests pass, including four new cases covering the gate
and the repair. The
repair test is mutation-checked: stub out the re-registration and it
fails.
- `tsc -b lana`, `eslint lana/src` and `prettier --check` clean.
- Dev host: Outline populates on a cold open of the fixture, folding and
sticky scroll still
work, and the hover shows once rather than twice. Verified separately
that the provider yields
12 nested symbols for that fixture, so the empty Outline was the gate
and not missing symbols.

## Noted, not fixed

`ShowAnalysisCodeLens` is the same "asked once" shape — it is registered
without an
`onDidChangeCodeLenses`, so a lens request that loses the tab-model race
has no repair either.
Pre-existing, and out of scope here.
The dev host started on no folder, so the test logs were always a few
clicks away. The folder arg opens `sample-app`, which holds them. The
worktree config opens that worktree's own copy, and the AGENTS.md
command matches.

Related: certinia#992, which added the `lana-dev` profile these launch configs
name.
…tinia#1009)

# 📝 PR Overview

The log writes `{}` for an object it could not serialise, so a Variables
row read as empty while the log held that object's fields on lines of
their own. Three in four `{}` rows in real FINEST logs are in this
state.

A row now opens into the fields the log recorded for its object,
wherever they were written, and a field that is itself an object opens
again. Every row that opens previews what is inside it with a count
beside it, so nothing reads as empty when it is not.

## 🛠️ Changes made

- **Fields by owner.** A `this.field` line carries the address of the
object the field belongs to, so the index groups an object's field
writes by it — one map filled during the walk that already runs.
- **Two sources, one rule:** the latest write to a field wins. The index
finds a write wherever it was made, so a field a returned constructor
set is in scope; the frame walk finds the writes whose line reported no
address, which the index cannot see.
- **A dead object's fields stay out.** An address is reused once its
object is collected, so a read is bounded at the object's own class run.
A construction always starts a new run, even of the same class.
- **Preview and count on every row that opens**, assembled or
serialised, with the hover saying which: only parts written on lines of
their own can be as this frame stood.
- **Per-field caps**, so one field written in a long loop cannot evict
the rest of its object.
- **One index read per object per selection**, held for the frame: 42ms
to build on a 9MB log, 97ms on a field-heavy 19MB one, field reads under
a millisecond, retained heap unchanged.

## 🧩 Type of change (check all applicable)

- [ ] 🐛 Bug fix - something not working as expected
- [x] ✨ New feature – adds new functionality
- [ ] ♻️ Refactor - internal changes with no user impact
- [ ] ⚡ Performance Improvement
- [ ] 📝 Documentation - README or documentation site changes
- [ ] 🔧 Chore - dev tooling, CI, config
- [ ] 💥 Breaking change

## 🔗 Related Issues

related certinia#373

## ✅ Tests added?

- [x] 👍 yes

25 new tests; 2298 pass across the three projects. Each new rule has a
test proven by mutation: the reuse bound, the same-class reuse case, the
per-field cap, the two-source merge, the address-less field write, the
held read, the assembled preview, the count, and the row that cannot
open.

## 📚 Docs updated?

- [x] 🔖 CHANGELOG.md
- [x] 📖 help site

## Anything else we need to know? [optional]

One deliberate limit: every recorded field of the object is listed, so a
base-class frame can show a field only the subclass declares. The log
names no class hierarchy, and the only available filter — the class of
the writing frame — would drop inherited fields set in a base
constructor, which is the common case. The trade is commented at the
merge site.
…ertinia#1012)

The unreleased section had grown to 65 lines with sub-bullets nested
three deep. Nobody reads that.

## Changelog

Unreleased is now 37 lines, 26 entries. Each entry is one or two lines
and says what the user gets.

- Sub-bullets folded into their headline. The Inspector went from 6
bullets to 1 line.
- Related entries merged. Three grid-styling entries became one.
- Internal names cut. "Replace webview-ui-toolkit with vscode-elements"
is not something a user can see.
- Each section ordered by impact. "Go to Code is 6x to 10x faster" moved
from last to third.
- All 14 issue references kept.

No released section is touched.

## AGENTS.md

Records the rules above, so the next entry starts in the right shape.
… and the pill (certinia#1011)

# 📝 PR Overview

Grid cells, query text, Inspector snippets and notification stack traces
took their
size from the reader's `editor.fontSize`, so a 14px editor font put them
two steps
over the chrome and the app could not state its own density.
`.soql-block` also
overrode two surfaces that had deliberately chosen a smaller step: the
diagnostics
evidence line, and the timeline tooltip, whose one-line clamp is
measured against it.

Code-shaped text now takes no size of its own and inherits the surface
that holds it.
One place cannot: tabulator's `textSize` is a Sass parameter, not a
declaration, so the
table root names the app's step. Nothing in the webview reads
`--vscode-editor-font-size`
any more, and the editor still supplies the family.

Alongside that, the appearance tokens the sweep needed: one focus ring
instead of nine
copies, a pill radius for a bar that must round whatever its height, and
a verdict that
reads as an outline chip.

## 🛠️ Changes made

- Code-shaped text inherits its surface: `.soql-block`, the grid's code
column, `CodeBlock`'s `pre` and `IssueList`'s stack traces all drop
their size. `--lana-text-mono` had no consumer left and is gone
- `--lana-focus-ring`, `--lana-focus-offset` and `--lana-focus-inset`
replace the same three declarations written out nine times across seven
files. The repo's rule already said a `calc` in three or more files is a
token, and that `calc` was in four
- `--lana-radius-pill` on both governor gauges and the facet count. A
corner radius un-rounds a thin bar as soon as a host sets a smaller step
- A verdict is an outline chip: one hue drives its text, a 12% ground
and a 30% edge, matching the tint percentages already in the app. "Not
selective" reads as a warning rather than an error
- `GovernorSummary`'s gauge figure states no size, so it reads at
whatever surface holds it
- Literals converted in the rules the sweep touched, and the comments it
made stale

## 🧩 Type of change (check all applicable)

- [ ] 🐛 Bug fix - something not working as expected
- [ ] ✨ New feature – adds new functionality
- [x] ♻️ Refactor - internal changes with no user impact
- [ ] ⚡ Performance Improvement
- [ ] 📝 Documentation - README or documentation site changes
- [ ] 🔧 Chore - dev tooling, CI, config
- [ ] 💥 Breaking change

## 📷 Screenshots / gifs / video [optional]

N/A

## 🔗 Related Issues

N/A

## ✅ Tests added?

- [x] 🙅 no, not needed

Appearance tokens only, and no test asserts a `--lana-*` value. Verified
with `jest --runInBand` (2298 tests / 169 suites, all three projects),
`tsc -b log-viewer --force`, eslint, prettier and a production build.

## 📚 Docs updated?

- [x] 🙅 not needed

`.claude/rules/log-viewer.md` records the rule that now holds:
code-shaped text takes no size of its own, so nothing in the webview
follows the reader's `editor.fontSize`.

## Anything else we need to know? [optional]

Two things found while reviewing, neither introduced here.

Tabulator's own `min-height: $textSize + ($headerMargin * 2)` cannot
take a `var()` — Sass concatenates instead of adding, so the shipped
rule is `min-height:var(--lana-text-base)8px`, which browsers drop. The
header-cell min-height has therefore never applied, with the old token
or the new one. Left alone; fixing it needs a literal or an unlayered
override of upstream. The gotcha is noted on the declaration that feeds
it.

The verdict chip's coloured text sits under WCAG AA on light themes,
roughly 3.1:1 for Light+'s warning colour at 10px. That is inherited
from `severityStyles`, which colours the Analysis findings the same way;
the fix is to darken the severity tokens for light grounds, app-wide,
and is tracked separately.
…tinia#1013)

# 📝 PR Overview

The four Governor trend charts shared one cursor. A sample read on one
chart answered the arrow keys and the live region on the other three, so
the keyboard reported a figure from a chart the reader was not on.
Holding Enter also re-zoomed the flame chart on every key repeat.

A cursor now belongs to the chart that placed it, and to the log that
placed it. Each chart reads only its own sample, and one chart reads at
a time.

## 🛠️ Changes made

- A cursor carries its chart's label, so a sample on one chart no longer
answers another.
- A held Enter is ignored after the first press - a key repeat must not
re-zoom the flame chart. Arrows still repeat, so holding one scrubs.
- A click with no coordinates (assistive tech, a programmatic click)
reads the chart's cursor, else the last sample, so it always reaches a
frame.
- The arrows carry on from the sample Enter answered, and keep stepping
while the pointer rests on the chart.
- A new log clears the cursor: metric labels repeat between logs.
- Removes `reveal-row--no-swatch`, a class with no rule behind it, and
the three tests that asserted the absence of an element it never
controlled.

## 🧩 Type of change (check all applicable)

- [x] 🐛 Bug fix - something not working as expected
- [ ] ✨ New feature – adds new functionality
- [x] ♻️ Refactor - internal changes with no user impact
- [ ] ⚡ Performance Improvement
- [ ] 📝 Documentation - README or documentation site changes
- [ ] 🔧 Chore - dev tooling, CI, config
- [ ] 💥 Breaking change

## 📷 Screenshots / gifs / video [optional]

N/A - keyboard and pointer behaviour, nothing new on screen.

## 🔗 Related Issues

related certinia#950

## ✅ Tests added?

- [x] 👍 yes

Eight tests in `GovernorTrends.test.ts` cover the cursor rules. Each new
guard was mutation proved: break it, watch its own test fail, restore
it.

\`\`\`
pnpm test    # 169 suites, 2306 tests
pnpm lint
\`\`\`

Dev host: step the arrows on one chart, then rest the pointer on
another. The stepped chart keeps answering, and only one chart reads at
a time.

## 📚 Docs updated?

- [x] 🙅 not needed

The trend seek feature is unreleased, so this fix reaches nobody as a
change. The Inspector changelog entry already covers it.

---------

Co-authored-by: Luke Cotter <81575432+lcottercertinia@users.noreply.github.com>
…tinia#1016)

# 📝 PR Overview

A key repeat should scrub a continuous control, not re-run a command.
Held keys did both. Holding Enter or Space on an Inspector section
header flapped the pane open and shut and wrote the collapsed setting to
disk on every repeat, roughly 30 times a second. On the timeline,
holding Enter re-zoomed to the same frame, J rebuilt the call-tree
table, Home reset an already-reset viewport, and Ctrl/Cmd+C rewrote the
clipboard, each at the repeat rate.

Every command now fires once. The key stays consumed on the repeats, so
Space still cannot scroll the pane stack and the browser never acts on a
repeat. Pan and zoom repeat as before, so holding an arrow key still
scrubs.

## 🛠️ Changes made

- `PaneView` header keys toggle once, so the pane no longer flaps and
the setting is written once per press.
- Timeline `Enter`/`Z` (focus), `J` (jump to call tree), `Home`/`0`
(reset zoom) and `Ctrl`/`Cmd`+`C` (copy) each fire once.
- `preventDefault` still runs on a suppressed repeat, so the key stays
ours; an unrelated held key, such as `Tab`, is untouched.
- Pan, zoom and `Escape` are unchanged: the first two are continuous,
and `Escape` converges on its own.

## 🧩 Type of change (check all applicable)

- [x] 🐛 Bug fix - something not working as expected
- [ ] ✨ New feature – adds new functionality
- [ ] ♻️ Refactor - internal changes with no user impact
- [x] ⚡ Performance Improvement
- [ ] 📝 Documentation - README or documentation site changes
- [ ] 🔧 Chore - dev tooling, CI, config
- [ ] 💥 Breaking change

## 📷 Screenshots / gifs / video [optional]

N/A - keyboard behaviour, nothing new on screen.

## 🔗 Related Issues

N/A

## ✅ Tests added?

- [x] 👍 yes

Eleven tests, and every guard was mutation proved: break it, watch its
own test fail, restore it. Tests also hold the two contracts the guard
must not break - a suppressed repeat still prevents the default, and pan
and zoom still act on every repeat.

\`\`\`
pnpm test    # 169 suites, 2317 tests
pnpm lint
\`\`\`

Dev host: hold Enter on an Inspector section header. The pane toggles
once. Reopen the log and the collapsed state matches, so the setting was
written once. Then hold an arrow key on the timeline: pan still scrubs.

## 📚 Docs updated?

- [x] 🙅 not needed

## Anything else we need to know? [optional]

The minimap and metric strip carry their own `Home`/`End`/`0` bindings,
which are the same class of command and still re-fire on a repeat. They
only fire while the pointer is over those strips, and guarding them
means six more branches inside two switch statements, which is the point
at which a declarative continuous-or-command binding table earns its
keep. Left out of this fix on purpose.
…ertinia#1021)

Part of certinia#373. Builds on the sidebar Variables section (certinia#1006) and
opening an object in it (certinia#1009).

The Variables section said "Pick one call to see its variables" for
every merged row. Now it compares those calls, so an Aggregated,
Bottom-Up or Analysis row answers with the reading the grids beside it
cannot give: which input varied, and which was the same every time.

## What a reader sees

- The names that varied lead. Each opens into every value it held, how
many calls held it, and whether that was one unbroken run or a value
that came and went.
- A name every call agreed on reads as it does for one frame.
- Hover a value to light the calls that held it in the timeline and the
grids; click, or press Enter, to keep them lit. The panel never
re-scopes to one call - every other section answers a merged row with
aggregated figures, and dropping onto one of its calls would throw away
the reading.
- An object opens into its fields, as it does for one frame, read as the
first call that held it recorded it.
- Statics are left out, and the section says so: a static lives for the
whole transaction, so it moves for reasons the row does not own.

Every cap says so on screen: over 1,000 values for a name, a mark that
stops at 200 calls, a truncated log, and an index that dropped writes.

## Speed and memory

A merged row can hold tens of thousands of calls, and the comparison
reads every one - a recursive frame's nested call is a call of its own.
It walks in frame-sized slices against a frame budget, so a wide
selection never blocks the panel, and a walk the selection has moved
past is abandoned.

| log | busiest signature | first | again |
| --- | --- | --- | --- |
| 19MB | 34,857 calls | 52ms | 0ms |
| 18MB FINEST | 2,364 calls | 9ms | 0ms |
| 9MB FINEST | 1,169 calls | 18ms | 0ms |

Reading the same shared caller frame once per call was the whole cost:
786ms to 63ms on the worst signature, 3,733ms to 47ms on the 34,857-call
one. Frame reads hold their parsed lines only from the second ask, and a
frame asked about once is scanned bounded at the cut, so a memo built
over a 500k-child frame is neither built nor held for a read that wanted
one line.

## Notes

- `scripts/measure/variables.ts` times the section: the index, a frame
snapshot, an early cut in the log's fattest frame, and the busiest
merged row's comparison.
- Opening an object into its fields at aggregate scope was out of scope
in the plan; it turned out to be needed to read the section at all, so
it is here.
- The last four commits act on a `/simplify` and a `/code-review` pass
over this branch.

Tests: 2,364 pass. `tsc -b`, eslint and prettier clean.
…#1022)

# 📝 PR Overview

The inspector remembered too much, and the wrong things.

A section height dragged for a 100MB log was stored and replayed onto
the next log, where it was wrong. One drag pinned **every** open
section, not the two beside the divider, so automatic sizing never came
back — each divider had to be double-clicked to undo it. The section
order was fixed in code. There was no way to hide a section you never
want, and no way to reset any of it.

Sizing is automatic again and never carried between logs. Sections
reorder by dragging their headers, the way VS Code's views do. A
right-click menu chooses which sections a tab shows — a hidden section
builds nothing at all — and one **Reset Sections** row restores the
defaults.

Two more things came out of it. Stepping from one timeline frame to the
next used to resize the whole stack, because sections whose content
changes with the selection were sized to that content; those now keep a
steady height and scroll inside. And a divider drag now cascades like VS
Code's: the sections on the other side give up room in turn, each down
to the same minimum, so the divider follows the pointer until they are
all there.

## 🛠️ Changes made

- **Reorder**: drag a section header, or press `Alt+Up` / `Alt+Down` on
a focused one. Works docked left, right and bottom.
- **Choose sections**: right-click a header to tick sections on and off,
plus a **Reset Sections** row. The last section showing cannot be
unticked — hiding it would remove the only header left to right-click.
- **Hidden means no work**: a hidden section's body never mounts, and
the SOQL lint behind the **SOQL issues** badge is skipped.
- **Per tab and per scope**: order, hidden and collapse are keyed
`<source>:<scope>:<id>`. `calltree` means the whole log on the
Timeline's summary and one frame's subtree in a detail list, so a choice
made in one never reaches the other.
- **Sizes are runtime only**: `inspector.paneSizes` is gone. A drag
lives as long as the panel is open.
- **Steady heights**: **Details** and a selection's **Self time by
namespace** take a `--lana-pane-*` tier; **Variables**, **Call stack**,
**Call tree** and **Findings** share what is left. Each tier is
`clamp(min, share, max)`, so it scales with the panel and depends on
nothing the selection changes.
- **Cascading drag**: one drag snapshots the whole open stack and hands
room out nearest-first, every section down to the same
`--lana-pane-min`.
- **Sizing lives in CSS**: every `flex` rule is in the stylesheet,
reached through `var(--pane-size, <default>)`. The drag emits numbers
only, so a dragged size beats each default without a second selector.
- **No section takes the panel**: a section sized to its content starts
from an equal share and grows back towards its content only as far as
the others leave room, scrolling inside past that. Sized to its content
first, one long list held every other section at its floor, because
flexbox shrinks by basis and the biggest keeps the most.
- **Arranged order survives the selection**: the list under one key
varies with what is selected - `issues` is built for a SOQL statement
and not for a DML one - so a reorder now keeps an id the store knows
that this build did not produce, and an id it never knew falls back to
where the builder puts it rather than to the end.
- **Call tree column view is private**: the view a table was last left
in is remembered UI state, not a preference, so
`lana.callTree.columnView` joins its three `database.*.columnView`
siblings in `globalState` and leaves the settings list. Neither it nor
the inspector keys have shipped, so no migration is needed.

## 🧩 Type of change (check all applicable)

- [x] 🐛 Bug fix - something not working as expected
- [x] ✨ New feature – adds new functionality
- [ ] ♻️ Refactor - internal changes with no user impact
- [ ] ⚡ Performance Improvement
- [ ] 📝 Documentation - README or documentation site changes
- [ ] 🔧 Chore - dev tooling, CI, config
- [ ] 💥 Breaking change

## 📷 Screenshots / gifs / video [optional]

To follow.

## 🔗 Related Issues

related certinia#113

## ✅ Tests added?

- [x] 👍 yes

`PaneView` covers the cascade (a drag past one section's floor moves the
next, and every open pane holds its measured size for the length of the
gesture), the sizing each `fit`/`height`/`weight` combination resolves
to on both axes, reorder by drag and by `Alt+Arrow`, and the drop
hit-test. `LogInspector` covers the composite keys, the last-visible
guard, hiding a section while its build is still running, and that a
reset returns the builder's order. Two new pure modules,
`inspectorLayout` and `sectionMenu`, are tested directly.

```
pnpm test    # 171 suites, 2388 tests
pnpm lint
```

Dev host, light and dark: opened a 2MB log then a 100MB one and no
layout carried over; dragged a divider past two sections' floors and
watched the third give way; stepped through timeline frames with no
stack movement; reordered by drag and by keyboard on all three dock
positions; unticked a section and confirmed it stayed shown on the other
tab; reset.

## 📚 Docs updated?

- [x] 🔖 CHANGELOG.md
- [x] 📖 help site
- [x] 🙅 not needed

The Inspector's Unreleased entry gains the reorder and the section menu.
`features/inspector.md` describes the heights and the cascade.
`settings.mdx` loses **Default column view**, and
`features/calltree.mdx` loses the link to it.

## Anything else we need to know? [optional]

Two things left alone on purpose:

- The `<code-block>` in **Details** is unbounded, so a long statement
pushes the figures below the fold inside that section. The section no
longer moves the stack, but capping the block would put the numbers back
in view.
- `detailSections.ts` and `databaseSections.ts` define `vitals`,
`variables`, `callstack` and `calltree` twice over, with matching ids,
titles, sizing and prose. Pre-existing, and wider than this branch;
`namespaceTimeSection` is the precedent for a shared factory.
…per-row bars against the transaction (certinia#1026)

## What changes

The log is now the only source of a governor maximum, and a per-row bar
measures contribution, not
headroom.

**A maximum is never assumed.** A hardcoded table of Salesforce's
*synchronous* maxima used to stand
in where a log reported none. It is wrong for a third of the logs that
do report: over 438 real logs,
85 ran async (CPU 60,000 / heap 12 MB / SOQL 200) and 15 reported CPU
25,000. Nothing in the code
could tell one context from the other. 23% of logs report no maximum at
all, and no debug level
guarantees one — 36 complete `APEX_PROFILING,FINE` logs and 7 complete
`INFO` logs carry no limit
block.

Without a reported limit:

- the overview gauges read as levels, with a sparkline of the metric
over the log where the bar sits;
- the Timeline strip and the governor trends scale each metric to its
own peak — no 80% band, no
  100% line, no breach fill, no traffic lights;
- **Gov Avg %** and **Gov Peak %** read `—` instead of a confident
`0.0%`;
- a limit line in the log body (`LIMIT_USAGE`, and the flow variants)
now reports a maximum too, so
  fewer logs fall into this state than before.

**Per-row governor bars answer contribution.** The governor count and
row columns in the Call Tree
and Analysis now fill against what the transaction consumed, the same
question the time columns
beside them already answered that way. A path that ran 3 of the
transaction's 12 SOQL drew a 3% bar
next to a 25% time bar; it now draws 25%. Headroom is still answered,
once, by **Gov Avg %** /
**Gov Peak %** and by the gauges. Each cell's tooltip still names the
limit.

The wording says which denominator is in play: `/` and "of limit" for
headroom, "of" and "of log" for
contribution.

## Two fixes found on the way

- A metric was dropped from the Timeline series when its limit was 0, so
a log with no limit block
  drew no strip at all.
- A hairline sparkline or trend at a metric's peak had half its stroke
clipped by the plot box.

## Verification

`pnpm lint` and `pnpm test` clean — 2412 tests. Checked in the dev host,
light and dark, on a log
that reports limits (`sample-app/debug-logs/sample-log.log`), one that
reports none, and two whose
maxima are not the old defaults (CPU 60,000 and CPU 25,000).

## Not in scope

A multi-namespace log can still read `SOQL 119 / 100`: the parser sums
`used` across namespaces while
keeping one namespace's limit (certinia#862). A log reporting both a sync and an
async family resolves to the
higher one.
…tinia#1027)

# 📝 PR Overview

The changelog rules sat in two places and disagreed. `AGENTS.md` banned
sub-bullets outright, so a
feature with several distinct parts had to become one run-on sentence.
The `changelog-entry` skill
meanwhile set a section order and a tense that this repo's
`CHANGELOG.md` has never used.

An entry may now carry up to three sub-bullets, each naming one
capability. `AGENTS.md` forwards to
the skill instead of restating it, so there is one place to read and one
place to change.

## 🛠️ Changes made

- Allow three sub-bullets at most under an entry, each naming one
capability the reader can use — a
  run-on sentence was the only alternative.
- Point `AGENTS.md` at the skill rather than repeating it, so the two
cannot drift apart again.
- Move the `- <emoji> **Label**:` house style into the skill, alongside
the rest of the guidance.
- Correct the skill's section order to Added, Changed, Fixed, and its
tense examples, to match what
  `CHANGELOG.md` actually does.
- Tighten the skill description so it loads while `CHANGELOG.md` is
being edited, and fits the
  200-character limit it was over.

## 🧩 Type of change (check all applicable)

- [ ] 🐛 Bug fix - something not working as expected
- [ ] ✨ New feature – adds new functionality
- [ ] ♻️ Refactor - internal changes with no user impact
- [ ] ⚡ Performance Improvement
- [x] 📝 Documentation - README or documentation site changes
- [ ] 🔧 Chore - dev tooling, CI, config
- [ ] 💥 Breaking change

## 📷 Screenshots / gifs / video [optional]

N/A

## 🔗 Related Issues

N/A

## ✅ Tests added?

- [ ] 👍 yes
- [x] 🙅 no, not needed
- [ ] 🙋 no, I need help

## 📚 Docs updated?

- [ ] 🔖 README.md
- [ ] 🔖 CHANGELOG.md
- [ ] 📖 help site
- [ ] 🧪 Marked any pre-release-only features (README `🧪` badge — see
[RELEASING.md](../RELEASING.md#-marking-pre-release-only-features))
- [x] 🙅 not needed

## Anything else we need to know? [optional]

Agent instructions only. Nothing ships to users.
## Summary

- bundle the browser extension and log viewer assets into one
self-contained web entrypoint
- retain packaged-file loading for the desktop extension host
- preserve replacement tokens such as $& when embedding minified
JavaScript and CSS, preventing bundle source from appearing as webview
text
- cover embedded browser assets and the desktop fallback with regression
tests

## Testing

- pnpm build
- pnpm test --runInBand (169 suites, 2,307 tests)
- pnpm lint

Co-authored-by: Luke Cotter <81575432+lcottercertinia@users.noreply.github.com>
…e's view (certinia#1031)

# 📝 PR Overview

Zoomed into the timeline, picking a row in the inspector marked the
frame but left the view where it was. A single-frame row panned only
when the frame overlapped the view nowhere, so one showing a pixel at
the screen edge stayed there; an aggregated or bottom-up row moved
nothing at all, and with every occurrence off screen the chart dimmed
with no lit frame anywhere.

A pick now brings a frame into view: the one it names, or for a merged
row the occurrence nearest the middle of the view. Nothing moves when
what you need is already on screen, a frame spanning the view edge to
edge stays put, and a merged pick still selects none of its occurrences
— the mark on all of them is what locates them. Zoom is never touched.

## 🛠️ Changes made

- `revealTarget` — one policy for both cases: which frame to bring in,
and which axes to centre it on, or nothing when the view already shows
one. A single frame is a one-element list.
- `TimelineViewport.centerOffsetFor(…, axes)` holds the centring maths.
`calculateCenterOffset`, `centerOnEvent` and `focusOnEvent` all delegate
to it, so the midpoint-and-clamp maths and the off-screen test each
exist once instead of three times — search navigation included.
- `FlameChart.panToFrame` pans without a selection, which is what lets a
merged pick move without naming one occurrence as the pick.
- `revealMerged?` replaces `movesToMergedPick?: boolean` in the
inspector wiring: the view chooses which occurrence, because only it
knows what nearest means in its own layout. The tables keep
first-occurrence behaviour through the shared `revealFirstOf`; the
Database grids still only mark.

## 🧩 Type of change (check all applicable)

- [x] 🐛 Bug fix - something not working as expected
- [ ] ✨ New feature – adds new functionality
- [x] ♻️ Refactor - internal changes with no user impact
- [ ] ⚡ Performance Improvement
- [ ] 📝 Documentation - README or documentation site changes
- [ ] 🔧 Chore - dev tooling, CI, config
- [ ] 💥 Breaking change

## 📷 Screenshots / gifs / video [optional]

N/A — the change is a viewport movement, not a new surface.

## 🔗 Related Issues

related certinia#373

## ✅ Tests added?

- [x] 👍 yes
- [ ] 🙅 no, not needed
- [ ] 🙋 no, I need help

`pnpm lint && pnpm test`. New cases cover the policy
(`detail-selection-sync.test.ts`), the geometry and its clamping
(`viewport.test.ts`), and the wiring for both a single frame and a
merged row (`inspector-reveal-pan.test.ts`). The new `centerOnEvent`
cases pass against the pre-refactor implementation too, which is what
pins that commit as behaviour-preserving.

To check by hand: open a log, Timeline tab, zoom well in, then in the
inspector pick a narrow Call Tree row off to one side (the view slides
so the frame is centred), a Call Stack ancestor that spans the screen
(nothing moves), a row at a depth off screen (the view scrolls to that
depth), and an aggregated or bottom-up row whose calls are all off
screen (the view moves to the nearest one, and no frame is selected).

## 📚 Docs updated?

- [ ] 🔖 README.md
- [ ] 🔖 CHANGELOG.md
- [ ] 📖 help site
- [ ] 🧪 Marked any pre-release-only features (README `🧪` badge — see
[RELEASING.md](../RELEASING.md#-marking-pre-release-only-features))
- [x] 🙅 not needed
…b-actions group (certinia#1024)

Bumps the github-actions group with 1 update:
[pnpm/action-setup](https://github.com/pnpm/action-setup).

Updates `pnpm/action-setup` from 6.0.10 to 6.1.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/pnpm/action-setup/releases">pnpm/action-setup's
releases</a>.</em></p>
<blockquote>
<h2>v6.1.0</h2>
<h2>What's Changed</h2>
<ul>
<li>feat: support pnpm v12 by <a
href="https://github.com/zkochan"><code>@​zkochan</code></a> in <a
href="https://redirect.github.com/pnpm/action-setup/pull/288">pnpm/action-setup#288</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/pnpm/action-setup/compare/v6.0.10...v6.1.0">https://github.com/pnpm/action-setup/compare/v6.0.10...v6.1.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/pnpm/action-setup/commit/ea17c68df8912ef543352723c149a84f56e3d413"><code>ea17c68</code></a>
feat: support pnpm v12 (<a
href="https://redirect.github.com/pnpm/action-setup/issues/288">#288</a>)</li>
<li>See full diff in <a
href="https://github.com/pnpm/action-setup/compare/v6.0.10...v6.1.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=pnpm/action-setup&package-manager=github_actions&previous-version=6.0.10&new-version=6.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Five views each declared an identical find event type, and a sixth copy sat
in the flame chart's types. One module now names them, keyed by event name so
a listener's payload follows the name it subscribed to.

Also drops a SearchOptions that collided by name with a different
SearchOptions in the same feature folder.
…window

Subscribes in hostConnected and unsubscribes in hostDisconnected, so a
listener on a global target lives exactly as long as its host is connected.

Handlers are passed as inline arrows: this package compiles with
useDefineForClassFields:false, so a field initialiser cannot reference a field
declared below it, and addEventListener with an undefined handler is a silent
no-op. The constructor throws instead.
Seven views registered a global listener in the constructor and removed it in
disconnectedCallback, so a re-attached view heard nothing. FindWidget never
removed either of its two.

Each view's event subset is unchanged. The adapter fields and the casts they
needed are gone, and FindWidget now reads the shared results type rather than
its own copy carrying a count no view sends.
The three tab views wired the inspector in their constructor and released it
in disconnectedCallback, so a re-attached view lost mark, reveal and clear.
The call moves beside wireCategoryColoring, which already had this shape, and
all three constructors are now empty and gone.

AnalysisView's suite mounted a bare element and relied on the constructor
doing the wiring; it now attaches to the document and awaits updateComplete.
Detaching the view destroys its three tables, but the only build path runs when
the log first arrives, so the view came back with its subscriptions and no
table. It now rebuilds on connect, for the view on show, under the filters and
grouping it was left with.
Five grids each carried their own copy of the column view, its overrides, and
the reads and writes either side of them. One controller holds that now, so a
grid declares only its section, presets and tables.
…d life

Three views each held an emphasis, called the wiring by hand on connect and
released it on disconnect. A controller does both now and owns the emphasis,
since nothing outside the subscription decides what it holds. A view that comes
back lights the pick again. The flame chart keeps the plain function: it is no
Lit host, and rests the emphasis itself.
The abort listener stayed on the signal after the element came on screen, so
the observer and the element it watched were held until the controller went.
@lukecotter

Copy link
Copy Markdown
Owner Author

Moved to certinia#1058.

@lukecotter lukecotter closed this Sep 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants