# Architecture and dependency contract

Status: M1 core plus M2 layout/element and M3 headless scene package boundaries are implemented; experimental macOS, Ubuntu/Wayland/GLES (including bounded grayscale text frames), and Windows native slices are present; the JS browser hosts Weekboard and the retained interaction lab with its in-process capability/MCP seam; a separate Node stdio fixture exercises the stateless MCP wire adapter; native and browser MCP endpoint topology remains planned.

This is the dependency and package boundary for M1 through M5. The module is `f4ah6o/gpui` in [`moon.mod`](../moon.mod), with current runtime packages `primitives/`, `diagnostics/`, `core/`, `layout/`, `scene/`, `element/`, `text/`, `text_layout/`, `app/`, `capability/`, and optional `mcp/`, plus native and example adapters. The lifecycle and entity semantics are in [product.md](product.md), while implementation evidence is tracked in [compatibility.md](compatibility.md).

## Runtime dependency budget

The published gpui.mbt runtime may depend on:

- the MoonBit language runtime and MoonBit standard/core packages;
- packages implemented in this repository;
- native operating-system APIs behind a gpui.mbt-owned backend and narrow FFI boundary.

No third-party MoonBit package is a runtime dependency by default. The current runtime packages import only MoonBit standard/core and repository packages. If a required facility is missing from standard/core, first write a narrow internal contract, implement the minimum behavior here, and test it independently. Reconsider extraction only after gpui.mbt has exercised the API. Do not vendor a general-purpose dependency merely to save initial implementation effort.

Development and CI tools are separate from the runtime graph. The initial allowed tools are `moonbitlang/quickcheck` for properties, `f4ah6o/turtles` for mutation testing, optional `mizchi/vlmkit` for external artifact review, Playwright for browser tests only, and the required platform CI tools. None may be imported by the published runtime packages. Their exact locked revisions, licenses, and transitive graphs belong in the development dependency audit.

For every release candidate, archive a machine-readable dependency inventory for runtime and development graphs separately. The audit must show direct and transitive MoonBit packages, target-specific native libraries, resolved revisions, license identifiers, and the package that introduced each dependency. Any native library must additionally name its platform, purpose, FFI owner, upgrade source, and failure behavior. A new runtime dependency requires a written exception in this document and a compatibility/release review; there is no implicit exception for the upstream Rust GPUI dependency list.

## Package direction

The intended dependency graph is acyclic and points from application-facing concepts toward lower-level contracts. M1 package names and their allowed imports are fixed as follows:

```text
application API / facade
  ├── core ──────────────> diagnostics ──> primitives
  │       └─────────────────────────────> primitives
  ├── element ──> layout ───────────────> primitives
  │      └──────> scene ────────────────> primitives
  └── platform API ──────> core + diagnostics + primitives
          └──────────────> renderer API ──> scene + primitives

semantic capability ──> core + diagnostics
optional MCP adapter ──> semantic capability + diagnostics
migration host-service bridge ──> semantic capability + diagnostics

target backend ──> platform API + renderer API + scene
target FFI     ──> native OS / graphics / text APIs

primitives ──> MoonBit standard/core only
text ─────────> MoonBit standard/core only
text_layout ──> text + primitives + MoonBit standard/core
platform/linux_text ──> text_layout + text + primitives + Linux PangoFT2/Fontconfig FFI
ubuntu ──private raster ABI──> platform/linux_text
ubuntu ──UTF-16 validation──> text
ubuntu ──headless semantic projection──> accessibility
examples/ubuntu_button ──transport-free adapter──> ubuntu + accessibility + button fixture
diagnostics ─> MoonBit standard/core + primitives
core       ──> MoonBit standard/core + diagnostics + primitives
```

The facade is a re-export surface; it must not contain a second implementation of lower-layer behavior. `core`, `geometry`, `layout`, `element`, `scene`, and renderer/platform contracts remain platform-neutral. A concrete backend may depend on these contracts, but no lower layer may import a concrete backend, renderer, OS handle, or native FFI type. `scene` contains portable draw data, not GPU resources. The renderer API consumes scene data and exposes framework-level resource and failure categories. Only the backend owns windows, event-loop integration, display information, clipboard, cursor, menus, accessibility bridges, text services, GPU surfaces, and native resources.

