Skip to content

parrot on Dear ImGui: a shared module's function addresses in the standalone exe, parked browser workers, cached model sets - #3995

Merged
borisbat merged 14 commits into
masterfrom
bbatkin/parrot-lab
Sep 11, 2026
Merged

parrot on Dear ImGui: a shared module's function addresses in the standalone exe, parked browser workers, cached model sets#3995
borisbat merged 14 commits into
masterfrom
bbatkin/parrot-lab

Conversation

@borisbat

@borisbat borisbat commented Sep 10, 2026

Copy link
Copy Markdown
Collaborator

Behavior change: a dasLLAMA program running in a browser now starts with the job queue's worker spin window at 0 - a page that wants the 30 ms window sets it with set_jobque_spin_us.

Why. The parrot page was a text overlay on a GL canvas with no way to see what the take, the synthesis or the job queue were doing, and its browser build could not use Dear ImGui at all: a @@fn taken in a shared module's global initializer came out null in a standalone exe, so the first icon button threw on the first frame. On the same page the eight spinning web workers held the caller's core: the poem generated at 1.1x real time with the renderer at 800% CPU, against 1.4x parked at 112%.

What changes.

  • Parrot is a lab on Dear ImGui through imgui_harness: dock windows for the status strip, the voice (record disc with the silence countdown, level, gain, the take's waveform, the roster picker), the text (editor, play and stop, the say's chunks in their state's colour), the output (the growing waveform with the mixer-clock playhead, the per-chunk stage times) and the lab (model facts, the job queue's jobs slider and team and spin toggles, a measure button reporting times real time).
  • The standalone-exe emitter's startup walk over global initializers skips only C++ builtin modules, so a promoted (shared) das module's @@fn is stored before the init script runs.
  • The engine's [init] sets the worker spin window to 0 when the running platform is emscripten; the facade exposes get_jobque_spin_us and set_jobque_spin_us over the engine's underscore spellings.
  • The wasm job pool cap rises from 4 to 8 workers, and the GLFW browser glue sizes the window to the canvas's parent box.
  • The three browser shells keep fetched model files in Cache Storage under their URL and sha256 once the bytes hash to that sha256, sweep the page's files a new manifest no longer names, and a revisit fetches nothing.
  • The control page plan leaves the server folder; the checklist no longer cites it.

Observable behavior.

  • parrot page throws WebAssembly.Exception on its first frame with an icon button -> the page runs; llvm_exe_shared_addr.das holds the shape.
  • parrot page: the poem at 1.1x real time, 800% CPU -> 1.4x real time, 112% CPU, with the lab's defaults.
  • a browser example re-downloads its model set on every visit -> fetches once per browser, then reads the cache.
  • the lab's jobs slider on a hybrid desktop moved nothing (the per-phase parking overrode a raw worker limit) -> it goes through set_dispatch_worker_limit, which stands the parking down.
  • the editor ignored the space bar and Tab in the browser -> both type.

Where to look. collect_external_functions in modules/dasLLVM/daslib/llvm_exe.das (one condition), dasllama_jobque_spin_default in modules/dasLLAMA/dasllama/dasllama_math.das, and examples/dasLLAMA/parrot/main.das for the lab; the measured figures are the PERF_LEDGER.md entry.

Validation, claims, ledger

