Commit graph

2,973 commits

Author SHA1 Message Date
b9a083c26f fix(android): bundle robius secondary dex + wrap app_main binaries
- bundle_crate_secondary_dex: merge OUT_DIR/classes.dex from dependency
  build scripts (robius-sms/trigger/ussd javac+d8 Java for manifest
  receivers/services) into the APK as classesN.dex. Without it the
  manifest declares BootReceiver/SmsReceiver/AccessibilityService that
  are missing at runtime (ClassNotFoundException on boot).
- has_explicit_lib_target: a crate with src/main.rs containing app_main!
  is an app, not a lib — generate the android wrapper ([lib] path =
  src/main.rs) so the JNI entry (activityOnCreate) is linked. Fixes
  UnsatisfiedLinkError for app crates that also ship src/lib.rs.
2026-09-10 16:26:35 +03:00
Kevin Boos
4b25a1bf1e
cargo-makepad: support custom iOS and tvOS Info.plist entries (#1221)
* cargo-makepad: declare native speech recognition metadata

* cargo-makepad: make Apple plist customization opt-in

* cargo-makepad: use macOS tools for plist overlays
2026-09-10 07:53:29 +02:00
Jason Yau
14fe611e66
Add Apply::Rebake so script_mod re-runs stop clobbering imperative state (#1219)
Co-authored-by: jasonqiu <jasonqiuchen@outlook.com>
2026-09-05 23:26:03 +02:00
Arena Agent
fe21c07d84 skills: add Makepad game skills pack ported from threejs-game-skills
Nine agent skills for building Makepad/Rust games, ported from
majidmanzarpour/threejs-game-skills. Same director-routed workflow and
premium bar; runtime rewritten for this fork's game crates.

- makepad-game-director        entrypoint, routing, continuity, asset probe
- makepad-gameplay-systems     loop, movers vs rigid bodies, input, camera, netplay
- makepad-aaa-graphics-builder lighting, shaders, budget, visual scorecard
- makepad-game-ui-designer     HUD, menus, touch and XR UI
- makepad-debug-profiler       defect bisection and profiling
- makepad-qa-release           verification ladder, evidence, packaging
- makepad-3d-generator         CC0 model search, casts, procedural geometry
- makepad-image-generator      texgen textures, palettes, sky, icons
- makepad-audio-generator      sample bank, mixer, material impacts, 3D audio

Written against the real APIs in libs/game/*, libs/sim and apps/arcade:
the game.* verb table, GameRenderer adaptive quality, the packed 6-float
GameMeshVertex layout, script_mod! splash styling, makepad-test driving,
and the BUDGETS.md numbers. No paid generation API is required - the CC0
library plus seeded makepad-game-gen replaces them.

Includes install.sh (Codex/Claude), validate-skills.sh and a repo-aware
probe_assets.sh; both scripts verified against this checkout.
2026-09-05 21:18:58 +00:00
Arena Agent
fe5b75d92d Merge latest makepad work while preserving fork game crates and apps 2026-09-05 20:55:35 +00:00
Admin
a75fe914ff layout: extend turtle sizing and add Grid 2026-09-05 17:21:48 +02:00
Admin
b005c6e9b2 Preserve complete Route geometry within measured web memory budgets 2026-09-05 17:07:06 +02:00
Admin
9e61553c96 Keep Route 3D buildings under bounded web memory pressure 2026-09-05 15:21:31 +02:00
Admin
09fa1f080c Restore WebGL text with complete fallback samplers
Use cached transparent 2D and cube textures for unallocated optional samplers without bypassing invalid-resource, target, or framebuffer-feedback guards.

Require actual glyph draws in release smoke tests and keep shader compilation asynchronous in probe instrumentation.
2026-09-05 14:39:06 +02:00
Admin
1801e38453 Harden web renderer and make Route location opt-in
Bound drawable, geometry, texture, image, map and radar work; validate WebGL submissions and retire GPU resources safely. Treat context loss as terminal without re-entering Wasm after worker termination.

Add explicit Route location consent and regression coverage, including software-WebGL release probes for six deployed demos.
2026-09-05 12:13:36 +02:00
435135ed50 feat(arcade): port makepad game libs + arcade from makepad-internal onto the fork
Reintroduce apps/arcade and the ten game crates that were ripped out of
the fork (assets, audio, blocks, coedit, gen, net, pkg, render, script,
session), from makepad-internal/dev. Reconcile against the fork's layout:

- makepad-game-sim/math come from the fork's existing libs/sim + sim/math;
  the copied internal libs/game/{sim,math} are dropped and the kept game
  crates plus arcade point at ../../sim and ../../sim/math.
- arcade AI is rewritten off the removed makepad-ai agent API onto the
  makepad-ai-hub headless ChatProvider worker (example/cad pattern):
  AiWorker{send,cancel,poll}, ai_worker_loop driving
  ClaudeApiChatProvider(ClaudeCli), AiWorkerEvent availability/delta/
  done/error mapped into the chat feed and authoring land_edit, with
  main.rs send_message/cancel_request/event-drain rebuilt around it.
- the game-script sandbox is adapted to the fork's jailed splash storage:
  every isolate gets mod.fs = splash_storage jail; splaes splash_storage
  set_root_for_heap is now public so the ScriptHost (or Splash) can grant
  a per-game jail root. ENT font: build.rs/dispatch.rs entities fill new
  fork sim Entity/Part fields via ..Default::default(); world_raycast now
  borrows mutably and returns the material id.

cargo check -p makepad-arcade and the game + arcade test suites pass.
2026-09-05 05:49:12 +03:00
Admin
83a00d2801 flow: archive generated assets and add live source editing
Host or attach the asset service, archive generated and terminal outputs, and provide image/video/audio/text/3D viewers with fullscreen and gallery navigation. Load only visible bounded previews, generate video posters and text excerpts, and normalize legacy thumbnails off the UI thread.

Expose video frame counts and Sandbox chat providers, make failed queue cleanup idempotent, compact the panels, and correct short-wire direction. Replace App view with a movable, resizable CodeEditor overlay with debounced source saves, live graph updates, invalid-source preservation and close/reopen geometry.

Validation: release Flow, Flow UI and flowgraph suites passed 335 tests (two ignored). Updated Flow UI suite passed 107 tests; asset route suites passed nine tests after legacy preview fixes. The rebuilt release app passed remote editing, dragging, resizing, invalid-source, close/reopen and App removal checks; final All assets scrolling measured 16.5 ms median and 18.3 ms maximum over 12 inputs. Test instances were closed through the remote protocol.
2026-09-05 01:47:53 +02:00
Admin
75b295ce9a vj: synchronize decks and queue remote stem processing
Update deck and mixer synchronization, apply matched deck rates to splats, and queue remote stem extraction through the fleet. Refresh catalog and creator pipeline integration.

Validation: release VJ suite reports 890 passed, 10 failed, nine ignored. Eight mixer failures reproduce in serial execution (gain, transitions, sample alignment and video fades); two asynchronous media tests also failed in the full run. The new matched-rate splat test passes. These remaining failures are not claimed as fixed.
2026-09-05 01:45:43 +02:00
Admin
b49e2e5060 piano-model: calibrate partial gains and decay against recordings
Apply immutable pitch/velocity-interpolated modal calibration while preserving an explicit uncalibrated constructor. Add offline acoustic tooling, reference measurements and regression coverage.

Validation: 16 calibration/acoustic release tests passed, one ignored.
2026-09-05 01:42:39 +02:00
Admin
3ce27922a4 sim: use deck geometry for collision and sensing
Use deck surfaces consistently in dynamics, floor normals, sensing and voxel handling.

Validation: release makepad-game-sim tests passed.
2026-09-05 01:42:39 +02:00
Admin
3dfe5aaed3 show-control: restore sixteen DMX scenes with local save overlays
Bundle the recovered numbered scene bank, support sixteen slots, and keep editable current state and overrides in the local overlay. Validate legacy control mapping.

Validation: 27 release tests passed.
2026-09-05 01:42:39 +02:00
Admin
2f44d20b51 apple: avoid blocking video clocks and release native players once
Use output/presentation timestamps instead of AVPlayerItem.currentTime on the UI thread. Consume only fresh frames and stop polling paused players after their poster arrives. Balance Objective-C ownership and make native cleanup idempotent.

Validation: release Flow playback smoke and process sampling; the previous currentTime mutex hotspot is absent in the updated sample.
2026-09-05 01:42:39 +02:00
Admin
f8b9a670b7 widgets: preserve numeric edit completion and menu focus
Find numeric completion actions reliably and restore menu focus using tracked areas. Handle touch dismissal and focus changes without leaving menus open.
2026-09-05 01:42:39 +02:00
Admin
88048aa784 assets: extend authoring pipelines and typed asset search
Add sandbox authoring effects and character/composite creation, improve creator submission handling, and extend publishing/search metadata. Update importer conversions and the asset UI integration.

Validation: 31 store search tests, ten composite tests and two author-policy tests passed in release mode.
2026-09-05 01:42:39 +02:00
Admin
97912796a8 render: support rigged models and custom materials across viewers
Add declarative CSG joints, bindings and clips, custom render materials, and skinning/lightmap updates. Update shared media and XR viewers, including splat visibility and optional mesh HUD.

Validation: 400 release render tests and seven CSG rig tests passed.
2026-09-05 01:42:39 +02:00
Admin
1be1e2153c ai-hub: gate downloads by disk capacity and recover fleet admission
Account for missing and partial model files per volume, reserve headroom, and reject disk-constrained workers before accepting a job. Preserve typed admission failures so callers can choose another peer, and make activity gating and cancellation recover cleanly.

Validation: 592 release hub tests passed, one ignored; required-CUDA builds deployed to six idle Windows workers.
2026-09-05 01:42:38 +02:00
Kevin Boos
a13034d85d
wayland: stop inverting the scroll direction (#1216)
* wayland: stop inverting the scroll direction

Wayland's wl_pointer axis values already carry Makepad's scroll
convention -- positive vertical means scroll down, i.e. the viewport
moves down. The backend negated them, so wheel and touchpad both
scrolled backwards relative to X11, macOS, Windows and web.

The spec pins the sign in wl_pointer::axis_relative_direction, whose
`identical` case is a user's fingers moving down producing a
"vertical_scroll down" axis event. libinput, which produces the values
compositors forward, documents the same: "the positive direction being
down or right". Makepad's own convention matches -- ScrollBar applies
`scroll_pos + e.scroll.y` against a position clamped to
[0, view_total - view_visible], and the turtle draws content at
`origin - layout.scroll` inside a clip rect fixed at the unshifted
origin, so a positive delta moves the viewport down.

The negation came from #875, which read a positive axis value as content
sliding down and cited winit's negation as precedent. But winit's
MouseScrollDelta is documented as positive = content moves down, the
inverse of Makepad's convention -- winit's own comment reads "Wayland
sign convention is the inverse of winit" -- so copying it was a double
negation. Whether a toolkit negates is decided by its own convention,
not by anything about Wayland: GTK, which shares Makepad's convention,
passes the values through; SDL and Chromium negate because theirs are
inverted, and SDL negates vertical only, which is self-consistent just
in case Wayland's +y is down and +x is right. #875 also cited the web
backend as agreeing, but web forwards DOM deltaY unnegated, and deltaY
is positive when scrolling down.

The AxisDiscrete and AxisValue120 handlers added later inherited the
sign, so all six sites flip together; the spec states each expresses its
direction along the same axis as the coupled axis event.

Natural scrolling needs no client-side handling. libinput applies it in
evdev_notify_axis_*, below the compositor, so the delivered axis value
already reflects the user's setting -- the negation was not implementing
that, it inverted both settings equally. AxisRelativeDirection stays
ignored, which is correct for scrolling content; it exists so widgets
that should track the physical wheel regardless of the setting (the
spec's example is a volume slider) can recover the direction.

Fixes #1173

* wayland: classify the scroll source, and choose each axis's delta on its own

Five defects in the wl_pointer frame handler, adjacent to the sign fix in
the previous commit but independent of it.

The detent-vs-pixel choice was made once for both axes, so a frame
carrying detents on one axis and only a smooth value on the other scaled
that second axis by a zero detent count and silently dropped it. Each
axis now chooses on its own.

`scroll_is_wheel` collapsed a five-valued classification into "Wheel vs
everything else", and its false default meant "finger gesture". So a
wheel tilt discarded its detents, a continuous source — a trackpoint, or
button-held scrolling — was reported as a touchpad gesture, and so was a
frame from a compositor that sent no axis_source at all, the event being
optional and sent only when the source is known. That default is the one
classification that can strand a widget: ScrollPhase::Ended is what
springs a stretched rubber band back, only a finger source is guaranteed
an AxisStop, and the spec tells clients to treat every other source as
unterminated by default. The bool gives way to the source itself, and a
sourceless frame is classified by whether it carried detents.

A bare AxisStop no longer dispatches for a source with no gesture to end.
Compositors stop an axis whenever its value reaches zero, whatever the
source, and a zero-delta ScrollPhase::None clears a widget's overscroll
and cuts short a running bounce.

Nor is a stop arriving alongside live motion treated as lift-off. Per the
frame event: "When a wl_pointer.axis and a wl_pointer.axis_stop event
occur within the same frame, this indicates that axis movement in one
axis has stopped but continues in the other axis." And because
axis_source is per-frame and optional, a gesture in flight now carries
its classification forward, so a lift-off frame that omits the source
still ends the gesture instead of losing the terminator.

The raw-pixel fallback for an axis without detents stays unscaled, which
is a deliberate non-change rather than an oversight. No units-per-detent
constant exists to scale it by — compositors disagree, and hwdb ships
wheels from 10 to 30 degrees per click — and a physical wheel never
reaches it: the fallback is for virtual pointers, whose axis value the
protocol already defines as a distance.

Finally, the claim that ScrollPhase::Ended lets widgets run their own
momentum fling was wrong. Widgets start their fling on
ScrollPhase::Momentum, which only macOS emits, so Wayland touchpads have
no kinetic scrolling at all; the comment now says that rather than its
opposite.

The frame decision moves into `frame_scroll`, which puts every case above
under a unit test instead of leaving it to be re-derived by reading.
2026-09-05 00:18:26 +02:00
Admin
39a1b742ac flow-ui: a locked run's pictures and clips still take clicks — the viewer opens from the Output card again; only the inputs stay inert
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 21:17:11 +02:00
Admin
6f2fdfa861 flowgraph: a wire between nearly level ports takes the short run instead of a trip around the card (the fillet rule rejected any interior segment under two radii); fewer bends win only among routes of comparable length; six screenshot fixtures and the routing review
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 21:07:02 +02:00
Admin
1181a3bae4 flow + flow-ui + widgets: every creator pipeline is a template — 55 templates in six groups (Image, Video, Audio, 3D, Vision & text, Utilities), all evaluated and engine-exercised in tests; the New picker, the flows.templates tool and the palette group the same way; the Templates menu shows them under group headings, and a menu taller than the window scrolls
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 21:03:54 +02:00
Admin
2b4bff9a38 widgets + flow-ui: menu entries fire again — the bar's Closed action no longer hides the Selected one behind it, and an open menu takes pointer and key input before the panels beneath its popup
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 20:54:18 +02:00
Admin
30575f082d flow: route generation by request workload
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WV6BzHQiJEvvK9EPc1d4ks
2026-09-04 20:27:00 +02:00
Kevin Boos
c5fb78ba09
wayland: client-side decorations that cast a real shadow (#1215)
Makepad windows on Wayland had no drop shadow, which on GNOME reads as
broken next to everything else on the desktop. Mutter implements no
server-side decoration protocol at all -- it advertises neither
zxdg_decoration_manager_v1 nor any KDE equivalent, and its shadow code
(MetaShadowFactory) lives in src/x11/ and isn't even in the
introspection surface. Every shadow on that desktop is drawn by the app
that owns the window.

So draw one, out of eight wl_subsurfaces hung outside the toplevel: four
corner tiles and four edge strips, backed by one memfd wl_shm pool and
sized with wp_viewport, with xdg_surface.set_window_geometry keeping them
out of the window's logical bounds. GTK instead oversizes its own surface
and paints the shadow into a transparent margin. Subsurfaces keep the GL
surface exactly window-sized, so the shadow costs no per-frame GPU fill,
and no margin ever crosses the platform/widget boundary -- which is the
entire class of off-by-a-margin bugs the other approach invites.

The profile is libadwaita 1.9's, computed rather than sampled. A
rectangle's Gaussian shadow is separable, so each box-shadow layer's 2-D
coverage is the product of two 1-D normal CDFs, and evaluating that for a
*square* rectangle is what makes the corners hug the window: sampling a
rounded window's shadow gives 14/255 where a square corner needs 44/255,
and fades the edge out over the last 20px before every corner. The
straight-edge profile this produces matches a capture of the real
libadwaita output to within 1/255, which is what the test pins. Corner
tiles reach 16px along each edge, far enough that they join the strips
bit-identically at any scale.

Resizing happens in the gutter, the way it does for every native app.
The shadow surfaces carry input regions whose union is the window rect
grown by 12px -- the same halo libadwaita gives its toplevels -- and each
piece maps to exactly one edge, so landing on a surface is the hit test.
Window controls no longer compete with the corner grabs for the pointer,
which is what let the close button swallow the top-right corner.

Server-side decorations are requested wherever a compositor offers them,
overridable per process with --wayland-decoration= or
MAKEPAD_WAYLAND_DECORATION, and fall back to the frame above. KWin and
wlroots grant them; GNOME cannot.

Alongside, the caption bar gains double-click-to-maximize, a right-click
window menu, resize cursors keyed off the wl_pointer.enter serial the
protocol actually asks for, and tiled/constrained edges that suppress the
grabs they cannot service -- degrading a corner to its free axis rather
than dropping it.

Finally, declare the toplevel's opaque region, under the same
`!transparent && backdrop == None` condition macOS already uses for its
layer's opaque flag. The buffer is ARGB8888, so without that promise a
compositor cannot learn the alpha is uniformly solid short of reading
every pixel: it must blend the whole window, cannot cull what the window
covers, and cannot scan a fullscreen buffer out directly.

Verified against a WAYLAND_DEBUG trace: over 67 committed frames the
shadow issues no protocol traffic at all, and set_window_geometry,
set_opaque_region and the nine wl_regions are each sent and destroyed
exactly once.
2026-09-04 20:23:43 +02:00
Admin
b0b0e41da0 flow-ui: select runs from the whole queue row
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WV6BzHQiJEvvK9EPc1d4ks
2026-09-04 20:15:05 +02:00
Admin
f3b6c2f36c Merge branch 'work' into webdemos 2026-09-04 20:13:43 +02:00
Admin
778dbb8fc7 flow: accept bodyless 204 responses
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WV6BzHQiJEvvK9EPc1d4ks
2026-09-04 20:12:49 +02:00
Admin
8f51704697 flow-ui: a Templates menu on the bar lists every template the server serves; choosing one creates and opens a flow from it
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 20:09:13 +02:00
Admin
f45793a8fa vj: batch live video publishes into grid rows 2026-09-04 17:47:47 +02:00
Admin
28016ca897 vj: keep generated clips at the head of the grid 2026-09-04 17:41:18 +02:00
Admin
2a064d3928 workspace: add loader, haptics, voice, and runtime fixes 2026-09-04 17:39:41 +02:00
Admin
acd23289c6 flow + flow-ui: a cancelled run clears its cards and bars at once and its live nodes read cancelled; layout edits (move, size, flip) work while a run is shown; the queue row is one centre line — name, strip, state · time, x
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 17:24:17 +02:00
Admin
a6c5f15bf7 widgets: FabValueInput honours visible, so the seed picker's random mode hides the number field
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 15:04:50 +02:00
Admin
767e260b97 flow + flow-ui: parallel runs — random seeds with a die, a fleet parallelism estimate (generation nodes bound it; the chat box never caps the image fleet), batch routes, the Run dropdown (1 / max · N), Ctrl+Enter queues a run, and the Running panel becomes a Queue of every run with per-row and per-batch cancel and Clear all
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 15:01:15 +02:00
Admin
bf9418e2bc vj: ironfish / synth rack, program mix, and a clean release check
Clocked piano/ironfish/drum rack, program-bus mix, splat/mixer/music
updates. Silence the unused warnings that show up in `cargo check -p
makepad-vj --release`.
2026-09-04 14:54:07 +02:00
Admin
b37b1168fd media_view: the video, audio, mesh and splat viewers leave asset-ui for one crate; flow-ui shows every media type on the Output card and in the modal viewer
ViewSplat gains a typed set_scene_bytes so a viewer inside a face isolate never needs a script apply; MeshView gains visible.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 13:49:32 +02:00
Admin
a7774885a1 flow + flow-ui + flowgraph: the loaded flow is the editable design (Input.value lives in the file); Play clones it into a numbered locked run instance with a Design button back; inspector text rows follow the graph
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 13:37:38 +02:00
Admin
c71d6392f9 flow + flow-ui + flowgraph: a stale keep-alive is replayed on a fresh socket; a palette drop rewrites the file text so the new card mounts; the progress bar is centred in the header and inset past the corners
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 13:27:21 +02:00
Admin
7e397cf31e flow + flow-ui: Publish end node writes to the asset library; Assets tab in the Inspector; prompt-to-library template
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 13:27:21 +02:00
Admin
9a31d2104a flow-ui + widgets: a chosen model shows no node list, and a closed ComboBox shows the start of a long label
The picker's own label counts the ready nodes, so the GPU list under a
chosen model was clutter; it stays only for a model no node can serve,
where it names why. A closed ComboBox reset its text field to the tail of
the label after set_text; the cursor now sits at the start.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 12:03:50 +02:00
Admin
24c927ad7e flow-ui + widgets: every dropdown is the searchable ComboBox
Model and format pickers, the inspector's one-of rows, the Ask face's
choice and face-declared pickers all render as ComboBox; the popup and
its input map through the canvas zoom. ComboBoxRef gains changed_label
and set_selected_by_label so the bindings did not have to change shape.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 12:01:42 +02:00
Admin
d20a20871a flowgraph: a routed wire turns right after its port and hugs its own card
The straight run out of a port is 10 px (8 px minimum) with the endpoint
fillets shrinking to fit, and the first and last vertical runs keep only
the narrow 6 px envelope from the wire's own card; other cards keep the
two-tier clearance and parallel wires keep their cable spacing.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 11:48:58 +02:00
Admin
30ef92597f flow-ui: the image generator card shows only its settings; the picture lives on the Output card it feeds
The generator's own preview was clutter next to the Output card's
picture. The Image face drops its preview and generator cards are no
longer full-bleed; the two picture tests follow the picture to the
Output card.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 11:35:05 +02:00
Admin
5863c43eb1 flow-ui: an input card is one text area filling the card, with no name beside it
The host wrapped every bound face control in a labelled row, so the
prompt card showed a "value" label beside a fixed-height box. A
multi-line text area is now its own row and follows the card's size.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 10:48:03 +02:00
Admin
cff15ac045 widgets: a fab number field drops a label that cannot fit instead of crushing it to a dot
A 54 px width chip left the "w" label one pixel column, which rendered
as a stray dot beside the number.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 10:43:12 +02:00
Admin
2a5172465c flowgraph + flow-ui: two wire modes never mixed — bezier or routed — and routed wires use narrow gaps
Routed mode never falls back to a curve: a wire with no corridor takes the
least-collision orthogonal path. Clearance is two-tier: the comfortable
12 px card clearance with 16 px fillets first, then 6 px per side with
8 px fillets, so a routed wire passes a 20 px gap. Bezier mode is a pure
cubic per wire. View → Wires switches the mode (in-process until the app
has a settings store).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 10:43:12 +02:00