Skip to content

Release v0.1.32: HPC/Slurm pipeline, global machines, monitoring, i18n#6

Merged
fseiffarth merged 22 commits into
mainfrom
develop
Jul 21, 2026
Merged

Release v0.1.32: HPC/Slurm pipeline, global machines, monitoring, i18n#6
fseiffarth merged 22 commits into
mainfrom
develop

Conversation

@fseiffarth

@fseiffarth fseiffarth commented Jul 20, 2026

Copy link
Copy Markdown
Owner

Merges develop into main for the v0.1.32 release.

Highlights

HPC / Slurm — pipeline wizard, interactive srun on a compute node (never the login node), sbatch directive parsing.

Global machines — machines are managed at the machine level (the VPN-tunnel pattern applied to SSH): a monitoring dialog, import/export of a machine list, reordering, and per-machine auto-connect. Export carries host/port/label only, never a username or password.

Remote — auto-reconnect for remote hosts, a hostBusy store so a working host reads as busy rather than idle, and remote usage sampling surfaced through the usage-warning dialog.

Viewers & files — YAML grid and PDF outline viewers; the file tree now shows directory sizes behind a per-view setting.

i18n — a translation layer with a language setting in Settings.

Themingfancy_dark becomes the default colour scheme.

Fixes

  • globalMachines.load() used .catch(() => []), which guards a rejection but not a command that resolves to nothing — leaving machines non-iterable and crashing RemoteUsageWarningDialog. Guarded with Array.isArray.
  • Updated the stale settings default-colour-scheme test to fancy_dark.

Privacy

  • eldrun-machines.json is now gitignored: the Machines menu export defaults to that filename and had dropped a file of real hostnames into the repo root. Never committed.
  • Removed a named HPC cluster from three comments, keeping the wording cluster-agnostic. Verified absent from git history.

Verification

tsc --noEmit clean · cargo test 1025 passed · vitest 1781 passed · npm run build clean.
CI green on test, test-windows, test-macos.

Note: features are code-complete but largely unverified in live UI use.

🤖 Generated with Claude Code

fseiffarth and others added 20 commits July 13, 2026 23:32
…nel-up gate

Import a project straight from a GitHub/GitLab URL (`git_clone` lands the
tree, then the ordinary import registers it in place), and reverse the
extend flow with `detach_project_from_remote`.

Remote hosts remember a default path (`remote_{list,get,set}_default_path`),
and the "Save password" opt-in is now the same control in every remote menu
— the Connect modal and the new-project / extend-to-remote dialogs share
`useRemoteSession`. The keychain is keyed by host target, not project id, so
the credential a create/extend dialog authenticated with is handed to that
project's first pooled connect (`stashRemotePassword`, single-use, never on
disk); connecting password-less would otherwise record `key_auth: true` on a
password host.

While a tunnel is up machine-wide, every project-scoped OpenVPN block
collapses to a one-line notice pointing at the header, via the shared
`useVpnSectionVisible` gate + `VpnTunnelUpNotice` — except a tunnel the
dialog itself brought up, which stays expanded so its log and Disconnect
remain where the user started it.

File tree gains per-directory size breakdown (`dir_size_breakdown`) and
drag-out to other apps (`start_file_drag` / `cancel_file_drag`).

Gates: tsc clean, 1358 frontend tests, 915 Rust tests, privacy scan clear.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ag1A6YVQxujZkcnrWahjua
The backend half of the invariant (an unvouched empty layout must not erase a
saved one) is already pinned by services_tests.rs. The frontend half was not —
and that is where the decision is actually made, so `persistScope`'s hydration
logic could regress with CI still green.

Covers the three cases that matter: a hydrated scope that genuinely holds no
tabs DOES vouch for the clear (a real close-all must persist), a scope that was
never hydrated does not, and — the SimpleGNN case — a scope whose tabs all get
filtered out as foreign does not, even though the layout it sends is just as
empty as a close-all.

Also documents why `saveLayout` is the footgun (it pairs the store's live scope
with a caller-supplied localFile; no production caller remains), and catches
Cargo.lock up to the v0.1.22 bump.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MHkrvVRCBNMFGvNiKkmAWC
Two viewer features, plus the experimental-flag gate they are staged behind.