## Layer responsibilities and allowed edges

| Layer | Owns | May depend on | Must not expose |
|---|---|---|---|
| `primitives/` | IDs-independent geometry, color, input, and event value types | MoonBit standard/core only | app-owned IDs, state, platform handles |
| `diagnostics/` | shared error categories and structured diagnostic values | MoonBit standard/core, `primitives/` | concrete backend types and framework state ownership |
| `app/` | reusable single-window `WindowView` runtime, sampled metrics, frame validation, close/exit policy, bounded ticks, after-present/idle hooks | `platform/`, `scene/`, `diagnostics/`, `primitives/` | native handles, concrete backend types, or demo state |
| `core/` | app/entity/task IDs, App/Entity/Context, lifecycle, subscriptions, deterministic foreground scheduler | MoonBit standard/core, `diagnostics/`, `primitives/` | window, OS, GPU, renderer, or concrete backend types |
| `examples/headless/` | consumer usage example and executable API example test | public `core/`, `diagnostics/`, and `primitives/` interfaces | runtime imports, native/platform APIs, private core types |
| `examples/browser_app/` | host-neutral interaction-lab model, event processing, flex layout, hit testing, and portable scene fixture | `core/`, `diagnostics/`, `element/`, `layout/`, `platform/`, `primitives/`, `scene/`, `capability/`, `mcp/` | DOM, Canvas, JS references, browser or native handles |
| `examples/browser/` | JS-only adapter translating browser callback values to framework events | `examples/browser_app/`, `diagnostics/`, `platform/`, `primitives/` | browser handles in shared packages or browser-to-model reverse dependencies |
| `examples/task_board/` | portable Weekboard task state, filtering/history, input, responsive flex layout, clipped hit testing, scrolling, drag gestures, and quad/text scene data | `capability/`, `core/`, `element/`, `layout/`, `platform/`, `primitives/`, `scene/` | DOM, Canvas, JS references, browser or native handles |
| `examples/browser_board/` | JS-only Weekboard exports over copied input, scene, status, and host-layout values | `examples/task_board/` | browser handles in shared packages or reverse dependencies from the task model |
| `layout/` | style subset, constraints, intrinsic measure interface, layout result | `primitives/` | renderer or platform types |
| `element/` | Render/IntoElement/Element, tree, hit-test and dispatch metadata, immutable scroll state and drag gesture transitions | `core/`, `primitives/`, `layout/`, `scene/` contract | backend callbacks or OS event structs |
| `scene/` | stable, platform-neutral quad/clip commands, bounded text snapshot items, validation, and ordering | `primitives/` | live GPU handles or backend resource objects |
| `text/` | UTF-16 ranges, directional selection, immutable documents, and composition transitions | MoonBit standard/core only | rendering, platform, or host-input types |
| `text_layout/` | Portable intrinsic text-measurement request/results and copied layout/caret/hit geometry | `text/`, `primitives/`, MoonBit standard/core | Pango/Fontconfig objects, native handles, GUI/session state |
| `platform/linux_text/` | Linux-only implementation of portable text-layout measurements, copied UTF-8/UTF-16 caret/hit results, and a private grayscale A8 mask raster ABI | `text_layout/`, `text/`, `primitives/`, MoonBit standard/core, Linux PangoFT2/Fontconfig via FFI | shared window `platform/` API, concrete backend, public renderer API, native object pointers, or persistent Pango handles |
| `capability/` | typed semantic operation descriptors, schema/value projection, registry, GUI binding, deterministic manifest generation | `core/`, `diagnostics/` | renderer/native/MCP transport state, host handles, duplicated domain handlers |
| `mcp/` | optional MCP-facing inventory/dispatch adapter over semantic capabilities | `capability/`, `diagnostics/` | application state ownership, domain handlers, privileged host APIs |
| `migration/host_services/` | portable service requests/completions, logical scopes, cancellation, bounded queues, and default-deny service policy for Electron/Tauri migration | `capability/`, `diagnostics/` | DOM, process APIs, native handles, or direct privileged service execution |
| `renderer API` | render submission and resource-lifetime contract | `scene/`, `primitives/` | a concrete renderer vocabulary in public app APIs |
| `platform API` | window, input, display, text, clipboard, timer, accessibility contracts | `core/`, `diagnostics/`, `primitives/`, renderer API | platform-specific types in core/facade signatures |
| `platform/` (first slice) | shared Backend trait, logical window IDs, copied ordered events | `scene/`, `diagnostics/`, `primitives/` | native pointers or OS types |
| `ubuntu/` | Wayland host/window, integer scale, basic input, EGL/GLES quad and bounded grayscale text renderer; headless semantic-model projection without an OS bridge | `platform/`, `scene/`, `diagnostics/`, `primitives/`, `text/` for UTF-16 validation, `accessibility/` for semantic projection, private `platform/linux_text` raster ABI, system native APIs | native handles in public application signatures; Pango objects; an OS accessibility bridge |
| `x11/` | experimental one-window Xlib/EGL host, direct keyboard/Compose and bounded UTF8 clipboard; logical scale 1 | `platform/`, `platform/testing/`, `scene/`, `diagnostics/`, `primitives/`, `text/`, private Linux text/renderer C ABI, system X11 APIs | native handles in portable APIs; Wayland backend dependency; IME or OS accessibility claims |
| `examples/ubuntu/` | native executable consuming the shared scene/window contracts | `ubuntu/`, `platform/`, `scene/`, `diagnostics/`, `primitives/`, standard env | private backend tokens |
| `examples/ubuntu_button/` | native Button executable plus in-process semantic adapter | `ubuntu/`, `accessibility/`, `examples/ubuntu_button/fixture`, `platform/`, `scene/`, `diagnostics/`, `primitives/`, standard env | D-Bus/AT-SPI transport or OS-accessibility claims |
| `windows/` | Win32 window/event loop, scale events, basic input, D3D11 hardware-or-WARP quad presentation, and transport-free copied accessibility snapshots | `platform/`, `scene/`, `diagnostics/`, `primitives/`, `accessibility/`, Windows system APIs | native handles in public application signatures; UI Automation transport or screen-reader qualification |
| `examples/windows/` | native executable consuming the shared scene/window contracts | `windows/`, `platform/`, `scene/`, `diagnostics/`, `primitives/`, standard env | private backend tokens |
| `examples/windows_button/` | Win32/D3D11 Button fixture composed with the shared Button owner and a session-owned copied semantic binding | `windows/`, `platform/`, `accessibility/`, `primitives/`, `scene/`, `diagnostics/`, `examples/ubuntu_button/fixture/` | native UI Automation provider or physical-input qualification |
| `platform/windows_text/` | Windows DirectWrite copied single-line geometry and private bounded grayscale mask adapter | `text_layout/`, `text/`, `primitives/`, Windows DirectWrite APIs | native handles or shaping objects in portable values |
| `platform/windows_app/` | reusable Windows application helpers over the `windows` backend: bounded scene-label measurement, `TextField` callbacks, cursor state, and one-window startup | `app/`, `controls/text_field/`, `platform/`, `windows/`, `platform/windows_text/`, `primitives/`, `scene/`, `text/`, `text_layout/` | native window/GPU handles in portable values; a new renderer or support tier |
| `examples/windows_text_field/` | native focused single-line field and opt-in private IMM32 composition example | `windows/`, `platform/windows_text/`, `controls/text_field/`, `text/`, `text_layout/`, `element/`, `platform/`, `scene/`, `diagnostics/`, `primitives/` | public text-input capability or a qualified Japanese IME claim |
| `examples/windows_command_palette/` | native Ctrl+K command-palette fixture with bounded search and opt-in private IMM32 ownership | `windows/`, `platform/windows_text/`, `controls/command_palette/`, `controls/text_field/`, `text/`, `text_layout/`, `element/`, `platform/`, `scene/`, `capability/`, `diagnostics/`, `primitives/` | UI Automation transport or a qualified Japanese IME claim |
| target backend / FFI | event loop and native resources/adapters | platform and renderer APIs; native APIs | types that leak upward through the public facade |

