Skip to content

Enhanced Inspector: automated install, classic fallback, and GT-style miller columns (#39)#137

Merged
jgfoster merged 9 commits into
mainfrom
eric/enhancedInspectorAutomation
Jul 2, 2026
Merged

Enhanced Inspector: automated install, classic fallback, and GT-style miller columns (#39)#137
jgfoster merged 9 commits into
mainfrom
eric/enhancedInspectorAutomation

Conversation

@ericwinger

Copy link
Copy Markdown
Collaborator

Summary

This PR turns the existing GT (Glamorous Toolkit) inspector into a first-class,
self-installing Enhanced Inspector feature. It automates the server-side
support that previously required a hand-run Topaz script, renames the
GT/Feenk-derived surface to a neutral "Enhanced Inspector" name (while keeping
upstream attribution), unifies inspection into a single command that gracefully
falls back to the classic tree inspector, and reworks the panel into a GT-style
miller-column layout.

Work item: #39 "Glamorous Toolkit Inspector Changes" (umbrella/epic).

User-visible changes (new/removed/renamed commands, keybindings, and settings,
plus a settings-migration note) are listed in
Commands, keybindings & settings changes.

What's included

  • Automated in-image install (enhancedInspectorCommand.ts,
    enhancedInspectorInstall.ts) — a GemStone: Install Enhanced Inspector Support command plus an opt-in auto-install-on-connect offer, replacing the
    external load_gemstone_gt_support.sh Topaz loader.
  • Rename GT/Feenk → "Enhanced Inspector" across code, commands, config keys,
    docs, and file names (gtInspector.tsenhancedInspector.ts,
    getGtViewSpecs.tsgetEnhancedInspectorViewSpecs.ts,
    docs/gtSupport/docs/enhancedInspectorSupport/), with upstream
    attribution preserved.
  • Unified "Inspect It" (inspectRouter.ts, codeExecutor.ts) — one command
    everywhere that routes to the Enhanced Inspector when available, else the
    classic gemstoneInspector tree view. Removes the separate "GT Inspect It"
    command, its menu entry, and the ctrl+k o keybinding.
  • GT-style miller columns (enhancedInspectorColumns.js,
    enhancedInspector.ts) — one webview with N min-width/grow columns and
    horizontal scroll; drilling inserts a column additively to the right, columns
    close independently, and the title tracks the focused column.
  • Vendored payload shipped in the VSIX (resources/enhancedInspector/*.gs)
    with developer scripts to refresh it from upstream
    (docs/enhancedInspectorSupport/).

Commands, keybindings & settings changes

New commands

Command ID Title Category
gemstone.installEnhancedInspector Install Enhanced Inspector Support GemStone
gemstone.configureEnhancedInspectorAutoInstall Enhanced Inspector Auto-Install… GemStone

Removed commands

Command ID Title Notes
gemstone.superInspectIt GT Inspect It Folded into the unified gemstone.inspectIt; its editor-context-menu entry and ctrl+k o / cmd+k o keybinding were removed too.

Renamed commands (GT → Enhanced Inspector; category GemStone GTGemStone)

Old ID New ID
gemstone.enableGtPerfTracking gemstone.enableEnhancedInspectorPerfTracking
gemstone.disableGtPerfTracking gemstone.disableEnhancedInspectorPerfTracking
gemstone.resetGtPerfCounter gemstone.resetEnhancedInspectorPerfCounter
gemstone.showGtPerfDetails gemstone.showEnhancedInspectorPerfDetails

Keybindings

  • Removed: ctrl+k o / cmd+k o (was "GT Inspect It").
  • Unchanged: ctrl+k i / cmd+k i still runs Inspect It — but it is now
    ungated. Previously the GT variant was gated on a gemstone.gtAvailable
    context; the single Inspect It now works everywhere and decides enhanced-vs-classic
    at runtime.

Settings

Setting Change Type / default
gemstone.gtPerfTrackinggemstone.enhancedInspectorPerfTracking Renamed boolean, default false
gemstone.enhancedInspector.autoInstall New enum ask | always | never, default ask

⚠️ Migration note: gemstone.gtPerfTracking was renamed, not aliased. Users who
had it set must re-enable gemstone.enhancedInspectorPerfTracking.

Login / connect behavior

  • On connecting to a stone without enhanced inspector support, behavior is driven by
    gemstone.enhancedInspector.autoInstall:
    • ask (default) — offer to install; the prompt's buttons write the chosen mode
      back into this setting.
    • always — install automatically using the SystemUser default password; if that
      password isn't accepted, a non-blocking notification explains how to install manually.
    • never — no offer.
  • Availability is probed at login (and re-latched after an install) and drives whether
    Inspect It opens the Enhanced Inspector or the classic tree view.

Context keys

  • gemstone.gtPerfTracking (menu when clauses) → gemstone.enhancedInspectorPerfTracking.
  • gemstone.gtAvailable is no longer used to gate any command (the unified Inspect It
    routes at runtime instead).

Walkthrough

  • New Get-Started step "Try the enhanced inspector", linking to the Auto-Install
    configuration command.

Key design decisions (for posterity)

Install model: one-time, idempotent, committed — not session/transient

A transient/session-method install was investigated and ruled out. The payload
is ~523 persistent class definitions plus ~279 kernel-class extension methods;
persistent classes cannot be session-scoped, and GemStone session methods can
only override existing selectors (never add new ones) and still require write
access to the class. So the install is a one-time, idempotent, committed
file-in, re-runnable at will (presence is not a gate).

SystemUser is required, obtained via a transient co-session

Adding the ~279 kernel-class extension methods requires write access to kernel
classes — i.e. SystemUser. The user is normally logged in as DataCurator,
so the install opens a short-lived, unregistered SystemUser session on the
same connection, files in, commits, and drops it.

  • The stock default password (swordfish) is tried first.
  • Manual install: if the default is rejected, the user is prompted for the
    SystemUser password; a wrong entry reports an error, cancel is a no-op.
  • Auto-install: if the default is rejected, it does not prompt (the user
    didn't initiate it) — it degrades to "not installed" with a non-blocking hint
    to run the manual command, and inspection falls back to the classic tree.
  • Known limitation: there is no way to pre-store a non-default SystemUser
    password, so a hardened stone requires re-entering it on each manual install.

Dictionary placement: Published, not Globals (and not UserGlobals)

Vendored classes are filed into the Published dictionary rather than
Globals. Published is already on every current and future user's symbol
list, so the classes are visible to everyone without polluting Globals.
UserGlobals (per-user) was considered and rejected: the kernel extension
methods are compiled into shared kernel classes and reference GT's own classes
by literal name, so those references must resolve through a shared dictionary —
per-user classes would be invisible to the shared kernel methods.

Vendoring: copy upstream verbatim + two deterministic transforms

The payload is refreshed from upstream verbatim
(update_enhanced_inspector_support.sh), then two idempotent transforms are
applied (apply_jasper_transforms.sh):

  1. rewrite inDictionary: GlobalsinDictionary: Published, and
  2. prepend a per-file attribution header (origin repo + MIT license).

Both transforms are re-appliable to any future upstream text, so we can always
pull the latest upstream by script.

"Minimal-subset refactor" (bullet 2 of #39): intentionally dropped

The idea of trimming the vendored code to a minimal subset (or splitting an
"ours" superclass from a "theirs" subclass) was explored and dropped. A
local structural refactor is fundamentally incompatible with the
"re-vendor upstream verbatim by script" model — any hand-edit would be
overwritten on the next refresh. The only vendoring-compatible version would be
to contribute the split upstream to Feenk, which is a large effort on a
third-party repo with uncertain acceptance; upstream marked it optional. We keep
the attribution/MIT headers (which satisfy the licensing intent) and defer any
minimal-subset work as an optional future upstream contribution.

Cosmetics

  • Command palette titles keep VS Code's Title Case convention (the lowercase
    "enhanced inspector" style applies to prose/docs only).
  • CHANGELOG.md history is left unchanged — it records what shipped under the
    names live at the time.

Attribution & licensing

Each vendored .gs file carries an origin (GitHub URL) + MIT license header:

  • gt4gemstone, gtoolkit-remote, gtoolkit-wireencoding, STON.gs,
    patch-gemstone.gs, Announcements.gs — © feenk gmbh (MIT)
  • RemoteServiceReplication.gs — © GemTalk Systems, Inc (MIT)

Testing

  • Latest main merged in; npm run compile clean.
  • Full suites green: server 320 / client 2372 (incl. live-stone integration) / mcp 95.
  • On-demand GCI smoke test added for enhanced-vs-classic routing
    (gciEnhancedInspectorRouting.smoke.test.ts).
  • Webview column model unit-tested in jsdom (enhancedInspectorColumns).

ericwinger and others added 9 commits June 30, 2026 17:01
Add server-side install of the enhanced inspector support and offer it
automatically when connecting to a stone that lacks it.

- enhancedInspectorInstall.ts: file the .gs payload in server-side via
  GsFileIn (one call per file, dependency order), commit once, verify.
- enhancedInspectorCommand.ts: Command Palette install over a transient
  SystemUser session, plus maybeOfferEnhancedInspectorInstall driven by the
  new gemstone.enhancedInspector.autoInstall tri-state (ask|always|never);
  the modal's buttons set the setting.
- gtAvailability.ts: shared refreshGtAvailable() latch used at login and
  after an install refresh.
- Post-install refresh is silent when the session has no pending work, and
  prompts (or when the probe can't tell) before discarding uncommitted work;
  aborts tolerate a session logged out mid-install.
- docs/gtSupport: retarget the payload to the Published dictionary, add
  per-file attribution headers, and an idempotent apply_jasper_transforms.sh
  wired into update_gemstone_gt_support.sh.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Packaging (ship blocker): move the 7 payload .gs files from docs/gtSupport/
to resources/enhancedInspector/ so they bundle into the VSIX (docs/** is
.vscodeignore'd). Repoint PAYLOAD_SUBDIR and the three dev scripts (which stay
in docs/gtSupport/) at the new location.

Discoverability: add the "GemStone: Enhanced Inspector Auto-Install…" command
(configureEnhancedInspectorAutoInstall) — a QuickPick that writes the tri-state
gemstone.enhancedInspector.autoInstall preference from anywhere, before login
too. It confirms the choice by flashing it in place (createQuickPick), since
notification toasts can be suppressed. Add a walkthrough step that links to it
and teaches the Command Palette shortcut. Skip an install button / first-inspect
offer: the connect-time modal already covers the install action.

Robustness (code review): guard the picker against re-entry, clear the flash
timer on early dismiss, and surface an error if the settings write fails.

Docs: rename "GT" prose to "Enhanced Inspector" (title case) / "enhanced
inspector" (in sentences); filenames unchanged.

Tests: cover runInstallEnhancedInspector (no session, default-password install,
password prompt success/failure/cancel), the missing-payload branch, and the
auto-install picker. Full suite green (client 2334, server 320, mcp 95).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… (Stage 5)

Rename the symbols, files, directories, config, commands, and comments we own
from GT* to Enhanced Inspector. Leave upstream Gt*/Rsr*/STON* classes, the .gs
payload filenames, and external Glamorous-Toolkit behavior references untouched.

- Class GtInspector -> EnhancedInspector; gtInspector.ts, gtAvailability.ts,
  gtPerfTracker.ts, queries/getGtViewSpecs.ts and 11 test files renamed to
  enhancedInspector*.
- Context key gemstone.gtAvailable -> gemstone.enhancedInspectorAvailable;
  webview panel viewType gemstoneSuperInspector -> gemstoneEnhancedInspector.
- docs/gtSupport/ -> docs/enhancedInspectorSupport/; loader/updater scripts and
  the perf-tracker .st renamed.
- Breaking: config key gtPerfTracking -> enhancedInspectorPerfTracking (no
  migration); perf commands, category, titles, output channel de-GT'd.

Fix a wire-value half-rename: cellHtml compared __typeLabel against the server's
'gtPhlowRunBasedText' value, which the rename wrongly changed on the client side
only, silently dropping run-based-text styling. Reverted, guarded with a
do-not-rename note, and covered by a new regression test for the previously
untested webview render path.

The deferred "GT Inspect It"/superInspectIt command is intentionally left for the
"one inspect to rule them all" work. Unit suite green (client 2337, server 320,
mcp 95).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…fallback

Collapse "Inspect It" and "GT Inspect It" into a single "Inspect It" that
routes through a shared inspectRouter.routeInspect: the Enhanced Inspector
webview when the session has the support installed, else the classic Inspector
tree view in the sidebar. Removes the separate gemstone.superInspectIt command,
its editor-context menu entry, and the ctrl+k o keybinding.

- codeExecutor: inspectIt / inspectExpression / executeAndInspect now route via
  routeInspect; superInspectIt / executeAndSuperInspect deleted.
- debuggerPanel: the variable context menu is now "Inspect" and uses the same
  routeInspect (enhanced beside the debugger, tracked to close with it; else the
  sidebar tree via the injected DebuggerPanel.inspectorProvider).
- extension: inspectGlobal only does its tree reveal/dedup when the classic
  inspector is in use (the webview path can't be found by findRootByLabel).
- enhancedInspector: open the panel with preserveFocus so a rapid repeat
  Inspect It doesn't lose the active editor.
- Remove the now-dead gemstone.enhancedInspectorAvailable context key (no
  when-clause consumers remain); routing reads the session flag directly.
- Tests: unit coverage for both routing branches (editor + debugger); new
  on-demand GCI smoke test asserting the lightweight availability probe agrees
  with the deep install check, plus the classic-inspector fallback queries.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the shrinking-panels behavior (each drill spawned a new VS Code
panel Beside, shrinking the others) with one webview holding N miller
columns in a horizontal-scroll strip — #39's last bullet.

Behavior (all settled interactively with Eric):
- Drilling is additive and never replaces: a drilled row opens its own
  column immediately to the right of its source, pushing later columns
  rightward, so the parent->child lineage reads left-to-right. Siblings
  drilled from the same column both stay open.
- Each column is independent: closing one removes only that column (not
  its neighbors); closing the last one disposes the whole panel.
- Focus tracks the focused column and drives the panel title.
- Columns have a minimum width and grow to fill spare space (a single
  column spans the tab, no dead space); a manual edge-drag pins a column
  to an exact width while the rest keep filling. Below the minimum the
  strip scrolls horizontally.
- Pronounced editorGroup-border dividers plus a gutter between columns;
  a long OOP no longer pushes the close button past the header edge.

Host protocol is now columnId-tagged end to end: drilling posts
addColumn (with sourceColumnId) instead of creating a new panel; every
fetch response echoes its columnId; setTitle/closePanel added.

The column-strip model is extracted to enhancedInspectorColumns.js
(injected as a <script>, not bundled — same pattern as
listFilter.js/methodListView.js/debuggerView.js) so the display/business
decisions are unit-testable in jsdom. Re-included in .vscodeignore since
it is read at module load.

Tests: enhancedInspectorColumns.test.ts (17, jsdom — insert-right order,
independent close, focus->title, width inherit/pin/min-clamp);
enhancedInspectorPanel.test.ts updated for the addColumn/columnId/
setTitle/closePanel protocol (31). Full unit suite 2591 pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jgfoster jgfoster merged commit fb8fd75 into main Jul 2, 2026
6 checks passed
@jgfoster jgfoster deleted the eric/enhancedInspectorAutomation branch July 2, 2026 21:06
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