YAML/JSON structure tree (#88). The tree is a VIEW ON THE TEXT: every edit is a
surgical splice back into the draft, never a re-serialization of the parsed model
— the only way a config file's comments survive an edit, and what lets Tree and
Source be two views on one draft. Both YAML syntaxes are first-class: block, and
flow (`{a: 1}` — i.e. JSON, so a .json file opens as a tree too), and which one a
node is written in decides how it is edited, so `[a, b]` grows to `[a, b, c]` and
is never quietly rewritten into block.

Round out the tree:

- Inline nested sequences (`- - x`) parse instead of failing the whole document.
  One such line previously sent the entire file to the Source fallback.
- Fix a corruption bug: an empty placeholder inside a flow collection — and so
  every `null` in a .json file — grew as a BLOCK child, splicing a line at column
  -1 (a flow node has no column) into the middle of the brackets and tearing the
  collection open. It now becomes a collection in place: `{a: null}` -> `{a: [x]}`.
- "+ key" on a list adds an item that IS a mapping (`- name: api`) — the shape a
  list of mappings is actually grown by.
- Comments are a node's own, not scenery. A `#` is the only place YAML documents a
  key, so each node reads the one behind its value and the run directly above it,
  shows it on the key's hover, and can rewrite it where the author already wrote.
  The consequence is in the edits: a comment TRAVELS with its node — deleting or
  reordering a key takes its description along, rather than leaving it to
  re-attach itself to whichever key slid into that place.
- Reorder siblings by dragging the row's grip. Pointer-based, with every handler
  bound up front (HTML5 DnD does not work under WebKitGTK, and mid-gesture
  listeners get dropped). `moveNodeTo` is the one reorder op: a drag across five
  rows is ONE splice, not five swaps — every splice invalidates the offsets after
  it.

Python in the code viewer (#87). Run/Debug open a TERMINAL TAB rather than a
bespoke exec path, which is what makes them inherit remote-host and container
locality for free and stay a real interactive terminal. Debug is pdb pre-loaded
with the gutter's breakpoints. Breakpoints snap to executable lines (pdb refuses
blank ones) and remap on every edit above them; go-to-definition is a lexical
import-graph walk, and only names it can actually follow are underlined.

Verified: cargo test green, 1517 frontend tests green, tsc clean. Not yet
exercised in the running app — the drag's geometry in particular has only run in
jsdom, where every row reports a zero-height rect.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ag1A6YVQxujZkcnrWahjua
Add a search box to FileTree — shared by the right-panel Files view and
the Files (Project) tab. Two modes: literal case-insensitive filename
substring search (list_project_paths) and in-file content search
(project_search). Every result can reveal+select the path in the tree
(jump-to-path) or open it (content hits open at the matched line).
Search is confined to the browsed folder by default, with a root toggle
for the whole project; local-source trees only.

Snapshot also includes other in-progress work on develop (GPU stat
device readout, system monitor, YAML/table viewers, tab plumbing).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016RhzuHHNTbXVcMM4yZHS2g
…eter window

Work in progress committed to unblock merging origin/main into develop.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vy2kXY3h8ApJVFYCS8yJBM
# Conflicts:
#	Cargo.lock
#	package.json
#	src-tauri/Cargo.toml
#	src-tauri/tauri.conf.json
#	src/components/files/FileTree.tsx
…apshot

Save the docked subwindow file viewer's browsed folder per subwindow on the
layout tree's GroupNode (filesFolder), alongside filesOpen/filesWidth — so it
persists with the layout, survives a restart, travels with a detach/popout via
the streamed `files` edit, and is freed when the subwindow (group) is dropped.
ProjectFilesTab gains a persistFolder override + a resync effect so a restore or
popout stream wins over local state.

Snapshot also carries in-progress work from the ongoing file-viewer refactor
(GifView, table/yaml viewers, file browser/sidebar) and related tests.
…shot

Broad snapshot across remote, terminal, monitoring, and file-viewer work:
- Multi-host remote projects (worker_sync, remote_usage, RemoteMachinesWindow)
- tmux-backed persistent shell sessions (local + remote), Sessions view
- System monitoring: gpustat/sysstat/net_usage expansion, SystemMonitorPane
- Custom agents (CustomAgentDialog/CustomAgents), shell-script run flow
- File viewer refactor (CompareView, FileViewerPane, SyncMergeView, FileTree)
- Remote-usage warnings, local-loss surfacing, terminal control/bus plumbing

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TecnBhmTjeuHqbBxJfLdxk
CI: the Windows backend build failed with E0432 (unresolved import
`windows::Win32::System::Pipes`) — services/openvpn.rs uses PeekNamedPipe /
SetNamedPipeHandleState for the OpenVPN Interactive Service named-pipe IPC but
the `Win32_System_Pipes` feature was never enabled on the target-gated `windows`
dep. Add it.

GitChangeTree flyout on-screen clamp: measure the box with its own transform
cleared instead of `rect − shiftX`, so the correction is a fixed reference and
converges in one pass. `rect − shiftX` converges in a real browser but diverges
by `margin` every render in an env that doesn't reflect the transform into
layout (jsdom under test) — an infinite render loop that reddened 4 tests.

Also carries in-progress work already in the tree: tab-close is now a
non-destructive tmux detach (kill only via the Sessions view ×), tmux session
names minted in split/detach paths, table-viewer column resize, and the
tmux-reattach identity-reply suppression in TerminalView.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TecnBhmTjeuHqbBxJfLdxk
`local_discovery_finds_every_venv_in_the_tree_not_only_the_root` built its
expected nested path from a `"services/api/.venv"` literal, which keeps forward
slashes on Windows — but discovery emits the relative path with the OS
separator (backslash), so the string compare failed there. Build the expected
path from PathBuf components so it matches on every platform. Test-only.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TecnBhmTjeuHqbBxJfLdxk
…ewers

- Slurm job submission/monitoring + HPC pipeline wizard (commands/slurm.rs,
  lib/slurm.ts, stores/hpcJobs.ts, hpcPipeline.ts, HpcPipelineWizard.tsx)
- Global machines registry + header MachinesIndicator (global_machines.rs,
  schema/global_machine.rs, stores/globalMachines.ts)
- Remote folder browser + reusable browse hook (RemoteFolderBrowser.tsx,
  useRemoteBrowse.ts, lib/remoteHosts.ts, stores/runHostPref.ts)
- Tab locality badges + per-host run preference (TabLocalityBadges.tsx)
- New viewers: YAML grid (YamlGrid.tsx, viewers/yamlGrid.ts), PDF outline
  (pdf/outline.ts), presentation overlay (PresentationOverlay.tsx)
- System monitor + remote-usage warning refinements
- Tests for Slurm, YamlGrid, PdfOutline, YamlViewer

The HPC wizard and slurm glue are cluster-agnostic: no institution-specific
hostnames, presets, or identifiers.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0184T6Pj4JrxFgjtaij9uE9n
fseiffarth and others added 2 commits July 21, 2026 14:38
Frontend
- Add an i18n layer (src/lib/i18n.ts) with a language setting in Settings.
- Global machine monitoring: GlobalMachineMonitorDialog plus a dedicated
  store, surfaced from the Machines menu.
- Machine list import/export and reordering (src/lib/machineSync.ts); the
  export writes host/port/label only, never a username or password.
- Remote auto-reconnect (src/lib/remoteAutoReconnect.ts) and a hostBusy
  store so a working host reads as busy rather than idle.
- File tree shows directory sizes, with a per-view setting.
- Theme work: fancy_dark becomes the default colour scheme.

Backend
- Global machine commands, remote usage sampling and sysstat session
  parsing; OpenVPN and SSH command updates.

Fixes
- globalMachines.load(): .catch guards a rejection but not a command that
  resolves to nothing, which left `machines` non-iterable and crashed
  RemoteUsageWarningDialog. Guard with Array.isArray.
- Update the settings default-colour-scheme test to fancy_dark.

Privacy
- gitignore eldrun-machines.json: the Machines menu export defaults to that
  name and had dropped a file of real hostnames into the repo root.
- Drop a named HPC cluster from three comments; keep the wording
  cluster-agnostic.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@fseiffarth fseiffarth changed the title Release v0.1.28: multi-host remote, tmux sessions, monitoring + Windows CI fix Release v0.1.32: HPC/Slurm pipeline, global machines, monitoring, i18n Jul 21, 2026
@fseiffarth
fseiffarth merged commit e45c58d into main Jul 21, 2026
14 checks passed
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.

1 participant