The current runtime edges include `primitives -> stdlib`, `text -> stdlib`, `diagnostics -> stdlib`, `core -> stdlib + diagnostics`, `capability -> core + diagnostics`, `mcp -> capability + diagnostics`, and `migration/host_services -> capability + diagnostics`; the executable allowlist also records current layout, scene, element, native, and example edges. The browser app fixture is portable and can use the semantic registry plus an in-process optional MCP dispatch seam; the JS host adapter remains a leaf above it. The host-service bridge queues bounded JSON-compatible requests and completions over copied framework values; browser/Electron/Tauri adapters must enforce their own permission and host allowlists before acting. The executable dependency check covers these boundaries and test-only imports; new runtime packages still require an explicit layer entry and reject unlisted edges. The dependency direction must remain acyclic; cross-cutting code belongs in a lower-level contract rather than a reverse import.

The `text/` package is a pure immutable value model. `TextComposition` retains
the original document and target range, rebuilds every preview from that
original pair, maps relative UTF-16 selection endpoints into the resulting
document, and yields a committed or cancelled value. `TextDocument` also
provides strict UTF-16/UTF-8 scalar-boundary conversion; each conversion is an
O(n) scan with overflow-checked UTF-8 byte counts and no cached offset table.
It provides no mutable session owner, event sequencing, freshness guarantee,
undo history, grapheme segmentation, host adapter, layout, caret geometry, or
rendering. Host owners must enforce their own event ordering and ownership
rules.

