Skip to content

GemStone Manager: one screen for the GemStone environment - #454

Open
srbaker wants to merge 13 commits into
mainfrom
srbaker/manager-panel
Open

GemStone Manager: one screen for the GemStone environment#454
srbaker wants to merge 13 commits into
mainfrom
srbaker/manager-panel

Conversation

@srbaker

@srbaker srbaker commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator

Running GemStone means keeping four things in order: an operating system
configured to hand out shared memory, a version installed from it, a database
made from that version, and a login that reaches the database. Each has its own
sidebar view, which is fine once everything is up — and four separate lists to
walk when it isn't.

This adds GemStone Admin: GemStone Manager, an editor tab that puts all four
on one screen in the order they matter. A machine that cannot hand out enough
shared memory says so before anything else; a machine with nothing installed
leads with the versions; once neither is true the screen leads with connecting,
because that is what it is usually opened to do.

Reading it

Eight commits. The first two stand on their own without the panel as their
excuse, and are worth taking first:

  • Put the 1 GB shared-memory rule in one place. Three places rederived
    shmmax / 2^30, shmall / 2^18 and >= 1 from scratch — the Start Stone
    preflight, Quick Setup, and the OS view's own status node, which also formats
    the reading for display. One helper now answers it, and the status node loses
    its if/else entirely.
  • Answer what is installed without asking the network. fetchCatalog does
    the scrape; versionsFrom turns a catalog plus the disk into rows;
    fetchAvailableVersions is the two together and is unchanged for its callers.
    getInstalledVersions becomes versionsFrom([]), which is what makes the
    offline list filtered and ordered like the online one — it had not been, so the
    panel's first paint showed releases Jasper cannot drive, which then vanished.

Then the panel itself, the two commits that complete it, the acceptance chapter,
a test-hardening pass, and the changelog note.

What the screen offers

  • Operating System — a checklist, one row per prerequisite this machine
    actually has (shared memory with how much is still free rather than just the
    limit, RemoveIPC, the WSL version, mirrored networking, both gs64ldi services
    entries, the hosts entry), each saying what the machine reports and carrying
    its own remedy only while it is failing.
  • Connect — every login with its user and stone and whether that stone is up;
    log in, start-and-log-in, edit, delete, duplicate, select a session, plus the
    session actions including Export Classes and Full Logical Backup.
  • Versions — download, extract, install, uninstall, register and unregister
    local builds, open the folder or a terminal, the Windows client trio, the
    walkthrough.
  • Databases — per row: version, stone and NetLDI state, processes with PIDs
    and ports, logins, extent chooser, log/conf/backup files; create, delete,
    start/stop, replace extent, back up, restore, install server support, terminal,
    reveal, create and edit logins, clear a stale lock, copy host.

Everything the four sidebar views offered, the manager offers. The panel accepts
47 kinds of message, two of which fan out through an allow-list — 8 session
actions and 9 operating-system remedies — and each was checked against the
contributions of the view that used to own it.

How it is built

It dispatches the existing gemstone.* commands rather than reimplementing them,
so confirmations, progress and tree refreshes come from the code that already
owns them. It does not trust the webview: session actions and OS remedies are
matched against allow-lists, and a file path is re-checked against its database
before anything is opened or restored from. It keeps itself current from the
admin views' own change events — coalesced, quiet, one scan at a time, and idle
while its tab is hidden.

Two things worth calling out

@vscode/codicons is a production dependency. The panel draws every icon
with the codicon font, which a webview inherits nothing of, and vsce prunes
devDependencies — so a .vscodeignore whitelist over one would find nothing left
to package. Two files ship (codicon.css, codicon.ttf), the icons are
CC BY 4.0, and THIRD-PARTY.md carries the attribution. Both files and the
dependency are pinned by a guard, because losing either costs nothing at compile
time and nothing in the dev host: the panel renders with every glyph a blank box,
and only once packaged.

The manager is palette-only for now. An icon beside the GEMSTONE title needs
viewContainer/title, which is a proposed API the workbench only honours for
workbench.view.debug. A gear on the container becomes available once the
sidebar collapses toward a single view.

Verified

lint, format:check, compile, lint:supply-chain, lint:lockfile clean.
npm test green — 5,421 client, 322 server, 92 mcp, against a live test stone.

