Skip to content

feat(theme): ThemeHost and the live theme editor — layered live reload, role saves, themed surface chrome - #35

Merged
fts-forge[bot] merged 23 commits into
mainfrom
feat/theme-host-live-editor
Nov 4, 2026
Merged

fts-forge[bot] merged 23 commits into
mainfrom
feat/theme-host-live-editor

Conversation

@fts-forge

@fts-forge fts-forge Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

Frame's runtime theme engine, as Studio uses it locally (studio#377). Includes #31 (the `frame.surface` view kind), which this line was built on; merge that first or close it in favour of this.

  • ThemeHost (`crates/frame/src/theme/host.rs`): layered themes, last-good live reload, versioned publication, agent actions; host-rendered slot geometry and target hit testing (ThemeHost: live theme editing, agent actions and host-rendered slots #33).
  • frame-doc / frame-editor: Frame data on figcraft nodes; editor documents compile as themes and publish to a ThemeHost safely; the background live theme editor selects and edits roles and saves them to their source layers (`docs/theme-save-concurrency.md` states what the save does not yet guard against).
  • fix(frame-doc): fontique 0.12 aligned to `fontconfig-dlopen` on Linux where figcraft enters the graph — `cargo check --workspace` failed with unresolved `FcCharSet*` imports; consumers (Studio) no longer carry the workaround.
  • frame-view: the surface pane's heading, notes and buttons read the host's CSS variables (architect puts the app's live `:root` theme into a process view's document), so the pane follows the app's theme.

Checked locally against architect/Studio/Keyflow local checkouts: `cargo check --workspace --all-targets`; frame-surface drawn in architect's lab in a real window, following light and dark themes; Studio's themed window reskinned and live-reloaded.

Open: the cooperative save lock (designed, not built); lowering is not incremental (85.7 ms for 2,000 rectangles).

🤖 Generated with Claude Code

fts-forge Bot and others added 23 commits November 2, 2026 02:09
…rchitect#224)

A process extension (frame-surface) whose view, of the frame.surface
kind, is a knob and a meter from a Frame document (surfaces/knob-meter.frame)
drawn as an inline svg; FRAME_SURFACE_SET / FRAME_SURFACE_STATE move and
read it. Architect's lab shows it in its Embedded views gallery (STA-653).

Co-Authored-By: Claude Code <noreply@anthropic.com>
…loaded (architect#224)

frame-surface now shows a Frame document rather than a fixed knob and
meter. The document's controls say what moves it: each param-bound control
is a param, each stream-bound control a feed (`surface::catalog_of`).

- FRAME_SURFACE_LOAD {path} shows a `.frame` file and watches it; a save
  reloads it, keeping the values of the params and feeds it still has. A
  save that does not parse keeps the surface and reports why in `error`.
- FRAME_SURFACE_PARAM_SET {addr, value} and FRAME_SURFACE_FEED {id, values}
  move it; FRAME_SURFACE_STATE reads it. These are Action List actions, so
  MCP and the CLI drive them.
- The view's knob can be dragged; the drag moves the param.
- FRAME_SURFACE_DOCUMENT loads a document at start-up.

Co-Authored-By: Claude Code <noreply@anthropic.com>
…#7)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ene (frame#8)

Frame's surface data (controls, bindings, slots, motion, shaders, emission)
rides on figcraft `Node::plugin_data` under `frame:*` keys as JSON of the
proto types; no fork patch.

- keys: the frame:* key set.
- data: FrameData (typed parse, bad JSON reads as absent with an error),
  FrameCache (per node revision via Arc identity), effective/effective_map
  (instances inherit from their main through `source`; overrides held on
  the instance root survive engine rebuilds), set_data, slot marks on slot
  nodes (so copies drive their own copies), slot_index, control_of,
  controls (all controls with one index).
- convert: scene_to_doc / doc_to_scene; v1-only values kept as a per-group
  shadow (frame:v1) that gives way when the figcraft side is edited.
- tests: round trip of every parity scenario and plugin face; frame data
  semantics; engine-level copy/paste, duplicate and component/instance
  tests in frame-editor; #[ignore] parse-cost benchmark (500 controls).

Release benchmark: cold read 1.86 ms (budget 8 ms), warm 0.11 ms (budget
1 ms): within budget, no typed slot needed on fts.

Co-Authored-By: Claude Code <noreply@anthropic.com>
# Conflicts:
#	Cargo.lock
#	Cargo.toml
#	crates/frame-doc/Cargo.toml
#	crates/frame-doc/src/lib.rs
#	crates/frame-editor/Cargo.toml
#	crates/frame-editor/src/lib.rs
#	docs/figcraft-fork.md
…re figcraft enters

figcraft's font catalog enables yeslogic-fontconfig-sys/dlopen through
fontique 0.11; Cargo unifies it with the fontique 0.12 Blitz links, which
then fails to build (unresolved FcCharSet*/FcConfig* imports) in any graph
that has both, e.g. `cargo check --workspace`. Consumers no longer carry
the workaround.
Its heading, notes and buttons use architect-ui's CSS variables
(--foreground, --muted-foreground, --border, --secondary, --destructive),
with today's colours as fallbacks. architect puts the host's live :root
sheet into a process view's document, so the pane follows the app's
theme.
@fts-forge
fts-forge Bot merged commit 1f6311a into main Nov 4, 2026
4 checks passed
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.

0 participants