The approved `capability -> core` edge consumes only the portable application
lifetime contract. `core` never imports capabilities, MCP, or platform code.
See [capability owner lifecycle](capability-lifecycle.md) for creation/adoption,
pre-start readiness, synchronous stop invalidation, and reentrant completion
semantics. This adds no third-party runtime dependency.

The optional MCP package generates transport inventory, projects each schema
to the modern MCP object-shaped tool contract, and routes wire calls back
through the same typed registry and domain handlers. Its stateless protocol
router implements discovery, tools, and query resources for MCP revision
`2026-07-28`. The checked JavaScript stdio fixture hosts that router as a
newline-delimited JSON-RPC subprocess; native and browser transport hosts,
prompts, legacy initialization, and interruption of running synchronous
handlers remain outside this adapter slice. See the [MCP adapter guide](mcp-adapter.md).

## Async and application scheduling

M1 implements a small synchronous app-executor scheduler, not a general asynchronous runtime. It defines the following observable behavior:

1. `App::dispatch` and zero-delay `schedule_after` tasks join one FIFO immediately when submitted. A foreground task receives only a `TaskContext`; entity mutation uses a separate `App::update` callback and scoped `Context`.
2. A task has one terminal state: `Completed`, `Cancelled`, or `Failed`; its observable path is `Queued -> Running -> terminal`, with `Queued -> Cancelled` allowed.
3. Cancellation clears queued callback state before it can run. Cancellation of running work is cooperative; it sets a token and cannot forcibly stop a function. A canceled task cannot deliver a success result.
4. Delayed timers use a manually advanced monotonic `UInt64` clock in tests and in the current core contract. Advancing the clock promotes due timers in deadline order, then registration order, appending them to the FIFO. Wall-clock reads are outside `core/`.
5. M1 has no background worker or executor. A later platform/backend package may add one, but it must accept immutable inputs, carry no `Context`, `Window`, or mutable entity reference across the boundary, and post completion back to the app executor. Tests must inject completion order.
6. `run_ready(budget)` processes no more than the requested count, rejects a negative budget, and cannot be called recursively or from an active read/update callback. Shutdown rejects new tasks, cancels queued tasks, requests cancellation from the running task, and queues entity teardown after the active callback.
7. Cancellation is normal control flow. Other task failures are wrapped as `TaskFailure`, preserve source code/operation/message context, and are available from both `Task::failure` and `App::diagnostics`.