A new acceptance chapter runs green headless in the container
(npm run test:acceptance:docker): the four sections on opening, the
operating-system checklist read from the machine's real sysctl and ipcs, and
logging in to a database from Connect. Writing it found three bugs the unit tests
could not — a section snapping shut on redraw, a live session offered "Start &
log in", and a stone this machine did not create always reading as stopped.

The tests were then audited by mutation rather than by reading: break a line of
production code, see whether anything fails. Fourteen changes broke nothing, the
worst being that neither allow-list had a test that the list is ever consulted —
the fixture held no sessions, so nothing reached that path, and deleting both
checks left the suite green. All fourteen now fail a test.

Known gaps

Four project-management acceptance scenarios are red, and were red before this
branch — verified by stashing its work and re-running. Diagnosed separately: the
shared Given I am logged in to a database asserts on a sidebar that logging in
has replaced, since the Explorer is its own view container.

The Connect scenario reaches the database through "Start & log in" rather than
"Log in": the container's GemStone lives outside the folder Jasper scans, so it
finds no installed version to run gslist from and cannot see the stone at all.
That is an honest picture of a login to a stone made elsewhere, but it leaves the
plain "Log in" path without acceptance coverage.

Three places knew that a stone needs a gigabyte, and each rederived it from the
same two magic divisors: `isSharedMemoryConfigured`, which the Start Stone
preflight gates on; Quick Setup, which warns before it builds anything; and the
OS view's own status node, which also formats the reading for display. Three
copies of `shmmax / 2^30`, `shmall / 2^18` and `>= 1`, in two files.

They are one question — does this reading clear the threshold, and how do we say
how much there is — so `sharedMemoryStatus` answers it once and the three ask.
An unreadable sysctl was already "not configured" everywhere; the helper returns
that, which is how the view's node loses its if/else entirely.

No behaviour changes: the divisors, the comparison and the label are the ones
the status node already produced, and its tests pin every branch of them.
`fetchAvailableVersions` did two jobs in one pass: scrape the downloads page,
then work out from the disk what is downloaded, extracted, or a local build.
Only the first needs the network, and only the second changes between two calls
a minute apart. A caller wanting the cheap half had no way to ask, so it paid
for a round trip — and got nothing at all when the machine was offline, which
is exactly when knowing what is already installed matters most.

The two are now separate. `fetchCatalog` answers what the downloads page lists.
`versionsFrom` turns a catalog plus the disk into rows, reading the disk afresh
every time, so a caller may hold one catalog and ask as often as it likes.
`fetchAvailableVersions` is the two together and is unchanged for its callers.

`getInstalledVersions` is then `versionsFrom([])`: a catalog listing nothing
already means every extracted version becomes a row, since none can be in it.
Saying it that way rather than mapping the rows a second time is what makes the
two lists agree — the offline answer is now filtered and ordered exactly like
the online one, where a hand-rolled second pass had left it in whatever order
the directory happened to be read in, carrying releases too old for Jasper to
drive that the catalog answer drops.

The row builder behind both is `installedVersion`, which is the fifteen lines
the two extracted-version loops each used to carry. It sets `local` only for a
symlinked build; a real directory leaves the flag absent, which is the shape
that pass has always produced.
Getting from a fresh install to a live session means visiting four separate
sidebar trees — OS prerequisites, versions, databases, logins — each showing a
slice of the answer and none of them showing what to do next. The manager is
one editor tab that renders all four, ordered by what is actually blocking you:
a machine that cannot run a stone leads with Operating System, a machine with
no release installed leads with Versions, and once both are settled they sink
below Connect and Databases.

It is a read/coordinate surface, not a reimplementation. Every mutating action
dispatches an existing `gemstone.*` command, so the confirmation modals,
progress notifications and tree refreshes come from the code that already owns
them. It does not trust the webview either: session actions are matched against
a fixed list rather than executed on trust, and a file it is asked to open or
restore from is re-checked against its own database directory first.

It keeps itself current. Logins live in a setting, and the editor that writes
them saves long after the command which opened it returned, so Connect follows
`gemstone.logins` rather than the moment of dispatch. Everything else follows
the admin views' own change events, coalesced so one command that refreshes
several views costs one rebuild — and a rebuild is quiet, because the panel is
refreshing under someone who is reading it. A change arriving while its tab is
hidden waits until the tab comes back.

