Releases: Lazy-Beee/simulation-batch-runner
Release list
v1.4.0
What's new
Telegram
- The zip and upload stages now report live progress to Telegram, not just their start and finish. Each stage sends one notice per progress band (e.g.
Compressing 'case' 40%,Uploading 'case' 60%), plus a single 100%, throttled so the chat is never flooded. Previously the archive stage went silent between "started" and "done", which made a long transfer look stalled to a remote watcher. - The TUI Running log and the CLI console show the same throttled progress. 7-Zip is switched to
-bsp1on the streaming path so its percent output can be parsed and forwarded.
TUI
- The queue Status column now reflects the post-sim archive stage (ZIPPING / UPLOADING), so a case that has finished simulating but is still archiving no longer reads as done.
- Pressing START now confirms before re-running cases that already finished simulating, so a stray keypress can't silently redo completed work.
Fixes
- Deleting the
.batchexe copy is now retried when a force-quit leaves the image briefly locked (Windows WinError 32), instead of giving up and leaving the copy behind. - CLI: stdout is made lossy (
errors="replace") so 7-Zip / rclone output carrying odd bytes can no longer crashprint()on a non-UTF-8 console codepage (e.g. GBK on a zh-CN box).
Config
- No new keys. The new zip / upload progress notices reuse the existing
upload.eta_step_percentthrottle (default20-> a notice every 20%).
Copy config.example.json to config.json next to the exe and edit it before first run (config.json is never bundled into the exe).
v1.3.0
What's new
Telegram
- Notifications can now be tagged with a machine name. Set the new
telegram.machine_nameconfig key and every message from that host is prefixed with a#machine_namehashtag, so a shared chat receiving batches from several machines stays sortable and filterable. - Notifications are now sent on a background thread, off the log-reader loop, so a slow or unreachable Telegram API can no longer stall reading the simulator's output.
- A failed post no longer kills the sender thread; delivery keeps working for the rest of the run.
- Backtick and backslash are escaped inside code blocks and the monospace ordering is fixed, so case names with special characters render correctly.
- Failed cases now show
-for their cost in the batch report instead of a misleading number.
Fixes
- A case that is force-stopped exactly as the dispatcher sweeps the queue now has its process reliably killed instead of being left running.
- Cases are dispatched by identity and claimed on the UI thread, so reordering or removing a case mid-batch can no longer skip or double-run one.
- The per-case log buffer is bounded, capping memory on long-running batches.
- Subprocess output is decoded as UTF-8 (with replacement) rather than the OS default, and TUI log lines render as plain text, so odd bytes or markup in the simulator's output can't corrupt the display.
- Missing 7-Zip in
zip_case_outputis handled gracefully instead of crashing. - The CLI is hardened against a bad exe path or a failed spawn, and skips spawning on a pre-spawn stop.
cleanup_exenow refuses to delete anything but the.batchcopies it made, guarding against removing the wrong file.
Config
- New key
telegram.machine_name(default""— no prefix). Seeconfig.example.json. upload.eta_step_percentis now documented in the config reference.
Copy config.example.json to config.json next to the exe and edit it before first run (config.json is never bundled into the exe).
v1.2.2
What's new
TUI
- The queue ETA now counts down live between the simulator's (often sparse) ETA updates instead of sitting frozen, so the remaining-time estimate keeps ticking toward
0:00:00and re-anchors whenever a fresh estimate arrives. - Quitting (
Ctrl+Q) while a batch / zip / upload is still in flight now asks to confirm first. Confirming kills every running simulator, 7-Zip and rclone process so none are left orphaned holding the launching console; Cancel keeps the app running. - The running-row highlight now uses black text on the yellow background for readability.
Fixes
- A case added mid-batch while the last queued case was still running is no longer stranded. The coordinator now keeps the queue open until every in-flight case finishes, so a just-added case is dispatched and run instead of the batch stopping the moment that last case completes.
Copy config.example.json to config.json next to the exe and edit it before first run (config.json is never bundled into the exe).
v1.2.1
What's new
Simulator process priority (new)
- New
simulator.priorityconfig sets the Windows kernel scheduling priority class for the simulator process:idle/below_normal/normal(default) /above_normal/high/realtime. Usebelow_normal/idleto keep the machine responsive while a batch runs in the background, orhighto favor the sim over other work. Under MPI the class is set onmpiexecand inherited by the spawned ranks; unknown values fall back tonormal, and non-Windows platforms ignore it.
Cloud upload
- rclone transfer progress now displays past 100% instead of clamping.
- Added Google Drive robustness flags to the example config (
--drive-chunk-size,--timeout,--contimeout, low-level/normal retries,--drive-stop-on-upload-limit). - The rclone stats flags (
--stats-one-line -v --stats 15s) are now fixed in code so periodic progress lines always show; ETA log lines are throttled to one perupload.eta_step_percent(default: every 20%).
TUI
- Refreshing the scene queue table keeps its scroll position instead of jumping back to the top.
Config
- New key:
simulator.priority. See the updatedconfig.example.json.
Copy config.example.json to config.json next to the exe and edit it before first run (config.json is never bundled into the exe).
v1.2.0
What's new
Cloud upload (new)
- Optional post-zip upload of each case archive to a cloud remote via rclone (
rclone copy), configured in a newuploadsection (enabled/rclone_path/remote/args). Set up the remote once withrclone config(one-time OAuth for Google Drive). - Runs on its own background worker (
upload.async, defaulttrue) so a transfer overlaps zipping the next case while staying serial. Per-case Upload switch in the TUI;--no-uploadin the CLI.
Parallel case execution (new)
- Run several cases at once via the Parallel control (config
defaults.parallel_cases, default1= the original sequential behavior). Each case gets its ownOMP_NUM_THREADS(no global race); the log interleaves output with[case name]prefixes. The value is read at START / RESUME and locked during a run; adjust with the ▲▼ stepper or the Up/Down arrow keys.
Three-state output cleanup (replaces the Remove switch)
- A Cleanup control cycling Keep / Folder / Both: keep everything, delete the raw output folder (default), or delete the folder and the local archive — the archive only after a successful upload, so the sole remaining copy is never dropped. CLI:
--keep-output/--purge.
TUI
- Numeric fields (OMP / MPI / Parallel) step by ±1 with the Up/Down arrow keys; Parallel also has a ▲▼ click stepper. The OMP field is one cell wider so a 2-digit value stays visible when focused.
- Queue table gains
CleanandUplcolumns.Zip/Uplshow-(off),Y(enabled, pending), andDonce that step completes for the case.
Bug fixes
- Fixed a crash when adding cases mid-batch (
call_from_threadinvoked from the app thread).
Config
simulator.zip_asyncis now a documented on/off switch (defaulttrue). New keys:upload.*,defaults.parallel_cases,defaults.zip,defaults.cleanup— see the updatedconfig.example.json.
v1.1.3
What's new
TUI
- Queue table supports multi-select.
Spacetoggles a*marker in the#column for the cursor row,Ctrl+Aselects everything,Escclears. With any selection: Remove selected drops every removable entry in one pass, Up / Down moves the whole group as a unit (rows that hit a boundary or a non-pending neighbour stay put while the rest still shift), and View log opens one tab per finished entry. - Zip + remove now run on a background daemon thread, so the next case starts as soon as the previous simulator exits while the previous output is still being archived. Tasks are serialised behind a single worker so multiple 7z runs don't thrash disk. The batch waits for any remaining tasks before declaring idle.
- Time and ETA columns share the same left-flush
H:MM:SSformat (up to 999h), so they line up cleanly. Elapsed time no longer rolls intoX days, ....
7-Zip
simulator.zip_ext(default.zip) picks the archive format from the filename extension. Switch to.7zfor LZMA2.simulator.zip_args(default[]) passes extra switches betweenaand the archive name. Defaults in the shipped template set-mx=5 -mmt=on(7z's own defaults, made explicit) so the knobs are discoverable.
Bug fixes
- Unquoted Windows paths typed / pasted into the Scene input no longer have their backslashes silently eaten (
shlex.splitis now called withposix=False).
Internal
- One-pass comment cleanup across the codebase, keeping the WHY notes (subprocess deadlock, OLE drag-drop modality, Textual binding collisions, etc.) and dropping the WHAT / historical references.
v1.1.2
What's new
Bug fixes
- 7z output no longer leaks ANSI / CR sequences into the Textual render. The zip pipeline now streams via PIPE and routes lines through the TUI log instead of inheriting the parent's stdio.
- Mid-batch Add no longer strands the
(index+1/total)denominator.run_casenow accepts a callable fortotalso per-step Telegram messages and the TUI's status / running-case labels re-evaluate the live queue length on every formatting; the periodic refresh re-renders both labels at 1 Hz. AQueue extended mid-batch: +N, now M totalinfo line is also logged through Telegram + the TUI log when the queue grows during a run, explaining the jump.
TUI
- Queue table sizes columns to the terminal: Simulator / Scene cells show extension-stripped filenames (head + ellipsis + tail truncation when needed), and absorb any width beyond the baseline at a 1:2 ratio, with overflow rolling to whichever side is still truncated.
- Warnings / Errors columns tick live as each case runs, alongside Time and ETA.
- Simulator field's Type label now flags a red
(file not found)when the entered path doesn't resolve to a file - catches bad paths before Add. - The whole table re-stats once a second so a simulator / scene file deleted between Add and run gets the
[!]marker within a second.
ETA extraction
- Profile regex now also accepts CAMMP's space-separated form
1h 01min addition to7h57mand<1m.
Testing
fake_simulatorgainsoutput_files/output_file_sizefields and a newscene_output.jsonfor exercising the zip + remove pipeline end-to-end.
v1.1.1
New
- ETA column in the queue table, populated from a per-profile
eta_patternregex (capture group 1 = the ETA token). Renders asH:MM:SSto line up with the Time column.<1mbecomes0:00:00; unparseable tokens fall back to the raw text. - Time column ticks live at 1 Hz while a case is running — no need to switch to the Running tab to see the per-case clock.
- Mid-batch Add is supported now. The worker reads
self.scene_entrieslive, so cases queued during a batch fall under the cursor and run as part of the same batch instead of waiting for the next START / RESUME. The old "paste blocked while running" gate is gone.
Changes (potentially breaking config)
- Simulator profile field
step_markeris renamed tostep_patternand is now interpreted as a Python regex (re.search). Capture group 1, if present, is the display text. Migrate by renaming the key and escaping regex metacharacters — e.g. SPlisHSPlasH's literal[step]becomes"step_pattern": "\\[step\\]". CAMMP's"Processed layer "works unchanged. requirements.txt:textualminimum bumped from>=0.50to>=1.0because we lean on newer API (App.copy_to_clipboard,Strip.text,events.DescendantFocus,Static.text_selection).
Polish
- README: prebuilt-binary callout in Setup, dedicated Building binaries section explaining
build.batand PyInstaller quirks. test/fake_simulatoremits ETA tokens on every step line so the ETA column can be exercised;scene_long.jsonticks down from14h30mviaeta_per_step: 30.- Per-Add exe snapshot semantics (introduced in v1.1.0) documented more clearly in How it works.
Assets
batch_simu_tui.exe (~35 MB) and batch_simu_cli.exe (~12 MB) are Windows x64 onefile binaries — drop next to a config.json (copy of config.example.json) and run, no Python install needed. Screenshots are the same UI as v1.1.0 except for the extra ETA column.
v1.1.0
New
- Windows x64 onefile binaries ship as release assets — no Python install needed. Copy
config.example.jsonnext to the exe asconfig.jsonand run.batch_simu_tui.exe(~35 MB, Textual TUI)batch_simu_cli.exe(~12 MB, interactive CLI)
- Per-Add exe snapshot: each
Addtakes its own copy of the simulator exe, so recompiling mid-batch only affects cases queued after the rebuild. Cases added in the sameAddshare one copy; reference-counted cleanup runs on Remove / Reset / app exit. - Copy log button on the Running and case-log tab toolbars (Textual's click-drag selection does not work on
RichLog— this provides a reliable cross-terminal OSC-52 copy path). - Close button on case-log tabs.
- Drag-target indicator + Clear buttons next to the Simulator and Scene inputs. The next paste / drop lands in whichever input you last clicked or Tab-focused.
- OMP / MPI numeric inputs gray out when their switch is off.
- TUI "Setup" tab renamed to Queue; redesigned with bold field labels, muted hints, accent-coloured queue-table border, consistent vertical breaks, and a progress bar with its own bottom margin.
- Case-log tab now mirrors the Running tab's three-row header (case / simulator / stats + Copy) and the same accent border on the log panel.
Changes (potentially breaking for callers)
- CLI script renamed:
batch_simu.py→batch_simu_cli.py. Update any wrappers that invoke the CLI by name. - Queue-table column "Exe" → "Simulator" (UI label only).
- Tab "Setup" → "Queue"; the F1 footer label follows.
Fixes
- Simulator hang from unread
stderrPIPE.stderris now merged intostdoutso the existing reader drains both streams;stdinisDEVNULLto avoid simulators stalling on accidental input reads. - Footer key order shifting when an
Inputwas focused —Ctrl+X(Stop) andCtrl+W(Close case tab) are nowshow=Falseso they no longer shuffle their visible position depending on focus.
Removed
- Replay-mode fake simulator. Synthetic mode covers the manual testing path.
Internal
simulation.py:_app_root()resolvesconfig.jsoncorrectly in both frozen-exe and source-tree modes (PyInstaller setssys.frozen).build.bat: one-step PyInstaller chain (--onefile,--collect-submodules textualso Textual's lazy widget loading survives freezing).
v1.0.1
Fixes
- Simulator hang from unread stderr PIPE.
stderrwas opened but never drained; once the OS pipe buffer filled, the simulator's next write blocked — stdout stopped advancing and the UI appeared to freeze, even when stdout was producing fewer than one line per second.stderris now merged intostdoutso the existing reader handles both, andstdinis pointed atDEVNULL. - Footer key order shifting when an Input was focused.
Ctrl+X(Stop) andCtrl+W(Close case tab) collide with Input's built-in cut / delete-word bindings; Textual interleaves them atInput.BINDINGSslot positions, scrambling the visible key order. Both are nowshow=False.Ctrl+Xstays priority so Stop still fires from inside an Input;Ctrl+Wstays non-priority so Input keeps delete-word.
TUI improvements
- Explicit drag-and-drop target. The next paste / drop lands in the input you last clicked or Tab-focused, shown as
Drag target: Simulator / Sceneunder the Scene input. Replaces focus-based routing, which broke when an OLE drag cleared Textual focus. - Clear button next to each of Simulator / Scene inputs. Clear empties the field and re-focuses it (which also sets it as the next drag target).
- Copy log button in the Running tab toolbar and in each case-log tab. Textual's click-drag selection works for
Static/Labelbut not forRichLog(mouse-down is consumed by the scrollable container), so the button pipes the activeRichLogthroughapp.copy_to_clipboard(OSC 52) for a reliable cross-terminal copy. Terminal-native Shift+drag still works for finer-grained selection. - Tighter Running and case-tab headers. Single-line header rows now line up with the Copy button alongside them. Case-tab header shows
Case | Exeon row 1 andStatus | Time | Warnings | Errors+ Copy on row 2.