MoUI benefits from AI assistance when changes remain small, reviewable, and aligned with the framework architecture. This guide records the project-specific workflow for agents and maintainers.
- Preserve the public
View[Msg]/ runtime tree pipeline. - Keep package boundaries clear and platform-neutral code out of platform hosts.
- Prefer focused edits, focused tests, and explicit validation over broad churn.
- Keep public API changes visible through generated interface diffs.
- Keep renderer capability status synchronized across code, tests, docs, and Showcase.
- Keep
AGENTS.mdand repo-local skills synchronized with fast-moving docs, validation commands, package layout, examples, and text/rendering boundaries.
-
Public view constructors return opaque
@moui.View[Msg]; concrete built-in behavior lives inmoui/viewsas@core.ViewNodeimplementations constructed with@core.View::from_node. -
The runtime pipeline stays:
View[Msg] -> ElementTree -> LayoutTree -> RenderTree -> DrawCommand -> renderer -
core/owns platform-neutral contracts, opaque views, events, geometry, draw/semantics/text/theme contracts, and the public message-independentViewNodeextension protocol wrapped by typedView[Msg]adapters;moui/runtimeownsAppRuntime, runtime state, tree/layout/paint, event dispatch, program message drain, effect tasks, subscriptions, and runtime diagnostics. -
views/owns public constructor helpers and concrete custom view behavior, reusing bindings, styles, and modifiers without exposing runtime internals. -
backend/ownsEvent, surface metrics, input contracts, file drag/drop normalization, text-input session state, and redraw driver behavior. -
Platform packages convert native events into
Event; they do not mutate element trees directly. -
Renderers consume
DrawCommandvalues and do not depend on view constructors. -
examples/*/app/packages contain shared app logic; platform subpackages stay thin. -
Linux has a Wayland host core plus WGPU provider path; keep remaining matching-host runtime evidence and native font-provider gaps explicit.
- Read
AGENTS.mdas a map (task router + hard-boundary summary only). - Open
docs/INDEX.md, then only the linked canonical pages for the task. Preferdocs/architecture-map.mdover the full architecture narrative until needed. Standing constraints:docs/invariants.md. Validation:docs/testing.md. - For multi-package or platform work, add or update
docs/plans/active/<id>.mdbefore large coding loops. - Locate the package boundary by reading the relevant
moon.pkg. - Use
moon ide doc,moon ide outline,moon ide peek-def, ormoon ide find-referencesfor MoonBit API discovery when names are unclear. - Edit package-locally and preserve
///|top-level delimiters. - Add or update focused tests in the package touched.
- Run the smallest useful validation command first (see the AGENTS task router).
- Run
moon fmtbefore handoff. - Run
moon infoafter public API changes and review generatedpkg.generated.mbtidiffs. - Update docs when commands, platform behavior, public APIs, renderer
capabilities, or examples change. Do not fork invariant tables into skills;
link
docs/invariants.md. Taste rules:docs/golden-principles.md. - Check
AGENTS.mdandskills/when guidance would otherwise become stale. If no edits are needed, say they were checked and left unchanged.
Add a MoUI view constructor for <control>. Keep it in views/, return @moui.View[Msg],
implement reusable behavior in views/ as a concrete @core.ViewNode and construct it with @core.View::from_node, reuse existing styles/modifiers where possible, add focused tests in
views/views_test.mbt, update docs/view-catalog.md if public coverage changes, and
run moon test moui/views --target native plus moon info if the public API changes.
Improve renderer support for <feature>. Keep DrawCommand as the renderer boundary,
update render/capabilities.mbt, render/capabilities_test.mbt, docs/renderer-capability-report.md,
and Showcase if visible. Validate with renderer package tests and a Showcase Web wasm-gc build.
Change backend handling for <event>. Keep platform-specific code in backend/<platform>,
normalize through backend Event, add focused backend tests, and validate with
moon test moui/backend --target native plus the affected backend package test.
Update the <example> example. Keep shared logic in examples/<example>/app and platform
entrypoints thin. Add app-package tests for behavior, build the Web wasm-gc entrypoint
if browser behavior changes, and update docs/examples.md if commands or coverage change.
Update MoUI docs for <topic>. Keep the root README.md as the short entrypoint, put
detailed commands in docs/development.md, platform caveats in docs/platform-notes.md,
example behavior in docs/examples.md, text architecture in docs/text-system.md,
Markdown Editor behavior in docs/markdown-editor.md, and validation policy in
docs/testing.md. Also check AGENTS.md and skills/ when the guidance surface changes.
- Does the change preserve the runtime pipeline?
- Are package boundaries respected?
- Does public API surface change intentionally?
- Were focused tests added or updated?
- Did
moon fmtrun? - Did
moon inforun for public API changes? - Are docs updated for user-facing behavior, commands, or platform constraints?
- Were
AGENTS.mdand repo-local skills checked when docs placement, validation, package layout, examples, platform behavior, renderer status, or text architecture changed? - If renderer behavior changed, are capability code, tests, report, and Showcase synchronized?
- If backend behavior changed, do events still flow through
Event? - If an example changed, is shared app logic still under
examples/*/app/?
MoUI maintains a three-layer record system for AI-agent-assisted development.
Short bullet-point facts that agents load automatically each session. Use for: key patterns, common pitfalls, validated conventions. Keep entries under 20 lines per file.
Formal structured records for significant technical decisions. Create an ADR when:
- Choosing between two or more architectural approaches.
- Changing a public API contract or package boundary.
- Introducing a new dependency or external protocol.
- Changing renderer, backend, or runtime pipeline behavior.
- Decisions that affect how agents should work in this repo.
Use the template at docs/decisions/TEMPLATE.md.
Number sequentially (0001-, 0002-, ...) and update the index in
docs/decisions/README.md.
Summaries of significant multi-file or architecture-touching sessions. Log a session when:
- Multi-file changes that touch architecture boundaries.
- The session produced an ADR.
- Significant debugging or discovery happened.
- A new pattern or anti-pattern was established.
Use the template at docs/ai-sessions/TEMPLATE.md.
Name files YYYY-MM-DD-short-description.md.
After a significant agent session:
- Update
memories/repo/with any new quick-reference facts. - If a formal decision was made, create an ADR in
docs/decisions/. - If the session was complex or educational, log it in
docs/ai-sessions/. - Reference the ADR/session log in the commit message or PR description.
- Putting platform window or renderer logic in
core/. - Returning legacy view types from public constructors.
- Letting backend packages directly modify runtime element or render trees.
- Duplicating renderer fallback decisions inside view constructors.
- Updating renderer behavior without updating the capability report and tests.
- Running broad native checks as the first validation step for a small package edit.
- Creating compatibility shims for removed APIs unless explicitly requested.
- Growing
AGENTS.mdinto an encyclopedia instead of routing todocs/. - Restating full invariant tables in skills or session notes (link instead).
- Leaving critical rules only in chat or session prose without promotion to
memories/repo/, ADR, plan, or a validator.