Validation

  • The dasLLVM module-owned suite passed on this box after the emitter change (284 s); llvm_exe_shared_addr.das was red before the change (EXCEPTION: invoke null function) and green after.
  • The changed-file dasLLAMA run (run.das -- --changed, every area) passed 120 of 122 files; the two reds, test_vulkan_dec_tail.das and test_vulkan_tier.das, are this Mac's Vulkan device declining a 33 KB row tile over its 32 KB shared-memory cap, and fail the same way in runs from before this branch.
  • The browser figures were taken in Chrome on the wasm64 release with nothing else on the box, three runs each within 3%, the arms flipped through the lab's own toggles and read off the engine's per-synthesis timing line; the spin-on and spin-off readings that decided the default came from separate page sessions, so the entry is tagged direction-grade (a 30% gap against runs within 3%). No board leg mints a browser row, so the measurement checklist's board-row duty cannot be met for this route; the ledger entry carries the provenance line instead. The automation browser has no microphone, so the record path was exercised by hand only.
  • The comment harvest and the style-hygiene audit were not run on this diff.
  • The imgui module now requires clipboard_core in its initDependencies, through the binder's new require_load_modules list, the module its DLL imports; modules/REVIEW.md (new) carries the duty. It does not change the Windows lane's primary sweep: the arm "a module whose C++ dependencies are deferred too" of tests/module_cache/test_deferred_modules.das fails there on master and on this branch alike (the OS resolves the DLL's import at load time, before any module code runs, and the deferred fallback loads imgui before clipboard), and the isolated retry passes, so the job reads green on both. A retry-until-no-progress pass in that fallback is a candidate for its own PR.
  • The external codex round returned one finding, verified real: the shells cached fetched bytes under the manifest's sha256 without hashing them, so a wrong body under an HTTP 200 would have been served on every later visit. Fixed in the three shells (the bytes are hashed before the put; a mismatch refuses the set and caches nothing).

Claims - stated, not tested

  • llvm_exe_shared_addr.das's Windows arm (the set PATH=...&& spelling of the run command, the .exe suffix) has not executed; the Windows nightly's dasLLVM lane is its first run, as for the two sibling exe tests. A break would read as that one file red on Windows only.

  • The spin default fires only when get_running_platform_name() answers emscripten; no desktop test reaches that arm. It was verified on the page: the lab's spin toggle reads the engine's value and starts unticked, and the measure reads 1.4x. A break would show the toggle ticked and the poem back at 1.1x.

  • The GLFW glue's parent-box sizing and the shells' Cache Storage are browser-only JavaScript; verified by the page's canvas rect and by a reload fetching only manifest.json and the wasm (304s). A break would show a vertically squeezed picture, or the model files fetched on every visit.

  • The parrot smoke proves the program runs to read-out and, through the read-out line's figures, that the say played to its end (a clip read as stopped on its first frame fails it - checked by mutation); the lab's measure path, the take's microphone wiring and the drawing layer run inside it without an assertion of their own. A break in one of them reads as a panic in the smoke or a wrong panel on the page.

  • The two per-PR dasLLAMA suites were not run as such; the changed-file run over every area (122 files) stands in for them, per the owner's ruling.

Not done

  • The browser's voice-clone time against the desktop's (150 ms for a 4 s clip) is not in the ledger: the automation browser cannot record.
  • Word-level highlighting of the spoken text is not attempted; the say is highlighted chunk by chunk, since Pocket TTS carries no alignment.

borisbat and others added 10 commits September 10, 2026 15:29
…n the author's own notes, and the folder's checklist names the module ledger as its planned-work home

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…Pocket clone, now with panels that show what the engine does while it does it. The status chip and line across the top say ready, recording with the seconds, cloning, generating, speaking or read out; the voice panel is the record disc with the silence countdown drawn around it, the level, a gain slider that scales the frames before the detector and the clone (the physical input gain is the browser's), the take's waveform with its kept window shaded, and a picker of the clone plus the file's nineteen voices; the text panel is an editor, say, and the say's chunks in the colour of their state - pending, generating, generated, speaking, spoken - so the phrase being read is the one lit; the output is the say's waveform growing chunk by chunk with a tick at each chunk's start and a playhead on the mixer's own clock, and a table of each chunk's prompt, backbone, head and codec time; the lab panel is the model's facts, the job queue's knobs (a jobs slider up to the engine's cap, team dispatch, the workers' spin) reaching the queue the speech thread dispatches on, and a measure button that says the text three times without playing it and reports each run's real-time factor. The speech thread announces each chunk's text before it synthesizes it and returns the clip with its stage times; each clip gets its own status box, since a box shared across clips reads the last clip's stop as the next one's and cut the say short (a rule in the folder's checklist now). take.das keeps the resampler, the take rules and the clip window and gains the countdown, the ten-millisecond waveform columns grown per drain, and the chunk ledger; the text-box helpers go with the text layer. dasGlfw's browser glue measures the canvas's parent box instead of the document viewport (the document when the parent is the body or in fullscreen), so a page whose stage sits under a nav gets a window the size of the stage instead of a viewport-sized picture squeezed into it. test_parrot holds the countdown, the columns (fed in drains of every size, the open column redone) and the ledger model-free, and the smoke rail reads the same witness lines; the desktop run and the browser page (the wasm64 release, dasImgui's archives built on demand) both read the poem in a cloned voice.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…instead of cores minus one: a browser build caps the pool at four, and the slider narrows dispatch below the pool, never above it

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ight and a size up; the state chip pulses with a spinner beside it while anything is going on; the output waveform keeps a fixed time scale so the playhead moves at one speed instead of jumping back as chunks land; say names the voice it will use; every figure prints to a tenth (speeds as times real time - seconds of audio per second of generation - the inverse of the engine's real-time factor); and the wasm job pool cap rises from four workers to eight (platform.h, emscripten only), inside the sixteen-worker pthread pool the wasm64 builds link

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…rrot across the top, voice, text over output, lab) the user splits and tabs; say and stop are the play and stop icon buttons beside the voice's name; the status row reserves its own height so the separator no longer cuts the chip and the spinner; a measure names its number so a second press reads as a second run; the shell keeps the space bar's keydown for the editor (a prevented keydown swallowed the keypress); and the three browser shells put a fetched model file in the origin's Cache Storage under its sha256 and read it from there on the next visit, so a set downloads once per browser

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…hes the standalone exe: the exe emitter's startup walk over global initializers (collect_external_functions) left out every module flagged builtIn, and a promoted das module - `module X shared`, imgui_icons and most of daslib - is flagged builtIn too, so a `@@fn` in such a module's global never had its address global stored, LLVM dropped the private function, and the first invoke threw "invoke null function" (the parrot page's WebAssembly.Exception on its first frame, at the first icon button). The walk now skips only the C++ modules (builtIn and not promoted); llvm_exe_shared_addr.das holds the shape against the interpreted run (red before the change), ARCHITECTURE.md sec.12 states the walk, and the checklist bans a module walk keyed on builtIn alone.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…moved focus out of the text one types into was the second key that did nothing in the editor, after the space bar the shell now leaves to it; the panels doc says so.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…30 ms spin-before-park window was unconditional, and in Chrome the eight spinning web workers cost the caller its core - Pocket TTS on the parrot page generated at 1.1x real time with the renderer at 800% CPU, 1.4x with the workers parked at 112% (one worker reads 0.7x, so the pool pays once nothing spins; team dispatch keeps its edge). dasllama_jobque_spin_default sets the window to 0 when the RUNNING platform is emscripten - get_platform_name folds at cross-compile time to the host's name, which is why a first form of the init never fired in the browser - and a box profile's jobque_spin_us and the setter still override it. The facade exposes get/set_jobque_spin_us over the engine's underscore spellings (the four engine-side callers renamed), ARCHITECTURE_RUNTIME.md 2.18a states the mechanism and PERF_LEDGER.md carries the numbers. The parrot lab reads the spin default from the engine, and its jobs slider goes through set_dispatch_worker_limit as the engine's contract says - a raw worker limit was overridden by the hybrid pool's per-phase parking on the desktop, which is why the measure's number did not follow the slider there; the panels doc says so. The page now measures 1.4x with its defaults.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…model file against the manifest's sha256 before they cache it - a wrong body under an HTTP 200 (a proxy's error page) is refused by name and never cached, where the store would have served it on every later visit - and sweep the page's keys a new manifest no longer names, so a re-mint does not wait on the browser's quota eviction (the three pages share one store, so each sweeps only its own models path); the parrot smoke gains an instrument for the per-clip status box rule - the read-out line reports the say's speech seconds and its playback wall, and the test holds the wall to the speech, so a clip read as stopped before its end (the shape the rule bans) fails it, where the witness lines alone stayed green; the facade's spin knob gets its cells (the desktop default read before any set, the setter landing on the engine); the standalone exe's architecture moves to its own companion, ARCHITECTURE_EXE.md (the require-resolver rows beside the startup address walk, stubs left in the main doc, which sat at the line cap) and the checklist rule that binds the walk is scoped to this module's daslib; the facade knobs are taught in the performance tutorial and its page, as the facade gate demands; a stale default in the tutorial, tune_for_this_box.md and two build comments reads the browser's 0 beside the desktop's 30 ms; the ledger entry carries its provenance; and the examples' checklist reads an input rule the imgui harness can meet.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…cap: get_jobque_spin_us and set_jobque_spin_us join the operations group, so the generated page carries no uncategorized entry.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings September 10, 2026 23:45

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The parrot smoke tests dropped --null-audio (risking headless/CI failures) and the performance tutorial leaks a global spin-window value instead of restoring the prior/default value.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR upgrades the dasLLAMA browser “parrot” experience into an ImGui-based lab UI, fixes standalone-exe address resolution for @@fn taken in shared-module global initializers, and improves browser runtime behavior (parked workers by default, higher wasm worker cap, and cached model downloads).

Changes:

  • Fix -exe startup global-initializer walking to include promoted (shared) das modules so @@fn globals are populated before init runs; add a dedicated regression test and architecture doc.
  • Change dasLLAMA browser defaults/perf: job-queue spin window defaults to 0 on emscripten, wasm worker cap increases to 8, and document the runtime/platform gating nuance.
  • Rework the parrot example into a multi-panel ImGui lab; update browser shells to cache model-set files in Cache Storage keyed by URL+sha256 and sweep stale entries.
File summaries
File Description
utils/dasllama-server/REVIEW.md Updates checklist to point planned work at the new follow-up doc location.
utils/dasllama-server/CONTROL_PAGE_PLAN.md Removes the in-folder control page plan document.
tutorials/dasLLAMA/05_performance.das Documents and demonstrates the job-queue spin window knob.
src/misc/job_que.cpp Comment update reflecting the wasm job cap change.
skills/daspkg.md Documents runtime vs compile-time platform name APIs for wasm gating.
modules/dasLLVM/tests/llvm_exe_shared_addr.das Adds regression test for shared-module @@fn addresses in standalone exes.
modules/dasLLVM/tests/llvm_exe_shared_addr_lib.das Shared-module fixture exercising global initializer function-address capture.
modules/dasLLVM/tests/_exe_shared_addr_root.das Minimal exported program used by the regression test.
modules/dasLLVM/REVIEW.md Adds checklist guidance about promoted modules being builtIn and requiring special-casing.
modules/dasLLVM/daslib/llvm_exe.das Includes promoted modules in the global-initializer walk; updates doc references.
modules/dasLLVM/ARCHITECTURE.md Routes standalone-exe details into a new dedicated architecture document.
modules/dasLLVM/ARCHITECTURE_EXE.md New doc describing exe link decisions and startup initializer/address behavior.
modules/dasLLAMA/tune_for_this_box.md Updates tuning doc to note browser default spin window is 0.
modules/dasLLAMA/tests/test_parrot.das Updates parrot tests for new pure functions and smoke witness; adjusts smoke argv.
modules/dasLLAMA/tests/test_facade.das Adds a facade-level test for the jobque spin getter/setter.
modules/dasLLAMA/tests/test_box_profile.das Switches profile application to the internal underscore spin getter/setter.
modules/dasLLAMA/PERF_LEDGER.md Records the browser parked-workers perf win as a landed ledger entry.
modules/dasLLAMA/dasllama/dasllama.das Exposes get_jobque_spin_us / set_jobque_spin_us via the facade.
modules/dasLLAMA/dasllama/dasllama_math.das Adds emscripten [init] defaulting spin to 0; renames internal spin accessors.
modules/dasLLAMA/dasllama/dasllama_fat_start.das Updates runtime snapshot to use underscore spin getter.
modules/dasLLAMA/dasllama/dasllama_common.das Applies box-profile jobque_spin_us via underscore spin setter.
modules/dasLLAMA/ARCHITECTURE_RUNTIME.md Documents the browser parked-workers default and rationale.
modules/dasGlfw/src/dasGLFW.main.cpp Improves emscripten canvas sizing logic to prefer parent box when appropriate.
include/daScript/misc/platform.h Raises wasm DAS_MAX_HW_JOBS default cap from 4 to 8 (with updated rationale).
examples/dasLLAMA/storywish/web_shell.html Adds Cache Storage model caching with sha256 verification and stale-key sweep.
examples/dasLLAMA/storyteller/web_shell.html Same caching/sweep logic as storywish shell.
examples/dasLLAMA/REVIEW.md Clarifies browser input rules for ImGui-harness vs manual GLFW polling; adds audio-status-box rule.
examples/dasLLAMA/parrot/web_shell.html Fixes keydown prevention (don’t swallow space) and adds model caching + sweep.
examples/dasLLAMA/parrot/take.das Replaces textbox/button logic with waveform peak aggregation + chunk ledger utilities.
examples/dasLLAMA/parrot/main.das Rebuilds parrot into an ImGui multi-panel lab, adds jobque controls and chunk timing display.
examples/dasLLAMA/parrot/.das_package Updates package description to reflect ImGui-based UI.
examples/dasLLAMA/ARCHITECTURE.md Updates example architecture docs for ImGui harness usage and model caching behavior.
doc/source/reference/tutorials/dasLLAMA_05_performance.rst Documents spin window semantics, defaults, and latching behavior.
doc/reflections/das2rst.das Updates doc grouping regex to include new facade spin APIs.
CMakeLists.txt Updates cached description of wasm DAS_MAX_HW_JOBS default to 8.
Review details
  • Files reviewed: 35/35 changed files
  • Comments generated: 3
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread modules/dasLLAMA/tests/test_parrot.das
Comment thread modules/dasLLAMA/tests/test_parrot.das
Comment thread tutorials/dasLLAMA/05_performance.das Outdated
…mple never declared (the run plays through the mixer and a box without a window server skips it), and the performance tutorial's spin section restores the window it found rather than a fixed desktop value, on the page as in the source.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings September 11, 2026 00:00

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

There are a few correctness/documentation issues in the changed code (notably a non-portable facade test expectation and some misleading checklist wording) that should be fixed before approval.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 35/35 changed files
  • Comments generated: 3
  • Review effort level: Lite

Comment thread examples/dasLLAMA/parrot/main.das
Comment thread modules/dasLLAMA/tests/test_facade.das
Comment thread utils/dasllama-server/REVIEW.md
… ready - a box profile's own value, or the desktop's 30 ms where the engine's default is 0 - instead of a fixed 30 ms that replaced a tuned window after a toggle off and on.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings September 11, 2026 00:13

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

There is at least one confirmed correctness hazard (int64→int narrowing without clamping for the spin window in examples/dasLLAMA/parrot/main.das) that should be addressed before approval.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 35/35 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread examples/dasLLAMA/parrot/main.das
… DLL imports dasModuleClipboard.shared_module, and a recording start that saw nothing require the clipboard module wrote it as deferred beside an eager imgui, so the next start's eager load of the three imgui DLLs failed on the import ("the specified module could not be found") and stayed pending, out of the deferred fallback's reach - the Windows lane's deferred-modules test, red or green by whichever manifests earlier children left. With the requirement declared the recording start pulls the clipboard module in, and the rows agree. modules/REVIEW.md, new, carries the duty for every module: a shared module linked against another module's target requires that module in its initDependencies in the same change.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings September 11, 2026 01:45

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

It modifies a generated binder output file (modules/dasImgui/src/dasIMGUI.cpp) in a way that is likely to be lost on regeneration, risking a silent dependency regression.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 37/37 changed files
  • Comments generated: 2
  • Review effort level: Lite

Comment thread modules/dasImgui/src/dasIMGUI.cpp
Comment thread examples/dasLLAMA/parrot/main.das
… gains require_load_modules, the modules a binding's library imports and must initialize first but whose types stay out of its type library (require_modules adds the module to the library, and imgui's ImVector fields then resolve to clipboard_core's copies of the same annotations - the OpenGL driver stops compiling), bind_imgui.das pushes clipboard_core into it, and the generated dasIMGUI.cpp carries the binder's exact emission (the require and its initDependencies), so the self-binder's freshness gate reproduces the file rather than reverting a hand edit. modules/REVIEW.md states the link-implies-require duty and the binder duty as two rules with one WHY each, cites no other folder's architecture doc, and routes the shader-emitter checklist by kind alone (the dasMetal and dasSpirv checklists already route by location). The lab's hint names Ctrl or Cmd, the chord the handler accepts.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings September 11, 2026 02:05

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

It spans cross-cutting runtime behavior changes (wasm threading defaults), exe emission logic, binding generation, and multiple UI/browser-shell paths, making it higher risk than can be safely auto-approved here.

Review details
  • Files reviewed: 39/39 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

@borisbat
borisbat merged commit 5e3e9f3 into master Sep 11, 2026
51 of 52 checks passed
@borisbat
borisbat deleted the bbatkin/parrot-lab branch September 11, 2026 04:42
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