# `embeddedForm` behaviour

*Open when a form is to render another form inside it — a record card with its own content form, a
side panel, a wizard step that reuses an existing form.*

`form` is `{ id, alias?, entity? }` — the whole reference the form picker emits, not a bare id. Two
modes: `source: 'record'` mounts a **full `FormHost`** for the active record (projection, hydration,
autosave, realtime, dirty guard — none of which the bare nested-runtime path has), and standalone
renders the form on its own. The builder always draws a dashed placeholder instead: there is no
design-time recursion.

## The content form must be `update`, and non-transactional

**`type: 'update'` with `settings.isTransactionMode: false`.** `FormHost` arms autosave only for
`record && !submitless && !transaction`, and `custom` / `workspace` are submitless — so a `custom`
content form inside an embed **saves nothing**. Edits sit in the runtime and a record swap discards
them, with no error and no prompt. Measured by the platform on forms 219 and 218 of this dev
tenant. With `update` + non-transaction each field edit diff-PATCHes the active record.

Keep the content form `isPublic: false`. A second `update` form on the entity does not hijack the
card's own resolve (probed at priority 0, 1 and 100), but that is the tested configuration.

An edit that never left its input — typed, no blur, then a programmatic record swap — is still
dropped, exactly as in v1. A *committed* edit is safe: the host flushes a debounced autosave in
`onBeforeUnmount`, and the persist closure owns the old record id, so it can never land on the new
record.

## Two traps for a form authored through the API instead of the builder

Both apply to this skill, because this skill writes rows rather than clicking the builder:

- **The default relation variable is not seeded for you.** `POST /core/forms/schema` creates the
  form without it, and then every `{{Entity.*}}` path in the form dies silently. Write it in the
  first update: `variables: [{ name: '<Entity>', type: 'relation', isDefault: true }]`.
- **`PUT /core/forms/:id/schema` must resend `code`** — omit it and the server **nulls
  `codeArtifact`**. (This skill's `write_form_draft` avoids the hazard by using the generic data
  endpoint and naming only `schema` and `settings`, so `code` and `codeArtifact` are untouched. The
  trap is live the moment anything switches to the platform's own save-draft endpoint.)

## Cross-form messaging

An embedded form talks to its host through the element's `formEvent`, scoped by **ownership**, not
by ids — two stacked cards on the same record stay independent. Never reach for `window` events:
they are global, they leak, and any form can spoof any other.

Failure states are explicit, never a blank: `embeddedFormRequired` (no form picked),
`embeddedFormEntityRequired` (record mode, no entity resolves), `embeddedFormRecordRequired`
(runtime only, no active record) and `formLoadFailed` (deleted, no access, or no published version).