The current executor uses an in-repository FIFO and deterministic timer list. Native loop wakeups, background execution, and timer integration remain future private backend responsibilities. The headless scheduler and state-machine tests run without a window server or GPU.

## Initial layout boundary

The first layout engine supports a deliberately bounded flex subset. It does not claim CSS or full GPUI style compatibility. The `layout/` package implements deterministic layout for a definite row/column container in `nowrap`, `wrap`, or `wrap-reverse` mode, including points/percent/auto child dimensions, two-axis gap, padding/border, line-local grow/shrink, main-axis min/max redistribution, cross-axis clamping, justification/alignment, stable child order, and explicit overflow reporting. Recursive flex-tree layout is available beneath a definite root viewport. The `element/` package exposes immutable element builders, open `Render` and `IntoElement` traits, and a headless request-layout → prepaint → paint path: request-layout resolves the recursive boxes, prepaint builds the live hit-test tree, and paint emits the current quad scene. Wrapped line formation is greedy from clamped hypothetical main sizes plus the main-axis gap; each line then resolves flex distribution independently. Cross-axis lines use configurable start/center/end/stretch content alignment, with stretch as the default, and independent start/center/end/stretch item alignment. Start/end content alignment is flex-relative under wrap-reverse; explicit modes keep signed overflow, while default stretch retains safe physical-start overflow placement. Recursive auto-sized containers still measure using the existing no-wrap flow-axis approximation rather than measuring wrapped lines. Other nested auto sizes measure their flow axis from child bases and gaps, and their cross axis from the maximum child size; insets and min/max bounds are applied. Percentages against an auto-measured axis are rejected as indefinite, while orthogonal percentages against a definite axis remain supported. Element nesting is bounded at 64. The current recursive algorithm repeatedly scans its flat pre-order input and nested auto measurement can rescan descendants, giving quadratic worst-case work in node count; the depth bound protects stack use only, and performance has not been benchmarked. Intrinsic measurement callbacks, invalidation, and the broader style surface remain pending.

### Inputs and outputs

- Coordinates and resolved lengths are finite logical points represented as `Double`; device pixels and scale conversion belong at the renderer/backend edge. A roughly 32-binary64-epsilon scale-relative tolerance suppresses arithmetic residue in overflow and exact-fit comparisons; it does not quantize all values to GPUI's `f32` pixel precision, so ULP-scale line-break boundaries are not claimed as identical.
- Each node has a row or column flow direction, fixed or percentage dimensions, `auto` dimensions, a `nowrap`/`wrap`/`wrap-reverse` mode for definite containers, two-axis gap, padding, border widths, min/max dimensions (with `min <= max` required per axis), flex basis, non-negative flex grow/shrink factors, main-axis justification, cross-axis start/center/end/stretch item alignment, and start/center/end/stretch/space-between/space-around/space-evenly wrapped-line content alignment (default stretch).
- Width and height are measured as border-box dimensions. Padding and borders are removed before child layout. An inner dimension never becomes negative; excess insets produce a zero inner dimension.
- A child can supply an intrinsic preferred size through a platform-neutral measure callback. Text intrinsic measurement is provided by the text-system contract; layout does not estimate text from character count.
- Percentage dimensions resolve only when the containing dimension is definite. A percentage against an indefinite dimension is `InvalidInput`; it is not silently treated as zero or auto.
- `auto` on the flow axis takes the sum of child bases and gaps plus insets; `auto` on the cross axis takes the largest child cross size plus insets. Empty auto containers resolve to their insets.

### Distribution and excluded behavior

