Repository navigation
fix(render): restore chart layers and event delivery; add background saves and Obsidian - #1267
Merged
Merged
Conversation
The coin-row cache compared raw slice addresses. An allocator could reuse an old address, and copy-on-write updates could preserve a vector's buffer, so changed aggregates could be mistaken for the same cached input. Retain Weak references to the actual Arc-owned base and scoped snapshots. Their control blocks keep allocation identity unique while obsolete source vectors are still freed when their readers release them. Compare those identities alongside the existing filter/sort key; unchanged inputs still reuse the built rows without copying aggregate payloads into the cache. Validation: regressions exercise Arc::make_mut on both inputs, actual row values, unchanged-cache reuse, and release of old aggregate payloads. Full Windows workspace tests and Clippy pass.
The malformed-container test changed a random payload byte and assumed the legacy checksum must change. A checksum collision could make a valid implementation fail intermittently during the full workspace suite. Flip a bit in the stored checksum instead, leaving the hashed bytes intact. The outer exported packet checksum is still valid, so the test continues to exercise rejection of the inner container hash for the intended reason. No packet format, parser, checksum implementation or production behavior changes. The complete workspace suite passes with this deterministic case.
The canvas bridge deliberately borrows native GPU objects instead of copying chart output. On Linux those pointers address Rust wgpu types: two separately resolved packages are not an ABI contract, even when their public APIs match. Keep the raw API and resolve the consumer to the same registry wgpu package as MoonUI. Remove the now-unused fork from the source allowlists and freeze the minimal public dependency graph without moving MoonProto or unrelated third-party packages. Document both callback safety contracts. Check the actual producer and consumer dependency edges even in sibling checkout builds. The old two-package graph fails this contract; the shared 29.0.4 graph passes. Native chart execution was exercised on Hel1 in X11 and Wayland using llvmpipe; this does not qualify hardware-GPU performance.
The Linux backend resolved embedded resources from the wrong relative location, and the candle-volume entry point called a missing WGSL helper. Fix the actual includes and restore the coordinate conversion so native chart pipelines can be created instead of failing before presentation. Validate every checked-in chart WGSL source with Naga on all test hosts. This catches a broken Linux shader while developing on Windows or macOS; it does not pretend that parsing a shader qualifies native rendering. The public lock adds only the existing Naga package as a direct test edge. Validation: all 14 WGSL sources parse and validate; native Linux builds and chart stages ran in X11 and Wayland on Hel1. The complete Windows workspace test suite passes with this final tree.
An unreadable or malformed config is not an authoritative empty document. Previously, a later autosave could replace that original after startup fell back to defaults, including when a transient sharing violation disappeared. Protect the affected path at the common atomic writer, distinguish missing files from failed reads, and route theme/order/hotkey, badge, figure and chart loaders through that contract. Preserve the existing successful quarantine and valid legacy migration behavior; unknown individual figures still round-trip. Add isolated corrupt/unreadable load-then-save regressions for each affected document, including restored access before save and an unrelated writable path. The protection lasts until restart so delayed or cloned fallbacks cannot silently become authoritative.
Routine chart, drawing, badge, update-history and config writes could block the GPUI coordination loop on serialization or slow storage. Moving the write alone would also allow an old snapshot to overwrite a later explicit save. Extend the existing serial worker with immutable snapshots and failure acknowledgements. Normalize config identities in the live owner before capture, coalesce edits while one write is in flight, and retain a separate one-second autosave admission window. Explicit config/key operations finish earlier work; quit captures the final authorities before window teardown and flushes in order. Failed figure/badge writes retain pending changes for retry. Keep the blocked-I/O, latest-on-quit, per-class retry, manual-write ordering, live-UID and independent figure-snapshot regressions with the implementation. Update persistence source contracts to assert the worker/admission boundaries. Only deliberate commit and exit boundaries may wait for storage.
A SQLite read snapshot does not freeze the external COIN-M knowledge cache. Concurrent learning or a replica reset could therefore give statements in one financial result different currency interpretations, or let old WAL evidence repopulate knowledge invalidated by a committed reset. Pin money interpretation for public queries and ReportSnapshot batches, sharing the pin with nested reads. Anchor the WAL under the writer's short commit/invalidation publication fence. Keep old transaction discovery local when its revision is unknown, and track Forget per core so unrelated resets do not discard still-valid positive evidence. Add isolated shared-cache regressions for concurrent learning, running and old snapshots, raw transactions, commit publication, unrelated-core Forget and proof-preserving reexamination. Assertions compare public currency totals, not only generated SQL or cache fields.
A bounded integrity scan that times out or cannot run has not established corruption. Closing history reads in that case hides existing data, while opening writes would bypass the full integrity gate. Apply the file-size shortcut only to the synchronous startup check and let the bounded background scan inspect large replicas. Preserve read access through SQLite read-only connections while writes remain blocked; confirmed damage still closes access. Publish an explicit incomplete-check notice on the existing report revision channel even when no writer can commit. Keep access-gate, large sparse-file, notice text and revision-delivery regressions with the change. Report retains its content and exposes the stopped-recording explanation in every supported locale; only a conclusive healthy gate permits new writable preference-reader connections.
Every SysStatus ping previously woke unrelated Backend observers, yet the status panel depended on those notifications for elapsed time and warning history. Simply suppressing pings would leave quiet panels stale. Retain every telemetry sample without marking general UI state dirty, and publish the warning engine's completed samples through a dedicated entity. Keep update transitions immediate. Hidden panels maintain cheap badge state and defer row/history materialization until activation, preserving one latest catch-up instead of rebuilding invisible tables. Keep the telemetry-drain regression and status throttle/averaging contract with the change. The shared native acceptance probe separately exercises quiet-tail progression and hidden-panel event delivery in the real app.
Market revisions do not necessarily notify Backend. The old time gate only sampled when an unrelated event arrived, so the last market update could remain absent from Screener indefinitely after a burst stopped. Observe the existing market revision channel as well as Backend and coalesce both into one trailing refresh task. Explicit rebuilds cancel redundant pending work. The existing worker still prepares rows off-thread, while the latest publication now has its own delivery path within one second. The shared native application-acceptance probe exercises a market-only event and checks one admitted preparation without adding a rescue Backend event.
The global workspace generation changes for other groups as well as this Report. Treating every such event as a scope change needlessly reset queries and selection, and invalidated an export while its destination picker was open. Remember the semantic effective scope consumed by the last request and skip workspace events that leave it unchanged. Compare exports against that scope and the effective core ids, preserving real mode and membership changes. Update export-identity regressions with the implementation. The shared native acceptance probe additionally checks the actual observer path, retained selection, query sequence and export authority after a foreign workspace event.
Scale, center, switch and close-all commands advanced their revisions without notifying the existing chart observers. On a quiet core the command could wait for unrelated traffic even though the action had already been accepted. Notify after the accepted revision changes, including global commands issued from detached charts. Reuse the existing Backend observation path instead of adding a polling channel or a new command queue. Change the native price-scale stage to dispatch the real Shell ScaleMinus action from Auto. The following stage verifies the resulting 50-percent chart specification rather than having the test write the same fields itself.
The save-group and named-build prompts focused their field before Root opened the dialog. Root then captured the new field as the previous owner, losing the focus target it should restore when the dialog closes. Create the field first, open the normal Moon dialog, and only then focus it. Keep field construction separate from focus assignment so the named-build input cannot steal ownership before its host exists. This uses the existing MoonUI dialog lifecycle and its focus-restoration regressions; no substitute modal or global focus state is introduced.
The fixed decimal floor could turn small prices into zero, and the fixed 56-pixel gutter could clip a correct satoshi label. Enlarging only the painted axis would leave navigation and hit geometry using a different plot width. Share one grid-aware price formatter between axis and cursor labels, with satoshi formatting and a magnitude fallback when the tick is unavailable. Measure the axis labels and apply a pending width at the next chart layout, only for the same rendered market. Input and the displayed pane then consume the same applied geometry; unchanged measurements create no additional debt. Keep microprice/grid-precision, cursor-plate and applied-versus-pending geometry regressions with the change, including the final quiet-frame assertion.
The last book update inside the native bake throttle could remain invisible once the market stopped. Rebuilding only the inner book texture was also insufficient while the chart continued presenting its unchanged outer base. Expose the existing book deadline to the quiet chart frame path and return whether native preparation actually rebaked the book. Propagate that result to the containing base cache so the final levels reach the user without waiting for a new market revision. Add a software-D3D regression that observes the final target pixels through the real frame/prepare/draw boundary: the throttled stripe stays old before the deadline, changes afterwards, and leaves no further presentation debt.
A device replacement invalidates GPU buffers without changing source revisions. Quiet producers may never send another update, so consuming and discarding the only replayable input left recovered charts incomplete. Recreate native layers from their retained CPU authority, preserving tick ring order and the latest marker hover patch. Keep a queued replacement or clear authoritative over retained history; do not introduce a central reupload bus or require a synthetic feed event. Add native-buffer regressions for repeated replacements, ring head/order, horizontal and side volumes, complete user geometry, hover updates and clears. Extend the D3D book test to verify the retained stripe after replacement. The separate full-app acceptance step checks frozen own-pass pixel equality.
Render acceptance needs actual dense history rather than a nominal count or a replacement renderer. Multiple charts must consume the same producer independently, including after a device reset or a lapped trade cursor. Add a deterministic bounded dense fixture and adapt it through the ordinary market-history interface. Preserve candle history beyond the clipped trade tail and deliver incremental rows to each consumer's own cursor. Route fixture market names through normal synthetic startup; live protocol behavior is unchanged. Include repeatability, bounded eviction, independent-reader, initial/tail/reset and retained-candle regressions. The following native acceptance step connects these data to the ordinary Main chart stack and real rendering backends.
Acceptance must observe the visible application and completed GPU work. Hidden retained tabs, CPU history counts, a nominal text configuration or an unrelated input event cannot establish that the intended path reached the screen. Bind workload and mouse geometry to one visible chart, count actual GPUI renders and submitted retained text, and use consistent overlay-pass counters. Run the dense fixture in the ordinary Main stack with independent hybrid and candle charts. Freeze input history for repeated device resets and compare the actual DirectX own-pass pixels, including nonempty volume layers. Exercise blocked/failed autosave with observed UI/input progress and a verified latest file, dedicated application event delivery, and painted Input/Resizable changes during native prepaint/paint without a rescue invalidation. Keep the oracle regressions and diagnostic build documentation with their probes. Windows native F1 has a restored green run and two targeted reverse-mutation failures. Linux generation/history coverage does not claim full pixel readback, software-renderer CPU failures remain failures, and Metal qualification remains a separate gate. No performance thresholds are relaxed by this commit.
MoonUI now routes its client-drawn close button through the same should-close policy as native close messages. Remove the Linux guess that every detached dock-panel release was user initiated; start the user-close marker at false on every platform. Only an explicit close request may repin the dock panel and delete its detached specification. Keep registry identity, quitting guards and forced teardown unchanged. Independent detached chart windows use their existing registry-based lifecycle and are not changed. Validation: full workspace tests and Clippy pass; the source contract now requires false on all platforms and retains the guard-before-repin ordering. MoonUI lifetime and FrameButton tests pass on Windows and Hel1 Linux. Native Linux compositor lifecycle remains a separate qualification boundary.
Text preparation already updates the cursor backing rectangles before the current GPU draw. Marking needs_present again after that synchronization creates an unnecessary next frame when the chart is otherwise idle. Remove only the already-served readout debt. Keep axis-width relayout and the framework debt for refused presentation unchanged. Regression: a real GPUI frame callback measures the cursor text, produces a containing plate with the measured height, then returns Skip on the next chart frame. Restoring the old needs_present assignment fails that final assertion; the fix passes. Full workspace tests and Clippy pass. The test reuses the MoonUI test-support frame callback without allocating hardware resources.
Chart report scope and unresolved Auto targets observed the frequent price channel even though their inputs are catalog membership, client lifetime and provider routing. This repeatedly rebuilt scope while prices changed and made catalog readiness depend on unrelated market activity. Carry a rare catalog event through the existing feed drain for client install/clear and list changes, including cores with no open charts or elected market role. Publish the same narrow notification after provider mapping and structural/mode changes. Keep price notifications for Screener and all retained chart data. A catalog event re-arms only unresolved Auto attempts. Remove the snapshot-revision component from that attempt key: replacement clients can reuse a counter, and coalesced reconnect events must still retry the same target. Successfully selected targets remain stable. Validation: actual feed-drain tests cover a catalog with no open markets, 100 price updates without catalog wakes, initial routing, late identity, ready-provider failover and removal. Auto tests cover repeated same-target events and stable success. Full workspace: 9108 passed, 0 failed; Clippy all-targets passes. Independent Sol found the reconnect-counter edge and Astra reviewed the final correction.
The tab-strip scale control changed a Custom stack immediately, but persist_scales visited only Main, ordinary Add tabs and detached stacks. A Custom tab still attached to its group window lost the selected scale after restart. Include Custom stacks in the existing persistence traversal and combine the identical stack loops. Restore already applies the stored scale; no new storage, window registry or FireTest state is needed. Validation: full workspace tests and Clippy pass. In an isolated native synthetic terminal, a restored Custom tab was changed from Auto to 50 percent through the actual dropdown, wrote scale=0.5, and reopened at 50 percent after a clean exit and restart. Returning to Auto wrote null. The current native dense FireTest also passes.
Integrate the completed MoonUI Facet design into the existing terminal surface owners. Add Obsidian to theme selection, preview, persisted settings, chart color editing and all seven locales. Give its chart colors a separate table; old dark and light settings keep their values and do not get rewritten merely on loading. Keep native chart hosts transparent so the GPU chart remains visible. Style existing chrome, panels and tool windows in place, preserving dock activity, context-menu ownership, background saves and protected config loading from the render audit. Synchronize no-fill window clear colors on Facet entry and exit, including a window opened directly in Obsidian; Flat-only transitions retain their previous behavior. Validation: 42 core theme tests pass, including sparse/legacy table migration, round-trip and old palette preservation. Integrated terminal unit tests and the native FireTest/visual qualification are recorded in the delivery journal. Sol and Astra reviewed the author diff and the resolved integration conflicts.
The userdata pass used the entire pane as its scissor, so offscreen trade arrows and segments could paint over the left price labels and the bottom time axis. Use the existing plot-to-book content rectangle on DX11, Metal and wgpu. Restrict trade arrows to their existing plot-only hit area in all three shaders. Keep order-line continuations into the book, the independent horizontal-volume zone, axis text, cursor readouts and the arrival border. Remove the obsolete HVOL-only clip helper rather than adding another clipping state. Add a dense FireTest probe to the real DX11 userdata pass. It paints adversarial arrows/segments under the already-installed production scissor, compares native pixels against independent layout bounds, and requires both visible arrows and book-reaching order lines. Normal rendering removes the probe on the next frame. Native unit coverage checks left/right price gutters and a disabled book. The probe makes no claim to test every text layer or Metal/wgpu pixels. The shared clip policy and matching shader change cover those backends in source. Validation: native GPU regression passes, including the integrated workspace run; Sol reviewed the complete layer matrix, preserved exceptions and pixel oracle.
A provider continues updating its retained market snapshot with all charts closed, but the feed previously suppressed MarketDataChanged when its wanted-name list was empty. The session drain also discarded an empty notification, leaving the Screener stale after the generic backend heartbeat was removed. Distinguish no relevant event from a changed snapshot with no chart-local dirty names using Option<Vec<MarketDirty>>. Publish the existing market revision for accepted changes and keep targeted chart invalidation conditional on names. Include successful retained stats and initial candle-snapshot events; failures must not manufacture updates. Observe the rare catalog/provider channel through the Screener's existing coalesced refresh, with no new timer or full data copy. Validation: the real SDK classifier -> FeedMsg -> SessionManager drain regression passes on Windows and Linux with no chart subscriptions or backend heartbeat. Failed refreshes produce no wake. Native FireTest checks the adjacent consumer and burst coalescing, now including a catalog-only event. This separation avoids adding a fake debug transport to production just to join test boundaries. Astra reviewed the full producer, routing, drain and consumer chain.
The parallel workspace run returned "12 ms" and "12 мс" from two consecutive cell_text_for calls because other tests changed the process-wide locale between them. Use the existing locale guard and assert the concrete retained ping value. This preserves the regression against dashing a connecting core without changing production formatting or weakening the numeric assertion.
Keep the selected theme identifiable as Obsidian in Latin-script locales and retain the Russian and Ukrainian Cyrillic spellings. Register both captions in the existing deliberate-translation inventory; do not change the translation test or its coverage. The full workspace run exposed these two missing declarations after all 3524 terminal unit tests passed.
Point all four normal and test dependency declarations to the published MoonUI audit branch so reviewers and CI can build the paired change without local sibling paths. Commit the matching public lock for aca1811. All 23 MoonUI packages resolve to that revision; every non-MoonUI package identity and the MoonProto 97d90081 pin remain unchanged. Merge MoonUI first, then return these declarations to rolling master before merging this Terminal PR. The local override is preserved outside the checkout during public dependency qualification.
…dict The Linux diagnostic run reproduced a false catalog-only failure: its notification reached Screener immediately, but GPU recovery delayed the first poll of the one-second trailing task by 584 ms. The old 1,100 ms sleep checked that task after only 645 ms and then the next probe cancelled it through an unrelated workspace rebuild. Wait for the observed consumer sequence with a bounded deadline instead of assuming that notification time equals task-start time. Preserve the strict exactly-one-refresh assertion and never emit a rescue notification. Let the existing cooldown stage await outstanding callbacks, with an outer deadline so a lost notification or missing Report callback still fails. Healthy runs add no fixed delay; production Screener behavior is unchanged. Extend the existing stage timeout contract to include cooldown. Independent Sol and Astra source review covers the complete consumer-to-verdict path; the preserved Hel1 timing trace reproduces the original ordering failure.
- Release failed with E0599: FireTest compiles into every profile, and its dense run reaches ChartPanel::debug_data_handle, which was debug-gated. - Figure price labels used a magnitude-based decimal count and printed 0.0000 on small-price markets. They now use the axis format with the pane's tick; format_price takes f64 so a stored price keeps its last tick, while f32 axis values print exactly as before. - Pin, lock and broom buttons and the wheel-over-axis strip read the measured gutter of a left axis instead of its 56 px minimum.
Moonbot-Tech/MoonUI#146 is on master, so the review branch reference goes. The lock's MoonUI rows stay stale by design: CI and the release refresh them to master. The only lock change left is dropping the zed wgpu fork.
This was referenced Nov 6, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Charts could paint trade geometry over the price axis, lose retained layers after GPU replacement, or wait for unrelated traffic to publish an accepted change. This series repairs those paths, moves recurring saves off the UI thread, and integrates Obsidian as an optional theme.
Companion runtime/component PR: Moonbot-Tech/MoonUI#146. Each commit contains one semantic change with its reason and validation. Please preserve that commit history when merging this series.
User-visible changes
FireTest
moonterminal --fixture dense --debug-script chart-smokeruns in the real terminal with its Main window and two independent charts: candles plus a dense hybrid, backed by 100,000 deterministic generated trades. No stored market history or live trading account is needed.It exercises real native input and frame delivery, retained text, moving/resizing/multiple windows, two GPU replacements, slow/failing autosaves, F1 quiet-frame behavior, and scoped panel updates. The new gutter probe checks actual DX11 pixels and also requires the order-line continuation in the book. GPU recovery compares the own-pass image before/after exactly on DX11. Trading commands remain off unless explicitly enabled.
Validation
cargo test --workspace -- --test-threads=1, workspace/all-target Clippy with-D warnings, formatting and final native build pass. The default parallel cargo runner exposed two existing process-global/timing flakes; neither assertion was weakened, and both pass under the serial and process-isolated runners.Related issue
Partially addresses #1190: healthy large replicas are no longer skipped by the full background check; inconclusive checks retain history reads and display a specific recording-disabled notice. An inconclusive check still does not authorize writes or an in-app reset through the blocked writer, so this PR intentionally does not auto-close that issue.
Dependency and platform boundaries
master. The lock's MoonUI rows stay stale by design, since CI and the release refresh them; the only lock change is dropping the zed wgpu fork, andassert-only-moonui-moved.shpasses against the refreshed master. MoonProto stays at 97d90081.Added on top before landing
ChartPanel::debug_data_handle. The accessor is no longer gated.0.0000on small-price markets. They now use the axis format with the pane's tick.format_pricetakesf64, so a stored price keeps its last tick, andf32axis values print exactly as before.Local gates on the final code
cargo fmt --all -- --check,cargo clippy --workspace --all-targets --locked -- -D warnings,cargo check --releaseand the debug build pass against refreshed MoonUI master.cargo test --workspace: 9,135 passed, 0 failed, 210 ignored, run on the same MoonUI tree before this PR returned tomaster. FireTest was not re-run on the additions.Refs #1190