The complete rules for writing or editing a shape's component (kind component). Use when creating, editing, patching or fixing a kind component, calling any kindcomp_* tool, or when a shape renders empty, broken, cropped, cramped or ugly.
The English summary is being prepared. Showing the original description.
Review the instructions the agent will receive before you install.
<!-- SYNCED COPY — do not edit here.
Canonical: common-docs/skills/shape-authoring/SKILL.md
This file is distributed to every consuming repo by
common-docs/meta/scripts/sync_skills.py. Edit the canonical, run the
sync, and commit each repo. Edits made here are overwritten and lost. -->
shape-authoring — the one rulebook for shape components
<!-- rules:stamp -->
Rules from common-docs/systems/architecture/content-ir/FEATURE.md — edit there, never here (python3 common-docs/meta/scripts/one_home.py --write).
Every schema declares __kind at every object position: const + required where the identity is known, and declared but optional everywhere else. The only exceptions are the boolean/number scalar roots and the json kind. BEFORE triggers guarantee this on kind_definition, kind_example, kind_instance and agent.definition.output_schema (wf_066). Never add a write-time check that rejects an unmarked schema, because the trigger fixes it.
Never strip __kind and never loosen a schema to fit the data. Bring the data up to the schema with content_ir.stamp_markers_from_schema. Never reintroduce injectKind: false, and never hand-patch emitted_json_schema, because it is emitted from the kind's source. Guards: aidream scripts/check_kind_marker_law.py --live and matrx-frontend pnpm check:kind-marker-law.
__kind is the first key. An unfenced bound-agent stream is typed from its first key (block_detector.root_kind_declaration). jsonb reorders keys, so SQL that mints an instance builds it as text/json and reads the row back.
An agent is never asked for plain JSON. A structured result is a kind instance or it is markdown.
A registered kind is not a payload with a __kind key.content_ir.evaluate_kind_activation checks that its example validates, it has a real output component, and its schema is unique; the result is advice shown beside the switch (warnings), never a refusal (rule 24). The generic key/value view is not a component; activation changes go through set_kind_activation.
Machine contracts are quarantined by residence. They live in content_ir.io_contract. The family names action_io, tool_io and agent_io are reserved and never appear on a kind_definition row. workflow_io is a pinned slug set, and data_only is informational only: it never removes a form. Guard: scripts/check_kind_family_law.py.
directive_v is a reserved prefix. No hand-authored or user kind may start with it (enforced in @kind, kind authoring and the shape creator, and checked by scripts/validate_kind_directive_registry.py at zero). Capability is derived from the directive class and never stored.
The position law has one home: matrx_graph.content_ir.directives. Only create, update, delete and action execute, and only at an agent's output root. Only reference and secret resolve inside content. A side effect found in content renders as a button and runs only on a human click.
The directive ledger key is sha256(namespace·type·item) with kind excluded. Changing how type is derived from the slug re-applies every past action. Keep "matrx" in MATRX_OWNED_BLOCK_TYPES, never seed a kind_definition row per directive, and never attach __ir to a matrx block, or directives render as raw JSON.
Shared logic lives once, in aidream/apps/shared/content-ir-core (kernel) and content-ir-react (route, resolver, shared views). No consumer keeps a local copy of a parser, a route decision or the directive decoder. The kernel refuses React, and the render layer refuses Next.js, Redux and Supabase. Consumers ride the npm latest tag, and versions live in each package's CHANGELOG.
Detection is identical in Python and TypeScript. A container never hides a kind: when a region closes, balanced JSON objects with a non-empty __kind become their own instances, in document order. XML owns its body until its root closes, and a ```matrx fence is a container. Shared conformance vectors pin markdown-fence nesting. A change to one runtime lands with the other and its vectors.
A streaming partial follows the partial wire contract. Partials ride metadata.__ir_partial. The state is partial, superseded or retracted, and exactly one terminal state ends every partial, so a skeleton can never stick. Every partial is closed into valid JSON. The key is absent on most events: consumers carry state forward, never reset on absence.
Runtime wrappers delegate, never reimplement.node_outcome renders its inner kind through the ordinary route. Elided payloads ride once, through output_ref.
A skipped check is never a pass. A degraded verdict carries a named KindDegradedReason. Only catalog_unreachable is a loud skip, KindContractViolation is non-retryable, and an invalid typed output is never stored as a success.
Enforcement is the code constant matrx_graph.kinds.KIND_ENFORCEMENT, never an environment variable. The DB admission_config ratchet coexists with it on purpose.
Undeclared keys never sit at a payload's root. They go in a declared map (for example extras).
A primitive binds; it does not get a new component. A shape that maps onto an existing primitive binds through the primitive plus props_transform. Block-type string values, routes, dispatch outcomes and stored content bytes are frozen, and a rename that changes one is a defect.
Every emitted kind declares a disposition. A kind with none gets no storage and files an ops.system_error row (kind_disposition_undeclared). New kind data lands in records, never in content_ir.kind_instance.
A missing or broken component is replaced at once and reviewed afterwards. The replacement shows a "just built" mark and a one-click way back to the plain data view. This never replaces a working, registered component without review.
Reuse before you mint. Well-known kinds (web results, citations, address, rating) are reused through provider translation functions, never re-minted under a new name. metadata.maturity = verified is earned only by the verification pass.
Every active shape has a skill, and a hand-written one is never overwritten. Generated skills come from the non-AI template (kind_create_skill) and carry metadata.created_via; a weekly refresh regenerates only those. A shape with no description gets a concise one from a weekly batch run on a fast model.
Shapes picked in chat: up to a knob (default 10) go to the model in full; past it, the model gets each shape's name and description and loads the ones it uses. Picks travel as output_kinds (kind slugs) on start, chat and continue requests, never as skill ids; an omitted field means the chat's saved picks (chat.conversation.metadata.run_configuration.outputKinds). The server alone resolves shape → skill (aidream services/tooling/output_kinds.py, knob chat.output_kinds.full_body_max).
An agent locked to a structured output schema answers in its own shape; a different picked shape is never an error. The picker warns at the moment of selection, and a saved conflicting pick shows the same warning; the server drops picks the agent cannot honor and sends a visible warning (output_kind_locked), never a failed run. The agent's schema is never modified per request.
Every kind, kind component, surface and converter is born ACTIVE, from every screen, tool, seed script or automation. Switching one off is a deliberate act; turning one on is never refused. Never write is_active=False on create and never add a check that blocks activation or disables the Activate button.
A streamed shape's render state is a one-way ratchet: markdown text → JSON found → __kind found → kind resolved and its component rendering. Once forward it never goes back (no re-mount, no generic or text flash) because a chunk is partial, unparseable or fails validation; hold the last good render and fall back only on strong, repeated evidence (the stream ended and the final value is invalid). Mount count stays 1 per block; test with token-by-token replay including mid-key and mid-__kind splits.
Rich content helps, never hinders. Every surface offers copy as markdown and copy as plain text one click away; formatting buttons work in every mode including raw markdown; editing happens in place. Replacing a UI never ships without full parity verified by screenshot in EVERY mode, and "done" means a clipboard capture plus a screenshot of the visible button, not a green guard. Judge each surface from the user's seat (copy, select, format, edit in place, every mode, window panels, phone) and audit every surface for consistency; copy never puts raw <artifact> tags on the clipboard. Every rename or cleanup ships with its full inventory (tools, routes, DB, tokens, copy, docs, tests) and is done 100%, never half-way; the domain tree wins on names and placement. The basics come before any side work, and when Arman says "focus on my vision" every other lane drops.
A kind's name and schema are ONE shared contract per slug; how it looks layers user → org → system, most personal wins. Anyone fixes a bad render for themselves in one click, org admins for their organization, and super admins get a link to the admin pages for a global change (never admin power on a user route). The fix ladder starts at "kind not registered".
<!-- rules:stamp-end -->
A shape component is React (TSX) stored in the platform and compiled in the reader's browser. It
renders one item an agent produced. This file is the whole contract. An import, prop, action
or pattern that is not written here does not exist — do not guess one.
Each block below is the single home of its rule. To change a rule, change its block.
<workflow>
1. `kindcomp_get_context` with the kind (or component_id) — FIRST, every time. It returns the
kind's schema, the example payload your component receives, the other components, and open
render incidents.
2. Write the COMPLETE component against the example payload, following every block below.
3. Save: `kindcomp_create_component` (new), `kindcomp_update_code` (whole source),
`kindcomp_patch_code` (small exact edits).
4. A save can be REFUSED with a sentence (unknown import, banned global, no `data` read). Fix
exactly what it names and save again — never work around it.
5. Fixing a crash: read the incident from step 1, fix, save, then `kindcomp_resolve_incident`.
</workflow>
data — the item. EVERY field is read from it: data.title, data.items?.map(…). Flat props
(props.title) are never provided; a component reading them renders empty with no error.
Read-only — never mutate it, never write results into it.
props_transform (optional) reshapes the value before mounting; its output STILL arrives as
data.
kind, config — the kind slug and this component's config.
runAction(key, input) — the ONLY way anything leaves the component (see <actions>).
itemState — what actions saved onto this item; {} when nothing yet. Survives reload.
onResolve, uiOptions — only inside a picker the page opened; ignore otherwise.
One default export. Hooks only at the top level of components.
</props_contract>
<available_imports>
Only these module paths may be imported, with exactly these names. Anything else is refused at save.
Kit (use FIRST — see <kit>):
"@/components/kind-kit/KindHeaderBar"
"@/components/kind-kit/KindPanel"
"@/components/kind-kit/KindPanelGrid"
"@/components/kind-kit/SortableList"
"@/components/kind-kit/TagList"
"@/components/kind-kit/StreamingSkeleton"
"@/components/kind-kit/KindActionButton"
"@/components/kind-kit/KindImage"
Libraries:
"react"
"recharts"
"motion/react"
"date-fns"
"lodash"
"react-katex"
"react-pdf" (PDFs from data: URIs or bytes only — never a URL)
"xlsx"
"three"
"@react-three/fiber"
Applets (page only — they do not run inside the sealed frame; do not use in shapes):
"@/applets"
"@ai-matrx/applets/react"
Libraries load only when imported. props_transform cannot import them.
</available_imports>
<kit>
The kit makes every shape correct and consistent by construction. Hand-rolling a header, panel,
grid, sortable list, chip list, skeleton, action button or image is a defect.
KindHeaderBar — the one compact header: title (required), icon?, subtitle?,
stats?: [{label, value, icon?}], streaming?, copy? (CopyButtons props, label required),
actions?, size?: 'sm'|'md', className?. It has NO padding of its own: the host frame pads
it. Put it inside your own bordered card and you pad it to match your rows
(className="px-3 py-2" beside px-3 rows), or the icon touches the card edge.
KindPanelGrid — auto-fit grid of equal-height panels: minColumnWidth? (default 280, never
smaller for text), maxColumns?, gap?: 'sm'|'md'|'lg'.
KindPanel — title (required), icon?, count?, badge?, streaming?, actions? (≤2),
menuItems?: [{label, onSelect, icon?, disabled?, destructive?, separatorBefore?}],
subline? (full width under the header), footer? (pinned to the bottom), variant?: 'card'|'bare', dense?.
SortableList — drag to reorder with displacement and a drop placeholder: items,
onReorder(items) (required), getKey?, renderItem?(item, {index, isDragging}),
onRemove?, emptyState?.
TagList / KeywordChip — chips that wrap, never truncate. TagList: items (strings or
{label, key?, meta?}), selected?, onToggle?, onRemove?, onEdit?, onAdd? (renders the
add input), addPlaceholder?. KeywordChip: label, meta?, selected?, onSelect?,
onRemove?, tone?: 'default'|'primary'|'muted'.
StreamingSkeleton, useStreamingValue, streamList, streamText — see <streaming>.
KindActionButton — see <actions>. KindImage — see <media>.
Import each by its exact path with the named export: import { KindPanel } from "@/components/kind-kit/KindPanel".
</kit>
<copy>
Every shape has a copy bar in its header (`KindHeaderBar copy={…}`); rows and panels that hold
something worth copying get their own small `CopyButtons`.
CopyButtons: label (REQUIRED), human?: string | () => string (plain text or markdown you
build), agent?: () => ({ kind, location, description, data, summary? }) (Copy for AI),
json?: () => value, size?: 'xs'|'icon'|'sm', export?: { items: [{ id, label, filename, content: () => string }] } (downloads), hide?: ('copy'|'ai'|'export')[].
There is no content or data prop. Pass builder functions so text is built at click time.
CopyForAiButton: label and agent required; size?, compact?.
</copy>
<actions>
`runAction(key, input)` never throws. It resolves `{ok: true, result}` or `{ok: false, error}`;
show `error` small beside the control that caused it.
shortcutId — a named constant at the top of the file. Never a raw agent id.
scope: { selection, content, … } — TEXT the agent can read (a short markdown rendering of
the piece), never the raw object.
No saveAs → the shortcut opens in its own window (a conversation the person continues).
saveAs: "idea_3_brief" → runs in the background and the platform saves the product onto
this item as itemState.idea_3_brief. Key per piece: <piece>_<n>_<what>.
Chains: await step 1 with saveAs, pass its product into step 2's scope, saveAs again.
Render saved results in place, next to the piece they belong to; keep the button available to
run again (re-running replaces the value). Where the item has no saved record (a preview),
saveAs and save_item_state refuse with a sentence; opening in a window still works.
KindActionButton is the button for any action — busy state, double-click guard, error line,
confirm:
<media>
- A saved image (an `itemState` value with `file_id`) renders ONLY with
`<KindImage image={ref} alt="…" runAction={runAction} pending={busy && !ref} maxHeight={480} />`.
It shows the whole image at its real proportions (never cropped), with expand and share.
Never a bare `<img>` for it, and never build a URL from a `file_id`.
- Images inside `data` as `data:` URIs and inline `<svg>` render normally.
- Images from other websites do not load. Do not reference them.
- Never save a `src`, URL or download link into item state — only the ref.
</media>
<links>
- Plain `<a href="…">` for web (`https:`), `mailto:`, `tel:` and in-app paths (`/crm/…`). The
platform opens them in a new tab, inside the frame too. Links that arrive in `data` are fine;
`javascript:`, `data:` and `blob:` links are refused.
</links>
<frame_rules>
A shape may run inside a sealed frame. Write every component so it works there:
No fetch, XMLHttpRequest, WebSocket, EventSource, sendBeacon, eval,
new Function, dynamic import(), cookies, localStorage, sessionStorage — refused at save.
Keep transient state in React state; keep durable state with save_item_state.
No window.parent, window.top, no navigating or reading the page around you.
Size against your own box: container queries (@container with @sm:, @md:, @lg:), never
screen classes (sm:, md:, lg:).
Dialogs, popovers, menus and tooltips work but are clipped to the shape's box. Anything that
needs the whole screen goes behind an action.
No alert, confirm, prompt, window.open, window.print — use dialogs, the kit's
confirm, and actions.
The frame never scrolls; long content scrolls inside a panel (max-h-* overflow-y-auto).
</frame_rules>
<streaming>
The item arrives progressively while the agent streams. The component renders its full layout
immediately and fills in:
- Before data lands: `<StreamingSkeleton layout="list"|"cards"|"table"|"text" rows={3} />` that
mimics the finished layout — never a spinner, never a blank box.
- `const { value, arrived } = useStreamingValue(data?.summary, "")` keeps the last defined value;
call it unconditionally with a field read. `streamList(data?.items)` for arrays,
`streamText(data?.body, "")` for strings.
- Render list items as each one parses, with stable keys. Every field access tolerates absence:
never show `undefined`, `[object Object]` or a raw JSON dump.
</streaming>
<layout>
- Budget width from the CONTENT, never from how many things you want side by side. Text panels
need ≥280px: use `KindPanelGrid` so four panels become 2×2 or one column when space is short.
- Text wraps; it is never truncated with an ellipsis.
- A header row holds the title, ONE count or badge and at most two controls; the rest go in the
panel's overflow menu. Per-row actions appear on hover and focus.
- Side-by-side panels are equal height with footer actions pinned to the bottom.
- Dense, never cramped: minimal outer padding, tight inner spacing, full width.
- Prefer one excellent column over four unreadable ones.
</layout>
<design>
- **Unstyled element inside the sandbox frame? Check the daily stylesheet first.** On Vercel the
frame's stylesheet (`public/kind-sandbox.css`) is rebuilt at most once a day: a Tailwind class used
for the FIRST time in a repo file since the last rebuild is missing from it until the next one
(the main app is unaffected). The release's build log has one `[kind-sandbox-css] REUSED …` or
`BUILT …` line saying which happened. Fix now: put `[fresh-css]` in the next release message.
Rule + reason: `features/content-ir/sandbox/build-kind-sandbox.ts` § THE DAILY STYLESHEET.
- Modern, professional, delicate. Semantic Tailwind tokens only: `bg-card`, `bg-muted`,
`text-foreground`, `text-muted-foreground`, `border-border`, `text-primary` and their variants.
No hex colors, no arbitrary values, no emojis in the interface.
- Correct in light and dark mode — tokens guarantee it; fixed colors break it.
- Interactive wherever the data invites it: reorder, inline edit, add and remove, one-click copy.
Dragging always shows where the item will land (`SortableList` does this).
- In-app text is short labels, not sentences.
</design>
<before_saving>
Every field read from data, null-guarded.
Every import is in <available_imports>, by exact path and name.
Kit used for header, panels, grid, lists, chips, skeleton, buttons, images.
Header copy bar with a label.
Renders a skeleton before data and fills in while streaming.
Container queries, no screen-width classes; nothing truncated; nothing cropped.
Results in itemState, never in data; shortcuts by named constant; credit-spending
buttons confirm.
</before_saving>
Reviews
No reviews yet. Tell others what you thought.
Comments
No login needed. Share how it worked for you, ask a question, or note where it did not run.
Admin debug system wiring for the floating AdminIndicator's live debug data and Copy Full Context. Use when adding debug visibility to a route or feature, wiring useDebugContext or the debug panel, capturing console errors, or enabling the copy-context workflow for a page.
The English summary is being prepared. Showing the original description.
Compact two-icon Copy / Copy-for-AI controls (components/agent-copy). Use when adding copy buttons to a row, card, list, or record; merging duplicate Copy/JSON/AI controls; continuing the copy rollout; or writing a Copy-for-AI payload. NOT for markdown content actions (use rich-document-actions).
The English summary is being prepared. Showing the original description.
Disclosing a surface's existing fixed AI jobs in the shell's top Agents menu. Use when a page, panel, overlay, or window already runs a mandate behind a button, assist, automatic action, or mode; when the agent-disclosure guard names a file; or during a surface check.
The English summary is being prepared. Showing the original description.
The watch-fix-rerun method for making an existing platform agent or automated process efficient and correct: baseline its ledger, run one unit yourself, fix the class behind every wasted call, rerun, record. Use when asked to improve, optimize, watch, or 'make efficient' an agent, a sandbox session, a sync job, or any recurring automated process.
The English summary is being prepared. Showing the original description.
Redux state for agent execution and firing agent shortcuts. Use when editing features/agents/redux/, building agent UI, creating a conversation, touching assembleRequest or NDJSON stream state, wiring agent-state selectors, adding a per-conversation capability, or triggering a shortcut from a button, menu, or code (useShortcutTrigger, launchAgentExecution).
The English summary is being prepared. Showing the original description.
The provision for a call site: the exhaustive menu of values that place in the code can realistically produce. Use before creating or fixing a mandate or agent that reasons about more than its own input, when deciding whether an agent can answer at all with what it is sent, or when its output 'looks right' but nobody checked it could be. NOT for building the agent (use create-agent).
The English summary is being prepared. Showing the original description.