For a definite main-axis size, layout subtracts gaps and insets and resolves each child's basis. In wrapping modes, clamped hypothetical main sizes and the main-axis gap greedily determine line breaks before flexing; an oversized item remains alone and is then resolved on its own line. Each line applies the existing min/max freeze algorithm independently: constrained and inflexible children freeze, and subsequent passes distribute remaining space to unfrozen children by grow factors or `shrink * basis` weights, clamp them and freeze min/max violations. Every nonterminal pass freezes at least one child, so a line takes at most its child count in passes (quadratic worst-case work). Grow or raw shrink totals below one retain a share of the initial free space, with the pinned GPUI gap adjustment; freezing does not normalize partial factors into filling all space. Remaining space, including unavoidable overflow, uses the selected signed justification. Wrapped cross-axis line boxes include the cross-axis gap. `AlignContent::stretch()` is the default and divides positive remaining cross space equally among line boxes; `start()`, `center()`, and `end()` instead position their natural-size stack. Start/end are flex-relative, so `wrap-reverse` reverses their physical anchoring. Start/center/end retain signed overflow space. `space_between()`, `space_around()`, and `space_evenly()` preserve natural line sizes and distribute positive space as extra inter-line gaps, with half-sized outer space for around and equal outer space for evenly. The three distributed modes and stretch fall back to safe physical-start placement on overflow, including wrap-reverse. A fitting singleton stays at flex-start for between and is centered for around/evenly. `align-items` independently controls each child within its line. Both `FlexContainer` and `FlexTreeStyle` expose `with_align_content`; all builders and device-scale tree preparation preserve it. `nowrap` ignores content alignment. See the [bounded align-content contract](conformance-align-content.md) and [distributed-line extension](conformance-content-distribution.md). Margins, baseline alignment, flex order, CSS writing modes, min-content negotiation, and full GPUI style compatibility remain outside scope. Recursive auto-sized containers do not compute wrapped intrinsic dimensions. These limits and the pinned-oracle cases are covered by the [layout wrapping tests](../layout/flex_wrap_test.mbt) and [Linux flex-wrap corpus](https://github.com/gpui-mbt/gpui-conformance/blob/main/flex_wrap_scenarios.json). See also [the measured min/max comparison](conformance-flex-limits.md).

This subset does not model grid, absolute/fixed positioning, floats, percentage margins, arbitrary CSS units, intrinsic min-content/max-content negotiation, fragmentation, browser-specific style behavior, or the unlisted CSS/GPUI flex features above. The current input API has no representation for those features and does not promise to parse arbitrary styles or emit a typed unsupported-style diagnostic for them. Adding support requires contract and property tests before implementation.

Invalid or non-finite constraints are rejected before producing a layout tree. For valid input, identical constraints and intrinsic measurements produce identical logical bounds. Origins must be finite; lengths must also be non-negative, respect declared min/max constraints, and preserve source child order. Child overflow caused by fixed dimensions or an explicit minimum larger than available space is allowed and reported on either side of the content bounds; layout does not hide it by returning invalid geometry. The `layout` to `element` boundary returns IDs and logical bounds only, not platform objects.

## Scene and renderer boundary

Scene generation and pixel output are separate oracles. The current command stream emits quads and rectangle clip push/pop commands. `SceneSnapshot` v1 adds explicit clip-chain tables, transforms, opacity, and ordered `TextItem` values alongside quads. The bounded text item is copied plain text plus bounds, font size, color, transform, opacity, and clip reference; it does not carry a native font handle or implement an editable-control contract. Existing quad serialization remains byte-stable. The Canvas 2D host presents these text items using a system sans font and clips each run to its bounds. Ubuntu's GLES host presents a bounded grayscale subset through PangoFT2 masks; `platform.Capability::GrayscaleTextFrames` is a discovery flag, while each frame still undergoes unsupported/resource preflight and color glyphs reject the whole frame. Windows also presents a bounded LTR grayscale subset through DirectWrite and D3D11. macOS measures and presents bounded single-line grayscale text through CoreText, using copied logical/ink bounds and scalar cursor-stop geometry; its renderer caps fonts at 32 points and rejects unsupported text during frame preflight. These rendering capabilities do not advertise Windows public `TextInput` or establish shared editable-control parity. See [snapshot validation](../scene/snapshot.mbt), [text tests](../scene/snapshot_text_test.mbt), the [macOS native guide](macos-native.md), the [Linux text guide](linux-text.md#ubuntu-grayscale-scene-text), the [Windows native guide](windows-native.md), and [the Canvas renderer](../examples/browser/site/canvas-renderer.js).

