# Mode 5c, Editor-shell composition: the canonical parts

Script: `scripts/dev/audit-shell-composition.mjs` (repo-local), npm gates
`audit:shell-composition{,:strict,:all}`. Static AST walk over
`apps/**/*.html`, `playgrounds/**/*.html`, `catalog/page-shells/**/*.html`, no browser needed; pre-commit fast. Shares one script and one output
contract with the `<admin-shell>` census
([admin-shell-anatomy](admin-shell-anatomy.md)): the script's own
`EDITOR_PARTS` array is the mechanical census; this file is the human
review standard. Canonical source:
`packages/web-modules/editor/editor-shell/editor-shell.yaml` (the
behavioral contract) and `apps/construct-canvas/app/construct-canvas.contents.html`
(the canonical rendered reference, cited by `apps/genui/PATTERNS.md`'s
chrome-decision table as editor-shell's canonical demo, alongside
`apps/genui`'s own a2ui-editor consumer).

`gh#2909`/`apps/genui/PATTERNS.md:329-337` established that `apps/genui`
(a2ui-editor) is a real `<editor-shell>` consumer that a
`<admin-shell>`-only mode 5 sweep never scanned, this anatomy closes that
blind spot.

## The canonical parts

1. `<editor-shell>` outer.
2. `<editor-canvas>` direct child, the central work surface. Required:
   without it there is nowhere for artboards/document body/canvas content
   to land, the editor equivalent of admin-shell's `<admin-content>`.
3. `<editor-toolbar>` direct child, the app-scope top chrome bar (document
   title, run/save/undo/redo, focus-mode toggle). Recommended; an editor
   with no toolbar has no document-wide action surface.
4. `<editor-canvas> > <editor-canvas-empty>` as (typically first) child, the empty-state placeholder shown via the parent's `[empty]` reflected
   attribute before any content exists.
5. `<editor-canvas> > <editor-canvas-toolbar>`, optional canvas-scope
   chrome (view-mode tabs, breadcrumbs) sticky to the canvas top edge;
   distinct from part 3's app-scope toolbar.
6. `<editor-statusbar>` direct child, bottom chrome bar (save/sync state,
   zoom, cursor position). Recommended; loses the canonical status-strip
   without it.
7. `<editor-sidebar slot="leading"|"trailing">`, optional navigator or
   inspector rail.
8. When an `<editor-sidebar>` is present, it must wrap `<pane-ui
   resizable>` (or at minimum `<pane-ui>`), editor-sidebar is the one
   bespoke shell child that **delegates** rather than duplicates a
   primitive's resize behavior (per `shell-patterns.md`'s "FIRST bespoke
   shell child that delegates" note); an editor-sidebar with no inner
   `<pane-ui>` reimplements drag by hand instead of reusing the primitive.
9. No bare `<header>` / `<footer>` native elements as direct children of
   `<editor-shell>`: these are the ADR-0024-retired legacy chrome shapes
   that `<editor-toolbar>` / `<editor-statusbar>` replaced.

## Severity mapping

- **critical**, `<editor-shell>` present but missing `<editor-canvas>`
  (part 2). The shell can't render usable content without it.
- **warning**, no `<editor-toolbar>` (part 3); no `<editor-statusbar>`
  (part 6); an `<editor-sidebar>` present with no inner `<pane-ui>` (part
  8); a bare native `<header>`/`<footer>` direct child (part 9, the
  retired-legacy-shape leak).
- **info**, `<editor-canvas>` missing its `<editor-canvas-empty>` first
  child (part 4; a canvas pre-seeded with real content legitimately skips
  this); no `<editor-canvas-toolbar>` (part 5, optional canvas chrome); no
  `<editor-sidebar>` at all (part 7, `construct-canvas`'s own comment
  notes "no leading pane today", a legitimately sidebar-less composition).

## What the script flags (mechanical subset)

| Symptom | Diagnosis |
|---|---|
| `<editor-shell>` with no `<editor-canvas>` | critical, part 2 |
| `<editor-shell>` with no `<editor-toolbar>` | warning, part 3 |
| `<editor-shell>` with no `<editor-statusbar>` | warning, part 6 |
| `<editor-sidebar>` present, no inner `<pane-ui>` | warning, part 8 (delegation contract violated) |
| `<editor-shell>` direct child is native `<header>`/`<footer>` | warning, part 9 (retired-legacy-shape leak) |
| `<editor-canvas>` with no `<editor-canvas-empty>` child | info, part 4 |

## Opt-out contract

Same annotation mechanism as admin-shell: `<editor-shell
data-shell-opt-out="reason">` downgrades every finding on that shell to
info and prints the reason for reviewers.

## Triage

- Canonical product surface (`apps/construct-canvas`, `apps/genui`'s
  a2ui-editor) → fix mandatory.
- A narrow single-feature playground isolating one editor behavior → fix
  optional; annotate the opt-out.
- Never point this audit at `packages/web-modules/editor/**/*.examples.html`
  or `packages/web-components/components/*/*.html` (single-primitive
  spotlights), the script's `isShowcaseDemo`/showcase-path exclusion
  already keeps those out of scope, same as admin-shell.
- **Don't nest `<editor-shell>` inside `<admin-shell>`** as page chrome, `editor-shell.examples.html` documents them as sibling surfaces, not
  nested; this audit doesn't mechanically flag the nesting mistake (a
  cross-shell structural rule, not a within-shell anatomy gap), but a
  reviewer seeing both tags in one file should treat it as a design smell.
- `:strict` is the CI/publish posture; keep warn-only while iterating
  locally.

## Legacy shapes, never re-authored

`editor-shell.yaml`'s own description lists the ADR-0024-retired legacy
data-attribute shapes (`<header>`, `<div data-editor-body>`, `<pane-ui
data-left|data-right>`, `<div data-canvas>`, `<footer>`, `<span
data-spacer>`) as silently unrecognized, not merely deprecated. Part 9
above catches the two structural container tags (`<header>`/`<footer>`)
mechanically; the finer-grained data-attribute forms are already covered
by `verify:no-legacy-shell-shapes` in `npm run check`.