A refresh renders twice: once from what is already on disk, then again when the
download catalog answers, so the panel is usable while the catalog is in flight
and stays usable when it never arrives. The catalog is then held for as long as
the panel is open — what changes between two rebuilds is on disk, and a network
round trip behind every stone start is a wait for nothing. Refresh drops it, so
the button still means what it says.

A command that rejects is reported rather than dropped: a dispatch is
fire-and-forget from here, so without that a failed start reads as a click that
never registered — nothing said, nothing logged, the panel unchanged. Listing a
database's files asks the filesystem once per directory, too. Stating each name
in turn costs a `wsl.exe` spawn per file where paths route through WSL, which a
directory of stone logs turns into a frozen window on every rebuild.

What the reader has said stands. Which sections start open follows what needs
attention, which is right on arrival and wrong afterwards: the panel redraws
whenever anything changes, so a section opened to work through would otherwise
snap shut under them. And a live session outranks anything guessed about its
stone — the session is first-hand knowledge that the stone is up, where
"running" is read from a process list this machine may have no installed version
to consult, so a login that is connected is no longer offered the button that
starts its stone. Whether a stone is up now falls back to that process list for
a login whose database was not made here, rather than reading as stopped.

Two things it learned from being used: `startstone` and `startnetldi` exit
non-zero when the server is already running, so it starts only what is down —
the sidebar never hit that because its Start actions only appeared on a stopped
row. And gslist reports a start time to the minute, so a stone that came up
seconds ago reads "just started" rather than "running 0 min".

It follows the two settings it depends on, `gemstone.logins` and
`gemstone.rootPath` — the second being the folder every database and installed
version is found under, and the one the panel itself offers a button to change.

The icons are the codicon font, which a webview inherits nothing of, so
`codicon.css` and `codicon.ttf` ship in the `.vsix` behind two `!` lines holding
them out of the wholesale `node_modules/**` exclusion. That makes them
third-party files this extension distributes: the icons are CC BY 4.0, and
THIRD-PARTY.md carries the attribution beside the vendored AST it already
covers. Both files are pinned by a guard, since losing the whitelist or the
production dependency that leaves them there costs nothing at compile time and
nothing in the dev host — the panel renders with every glyph a blank box, and
only once packaged.

The behavior lives in gemstoneManagerView.js, read at module load and injected
as a nonce'd <script> under a strict CSP, as debuggerPanel.ts does. The
`*View.js` suffix is not decoration: a webview script sharing this module's
basename would shadow it, since Vite resolves an extensionless import to the
.js of such a pair. The codicon font ships with the extension because a webview
inherits none.
The panel could say only that shared memory was short, and offer Quick Setup.
Every other prerequisite the Configure OS view knew about — RemoveIPC, the WSL
version, mirrored networking, the two gs64ldi services entries, the hosts entry
— was invisible here, and so were the eight commands that fix them. On Windows
that is the whole story of why a stone will not start.

The OS section is now a checklist: one row per prerequisite this machine
actually has, each saying what the machine reports — '2.0 GB', 'mirrored',
'gs64ldi missing' — and carrying its own remedy only when it is not ok. That is
how the tree read, a status with the thing that fixes it underneath, and it
answers "which part is wrong" rather than only "something is".

Which rows appear follows the machine: shared memory everywhere, RemoveIPC on
Linux and on the Linux inside WSL, and the WSL set only where paths route
through WSL. The hosts entry appears only while networking is NAT, since that
is the only time it matters.

The shared-memory row reports headroom, not just the limit. shmall is a ceiling
for the machine, not for one stone: caches other stones already hold count
against it, so this laptop cleared the 1 GB threshold with 123 MB free and no
stone would start. The row now reads what is allocated against the limit, from
ipcs, and warns below 100 MB free — what a database Jasper creates asks for
(SHR_PAGE_CACHE_SIZE_KB = 100000). Reading ipcs means knowing which lines are
segments: macOS opens one with the type letter and Linux with the hex key, and
taking any line with enough columns counts macOS's title line, whose last field
is the year.