The complete design also includes paths, images, richer text runs, and logical resource descriptors. IDs and serialized scene ordering must be deterministic for identical input. Image/font resources will use framework IDs plus validated descriptors, never raw GPU handles. Those broader resource and shaping contracts remain pending.

The renderer consumes scene values and reports typed outcomes for invalid resources, allocation failure, surface/device loss, and submission/presentation failure. The headless scene implementation supplies scene contracts; Ubuntu GLES and Windows D3D11 now present quads and their separately bounded grayscale text subsets. A shared software raster path may still be added for deterministic pixels, but pixel equality across native text/render stacks is not a cross-platform contract. Backend recovery and raster performance gates are specified in the platform and release packets.

## Native and unsafe boundary

Native calls are contained in target backend/FFI packages. Every boundary must document ownership, lifetime, nullability, encoding, threading, callback/reentrancy, failure mapping, and cleanup. A callback after logical destruction must be ignored safely and diagnosed. Public core values use framework IDs or copied data; native handles never escape through `App`, `Entity`, `Context`, `Element`, or scene APIs.

Prefer a narrow C ABI when it keeps platform types out of MoonBit package interfaces and simplifies ownership review. A backend cannot be promoted to a supported platform tier while it has undocumented native boundaries, aborts on a recoverable operation failure, or lacks teardown coverage.

## Dependency audit and merge checks

Every dependency addition must identify whether it is runtime, development-only, or platform-native and list its owning package. The executable package-boundary check fails if test tooling reaches a runtime package or an unreviewed third-party MoonBit package enters the runtime graph. Native library inventories are separate per target. Dependency review must also check version pinning, license notices, and the lockfile/toolchain reproducibility policy.

The [package-boundary check](../scripts/check_contracts.py) validates the current graph, including `scene -> primitives`, `element -> core/primitives/layout/scene`, the consumer-only `examples/headless/` package, and the one-way `examples/browser -> examples/browser_app` and `examples/browser_board -> examples/task_board` adapter edges. The task-board package may import only `capability/core/element/layout/platform/primitives/scene` plus standard/core. Checker regressions prevent the portable examples from importing their JS host layers. Current contract, dependency, format, build, and test commands are listed in [README.md](../README.md) and the [browser guide](browser-demo.md).

## Ubuntu native dependency exception

