UI-09: BVH rewritten over a stable primitive-index permutation with
explicit child indices, structural validator, and differential tests
(the old tree walked prims directly and assumed adjacent children).
UI-07: AI worker constructs the selected backend (local fails closed
without a loopback/https endpoint instead of sending prompts to
Claude); streaming is preview-only (never replaces the editor
mid-stream); stale post-cancel events discarded; AI-sized responses
checked against the script ceiling before apply.
UI-06: script source ceiling enforced before VM creation; output
triangle ceiling before cache/export.
UI-12: export dispatch bounded (1 active + 2 queued, explicit reject).
UI-13: GLB preserves hierarchy/scale/visibility/units; PDF uses real
CSG mesh bounds (never fabricated 1x1) and validated grid spacing; SVG
fits viewBox to bounds with validated bounded grids.
Also: corrected PDF CSG test to real bounds, tightened the disabled-copy
test to success markers, FileLock Debug for green lib-test compile.
project_repo.rs/capabilities.rs ride along concurrent fmt/test fixes in
the same files.
CORE-11: parsed scheme/host identity replaces string-prefix trust;
loopback is exactly localhost/127/8/::1; plaintext http only for
loopback; lookalikes, user-info, bad ports, fragments rejected.
CORE-12: resource_limits, format_interop (independent parsers), and
migration_corpus integration targets.
Hygiene for green gates under the pinned toolchain: unused-import
cleanup, derivable Default impls, needless-range/manual-contains
fixes, type aliases, fixture-literal allows (no numeric changes).
CORE-06: DocumentEdit/ScenePatch transactions against base revisions;
failed patches leave byte-identical state, stale bases rejected, undo
via inverse patches, refuse/cascade deletion policy.
CORE-07: one canonical bounded world-mesh stream (hierarchy, full
transforms, inherited visibility, named unit conversion, triangle
budgets, chunked cancellation with no partial success).
CORE-01: CadError with kind/entity-path, ValidationPolicy/GeometryBudget
hard ceilings enforced before allocation, opaque typed ids with checked
supply, explicit remap tables; missing material/layer refs are hard
errors, never silent fallbacks.
CORE-02: identity transform is translation 0/rotation 0/scale 1
(Default no longer collapses to zero scale); single local/world matrix
convention T*Rz*Ry*Rx*S with iterative validation (duplicates, dangling,
cycles, depth 1024) and inherited visibility.
CORE-03: versioned lossless CadDocument with tagged EntityKind, explicit
units, deterministic canonical bytes, future-version quarantine, and
explicit legacy migration warnings.
Verified in worktree at 64ae8d7: cad-core 319 tests green, clippy/fmt clean.
Contain production capabilities, remove the production sync surface, and keep legacy media/export/transport implementations test-only.
Require authenticated existing-key storage with preservation-first recovery and sticky write disablement, backed by deterministic fault and concurrency tests plus dependency and workflow contracts.
- Use WidgetRef::borrow_mut/borrow directly for the DocEditor host
(new Widget derive: borrow has no generics on refs, as_* only on
WidgetRefExt; WidgetExt blanket impl covers View lookups).
- Semicolon fix for RefMut temporary lifetime in set_rich_mode.
Whole-tree sync: cad-core/cad-ui split sources, nigig-build
construction_frame migration, pdf port progress, mpesa/pay/uikit/doc
updates, workspace members/profiles/lock, CI workflows and reviews.
See individual file history for details.
- nigig-build: cad-ui + construction_frame back on unconditionally.
The host-only gate is dropped: cad-ui now compiles for aarch64, and
pageflipnav mobile needs ConstructionScreen / BuildProjectsPage
(CAD/Docs/Spreadsheet buttons) — gating produced the white screen.
- cad-ui: ScriptVmHost for standalone eval (no more vm.std / () host),
std::thread workers (Cx::spawn_thread removed upstream).
- viewport: same worker fix + section_state helper for the CPU cull path.
- script_bindings: new script/geometry binding module.
- spreadsheet grid + invoice Walk literals: ..Default::default() for
new aspect/cell/deferred fields; explicit style::CellAlign import
(makepad added its own CellAlign).
Verified: pageflipnav aarch64 release links with 0 errors; APK built,
installed (54M) and running with home screen drawing.
- nigig-build: cad-ui + construction_frame host-only (DO NOT enable
unconditionally: CadViewport Script derive fails ScriptApply for
aarch64 and breaks every pageflipnav android build).
- map: vendor TagThreadPool (removed upstream with the task-pool
scheduler) into thread_pool.rs; Walk literals gain
..Default::default() for new aspect/cell/deferred fields.
Verified by pageflipnav aarch64 release rust build (0 errors).
Fork nigig-makepad-test-android now at b9a083c26 (upstream merge +
robot secondary-dex bundling + app_main wrapper fix, on top of the
game-libs/arcade port). All 16 workspace makepad revs follow.
Also takes the in-tree workspace updates: exclude nested
crates/nimanyatta workspace, add crates/apps/nigig-site member, and
PERF-OPS Phase 1 profile tuning (thin LTO + engine opt-level 3).
cad-core/cad-ui split and nigig-traffic members stay WIP.
cad-ui's Widget Script derive (CadViewport) needs LiveHook fix for
aarch64; until then, gate it behind cfg(not(target_os="android"))
in nigig-build so pageflipnav's aarch64 wrapper (which pulls
nigig-build) can link without cad-ui. Host builds still include
cad-ui. Unblocks pageflipnav aarch64 release.
The CAD dashboard's CadDashboard node never realized as a widget, so
tapping 'CAD Workspace' opened to a blank/editor-only sheet. Empirical
device dumps showed the first child after the root realizes reliably
while a sibling placed after the editor AdaptiveView does not, and a
root ':=' widget child alone never realizes here.
- Place dashboard_layer as the FIRST direct child of CadWorkspaceBase,
wrapping mod.widgets.CadDashboard so it is a reliably-realizable,
togglable View layer (matching the working doc workspace pattern).
- Wrap the editor AdaptiveView in editor_layer (a plain View) and toggle
editor_layer/dashboard_layer visibility from apply_dashboard_visibility
instead of toggling the AdaptiveView variants, which always draw their
active variant regardless of visible.
- Add use mod.widgets.* to the CadDashboard script_mod (matches the
CadEditorSheet registration that realizes inside this workspace).
- Add regression test candlands_on_dashboard asserting the dashboard
title and + New Project button land when opening the workspace.
ADR 0035 left one of p2p-intel's four limits open: no OS notification
backend, so alerts stopped when the window closed. The seam existed with one
implementation that truthfully did nothing. This is the crate that fills it.
Posting a notification on Linux is one D-Bus method call. Three ways to make
it were measured rather than assumed: notify-rust with libdbus is twelve
crates but a C library, which needs pkg-config and breaks the Android and
iOS cross-compile this crate family keeps clean; notify-rust with zbus is
pure Rust and 169 crates including an async executor; writing the wire
format out is about 250 lines and nothing at all. robius-sms deleted polkit
and gio for exactly this reason -- its E9 note records they were the sole
source of two RUSTSEC advisories and an LGPL question for every consumer --
so pulling a 169-crate tree back into the same family for one method call
would reverse that decision for a worse reason.
The cost of hand-rolling is that the protocol has to be exactly right, and a
mistake makes the daemon disconnect with no diagnostic. That cost was paid
in tests: the suite starts a private dbus-daemon per test and talks to it.
This matters more than it sounds. The marshaller and the parser were written
from the same reading of the specification, so them agreeing with each other
proves only that I was consistently wrong or consistently right; only a
third party can say which.
It found three bugs no unit test would have.
The first is the one worth dwelling on. Every error reply parsed as success.
The header-field walk assumed all fields were strings, but REPLY_SERIAL is a
u32, and reading its four bytes as a string length desynchronised the cursor
so ERROR_NAME was never reached. `post` returned Ok against a bus with no
notification service running. That is precisely the bug this crate was
written to eliminate -- a notifier that reports success and delivers nothing
-- reintroduced by accident inside its own parser. I cannot think of a
stronger argument for testing against something you did not write.
Second, is_available() was true on a bare bus, because NameHasOwner
*succeeds* and answers false in its body; checking only for an error
reported a working notifier on a machine with no notification daemon.
Third, replies were not correlated. The bus sends NameAcquired unprompted
right after Hello, so "read the next message" consumed a signal and treated
it as the answer. Replies are now matched on REPLY_SERIAL, and a single read
carrying several messages is walked rather than truncated.
The suite also serialises every test that mutates DBUS_SESSION_BUS_ADDRESS
behind a mutex. The variable is process-wide and cargo runs tests in
parallel threads; three consecutive parallel runs are now green.
--test-threads=1 would have made the failures go away too, and would have
hidden a real hazard from whoever reads the file next.
On the four platforms, honestly. Linux is implemented and tested. Android is
implemented and *compiles* -- cargo check and clippy both pass for
aarch64-linux-android -- but has never run on a device, and the module says
so in its first paragraph. It handles the two things Android drops silently,
missing POST_NOTIFICATIONS on API 33+ and a missing channel on API 26+,
because both are the same accepted-and-discarded failure this crate exists
to remove.
Apple and Windows are deliberately not written. Neither could be compiled
here -- no macOS or Windows toolchain and no way to add one -- and objc2
message sends or WinRT calls that no compiler has ever seen are not an
implementation. They are plausible-looking text that would sit in the same
crate as tested code and be read as equally finished. Both return
PermanentlyUnavailable with a reason naming ADR 0036, and their module docs
record the call sequence so the next person starts from a design rather than
a blank file. The support table says "written" and "verified" in separate
columns for the same reason.
p2p-intel's dashboard now uses SystemNotifications instead of
UnavailableNotifications. The latter stays: on a platform with no backend it
is still the truthful answer, and a test needs something that reliably
cannot deliver. Alerts are tagged per fiat so a market replaces its own
previous notification rather than stacking -- a 30-second poll would
otherwise fill the shade, and a full shade is what makes someone turn
notifications off for the app entirely, which costs more than the feature is
worth. Two new tests pin the invariant that a sink must never report
delivery it did not achieve.
CI gains a notifications job that installs dbus and sets
ROBIUS_NOTIFICATION_REQUIRE_DBUS=1. The bus-backed tests skip when
dbus-daemon is absent so the suite stays green on a bare machine, but a
silent skip in CI would mean the integration tests quietly stopped running
while the build stayed green. I verified the guard fails by hiding
dbus-daemon behind a stub that exits 127.
50 tests in the new crate, 225 in p2p-intel, clippy clean on host and
Android, and the app still starts under Xvfb.