Refresh forgets the WSL answers before rebuilding. They are cached and the
checklist reads them, so a machine could stay "WSL not reachable" after the
user had made it reachable — a checklist that cannot recover from being right
once. `gemstone.refreshVersions` already did this, which is why the trees
recovered and the panel did not.

The probes were all there — getRemoveIpcConfigured, getWslInfo,
getWslNetworkInfoCached, and the two services checks, which are exported now
rather than private to the module that used to draw them. Remedies dispatch
through an allow-list, exactly as session actions do: the webview sends a
command name, and a name that is not a known remedy is dropped rather than run.
Fourteen actions the trees had and the panel did not, each dispatched to the
command that already owns it.

Logins gain Delete and Duplicate beside Edit, and selecting a session goes
through `gemstone.selectSession` rather than the session manager directly, so
everything else showing the selection follows. Export Classes and Full Logical
Backup join the session actions — the second is a different backup from the
extent one already here, and it belongs to a session rather than to a database.

Versions gain a terminal for a product folder, the Windows client trio, and the
walkthrough. The client actions need to know whether a client is extracted, so
the row carries that now; they and Copy Host appear only where paths route
through WSL, since they mean nothing anywhere else.

Processes gain Copy Host and, on a process that stopped responding, clearing
its stale lock — the row already knew it was stale, it just had nothing to
offer about it.

Databases gain Install Server Support. Whether a stone has the Enhanced
Inspector and refactoring support is a property of that database, and until
now the only way to find out was an inspector behaving differently. The
command resolves the session it needs and says so when there is none, so the
panel offers it without second-guessing.

Create Database now dispatches its command instead of calling the database
manager itself. Doing it here skipped that command's check for whether a login
already targets the new stone, so a database made from the panel could end up
with a second DataCurator login and no message. That was the last thing the
panel did for itself rather than delegating, and dropping it takes the whole
DatabaseManager dependency out of the panel's bag.
The panel had unit tests and nothing that had ever opened it. Those tests know
what the host posts and what the webview draws from a state handed to it; what
neither of them touches is the panel actually rendering inside VS Code, in a
webview two frames deep, wired to commands that reach a live database.

Three scenarios, in a chapter of their own so the storyboard reads as the
screen's own section of the manual: the four sections are there on opening; the
operating-system checklist says what this machine reports, read from its real
sysctl and ipcs; and a login listed under Connect logs in, leaving the row
offering to log out again and naming the session the editor now works through.

Writing them found three things the unit tests could not. A section opened to
read through snapped shut on the next redraw, because which sections start open
is decided fresh each render — now the reader's answer outlives it. A login
whose stone Jasper cannot see running was offered "Start & log in" even while
connected to it, because the row asked about the stone before asking whether a
session was already open on it. And whether a stone is up fell back to reading
as "no" for any database this machine did not make here, rather than asking the
process list. Each has a unit test of its own alongside the fix.

The Connect scenario reaches the database through "Start & log in" rather than
"Log in": the container's GemStone lives outside the folder Jasper scans, so it
finds no installed version to run gslist from and cannot see the stone at all.
That is the honest picture of a login to a stone made elsewhere, and the button
starts only what is down, so it is the way in either way.
A mutation run over the panel — break a line of production code, see whether
any test notices — found fourteen changes the suite let through. They fall into
three groups, and none of them was a test that failed to assert; they were
guarantees nothing had been written about at all.

The two allow-lists are the worst of it. Both are described in this code as the
panel's defence against running a command name the webview invented, and
neither had a test that the list is ever consulted: the fixture held no
sessions, so nothing reached the session-action path, and deleting both checks
outright left the suite green. There are now four tests — an offered action
runs, one that is not offered does not, for each list — and a fifth asserting
every id in them is a command this extension registers, since a rename
elsewhere would leave a button silently doing nothing.

The panel's own machinery was the second group. It is a singleton, and building
a second one instead of revealing the first went unnoticed, as did never
releasing it on close; two panels would show the same environment side by side
and drift apart the moment either acted. Its one-scan-at-a-time rule was in the
same position: running scans concurrently, or dropping the pass queued behind
one, both passed — and the first is how an older scan comes to post its state
last.