The first Ubuntu backend uses system Wayland/xdg-shell, EGL/GLES, xkbcommon and
libc/pthread behind `ubuntu/`. This narrow native exception and its dependency
inventory, licenses, upgrade sources and failure behavior are documented in
[ubuntu.md](ubuntu.md#native-dependency-inventory-and-exception). No portable
package imports the concrete backend. The executable package audit now permits
`platform -> scene/diagnostics/primitives`; `ubuntu` may depend on
`platform/scene/diagnostics/primitives`, `text`, `accessibility`, and the private
`platform/linux_text` raster ABI; the Ubuntu Button executable may consume
`accessibility` for its in-process adapter, alongside the native example edges
above. It audits aliased imports and whitebox test imports as well as blackbox
test imports. All other runtime dependencies continue to require a written
exception.

The experimental `x11/` leaf has the same portable scene/event contracts and
private Linux text raster dependency, plus system libX11 for native windows,
keyboard/pointer events and selection ownership. It shares bounded GLES2 frame
preflight/drawing with `ubuntu/` through private C includes under
`platform/linux_renderer/`; neither backend imports the other. X11 symbols are
namespaced separately so both leaves can be linked in one application. The
runtime checker permits only `platform`, `platform/testing`, `platform/linux_text`,
`text`, `primitives`, `diagnostics` and `scene` edges from `x11`. Portable core and
other lower layers cannot import it. [X11 scope and checks](../x11/README.md) record
one owner thread/window, scale 1, direct Compose versus unsupported IME, bounded
clipboard transfers and headless checks. Real X-server acceptance remains a
separate gate; adding this leaf does not promote a supported platform tier.

The Linux text adapter has a Linux-only PangoFT2/Fontconfig system-library
exception. `text_layout/` remains portable, while `platform/linux_text/` owns
all native calls, copied geometry results, and the private grayscale-mask
raster boundary. The Ubuntu renderer consumes that raster ABI but does not
expose Pango values or handles. Headless measurement remains independent of a
window/backend or display server. The public
`require_grayscale_raster()` admission check verifies the linked private ABI
and Pango >= 1.50 glyph-color metadata at runtime. The executable package
allowlist records the Ubuntu-to-`platform/linux_text` and Ubuntu-to-`text`
edges; this exception does not permit other portable packages to depend on the
adapter. See the [Linux text guide](linux-text.md)
for FFI, build, font-fixture, and dependency/license boundaries.

## Initial native package edges

The reusable application layer adds `app -> platform/scene/diagnostics/primitives`
and `platform/macos_app -> app/platform/platform/macos/platform/macos_text/
controls/text_field/scene/text/text_layout/primitives/diagnostics`.
`platform/testing` adds `primitives` and `scene` for deterministic frame and
backend fixtures. The first macOS slice adds checked edges
`platform -> primitives/diagnostics/scene`,
`platform/macos -> platform/primitives/diagnostics/scene`, and
`examples/native_macos -> platform/macos/platform/primitives/diagnostics/scene`.
The portable Backend trait includes frame submission in this first slice; a
separate renderer interface is deferred. No reverse edge from core, element,
layout, or scene to a backend is permitted. Native OS dependencies and ABI
ownership are documented in [macos-native.md](macos-native.md).

The Windows packages use checked edges `windows -> platform/, platform/windows_text/, scene/, diagnostics/, primitives/, accessibility/`, `platform/windows_text -> text_layout/, text/, primitives/`, `examples/windows -> windows/, platform/, scene/, diagnostics/, primitives/`, `examples/windows_button -> windows/, platform/, platform/testing/, primitives/, scene/, diagnostics/, accessibility/, examples/ubuntu_button/fixture/`, `examples/windows_text_field -> windows/, platform/windows_text/, controls/text_field/, text/, text_layout/, element/, platform/, scene/, diagnostics/, primitives/`, and `examples/windows_command_palette -> windows/, platform/windows_text/, controls/command_palette/, controls/text_field/, text/, text_layout/, element/, platform/, scene/, capability/, diagnostics/, primitives/`. Win32/D3D11 and DirectWrite calls remain in native leaf adapters. Windows accessibility snapshots are transport-free and do not implement UI Automation; the Button sample revalidates copied actions through its app-owned fixture dispatcher. Bounded grayscale scene text and the opt-in IMM32 field/palette fixtures do not establish a Windows support tier or qualify real Japanese IME behavior. Native dependency and smoke boundaries are documented in [windows-native.md](windows-native.md).

## JavaScript browser example edges

The interaction lab uses `examples/browser_app -> core/diagnostics/element/layout/platform/primitives/scene/capability/mcp` and `examples/browser -> examples/browser_app/diagnostics/platform/primitives`. The first package is host-neutral and compiles on all configured targets; its MCP seam is in-process dispatch through the registry, not MCP wire transport. The second is JavaScript-only.

Weekboard adds `examples/task_board -> capability/core/element/layout/platform/primitives/scene` and `examples/browser_board -> examples/task_board`. Its model owns task operations, history, scroll/drag state, filtering, selection, and logical geometry. The JS leaf exposes only copied values. Canvas rendering and ordinary HTML search/add/detail controls live in the static host. The dynamic visible-card DOM projection consumes the model's layout DTO and returns actions to the model; it does not move layout or task ownership into the DOM or establish a general semantic tree. Both pages share the bounded Canvas renderer. See the [browser guide](browser-demo.md) for implementation, test links, and limits.
