Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
4fdc6b3
refactor(log-viewer): give one object the whole key and path vocabula…
lukecotter Aug 28, 2026
e2fd2a2
perf(log-viewer): 24% faster Call Tree grids, and a highlight that fo…
lukecotter Aug 28, 2026
72e9089
fix(log-viewer): keep the inspector mark and the tab it points at in …
lukecotter Aug 28, 2026
104b9e5
fix(log-viewer): mark every row an inspector pick names, not just the…
lukecotter Aug 28, 2026
5bc9dad
docs(log-viewer): say what the row mark actually missed (#976)
lukecotter Aug 28, 2026
181c74c
refactor(log-viewer): give a tab one wiring call to the inspector (#977)
lukecotter Sep 1, 2026
7ca30f3
fix(log-viewer): span the timeline across the whole log (#978)
lukecotter Sep 1, 2026
b9ed80d
fix(log-viewer): mark a caller row by the caller, not the calls it ma…
lukecotter Sep 1, 2026
09386e7
refactor(lana): use URI-safe file access (#952)
peternhale Sep 1, 2026
c42be6a
fix(log-viewer): make a timeline resize smooth (#982)
lukecotter Sep 1, 2026
2fb6c43
fix(log-viewer): mark a row the renderer hands back without rebuildin…
lukecotter Sep 1, 2026
a1f7146
fix(log-viewer): keep grid search highlights in step with the rows on…
lukecotter Sep 1, 2026
22010a3
fix(log-viewer): hold the pointer on the governor limits strip (#983)
lukecotter Sep 1, 2026
6872734
fix(log-viewer): outline a selected frame instead of dimming the char…
lukecotter Sep 1, 2026
2c52fec
fix(lana): read files through workspace.fs, not Salesforce Services (…
lukecotter Sep 1, 2026
5456703
fix(log-viewer): point the inspector at one row, not the whole chain …
lukecotter Sep 2, 2026
cacf9cc
fix(lana): follow-up fixes for the Salesforce Services migration (#969)
lukecotter Sep 2, 2026
76c5b99
perf(log-viewer): stop re-rendering the grid header on every row sele…
lukecotter Sep 2, 2026
ff7ddf3
feat(lana): add VS Code web entrypoint (#953)
peternhale Sep 2, 2026
c32d0ff
test(lana): cover VS Code web host (#954)
peternhale Sep 2, 2026
ac87cb2
test(lana): fix the web e2e log fixture (#1000)
lukecotter Sep 2, 2026
0289974
build: add reproducible VSIX package command (#957)
peternhale Sep 2, 2026
29f3e51
build(deps-dev): bump the development-dependencies group across 1 dir…
dependabot[bot] Sep 3, 2026
4e8722f
build(deps): bump the production-dependencies group across 1 director…
dependabot[bot] Sep 3, 2026
b477f67
build(deps): bump the github-actions group across 1 directory with 2 …
dependabot[bot] Sep 3, 2026
a1bd27a
build(deps): bump actions/upload-artifact from 4 to 7 (#1002)
lukecotter Sep 3, 2026
5744ac1
ci(dependabot): drop the dead salesforce group (#1003)
lukecotter Sep 3, 2026
cb91a8a
fix(lana): bundle the web extension as a single file (#1001)
lukecotter Sep 3, 2026
fbeb675
fix(lana): follow-ups to the URI-safe file access migration (#997)
lukecotter Sep 3, 2026
d60bc49
build(deps-dev): bump lint-staged from 17.3.0 to 17.4.1 in the develo…
dependabot[bot] Sep 3, 2026
161a5c9
ci: gate merges on one aggregate job (#998)
lukecotter Sep 3, 2026
19a5f3c
chore: run the dev host in a Lana-only profile (#992)
lukecotter Sep 3, 2026
502ce63
refactor(log-viewer): find a grid's body through the one helper that …
lukecotter Sep 3, 2026
adaa137
perf(log-viewer): build the minimap skyline once per log, not once pe…
lukecotter Sep 3, 2026
aa3e77c
feat(log-viewer): show the variables in scope at the selected frame (…
lukecotter Sep 3, 2026
7db4979
ci: stop installing vsce and ovsx unpinned (#1004)
lukecotter Sep 3, 2026
af78b3c
fix(lana): keep the raw log Outline when the tab model lags (#1007)
lukecotter Sep 3, 2026
a40d4b5
chore(vscode): open sample-app in the dev host (#1008)
lukecotter Sep 4, 2026
ddabe8a
feat(log-viewer): open a class instance in the Variables section (#1009)
lukecotter Sep 4, 2026
bf37abd
docs: trim the unreleased changelog to short, user-focused entries (#…
lukecotter Sep 4, 2026
011058e
refactor(log-viewer): one size for code text, and tokens for the ring…
lukecotter Sep 4, 2026
bd833b0
fix(log-viewer): keep one governor trend chart reading at a time (#1013)
lukecotter Sep 4, 2026
a8a0dc8
fix(log-viewer): fire keyboard commands once while a key is held (#1016)
lukecotter Sep 5, 2026
34c79c3
fix(log-viewer): make severity text readable on light themes (#1019)
lukecotter Sep 8, 2026
3b0ee5a
fix(log-viewer): finish the fire-once contract for held keys (#1017)
lukecotter Sep 8, 2026
75cd033
refactor(log-viewer): style the located row once, not in six grids (#…
lukecotter Sep 8, 2026
8cc9231
feat(log-viewer): compare the variables across a merged row's calls (…
lukecotter Sep 9, 2026
b33496b
feat(log-viewer): arrange and size the inspector's sections (#1022)
lukecotter Sep 9, 2026
bbb02d3
fix(log-viewer): take governor limits only from the log, and measure …
lukecotter Sep 9, 2026
bcc6e21
docs: put every changelog rule in its skill, sub-bullets allowed (#1027)
lukecotter Sep 9, 2026
ff71cdc
fix(lana): embed browser log viewer assets (#1015)
peternhale Sep 9, 2026
3c163fe
fix(log-viewer): bring the frame the inspector picks into the timelin…
lukecotter Sep 10, 2026
a32e098
build(deps): bump pnpm/action-setup from 6.0.10 to 6.1.0 in the githu…
dependabot[bot] Sep 10, 2026
7e38acc
refactor(log-viewer): name the find bus events in one place
lukecotter Sep 14, 2026
9711c39
refactor(log-viewer): add a controller for listeners on document and …
lukecotter Sep 14, 2026
b0e30db
refactor(log-viewer): tie the find bus to each view's connected life
lukecotter Sep 14, 2026
0e09cb4
refactor(log-viewer): wire the inspector on the connected lifetime
lukecotter Sep 14, 2026
cd93633
fix(log-viewer): rebuild the call tree after a re-attach
lukecotter Sep 15, 2026
6d78a0f
refactor(log-viewer): give the grids one owner for their columns
lukecotter Sep 15, 2026
3a95cf4
refactor(log-viewer): tie the inspector wiring to the host's connecte…
lukecotter Sep 16, 2026
5453095
fix(log-viewer): release a visibility wait's listener when it resolves
lukecotter Sep 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .claude/rules/lana.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ VS Code extension. Applies when working under `lana/`.
## Settings

- **Give every user preference a `lana.*` setting.** Do not hide it in `globalState`.
- **Remembered UI state is not a preference.** The view a table was last left in, the inspector's
section layout, column overrides: these persist privately in `globalState` β€” see
`PRIVATE_SECTIONS` in `AppConfig.ts` β€” and are not registered settings.
- **Push `configChanged` to an open panel when a setting changes.** The panel sets
`retainContextWhenHidden`, so it is never re-created and never re-reads the config itself.

Expand Down
5 changes: 3 additions & 2 deletions .claude/rules/log-viewer.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ Webview UI.
- Never define or override a `--vscode-*` name β€” an override is global to the webview. Exception:
skinning a `vscode-elements` component; scope it to that element, never `:host` or `:root`.
- Write no literal font size or family. Take a step from the ramp in `styles/tokens.css`
(`--lana-text-*`, `--lana-text-mono` for editor-sized text, `--lana-text-meta` for header
metadata) and a family from `--lana-font-mono` or `--lana-font-ui`.
(`--lana-text-*`, `--lana-text-meta` for header metadata) and a family from `--lana-font-mono` or
`--lana-font-ui`. Code-shaped text takes no size of its own: it inherits the surface that holds
it, so nothing in the webview follows the reader's `editor.fontSize`.
- Mono is for text whose alignment carries meaning β€” stacks, code, log text. Prose takes the UI font.
- An all-caps run takes `--lana-text-caps` and `--lana-text-caps-tracking`, one step down: every
glyph reaches cap height, so caps read a size larger.
Expand Down
128 changes: 128 additions & 0 deletions .claude/skills/changelog-entry/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
---
name: changelog-entry
description: Write, review or trim CHANGELOG.md entries. Use when editing CHANGELOG.md, when a PR needs a changelog line, when a section is too long or a change may be breaking, or on a changelog conflict.
---

# Changelog entry

A changelog is written for the person who upgrades. How the change was made, what it cost, and which
files moved belong in the issue and the pull request.

## The shape of an entry

```
- [**Breaking:** ]<present-tense verb> <what the user gets> ([#<issue>])
```

```markdown
### Changed

- **Breaking:** drop `file` from `get_apex_log_summary` in favour of the scalar `topMethodsSelfPercentage` ([#86])
- Reduce every tool response with no fact lost: `execute_anonymous` by 30%, `get_apex_log_summary` by 27% ([#86])

<!-- Unreleased -->

[#86]: https://github.com/owner/repo/issues/86
```

- **One sentence.** No semicolon joining two facts. Two wrapped lines is the ceiling.
- **Sub-bullets only where one feature has distinct parts** β€” three at most, each naming one
capability. Never how it was built.
- **Present tense.** "reports", "shows", "flags" β€” never "reported", "showed".
- **Breaking entries first** in their section, prefixed `**Breaking:**`.
- **Then most impactful first.** The entry that changes the most readers' day leads its
section. Not commit order, not issue number, not the order you wrote them.
- **Sections in this order:** Added, Changed, Fixed.
- **A reference link on every substantial entry**, defined under `<!-- Unreleased -->` at the end of
the file. Never an inline URL.

## This repo's house style

```
- <emoji> **Label**: <what the user gets> ([#issue])
```

Say what the user gets. No leading verb β€” the label names the feature. Use an emoji no other entry
in the section uses.

The root `CHANGELOG.md` is the source. The `lana/` copy is generated by the build β€” never edit it.

**The file outranks this skill on style.** Match the released sections. Length and jargon are not
style β€” those rules always hold.

## Write for the reader, not the author

The reader upgrades the package; they did not write it. Name the outcome they can see.

- **No internal jargon.** No module, class, library or algorithm names. If the reader cannot find
the word in the product, cut it.
- **A fix names the symptom, not the cause.**
- **A big feature gets one headline entry**, plus up to three sub-bullets for its parts. Detail
belongs in the docs.

## What earns an entry

One entry per user-visible change, not one per commit. If a user of the released package cannot see
it, it gets no entry: a refactor, a renamed internal helper, a test, the mechanism behind a fix.

Give the result, not the method. A number earns its place when the size **is** the result; how it
was measured does not.

**A performance entry always carries its number** β€” a multiple or a percentage, and what it is of.
"Faster" on its own is not an entry, because the reader cannot tell whether to care.

Already-unreleased work: edit the existing entry, and drop a fix for a bug that only ever existed
in it. A change nobody has received is not a change, and nobody met the bug.

No issue fits? File one, then reference it.

## Wrong, then right

| Wrong | Right |
| ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
| `- Removed destructiveHint from three tools, since the spec says it is meaningless when readOnlyHint is true` | no entry β€” the user sees no difference |
| `- Replaced ten per-category properties with one z.partialRecord, cutting ~844 to ~428 tokens` | fold the result into the one user-facing entry |
| `- Reduced the cost by 31% ([#87](https://.../87))` | `- Reduce the cost by 31% ([#87])`, plus a reference definition |
| `- Refactor CSV parsing to process dataset arrays asynchronously` | `- Fix the freeze on a large CSV export` |
| `- Replace webview-ui-toolkit with vscode-elements` | `- Match the host's controls more closely` |
| a feature with six nested sub-bullets | a headline sentence, then three sub-bullets at most, one capability each |
| `- Improve search performance` | `- Search a 100MB log 10Γ— faster` |
| `- Optimise the parser` | `- Cut parse time on a large log by 31%` |

## Trim a section nobody will read

Screens long, or nested three deep. Rewrite the section whole β€” entry-by-entry edits never merge
anything, and merging is most of the win.

1. Find the bounds: `grep -n '^## \[' CHANGELOG.md`.
2. Read the whole section before changing a word.
3. Draft the replacement in one pass. Three sub-bullets at most under a headline; fold or drop
the rest.
4. Merge entries that name the same surface or the same fix. Three styling entries are one entry.
5. Drop what the reader cannot see, by the rules above.
6. Re-order each section by impact. A trimmed section in the old order still buries the lead.
7. Keep every issue reference. Losing one loses the trail to the detail you cut.
8. Splice it in, then check the references β€” left column is used but undefined, right is defined but
unused:

```bash
comm -3 <(grep -v '^\[#' CHANGELOG.md | grep -o '\[#[0-9]*\]' | sort -u) \
<(grep -o '^\[#[0-9]*\]' CHANGELOG.md | sort -u)
```

9. Run the repo's formatter.

Report the before/after line count and every entry you merged or dropped. A cut the author disagrees
with is invisible to them otherwise.

## Versions and migration

- A version heading is added when the release is tagged, with an absolute date: `## [1.0.0] - 2026-03-20`.
Until then everything sits under `## [Unreleased]`.
- **Major** is forced by behaviour that changes for someone who upgrades and changes nothing else.
- When upgrading needs an action, add a migration note under `## [Unreleased]` that points at it.

## Stacked branches

Every branch in a stack writes into the same `## [Unreleased]` section, so a rebase conflicts there.
Keep both sides. Losing the other branch's entry is silent, and review will not catch it.
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
*.log filter=lfs diff=lfs merge=lfs -text

# e2e fixture: small enough to keep in git, and LFS pointers are not Apex logs
lana/test/playwright/fixtures/*.log -filter diff merge text
4 changes: 0 additions & 4 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,6 @@ updates:
# majors are deliberately left out of the minor/patch groups so each one still
# arrives as its own PR - they need reading and are reverted individually
groups:
# exception: @salesforce/apex-node majors require the matching
# @salesforce/core major, so these move in lockstep incl. majors
salesforce:
patterns: ['@salesforce/*']
production-dependencies:
dependency-type: 'production'
update-types: ['minor', 'patch']
Expand Down
18 changes: 6 additions & 12 deletions .github/workflows/cd-prerelease.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,28 +63,22 @@ jobs:
- name: Checkout code
uses: actions/checkout@v7
- name: Setup pnpm
uses: pnpm/action-setup@v6.0.9
uses: pnpm/action-setup@v6.1.0
with:
version: 10
- name: Set up Node
uses: actions/setup-node@v7
with:
node-version: '24'
cache: 'pnpm'
- name: Install vsce + ovsx
run: |
pnpm add --global @vscode/vsce
pnpm add --global ovsx
- name: Dependencies
run: pnpm run ci:install
- name: update pre-release version
run: |
echo "Updating pre-release version"
pnpm run bump-prerelease;
- name: Package the extension
run: |
cd lana
vsce package --pre-release --no-dependencies
run: pnpm --filter lana exec vsce package --pre-release --no-dependencies
- name: Publish to VS Code Marketplace + Open VSX Registry
# Tokens via env (not -p) so they don't appear in the process list.
env:
Expand All @@ -93,22 +87,22 @@ jobs:
run: |
cd lana
echo "Verify vsce token has not expired"
vsce verify-pat
pnpm exec vsce verify-pat

echo "
Verify ovsx token has not expired"
ovsx verify-pat
pnpm dlx ovsx@1.1.1 verify-pat

versionNum=$(jq -r '.version' package.json)
pkgPath="lana-${versionNum}.vsix"

echo "Publish to vsce
vsix name: $pkgPath"
vsce publish --packagePath "${pkgPath}" --no-dependencies --pre-release --skip-duplicate
pnpm exec vsce publish --packagePath "${pkgPath}" --no-dependencies --pre-release --skip-duplicate

echo "
Publish to ovsx"
ovsx publish "${pkgPath}" --no-dependencies --pre-release --skip-duplicate
pnpm dlx ovsx@1.1.1 publish "${pkgPath}" --no-dependencies --pre-release --skip-duplicate
- name: Update pre-release tag
run: |
echo "Updating pre release tag"
Expand Down
62 changes: 54 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ on:
push:
branches: [main, release/**]
pull_request:
branches: [main, release/**]
workflow_dispatch:

# Least-privilege default: CI only needs to read the repository.
Expand All @@ -19,7 +18,7 @@ jobs:
- uses: actions/checkout@v7
with:
persist-credentials: false
- uses: pnpm/action-setup@v6.0.9
- uses: pnpm/action-setup@v6.1.0
with:
version: 10
- name: Set up Node
Expand All @@ -45,7 +44,7 @@ jobs:
- uses: actions/checkout@v7
with:
persist-credentials: false
- uses: pnpm/action-setup@v6.0.9
- uses: pnpm/action-setup@v6.1.0
with:
version: 10
- name: Set up Node
Expand All @@ -58,26 +57,73 @@ jobs:
- name: Tests
run: pnpm exec jest --selectProjects ${{ matrix.project }} --runInBand

e2e:
name: Test (web e2e)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false
- uses: pnpm/action-setup@v6.1.0
with:
version: 10
- name: Set up Node
uses: actions/setup-node@v7
with:
node-version: '24'
cache: 'pnpm'
- name: Install Packages
run: pnpm run ci:install
- name: Install Chromium
run: pnpm exec playwright install --with-deps chromium
- name: Tests
run: pnpm run test:e2e:web
- name: Upload Playwright HTML report
if: failure()
uses: actions/upload-artifact@v7
with:
name: playwright-report-web
path: lana/playwright-report/web
if-no-files-found: ignore
retention-days: 7
- name: Upload Playwright test results
if: failure()
uses: actions/upload-artifact@v7
with:
name: playwright-test-results-web
path: lana/test-results/web
if-no-files-found: ignore
retention-days: 7

build:
name: Verify VSCode Package Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false
- uses: pnpm/action-setup@v6.0.9
- uses: pnpm/action-setup@v6.1.0
with:
version: 10
- name: Set up Node
uses: actions/setup-node@v7
with:
node-version: '24'
cache: 'pnpm'
- name: Install vsce
run: pnpm add --global @vscode/vsce
- name: Install Dependencies
run: pnpm run ci:install
- name: Build VSCode Package
run: pnpm --filter lana run build:vsix

gate:
# The single required status check: the ruleset never needs updating when jobs change.
name: CI Gate
needs: [verify_files, tests, build]
if: always()
runs-on: ubuntu-latest
steps:
- name: Check job results
if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') || contains(needs.*.result, 'skipped')
run: |
cd lana
vsce package --no-dependencies
echo "A required job did not succeed."
exit 1
4 changes: 2 additions & 2 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,12 @@ jobs:
# JavaScript/TypeScript is analyzed straight from source, so no build is needed
# (build-mode: none skips the Autobuild dependency-install/build attempt).
- name: Initialize CodeQL
uses: github/codeql-action/init@v4.37.4
uses: github/codeql-action/init@v4.37.9
with:
languages: ${{ matrix.language }}
build-mode: none

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v4.37.4
uses: github/codeql-action/analyze@v4.37.9
with:
category: '/language:${{matrix.language}}'
2 changes: 1 addition & 1 deletion .github/workflows/publish-gh-pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
persist-credentials: false
# πŸ‘‡ Build steps
- name: pnpm setup
uses: pnpm/action-setup@v6.0.9
uses: pnpm/action-setup@v6.1.0
with:
version: 10
- name: Set up Node
Expand Down
18 changes: 6 additions & 12 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,18 @@ jobs:
- uses: actions/checkout@v7
with:
persist-credentials: false
- uses: pnpm/action-setup@v6.0.9
- uses: pnpm/action-setup@v6.1.0
with:
version: 10
- name: Set up Node
uses: actions/setup-node@v7
with:
node-version: '24'
cache: 'pnpm'
- name: Install vsce + ovsx
run: |
pnpm add --global @vscode/vsce
pnpm add --global ovsx
- name: Dependencies
run: pnpm run ci:install
- name: Build extension
run: |
cd lana
vsce package --no-dependencies
run: pnpm --filter lana run build:vsix
- name: Publish to VS Code Marketplace + Open VSX Registry
# Secrets and the release tag are passed via env (not interpolated into the
# shell) to avoid leaking tokens in the process list and shell injection.
Expand All @@ -44,11 +38,11 @@ jobs:
run: |
cd lana
echo "Verify vsce token has not expired"
vsce verify-pat
pnpm exec vsce verify-pat
echo "Verify ovsx token has not expired"
ovsx verify-pat
pnpm dlx ovsx@1.1.1 verify-pat

echo "Publish to vsce"
vsce publish --packagePath "lana-${TAG}.vsix" --no-dependencies
pnpm exec vsce publish --packagePath "lana-${TAG}.vsix" --no-dependencies
echo "Publish to ovsx"
ovsx publish "lana-${TAG}.vsix" --no-dependencies
pnpm dlx ovsx@1.1.1 publish "lana-${TAG}.vsix" --no-dependencies
Loading