The rest were single guarantees: markup in a name has to arrive as text, a
process belongs to a database only if the version matches too, a change of
session redraws Connect, a tab being shown is not a reason to rescan, and a
start time that is not a date answers nothing.

Every one of the fourteen now fails a test.
Comment thread client/src/gemstoneManagerView.js Fixed
Every user-facing change in the file carries an entry; this is the largest one
since the refactoring engine.
@srbaker
srbaker force-pushed the srbaker/manager-panel branch from b15d286 to 7e1c6ab Compare August 18, 2026 18:28
srbaker and others added 5 commits August 18, 2026 21:30
…te scripting'

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
The autofix for the cross-site-scripting finding added `ev.source !== window` to
the webview's message listener, which drops every message the panel exists to
receive: VS Code relays the extension host's messages in from the frame around
this one, so `ev.source` is never this window. The panel renders its loading
skeleton and then nothing, for ever.

Nothing local caught it. The unit tests call `render(state)` directly and never
go near the listener; compile, lint and the packaging check are all indifferent.
The three acceptance scenarios, which drive a real editor window, went from green
to timing out on a section that never appears — which is the whole reason they
exist.

The two type guards that came with it are kept: they cost nothing and a message
without a `state` is not one this panel can draw.

The finding itself is about `innerHTML` in `render`, and checking the event's
source sanitizes nothing — it only cuts the path the analysis was following.
What answers it is `esc`, which every interpolation goes through, with tests
pinning that markup in a database name and in a login label arrives as text.
GemStone Search docks a webview of its own in the panel as soon as a session
exists, so from the login scenario onward `iframe.webview` matches two frames
and Playwright refuses the ambiguity rather than guessing. Its QuickPick form is
the same feature with no second webview, and this suite is not about search.

It sits with the other settings that quiet the workbench for a clean trace.
Auditing every interpolation in the view for the cross-site-scripting finding
turned up two that skipped the escaper: a process's pid and port. Both come from
parsing gslist output, so neither is a plausible carrier, but they were the only
values reaching the markup unescaped and the rule this file follows is that all
of them go through `esc`.

This does not answer the finding, which is about the `innerHTML` in `render`
rather than any particular value. It closes the gap the audit for it found.
@ericwinger
ericwinger self-requested a review August 19, 2026 17:33

@MatiasFernandez MatiasFernandez left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left a few comments, I want to spend some time testing the new view. We discussed with Eric in the past that the sidebar would require some improvements but we haven't settle on a path forward, so I want to play around with this proposal to see how it feels

* would otherwise need, in the order that works. The stone must answer before
* the login is attempted, so the start is awaited rather than fired alongside.
*/
/** Run one of the allowed session commands against a live session. */

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💭 Three doc blocks have stacked up on this one method, and the two above it belong to methods further down: "Connect as a specific login..." is connectLogin's, and "Bring a stopped database up and then log in..." is startAndConnect's -- both of which now sit below with no doc of their own. Someone hovering runSessionAction is told it connects a login.

Same shape at line 759: installNewVersion carries installVersion's "Installing a chosen release is a single action: fetch the archive, then extract it" ahead of its own block.

Looks like a reorder that left the comments behind -- can you move each block back onto the method it describes? It matters a bit more than usual here since runSessionAction is one of the two allow-list gates, so it's a method people will read before touching.

const { panel } = openPanel();

changeSetting('editor.fontSize');
await new Promise((resolve) => setTimeout(resolve, 0));

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💭 I think this one passes whether the code is right or wrong. markStale schedules the rebuild on the 200 ms coalescing timer, so at setTimeout(..., 0) nothing has been posted yet even if editor.fontSize had wrongly triggered a rebuild -- the assertion is satisfied by the timer not having fired, not by the setting being ignored.

await settle() (400 ms, as the neighbouring tests use) would make it fail if the filter regressed. Worth calling out given the mutation audit in the description: this is exactly the shape that survives one -- delete both affectsConfiguration checks and this test stays green.

* `gs64ldi <port>/tcp` entry? Routed through wslExecSync so the check
* inspects the Linux distro, not any Windows file of the same name. */
function wslServicesHasGs64ldi(): boolean {
/** Does the WSL distro's /etc/services carry the gs64ldi entry? */

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💭 The original block comment is still sitting above this one, so the function now carries two docs -- and TS surfaces only the nearest, which means the tooltip loses "Routed through wslExecSync so the check inspects the Linux distro, not any Windows file of the same name". That was the part explaining why the function exists rather than just reading the file. Same at line 48 for windowsServicesHasGs64ldi.

Was the intent to replace them? If so, should the routing rationale fold into the new one-liner rather than being dropped?

Related, while you're in here: isSharedMemoryConfigured (line 149) lost its doc entirely in this pass. "Treats an unreadable sysctl as not configured" is still true and still not obvious from the body.

}

/** Long enough for the panel's coalescing window to close and a rebuild to land. */
function settle(): Promise<void> {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💭 settle() is a flat 400 ms sleep and it's awaited around 20 times in this file, so roughly eight seconds of the suite is spent waiting out a 200 ms timer -- and it's the kind of margin that gets thin on a loaded CI box.

Would vi.useFakeTimers() plus await vi.advanceTimersByTimeAsync(COALESCE_MS + 1) work here? It would make the "exactly one more pass" and "rebuilds once for a burst" tests deterministic rather than merely likely, which is where the real value is -- those are the ones asserting an exact count. The tests that just wait for something to arrive already use vi.waitFor.

if (a.iconOnly) {
return `<button type="button" class="icon-btn" data-action="${action}"${data}${title} aria-label="${esc(label)}">${icon(iconKey)}</button>`;
}
const variant = cls === 'btn-primary' ? ' btn-primary' : '';

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💭 btn() only honours 'btn-primary' -- every other value of cls is silently discarded. 'btn-ghost' is passed at 24 call sites and 'btn-secondary' at one, and neither class appears in the CSS block in gemstoneManager.ts, so today they read as styling intent that never lands.

Should the argument just be dropped where it isn't btn-primary, or was .btn-ghost a rule meant to ship with the stylesheet? Either way it would stop the next reader assuming those buttons already render differently from the default secondary treatment.

// fails however comfortably the limit itself clears 1 GB.
const shmallBytes = mem ? mem.shmall * 4096 : undefined;
const free = shmallBytes !== undefined && inUse !== undefined ? shmallBytes - inUse : undefined;
const roomForACache = free === undefined || free >= 100 * 1024 * 1024;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💭 This 100 MB is the cache size databaseManager.ts:252 writes into every generated conf as SHR_PAGE_CACHE_SIZE_KB = 100000, but the two are independent literals -- and they don't quite agree, since 100000 KB is 102,400,000 bytes and this is 104,857,600.

Should the conf value become a shared constant both can read? The comment just above already names the coupling, which is what makes it worth pinning: if someone bumps the cache in databaseManager, this check keeps warning against the old figure and nothing fails.

@@ -0,0 +1,1509 @@
// GemStone Manager — a single, consolidated editor-tab webview that manages the

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💭 I see that all the logic for the gemstoneManager is sitting at the root of the client workspace. We've been working with Eric on reorganizing the code a bit to keep the code for big features grouped together. Could you create a gemstoneManager folder in client/src to group the logic and the related tests there?

Comment thread THIRD-PARTY.md

---

## Microsoft codicons (icon font)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💭 Why are we including this here if we are not vendoring codicons?

expect(whitelist.has(`!${file}`)).toBe(true);
});

// vsce prunes devDependencies before it packages, so a whitelist over one

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💭 I don't understand the purpose of this test; parsing the package.json feels weird. And the comment mentions devDependencies but the package is imported as a normal dependency. What do we lose if we remove this?

Comment thread .vscodeignore
!node_modules/koffi/index.d.ts
!node_modules/koffi/LICENSE.txt
!node_modules/koffi/build/**
# The GemStone Manager webview draws every icon with the codicon font, which a

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💭 Eric has been working on multiple webviews for different features, but this new one seems to be using a different styling/UI design. Are there specific limitations you found with the current established font/icons/styling, or is this just a preference? I'm worried about the visual consistency across the different webviews of Jasper.

@ericwinger

Copy link
Copy Markdown
Member

Left a few comments, I want to spend some time testing the new view. We discussed with Eric in the past that the sidebar would require some improvements but we haven't settle on a path forward, so I want to play around with this proposal to see how it feels

Yes, and I'd like to give it a try too.

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.

4 participants