@yugoo-design/dsh-design-studio-dsh 0.2.2 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/lib/authoring/panel-components.json +118 -81
- package/lib/authoring/studio-creators/material.json +1 -1
- package/lib/authoring-entry.js +1 -1
- package/lib/{authoring-service-WClXJGik.js → authoring-service-BRUrHzSH.js} +4 -2
- package/lib/authoring-service.js +1 -1
- package/lib/typert.host.d.ts +2 -2
- package/licenses/dsh-distribution.json +84 -84
- package/package.json +5 -5
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
"sections": [
|
|
22
22
|
{
|
|
23
23
|
"file": "docs/dsl-spec.md",
|
|
24
|
-
"line":
|
|
25
|
-
"endLine":
|
|
24
|
+
"line": 1220,
|
|
25
|
+
"endLine": 1284,
|
|
26
26
|
"heading": "`tabs` — mounted views with stable identities",
|
|
27
27
|
"content": "### `tabs` — mounted views with stable identities\n\nUse `tabs` to switch between declared child views, not to split canonical data\ninto copies. Its inputs are `id`, optional `title` (the tablist accessible name),\nand `children`. Each child needs a non-empty `id`, unique among its siblings;\nits optional `title` is the tab label, falling back to its ID. IDs are data\nidentities, not translated labels. Nested groups may reuse IDs because their\nDOM relationships are independently scoped. Empty children render no tabs.\n\nSelection is local presentation state. The first child is initially active;\nchanging labels or child order preserves selection by ID. Removing the active\nchild selects the first remaining child; re-adding it does not steal selection.\nInactive children stay mounted but are hidden, preserving their local drafts.\nDo not use this component when inactive content must be unloaded or its readers\nmust stop: it does not promise lazy loading or cancellation. Hidden controls\nare not reachable through ordinary keyboard focus.\n\nClick/focus selects a tab. ArrowLeft/ArrowRight wrap between tabs; Home/End\nselect the first/last. The active tab is the one tablist entry in the Tab order;\neach panel is linked through reciprocal `aria-controls`/`aria-labelledby`.\nTab selection emits no canonical edit. Child editors retain their existing\nschema, save and read-only authority; a hidden editor is not an authorization\nboundary. The host still owns atomic persistence and unsaved-change handling.\n\nThis non-Web equipment note example composes existing components only:\n\n```yaml\nversion: 1\npanel_kind: evidence_workbook\nsections:\n - {id: equipment, title: Equipment notes, add_mode: none}\nfields:\n - {key: title, label: Equipment, control: text, applies_to: [equipment]}\n - {key: note, label: Inspection note, control: textarea, applies_to: [equipment]}\nui:\n component: tabs\n id: equipment-views\n title: Equipment views\n children:\n - {component: text_block, id: guidance, title: Guidance, text: Record observations without inventing inspection results.}\n - {component: record_form, id: notes, title: Notes, source: equipment}\n```\n\nThis notes-only example explicitly sets `add_mode: none`; adding or removing\nequipment records is not authorized by its editors. It expects a declared\n`equipment` map of records containing string `title` and\n`note` fields, e.g. `{equipment: {pump_a: {title: 'Synthetic pump', note: ''}}}`.\nIt is a composition example, not a complete Kit or verified inspection fact.\nThe executable example test validates the actual YAML, schema-bound generated\nadapter, retention and editor permissions; installed-host save/reopen remains\na separate verification layer. For localization, put display strings in Bundle\nlocale resources and replace titles/labels/text with `$t:` tokens; do not\ntranslate `equipment`, `pump_a`, child IDs or stored observations.\n\nThe trusted catalog registers `tabs` for the supported generated subset. A2UI\nconversion must still validate the complete child tree and edit bindings; tabs\ncannot authorize an unsupported child, action or wider write scope. Generated\nand retained DSL use the same renderer. Unknown components or incompatible\nretained definitions must fail explicitly, not silently drop a tab.\n\nStyles use the dedicated `.dsh-component-tabs` namespace so public `renderNode`\nmounting does not collide with host navigation. Hosts must load shared Panel\nstyles; the component does not inject CSS. Test keyboard/hidden behavior and\nnarrow-container overflow in a real browser in addition to structural checks.\n"
|
|
28
28
|
}
|
|
@@ -137,8 +137,8 @@
|
|
|
137
137
|
"sections": [
|
|
138
138
|
{
|
|
139
139
|
"file": "docs/dsl-spec.md",
|
|
140
|
-
"line":
|
|
141
|
-
"endLine":
|
|
140
|
+
"line": 958,
|
|
141
|
+
"endLine": 1169,
|
|
142
142
|
"heading": "`component` (trusted, extensible library)",
|
|
143
143
|
"content": "### `component` (trusted, extensible library)\n\nThe authoritative vocabulary is [`PANEL_COMPONENT_CATALOG`](../packages/core/src/panel-component-catalog.ts).\n`COMPONENT_KINDS`, workspace ownership, source bindings and the generated-panel\nsubset are derived from that one registry; this document is not a second\nvalidation whitelist. Bundle data cannot register executable components.\n\nThe shared library includes basic layouts and controls, question workspaces,\nrecord navigation/editing, diagrams, canvases, artifact readers and previews.\nFull-height workspace components preserve scroll and navigation ownership:\n`record_board`, `document_workspace`, `artifact_workspace`, `diagram_workspace`,\n`canvas_workspace`, `preview_workspace` and `navigation_workspace` expose their\nbehavior through explicit data bindings rather than Kit names. These are reusable\ncapabilities, not a guarantee that every record schema fits every workspace.\n\n`record_board.board.detail_sources` can embed exactly one `record_workspace`\nunder the selected card. Each `{section, reference}` binding declares an unordered\ndirect record collection and a readonly `record_select` back to the board's\nparent section. The child workspace sources must belong to those bindings.\nOwner and child storage paths cannot alias or overlap. The renderer filters\nchildren by the selected parent, binds new records to it, and merges hidden\nsibling records back into canonical updates. It refuses sibling-id replacement,\nreparenting and writes outside these collections. This is a view projection,\nnot a second stored copy; it does not support independently ordered child maps,\nnested `fields_path` records or artifact staging in this first composition slice.\nOrdinary `detail_sections` retain their existing same-record nested-form meaning.\n\n`record_board` uses full-width cards and a workspace-covering overview. Optional\n`board.group` binds a real grouping field. When omitted, the sidebar lists records\ndirectly, cards have no artificial group heading, and the overview connects the\nroot directly to records. Do not bind long summaries merely to satisfy grouping;\nthis projection never adds a grouping field to canonical records.\nSidebar selection scrolls to a card; it does not start editing. Description and\nbadge drafts have explicit Save/Cancel, while rejected records remain inspectable\nwithout granting edit access. Optional `board.id_field` binds a declared visible,\nreadonly `text` field and displays its existing string beside the card title and\nat the top of cover details. Inline details retain the same card header. It does\nnot add an ID editor, generate a fallback ID or write state; omission retains the\nexisting title-only presentation. `board.detail_fields` restricts the parent fields\nshown in the detail fold, and `details_title` localizes its heading. Optional nested\ndimensions can be added or removed without replacing unrelated record fields.\n`board.detail_fields_mode: fixed` instead shows every declared nested input and\nremoves dimension-level add/delete controls; collection item add/delete still\nuses its usual editor. Fields remain schema-optional, including empty inputs.\nViewing does not insert missing strings/maps. Omitted/`on_demand` retains the\nexisting optional-dimension behavior. This option grants no new write authority.\n\n`record_workspace.workspace_view: switch` puts the first child canvas over the\nwhole workspace. The edge action opens it, and the return action or a node's\ndetails action returns to the selected record. It does not add form/canvas tabs\nto the sidebar. Covered content stays mounted and inert to preserve selection,\ndrafts and the graph viewport without allowing hidden controls to receive input.\n\n`record_related_editor.record_table` is an authored-only table presentation of\nthe same child collection, not a conversion to a `rows` array. Its finite\n`columns: [{fields: [field_key, ...], label?: string}]` groups existing field\neditors into cells. Every non-hidden field declared for that child section must\nappear exactly once; hidden/foreign/duplicate bindings and unknown column keys\nare rejected. Column labels default to the first field's label and use the usual\nlocale resolution. A cell retains field visibility, help, requiredness, custom\nconditions and existing edit/derived-field rules. Record creation still binds\nthe selected parent, deletion preserves the normal section cleanup rules, and\n`inherit_from_graph` tables remain source-linked and read-only. The shared table\nwrapper owns horizontal scrolling at narrow widths. This does not promote the\ncomponent or this declaration to generated A2UI.\n\nAn authored graph hierarchy with `max_parents: 1` may opt into\n`parent_control: header`. The existing single-parent selector then sits beside\nthe selected record's form title, rather than above the whole inspector. It\nstill updates the same relation edge, rejects cycles, retains the source-record\nnavigation and shows the actual parent in read-only mode. Omission preserves\nthe prior inspector presentation; neither view creates an extra parent field.\n\n`diagram_workspace.diagram.detail_rows` groups declared read-only fields into\nresponsive fact cards. `chip_fields` selects string-list fields rendered as tags;\n`detail_hint_fields` supplies the populated field labels for the details action.\n`tags` maps declared enum fields to labels and finite semantic tones. These are\npresentation declarations, not new edit rights or storage. Diagram details cover\nonly the content pane; the navigator remains available. Leaving an edited diagram\nstill requires successful serialization through the existing save barrier.\n\n`diagram_workspace.diagram.label_source` can read a declared label from another\nsection bound to the same record collection. The optional `inspector` keeps a\ncontext editor alongside the BPMN canvas: `process_sections` edit the selected\nprocess; `nodes` binds `source`, `process_field`, `element_field`, `label_field`\nand same-collection `sections`. Optional `related` groups use a process reference\nand an optional `node_field`; `advanced: true` starts the group collapsed.\nReferences must be declared `record_select` fields targeting the corresponding\ncollection. Clicking an element resolves its exact ID within the selected\nprocess only; absent or duplicate bindings do not guess a record. Existing field\nedit permissions and the atomic artifact save barrier remain authoritative.\nThis is contextual navigation, not automatic synchronization of BPMN structure\nand business facts; authors must explain how structural changes are reconciled.\n\nFor an exact component contract and on-demand local type declarations, use the\nauthoring inspector from the repository root:\n\n```sh\nnode .agents/skills/design-bundle-creator/scripts/inspect-panel-component.mjs . navigation_workspace --type ComponentNode.navigation_map.edges\n```\n\nUse the [component extension contract](a2ui-component-catalog-contract.md) when\nadding a component: catalog, validation, renderer, styles, edit boundaries,\ntests and authoring guidance must agree. Trusted runtime additions are possible;\nunknown component names in a manifest are rejected.\n\nAcceptance of a component name alone does not establish rendering fidelity,\neditable lifecycle support, or compatibility with every host; those require\nthe component's binding contract and actual runtime verification.\n\nPredefined DSL and A2UI-derived panels share this library, but generated panels\nmay use only the subset with an implemented generation/edit-authority contract.\nAn authored workspace is not automatically promoted into that subset.\nSupported generated results can be deterministically retained as DSL; unsupported\ncapabilities must fail explicitly, never disappear during conversion. This is\nnot an arbitrary bidirectional A2UI protocol converter.\n\n`question_list` is the standard controlled question interaction. Each source\nrecord uses `prompt`, optional `note`, `kind` (`text | single | multiple`),\noptional `choices[]` (`value`, `label`, `recommended`), `answer`, and optional\n`detail`. Text answers render as one multiline input; an existing text-question\n`detail` remains visible as read-only context rather than becoming a second\nanswer box. Single/multiple answers use accessible choice rows and may edit\n`detail`. Existing read-only context and choice supplements use the same\nlocalized label (without the optional-input suffix in reading mode). Cards\nwith a non-empty `answer` collapse to a readable result and can\nbe reopened for editing. The component writes only the fields exposed by that\ninteraction back to the owning record. It does not invent approval state, and an\nempty answer remains unanswered even when `detail` contains context. Native\nproviders may explicitly extend answer-state semantics for attachments, and\nmay add rounds or rejection around this base contract without making those\nextensions mandatory for other Kits.\n\nAuthored `question_list`, `question_rounds`, and `question_workspace` may declare\n`card_groups` with a unique `id`, `title`, and ordered `question_ids`. Members\nmust be contiguous in the existing record order and, for round workspaces, stay\nwithin one round. Invalid groups fall back to ordinary cards with a diagnostic;\ngrouping never reorders canonical records. Generated-origin Panels reject this\nauthored extension.\n\nEach group may declare a `presentation` object containing only optional boolean\n`always_expanded`, `show_detail`, and `show_attachments` properties. These select\nshared component behavior, not Bundle-specific styling. Omission preserves the\nusual collapse, detail, and attachment controls. Hiding a control preserves its\ncanonical data; keeping a card expanded does not grant editing permission.\nRead-only, disabled, protected, historical and rejection guards still apply.\n\n`question_workspace` composes the same question cards with the standard\n`panel_workspace` navigation shell. It groups records by optional numeric\n`round`, shows answer progress, and keeps only the selected group in the main\npane; records without a round form one current group. Its optional\n`description` is rendered through the shared sticky workspace Tip Bar above\nthe main content, never squeezed into the navigation sidebar. `question_rounds` is the\nbackward-compatible alias for this workspace behavior. Optional\n`multimodal_answer[]` entries use the Web App-compatible local reference shape\n(`type`, `file_md5`, `filename`, `mime_type`, `size_bytes`, `artifact_file`).\nThe client keeps pending bytes in a reserved browser-only transport, strips it\nbefore schema validation, and atomically saves only files still referenced by\ncanonical state. The transport is framework state, never a Bundle field.\n\nAuthored `question_workspace` / `question_rounds` nodes may explicitly set\n`question_policy.allow_choice_actions: true`. Expanded editable dynamic single\ncards offer “Switch to multiple choice”; multiple cards offer “Select all” /\n“Deselect all”. Omission or `false` preserves the existing controls. The shared\nruntime owns these actions and their localized styling, not Bundle CSS or an\nauthor-supplied `renderActions` callback. Switching changes only `kind` to\n`multiple`, preserving the exact answer bytes and keeping the editor open.\nSelect-all writes choice values in declared order through the existing\ncomma-separated `answer` contract; deselect-all writes an empty answer. Neither\naction changes detail, attachments, identity, choices or round. Records declared\nin `first_round_ids` are the fixed first-round configuration and do not receive\nthese actions; `protected_ids` still controls rejection only. Read-only,\ndisabled, rejected and read-only historical cards cannot invoke the actions.\nGenerated-origin/A2UI auto Panels reject this configuration, even when `false`;\ntheir existing answer/detail-only write authority and protected `kind` remain\nunchanged. Converting a generated view into an authored reusable panel does not\nsilently grant this capability: the author must opt in under the static contract.\n\n`panel_workspace` is the reusable panel-internal left navigation + main content\nlayout. It standardizes containment, scroll ownership and narrow-panel fallback;\nit does not define domain records or selection semantics. Use it rather than\ncopying a Kit-specific two-column shell.\n\nThe shared runtime `PanelWorkspaceNavigation` accepts optional per-item\n`description`, `supporting`, and `statusLabel` display slots alongside the\nlabel/current row. These are supplied display text, not canonical fields or\nnew DSL expressions. Omitted slots render no empty rows. The `meta` fallback\nremains supported. A marker requires both explicit `statusIndicator: true`\nand an existing `status`; a label-only item never gains an inferred status dot.\nFlat record navigation, question rounds, and future workspace consumers share\nthe same base navigation typography, spacing and selected appearance. Bundle\nCSS is not required. Hierarchical trees retain their separate structure.\nQuestion progress excludes rejected items from answered/completion checks,\nwhile retaining all group records in the displayed total and preserving fixed\nquestion grouping, stable IDs, selection and canonical answers. The original\nWeb App question panel used body round sections, not this sidebar; the shared\nsidebar is an enhanced structure using the original public navigation style,\nnot a claim of one-to-one restoration of a nonexistent original sidebar.\n\n`doc_lifecycle_studio` binds `objects`/`axes`/`actions` sections (validation\nfails loud when one is missing) and renders the fact table (actions × state\naxes, per-cell effects) plus process/derivation/ledger projections derived at\nrender time; unavailable views render disabled with a reason, never hidden.\n`rowview_workbench` renders the residue envelope (below) and requires a\n`source` declaring the add section it owns — the details-envelope schema\ncheck and the renderer are both scoped to that section; a workbench without\n`source` is rejected at compile time.\n\nIn editable mode `bpmn_canvas` edits bidirectionally: each process record's\n`name` and `steps` array (step name, `kind` task/gateway/event, order, add,\nremove) round-trip through the panel Save like any field edit.\n"
|
|
144
144
|
}
|
|
@@ -751,8 +751,8 @@
|
|
|
751
751
|
"sections": [
|
|
752
752
|
{
|
|
753
753
|
"file": "docs/dsl-spec.md",
|
|
754
|
-
"line":
|
|
755
|
-
"endLine":
|
|
754
|
+
"line": 958,
|
|
755
|
+
"endLine": 1169,
|
|
756
756
|
"heading": "`component` (trusted, extensible library)",
|
|
757
757
|
"content": "### `component` (trusted, extensible library)\n\nThe authoritative vocabulary is [`PANEL_COMPONENT_CATALOG`](../packages/core/src/panel-component-catalog.ts).\n`COMPONENT_KINDS`, workspace ownership, source bindings and the generated-panel\nsubset are derived from that one registry; this document is not a second\nvalidation whitelist. Bundle data cannot register executable components.\n\nThe shared library includes basic layouts and controls, question workspaces,\nrecord navigation/editing, diagrams, canvases, artifact readers and previews.\nFull-height workspace components preserve scroll and navigation ownership:\n`record_board`, `document_workspace`, `artifact_workspace`, `diagram_workspace`,\n`canvas_workspace`, `preview_workspace` and `navigation_workspace` expose their\nbehavior through explicit data bindings rather than Kit names. These are reusable\ncapabilities, not a guarantee that every record schema fits every workspace.\n\n`record_board.board.detail_sources` can embed exactly one `record_workspace`\nunder the selected card. Each `{section, reference}` binding declares an unordered\ndirect record collection and a readonly `record_select` back to the board's\nparent section. The child workspace sources must belong to those bindings.\nOwner and child storage paths cannot alias or overlap. The renderer filters\nchildren by the selected parent, binds new records to it, and merges hidden\nsibling records back into canonical updates. It refuses sibling-id replacement,\nreparenting and writes outside these collections. This is a view projection,\nnot a second stored copy; it does not support independently ordered child maps,\nnested `fields_path` records or artifact staging in this first composition slice.\nOrdinary `detail_sections` retain their existing same-record nested-form meaning.\n\n`record_board` uses full-width cards and a workspace-covering overview. Optional\n`board.group` binds a real grouping field. When omitted, the sidebar lists records\ndirectly, cards have no artificial group heading, and the overview connects the\nroot directly to records. Do not bind long summaries merely to satisfy grouping;\nthis projection never adds a grouping field to canonical records.\nSidebar selection scrolls to a card; it does not start editing. Description and\nbadge drafts have explicit Save/Cancel, while rejected records remain inspectable\nwithout granting edit access. Optional `board.id_field` binds a declared visible,\nreadonly `text` field and displays its existing string beside the card title and\nat the top of cover details. Inline details retain the same card header. It does\nnot add an ID editor, generate a fallback ID or write state; omission retains the\nexisting title-only presentation. `board.detail_fields` restricts the parent fields\nshown in the detail fold, and `details_title` localizes its heading. Optional nested\ndimensions can be added or removed without replacing unrelated record fields.\n`board.detail_fields_mode: fixed` instead shows every declared nested input and\nremoves dimension-level add/delete controls; collection item add/delete still\nuses its usual editor. Fields remain schema-optional, including empty inputs.\nViewing does not insert missing strings/maps. Omitted/`on_demand` retains the\nexisting optional-dimension behavior. This option grants no new write authority.\n\n`record_workspace.workspace_view: switch` puts the first child canvas over the\nwhole workspace. The edge action opens it, and the return action or a node's\ndetails action returns to the selected record. It does not add form/canvas tabs\nto the sidebar. Covered content stays mounted and inert to preserve selection,\ndrafts and the graph viewport without allowing hidden controls to receive input.\n\n`record_related_editor.record_table` is an authored-only table presentation of\nthe same child collection, not a conversion to a `rows` array. Its finite\n`columns: [{fields: [field_key, ...], label?: string}]` groups existing field\neditors into cells. Every non-hidden field declared for that child section must\nappear exactly once; hidden/foreign/duplicate bindings and unknown column keys\nare rejected. Column labels default to the first field's label and use the usual\nlocale resolution. A cell retains field visibility, help, requiredness, custom\nconditions and existing edit/derived-field rules. Record creation still binds\nthe selected parent, deletion preserves the normal section cleanup rules, and\n`inherit_from_graph` tables remain source-linked and read-only. The shared table\nwrapper owns horizontal scrolling at narrow widths. This does not promote the\ncomponent or this declaration to generated A2UI.\n\nAn authored graph hierarchy with `max_parents: 1` may opt into\n`parent_control: header`. The existing single-parent selector then sits beside\nthe selected record's form title, rather than above the whole inspector. It\nstill updates the same relation edge, rejects cycles, retains the source-record\nnavigation and shows the actual parent in read-only mode. Omission preserves\nthe prior inspector presentation; neither view creates an extra parent field.\n\n`diagram_workspace.diagram.detail_rows` groups declared read-only fields into\nresponsive fact cards. `chip_fields` selects string-list fields rendered as tags;\n`detail_hint_fields` supplies the populated field labels for the details action.\n`tags` maps declared enum fields to labels and finite semantic tones. These are\npresentation declarations, not new edit rights or storage. Diagram details cover\nonly the content pane; the navigator remains available. Leaving an edited diagram\nstill requires successful serialization through the existing save barrier.\n\n`diagram_workspace.diagram.label_source` can read a declared label from another\nsection bound to the same record collection. The optional `inspector` keeps a\ncontext editor alongside the BPMN canvas: `process_sections` edit the selected\nprocess; `nodes` binds `source`, `process_field`, `element_field`, `label_field`\nand same-collection `sections`. Optional `related` groups use a process reference\nand an optional `node_field`; `advanced: true` starts the group collapsed.\nReferences must be declared `record_select` fields targeting the corresponding\ncollection. Clicking an element resolves its exact ID within the selected\nprocess only; absent or duplicate bindings do not guess a record. Existing field\nedit permissions and the atomic artifact save barrier remain authoritative.\nThis is contextual navigation, not automatic synchronization of BPMN structure\nand business facts; authors must explain how structural changes are reconciled.\n\nFor an exact component contract and on-demand local type declarations, use the\nauthoring inspector from the repository root:\n\n```sh\nnode .agents/skills/design-bundle-creator/scripts/inspect-panel-component.mjs . navigation_workspace --type ComponentNode.navigation_map.edges\n```\n\nUse the [component extension contract](a2ui-component-catalog-contract.md) when\nadding a component: catalog, validation, renderer, styles, edit boundaries,\ntests and authoring guidance must agree. Trusted runtime additions are possible;\nunknown component names in a manifest are rejected.\n\nAcceptance of a component name alone does not establish rendering fidelity,\neditable lifecycle support, or compatibility with every host; those require\nthe component's binding contract and actual runtime verification.\n\nPredefined DSL and A2UI-derived panels share this library, but generated panels\nmay use only the subset with an implemented generation/edit-authority contract.\nAn authored workspace is not automatically promoted into that subset.\nSupported generated results can be deterministically retained as DSL; unsupported\ncapabilities must fail explicitly, never disappear during conversion. This is\nnot an arbitrary bidirectional A2UI protocol converter.\n\n`question_list` is the standard controlled question interaction. Each source\nrecord uses `prompt`, optional `note`, `kind` (`text | single | multiple`),\noptional `choices[]` (`value`, `label`, `recommended`), `answer`, and optional\n`detail`. Text answers render as one multiline input; an existing text-question\n`detail` remains visible as read-only context rather than becoming a second\nanswer box. Single/multiple answers use accessible choice rows and may edit\n`detail`. Existing read-only context and choice supplements use the same\nlocalized label (without the optional-input suffix in reading mode). Cards\nwith a non-empty `answer` collapse to a readable result and can\nbe reopened for editing. The component writes only the fields exposed by that\ninteraction back to the owning record. It does not invent approval state, and an\nempty answer remains unanswered even when `detail` contains context. Native\nproviders may explicitly extend answer-state semantics for attachments, and\nmay add rounds or rejection around this base contract without making those\nextensions mandatory for other Kits.\n\nAuthored `question_list`, `question_rounds`, and `question_workspace` may declare\n`card_groups` with a unique `id`, `title`, and ordered `question_ids`. Members\nmust be contiguous in the existing record order and, for round workspaces, stay\nwithin one round. Invalid groups fall back to ordinary cards with a diagnostic;\ngrouping never reorders canonical records. Generated-origin Panels reject this\nauthored extension.\n\nEach group may declare a `presentation` object containing only optional boolean\n`always_expanded`, `show_detail`, and `show_attachments` properties. These select\nshared component behavior, not Bundle-specific styling. Omission preserves the\nusual collapse, detail, and attachment controls. Hiding a control preserves its\ncanonical data; keeping a card expanded does not grant editing permission.\nRead-only, disabled, protected, historical and rejection guards still apply.\n\n`question_workspace` composes the same question cards with the standard\n`panel_workspace` navigation shell. It groups records by optional numeric\n`round`, shows answer progress, and keeps only the selected group in the main\npane; records without a round form one current group. Its optional\n`description` is rendered through the shared sticky workspace Tip Bar above\nthe main content, never squeezed into the navigation sidebar. `question_rounds` is the\nbackward-compatible alias for this workspace behavior. Optional\n`multimodal_answer[]` entries use the Web App-compatible local reference shape\n(`type`, `file_md5`, `filename`, `mime_type`, `size_bytes`, `artifact_file`).\nThe client keeps pending bytes in a reserved browser-only transport, strips it\nbefore schema validation, and atomically saves only files still referenced by\ncanonical state. The transport is framework state, never a Bundle field.\n\nAuthored `question_workspace` / `question_rounds` nodes may explicitly set\n`question_policy.allow_choice_actions: true`. Expanded editable dynamic single\ncards offer “Switch to multiple choice”; multiple cards offer “Select all” /\n“Deselect all”. Omission or `false` preserves the existing controls. The shared\nruntime owns these actions and their localized styling, not Bundle CSS or an\nauthor-supplied `renderActions` callback. Switching changes only `kind` to\n`multiple`, preserving the exact answer bytes and keeping the editor open.\nSelect-all writes choice values in declared order through the existing\ncomma-separated `answer` contract; deselect-all writes an empty answer. Neither\naction changes detail, attachments, identity, choices or round. Records declared\nin `first_round_ids` are the fixed first-round configuration and do not receive\nthese actions; `protected_ids` still controls rejection only. Read-only,\ndisabled, rejected and read-only historical cards cannot invoke the actions.\nGenerated-origin/A2UI auto Panels reject this configuration, even when `false`;\ntheir existing answer/detail-only write authority and protected `kind` remain\nunchanged. Converting a generated view into an authored reusable panel does not\nsilently grant this capability: the author must opt in under the static contract.\n\n`panel_workspace` is the reusable panel-internal left navigation + main content\nlayout. It standardizes containment, scroll ownership and narrow-panel fallback;\nit does not define domain records or selection semantics. Use it rather than\ncopying a Kit-specific two-column shell.\n\nThe shared runtime `PanelWorkspaceNavigation` accepts optional per-item\n`description`, `supporting`, and `statusLabel` display slots alongside the\nlabel/current row. These are supplied display text, not canonical fields or\nnew DSL expressions. Omitted slots render no empty rows. The `meta` fallback\nremains supported. A marker requires both explicit `statusIndicator: true`\nand an existing `status`; a label-only item never gains an inferred status dot.\nFlat record navigation, question rounds, and future workspace consumers share\nthe same base navigation typography, spacing and selected appearance. Bundle\nCSS is not required. Hierarchical trees retain their separate structure.\nQuestion progress excludes rejected items from answered/completion checks,\nwhile retaining all group records in the displayed total and preserving fixed\nquestion grouping, stable IDs, selection and canonical answers. The original\nWeb App question panel used body round sections, not this sidebar; the shared\nsidebar is an enhanced structure using the original public navigation style,\nnot a claim of one-to-one restoration of a nonexistent original sidebar.\n\n`doc_lifecycle_studio` binds `objects`/`axes`/`actions` sections (validation\nfails loud when one is missing) and renders the fact table (actions × state\naxes, per-cell effects) plus process/derivation/ledger projections derived at\nrender time; unavailable views render disabled with a reason, never hidden.\n`rowview_workbench` renders the residue envelope (below) and requires a\n`source` declaring the add section it owns — the details-envelope schema\ncheck and the renderer are both scoped to that section; a workbench without\n`source` is rejected at compile time.\n\nIn editable mode `bpmn_canvas` edits bidirectionally: each process record's\n`name` and `steps` array (step name, `kind` task/gateway/event, order, add,\nremove) round-trip through the panel Save like any field edit.\n"
|
|
758
758
|
}
|
|
@@ -867,8 +867,8 @@
|
|
|
867
867
|
"sections": [
|
|
868
868
|
{
|
|
869
869
|
"file": "docs/dsl-spec.md",
|
|
870
|
-
"line":
|
|
871
|
-
"endLine":
|
|
870
|
+
"line": 958,
|
|
871
|
+
"endLine": 1169,
|
|
872
872
|
"heading": "`component` (trusted, extensible library)",
|
|
873
873
|
"content": "### `component` (trusted, extensible library)\n\nThe authoritative vocabulary is [`PANEL_COMPONENT_CATALOG`](../packages/core/src/panel-component-catalog.ts).\n`COMPONENT_KINDS`, workspace ownership, source bindings and the generated-panel\nsubset are derived from that one registry; this document is not a second\nvalidation whitelist. Bundle data cannot register executable components.\n\nThe shared library includes basic layouts and controls, question workspaces,\nrecord navigation/editing, diagrams, canvases, artifact readers and previews.\nFull-height workspace components preserve scroll and navigation ownership:\n`record_board`, `document_workspace`, `artifact_workspace`, `diagram_workspace`,\n`canvas_workspace`, `preview_workspace` and `navigation_workspace` expose their\nbehavior through explicit data bindings rather than Kit names. These are reusable\ncapabilities, not a guarantee that every record schema fits every workspace.\n\n`record_board.board.detail_sources` can embed exactly one `record_workspace`\nunder the selected card. Each `{section, reference}` binding declares an unordered\ndirect record collection and a readonly `record_select` back to the board's\nparent section. The child workspace sources must belong to those bindings.\nOwner and child storage paths cannot alias or overlap. The renderer filters\nchildren by the selected parent, binds new records to it, and merges hidden\nsibling records back into canonical updates. It refuses sibling-id replacement,\nreparenting and writes outside these collections. This is a view projection,\nnot a second stored copy; it does not support independently ordered child maps,\nnested `fields_path` records or artifact staging in this first composition slice.\nOrdinary `detail_sections` retain their existing same-record nested-form meaning.\n\n`record_board` uses full-width cards and a workspace-covering overview. Optional\n`board.group` binds a real grouping field. When omitted, the sidebar lists records\ndirectly, cards have no artificial group heading, and the overview connects the\nroot directly to records. Do not bind long summaries merely to satisfy grouping;\nthis projection never adds a grouping field to canonical records.\nSidebar selection scrolls to a card; it does not start editing. Description and\nbadge drafts have explicit Save/Cancel, while rejected records remain inspectable\nwithout granting edit access. Optional `board.id_field` binds a declared visible,\nreadonly `text` field and displays its existing string beside the card title and\nat the top of cover details. Inline details retain the same card header. It does\nnot add an ID editor, generate a fallback ID or write state; omission retains the\nexisting title-only presentation. `board.detail_fields` restricts the parent fields\nshown in the detail fold, and `details_title` localizes its heading. Optional nested\ndimensions can be added or removed without replacing unrelated record fields.\n`board.detail_fields_mode: fixed` instead shows every declared nested input and\nremoves dimension-level add/delete controls; collection item add/delete still\nuses its usual editor. Fields remain schema-optional, including empty inputs.\nViewing does not insert missing strings/maps. Omitted/`on_demand` retains the\nexisting optional-dimension behavior. This option grants no new write authority.\n\n`record_workspace.workspace_view: switch` puts the first child canvas over the\nwhole workspace. The edge action opens it, and the return action or a node's\ndetails action returns to the selected record. It does not add form/canvas tabs\nto the sidebar. Covered content stays mounted and inert to preserve selection,\ndrafts and the graph viewport without allowing hidden controls to receive input.\n\n`record_related_editor.record_table` is an authored-only table presentation of\nthe same child collection, not a conversion to a `rows` array. Its finite\n`columns: [{fields: [field_key, ...], label?: string}]` groups existing field\neditors into cells. Every non-hidden field declared for that child section must\nappear exactly once; hidden/foreign/duplicate bindings and unknown column keys\nare rejected. Column labels default to the first field's label and use the usual\nlocale resolution. A cell retains field visibility, help, requiredness, custom\nconditions and existing edit/derived-field rules. Record creation still binds\nthe selected parent, deletion preserves the normal section cleanup rules, and\n`inherit_from_graph` tables remain source-linked and read-only. The shared table\nwrapper owns horizontal scrolling at narrow widths. This does not promote the\ncomponent or this declaration to generated A2UI.\n\nAn authored graph hierarchy with `max_parents: 1` may opt into\n`parent_control: header`. The existing single-parent selector then sits beside\nthe selected record's form title, rather than above the whole inspector. It\nstill updates the same relation edge, rejects cycles, retains the source-record\nnavigation and shows the actual parent in read-only mode. Omission preserves\nthe prior inspector presentation; neither view creates an extra parent field.\n\n`diagram_workspace.diagram.detail_rows` groups declared read-only fields into\nresponsive fact cards. `chip_fields` selects string-list fields rendered as tags;\n`detail_hint_fields` supplies the populated field labels for the details action.\n`tags` maps declared enum fields to labels and finite semantic tones. These are\npresentation declarations, not new edit rights or storage. Diagram details cover\nonly the content pane; the navigator remains available. Leaving an edited diagram\nstill requires successful serialization through the existing save barrier.\n\n`diagram_workspace.diagram.label_source` can read a declared label from another\nsection bound to the same record collection. The optional `inspector` keeps a\ncontext editor alongside the BPMN canvas: `process_sections` edit the selected\nprocess; `nodes` binds `source`, `process_field`, `element_field`, `label_field`\nand same-collection `sections`. Optional `related` groups use a process reference\nand an optional `node_field`; `advanced: true` starts the group collapsed.\nReferences must be declared `record_select` fields targeting the corresponding\ncollection. Clicking an element resolves its exact ID within the selected\nprocess only; absent or duplicate bindings do not guess a record. Existing field\nedit permissions and the atomic artifact save barrier remain authoritative.\nThis is contextual navigation, not automatic synchronization of BPMN structure\nand business facts; authors must explain how structural changes are reconciled.\n\nFor an exact component contract and on-demand local type declarations, use the\nauthoring inspector from the repository root:\n\n```sh\nnode .agents/skills/design-bundle-creator/scripts/inspect-panel-component.mjs . navigation_workspace --type ComponentNode.navigation_map.edges\n```\n\nUse the [component extension contract](a2ui-component-catalog-contract.md) when\nadding a component: catalog, validation, renderer, styles, edit boundaries,\ntests and authoring guidance must agree. Trusted runtime additions are possible;\nunknown component names in a manifest are rejected.\n\nAcceptance of a component name alone does not establish rendering fidelity,\neditable lifecycle support, or compatibility with every host; those require\nthe component's binding contract and actual runtime verification.\n\nPredefined DSL and A2UI-derived panels share this library, but generated panels\nmay use only the subset with an implemented generation/edit-authority contract.\nAn authored workspace is not automatically promoted into that subset.\nSupported generated results can be deterministically retained as DSL; unsupported\ncapabilities must fail explicitly, never disappear during conversion. This is\nnot an arbitrary bidirectional A2UI protocol converter.\n\n`question_list` is the standard controlled question interaction. Each source\nrecord uses `prompt`, optional `note`, `kind` (`text | single | multiple`),\noptional `choices[]` (`value`, `label`, `recommended`), `answer`, and optional\n`detail`. Text answers render as one multiline input; an existing text-question\n`detail` remains visible as read-only context rather than becoming a second\nanswer box. Single/multiple answers use accessible choice rows and may edit\n`detail`. Existing read-only context and choice supplements use the same\nlocalized label (without the optional-input suffix in reading mode). Cards\nwith a non-empty `answer` collapse to a readable result and can\nbe reopened for editing. The component writes only the fields exposed by that\ninteraction back to the owning record. It does not invent approval state, and an\nempty answer remains unanswered even when `detail` contains context. Native\nproviders may explicitly extend answer-state semantics for attachments, and\nmay add rounds or rejection around this base contract without making those\nextensions mandatory for other Kits.\n\nAuthored `question_list`, `question_rounds`, and `question_workspace` may declare\n`card_groups` with a unique `id`, `title`, and ordered `question_ids`. Members\nmust be contiguous in the existing record order and, for round workspaces, stay\nwithin one round. Invalid groups fall back to ordinary cards with a diagnostic;\ngrouping never reorders canonical records. Generated-origin Panels reject this\nauthored extension.\n\nEach group may declare a `presentation` object containing only optional boolean\n`always_expanded`, `show_detail`, and `show_attachments` properties. These select\nshared component behavior, not Bundle-specific styling. Omission preserves the\nusual collapse, detail, and attachment controls. Hiding a control preserves its\ncanonical data; keeping a card expanded does not grant editing permission.\nRead-only, disabled, protected, historical and rejection guards still apply.\n\n`question_workspace` composes the same question cards with the standard\n`panel_workspace` navigation shell. It groups records by optional numeric\n`round`, shows answer progress, and keeps only the selected group in the main\npane; records without a round form one current group. Its optional\n`description` is rendered through the shared sticky workspace Tip Bar above\nthe main content, never squeezed into the navigation sidebar. `question_rounds` is the\nbackward-compatible alias for this workspace behavior. Optional\n`multimodal_answer[]` entries use the Web App-compatible local reference shape\n(`type`, `file_md5`, `filename`, `mime_type`, `size_bytes`, `artifact_file`).\nThe client keeps pending bytes in a reserved browser-only transport, strips it\nbefore schema validation, and atomically saves only files still referenced by\ncanonical state. The transport is framework state, never a Bundle field.\n\nAuthored `question_workspace` / `question_rounds` nodes may explicitly set\n`question_policy.allow_choice_actions: true`. Expanded editable dynamic single\ncards offer “Switch to multiple choice”; multiple cards offer “Select all” /\n“Deselect all”. Omission or `false` preserves the existing controls. The shared\nruntime owns these actions and their localized styling, not Bundle CSS or an\nauthor-supplied `renderActions` callback. Switching changes only `kind` to\n`multiple`, preserving the exact answer bytes and keeping the editor open.\nSelect-all writes choice values in declared order through the existing\ncomma-separated `answer` contract; deselect-all writes an empty answer. Neither\naction changes detail, attachments, identity, choices or round. Records declared\nin `first_round_ids` are the fixed first-round configuration and do not receive\nthese actions; `protected_ids` still controls rejection only. Read-only,\ndisabled, rejected and read-only historical cards cannot invoke the actions.\nGenerated-origin/A2UI auto Panels reject this configuration, even when `false`;\ntheir existing answer/detail-only write authority and protected `kind` remain\nunchanged. Converting a generated view into an authored reusable panel does not\nsilently grant this capability: the author must opt in under the static contract.\n\n`panel_workspace` is the reusable panel-internal left navigation + main content\nlayout. It standardizes containment, scroll ownership and narrow-panel fallback;\nit does not define domain records or selection semantics. Use it rather than\ncopying a Kit-specific two-column shell.\n\nThe shared runtime `PanelWorkspaceNavigation` accepts optional per-item\n`description`, `supporting`, and `statusLabel` display slots alongside the\nlabel/current row. These are supplied display text, not canonical fields or\nnew DSL expressions. Omitted slots render no empty rows. The `meta` fallback\nremains supported. A marker requires both explicit `statusIndicator: true`\nand an existing `status`; a label-only item never gains an inferred status dot.\nFlat record navigation, question rounds, and future workspace consumers share\nthe same base navigation typography, spacing and selected appearance. Bundle\nCSS is not required. Hierarchical trees retain their separate structure.\nQuestion progress excludes rejected items from answered/completion checks,\nwhile retaining all group records in the displayed total and preserving fixed\nquestion grouping, stable IDs, selection and canonical answers. The original\nWeb App question panel used body round sections, not this sidebar; the shared\nsidebar is an enhanced structure using the original public navigation style,\nnot a claim of one-to-one restoration of a nonexistent original sidebar.\n\n`doc_lifecycle_studio` binds `objects`/`axes`/`actions` sections (validation\nfails loud when one is missing) and renders the fact table (actions × state\naxes, per-cell effects) plus process/derivation/ledger projections derived at\nrender time; unavailable views render disabled with a reason, never hidden.\n`rowview_workbench` renders the residue envelope (below) and requires a\n`source` declaring the add section it owns — the details-envelope schema\ncheck and the renderer are both scoped to that section; a workbench without\n`source` is rejected at compile time.\n\nIn editable mode `bpmn_canvas` edits bidirectionally: each process record's\n`name` and `steps` array (step name, `kind` task/gateway/event, order, add,\nremove) round-trip through the panel Save like any field edit.\n"
|
|
874
874
|
}
|
|
@@ -984,15 +984,15 @@
|
|
|
984
984
|
"sections": [
|
|
985
985
|
{
|
|
986
986
|
"file": "docs/dsl-spec.md",
|
|
987
|
-
"line":
|
|
988
|
-
"endLine":
|
|
987
|
+
"line": 511,
|
|
988
|
+
"endLine": 655,
|
|
989
989
|
"heading": "`record_form`: headers, body composition and order actions",
|
|
990
990
|
"content": "### `record_form`: headers, body composition and order actions\n\n`sections[].form` configures shared `record_form` presentation, including forms\ncomposed by an inspector or related-record editor. Omission preserves the old\nrecord label, body fields and order-dependent move controls.\n\n```yaml\nsections:\n - id: entries\n title: Entries\n order: entry_order\n form:\n reorder: false\n header: {variant: detail, title: {field: caption, editable: true}}\n - id: notes\n title: Notes\n form:\n reorder: false\n header: {variant: card, title: {text: Note, numbered: true}}\n```\n\nThe fixed `detail` header is 44px high, with a 32px editable title; `card` is\n40px high with a display title and optional ordinal in the currently displayed\nrecord list. Header text supports normal Bundle translation tokens. Ordinals\nare presentation, not record identities or newly stored facts.\n\nA field-bound title must reference an unconditional declared `text` field of\nthe same section, never its identity. `editable: true` additionally excludes\nreadonly and derived fields and schema metadata/references. It uses the same\nfield binding/edit channel as the body, and consumes that field once: no second\nbody input or title copy is created. Omitted/false `editable` presents it as\ntext. Host readonly mode never renders a title editor or lifecycle actions.\nTitle edits retain all other record fields, IDs, references and order. The\nexisting confirm/atomic-delete behavior is unaffected.\n\n`reorder: false` hides move controls only. It does not remove stored order,\nchange how records are read/added/deleted, or authorize other writes. `true`\nstill requires an existing durable order binding. This configuration is a\nstatic Panel capability: generated-origin A2UI panels currently reject `form`\nexplicitly on generation/export/reload rather than dropping it or widening\ntheir write permissions.\n\n`form.body` is an optional finite list of `field`, `row`, `group`, and `tabs` items:\n\n```yaml\nform:\n body:\n - kind: row\n items:\n - {kind: text, text: '$t:decisionPrefix'}\n - {kind: field, field: decision, label: visually_hidden, width: auto}\n - {kind: field, field: description, label: visually_hidden, width: fill}\n - kind: group\n title: $t:conditions\n description: $t:conditionsHelp\n separator: true\n items: [{kind: field, field: condition, label: inline}]\n```\n\nRows contain fields or display-only text; groups contain fields or rows, never\nnested groups. The shapes are closed, with no scripts, CSS or expressions.\nGroup titles are optional: use the field caption for one input, and title a\nmulti-field scope only when it adds meaning. The shared renderer removes an\nexact duplicate title for a single direct field with a visible caption and no\nsidecar. It retains differently named scopes, multi-field headings, sidecar\nheadings and the sole heading of a visually hidden caption. Required cues and\naccessible names remain bound to the original field; near-synonyms are an\nauthoring review concern, not runtime guesses. Field groups share the 16px\nsection / 8px control rhythm; field help has 8px before it and no trailing\nmargin, so it cannot add a second section gap.\nGroups may additionally declare one read-only preview beside their fields:\n\n```yaml\nsidecar:\n component: record_preview\n title: $t:preview\n preview: {title: title, body: description, action: next_action, empty: '$t:empty'}\n```\n\nThis reuses `record_preview`, bound to the exact record rendered by the form,\nincluding nested `records_path`/`fields_path`; it needs no workspace selection\nand cannot bind another section or execute the displayed action. The closed\nslot admits only `component`, optional display `title`, and `preview`.\nPreview title/body and optional action reference declared, unconditional, non-hidden text or\ntextarea fields in the same section. Binding names never translate; only the\nsidecar display title and `preview.empty` do. Fields remain editable through\ntheir existing canonical channel; the preview owns no state or write channel.\nIt stacks below fields in narrow containers. An empty conditional group still\ndisappears rather than exposing its hidden fields through a preview. This is a\nstatic authored capability; generated A2UI forms reject it explicitly along\nwith `form`, not silently drop it during retention/export.\n\nField references are same-section declared undotted keys, cannot be binding-only\nhidden fields, and cannot repeat another body/header editor. Conditional fields\nkeep their existing visibility/cleanup rules; empty groups and rows whose fields\nare all invisible disappear. Explicit text-only rows are allowed. Unconsumed\nvisible fields are appended with their original renderer: partial layouts never\nsilently omit facts. `label` is `stacked` (default), `inline` (stacks in narrow\ncontainers), or `visually_hidden` (accessible name remains). `width` is `auto`\nor `fill`; this changes presentation, not write authority. Group titles/help and\nrow text use existing Bundle translations; keys, IDs and canonical values do not.\n\nFor longer records, a top-level body item may declare bounded record-local tabs:\n\n```yaml\n- kind: tabs\n id: record-design\n title: Design views\n tabs:\n - id: experience\n title: Experience\n items: [{kind: field, field: purpose}]\n - id: agreements\n title: Agreements\n items:\n - kind: group\n title: Optional references\n collapsible: true\n items: [{kind: field, field: notes}]\n```\n\nTab-group IDs are unique in a body, and tab IDs unique within that group. Tabs\ncontain only the existing field/row/group items: no nested tabs or groups.\nThey reuse the shared `tabs` component, including keyboard navigation, stable\nID selection and mounted inactive editors. Fields remain unique across all\npages and the record header; fallback fields are appended once outside tabs.\nChanging page, language or disclosure state emits no canonical edit and never\nclears existing values. Readonly follows the original field's authority.\n`group.collapsible: true` requires a nonempty title, starts closed and uses the\nshared disclosure glyph with native keyboard-accessible details semantics.\nIts content remains mounted; display state is not another data field. Choose\nthis only for optional material, not to hide an unresolved blocking decision.\nBoth additions are static authored form presentation; generated-origin A2UI\nstill rejects the complete `form` extension rather than silently dropping it.\n\n`EditorField.choice_layout` is `column`, `row_wrap`, or `row_scroll`, only for\n`radio`, `radio_custom`, and `multi_select`. Omission keeps the old layout.\n`custom_focus: true` is only for `radio_custom` and focuses its custom input after\nthe user selects Other, not on mount, polling, locale switching or readonly.\n`allow_clear: false` is only for `select` and suppresses new empty selections.\nAn existing missing value gets a disabled blank placeholder; a stale saved value\nremains visible. Neither is normalized on load. Omitted/true retains the original\nempty option and `undefined` edit. These field presentation extensions, like\n`form`, explicitly reject in generated A2UI panels until separately supported.\n"
|
|
991
991
|
},
|
|
992
992
|
{
|
|
993
993
|
"file": "docs/dsl-spec.md",
|
|
994
|
-
"line":
|
|
995
|
-
"endLine":
|
|
994
|
+
"line": 737,
|
|
995
|
+
"endLine": 853,
|
|
996
996
|
"heading": "Field extensions for `record_form`",
|
|
997
997
|
"content": "### Field extensions for `record_form`\n\n```yaml\nfields:\n - key: detail\n control: textarea\n applies_to: [adaptations]\n visible_when: { field: decision, in: [adapt] } # conditional visibility\n - key: standard_ref\n control: record_select\n applies_to: [adaptations]\n options_from_section: standards # options = section records\n - key: module_ref\n control: record_select\n applies_to: [adaptations]\n options_from_panel: # cross-panel option source\n panel_type: function_modules\n section_id: functions\n - key: steps\n control: rows # typed sub-table\n applies_to: [adaptations]\n row_name: 步骤\n max_rows: 3 # default 50\n columns:\n - { key: title, control: text, label: 步骤 }\n - key: kind\n control: select\n label: 类型\n options: [{ value: dev, label: 开发 }]\n - { key: owner, control: ref, label: 负责标准, ref_sections: [standards] }\n - key: sources\n control: source_list # `kind:name` ref chips\n applies_to: [adaptations]\n```\n\n- `visible_when` hides the field unless another field of the same record\n currently holds a value in `in`; the gate re-evaluates on every edit.\n Authored fields may use `visible_when: {all: [{field: source_ref, in: ['']},\n {field: connection, in: [existing]}]}` for a nonempty, flat conjunction of\n these same conditions. Missing/null scalar values match `''`; arrays match\n if any string member matches. Every clause must match. Hidden values are\n retained unless the existing explicit `clear_when_hidden` contract applies;\n a change to any declared dependency then re-evaluates that contract. No\n recursive condition/expression language or executable predicates are allowed.\n- Authored `label_when: [{field: mode, in: [automatic], label: When it runs}]`\n selects display copy from sibling values, using the same matching rule as\n `visible_when`. The first matching entry wins; no match keeps `label` (or the\n field key). Dependencies must be declared on a shared section, or on the same\n child for `record_map.item_fields`. Labels support `$t:` translations and are\n used consistently for captions and accessible control names. This never\n changes bindings, values, requirements or save rules. Hide inapplicable fields\n with `visible_when`; do not erase data unless an existing, explicit clearing\n contract requires it. Generated Auto Panel editor fields do not yet accept\n `label_when` (like the existing authored visibility extension).\n- `options_from_section` / `options_from_panel` resolve choice options from\n record ids (label = record title). Cross-panel refs resolve through the\n host-supplied `panelData` render option; an absent resolver yields no\n options and never copies data into this panel.\n- Static `options[]` entries may carry `when: { field, in }` to offer the\n option only while another field of the record matches.\n- `rows` edits an array of row objects cell-by-cell; column controls are\n `text | textarea | select | ref`. `ref` columns need `ref_sections`\n (this panel) or `options_from_panel` (cross-panel).\n- `source_list` edits an array of `kind:name` reference strings and renders\n readable chips (`standard:*` → 标准参考, `upload|user|research|ai`\n suffixed); unknown kinds pass through.\n- `token_list` edits free string lists with optional suggested `options`. `token_layout:\n cards` displays option descriptions and `custom_description` for custom entries.\n Authored fields may opt into `token_add_mode: menu`: a keyboard-accessible preset\n menu disables already selected values and opens a cancellable custom-entry card.\n In card layout, the add/custom card shares the existing card grid (two columns\n in a wide workspace, one in a narrow workspace). `token_add_description` supplies\n a content-owned subtitle. `token_custom_icon` and each option's `icon` can select\n the shared `message-square` or `plug` glyph; arbitrary markup and unknown glyphs\n are rejected. These attributes are only valid on `token_list`, never generated\n scalar fields. Omission preserves the original inline editor.\n Options may declare `menu_description` and `selected_description` for distinct\n unselected/selected menu copy, both falling back to `description`. Saved cards\n keep the original `description`; copy never changes stored values.\n Cancel/Escape discard only the unsaved input; Add/Enter split and deduplicate values\n into the same bound list. Selecting another record discards the local entry draft.\n Omission or `inline` preserves the existing preset select and always-visible input.\n This static extension grants no new write scope; generated panels reject it explicitly.\n\n ```yaml\n - key: delivery_methods\n control: token_list\n token_layout: cards\n token_add_mode: menu\n custom_description: Requires an external service\n options: [{value: internal, label: Internal, description: Built in}]\n applies_to: [records]\n ```\n\nSemantics decisions:\n\n- Resolved options are deduped by value; earlier sources win (static\n `options`, then `options_from_section`, then `options_from_panel`).\n Record ids are Kit-level global reference ids.\n- Stored row/ref arrays are never destructively normalized: a\n non-conforming member disables the whole field's editing with a clear\n diagnostic while the raw value is preserved verbatim; explicit deletion\n (after fixing the data) is the only removal path.\n- `rows` keys React nodes through a module-level identity map over row\n objects, so deleting a middle row never re-keys the surviving rows;\n edited rows are cloned, untouched rows keep identity.\n- `multi_select`/`record_multi_select` round-trip as string arrays; a\n comma-separated string is an accepted input contract on read (split and\n trimmed), while writes always emit arrays.\n- `record_form` carries a generic record lifecycle in editable mode:\n add/remove/reorder emit whole-section rewrites through the panel-update\n channel (map insertion order is the record order); read-only renders no\n lifecycle affordances.\n- `visible_when` and option `when` gates must reference a declared field\n sharing at least one `applies_to` section (column option gates must\n reference a column of the same `rows` field).\n"
|
|
998
998
|
}
|
|
@@ -1107,8 +1107,8 @@
|
|
|
1107
1107
|
"sections": [
|
|
1108
1108
|
{
|
|
1109
1109
|
"file": "docs/dsl-spec.md",
|
|
1110
|
-
"line":
|
|
1111
|
-
"endLine":
|
|
1110
|
+
"line": 958,
|
|
1111
|
+
"endLine": 1169,
|
|
1112
1112
|
"heading": "`component` (trusted, extensible library)",
|
|
1113
1113
|
"content": "### `component` (trusted, extensible library)\n\nThe authoritative vocabulary is [`PANEL_COMPONENT_CATALOG`](../packages/core/src/panel-component-catalog.ts).\n`COMPONENT_KINDS`, workspace ownership, source bindings and the generated-panel\nsubset are derived from that one registry; this document is not a second\nvalidation whitelist. Bundle data cannot register executable components.\n\nThe shared library includes basic layouts and controls, question workspaces,\nrecord navigation/editing, diagrams, canvases, artifact readers and previews.\nFull-height workspace components preserve scroll and navigation ownership:\n`record_board`, `document_workspace`, `artifact_workspace`, `diagram_workspace`,\n`canvas_workspace`, `preview_workspace` and `navigation_workspace` expose their\nbehavior through explicit data bindings rather than Kit names. These are reusable\ncapabilities, not a guarantee that every record schema fits every workspace.\n\n`record_board.board.detail_sources` can embed exactly one `record_workspace`\nunder the selected card. Each `{section, reference}` binding declares an unordered\ndirect record collection and a readonly `record_select` back to the board's\nparent section. The child workspace sources must belong to those bindings.\nOwner and child storage paths cannot alias or overlap. The renderer filters\nchildren by the selected parent, binds new records to it, and merges hidden\nsibling records back into canonical updates. It refuses sibling-id replacement,\nreparenting and writes outside these collections. This is a view projection,\nnot a second stored copy; it does not support independently ordered child maps,\nnested `fields_path` records or artifact staging in this first composition slice.\nOrdinary `detail_sections` retain their existing same-record nested-form meaning.\n\n`record_board` uses full-width cards and a workspace-covering overview. Optional\n`board.group` binds a real grouping field. When omitted, the sidebar lists records\ndirectly, cards have no artificial group heading, and the overview connects the\nroot directly to records. Do not bind long summaries merely to satisfy grouping;\nthis projection never adds a grouping field to canonical records.\nSidebar selection scrolls to a card; it does not start editing. Description and\nbadge drafts have explicit Save/Cancel, while rejected records remain inspectable\nwithout granting edit access. Optional `board.id_field` binds a declared visible,\nreadonly `text` field and displays its existing string beside the card title and\nat the top of cover details. Inline details retain the same card header. It does\nnot add an ID editor, generate a fallback ID or write state; omission retains the\nexisting title-only presentation. `board.detail_fields` restricts the parent fields\nshown in the detail fold, and `details_title` localizes its heading. Optional nested\ndimensions can be added or removed without replacing unrelated record fields.\n`board.detail_fields_mode: fixed` instead shows every declared nested input and\nremoves dimension-level add/delete controls; collection item add/delete still\nuses its usual editor. Fields remain schema-optional, including empty inputs.\nViewing does not insert missing strings/maps. Omitted/`on_demand` retains the\nexisting optional-dimension behavior. This option grants no new write authority.\n\n`record_workspace.workspace_view: switch` puts the first child canvas over the\nwhole workspace. The edge action opens it, and the return action or a node's\ndetails action returns to the selected record. It does not add form/canvas tabs\nto the sidebar. Covered content stays mounted and inert to preserve selection,\ndrafts and the graph viewport without allowing hidden controls to receive input.\n\n`record_related_editor.record_table` is an authored-only table presentation of\nthe same child collection, not a conversion to a `rows` array. Its finite\n`columns: [{fields: [field_key, ...], label?: string}]` groups existing field\neditors into cells. Every non-hidden field declared for that child section must\nappear exactly once; hidden/foreign/duplicate bindings and unknown column keys\nare rejected. Column labels default to the first field's label and use the usual\nlocale resolution. A cell retains field visibility, help, requiredness, custom\nconditions and existing edit/derived-field rules. Record creation still binds\nthe selected parent, deletion preserves the normal section cleanup rules, and\n`inherit_from_graph` tables remain source-linked and read-only. The shared table\nwrapper owns horizontal scrolling at narrow widths. This does not promote the\ncomponent or this declaration to generated A2UI.\n\nAn authored graph hierarchy with `max_parents: 1` may opt into\n`parent_control: header`. The existing single-parent selector then sits beside\nthe selected record's form title, rather than above the whole inspector. It\nstill updates the same relation edge, rejects cycles, retains the source-record\nnavigation and shows the actual parent in read-only mode. Omission preserves\nthe prior inspector presentation; neither view creates an extra parent field.\n\n`diagram_workspace.diagram.detail_rows` groups declared read-only fields into\nresponsive fact cards. `chip_fields` selects string-list fields rendered as tags;\n`detail_hint_fields` supplies the populated field labels for the details action.\n`tags` maps declared enum fields to labels and finite semantic tones. These are\npresentation declarations, not new edit rights or storage. Diagram details cover\nonly the content pane; the navigator remains available. Leaving an edited diagram\nstill requires successful serialization through the existing save barrier.\n\n`diagram_workspace.diagram.label_source` can read a declared label from another\nsection bound to the same record collection. The optional `inspector` keeps a\ncontext editor alongside the BPMN canvas: `process_sections` edit the selected\nprocess; `nodes` binds `source`, `process_field`, `element_field`, `label_field`\nand same-collection `sections`. Optional `related` groups use a process reference\nand an optional `node_field`; `advanced: true` starts the group collapsed.\nReferences must be declared `record_select` fields targeting the corresponding\ncollection. Clicking an element resolves its exact ID within the selected\nprocess only; absent or duplicate bindings do not guess a record. Existing field\nedit permissions and the atomic artifact save barrier remain authoritative.\nThis is contextual navigation, not automatic synchronization of BPMN structure\nand business facts; authors must explain how structural changes are reconciled.\n\nFor an exact component contract and on-demand local type declarations, use the\nauthoring inspector from the repository root:\n\n```sh\nnode .agents/skills/design-bundle-creator/scripts/inspect-panel-component.mjs . navigation_workspace --type ComponentNode.navigation_map.edges\n```\n\nUse the [component extension contract](a2ui-component-catalog-contract.md) when\nadding a component: catalog, validation, renderer, styles, edit boundaries,\ntests and authoring guidance must agree. Trusted runtime additions are possible;\nunknown component names in a manifest are rejected.\n\nAcceptance of a component name alone does not establish rendering fidelity,\neditable lifecycle support, or compatibility with every host; those require\nthe component's binding contract and actual runtime verification.\n\nPredefined DSL and A2UI-derived panels share this library, but generated panels\nmay use only the subset with an implemented generation/edit-authority contract.\nAn authored workspace is not automatically promoted into that subset.\nSupported generated results can be deterministically retained as DSL; unsupported\ncapabilities must fail explicitly, never disappear during conversion. This is\nnot an arbitrary bidirectional A2UI protocol converter.\n\n`question_list` is the standard controlled question interaction. Each source\nrecord uses `prompt`, optional `note`, `kind` (`text | single | multiple`),\noptional `choices[]` (`value`, `label`, `recommended`), `answer`, and optional\n`detail`. Text answers render as one multiline input; an existing text-question\n`detail` remains visible as read-only context rather than becoming a second\nanswer box. Single/multiple answers use accessible choice rows and may edit\n`detail`. Existing read-only context and choice supplements use the same\nlocalized label (without the optional-input suffix in reading mode). Cards\nwith a non-empty `answer` collapse to a readable result and can\nbe reopened for editing. The component writes only the fields exposed by that\ninteraction back to the owning record. It does not invent approval state, and an\nempty answer remains unanswered even when `detail` contains context. Native\nproviders may explicitly extend answer-state semantics for attachments, and\nmay add rounds or rejection around this base contract without making those\nextensions mandatory for other Kits.\n\nAuthored `question_list`, `question_rounds`, and `question_workspace` may declare\n`card_groups` with a unique `id`, `title`, and ordered `question_ids`. Members\nmust be contiguous in the existing record order and, for round workspaces, stay\nwithin one round. Invalid groups fall back to ordinary cards with a diagnostic;\ngrouping never reorders canonical records. Generated-origin Panels reject this\nauthored extension.\n\nEach group may declare a `presentation` object containing only optional boolean\n`always_expanded`, `show_detail`, and `show_attachments` properties. These select\nshared component behavior, not Bundle-specific styling. Omission preserves the\nusual collapse, detail, and attachment controls. Hiding a control preserves its\ncanonical data; keeping a card expanded does not grant editing permission.\nRead-only, disabled, protected, historical and rejection guards still apply.\n\n`question_workspace` composes the same question cards with the standard\n`panel_workspace` navigation shell. It groups records by optional numeric\n`round`, shows answer progress, and keeps only the selected group in the main\npane; records without a round form one current group. Its optional\n`description` is rendered through the shared sticky workspace Tip Bar above\nthe main content, never squeezed into the navigation sidebar. `question_rounds` is the\nbackward-compatible alias for this workspace behavior. Optional\n`multimodal_answer[]` entries use the Web App-compatible local reference shape\n(`type`, `file_md5`, `filename`, `mime_type`, `size_bytes`, `artifact_file`).\nThe client keeps pending bytes in a reserved browser-only transport, strips it\nbefore schema validation, and atomically saves only files still referenced by\ncanonical state. The transport is framework state, never a Bundle field.\n\nAuthored `question_workspace` / `question_rounds` nodes may explicitly set\n`question_policy.allow_choice_actions: true`. Expanded editable dynamic single\ncards offer “Switch to multiple choice”; multiple cards offer “Select all” /\n“Deselect all”. Omission or `false` preserves the existing controls. The shared\nruntime owns these actions and their localized styling, not Bundle CSS or an\nauthor-supplied `renderActions` callback. Switching changes only `kind` to\n`multiple`, preserving the exact answer bytes and keeping the editor open.\nSelect-all writes choice values in declared order through the existing\ncomma-separated `answer` contract; deselect-all writes an empty answer. Neither\naction changes detail, attachments, identity, choices or round. Records declared\nin `first_round_ids` are the fixed first-round configuration and do not receive\nthese actions; `protected_ids` still controls rejection only. Read-only,\ndisabled, rejected and read-only historical cards cannot invoke the actions.\nGenerated-origin/A2UI auto Panels reject this configuration, even when `false`;\ntheir existing answer/detail-only write authority and protected `kind` remain\nunchanged. Converting a generated view into an authored reusable panel does not\nsilently grant this capability: the author must opt in under the static contract.\n\n`panel_workspace` is the reusable panel-internal left navigation + main content\nlayout. It standardizes containment, scroll ownership and narrow-panel fallback;\nit does not define domain records or selection semantics. Use it rather than\ncopying a Kit-specific two-column shell.\n\nThe shared runtime `PanelWorkspaceNavigation` accepts optional per-item\n`description`, `supporting`, and `statusLabel` display slots alongside the\nlabel/current row. These are supplied display text, not canonical fields or\nnew DSL expressions. Omitted slots render no empty rows. The `meta` fallback\nremains supported. A marker requires both explicit `statusIndicator: true`\nand an existing `status`; a label-only item never gains an inferred status dot.\nFlat record navigation, question rounds, and future workspace consumers share\nthe same base navigation typography, spacing and selected appearance. Bundle\nCSS is not required. Hierarchical trees retain their separate structure.\nQuestion progress excludes rejected items from answered/completion checks,\nwhile retaining all group records in the displayed total and preserving fixed\nquestion grouping, stable IDs, selection and canonical answers. The original\nWeb App question panel used body round sections, not this sidebar; the shared\nsidebar is an enhanced structure using the original public navigation style,\nnot a claim of one-to-one restoration of a nonexistent original sidebar.\n\n`doc_lifecycle_studio` binds `objects`/`axes`/`actions` sections (validation\nfails loud when one is missing) and renders the fact table (actions × state\naxes, per-cell effects) plus process/derivation/ledger projections derived at\nrender time; unavailable views render disabled with a reason, never hidden.\n`rowview_workbench` renders the residue envelope (below) and requires a\n`source` declaring the add section it owns — the details-envelope schema\ncheck and the renderer are both scoped to that section; a workbench without\n`source` is rejected at compile time.\n\nIn editable mode `bpmn_canvas` edits bidirectionally: each process record's\n`name` and `steps` array (step name, `kind` task/gateway/event, order, add,\nremove) round-trip through the panel Save like any field edit.\n"
|
|
1114
1114
|
}
|
|
@@ -1223,8 +1223,8 @@
|
|
|
1223
1223
|
"sections": [
|
|
1224
1224
|
{
|
|
1225
1225
|
"file": "docs/dsl-spec.md",
|
|
1226
|
-
"line":
|
|
1227
|
-
"endLine":
|
|
1226
|
+
"line": 958,
|
|
1227
|
+
"endLine": 1169,
|
|
1228
1228
|
"heading": "`component` (trusted, extensible library)",
|
|
1229
1229
|
"content": "### `component` (trusted, extensible library)\n\nThe authoritative vocabulary is [`PANEL_COMPONENT_CATALOG`](../packages/core/src/panel-component-catalog.ts).\n`COMPONENT_KINDS`, workspace ownership, source bindings and the generated-panel\nsubset are derived from that one registry; this document is not a second\nvalidation whitelist. Bundle data cannot register executable components.\n\nThe shared library includes basic layouts and controls, question workspaces,\nrecord navigation/editing, diagrams, canvases, artifact readers and previews.\nFull-height workspace components preserve scroll and navigation ownership:\n`record_board`, `document_workspace`, `artifact_workspace`, `diagram_workspace`,\n`canvas_workspace`, `preview_workspace` and `navigation_workspace` expose their\nbehavior through explicit data bindings rather than Kit names. These are reusable\ncapabilities, not a guarantee that every record schema fits every workspace.\n\n`record_board.board.detail_sources` can embed exactly one `record_workspace`\nunder the selected card. Each `{section, reference}` binding declares an unordered\ndirect record collection and a readonly `record_select` back to the board's\nparent section. The child workspace sources must belong to those bindings.\nOwner and child storage paths cannot alias or overlap. The renderer filters\nchildren by the selected parent, binds new records to it, and merges hidden\nsibling records back into canonical updates. It refuses sibling-id replacement,\nreparenting and writes outside these collections. This is a view projection,\nnot a second stored copy; it does not support independently ordered child maps,\nnested `fields_path` records or artifact staging in this first composition slice.\nOrdinary `detail_sections` retain their existing same-record nested-form meaning.\n\n`record_board` uses full-width cards and a workspace-covering overview. Optional\n`board.group` binds a real grouping field. When omitted, the sidebar lists records\ndirectly, cards have no artificial group heading, and the overview connects the\nroot directly to records. Do not bind long summaries merely to satisfy grouping;\nthis projection never adds a grouping field to canonical records.\nSidebar selection scrolls to a card; it does not start editing. Description and\nbadge drafts have explicit Save/Cancel, while rejected records remain inspectable\nwithout granting edit access. Optional `board.id_field` binds a declared visible,\nreadonly `text` field and displays its existing string beside the card title and\nat the top of cover details. Inline details retain the same card header. It does\nnot add an ID editor, generate a fallback ID or write state; omission retains the\nexisting title-only presentation. `board.detail_fields` restricts the parent fields\nshown in the detail fold, and `details_title` localizes its heading. Optional nested\ndimensions can be added or removed without replacing unrelated record fields.\n`board.detail_fields_mode: fixed` instead shows every declared nested input and\nremoves dimension-level add/delete controls; collection item add/delete still\nuses its usual editor. Fields remain schema-optional, including empty inputs.\nViewing does not insert missing strings/maps. Omitted/`on_demand` retains the\nexisting optional-dimension behavior. This option grants no new write authority.\n\n`record_workspace.workspace_view: switch` puts the first child canvas over the\nwhole workspace. The edge action opens it, and the return action or a node's\ndetails action returns to the selected record. It does not add form/canvas tabs\nto the sidebar. Covered content stays mounted and inert to preserve selection,\ndrafts and the graph viewport without allowing hidden controls to receive input.\n\n`record_related_editor.record_table` is an authored-only table presentation of\nthe same child collection, not a conversion to a `rows` array. Its finite\n`columns: [{fields: [field_key, ...], label?: string}]` groups existing field\neditors into cells. Every non-hidden field declared for that child section must\nappear exactly once; hidden/foreign/duplicate bindings and unknown column keys\nare rejected. Column labels default to the first field's label and use the usual\nlocale resolution. A cell retains field visibility, help, requiredness, custom\nconditions and existing edit/derived-field rules. Record creation still binds\nthe selected parent, deletion preserves the normal section cleanup rules, and\n`inherit_from_graph` tables remain source-linked and read-only. The shared table\nwrapper owns horizontal scrolling at narrow widths. This does not promote the\ncomponent or this declaration to generated A2UI.\n\nAn authored graph hierarchy with `max_parents: 1` may opt into\n`parent_control: header`. The existing single-parent selector then sits beside\nthe selected record's form title, rather than above the whole inspector. It\nstill updates the same relation edge, rejects cycles, retains the source-record\nnavigation and shows the actual parent in read-only mode. Omission preserves\nthe prior inspector presentation; neither view creates an extra parent field.\n\n`diagram_workspace.diagram.detail_rows` groups declared read-only fields into\nresponsive fact cards. `chip_fields` selects string-list fields rendered as tags;\n`detail_hint_fields` supplies the populated field labels for the details action.\n`tags` maps declared enum fields to labels and finite semantic tones. These are\npresentation declarations, not new edit rights or storage. Diagram details cover\nonly the content pane; the navigator remains available. Leaving an edited diagram\nstill requires successful serialization through the existing save barrier.\n\n`diagram_workspace.diagram.label_source` can read a declared label from another\nsection bound to the same record collection. The optional `inspector` keeps a\ncontext editor alongside the BPMN canvas: `process_sections` edit the selected\nprocess; `nodes` binds `source`, `process_field`, `element_field`, `label_field`\nand same-collection `sections`. Optional `related` groups use a process reference\nand an optional `node_field`; `advanced: true` starts the group collapsed.\nReferences must be declared `record_select` fields targeting the corresponding\ncollection. Clicking an element resolves its exact ID within the selected\nprocess only; absent or duplicate bindings do not guess a record. Existing field\nedit permissions and the atomic artifact save barrier remain authoritative.\nThis is contextual navigation, not automatic synchronization of BPMN structure\nand business facts; authors must explain how structural changes are reconciled.\n\nFor an exact component contract and on-demand local type declarations, use the\nauthoring inspector from the repository root:\n\n```sh\nnode .agents/skills/design-bundle-creator/scripts/inspect-panel-component.mjs . navigation_workspace --type ComponentNode.navigation_map.edges\n```\n\nUse the [component extension contract](a2ui-component-catalog-contract.md) when\nadding a component: catalog, validation, renderer, styles, edit boundaries,\ntests and authoring guidance must agree. Trusted runtime additions are possible;\nunknown component names in a manifest are rejected.\n\nAcceptance of a component name alone does not establish rendering fidelity,\neditable lifecycle support, or compatibility with every host; those require\nthe component's binding contract and actual runtime verification.\n\nPredefined DSL and A2UI-derived panels share this library, but generated panels\nmay use only the subset with an implemented generation/edit-authority contract.\nAn authored workspace is not automatically promoted into that subset.\nSupported generated results can be deterministically retained as DSL; unsupported\ncapabilities must fail explicitly, never disappear during conversion. This is\nnot an arbitrary bidirectional A2UI protocol converter.\n\n`question_list` is the standard controlled question interaction. Each source\nrecord uses `prompt`, optional `note`, `kind` (`text | single | multiple`),\noptional `choices[]` (`value`, `label`, `recommended`), `answer`, and optional\n`detail`. Text answers render as one multiline input; an existing text-question\n`detail` remains visible as read-only context rather than becoming a second\nanswer box. Single/multiple answers use accessible choice rows and may edit\n`detail`. Existing read-only context and choice supplements use the same\nlocalized label (without the optional-input suffix in reading mode). Cards\nwith a non-empty `answer` collapse to a readable result and can\nbe reopened for editing. The component writes only the fields exposed by that\ninteraction back to the owning record. It does not invent approval state, and an\nempty answer remains unanswered even when `detail` contains context. Native\nproviders may explicitly extend answer-state semantics for attachments, and\nmay add rounds or rejection around this base contract without making those\nextensions mandatory for other Kits.\n\nAuthored `question_list`, `question_rounds`, and `question_workspace` may declare\n`card_groups` with a unique `id`, `title`, and ordered `question_ids`. Members\nmust be contiguous in the existing record order and, for round workspaces, stay\nwithin one round. Invalid groups fall back to ordinary cards with a diagnostic;\ngrouping never reorders canonical records. Generated-origin Panels reject this\nauthored extension.\n\nEach group may declare a `presentation` object containing only optional boolean\n`always_expanded`, `show_detail`, and `show_attachments` properties. These select\nshared component behavior, not Bundle-specific styling. Omission preserves the\nusual collapse, detail, and attachment controls. Hiding a control preserves its\ncanonical data; keeping a card expanded does not grant editing permission.\nRead-only, disabled, protected, historical and rejection guards still apply.\n\n`question_workspace` composes the same question cards with the standard\n`panel_workspace` navigation shell. It groups records by optional numeric\n`round`, shows answer progress, and keeps only the selected group in the main\npane; records without a round form one current group. Its optional\n`description` is rendered through the shared sticky workspace Tip Bar above\nthe main content, never squeezed into the navigation sidebar. `question_rounds` is the\nbackward-compatible alias for this workspace behavior. Optional\n`multimodal_answer[]` entries use the Web App-compatible local reference shape\n(`type`, `file_md5`, `filename`, `mime_type`, `size_bytes`, `artifact_file`).\nThe client keeps pending bytes in a reserved browser-only transport, strips it\nbefore schema validation, and atomically saves only files still referenced by\ncanonical state. The transport is framework state, never a Bundle field.\n\nAuthored `question_workspace` / `question_rounds` nodes may explicitly set\n`question_policy.allow_choice_actions: true`. Expanded editable dynamic single\ncards offer “Switch to multiple choice”; multiple cards offer “Select all” /\n“Deselect all”. Omission or `false` preserves the existing controls. The shared\nruntime owns these actions and their localized styling, not Bundle CSS or an\nauthor-supplied `renderActions` callback. Switching changes only `kind` to\n`multiple`, preserving the exact answer bytes and keeping the editor open.\nSelect-all writes choice values in declared order through the existing\ncomma-separated `answer` contract; deselect-all writes an empty answer. Neither\naction changes detail, attachments, identity, choices or round. Records declared\nin `first_round_ids` are the fixed first-round configuration and do not receive\nthese actions; `protected_ids` still controls rejection only. Read-only,\ndisabled, rejected and read-only historical cards cannot invoke the actions.\nGenerated-origin/A2UI auto Panels reject this configuration, even when `false`;\ntheir existing answer/detail-only write authority and protected `kind` remain\nunchanged. Converting a generated view into an authored reusable panel does not\nsilently grant this capability: the author must opt in under the static contract.\n\n`panel_workspace` is the reusable panel-internal left navigation + main content\nlayout. It standardizes containment, scroll ownership and narrow-panel fallback;\nit does not define domain records or selection semantics. Use it rather than\ncopying a Kit-specific two-column shell.\n\nThe shared runtime `PanelWorkspaceNavigation` accepts optional per-item\n`description`, `supporting`, and `statusLabel` display slots alongside the\nlabel/current row. These are supplied display text, not canonical fields or\nnew DSL expressions. Omitted slots render no empty rows. The `meta` fallback\nremains supported. A marker requires both explicit `statusIndicator: true`\nand an existing `status`; a label-only item never gains an inferred status dot.\nFlat record navigation, question rounds, and future workspace consumers share\nthe same base navigation typography, spacing and selected appearance. Bundle\nCSS is not required. Hierarchical trees retain their separate structure.\nQuestion progress excludes rejected items from answered/completion checks,\nwhile retaining all group records in the displayed total and preserving fixed\nquestion grouping, stable IDs, selection and canonical answers. The original\nWeb App question panel used body round sections, not this sidebar; the shared\nsidebar is an enhanced structure using the original public navigation style,\nnot a claim of one-to-one restoration of a nonexistent original sidebar.\n\n`doc_lifecycle_studio` binds `objects`/`axes`/`actions` sections (validation\nfails loud when one is missing) and renders the fact table (actions × state\naxes, per-cell effects) plus process/derivation/ledger projections derived at\nrender time; unavailable views render disabled with a reason, never hidden.\n`rowview_workbench` renders the residue envelope (below) and requires a\n`source` declaring the add section it owns — the details-envelope schema\ncheck and the renderer are both scoped to that section; a workbench without\n`source` is rejected at compile time.\n\nIn editable mode `bpmn_canvas` edits bidirectionally: each process record's\n`name` and `steps` array (step name, `kind` task/gateway/event, order, add,\nremove) round-trip through the panel Save like any field edit.\n"
|
|
1230
1230
|
}
|
|
@@ -1341,8 +1341,8 @@
|
|
|
1341
1341
|
"sections": [
|
|
1342
1342
|
{
|
|
1343
1343
|
"file": "docs/dsl-spec.md",
|
|
1344
|
-
"line":
|
|
1345
|
-
"endLine":
|
|
1344
|
+
"line": 958,
|
|
1345
|
+
"endLine": 1169,
|
|
1346
1346
|
"heading": "`component` (trusted, extensible library)",
|
|
1347
1347
|
"content": "### `component` (trusted, extensible library)\n\nThe authoritative vocabulary is [`PANEL_COMPONENT_CATALOG`](../packages/core/src/panel-component-catalog.ts).\n`COMPONENT_KINDS`, workspace ownership, source bindings and the generated-panel\nsubset are derived from that one registry; this document is not a second\nvalidation whitelist. Bundle data cannot register executable components.\n\nThe shared library includes basic layouts and controls, question workspaces,\nrecord navigation/editing, diagrams, canvases, artifact readers and previews.\nFull-height workspace components preserve scroll and navigation ownership:\n`record_board`, `document_workspace`, `artifact_workspace`, `diagram_workspace`,\n`canvas_workspace`, `preview_workspace` and `navigation_workspace` expose their\nbehavior through explicit data bindings rather than Kit names. These are reusable\ncapabilities, not a guarantee that every record schema fits every workspace.\n\n`record_board.board.detail_sources` can embed exactly one `record_workspace`\nunder the selected card. Each `{section, reference}` binding declares an unordered\ndirect record collection and a readonly `record_select` back to the board's\nparent section. The child workspace sources must belong to those bindings.\nOwner and child storage paths cannot alias or overlap. The renderer filters\nchildren by the selected parent, binds new records to it, and merges hidden\nsibling records back into canonical updates. It refuses sibling-id replacement,\nreparenting and writes outside these collections. This is a view projection,\nnot a second stored copy; it does not support independently ordered child maps,\nnested `fields_path` records or artifact staging in this first composition slice.\nOrdinary `detail_sections` retain their existing same-record nested-form meaning.\n\n`record_board` uses full-width cards and a workspace-covering overview. Optional\n`board.group` binds a real grouping field. When omitted, the sidebar lists records\ndirectly, cards have no artificial group heading, and the overview connects the\nroot directly to records. Do not bind long summaries merely to satisfy grouping;\nthis projection never adds a grouping field to canonical records.\nSidebar selection scrolls to a card; it does not start editing. Description and\nbadge drafts have explicit Save/Cancel, while rejected records remain inspectable\nwithout granting edit access. Optional `board.id_field` binds a declared visible,\nreadonly `text` field and displays its existing string beside the card title and\nat the top of cover details. Inline details retain the same card header. It does\nnot add an ID editor, generate a fallback ID or write state; omission retains the\nexisting title-only presentation. `board.detail_fields` restricts the parent fields\nshown in the detail fold, and `details_title` localizes its heading. Optional nested\ndimensions can be added or removed without replacing unrelated record fields.\n`board.detail_fields_mode: fixed` instead shows every declared nested input and\nremoves dimension-level add/delete controls; collection item add/delete still\nuses its usual editor. Fields remain schema-optional, including empty inputs.\nViewing does not insert missing strings/maps. Omitted/`on_demand` retains the\nexisting optional-dimension behavior. This option grants no new write authority.\n\n`record_workspace.workspace_view: switch` puts the first child canvas over the\nwhole workspace. The edge action opens it, and the return action or a node's\ndetails action returns to the selected record. It does not add form/canvas tabs\nto the sidebar. Covered content stays mounted and inert to preserve selection,\ndrafts and the graph viewport without allowing hidden controls to receive input.\n\n`record_related_editor.record_table` is an authored-only table presentation of\nthe same child collection, not a conversion to a `rows` array. Its finite\n`columns: [{fields: [field_key, ...], label?: string}]` groups existing field\neditors into cells. Every non-hidden field declared for that child section must\nappear exactly once; hidden/foreign/duplicate bindings and unknown column keys\nare rejected. Column labels default to the first field's label and use the usual\nlocale resolution. A cell retains field visibility, help, requiredness, custom\nconditions and existing edit/derived-field rules. Record creation still binds\nthe selected parent, deletion preserves the normal section cleanup rules, and\n`inherit_from_graph` tables remain source-linked and read-only. The shared table\nwrapper owns horizontal scrolling at narrow widths. This does not promote the\ncomponent or this declaration to generated A2UI.\n\nAn authored graph hierarchy with `max_parents: 1` may opt into\n`parent_control: header`. The existing single-parent selector then sits beside\nthe selected record's form title, rather than above the whole inspector. It\nstill updates the same relation edge, rejects cycles, retains the source-record\nnavigation and shows the actual parent in read-only mode. Omission preserves\nthe prior inspector presentation; neither view creates an extra parent field.\n\n`diagram_workspace.diagram.detail_rows` groups declared read-only fields into\nresponsive fact cards. `chip_fields` selects string-list fields rendered as tags;\n`detail_hint_fields` supplies the populated field labels for the details action.\n`tags` maps declared enum fields to labels and finite semantic tones. These are\npresentation declarations, not new edit rights or storage. Diagram details cover\nonly the content pane; the navigator remains available. Leaving an edited diagram\nstill requires successful serialization through the existing save barrier.\n\n`diagram_workspace.diagram.label_source` can read a declared label from another\nsection bound to the same record collection. The optional `inspector` keeps a\ncontext editor alongside the BPMN canvas: `process_sections` edit the selected\nprocess; `nodes` binds `source`, `process_field`, `element_field`, `label_field`\nand same-collection `sections`. Optional `related` groups use a process reference\nand an optional `node_field`; `advanced: true` starts the group collapsed.\nReferences must be declared `record_select` fields targeting the corresponding\ncollection. Clicking an element resolves its exact ID within the selected\nprocess only; absent or duplicate bindings do not guess a record. Existing field\nedit permissions and the atomic artifact save barrier remain authoritative.\nThis is contextual navigation, not automatic synchronization of BPMN structure\nand business facts; authors must explain how structural changes are reconciled.\n\nFor an exact component contract and on-demand local type declarations, use the\nauthoring inspector from the repository root:\n\n```sh\nnode .agents/skills/design-bundle-creator/scripts/inspect-panel-component.mjs . navigation_workspace --type ComponentNode.navigation_map.edges\n```\n\nUse the [component extension contract](a2ui-component-catalog-contract.md) when\nadding a component: catalog, validation, renderer, styles, edit boundaries,\ntests and authoring guidance must agree. Trusted runtime additions are possible;\nunknown component names in a manifest are rejected.\n\nAcceptance of a component name alone does not establish rendering fidelity,\neditable lifecycle support, or compatibility with every host; those require\nthe component's binding contract and actual runtime verification.\n\nPredefined DSL and A2UI-derived panels share this library, but generated panels\nmay use only the subset with an implemented generation/edit-authority contract.\nAn authored workspace is not automatically promoted into that subset.\nSupported generated results can be deterministically retained as DSL; unsupported\ncapabilities must fail explicitly, never disappear during conversion. This is\nnot an arbitrary bidirectional A2UI protocol converter.\n\n`question_list` is the standard controlled question interaction. Each source\nrecord uses `prompt`, optional `note`, `kind` (`text | single | multiple`),\noptional `choices[]` (`value`, `label`, `recommended`), `answer`, and optional\n`detail`. Text answers render as one multiline input; an existing text-question\n`detail` remains visible as read-only context rather than becoming a second\nanswer box. Single/multiple answers use accessible choice rows and may edit\n`detail`. Existing read-only context and choice supplements use the same\nlocalized label (without the optional-input suffix in reading mode). Cards\nwith a non-empty `answer` collapse to a readable result and can\nbe reopened for editing. The component writes only the fields exposed by that\ninteraction back to the owning record. It does not invent approval state, and an\nempty answer remains unanswered even when `detail` contains context. Native\nproviders may explicitly extend answer-state semantics for attachments, and\nmay add rounds or rejection around this base contract without making those\nextensions mandatory for other Kits.\n\nAuthored `question_list`, `question_rounds`, and `question_workspace` may declare\n`card_groups` with a unique `id`, `title`, and ordered `question_ids`. Members\nmust be contiguous in the existing record order and, for round workspaces, stay\nwithin one round. Invalid groups fall back to ordinary cards with a diagnostic;\ngrouping never reorders canonical records. Generated-origin Panels reject this\nauthored extension.\n\nEach group may declare a `presentation` object containing only optional boolean\n`always_expanded`, `show_detail`, and `show_attachments` properties. These select\nshared component behavior, not Bundle-specific styling. Omission preserves the\nusual collapse, detail, and attachment controls. Hiding a control preserves its\ncanonical data; keeping a card expanded does not grant editing permission.\nRead-only, disabled, protected, historical and rejection guards still apply.\n\n`question_workspace` composes the same question cards with the standard\n`panel_workspace` navigation shell. It groups records by optional numeric\n`round`, shows answer progress, and keeps only the selected group in the main\npane; records without a round form one current group. Its optional\n`description` is rendered through the shared sticky workspace Tip Bar above\nthe main content, never squeezed into the navigation sidebar. `question_rounds` is the\nbackward-compatible alias for this workspace behavior. Optional\n`multimodal_answer[]` entries use the Web App-compatible local reference shape\n(`type`, `file_md5`, `filename`, `mime_type`, `size_bytes`, `artifact_file`).\nThe client keeps pending bytes in a reserved browser-only transport, strips it\nbefore schema validation, and atomically saves only files still referenced by\ncanonical state. The transport is framework state, never a Bundle field.\n\nAuthored `question_workspace` / `question_rounds` nodes may explicitly set\n`question_policy.allow_choice_actions: true`. Expanded editable dynamic single\ncards offer “Switch to multiple choice”; multiple cards offer “Select all” /\n“Deselect all”. Omission or `false` preserves the existing controls. The shared\nruntime owns these actions and their localized styling, not Bundle CSS or an\nauthor-supplied `renderActions` callback. Switching changes only `kind` to\n`multiple`, preserving the exact answer bytes and keeping the editor open.\nSelect-all writes choice values in declared order through the existing\ncomma-separated `answer` contract; deselect-all writes an empty answer. Neither\naction changes detail, attachments, identity, choices or round. Records declared\nin `first_round_ids` are the fixed first-round configuration and do not receive\nthese actions; `protected_ids` still controls rejection only. Read-only,\ndisabled, rejected and read-only historical cards cannot invoke the actions.\nGenerated-origin/A2UI auto Panels reject this configuration, even when `false`;\ntheir existing answer/detail-only write authority and protected `kind` remain\nunchanged. Converting a generated view into an authored reusable panel does not\nsilently grant this capability: the author must opt in under the static contract.\n\n`panel_workspace` is the reusable panel-internal left navigation + main content\nlayout. It standardizes containment, scroll ownership and narrow-panel fallback;\nit does not define domain records or selection semantics. Use it rather than\ncopying a Kit-specific two-column shell.\n\nThe shared runtime `PanelWorkspaceNavigation` accepts optional per-item\n`description`, `supporting`, and `statusLabel` display slots alongside the\nlabel/current row. These are supplied display text, not canonical fields or\nnew DSL expressions. Omitted slots render no empty rows. The `meta` fallback\nremains supported. A marker requires both explicit `statusIndicator: true`\nand an existing `status`; a label-only item never gains an inferred status dot.\nFlat record navigation, question rounds, and future workspace consumers share\nthe same base navigation typography, spacing and selected appearance. Bundle\nCSS is not required. Hierarchical trees retain their separate structure.\nQuestion progress excludes rejected items from answered/completion checks,\nwhile retaining all group records in the displayed total and preserving fixed\nquestion grouping, stable IDs, selection and canonical answers. The original\nWeb App question panel used body round sections, not this sidebar; the shared\nsidebar is an enhanced structure using the original public navigation style,\nnot a claim of one-to-one restoration of a nonexistent original sidebar.\n\n`doc_lifecycle_studio` binds `objects`/`axes`/`actions` sections (validation\nfails loud when one is missing) and renders the fact table (actions × state\naxes, per-cell effects) plus process/derivation/ledger projections derived at\nrender time; unavailable views render disabled with a reason, never hidden.\n`rowview_workbench` renders the residue envelope (below) and requires a\n`source` declaring the add section it owns — the details-envelope schema\ncheck and the renderer are both scoped to that section; a workbench without\n`source` is rejected at compile time.\n\nIn editable mode `bpmn_canvas` edits bidirectionally: each process record's\n`name` and `steps` array (step name, `kind` task/gateway/event, order, add,\nremove) round-trip through the panel Save like any field edit.\n"
|
|
1348
1348
|
}
|
|
@@ -1460,8 +1460,8 @@
|
|
|
1460
1460
|
"sections": [
|
|
1461
1461
|
{
|
|
1462
1462
|
"file": "docs/dsl-spec.md",
|
|
1463
|
-
"line":
|
|
1464
|
-
"endLine":
|
|
1463
|
+
"line": 958,
|
|
1464
|
+
"endLine": 1169,
|
|
1465
1465
|
"heading": "`component` (trusted, extensible library)",
|
|
1466
1466
|
"content": "### `component` (trusted, extensible library)\n\nThe authoritative vocabulary is [`PANEL_COMPONENT_CATALOG`](../packages/core/src/panel-component-catalog.ts).\n`COMPONENT_KINDS`, workspace ownership, source bindings and the generated-panel\nsubset are derived from that one registry; this document is not a second\nvalidation whitelist. Bundle data cannot register executable components.\n\nThe shared library includes basic layouts and controls, question workspaces,\nrecord navigation/editing, diagrams, canvases, artifact readers and previews.\nFull-height workspace components preserve scroll and navigation ownership:\n`record_board`, `document_workspace`, `artifact_workspace`, `diagram_workspace`,\n`canvas_workspace`, `preview_workspace` and `navigation_workspace` expose their\nbehavior through explicit data bindings rather than Kit names. These are reusable\ncapabilities, not a guarantee that every record schema fits every workspace.\n\n`record_board.board.detail_sources` can embed exactly one `record_workspace`\nunder the selected card. Each `{section, reference}` binding declares an unordered\ndirect record collection and a readonly `record_select` back to the board's\nparent section. The child workspace sources must belong to those bindings.\nOwner and child storage paths cannot alias or overlap. The renderer filters\nchildren by the selected parent, binds new records to it, and merges hidden\nsibling records back into canonical updates. It refuses sibling-id replacement,\nreparenting and writes outside these collections. This is a view projection,\nnot a second stored copy; it does not support independently ordered child maps,\nnested `fields_path` records or artifact staging in this first composition slice.\nOrdinary `detail_sections` retain their existing same-record nested-form meaning.\n\n`record_board` uses full-width cards and a workspace-covering overview. Optional\n`board.group` binds a real grouping field. When omitted, the sidebar lists records\ndirectly, cards have no artificial group heading, and the overview connects the\nroot directly to records. Do not bind long summaries merely to satisfy grouping;\nthis projection never adds a grouping field to canonical records.\nSidebar selection scrolls to a card; it does not start editing. Description and\nbadge drafts have explicit Save/Cancel, while rejected records remain inspectable\nwithout granting edit access. Optional `board.id_field` binds a declared visible,\nreadonly `text` field and displays its existing string beside the card title and\nat the top of cover details. Inline details retain the same card header. It does\nnot add an ID editor, generate a fallback ID or write state; omission retains the\nexisting title-only presentation. `board.detail_fields` restricts the parent fields\nshown in the detail fold, and `details_title` localizes its heading. Optional nested\ndimensions can be added or removed without replacing unrelated record fields.\n`board.detail_fields_mode: fixed` instead shows every declared nested input and\nremoves dimension-level add/delete controls; collection item add/delete still\nuses its usual editor. Fields remain schema-optional, including empty inputs.\nViewing does not insert missing strings/maps. Omitted/`on_demand` retains the\nexisting optional-dimension behavior. This option grants no new write authority.\n\n`record_workspace.workspace_view: switch` puts the first child canvas over the\nwhole workspace. The edge action opens it, and the return action or a node's\ndetails action returns to the selected record. It does not add form/canvas tabs\nto the sidebar. Covered content stays mounted and inert to preserve selection,\ndrafts and the graph viewport without allowing hidden controls to receive input.\n\n`record_related_editor.record_table` is an authored-only table presentation of\nthe same child collection, not a conversion to a `rows` array. Its finite\n`columns: [{fields: [field_key, ...], label?: string}]` groups existing field\neditors into cells. Every non-hidden field declared for that child section must\nappear exactly once; hidden/foreign/duplicate bindings and unknown column keys\nare rejected. Column labels default to the first field's label and use the usual\nlocale resolution. A cell retains field visibility, help, requiredness, custom\nconditions and existing edit/derived-field rules. Record creation still binds\nthe selected parent, deletion preserves the normal section cleanup rules, and\n`inherit_from_graph` tables remain source-linked and read-only. The shared table\nwrapper owns horizontal scrolling at narrow widths. This does not promote the\ncomponent or this declaration to generated A2UI.\n\nAn authored graph hierarchy with `max_parents: 1` may opt into\n`parent_control: header`. The existing single-parent selector then sits beside\nthe selected record's form title, rather than above the whole inspector. It\nstill updates the same relation edge, rejects cycles, retains the source-record\nnavigation and shows the actual parent in read-only mode. Omission preserves\nthe prior inspector presentation; neither view creates an extra parent field.\n\n`diagram_workspace.diagram.detail_rows` groups declared read-only fields into\nresponsive fact cards. `chip_fields` selects string-list fields rendered as tags;\n`detail_hint_fields` supplies the populated field labels for the details action.\n`tags` maps declared enum fields to labels and finite semantic tones. These are\npresentation declarations, not new edit rights or storage. Diagram details cover\nonly the content pane; the navigator remains available. Leaving an edited diagram\nstill requires successful serialization through the existing save barrier.\n\n`diagram_workspace.diagram.label_source` can read a declared label from another\nsection bound to the same record collection. The optional `inspector` keeps a\ncontext editor alongside the BPMN canvas: `process_sections` edit the selected\nprocess; `nodes` binds `source`, `process_field`, `element_field`, `label_field`\nand same-collection `sections`. Optional `related` groups use a process reference\nand an optional `node_field`; `advanced: true` starts the group collapsed.\nReferences must be declared `record_select` fields targeting the corresponding\ncollection. Clicking an element resolves its exact ID within the selected\nprocess only; absent or duplicate bindings do not guess a record. Existing field\nedit permissions and the atomic artifact save barrier remain authoritative.\nThis is contextual navigation, not automatic synchronization of BPMN structure\nand business facts; authors must explain how structural changes are reconciled.\n\nFor an exact component contract and on-demand local type declarations, use the\nauthoring inspector from the repository root:\n\n```sh\nnode .agents/skills/design-bundle-creator/scripts/inspect-panel-component.mjs . navigation_workspace --type ComponentNode.navigation_map.edges\n```\n\nUse the [component extension contract](a2ui-component-catalog-contract.md) when\nadding a component: catalog, validation, renderer, styles, edit boundaries,\ntests and authoring guidance must agree. Trusted runtime additions are possible;\nunknown component names in a manifest are rejected.\n\nAcceptance of a component name alone does not establish rendering fidelity,\neditable lifecycle support, or compatibility with every host; those require\nthe component's binding contract and actual runtime verification.\n\nPredefined DSL and A2UI-derived panels share this library, but generated panels\nmay use only the subset with an implemented generation/edit-authority contract.\nAn authored workspace is not automatically promoted into that subset.\nSupported generated results can be deterministically retained as DSL; unsupported\ncapabilities must fail explicitly, never disappear during conversion. This is\nnot an arbitrary bidirectional A2UI protocol converter.\n\n`question_list` is the standard controlled question interaction. Each source\nrecord uses `prompt`, optional `note`, `kind` (`text | single | multiple`),\noptional `choices[]` (`value`, `label`, `recommended`), `answer`, and optional\n`detail`. Text answers render as one multiline input; an existing text-question\n`detail` remains visible as read-only context rather than becoming a second\nanswer box. Single/multiple answers use accessible choice rows and may edit\n`detail`. Existing read-only context and choice supplements use the same\nlocalized label (without the optional-input suffix in reading mode). Cards\nwith a non-empty `answer` collapse to a readable result and can\nbe reopened for editing. The component writes only the fields exposed by that\ninteraction back to the owning record. It does not invent approval state, and an\nempty answer remains unanswered even when `detail` contains context. Native\nproviders may explicitly extend answer-state semantics for attachments, and\nmay add rounds or rejection around this base contract without making those\nextensions mandatory for other Kits.\n\nAuthored `question_list`, `question_rounds`, and `question_workspace` may declare\n`card_groups` with a unique `id`, `title`, and ordered `question_ids`. Members\nmust be contiguous in the existing record order and, for round workspaces, stay\nwithin one round. Invalid groups fall back to ordinary cards with a diagnostic;\ngrouping never reorders canonical records. Generated-origin Panels reject this\nauthored extension.\n\nEach group may declare a `presentation` object containing only optional boolean\n`always_expanded`, `show_detail`, and `show_attachments` properties. These select\nshared component behavior, not Bundle-specific styling. Omission preserves the\nusual collapse, detail, and attachment controls. Hiding a control preserves its\ncanonical data; keeping a card expanded does not grant editing permission.\nRead-only, disabled, protected, historical and rejection guards still apply.\n\n`question_workspace` composes the same question cards with the standard\n`panel_workspace` navigation shell. It groups records by optional numeric\n`round`, shows answer progress, and keeps only the selected group in the main\npane; records without a round form one current group. Its optional\n`description` is rendered through the shared sticky workspace Tip Bar above\nthe main content, never squeezed into the navigation sidebar. `question_rounds` is the\nbackward-compatible alias for this workspace behavior. Optional\n`multimodal_answer[]` entries use the Web App-compatible local reference shape\n(`type`, `file_md5`, `filename`, `mime_type`, `size_bytes`, `artifact_file`).\nThe client keeps pending bytes in a reserved browser-only transport, strips it\nbefore schema validation, and atomically saves only files still referenced by\ncanonical state. The transport is framework state, never a Bundle field.\n\nAuthored `question_workspace` / `question_rounds` nodes may explicitly set\n`question_policy.allow_choice_actions: true`. Expanded editable dynamic single\ncards offer “Switch to multiple choice”; multiple cards offer “Select all” /\n“Deselect all”. Omission or `false` preserves the existing controls. The shared\nruntime owns these actions and their localized styling, not Bundle CSS or an\nauthor-supplied `renderActions` callback. Switching changes only `kind` to\n`multiple`, preserving the exact answer bytes and keeping the editor open.\nSelect-all writes choice values in declared order through the existing\ncomma-separated `answer` contract; deselect-all writes an empty answer. Neither\naction changes detail, attachments, identity, choices or round. Records declared\nin `first_round_ids` are the fixed first-round configuration and do not receive\nthese actions; `protected_ids` still controls rejection only. Read-only,\ndisabled, rejected and read-only historical cards cannot invoke the actions.\nGenerated-origin/A2UI auto Panels reject this configuration, even when `false`;\ntheir existing answer/detail-only write authority and protected `kind` remain\nunchanged. Converting a generated view into an authored reusable panel does not\nsilently grant this capability: the author must opt in under the static contract.\n\n`panel_workspace` is the reusable panel-internal left navigation + main content\nlayout. It standardizes containment, scroll ownership and narrow-panel fallback;\nit does not define domain records or selection semantics. Use it rather than\ncopying a Kit-specific two-column shell.\n\nThe shared runtime `PanelWorkspaceNavigation` accepts optional per-item\n`description`, `supporting`, and `statusLabel` display slots alongside the\nlabel/current row. These are supplied display text, not canonical fields or\nnew DSL expressions. Omitted slots render no empty rows. The `meta` fallback\nremains supported. A marker requires both explicit `statusIndicator: true`\nand an existing `status`; a label-only item never gains an inferred status dot.\nFlat record navigation, question rounds, and future workspace consumers share\nthe same base navigation typography, spacing and selected appearance. Bundle\nCSS is not required. Hierarchical trees retain their separate structure.\nQuestion progress excludes rejected items from answered/completion checks,\nwhile retaining all group records in the displayed total and preserving fixed\nquestion grouping, stable IDs, selection and canonical answers. The original\nWeb App question panel used body round sections, not this sidebar; the shared\nsidebar is an enhanced structure using the original public navigation style,\nnot a claim of one-to-one restoration of a nonexistent original sidebar.\n\n`doc_lifecycle_studio` binds `objects`/`axes`/`actions` sections (validation\nfails loud when one is missing) and renders the fact table (actions × state\naxes, per-cell effects) plus process/derivation/ledger projections derived at\nrender time; unavailable views render disabled with a reason, never hidden.\n`rowview_workbench` renders the residue envelope (below) and requires a\n`source` declaring the add section it owns — the details-envelope schema\ncheck and the renderer are both scoped to that section; a workbench without\n`source` is rejected at compile time.\n\nIn editable mode `bpmn_canvas` edits bidirectionally: each process record's\n`name` and `steps` array (step name, `kind` task/gateway/event, order, add,\nremove) round-trip through the panel Save like any field edit.\n"
|
|
1467
1467
|
}
|
|
@@ -1620,8 +1620,8 @@
|
|
|
1620
1620
|
"sections": [
|
|
1621
1621
|
{
|
|
1622
1622
|
"file": "docs/dsl-spec.md",
|
|
1623
|
-
"line":
|
|
1624
|
-
"endLine":
|
|
1623
|
+
"line": 958,
|
|
1624
|
+
"endLine": 1169,
|
|
1625
1625
|
"heading": "`component` (trusted, extensible library)",
|
|
1626
1626
|
"content": "### `component` (trusted, extensible library)\n\nThe authoritative vocabulary is [`PANEL_COMPONENT_CATALOG`](../packages/core/src/panel-component-catalog.ts).\n`COMPONENT_KINDS`, workspace ownership, source bindings and the generated-panel\nsubset are derived from that one registry; this document is not a second\nvalidation whitelist. Bundle data cannot register executable components.\n\nThe shared library includes basic layouts and controls, question workspaces,\nrecord navigation/editing, diagrams, canvases, artifact readers and previews.\nFull-height workspace components preserve scroll and navigation ownership:\n`record_board`, `document_workspace`, `artifact_workspace`, `diagram_workspace`,\n`canvas_workspace`, `preview_workspace` and `navigation_workspace` expose their\nbehavior through explicit data bindings rather than Kit names. These are reusable\ncapabilities, not a guarantee that every record schema fits every workspace.\n\n`record_board.board.detail_sources` can embed exactly one `record_workspace`\nunder the selected card. Each `{section, reference}` binding declares an unordered\ndirect record collection and a readonly `record_select` back to the board's\nparent section. The child workspace sources must belong to those bindings.\nOwner and child storage paths cannot alias or overlap. The renderer filters\nchildren by the selected parent, binds new records to it, and merges hidden\nsibling records back into canonical updates. It refuses sibling-id replacement,\nreparenting and writes outside these collections. This is a view projection,\nnot a second stored copy; it does not support independently ordered child maps,\nnested `fields_path` records or artifact staging in this first composition slice.\nOrdinary `detail_sections` retain their existing same-record nested-form meaning.\n\n`record_board` uses full-width cards and a workspace-covering overview. Optional\n`board.group` binds a real grouping field. When omitted, the sidebar lists records\ndirectly, cards have no artificial group heading, and the overview connects the\nroot directly to records. Do not bind long summaries merely to satisfy grouping;\nthis projection never adds a grouping field to canonical records.\nSidebar selection scrolls to a card; it does not start editing. Description and\nbadge drafts have explicit Save/Cancel, while rejected records remain inspectable\nwithout granting edit access. Optional `board.id_field` binds a declared visible,\nreadonly `text` field and displays its existing string beside the card title and\nat the top of cover details. Inline details retain the same card header. It does\nnot add an ID editor, generate a fallback ID or write state; omission retains the\nexisting title-only presentation. `board.detail_fields` restricts the parent fields\nshown in the detail fold, and `details_title` localizes its heading. Optional nested\ndimensions can be added or removed without replacing unrelated record fields.\n`board.detail_fields_mode: fixed` instead shows every declared nested input and\nremoves dimension-level add/delete controls; collection item add/delete still\nuses its usual editor. Fields remain schema-optional, including empty inputs.\nViewing does not insert missing strings/maps. Omitted/`on_demand` retains the\nexisting optional-dimension behavior. This option grants no new write authority.\n\n`record_workspace.workspace_view: switch` puts the first child canvas over the\nwhole workspace. The edge action opens it, and the return action or a node's\ndetails action returns to the selected record. It does not add form/canvas tabs\nto the sidebar. Covered content stays mounted and inert to preserve selection,\ndrafts and the graph viewport without allowing hidden controls to receive input.\n\n`record_related_editor.record_table` is an authored-only table presentation of\nthe same child collection, not a conversion to a `rows` array. Its finite\n`columns: [{fields: [field_key, ...], label?: string}]` groups existing field\neditors into cells. Every non-hidden field declared for that child section must\nappear exactly once; hidden/foreign/duplicate bindings and unknown column keys\nare rejected. Column labels default to the first field's label and use the usual\nlocale resolution. A cell retains field visibility, help, requiredness, custom\nconditions and existing edit/derived-field rules. Record creation still binds\nthe selected parent, deletion preserves the normal section cleanup rules, and\n`inherit_from_graph` tables remain source-linked and read-only. The shared table\nwrapper owns horizontal scrolling at narrow widths. This does not promote the\ncomponent or this declaration to generated A2UI.\n\nAn authored graph hierarchy with `max_parents: 1` may opt into\n`parent_control: header`. The existing single-parent selector then sits beside\nthe selected record's form title, rather than above the whole inspector. It\nstill updates the same relation edge, rejects cycles, retains the source-record\nnavigation and shows the actual parent in read-only mode. Omission preserves\nthe prior inspector presentation; neither view creates an extra parent field.\n\n`diagram_workspace.diagram.detail_rows` groups declared read-only fields into\nresponsive fact cards. `chip_fields` selects string-list fields rendered as tags;\n`detail_hint_fields` supplies the populated field labels for the details action.\n`tags` maps declared enum fields to labels and finite semantic tones. These are\npresentation declarations, not new edit rights or storage. Diagram details cover\nonly the content pane; the navigator remains available. Leaving an edited diagram\nstill requires successful serialization through the existing save barrier.\n\n`diagram_workspace.diagram.label_source` can read a declared label from another\nsection bound to the same record collection. The optional `inspector` keeps a\ncontext editor alongside the BPMN canvas: `process_sections` edit the selected\nprocess; `nodes` binds `source`, `process_field`, `element_field`, `label_field`\nand same-collection `sections`. Optional `related` groups use a process reference\nand an optional `node_field`; `advanced: true` starts the group collapsed.\nReferences must be declared `record_select` fields targeting the corresponding\ncollection. Clicking an element resolves its exact ID within the selected\nprocess only; absent or duplicate bindings do not guess a record. Existing field\nedit permissions and the atomic artifact save barrier remain authoritative.\nThis is contextual navigation, not automatic synchronization of BPMN structure\nand business facts; authors must explain how structural changes are reconciled.\n\nFor an exact component contract and on-demand local type declarations, use the\nauthoring inspector from the repository root:\n\n```sh\nnode .agents/skills/design-bundle-creator/scripts/inspect-panel-component.mjs . navigation_workspace --type ComponentNode.navigation_map.edges\n```\n\nUse the [component extension contract](a2ui-component-catalog-contract.md) when\nadding a component: catalog, validation, renderer, styles, edit boundaries,\ntests and authoring guidance must agree. Trusted runtime additions are possible;\nunknown component names in a manifest are rejected.\n\nAcceptance of a component name alone does not establish rendering fidelity,\neditable lifecycle support, or compatibility with every host; those require\nthe component's binding contract and actual runtime verification.\n\nPredefined DSL and A2UI-derived panels share this library, but generated panels\nmay use only the subset with an implemented generation/edit-authority contract.\nAn authored workspace is not automatically promoted into that subset.\nSupported generated results can be deterministically retained as DSL; unsupported\ncapabilities must fail explicitly, never disappear during conversion. This is\nnot an arbitrary bidirectional A2UI protocol converter.\n\n`question_list` is the standard controlled question interaction. Each source\nrecord uses `prompt`, optional `note`, `kind` (`text | single | multiple`),\noptional `choices[]` (`value`, `label`, `recommended`), `answer`, and optional\n`detail`. Text answers render as one multiline input; an existing text-question\n`detail` remains visible as read-only context rather than becoming a second\nanswer box. Single/multiple answers use accessible choice rows and may edit\n`detail`. Existing read-only context and choice supplements use the same\nlocalized label (without the optional-input suffix in reading mode). Cards\nwith a non-empty `answer` collapse to a readable result and can\nbe reopened for editing. The component writes only the fields exposed by that\ninteraction back to the owning record. It does not invent approval state, and an\nempty answer remains unanswered even when `detail` contains context. Native\nproviders may explicitly extend answer-state semantics for attachments, and\nmay add rounds or rejection around this base contract without making those\nextensions mandatory for other Kits.\n\nAuthored `question_list`, `question_rounds`, and `question_workspace` may declare\n`card_groups` with a unique `id`, `title`, and ordered `question_ids`. Members\nmust be contiguous in the existing record order and, for round workspaces, stay\nwithin one round. Invalid groups fall back to ordinary cards with a diagnostic;\ngrouping never reorders canonical records. Generated-origin Panels reject this\nauthored extension.\n\nEach group may declare a `presentation` object containing only optional boolean\n`always_expanded`, `show_detail`, and `show_attachments` properties. These select\nshared component behavior, not Bundle-specific styling. Omission preserves the\nusual collapse, detail, and attachment controls. Hiding a control preserves its\ncanonical data; keeping a card expanded does not grant editing permission.\nRead-only, disabled, protected, historical and rejection guards still apply.\n\n`question_workspace` composes the same question cards with the standard\n`panel_workspace` navigation shell. It groups records by optional numeric\n`round`, shows answer progress, and keeps only the selected group in the main\npane; records without a round form one current group. Its optional\n`description` is rendered through the shared sticky workspace Tip Bar above\nthe main content, never squeezed into the navigation sidebar. `question_rounds` is the\nbackward-compatible alias for this workspace behavior. Optional\n`multimodal_answer[]` entries use the Web App-compatible local reference shape\n(`type`, `file_md5`, `filename`, `mime_type`, `size_bytes`, `artifact_file`).\nThe client keeps pending bytes in a reserved browser-only transport, strips it\nbefore schema validation, and atomically saves only files still referenced by\ncanonical state. The transport is framework state, never a Bundle field.\n\nAuthored `question_workspace` / `question_rounds` nodes may explicitly set\n`question_policy.allow_choice_actions: true`. Expanded editable dynamic single\ncards offer “Switch to multiple choice”; multiple cards offer “Select all” /\n“Deselect all”. Omission or `false` preserves the existing controls. The shared\nruntime owns these actions and their localized styling, not Bundle CSS or an\nauthor-supplied `renderActions` callback. Switching changes only `kind` to\n`multiple`, preserving the exact answer bytes and keeping the editor open.\nSelect-all writes choice values in declared order through the existing\ncomma-separated `answer` contract; deselect-all writes an empty answer. Neither\naction changes detail, attachments, identity, choices or round. Records declared\nin `first_round_ids` are the fixed first-round configuration and do not receive\nthese actions; `protected_ids` still controls rejection only. Read-only,\ndisabled, rejected and read-only historical cards cannot invoke the actions.\nGenerated-origin/A2UI auto Panels reject this configuration, even when `false`;\ntheir existing answer/detail-only write authority and protected `kind` remain\nunchanged. Converting a generated view into an authored reusable panel does not\nsilently grant this capability: the author must opt in under the static contract.\n\n`panel_workspace` is the reusable panel-internal left navigation + main content\nlayout. It standardizes containment, scroll ownership and narrow-panel fallback;\nit does not define domain records or selection semantics. Use it rather than\ncopying a Kit-specific two-column shell.\n\nThe shared runtime `PanelWorkspaceNavigation` accepts optional per-item\n`description`, `supporting`, and `statusLabel` display slots alongside the\nlabel/current row. These are supplied display text, not canonical fields or\nnew DSL expressions. Omitted slots render no empty rows. The `meta` fallback\nremains supported. A marker requires both explicit `statusIndicator: true`\nand an existing `status`; a label-only item never gains an inferred status dot.\nFlat record navigation, question rounds, and future workspace consumers share\nthe same base navigation typography, spacing and selected appearance. Bundle\nCSS is not required. Hierarchical trees retain their separate structure.\nQuestion progress excludes rejected items from answered/completion checks,\nwhile retaining all group records in the displayed total and preserving fixed\nquestion grouping, stable IDs, selection and canonical answers. The original\nWeb App question panel used body round sections, not this sidebar; the shared\nsidebar is an enhanced structure using the original public navigation style,\nnot a claim of one-to-one restoration of a nonexistent original sidebar.\n\n`doc_lifecycle_studio` binds `objects`/`axes`/`actions` sections (validation\nfails loud when one is missing) and renders the fact table (actions × state\naxes, per-cell effects) plus process/derivation/ledger projections derived at\nrender time; unavailable views render disabled with a reason, never hidden.\n`rowview_workbench` renders the residue envelope (below) and requires a\n`source` declaring the add section it owns — the details-envelope schema\ncheck and the renderer are both scoped to that section; a workbench without\n`source` is rejected at compile time.\n\nIn editable mode `bpmn_canvas` edits bidirectionally: each process record's\n`name` and `steps` array (step name, `kind` task/gateway/event, order, add,\nremove) round-trip through the panel Save like any field edit.\n"
|
|
1627
1627
|
}
|
|
@@ -1736,8 +1736,8 @@
|
|
|
1736
1736
|
"sections": [
|
|
1737
1737
|
{
|
|
1738
1738
|
"file": "docs/dsl-spec.md",
|
|
1739
|
-
"line":
|
|
1740
|
-
"endLine":
|
|
1739
|
+
"line": 958,
|
|
1740
|
+
"endLine": 1169,
|
|
1741
1741
|
"heading": "`component` (trusted, extensible library)",
|
|
1742
1742
|
"content": "### `component` (trusted, extensible library)\n\nThe authoritative vocabulary is [`PANEL_COMPONENT_CATALOG`](../packages/core/src/panel-component-catalog.ts).\n`COMPONENT_KINDS`, workspace ownership, source bindings and the generated-panel\nsubset are derived from that one registry; this document is not a second\nvalidation whitelist. Bundle data cannot register executable components.\n\nThe shared library includes basic layouts and controls, question workspaces,\nrecord navigation/editing, diagrams, canvases, artifact readers and previews.\nFull-height workspace components preserve scroll and navigation ownership:\n`record_board`, `document_workspace`, `artifact_workspace`, `diagram_workspace`,\n`canvas_workspace`, `preview_workspace` and `navigation_workspace` expose their\nbehavior through explicit data bindings rather than Kit names. These are reusable\ncapabilities, not a guarantee that every record schema fits every workspace.\n\n`record_board.board.detail_sources` can embed exactly one `record_workspace`\nunder the selected card. Each `{section, reference}` binding declares an unordered\ndirect record collection and a readonly `record_select` back to the board's\nparent section. The child workspace sources must belong to those bindings.\nOwner and child storage paths cannot alias or overlap. The renderer filters\nchildren by the selected parent, binds new records to it, and merges hidden\nsibling records back into canonical updates. It refuses sibling-id replacement,\nreparenting and writes outside these collections. This is a view projection,\nnot a second stored copy; it does not support independently ordered child maps,\nnested `fields_path` records or artifact staging in this first composition slice.\nOrdinary `detail_sections` retain their existing same-record nested-form meaning.\n\n`record_board` uses full-width cards and a workspace-covering overview. Optional\n`board.group` binds a real grouping field. When omitted, the sidebar lists records\ndirectly, cards have no artificial group heading, and the overview connects the\nroot directly to records. Do not bind long summaries merely to satisfy grouping;\nthis projection never adds a grouping field to canonical records.\nSidebar selection scrolls to a card; it does not start editing. Description and\nbadge drafts have explicit Save/Cancel, while rejected records remain inspectable\nwithout granting edit access. Optional `board.id_field` binds a declared visible,\nreadonly `text` field and displays its existing string beside the card title and\nat the top of cover details. Inline details retain the same card header. It does\nnot add an ID editor, generate a fallback ID or write state; omission retains the\nexisting title-only presentation. `board.detail_fields` restricts the parent fields\nshown in the detail fold, and `details_title` localizes its heading. Optional nested\ndimensions can be added or removed without replacing unrelated record fields.\n`board.detail_fields_mode: fixed` instead shows every declared nested input and\nremoves dimension-level add/delete controls; collection item add/delete still\nuses its usual editor. Fields remain schema-optional, including empty inputs.\nViewing does not insert missing strings/maps. Omitted/`on_demand` retains the\nexisting optional-dimension behavior. This option grants no new write authority.\n\n`record_workspace.workspace_view: switch` puts the first child canvas over the\nwhole workspace. The edge action opens it, and the return action or a node's\ndetails action returns to the selected record. It does not add form/canvas tabs\nto the sidebar. Covered content stays mounted and inert to preserve selection,\ndrafts and the graph viewport without allowing hidden controls to receive input.\n\n`record_related_editor.record_table` is an authored-only table presentation of\nthe same child collection, not a conversion to a `rows` array. Its finite\n`columns: [{fields: [field_key, ...], label?: string}]` groups existing field\neditors into cells. Every non-hidden field declared for that child section must\nappear exactly once; hidden/foreign/duplicate bindings and unknown column keys\nare rejected. Column labels default to the first field's label and use the usual\nlocale resolution. A cell retains field visibility, help, requiredness, custom\nconditions and existing edit/derived-field rules. Record creation still binds\nthe selected parent, deletion preserves the normal section cleanup rules, and\n`inherit_from_graph` tables remain source-linked and read-only. The shared table\nwrapper owns horizontal scrolling at narrow widths. This does not promote the\ncomponent or this declaration to generated A2UI.\n\nAn authored graph hierarchy with `max_parents: 1` may opt into\n`parent_control: header`. The existing single-parent selector then sits beside\nthe selected record's form title, rather than above the whole inspector. It\nstill updates the same relation edge, rejects cycles, retains the source-record\nnavigation and shows the actual parent in read-only mode. Omission preserves\nthe prior inspector presentation; neither view creates an extra parent field.\n\n`diagram_workspace.diagram.detail_rows` groups declared read-only fields into\nresponsive fact cards. `chip_fields` selects string-list fields rendered as tags;\n`detail_hint_fields` supplies the populated field labels for the details action.\n`tags` maps declared enum fields to labels and finite semantic tones. These are\npresentation declarations, not new edit rights or storage. Diagram details cover\nonly the content pane; the navigator remains available. Leaving an edited diagram\nstill requires successful serialization through the existing save barrier.\n\n`diagram_workspace.diagram.label_source` can read a declared label from another\nsection bound to the same record collection. The optional `inspector` keeps a\ncontext editor alongside the BPMN canvas: `process_sections` edit the selected\nprocess; `nodes` binds `source`, `process_field`, `element_field`, `label_field`\nand same-collection `sections`. Optional `related` groups use a process reference\nand an optional `node_field`; `advanced: true` starts the group collapsed.\nReferences must be declared `record_select` fields targeting the corresponding\ncollection. Clicking an element resolves its exact ID within the selected\nprocess only; absent or duplicate bindings do not guess a record. Existing field\nedit permissions and the atomic artifact save barrier remain authoritative.\nThis is contextual navigation, not automatic synchronization of BPMN structure\nand business facts; authors must explain how structural changes are reconciled.\n\nFor an exact component contract and on-demand local type declarations, use the\nauthoring inspector from the repository root:\n\n```sh\nnode .agents/skills/design-bundle-creator/scripts/inspect-panel-component.mjs . navigation_workspace --type ComponentNode.navigation_map.edges\n```\n\nUse the [component extension contract](a2ui-component-catalog-contract.md) when\nadding a component: catalog, validation, renderer, styles, edit boundaries,\ntests and authoring guidance must agree. Trusted runtime additions are possible;\nunknown component names in a manifest are rejected.\n\nAcceptance of a component name alone does not establish rendering fidelity,\neditable lifecycle support, or compatibility with every host; those require\nthe component's binding contract and actual runtime verification.\n\nPredefined DSL and A2UI-derived panels share this library, but generated panels\nmay use only the subset with an implemented generation/edit-authority contract.\nAn authored workspace is not automatically promoted into that subset.\nSupported generated results can be deterministically retained as DSL; unsupported\ncapabilities must fail explicitly, never disappear during conversion. This is\nnot an arbitrary bidirectional A2UI protocol converter.\n\n`question_list` is the standard controlled question interaction. Each source\nrecord uses `prompt`, optional `note`, `kind` (`text | single | multiple`),\noptional `choices[]` (`value`, `label`, `recommended`), `answer`, and optional\n`detail`. Text answers render as one multiline input; an existing text-question\n`detail` remains visible as read-only context rather than becoming a second\nanswer box. Single/multiple answers use accessible choice rows and may edit\n`detail`. Existing read-only context and choice supplements use the same\nlocalized label (without the optional-input suffix in reading mode). Cards\nwith a non-empty `answer` collapse to a readable result and can\nbe reopened for editing. The component writes only the fields exposed by that\ninteraction back to the owning record. It does not invent approval state, and an\nempty answer remains unanswered even when `detail` contains context. Native\nproviders may explicitly extend answer-state semantics for attachments, and\nmay add rounds or rejection around this base contract without making those\nextensions mandatory for other Kits.\n\nAuthored `question_list`, `question_rounds`, and `question_workspace` may declare\n`card_groups` with a unique `id`, `title`, and ordered `question_ids`. Members\nmust be contiguous in the existing record order and, for round workspaces, stay\nwithin one round. Invalid groups fall back to ordinary cards with a diagnostic;\ngrouping never reorders canonical records. Generated-origin Panels reject this\nauthored extension.\n\nEach group may declare a `presentation` object containing only optional boolean\n`always_expanded`, `show_detail`, and `show_attachments` properties. These select\nshared component behavior, not Bundle-specific styling. Omission preserves the\nusual collapse, detail, and attachment controls. Hiding a control preserves its\ncanonical data; keeping a card expanded does not grant editing permission.\nRead-only, disabled, protected, historical and rejection guards still apply.\n\n`question_workspace` composes the same question cards with the standard\n`panel_workspace` navigation shell. It groups records by optional numeric\n`round`, shows answer progress, and keeps only the selected group in the main\npane; records without a round form one current group. Its optional\n`description` is rendered through the shared sticky workspace Tip Bar above\nthe main content, never squeezed into the navigation sidebar. `question_rounds` is the\nbackward-compatible alias for this workspace behavior. Optional\n`multimodal_answer[]` entries use the Web App-compatible local reference shape\n(`type`, `file_md5`, `filename`, `mime_type`, `size_bytes`, `artifact_file`).\nThe client keeps pending bytes in a reserved browser-only transport, strips it\nbefore schema validation, and atomically saves only files still referenced by\ncanonical state. The transport is framework state, never a Bundle field.\n\nAuthored `question_workspace` / `question_rounds` nodes may explicitly set\n`question_policy.allow_choice_actions: true`. Expanded editable dynamic single\ncards offer “Switch to multiple choice”; multiple cards offer “Select all” /\n“Deselect all”. Omission or `false` preserves the existing controls. The shared\nruntime owns these actions and their localized styling, not Bundle CSS or an\nauthor-supplied `renderActions` callback. Switching changes only `kind` to\n`multiple`, preserving the exact answer bytes and keeping the editor open.\nSelect-all writes choice values in declared order through the existing\ncomma-separated `answer` contract; deselect-all writes an empty answer. Neither\naction changes detail, attachments, identity, choices or round. Records declared\nin `first_round_ids` are the fixed first-round configuration and do not receive\nthese actions; `protected_ids` still controls rejection only. Read-only,\ndisabled, rejected and read-only historical cards cannot invoke the actions.\nGenerated-origin/A2UI auto Panels reject this configuration, even when `false`;\ntheir existing answer/detail-only write authority and protected `kind` remain\nunchanged. Converting a generated view into an authored reusable panel does not\nsilently grant this capability: the author must opt in under the static contract.\n\n`panel_workspace` is the reusable panel-internal left navigation + main content\nlayout. It standardizes containment, scroll ownership and narrow-panel fallback;\nit does not define domain records or selection semantics. Use it rather than\ncopying a Kit-specific two-column shell.\n\nThe shared runtime `PanelWorkspaceNavigation` accepts optional per-item\n`description`, `supporting`, and `statusLabel` display slots alongside the\nlabel/current row. These are supplied display text, not canonical fields or\nnew DSL expressions. Omitted slots render no empty rows. The `meta` fallback\nremains supported. A marker requires both explicit `statusIndicator: true`\nand an existing `status`; a label-only item never gains an inferred status dot.\nFlat record navigation, question rounds, and future workspace consumers share\nthe same base navigation typography, spacing and selected appearance. Bundle\nCSS is not required. Hierarchical trees retain their separate structure.\nQuestion progress excludes rejected items from answered/completion checks,\nwhile retaining all group records in the displayed total and preserving fixed\nquestion grouping, stable IDs, selection and canonical answers. The original\nWeb App question panel used body round sections, not this sidebar; the shared\nsidebar is an enhanced structure using the original public navigation style,\nnot a claim of one-to-one restoration of a nonexistent original sidebar.\n\n`doc_lifecycle_studio` binds `objects`/`axes`/`actions` sections (validation\nfails loud when one is missing) and renders the fact table (actions × state\naxes, per-cell effects) plus process/derivation/ledger projections derived at\nrender time; unavailable views render disabled with a reason, never hidden.\n`rowview_workbench` renders the residue envelope (below) and requires a\n`source` declaring the add section it owns — the details-envelope schema\ncheck and the renderer are both scoped to that section; a workbench without\n`source` is rejected at compile time.\n\nIn editable mode `bpmn_canvas` edits bidirectionally: each process record's\n`name` and `steps` array (step name, `kind` task/gateway/event, order, add,\nremove) round-trip through the panel Save like any field edit.\n"
|
|
1743
1743
|
}
|
|
@@ -1852,8 +1852,8 @@
|
|
|
1852
1852
|
"sections": [
|
|
1853
1853
|
{
|
|
1854
1854
|
"file": "docs/dsl-spec.md",
|
|
1855
|
-
"line":
|
|
1856
|
-
"endLine":
|
|
1855
|
+
"line": 958,
|
|
1856
|
+
"endLine": 1169,
|
|
1857
1857
|
"heading": "`component` (trusted, extensible library)",
|
|
1858
1858
|
"content": "### `component` (trusted, extensible library)\n\nThe authoritative vocabulary is [`PANEL_COMPONENT_CATALOG`](../packages/core/src/panel-component-catalog.ts).\n`COMPONENT_KINDS`, workspace ownership, source bindings and the generated-panel\nsubset are derived from that one registry; this document is not a second\nvalidation whitelist. Bundle data cannot register executable components.\n\nThe shared library includes basic layouts and controls, question workspaces,\nrecord navigation/editing, diagrams, canvases, artifact readers and previews.\nFull-height workspace components preserve scroll and navigation ownership:\n`record_board`, `document_workspace`, `artifact_workspace`, `diagram_workspace`,\n`canvas_workspace`, `preview_workspace` and `navigation_workspace` expose their\nbehavior through explicit data bindings rather than Kit names. These are reusable\ncapabilities, not a guarantee that every record schema fits every workspace.\n\n`record_board.board.detail_sources` can embed exactly one `record_workspace`\nunder the selected card. Each `{section, reference}` binding declares an unordered\ndirect record collection and a readonly `record_select` back to the board's\nparent section. The child workspace sources must belong to those bindings.\nOwner and child storage paths cannot alias or overlap. The renderer filters\nchildren by the selected parent, binds new records to it, and merges hidden\nsibling records back into canonical updates. It refuses sibling-id replacement,\nreparenting and writes outside these collections. This is a view projection,\nnot a second stored copy; it does not support independently ordered child maps,\nnested `fields_path` records or artifact staging in this first composition slice.\nOrdinary `detail_sections` retain their existing same-record nested-form meaning.\n\n`record_board` uses full-width cards and a workspace-covering overview. Optional\n`board.group` binds a real grouping field. When omitted, the sidebar lists records\ndirectly, cards have no artificial group heading, and the overview connects the\nroot directly to records. Do not bind long summaries merely to satisfy grouping;\nthis projection never adds a grouping field to canonical records.\nSidebar selection scrolls to a card; it does not start editing. Description and\nbadge drafts have explicit Save/Cancel, while rejected records remain inspectable\nwithout granting edit access. Optional `board.id_field` binds a declared visible,\nreadonly `text` field and displays its existing string beside the card title and\nat the top of cover details. Inline details retain the same card header. It does\nnot add an ID editor, generate a fallback ID or write state; omission retains the\nexisting title-only presentation. `board.detail_fields` restricts the parent fields\nshown in the detail fold, and `details_title` localizes its heading. Optional nested\ndimensions can be added or removed without replacing unrelated record fields.\n`board.detail_fields_mode: fixed` instead shows every declared nested input and\nremoves dimension-level add/delete controls; collection item add/delete still\nuses its usual editor. Fields remain schema-optional, including empty inputs.\nViewing does not insert missing strings/maps. Omitted/`on_demand` retains the\nexisting optional-dimension behavior. This option grants no new write authority.\n\n`record_workspace.workspace_view: switch` puts the first child canvas over the\nwhole workspace. The edge action opens it, and the return action or a node's\ndetails action returns to the selected record. It does not add form/canvas tabs\nto the sidebar. Covered content stays mounted and inert to preserve selection,\ndrafts and the graph viewport without allowing hidden controls to receive input.\n\n`record_related_editor.record_table` is an authored-only table presentation of\nthe same child collection, not a conversion to a `rows` array. Its finite\n`columns: [{fields: [field_key, ...], label?: string}]` groups existing field\neditors into cells. Every non-hidden field declared for that child section must\nappear exactly once; hidden/foreign/duplicate bindings and unknown column keys\nare rejected. Column labels default to the first field's label and use the usual\nlocale resolution. A cell retains field visibility, help, requiredness, custom\nconditions and existing edit/derived-field rules. Record creation still binds\nthe selected parent, deletion preserves the normal section cleanup rules, and\n`inherit_from_graph` tables remain source-linked and read-only. The shared table\nwrapper owns horizontal scrolling at narrow widths. This does not promote the\ncomponent or this declaration to generated A2UI.\n\nAn authored graph hierarchy with `max_parents: 1` may opt into\n`parent_control: header`. The existing single-parent selector then sits beside\nthe selected record's form title, rather than above the whole inspector. It\nstill updates the same relation edge, rejects cycles, retains the source-record\nnavigation and shows the actual parent in read-only mode. Omission preserves\nthe prior inspector presentation; neither view creates an extra parent field.\n\n`diagram_workspace.diagram.detail_rows` groups declared read-only fields into\nresponsive fact cards. `chip_fields` selects string-list fields rendered as tags;\n`detail_hint_fields` supplies the populated field labels for the details action.\n`tags` maps declared enum fields to labels and finite semantic tones. These are\npresentation declarations, not new edit rights or storage. Diagram details cover\nonly the content pane; the navigator remains available. Leaving an edited diagram\nstill requires successful serialization through the existing save barrier.\n\n`diagram_workspace.diagram.label_source` can read a declared label from another\nsection bound to the same record collection. The optional `inspector` keeps a\ncontext editor alongside the BPMN canvas: `process_sections` edit the selected\nprocess; `nodes` binds `source`, `process_field`, `element_field`, `label_field`\nand same-collection `sections`. Optional `related` groups use a process reference\nand an optional `node_field`; `advanced: true` starts the group collapsed.\nReferences must be declared `record_select` fields targeting the corresponding\ncollection. Clicking an element resolves its exact ID within the selected\nprocess only; absent or duplicate bindings do not guess a record. Existing field\nedit permissions and the atomic artifact save barrier remain authoritative.\nThis is contextual navigation, not automatic synchronization of BPMN structure\nand business facts; authors must explain how structural changes are reconciled.\n\nFor an exact component contract and on-demand local type declarations, use the\nauthoring inspector from the repository root:\n\n```sh\nnode .agents/skills/design-bundle-creator/scripts/inspect-panel-component.mjs . navigation_workspace --type ComponentNode.navigation_map.edges\n```\n\nUse the [component extension contract](a2ui-component-catalog-contract.md) when\nadding a component: catalog, validation, renderer, styles, edit boundaries,\ntests and authoring guidance must agree. Trusted runtime additions are possible;\nunknown component names in a manifest are rejected.\n\nAcceptance of a component name alone does not establish rendering fidelity,\neditable lifecycle support, or compatibility with every host; those require\nthe component's binding contract and actual runtime verification.\n\nPredefined DSL and A2UI-derived panels share this library, but generated panels\nmay use only the subset with an implemented generation/edit-authority contract.\nAn authored workspace is not automatically promoted into that subset.\nSupported generated results can be deterministically retained as DSL; unsupported\ncapabilities must fail explicitly, never disappear during conversion. This is\nnot an arbitrary bidirectional A2UI protocol converter.\n\n`question_list` is the standard controlled question interaction. Each source\nrecord uses `prompt`, optional `note`, `kind` (`text | single | multiple`),\noptional `choices[]` (`value`, `label`, `recommended`), `answer`, and optional\n`detail`. Text answers render as one multiline input; an existing text-question\n`detail` remains visible as read-only context rather than becoming a second\nanswer box. Single/multiple answers use accessible choice rows and may edit\n`detail`. Existing read-only context and choice supplements use the same\nlocalized label (without the optional-input suffix in reading mode). Cards\nwith a non-empty `answer` collapse to a readable result and can\nbe reopened for editing. The component writes only the fields exposed by that\ninteraction back to the owning record. It does not invent approval state, and an\nempty answer remains unanswered even when `detail` contains context. Native\nproviders may explicitly extend answer-state semantics for attachments, and\nmay add rounds or rejection around this base contract without making those\nextensions mandatory for other Kits.\n\nAuthored `question_list`, `question_rounds`, and `question_workspace` may declare\n`card_groups` with a unique `id`, `title`, and ordered `question_ids`. Members\nmust be contiguous in the existing record order and, for round workspaces, stay\nwithin one round. Invalid groups fall back to ordinary cards with a diagnostic;\ngrouping never reorders canonical records. Generated-origin Panels reject this\nauthored extension.\n\nEach group may declare a `presentation` object containing only optional boolean\n`always_expanded`, `show_detail`, and `show_attachments` properties. These select\nshared component behavior, not Bundle-specific styling. Omission preserves the\nusual collapse, detail, and attachment controls. Hiding a control preserves its\ncanonical data; keeping a card expanded does not grant editing permission.\nRead-only, disabled, protected, historical and rejection guards still apply.\n\n`question_workspace` composes the same question cards with the standard\n`panel_workspace` navigation shell. It groups records by optional numeric\n`round`, shows answer progress, and keeps only the selected group in the main\npane; records without a round form one current group. Its optional\n`description` is rendered through the shared sticky workspace Tip Bar above\nthe main content, never squeezed into the navigation sidebar. `question_rounds` is the\nbackward-compatible alias for this workspace behavior. Optional\n`multimodal_answer[]` entries use the Web App-compatible local reference shape\n(`type`, `file_md5`, `filename`, `mime_type`, `size_bytes`, `artifact_file`).\nThe client keeps pending bytes in a reserved browser-only transport, strips it\nbefore schema validation, and atomically saves only files still referenced by\ncanonical state. The transport is framework state, never a Bundle field.\n\nAuthored `question_workspace` / `question_rounds` nodes may explicitly set\n`question_policy.allow_choice_actions: true`. Expanded editable dynamic single\ncards offer “Switch to multiple choice”; multiple cards offer “Select all” /\n“Deselect all”. Omission or `false` preserves the existing controls. The shared\nruntime owns these actions and their localized styling, not Bundle CSS or an\nauthor-supplied `renderActions` callback. Switching changes only `kind` to\n`multiple`, preserving the exact answer bytes and keeping the editor open.\nSelect-all writes choice values in declared order through the existing\ncomma-separated `answer` contract; deselect-all writes an empty answer. Neither\naction changes detail, attachments, identity, choices or round. Records declared\nin `first_round_ids` are the fixed first-round configuration and do not receive\nthese actions; `protected_ids` still controls rejection only. Read-only,\ndisabled, rejected and read-only historical cards cannot invoke the actions.\nGenerated-origin/A2UI auto Panels reject this configuration, even when `false`;\ntheir existing answer/detail-only write authority and protected `kind` remain\nunchanged. Converting a generated view into an authored reusable panel does not\nsilently grant this capability: the author must opt in under the static contract.\n\n`panel_workspace` is the reusable panel-internal left navigation + main content\nlayout. It standardizes containment, scroll ownership and narrow-panel fallback;\nit does not define domain records or selection semantics. Use it rather than\ncopying a Kit-specific two-column shell.\n\nThe shared runtime `PanelWorkspaceNavigation` accepts optional per-item\n`description`, `supporting`, and `statusLabel` display slots alongside the\nlabel/current row. These are supplied display text, not canonical fields or\nnew DSL expressions. Omitted slots render no empty rows. The `meta` fallback\nremains supported. A marker requires both explicit `statusIndicator: true`\nand an existing `status`; a label-only item never gains an inferred status dot.\nFlat record navigation, question rounds, and future workspace consumers share\nthe same base navigation typography, spacing and selected appearance. Bundle\nCSS is not required. Hierarchical trees retain their separate structure.\nQuestion progress excludes rejected items from answered/completion checks,\nwhile retaining all group records in the displayed total and preserving fixed\nquestion grouping, stable IDs, selection and canonical answers. The original\nWeb App question panel used body round sections, not this sidebar; the shared\nsidebar is an enhanced structure using the original public navigation style,\nnot a claim of one-to-one restoration of a nonexistent original sidebar.\n\n`doc_lifecycle_studio` binds `objects`/`axes`/`actions` sections (validation\nfails loud when one is missing) and renders the fact table (actions × state\naxes, per-cell effects) plus process/derivation/ledger projections derived at\nrender time; unavailable views render disabled with a reason, never hidden.\n`rowview_workbench` renders the residue envelope (below) and requires a\n`source` declaring the add section it owns — the details-envelope schema\ncheck and the renderer are both scoped to that section; a workbench without\n`source` is rejected at compile time.\n\nIn editable mode `bpmn_canvas` edits bidirectionally: each process record's\n`name` and `steps` array (step name, `kind` task/gateway/event, order, add,\nremove) round-trip through the panel Save like any field edit.\n"
|
|
1859
1859
|
}
|
|
@@ -1968,8 +1968,8 @@
|
|
|
1968
1968
|
"sections": [
|
|
1969
1969
|
{
|
|
1970
1970
|
"file": "docs/dsl-spec.md",
|
|
1971
|
-
"line":
|
|
1972
|
-
"endLine":
|
|
1971
|
+
"line": 958,
|
|
1972
|
+
"endLine": 1169,
|
|
1973
1973
|
"heading": "`component` (trusted, extensible library)",
|
|
1974
1974
|
"content": "### `component` (trusted, extensible library)\n\nThe authoritative vocabulary is [`PANEL_COMPONENT_CATALOG`](../packages/core/src/panel-component-catalog.ts).\n`COMPONENT_KINDS`, workspace ownership, source bindings and the generated-panel\nsubset are derived from that one registry; this document is not a second\nvalidation whitelist. Bundle data cannot register executable components.\n\nThe shared library includes basic layouts and controls, question workspaces,\nrecord navigation/editing, diagrams, canvases, artifact readers and previews.\nFull-height workspace components preserve scroll and navigation ownership:\n`record_board`, `document_workspace`, `artifact_workspace`, `diagram_workspace`,\n`canvas_workspace`, `preview_workspace` and `navigation_workspace` expose their\nbehavior through explicit data bindings rather than Kit names. These are reusable\ncapabilities, not a guarantee that every record schema fits every workspace.\n\n`record_board.board.detail_sources` can embed exactly one `record_workspace`\nunder the selected card. Each `{section, reference}` binding declares an unordered\ndirect record collection and a readonly `record_select` back to the board's\nparent section. The child workspace sources must belong to those bindings.\nOwner and child storage paths cannot alias or overlap. The renderer filters\nchildren by the selected parent, binds new records to it, and merges hidden\nsibling records back into canonical updates. It refuses sibling-id replacement,\nreparenting and writes outside these collections. This is a view projection,\nnot a second stored copy; it does not support independently ordered child maps,\nnested `fields_path` records or artifact staging in this first composition slice.\nOrdinary `detail_sections` retain their existing same-record nested-form meaning.\n\n`record_board` uses full-width cards and a workspace-covering overview. Optional\n`board.group` binds a real grouping field. When omitted, the sidebar lists records\ndirectly, cards have no artificial group heading, and the overview connects the\nroot directly to records. Do not bind long summaries merely to satisfy grouping;\nthis projection never adds a grouping field to canonical records.\nSidebar selection scrolls to a card; it does not start editing. Description and\nbadge drafts have explicit Save/Cancel, while rejected records remain inspectable\nwithout granting edit access. Optional `board.id_field` binds a declared visible,\nreadonly `text` field and displays its existing string beside the card title and\nat the top of cover details. Inline details retain the same card header. It does\nnot add an ID editor, generate a fallback ID or write state; omission retains the\nexisting title-only presentation. `board.detail_fields` restricts the parent fields\nshown in the detail fold, and `details_title` localizes its heading. Optional nested\ndimensions can be added or removed without replacing unrelated record fields.\n`board.detail_fields_mode: fixed` instead shows every declared nested input and\nremoves dimension-level add/delete controls; collection item add/delete still\nuses its usual editor. Fields remain schema-optional, including empty inputs.\nViewing does not insert missing strings/maps. Omitted/`on_demand` retains the\nexisting optional-dimension behavior. This option grants no new write authority.\n\n`record_workspace.workspace_view: switch` puts the first child canvas over the\nwhole workspace. The edge action opens it, and the return action or a node's\ndetails action returns to the selected record. It does not add form/canvas tabs\nto the sidebar. Covered content stays mounted and inert to preserve selection,\ndrafts and the graph viewport without allowing hidden controls to receive input.\n\n`record_related_editor.record_table` is an authored-only table presentation of\nthe same child collection, not a conversion to a `rows` array. Its finite\n`columns: [{fields: [field_key, ...], label?: string}]` groups existing field\neditors into cells. Every non-hidden field declared for that child section must\nappear exactly once; hidden/foreign/duplicate bindings and unknown column keys\nare rejected. Column labels default to the first field's label and use the usual\nlocale resolution. A cell retains field visibility, help, requiredness, custom\nconditions and existing edit/derived-field rules. Record creation still binds\nthe selected parent, deletion preserves the normal section cleanup rules, and\n`inherit_from_graph` tables remain source-linked and read-only. The shared table\nwrapper owns horizontal scrolling at narrow widths. This does not promote the\ncomponent or this declaration to generated A2UI.\n\nAn authored graph hierarchy with `max_parents: 1` may opt into\n`parent_control: header`. The existing single-parent selector then sits beside\nthe selected record's form title, rather than above the whole inspector. It\nstill updates the same relation edge, rejects cycles, retains the source-record\nnavigation and shows the actual parent in read-only mode. Omission preserves\nthe prior inspector presentation; neither view creates an extra parent field.\n\n`diagram_workspace.diagram.detail_rows` groups declared read-only fields into\nresponsive fact cards. `chip_fields` selects string-list fields rendered as tags;\n`detail_hint_fields` supplies the populated field labels for the details action.\n`tags` maps declared enum fields to labels and finite semantic tones. These are\npresentation declarations, not new edit rights or storage. Diagram details cover\nonly the content pane; the navigator remains available. Leaving an edited diagram\nstill requires successful serialization through the existing save barrier.\n\n`diagram_workspace.diagram.label_source` can read a declared label from another\nsection bound to the same record collection. The optional `inspector` keeps a\ncontext editor alongside the BPMN canvas: `process_sections` edit the selected\nprocess; `nodes` binds `source`, `process_field`, `element_field`, `label_field`\nand same-collection `sections`. Optional `related` groups use a process reference\nand an optional `node_field`; `advanced: true` starts the group collapsed.\nReferences must be declared `record_select` fields targeting the corresponding\ncollection. Clicking an element resolves its exact ID within the selected\nprocess only; absent or duplicate bindings do not guess a record. Existing field\nedit permissions and the atomic artifact save barrier remain authoritative.\nThis is contextual navigation, not automatic synchronization of BPMN structure\nand business facts; authors must explain how structural changes are reconciled.\n\nFor an exact component contract and on-demand local type declarations, use the\nauthoring inspector from the repository root:\n\n```sh\nnode .agents/skills/design-bundle-creator/scripts/inspect-panel-component.mjs . navigation_workspace --type ComponentNode.navigation_map.edges\n```\n\nUse the [component extension contract](a2ui-component-catalog-contract.md) when\nadding a component: catalog, validation, renderer, styles, edit boundaries,\ntests and authoring guidance must agree. Trusted runtime additions are possible;\nunknown component names in a manifest are rejected.\n\nAcceptance of a component name alone does not establish rendering fidelity,\neditable lifecycle support, or compatibility with every host; those require\nthe component's binding contract and actual runtime verification.\n\nPredefined DSL and A2UI-derived panels share this library, but generated panels\nmay use only the subset with an implemented generation/edit-authority contract.\nAn authored workspace is not automatically promoted into that subset.\nSupported generated results can be deterministically retained as DSL; unsupported\ncapabilities must fail explicitly, never disappear during conversion. This is\nnot an arbitrary bidirectional A2UI protocol converter.\n\n`question_list` is the standard controlled question interaction. Each source\nrecord uses `prompt`, optional `note`, `kind` (`text | single | multiple`),\noptional `choices[]` (`value`, `label`, `recommended`), `answer`, and optional\n`detail`. Text answers render as one multiline input; an existing text-question\n`detail` remains visible as read-only context rather than becoming a second\nanswer box. Single/multiple answers use accessible choice rows and may edit\n`detail`. Existing read-only context and choice supplements use the same\nlocalized label (without the optional-input suffix in reading mode). Cards\nwith a non-empty `answer` collapse to a readable result and can\nbe reopened for editing. The component writes only the fields exposed by that\ninteraction back to the owning record. It does not invent approval state, and an\nempty answer remains unanswered even when `detail` contains context. Native\nproviders may explicitly extend answer-state semantics for attachments, and\nmay add rounds or rejection around this base contract without making those\nextensions mandatory for other Kits.\n\nAuthored `question_list`, `question_rounds`, and `question_workspace` may declare\n`card_groups` with a unique `id`, `title`, and ordered `question_ids`. Members\nmust be contiguous in the existing record order and, for round workspaces, stay\nwithin one round. Invalid groups fall back to ordinary cards with a diagnostic;\ngrouping never reorders canonical records. Generated-origin Panels reject this\nauthored extension.\n\nEach group may declare a `presentation` object containing only optional boolean\n`always_expanded`, `show_detail`, and `show_attachments` properties. These select\nshared component behavior, not Bundle-specific styling. Omission preserves the\nusual collapse, detail, and attachment controls. Hiding a control preserves its\ncanonical data; keeping a card expanded does not grant editing permission.\nRead-only, disabled, protected, historical and rejection guards still apply.\n\n`question_workspace` composes the same question cards with the standard\n`panel_workspace` navigation shell. It groups records by optional numeric\n`round`, shows answer progress, and keeps only the selected group in the main\npane; records without a round form one current group. Its optional\n`description` is rendered through the shared sticky workspace Tip Bar above\nthe main content, never squeezed into the navigation sidebar. `question_rounds` is the\nbackward-compatible alias for this workspace behavior. Optional\n`multimodal_answer[]` entries use the Web App-compatible local reference shape\n(`type`, `file_md5`, `filename`, `mime_type`, `size_bytes`, `artifact_file`).\nThe client keeps pending bytes in a reserved browser-only transport, strips it\nbefore schema validation, and atomically saves only files still referenced by\ncanonical state. The transport is framework state, never a Bundle field.\n\nAuthored `question_workspace` / `question_rounds` nodes may explicitly set\n`question_policy.allow_choice_actions: true`. Expanded editable dynamic single\ncards offer “Switch to multiple choice”; multiple cards offer “Select all” /\n“Deselect all”. Omission or `false` preserves the existing controls. The shared\nruntime owns these actions and their localized styling, not Bundle CSS or an\nauthor-supplied `renderActions` callback. Switching changes only `kind` to\n`multiple`, preserving the exact answer bytes and keeping the editor open.\nSelect-all writes choice values in declared order through the existing\ncomma-separated `answer` contract; deselect-all writes an empty answer. Neither\naction changes detail, attachments, identity, choices or round. Records declared\nin `first_round_ids` are the fixed first-round configuration and do not receive\nthese actions; `protected_ids` still controls rejection only. Read-only,\ndisabled, rejected and read-only historical cards cannot invoke the actions.\nGenerated-origin/A2UI auto Panels reject this configuration, even when `false`;\ntheir existing answer/detail-only write authority and protected `kind` remain\nunchanged. Converting a generated view into an authored reusable panel does not\nsilently grant this capability: the author must opt in under the static contract.\n\n`panel_workspace` is the reusable panel-internal left navigation + main content\nlayout. It standardizes containment, scroll ownership and narrow-panel fallback;\nit does not define domain records or selection semantics. Use it rather than\ncopying a Kit-specific two-column shell.\n\nThe shared runtime `PanelWorkspaceNavigation` accepts optional per-item\n`description`, `supporting`, and `statusLabel` display slots alongside the\nlabel/current row. These are supplied display text, not canonical fields or\nnew DSL expressions. Omitted slots render no empty rows. The `meta` fallback\nremains supported. A marker requires both explicit `statusIndicator: true`\nand an existing `status`; a label-only item never gains an inferred status dot.\nFlat record navigation, question rounds, and future workspace consumers share\nthe same base navigation typography, spacing and selected appearance. Bundle\nCSS is not required. Hierarchical trees retain their separate structure.\nQuestion progress excludes rejected items from answered/completion checks,\nwhile retaining all group records in the displayed total and preserving fixed\nquestion grouping, stable IDs, selection and canonical answers. The original\nWeb App question panel used body round sections, not this sidebar; the shared\nsidebar is an enhanced structure using the original public navigation style,\nnot a claim of one-to-one restoration of a nonexistent original sidebar.\n\n`doc_lifecycle_studio` binds `objects`/`axes`/`actions` sections (validation\nfails loud when one is missing) and renders the fact table (actions × state\naxes, per-cell effects) plus process/derivation/ledger projections derived at\nrender time; unavailable views render disabled with a reason, never hidden.\n`rowview_workbench` renders the residue envelope (below) and requires a\n`source` declaring the add section it owns — the details-envelope schema\ncheck and the renderer are both scoped to that section; a workbench without\n`source` is rejected at compile time.\n\nIn editable mode `bpmn_canvas` edits bidirectionally: each process record's\n`name` and `steps` array (step name, `kind` task/gateway/event, order, add,\nremove) round-trip through the panel Save like any field edit.\n"
|
|
1975
1975
|
}
|
|
@@ -2083,8 +2083,8 @@
|
|
|
2083
2083
|
"sections": [
|
|
2084
2084
|
{
|
|
2085
2085
|
"file": "docs/dsl-spec.md",
|
|
2086
|
-
"line":
|
|
2087
|
-
"endLine":
|
|
2086
|
+
"line": 958,
|
|
2087
|
+
"endLine": 1169,
|
|
2088
2088
|
"heading": "`component` (trusted, extensible library)",
|
|
2089
2089
|
"content": "### `component` (trusted, extensible library)\n\nThe authoritative vocabulary is [`PANEL_COMPONENT_CATALOG`](../packages/core/src/panel-component-catalog.ts).\n`COMPONENT_KINDS`, workspace ownership, source bindings and the generated-panel\nsubset are derived from that one registry; this document is not a second\nvalidation whitelist. Bundle data cannot register executable components.\n\nThe shared library includes basic layouts and controls, question workspaces,\nrecord navigation/editing, diagrams, canvases, artifact readers and previews.\nFull-height workspace components preserve scroll and navigation ownership:\n`record_board`, `document_workspace`, `artifact_workspace`, `diagram_workspace`,\n`canvas_workspace`, `preview_workspace` and `navigation_workspace` expose their\nbehavior through explicit data bindings rather than Kit names. These are reusable\ncapabilities, not a guarantee that every record schema fits every workspace.\n\n`record_board.board.detail_sources` can embed exactly one `record_workspace`\nunder the selected card. Each `{section, reference}` binding declares an unordered\ndirect record collection and a readonly `record_select` back to the board's\nparent section. The child workspace sources must belong to those bindings.\nOwner and child storage paths cannot alias or overlap. The renderer filters\nchildren by the selected parent, binds new records to it, and merges hidden\nsibling records back into canonical updates. It refuses sibling-id replacement,\nreparenting and writes outside these collections. This is a view projection,\nnot a second stored copy; it does not support independently ordered child maps,\nnested `fields_path` records or artifact staging in this first composition slice.\nOrdinary `detail_sections` retain their existing same-record nested-form meaning.\n\n`record_board` uses full-width cards and a workspace-covering overview. Optional\n`board.group` binds a real grouping field. When omitted, the sidebar lists records\ndirectly, cards have no artificial group heading, and the overview connects the\nroot directly to records. Do not bind long summaries merely to satisfy grouping;\nthis projection never adds a grouping field to canonical records.\nSidebar selection scrolls to a card; it does not start editing. Description and\nbadge drafts have explicit Save/Cancel, while rejected records remain inspectable\nwithout granting edit access. Optional `board.id_field` binds a declared visible,\nreadonly `text` field and displays its existing string beside the card title and\nat the top of cover details. Inline details retain the same card header. It does\nnot add an ID editor, generate a fallback ID or write state; omission retains the\nexisting title-only presentation. `board.detail_fields` restricts the parent fields\nshown in the detail fold, and `details_title` localizes its heading. Optional nested\ndimensions can be added or removed without replacing unrelated record fields.\n`board.detail_fields_mode: fixed` instead shows every declared nested input and\nremoves dimension-level add/delete controls; collection item add/delete still\nuses its usual editor. Fields remain schema-optional, including empty inputs.\nViewing does not insert missing strings/maps. Omitted/`on_demand` retains the\nexisting optional-dimension behavior. This option grants no new write authority.\n\n`record_workspace.workspace_view: switch` puts the first child canvas over the\nwhole workspace. The edge action opens it, and the return action or a node's\ndetails action returns to the selected record. It does not add form/canvas tabs\nto the sidebar. Covered content stays mounted and inert to preserve selection,\ndrafts and the graph viewport without allowing hidden controls to receive input.\n\n`record_related_editor.record_table` is an authored-only table presentation of\nthe same child collection, not a conversion to a `rows` array. Its finite\n`columns: [{fields: [field_key, ...], label?: string}]` groups existing field\neditors into cells. Every non-hidden field declared for that child section must\nappear exactly once; hidden/foreign/duplicate bindings and unknown column keys\nare rejected. Column labels default to the first field's label and use the usual\nlocale resolution. A cell retains field visibility, help, requiredness, custom\nconditions and existing edit/derived-field rules. Record creation still binds\nthe selected parent, deletion preserves the normal section cleanup rules, and\n`inherit_from_graph` tables remain source-linked and read-only. The shared table\nwrapper owns horizontal scrolling at narrow widths. This does not promote the\ncomponent or this declaration to generated A2UI.\n\nAn authored graph hierarchy with `max_parents: 1` may opt into\n`parent_control: header`. The existing single-parent selector then sits beside\nthe selected record's form title, rather than above the whole inspector. It\nstill updates the same relation edge, rejects cycles, retains the source-record\nnavigation and shows the actual parent in read-only mode. Omission preserves\nthe prior inspector presentation; neither view creates an extra parent field.\n\n`diagram_workspace.diagram.detail_rows` groups declared read-only fields into\nresponsive fact cards. `chip_fields` selects string-list fields rendered as tags;\n`detail_hint_fields` supplies the populated field labels for the details action.\n`tags` maps declared enum fields to labels and finite semantic tones. These are\npresentation declarations, not new edit rights or storage. Diagram details cover\nonly the content pane; the navigator remains available. Leaving an edited diagram\nstill requires successful serialization through the existing save barrier.\n\n`diagram_workspace.diagram.label_source` can read a declared label from another\nsection bound to the same record collection. The optional `inspector` keeps a\ncontext editor alongside the BPMN canvas: `process_sections` edit the selected\nprocess; `nodes` binds `source`, `process_field`, `element_field`, `label_field`\nand same-collection `sections`. Optional `related` groups use a process reference\nand an optional `node_field`; `advanced: true` starts the group collapsed.\nReferences must be declared `record_select` fields targeting the corresponding\ncollection. Clicking an element resolves its exact ID within the selected\nprocess only; absent or duplicate bindings do not guess a record. Existing field\nedit permissions and the atomic artifact save barrier remain authoritative.\nThis is contextual navigation, not automatic synchronization of BPMN structure\nand business facts; authors must explain how structural changes are reconciled.\n\nFor an exact component contract and on-demand local type declarations, use the\nauthoring inspector from the repository root:\n\n```sh\nnode .agents/skills/design-bundle-creator/scripts/inspect-panel-component.mjs . navigation_workspace --type ComponentNode.navigation_map.edges\n```\n\nUse the [component extension contract](a2ui-component-catalog-contract.md) when\nadding a component: catalog, validation, renderer, styles, edit boundaries,\ntests and authoring guidance must agree. Trusted runtime additions are possible;\nunknown component names in a manifest are rejected.\n\nAcceptance of a component name alone does not establish rendering fidelity,\neditable lifecycle support, or compatibility with every host; those require\nthe component's binding contract and actual runtime verification.\n\nPredefined DSL and A2UI-derived panels share this library, but generated panels\nmay use only the subset with an implemented generation/edit-authority contract.\nAn authored workspace is not automatically promoted into that subset.\nSupported generated results can be deterministically retained as DSL; unsupported\ncapabilities must fail explicitly, never disappear during conversion. This is\nnot an arbitrary bidirectional A2UI protocol converter.\n\n`question_list` is the standard controlled question interaction. Each source\nrecord uses `prompt`, optional `note`, `kind` (`text | single | multiple`),\noptional `choices[]` (`value`, `label`, `recommended`), `answer`, and optional\n`detail`. Text answers render as one multiline input; an existing text-question\n`detail` remains visible as read-only context rather than becoming a second\nanswer box. Single/multiple answers use accessible choice rows and may edit\n`detail`. Existing read-only context and choice supplements use the same\nlocalized label (without the optional-input suffix in reading mode). Cards\nwith a non-empty `answer` collapse to a readable result and can\nbe reopened for editing. The component writes only the fields exposed by that\ninteraction back to the owning record. It does not invent approval state, and an\nempty answer remains unanswered even when `detail` contains context. Native\nproviders may explicitly extend answer-state semantics for attachments, and\nmay add rounds or rejection around this base contract without making those\nextensions mandatory for other Kits.\n\nAuthored `question_list`, `question_rounds`, and `question_workspace` may declare\n`card_groups` with a unique `id`, `title`, and ordered `question_ids`. Members\nmust be contiguous in the existing record order and, for round workspaces, stay\nwithin one round. Invalid groups fall back to ordinary cards with a diagnostic;\ngrouping never reorders canonical records. Generated-origin Panels reject this\nauthored extension.\n\nEach group may declare a `presentation` object containing only optional boolean\n`always_expanded`, `show_detail`, and `show_attachments` properties. These select\nshared component behavior, not Bundle-specific styling. Omission preserves the\nusual collapse, detail, and attachment controls. Hiding a control preserves its\ncanonical data; keeping a card expanded does not grant editing permission.\nRead-only, disabled, protected, historical and rejection guards still apply.\n\n`question_workspace` composes the same question cards with the standard\n`panel_workspace` navigation shell. It groups records by optional numeric\n`round`, shows answer progress, and keeps only the selected group in the main\npane; records without a round form one current group. Its optional\n`description` is rendered through the shared sticky workspace Tip Bar above\nthe main content, never squeezed into the navigation sidebar. `question_rounds` is the\nbackward-compatible alias for this workspace behavior. Optional\n`multimodal_answer[]` entries use the Web App-compatible local reference shape\n(`type`, `file_md5`, `filename`, `mime_type`, `size_bytes`, `artifact_file`).\nThe client keeps pending bytes in a reserved browser-only transport, strips it\nbefore schema validation, and atomically saves only files still referenced by\ncanonical state. The transport is framework state, never a Bundle field.\n\nAuthored `question_workspace` / `question_rounds` nodes may explicitly set\n`question_policy.allow_choice_actions: true`. Expanded editable dynamic single\ncards offer “Switch to multiple choice”; multiple cards offer “Select all” /\n“Deselect all”. Omission or `false` preserves the existing controls. The shared\nruntime owns these actions and their localized styling, not Bundle CSS or an\nauthor-supplied `renderActions` callback. Switching changes only `kind` to\n`multiple`, preserving the exact answer bytes and keeping the editor open.\nSelect-all writes choice values in declared order through the existing\ncomma-separated `answer` contract; deselect-all writes an empty answer. Neither\naction changes detail, attachments, identity, choices or round. Records declared\nin `first_round_ids` are the fixed first-round configuration and do not receive\nthese actions; `protected_ids` still controls rejection only. Read-only,\ndisabled, rejected and read-only historical cards cannot invoke the actions.\nGenerated-origin/A2UI auto Panels reject this configuration, even when `false`;\ntheir existing answer/detail-only write authority and protected `kind` remain\nunchanged. Converting a generated view into an authored reusable panel does not\nsilently grant this capability: the author must opt in under the static contract.\n\n`panel_workspace` is the reusable panel-internal left navigation + main content\nlayout. It standardizes containment, scroll ownership and narrow-panel fallback;\nit does not define domain records or selection semantics. Use it rather than\ncopying a Kit-specific two-column shell.\n\nThe shared runtime `PanelWorkspaceNavigation` accepts optional per-item\n`description`, `supporting`, and `statusLabel` display slots alongside the\nlabel/current row. These are supplied display text, not canonical fields or\nnew DSL expressions. Omitted slots render no empty rows. The `meta` fallback\nremains supported. A marker requires both explicit `statusIndicator: true`\nand an existing `status`; a label-only item never gains an inferred status dot.\nFlat record navigation, question rounds, and future workspace consumers share\nthe same base navigation typography, spacing and selected appearance. Bundle\nCSS is not required. Hierarchical trees retain their separate structure.\nQuestion progress excludes rejected items from answered/completion checks,\nwhile retaining all group records in the displayed total and preserving fixed\nquestion grouping, stable IDs, selection and canonical answers. The original\nWeb App question panel used body round sections, not this sidebar; the shared\nsidebar is an enhanced structure using the original public navigation style,\nnot a claim of one-to-one restoration of a nonexistent original sidebar.\n\n`doc_lifecycle_studio` binds `objects`/`axes`/`actions` sections (validation\nfails loud when one is missing) and renders the fact table (actions × state\naxes, per-cell effects) plus process/derivation/ledger projections derived at\nrender time; unavailable views render disabled with a reason, never hidden.\n`rowview_workbench` renders the residue envelope (below) and requires a\n`source` declaring the add section it owns — the details-envelope schema\ncheck and the renderer are both scoped to that section; a workbench without\n`source` is rejected at compile time.\n\nIn editable mode `bpmn_canvas` edits bidirectionally: each process record's\n`name` and `steps` array (step name, `kind` task/gateway/event, order, add,\nremove) round-trip through the panel Save like any field edit.\n"
|
|
2090
2090
|
}
|
|
@@ -2198,8 +2198,8 @@
|
|
|
2198
2198
|
"sections": [
|
|
2199
2199
|
{
|
|
2200
2200
|
"file": "docs/dsl-spec.md",
|
|
2201
|
-
"line":
|
|
2202
|
-
"endLine":
|
|
2201
|
+
"line": 958,
|
|
2202
|
+
"endLine": 1169,
|
|
2203
2203
|
"heading": "`component` (trusted, extensible library)",
|
|
2204
2204
|
"content": "### `component` (trusted, extensible library)\n\nThe authoritative vocabulary is [`PANEL_COMPONENT_CATALOG`](../packages/core/src/panel-component-catalog.ts).\n`COMPONENT_KINDS`, workspace ownership, source bindings and the generated-panel\nsubset are derived from that one registry; this document is not a second\nvalidation whitelist. Bundle data cannot register executable components.\n\nThe shared library includes basic layouts and controls, question workspaces,\nrecord navigation/editing, diagrams, canvases, artifact readers and previews.\nFull-height workspace components preserve scroll and navigation ownership:\n`record_board`, `document_workspace`, `artifact_workspace`, `diagram_workspace`,\n`canvas_workspace`, `preview_workspace` and `navigation_workspace` expose their\nbehavior through explicit data bindings rather than Kit names. These are reusable\ncapabilities, not a guarantee that every record schema fits every workspace.\n\n`record_board.board.detail_sources` can embed exactly one `record_workspace`\nunder the selected card. Each `{section, reference}` binding declares an unordered\ndirect record collection and a readonly `record_select` back to the board's\nparent section. The child workspace sources must belong to those bindings.\nOwner and child storage paths cannot alias or overlap. The renderer filters\nchildren by the selected parent, binds new records to it, and merges hidden\nsibling records back into canonical updates. It refuses sibling-id replacement,\nreparenting and writes outside these collections. This is a view projection,\nnot a second stored copy; it does not support independently ordered child maps,\nnested `fields_path` records or artifact staging in this first composition slice.\nOrdinary `detail_sections` retain their existing same-record nested-form meaning.\n\n`record_board` uses full-width cards and a workspace-covering overview. Optional\n`board.group` binds a real grouping field. When omitted, the sidebar lists records\ndirectly, cards have no artificial group heading, and the overview connects the\nroot directly to records. Do not bind long summaries merely to satisfy grouping;\nthis projection never adds a grouping field to canonical records.\nSidebar selection scrolls to a card; it does not start editing. Description and\nbadge drafts have explicit Save/Cancel, while rejected records remain inspectable\nwithout granting edit access. Optional `board.id_field` binds a declared visible,\nreadonly `text` field and displays its existing string beside the card title and\nat the top of cover details. Inline details retain the same card header. It does\nnot add an ID editor, generate a fallback ID or write state; omission retains the\nexisting title-only presentation. `board.detail_fields` restricts the parent fields\nshown in the detail fold, and `details_title` localizes its heading. Optional nested\ndimensions can be added or removed without replacing unrelated record fields.\n`board.detail_fields_mode: fixed` instead shows every declared nested input and\nremoves dimension-level add/delete controls; collection item add/delete still\nuses its usual editor. Fields remain schema-optional, including empty inputs.\nViewing does not insert missing strings/maps. Omitted/`on_demand` retains the\nexisting optional-dimension behavior. This option grants no new write authority.\n\n`record_workspace.workspace_view: switch` puts the first child canvas over the\nwhole workspace. The edge action opens it, and the return action or a node's\ndetails action returns to the selected record. It does not add form/canvas tabs\nto the sidebar. Covered content stays mounted and inert to preserve selection,\ndrafts and the graph viewport without allowing hidden controls to receive input.\n\n`record_related_editor.record_table` is an authored-only table presentation of\nthe same child collection, not a conversion to a `rows` array. Its finite\n`columns: [{fields: [field_key, ...], label?: string}]` groups existing field\neditors into cells. Every non-hidden field declared for that child section must\nappear exactly once; hidden/foreign/duplicate bindings and unknown column keys\nare rejected. Column labels default to the first field's label and use the usual\nlocale resolution. A cell retains field visibility, help, requiredness, custom\nconditions and existing edit/derived-field rules. Record creation still binds\nthe selected parent, deletion preserves the normal section cleanup rules, and\n`inherit_from_graph` tables remain source-linked and read-only. The shared table\nwrapper owns horizontal scrolling at narrow widths. This does not promote the\ncomponent or this declaration to generated A2UI.\n\nAn authored graph hierarchy with `max_parents: 1` may opt into\n`parent_control: header`. The existing single-parent selector then sits beside\nthe selected record's form title, rather than above the whole inspector. It\nstill updates the same relation edge, rejects cycles, retains the source-record\nnavigation and shows the actual parent in read-only mode. Omission preserves\nthe prior inspector presentation; neither view creates an extra parent field.\n\n`diagram_workspace.diagram.detail_rows` groups declared read-only fields into\nresponsive fact cards. `chip_fields` selects string-list fields rendered as tags;\n`detail_hint_fields` supplies the populated field labels for the details action.\n`tags` maps declared enum fields to labels and finite semantic tones. These are\npresentation declarations, not new edit rights or storage. Diagram details cover\nonly the content pane; the navigator remains available. Leaving an edited diagram\nstill requires successful serialization through the existing save barrier.\n\n`diagram_workspace.diagram.label_source` can read a declared label from another\nsection bound to the same record collection. The optional `inspector` keeps a\ncontext editor alongside the BPMN canvas: `process_sections` edit the selected\nprocess; `nodes` binds `source`, `process_field`, `element_field`, `label_field`\nand same-collection `sections`. Optional `related` groups use a process reference\nand an optional `node_field`; `advanced: true` starts the group collapsed.\nReferences must be declared `record_select` fields targeting the corresponding\ncollection. Clicking an element resolves its exact ID within the selected\nprocess only; absent or duplicate bindings do not guess a record. Existing field\nedit permissions and the atomic artifact save barrier remain authoritative.\nThis is contextual navigation, not automatic synchronization of BPMN structure\nand business facts; authors must explain how structural changes are reconciled.\n\nFor an exact component contract and on-demand local type declarations, use the\nauthoring inspector from the repository root:\n\n```sh\nnode .agents/skills/design-bundle-creator/scripts/inspect-panel-component.mjs . navigation_workspace --type ComponentNode.navigation_map.edges\n```\n\nUse the [component extension contract](a2ui-component-catalog-contract.md) when\nadding a component: catalog, validation, renderer, styles, edit boundaries,\ntests and authoring guidance must agree. Trusted runtime additions are possible;\nunknown component names in a manifest are rejected.\n\nAcceptance of a component name alone does not establish rendering fidelity,\neditable lifecycle support, or compatibility with every host; those require\nthe component's binding contract and actual runtime verification.\n\nPredefined DSL and A2UI-derived panels share this library, but generated panels\nmay use only the subset with an implemented generation/edit-authority contract.\nAn authored workspace is not automatically promoted into that subset.\nSupported generated results can be deterministically retained as DSL; unsupported\ncapabilities must fail explicitly, never disappear during conversion. This is\nnot an arbitrary bidirectional A2UI protocol converter.\n\n`question_list` is the standard controlled question interaction. Each source\nrecord uses `prompt`, optional `note`, `kind` (`text | single | multiple`),\noptional `choices[]` (`value`, `label`, `recommended`), `answer`, and optional\n`detail`. Text answers render as one multiline input; an existing text-question\n`detail` remains visible as read-only context rather than becoming a second\nanswer box. Single/multiple answers use accessible choice rows and may edit\n`detail`. Existing read-only context and choice supplements use the same\nlocalized label (without the optional-input suffix in reading mode). Cards\nwith a non-empty `answer` collapse to a readable result and can\nbe reopened for editing. The component writes only the fields exposed by that\ninteraction back to the owning record. It does not invent approval state, and an\nempty answer remains unanswered even when `detail` contains context. Native\nproviders may explicitly extend answer-state semantics for attachments, and\nmay add rounds or rejection around this base contract without making those\nextensions mandatory for other Kits.\n\nAuthored `question_list`, `question_rounds`, and `question_workspace` may declare\n`card_groups` with a unique `id`, `title`, and ordered `question_ids`. Members\nmust be contiguous in the existing record order and, for round workspaces, stay\nwithin one round. Invalid groups fall back to ordinary cards with a diagnostic;\ngrouping never reorders canonical records. Generated-origin Panels reject this\nauthored extension.\n\nEach group may declare a `presentation` object containing only optional boolean\n`always_expanded`, `show_detail`, and `show_attachments` properties. These select\nshared component behavior, not Bundle-specific styling. Omission preserves the\nusual collapse, detail, and attachment controls. Hiding a control preserves its\ncanonical data; keeping a card expanded does not grant editing permission.\nRead-only, disabled, protected, historical and rejection guards still apply.\n\n`question_workspace` composes the same question cards with the standard\n`panel_workspace` navigation shell. It groups records by optional numeric\n`round`, shows answer progress, and keeps only the selected group in the main\npane; records without a round form one current group. Its optional\n`description` is rendered through the shared sticky workspace Tip Bar above\nthe main content, never squeezed into the navigation sidebar. `question_rounds` is the\nbackward-compatible alias for this workspace behavior. Optional\n`multimodal_answer[]` entries use the Web App-compatible local reference shape\n(`type`, `file_md5`, `filename`, `mime_type`, `size_bytes`, `artifact_file`).\nThe client keeps pending bytes in a reserved browser-only transport, strips it\nbefore schema validation, and atomically saves only files still referenced by\ncanonical state. The transport is framework state, never a Bundle field.\n\nAuthored `question_workspace` / `question_rounds` nodes may explicitly set\n`question_policy.allow_choice_actions: true`. Expanded editable dynamic single\ncards offer “Switch to multiple choice”; multiple cards offer “Select all” /\n“Deselect all”. Omission or `false` preserves the existing controls. The shared\nruntime owns these actions and their localized styling, not Bundle CSS or an\nauthor-supplied `renderActions` callback. Switching changes only `kind` to\n`multiple`, preserving the exact answer bytes and keeping the editor open.\nSelect-all writes choice values in declared order through the existing\ncomma-separated `answer` contract; deselect-all writes an empty answer. Neither\naction changes detail, attachments, identity, choices or round. Records declared\nin `first_round_ids` are the fixed first-round configuration and do not receive\nthese actions; `protected_ids` still controls rejection only. Read-only,\ndisabled, rejected and read-only historical cards cannot invoke the actions.\nGenerated-origin/A2UI auto Panels reject this configuration, even when `false`;\ntheir existing answer/detail-only write authority and protected `kind` remain\nunchanged. Converting a generated view into an authored reusable panel does not\nsilently grant this capability: the author must opt in under the static contract.\n\n`panel_workspace` is the reusable panel-internal left navigation + main content\nlayout. It standardizes containment, scroll ownership and narrow-panel fallback;\nit does not define domain records or selection semantics. Use it rather than\ncopying a Kit-specific two-column shell.\n\nThe shared runtime `PanelWorkspaceNavigation` accepts optional per-item\n`description`, `supporting`, and `statusLabel` display slots alongside the\nlabel/current row. These are supplied display text, not canonical fields or\nnew DSL expressions. Omitted slots render no empty rows. The `meta` fallback\nremains supported. A marker requires both explicit `statusIndicator: true`\nand an existing `status`; a label-only item never gains an inferred status dot.\nFlat record navigation, question rounds, and future workspace consumers share\nthe same base navigation typography, spacing and selected appearance. Bundle\nCSS is not required. Hierarchical trees retain their separate structure.\nQuestion progress excludes rejected items from answered/completion checks,\nwhile retaining all group records in the displayed total and preserving fixed\nquestion grouping, stable IDs, selection and canonical answers. The original\nWeb App question panel used body round sections, not this sidebar; the shared\nsidebar is an enhanced structure using the original public navigation style,\nnot a claim of one-to-one restoration of a nonexistent original sidebar.\n\n`doc_lifecycle_studio` binds `objects`/`axes`/`actions` sections (validation\nfails loud when one is missing) and renders the fact table (actions × state\naxes, per-cell effects) plus process/derivation/ledger projections derived at\nrender time; unavailable views render disabled with a reason, never hidden.\n`rowview_workbench` renders the residue envelope (below) and requires a\n`source` declaring the add section it owns — the details-envelope schema\ncheck and the renderer are both scoped to that section; a workbench without\n`source` is rejected at compile time.\n\nIn editable mode `bpmn_canvas` edits bidirectionally: each process record's\n`name` and `steps` array (step name, `kind` task/gateway/event, order, add,\nremove) round-trip through the panel Save like any field edit.\n"
|
|
2205
2205
|
}
|
|
@@ -2315,8 +2315,8 @@
|
|
|
2315
2315
|
"sections": [
|
|
2316
2316
|
{
|
|
2317
2317
|
"file": "docs/dsl-spec.md",
|
|
2318
|
-
"line":
|
|
2319
|
-
"endLine":
|
|
2318
|
+
"line": 958,
|
|
2319
|
+
"endLine": 1169,
|
|
2320
2320
|
"heading": "`component` (trusted, extensible library)",
|
|
2321
2321
|
"content": "### `component` (trusted, extensible library)\n\nThe authoritative vocabulary is [`PANEL_COMPONENT_CATALOG`](../packages/core/src/panel-component-catalog.ts).\n`COMPONENT_KINDS`, workspace ownership, source bindings and the generated-panel\nsubset are derived from that one registry; this document is not a second\nvalidation whitelist. Bundle data cannot register executable components.\n\nThe shared library includes basic layouts and controls, question workspaces,\nrecord navigation/editing, diagrams, canvases, artifact readers and previews.\nFull-height workspace components preserve scroll and navigation ownership:\n`record_board`, `document_workspace`, `artifact_workspace`, `diagram_workspace`,\n`canvas_workspace`, `preview_workspace` and `navigation_workspace` expose their\nbehavior through explicit data bindings rather than Kit names. These are reusable\ncapabilities, not a guarantee that every record schema fits every workspace.\n\n`record_board.board.detail_sources` can embed exactly one `record_workspace`\nunder the selected card. Each `{section, reference}` binding declares an unordered\ndirect record collection and a readonly `record_select` back to the board's\nparent section. The child workspace sources must belong to those bindings.\nOwner and child storage paths cannot alias or overlap. The renderer filters\nchildren by the selected parent, binds new records to it, and merges hidden\nsibling records back into canonical updates. It refuses sibling-id replacement,\nreparenting and writes outside these collections. This is a view projection,\nnot a second stored copy; it does not support independently ordered child maps,\nnested `fields_path` records or artifact staging in this first composition slice.\nOrdinary `detail_sections` retain their existing same-record nested-form meaning.\n\n`record_board` uses full-width cards and a workspace-covering overview. Optional\n`board.group` binds a real grouping field. When omitted, the sidebar lists records\ndirectly, cards have no artificial group heading, and the overview connects the\nroot directly to records. Do not bind long summaries merely to satisfy grouping;\nthis projection never adds a grouping field to canonical records.\nSidebar selection scrolls to a card; it does not start editing. Description and\nbadge drafts have explicit Save/Cancel, while rejected records remain inspectable\nwithout granting edit access. Optional `board.id_field` binds a declared visible,\nreadonly `text` field and displays its existing string beside the card title and\nat the top of cover details. Inline details retain the same card header. It does\nnot add an ID editor, generate a fallback ID or write state; omission retains the\nexisting title-only presentation. `board.detail_fields` restricts the parent fields\nshown in the detail fold, and `details_title` localizes its heading. Optional nested\ndimensions can be added or removed without replacing unrelated record fields.\n`board.detail_fields_mode: fixed` instead shows every declared nested input and\nremoves dimension-level add/delete controls; collection item add/delete still\nuses its usual editor. Fields remain schema-optional, including empty inputs.\nViewing does not insert missing strings/maps. Omitted/`on_demand` retains the\nexisting optional-dimension behavior. This option grants no new write authority.\n\n`record_workspace.workspace_view: switch` puts the first child canvas over the\nwhole workspace. The edge action opens it, and the return action or a node's\ndetails action returns to the selected record. It does not add form/canvas tabs\nto the sidebar. Covered content stays mounted and inert to preserve selection,\ndrafts and the graph viewport without allowing hidden controls to receive input.\n\n`record_related_editor.record_table` is an authored-only table presentation of\nthe same child collection, not a conversion to a `rows` array. Its finite\n`columns: [{fields: [field_key, ...], label?: string}]` groups existing field\neditors into cells. Every non-hidden field declared for that child section must\nappear exactly once; hidden/foreign/duplicate bindings and unknown column keys\nare rejected. Column labels default to the first field's label and use the usual\nlocale resolution. A cell retains field visibility, help, requiredness, custom\nconditions and existing edit/derived-field rules. Record creation still binds\nthe selected parent, deletion preserves the normal section cleanup rules, and\n`inherit_from_graph` tables remain source-linked and read-only. The shared table\nwrapper owns horizontal scrolling at narrow widths. This does not promote the\ncomponent or this declaration to generated A2UI.\n\nAn authored graph hierarchy with `max_parents: 1` may opt into\n`parent_control: header`. The existing single-parent selector then sits beside\nthe selected record's form title, rather than above the whole inspector. It\nstill updates the same relation edge, rejects cycles, retains the source-record\nnavigation and shows the actual parent in read-only mode. Omission preserves\nthe prior inspector presentation; neither view creates an extra parent field.\n\n`diagram_workspace.diagram.detail_rows` groups declared read-only fields into\nresponsive fact cards. `chip_fields` selects string-list fields rendered as tags;\n`detail_hint_fields` supplies the populated field labels for the details action.\n`tags` maps declared enum fields to labels and finite semantic tones. These are\npresentation declarations, not new edit rights or storage. Diagram details cover\nonly the content pane; the navigator remains available. Leaving an edited diagram\nstill requires successful serialization through the existing save barrier.\n\n`diagram_workspace.diagram.label_source` can read a declared label from another\nsection bound to the same record collection. The optional `inspector` keeps a\ncontext editor alongside the BPMN canvas: `process_sections` edit the selected\nprocess; `nodes` binds `source`, `process_field`, `element_field`, `label_field`\nand same-collection `sections`. Optional `related` groups use a process reference\nand an optional `node_field`; `advanced: true` starts the group collapsed.\nReferences must be declared `record_select` fields targeting the corresponding\ncollection. Clicking an element resolves its exact ID within the selected\nprocess only; absent or duplicate bindings do not guess a record. Existing field\nedit permissions and the atomic artifact save barrier remain authoritative.\nThis is contextual navigation, not automatic synchronization of BPMN structure\nand business facts; authors must explain how structural changes are reconciled.\n\nFor an exact component contract and on-demand local type declarations, use the\nauthoring inspector from the repository root:\n\n```sh\nnode .agents/skills/design-bundle-creator/scripts/inspect-panel-component.mjs . navigation_workspace --type ComponentNode.navigation_map.edges\n```\n\nUse the [component extension contract](a2ui-component-catalog-contract.md) when\nadding a component: catalog, validation, renderer, styles, edit boundaries,\ntests and authoring guidance must agree. Trusted runtime additions are possible;\nunknown component names in a manifest are rejected.\n\nAcceptance of a component name alone does not establish rendering fidelity,\neditable lifecycle support, or compatibility with every host; those require\nthe component's binding contract and actual runtime verification.\n\nPredefined DSL and A2UI-derived panels share this library, but generated panels\nmay use only the subset with an implemented generation/edit-authority contract.\nAn authored workspace is not automatically promoted into that subset.\nSupported generated results can be deterministically retained as DSL; unsupported\ncapabilities must fail explicitly, never disappear during conversion. This is\nnot an arbitrary bidirectional A2UI protocol converter.\n\n`question_list` is the standard controlled question interaction. Each source\nrecord uses `prompt`, optional `note`, `kind` (`text | single | multiple`),\noptional `choices[]` (`value`, `label`, `recommended`), `answer`, and optional\n`detail`. Text answers render as one multiline input; an existing text-question\n`detail` remains visible as read-only context rather than becoming a second\nanswer box. Single/multiple answers use accessible choice rows and may edit\n`detail`. Existing read-only context and choice supplements use the same\nlocalized label (without the optional-input suffix in reading mode). Cards\nwith a non-empty `answer` collapse to a readable result and can\nbe reopened for editing. The component writes only the fields exposed by that\ninteraction back to the owning record. It does not invent approval state, and an\nempty answer remains unanswered even when `detail` contains context. Native\nproviders may explicitly extend answer-state semantics for attachments, and\nmay add rounds or rejection around this base contract without making those\nextensions mandatory for other Kits.\n\nAuthored `question_list`, `question_rounds`, and `question_workspace` may declare\n`card_groups` with a unique `id`, `title`, and ordered `question_ids`. Members\nmust be contiguous in the existing record order and, for round workspaces, stay\nwithin one round. Invalid groups fall back to ordinary cards with a diagnostic;\ngrouping never reorders canonical records. Generated-origin Panels reject this\nauthored extension.\n\nEach group may declare a `presentation` object containing only optional boolean\n`always_expanded`, `show_detail`, and `show_attachments` properties. These select\nshared component behavior, not Bundle-specific styling. Omission preserves the\nusual collapse, detail, and attachment controls. Hiding a control preserves its\ncanonical data; keeping a card expanded does not grant editing permission.\nRead-only, disabled, protected, historical and rejection guards still apply.\n\n`question_workspace` composes the same question cards with the standard\n`panel_workspace` navigation shell. It groups records by optional numeric\n`round`, shows answer progress, and keeps only the selected group in the main\npane; records without a round form one current group. Its optional\n`description` is rendered through the shared sticky workspace Tip Bar above\nthe main content, never squeezed into the navigation sidebar. `question_rounds` is the\nbackward-compatible alias for this workspace behavior. Optional\n`multimodal_answer[]` entries use the Web App-compatible local reference shape\n(`type`, `file_md5`, `filename`, `mime_type`, `size_bytes`, `artifact_file`).\nThe client keeps pending bytes in a reserved browser-only transport, strips it\nbefore schema validation, and atomically saves only files still referenced by\ncanonical state. The transport is framework state, never a Bundle field.\n\nAuthored `question_workspace` / `question_rounds` nodes may explicitly set\n`question_policy.allow_choice_actions: true`. Expanded editable dynamic single\ncards offer “Switch to multiple choice”; multiple cards offer “Select all” /\n“Deselect all”. Omission or `false` preserves the existing controls. The shared\nruntime owns these actions and their localized styling, not Bundle CSS or an\nauthor-supplied `renderActions` callback. Switching changes only `kind` to\n`multiple`, preserving the exact answer bytes and keeping the editor open.\nSelect-all writes choice values in declared order through the existing\ncomma-separated `answer` contract; deselect-all writes an empty answer. Neither\naction changes detail, attachments, identity, choices or round. Records declared\nin `first_round_ids` are the fixed first-round configuration and do not receive\nthese actions; `protected_ids` still controls rejection only. Read-only,\ndisabled, rejected and read-only historical cards cannot invoke the actions.\nGenerated-origin/A2UI auto Panels reject this configuration, even when `false`;\ntheir existing answer/detail-only write authority and protected `kind` remain\nunchanged. Converting a generated view into an authored reusable panel does not\nsilently grant this capability: the author must opt in under the static contract.\n\n`panel_workspace` is the reusable panel-internal left navigation + main content\nlayout. It standardizes containment, scroll ownership and narrow-panel fallback;\nit does not define domain records or selection semantics. Use it rather than\ncopying a Kit-specific two-column shell.\n\nThe shared runtime `PanelWorkspaceNavigation` accepts optional per-item\n`description`, `supporting`, and `statusLabel` display slots alongside the\nlabel/current row. These are supplied display text, not canonical fields or\nnew DSL expressions. Omitted slots render no empty rows. The `meta` fallback\nremains supported. A marker requires both explicit `statusIndicator: true`\nand an existing `status`; a label-only item never gains an inferred status dot.\nFlat record navigation, question rounds, and future workspace consumers share\nthe same base navigation typography, spacing and selected appearance. Bundle\nCSS is not required. Hierarchical trees retain their separate structure.\nQuestion progress excludes rejected items from answered/completion checks,\nwhile retaining all group records in the displayed total and preserving fixed\nquestion grouping, stable IDs, selection and canonical answers. The original\nWeb App question panel used body round sections, not this sidebar; the shared\nsidebar is an enhanced structure using the original public navigation style,\nnot a claim of one-to-one restoration of a nonexistent original sidebar.\n\n`doc_lifecycle_studio` binds `objects`/`axes`/`actions` sections (validation\nfails loud when one is missing) and renders the fact table (actions × state\naxes, per-cell effects) plus process/derivation/ledger projections derived at\nrender time; unavailable views render disabled with a reason, never hidden.\n`rowview_workbench` renders the residue envelope (below) and requires a\n`source` declaring the add section it owns — the details-envelope schema\ncheck and the renderer are both scoped to that section; a workbench without\n`source` is rejected at compile time.\n\nIn editable mode `bpmn_canvas` edits bidirectionally: each process record's\n`name` and `steps` array (step name, `kind` task/gateway/event, order, add,\nremove) round-trip through the panel Save like any field edit.\n"
|
|
2322
2322
|
}
|
|
@@ -2819,8 +2819,8 @@
|
|
|
2819
2819
|
"sections": [
|
|
2820
2820
|
{
|
|
2821
2821
|
"file": "docs/dsl-spec.md",
|
|
2822
|
-
"line":
|
|
2823
|
-
"endLine":
|
|
2822
|
+
"line": 958,
|
|
2823
|
+
"endLine": 1169,
|
|
2824
2824
|
"heading": "`component` (trusted, extensible library)",
|
|
2825
2825
|
"content": "### `component` (trusted, extensible library)\n\nThe authoritative vocabulary is [`PANEL_COMPONENT_CATALOG`](../packages/core/src/panel-component-catalog.ts).\n`COMPONENT_KINDS`, workspace ownership, source bindings and the generated-panel\nsubset are derived from that one registry; this document is not a second\nvalidation whitelist. Bundle data cannot register executable components.\n\nThe shared library includes basic layouts and controls, question workspaces,\nrecord navigation/editing, diagrams, canvases, artifact readers and previews.\nFull-height workspace components preserve scroll and navigation ownership:\n`record_board`, `document_workspace`, `artifact_workspace`, `diagram_workspace`,\n`canvas_workspace`, `preview_workspace` and `navigation_workspace` expose their\nbehavior through explicit data bindings rather than Kit names. These are reusable\ncapabilities, not a guarantee that every record schema fits every workspace.\n\n`record_board.board.detail_sources` can embed exactly one `record_workspace`\nunder the selected card. Each `{section, reference}` binding declares an unordered\ndirect record collection and a readonly `record_select` back to the board's\nparent section. The child workspace sources must belong to those bindings.\nOwner and child storage paths cannot alias or overlap. The renderer filters\nchildren by the selected parent, binds new records to it, and merges hidden\nsibling records back into canonical updates. It refuses sibling-id replacement,\nreparenting and writes outside these collections. This is a view projection,\nnot a second stored copy; it does not support independently ordered child maps,\nnested `fields_path` records or artifact staging in this first composition slice.\nOrdinary `detail_sections` retain their existing same-record nested-form meaning.\n\n`record_board` uses full-width cards and a workspace-covering overview. Optional\n`board.group` binds a real grouping field. When omitted, the sidebar lists records\ndirectly, cards have no artificial group heading, and the overview connects the\nroot directly to records. Do not bind long summaries merely to satisfy grouping;\nthis projection never adds a grouping field to canonical records.\nSidebar selection scrolls to a card; it does not start editing. Description and\nbadge drafts have explicit Save/Cancel, while rejected records remain inspectable\nwithout granting edit access. Optional `board.id_field` binds a declared visible,\nreadonly `text` field and displays its existing string beside the card title and\nat the top of cover details. Inline details retain the same card header. It does\nnot add an ID editor, generate a fallback ID or write state; omission retains the\nexisting title-only presentation. `board.detail_fields` restricts the parent fields\nshown in the detail fold, and `details_title` localizes its heading. Optional nested\ndimensions can be added or removed without replacing unrelated record fields.\n`board.detail_fields_mode: fixed` instead shows every declared nested input and\nremoves dimension-level add/delete controls; collection item add/delete still\nuses its usual editor. Fields remain schema-optional, including empty inputs.\nViewing does not insert missing strings/maps. Omitted/`on_demand` retains the\nexisting optional-dimension behavior. This option grants no new write authority.\n\n`record_workspace.workspace_view: switch` puts the first child canvas over the\nwhole workspace. The edge action opens it, and the return action or a node's\ndetails action returns to the selected record. It does not add form/canvas tabs\nto the sidebar. Covered content stays mounted and inert to preserve selection,\ndrafts and the graph viewport without allowing hidden controls to receive input.\n\n`record_related_editor.record_table` is an authored-only table presentation of\nthe same child collection, not a conversion to a `rows` array. Its finite\n`columns: [{fields: [field_key, ...], label?: string}]` groups existing field\neditors into cells. Every non-hidden field declared for that child section must\nappear exactly once; hidden/foreign/duplicate bindings and unknown column keys\nare rejected. Column labels default to the first field's label and use the usual\nlocale resolution. A cell retains field visibility, help, requiredness, custom\nconditions and existing edit/derived-field rules. Record creation still binds\nthe selected parent, deletion preserves the normal section cleanup rules, and\n`inherit_from_graph` tables remain source-linked and read-only. The shared table\nwrapper owns horizontal scrolling at narrow widths. This does not promote the\ncomponent or this declaration to generated A2UI.\n\nAn authored graph hierarchy with `max_parents: 1` may opt into\n`parent_control: header`. The existing single-parent selector then sits beside\nthe selected record's form title, rather than above the whole inspector. It\nstill updates the same relation edge, rejects cycles, retains the source-record\nnavigation and shows the actual parent in read-only mode. Omission preserves\nthe prior inspector presentation; neither view creates an extra parent field.\n\n`diagram_workspace.diagram.detail_rows` groups declared read-only fields into\nresponsive fact cards. `chip_fields` selects string-list fields rendered as tags;\n`detail_hint_fields` supplies the populated field labels for the details action.\n`tags` maps declared enum fields to labels and finite semantic tones. These are\npresentation declarations, not new edit rights or storage. Diagram details cover\nonly the content pane; the navigator remains available. Leaving an edited diagram\nstill requires successful serialization through the existing save barrier.\n\n`diagram_workspace.diagram.label_source` can read a declared label from another\nsection bound to the same record collection. The optional `inspector` keeps a\ncontext editor alongside the BPMN canvas: `process_sections` edit the selected\nprocess; `nodes` binds `source`, `process_field`, `element_field`, `label_field`\nand same-collection `sections`. Optional `related` groups use a process reference\nand an optional `node_field`; `advanced: true` starts the group collapsed.\nReferences must be declared `record_select` fields targeting the corresponding\ncollection. Clicking an element resolves its exact ID within the selected\nprocess only; absent or duplicate bindings do not guess a record. Existing field\nedit permissions and the atomic artifact save barrier remain authoritative.\nThis is contextual navigation, not automatic synchronization of BPMN structure\nand business facts; authors must explain how structural changes are reconciled.\n\nFor an exact component contract and on-demand local type declarations, use the\nauthoring inspector from the repository root:\n\n```sh\nnode .agents/skills/design-bundle-creator/scripts/inspect-panel-component.mjs . navigation_workspace --type ComponentNode.navigation_map.edges\n```\n\nUse the [component extension contract](a2ui-component-catalog-contract.md) when\nadding a component: catalog, validation, renderer, styles, edit boundaries,\ntests and authoring guidance must agree. Trusted runtime additions are possible;\nunknown component names in a manifest are rejected.\n\nAcceptance of a component name alone does not establish rendering fidelity,\neditable lifecycle support, or compatibility with every host; those require\nthe component's binding contract and actual runtime verification.\n\nPredefined DSL and A2UI-derived panels share this library, but generated panels\nmay use only the subset with an implemented generation/edit-authority contract.\nAn authored workspace is not automatically promoted into that subset.\nSupported generated results can be deterministically retained as DSL; unsupported\ncapabilities must fail explicitly, never disappear during conversion. This is\nnot an arbitrary bidirectional A2UI protocol converter.\n\n`question_list` is the standard controlled question interaction. Each source\nrecord uses `prompt`, optional `note`, `kind` (`text | single | multiple`),\noptional `choices[]` (`value`, `label`, `recommended`), `answer`, and optional\n`detail`. Text answers render as one multiline input; an existing text-question\n`detail` remains visible as read-only context rather than becoming a second\nanswer box. Single/multiple answers use accessible choice rows and may edit\n`detail`. Existing read-only context and choice supplements use the same\nlocalized label (without the optional-input suffix in reading mode). Cards\nwith a non-empty `answer` collapse to a readable result and can\nbe reopened for editing. The component writes only the fields exposed by that\ninteraction back to the owning record. It does not invent approval state, and an\nempty answer remains unanswered even when `detail` contains context. Native\nproviders may explicitly extend answer-state semantics for attachments, and\nmay add rounds or rejection around this base contract without making those\nextensions mandatory for other Kits.\n\nAuthored `question_list`, `question_rounds`, and `question_workspace` may declare\n`card_groups` with a unique `id`, `title`, and ordered `question_ids`. Members\nmust be contiguous in the existing record order and, for round workspaces, stay\nwithin one round. Invalid groups fall back to ordinary cards with a diagnostic;\ngrouping never reorders canonical records. Generated-origin Panels reject this\nauthored extension.\n\nEach group may declare a `presentation` object containing only optional boolean\n`always_expanded`, `show_detail`, and `show_attachments` properties. These select\nshared component behavior, not Bundle-specific styling. Omission preserves the\nusual collapse, detail, and attachment controls. Hiding a control preserves its\ncanonical data; keeping a card expanded does not grant editing permission.\nRead-only, disabled, protected, historical and rejection guards still apply.\n\n`question_workspace` composes the same question cards with the standard\n`panel_workspace` navigation shell. It groups records by optional numeric\n`round`, shows answer progress, and keeps only the selected group in the main\npane; records without a round form one current group. Its optional\n`description` is rendered through the shared sticky workspace Tip Bar above\nthe main content, never squeezed into the navigation sidebar. `question_rounds` is the\nbackward-compatible alias for this workspace behavior. Optional\n`multimodal_answer[]` entries use the Web App-compatible local reference shape\n(`type`, `file_md5`, `filename`, `mime_type`, `size_bytes`, `artifact_file`).\nThe client keeps pending bytes in a reserved browser-only transport, strips it\nbefore schema validation, and atomically saves only files still referenced by\ncanonical state. The transport is framework state, never a Bundle field.\n\nAuthored `question_workspace` / `question_rounds` nodes may explicitly set\n`question_policy.allow_choice_actions: true`. Expanded editable dynamic single\ncards offer “Switch to multiple choice”; multiple cards offer “Select all” /\n“Deselect all”. Omission or `false` preserves the existing controls. The shared\nruntime owns these actions and their localized styling, not Bundle CSS or an\nauthor-supplied `renderActions` callback. Switching changes only `kind` to\n`multiple`, preserving the exact answer bytes and keeping the editor open.\nSelect-all writes choice values in declared order through the existing\ncomma-separated `answer` contract; deselect-all writes an empty answer. Neither\naction changes detail, attachments, identity, choices or round. Records declared\nin `first_round_ids` are the fixed first-round configuration and do not receive\nthese actions; `protected_ids` still controls rejection only. Read-only,\ndisabled, rejected and read-only historical cards cannot invoke the actions.\nGenerated-origin/A2UI auto Panels reject this configuration, even when `false`;\ntheir existing answer/detail-only write authority and protected `kind` remain\nunchanged. Converting a generated view into an authored reusable panel does not\nsilently grant this capability: the author must opt in under the static contract.\n\n`panel_workspace` is the reusable panel-internal left navigation + main content\nlayout. It standardizes containment, scroll ownership and narrow-panel fallback;\nit does not define domain records or selection semantics. Use it rather than\ncopying a Kit-specific two-column shell.\n\nThe shared runtime `PanelWorkspaceNavigation` accepts optional per-item\n`description`, `supporting`, and `statusLabel` display slots alongside the\nlabel/current row. These are supplied display text, not canonical fields or\nnew DSL expressions. Omitted slots render no empty rows. The `meta` fallback\nremains supported. A marker requires both explicit `statusIndicator: true`\nand an existing `status`; a label-only item never gains an inferred status dot.\nFlat record navigation, question rounds, and future workspace consumers share\nthe same base navigation typography, spacing and selected appearance. Bundle\nCSS is not required. Hierarchical trees retain their separate structure.\nQuestion progress excludes rejected items from answered/completion checks,\nwhile retaining all group records in the displayed total and preserving fixed\nquestion grouping, stable IDs, selection and canonical answers. The original\nWeb App question panel used body round sections, not this sidebar; the shared\nsidebar is an enhanced structure using the original public navigation style,\nnot a claim of one-to-one restoration of a nonexistent original sidebar.\n\n`doc_lifecycle_studio` binds `objects`/`axes`/`actions` sections (validation\nfails loud when one is missing) and renders the fact table (actions × state\naxes, per-cell effects) plus process/derivation/ledger projections derived at\nrender time; unavailable views render disabled with a reason, never hidden.\n`rowview_workbench` renders the residue envelope (below) and requires a\n`source` declaring the add section it owns — the details-envelope schema\ncheck and the renderer are both scoped to that section; a workbench without\n`source` is rejected at compile time.\n\nIn editable mode `bpmn_canvas` edits bidirectionally: each process record's\n`name` and `steps` array (step name, `kind` task/gateway/event, order, add,\nremove) round-trip through the panel Save like any field edit.\n"
|
|
2826
2826
|
}
|
|
@@ -2976,8 +2976,8 @@
|
|
|
2976
2976
|
"sections": [
|
|
2977
2977
|
{
|
|
2978
2978
|
"file": "docs/dsl-spec.md",
|
|
2979
|
-
"line":
|
|
2980
|
-
"endLine":
|
|
2979
|
+
"line": 958,
|
|
2980
|
+
"endLine": 1169,
|
|
2981
2981
|
"heading": "`component` (trusted, extensible library)",
|
|
2982
2982
|
"content": "### `component` (trusted, extensible library)\n\nThe authoritative vocabulary is [`PANEL_COMPONENT_CATALOG`](../packages/core/src/panel-component-catalog.ts).\n`COMPONENT_KINDS`, workspace ownership, source bindings and the generated-panel\nsubset are derived from that one registry; this document is not a second\nvalidation whitelist. Bundle data cannot register executable components.\n\nThe shared library includes basic layouts and controls, question workspaces,\nrecord navigation/editing, diagrams, canvases, artifact readers and previews.\nFull-height workspace components preserve scroll and navigation ownership:\n`record_board`, `document_workspace`, `artifact_workspace`, `diagram_workspace`,\n`canvas_workspace`, `preview_workspace` and `navigation_workspace` expose their\nbehavior through explicit data bindings rather than Kit names. These are reusable\ncapabilities, not a guarantee that every record schema fits every workspace.\n\n`record_board.board.detail_sources` can embed exactly one `record_workspace`\nunder the selected card. Each `{section, reference}` binding declares an unordered\ndirect record collection and a readonly `record_select` back to the board's\nparent section. The child workspace sources must belong to those bindings.\nOwner and child storage paths cannot alias or overlap. The renderer filters\nchildren by the selected parent, binds new records to it, and merges hidden\nsibling records back into canonical updates. It refuses sibling-id replacement,\nreparenting and writes outside these collections. This is a view projection,\nnot a second stored copy; it does not support independently ordered child maps,\nnested `fields_path` records or artifact staging in this first composition slice.\nOrdinary `detail_sections` retain their existing same-record nested-form meaning.\n\n`record_board` uses full-width cards and a workspace-covering overview. Optional\n`board.group` binds a real grouping field. When omitted, the sidebar lists records\ndirectly, cards have no artificial group heading, and the overview connects the\nroot directly to records. Do not bind long summaries merely to satisfy grouping;\nthis projection never adds a grouping field to canonical records.\nSidebar selection scrolls to a card; it does not start editing. Description and\nbadge drafts have explicit Save/Cancel, while rejected records remain inspectable\nwithout granting edit access. Optional `board.id_field` binds a declared visible,\nreadonly `text` field and displays its existing string beside the card title and\nat the top of cover details. Inline details retain the same card header. It does\nnot add an ID editor, generate a fallback ID or write state; omission retains the\nexisting title-only presentation. `board.detail_fields` restricts the parent fields\nshown in the detail fold, and `details_title` localizes its heading. Optional nested\ndimensions can be added or removed without replacing unrelated record fields.\n`board.detail_fields_mode: fixed` instead shows every declared nested input and\nremoves dimension-level add/delete controls; collection item add/delete still\nuses its usual editor. Fields remain schema-optional, including empty inputs.\nViewing does not insert missing strings/maps. Omitted/`on_demand` retains the\nexisting optional-dimension behavior. This option grants no new write authority.\n\n`record_workspace.workspace_view: switch` puts the first child canvas over the\nwhole workspace. The edge action opens it, and the return action or a node's\ndetails action returns to the selected record. It does not add form/canvas tabs\nto the sidebar. Covered content stays mounted and inert to preserve selection,\ndrafts and the graph viewport without allowing hidden controls to receive input.\n\n`record_related_editor.record_table` is an authored-only table presentation of\nthe same child collection, not a conversion to a `rows` array. Its finite\n`columns: [{fields: [field_key, ...], label?: string}]` groups existing field\neditors into cells. Every non-hidden field declared for that child section must\nappear exactly once; hidden/foreign/duplicate bindings and unknown column keys\nare rejected. Column labels default to the first field's label and use the usual\nlocale resolution. A cell retains field visibility, help, requiredness, custom\nconditions and existing edit/derived-field rules. Record creation still binds\nthe selected parent, deletion preserves the normal section cleanup rules, and\n`inherit_from_graph` tables remain source-linked and read-only. The shared table\nwrapper owns horizontal scrolling at narrow widths. This does not promote the\ncomponent or this declaration to generated A2UI.\n\nAn authored graph hierarchy with `max_parents: 1` may opt into\n`parent_control: header`. The existing single-parent selector then sits beside\nthe selected record's form title, rather than above the whole inspector. It\nstill updates the same relation edge, rejects cycles, retains the source-record\nnavigation and shows the actual parent in read-only mode. Omission preserves\nthe prior inspector presentation; neither view creates an extra parent field.\n\n`diagram_workspace.diagram.detail_rows` groups declared read-only fields into\nresponsive fact cards. `chip_fields` selects string-list fields rendered as tags;\n`detail_hint_fields` supplies the populated field labels for the details action.\n`tags` maps declared enum fields to labels and finite semantic tones. These are\npresentation declarations, not new edit rights or storage. Diagram details cover\nonly the content pane; the navigator remains available. Leaving an edited diagram\nstill requires successful serialization through the existing save barrier.\n\n`diagram_workspace.diagram.label_source` can read a declared label from another\nsection bound to the same record collection. The optional `inspector` keeps a\ncontext editor alongside the BPMN canvas: `process_sections` edit the selected\nprocess; `nodes` binds `source`, `process_field`, `element_field`, `label_field`\nand same-collection `sections`. Optional `related` groups use a process reference\nand an optional `node_field`; `advanced: true` starts the group collapsed.\nReferences must be declared `record_select` fields targeting the corresponding\ncollection. Clicking an element resolves its exact ID within the selected\nprocess only; absent or duplicate bindings do not guess a record. Existing field\nedit permissions and the atomic artifact save barrier remain authoritative.\nThis is contextual navigation, not automatic synchronization of BPMN structure\nand business facts; authors must explain how structural changes are reconciled.\n\nFor an exact component contract and on-demand local type declarations, use the\nauthoring inspector from the repository root:\n\n```sh\nnode .agents/skills/design-bundle-creator/scripts/inspect-panel-component.mjs . navigation_workspace --type ComponentNode.navigation_map.edges\n```\n\nUse the [component extension contract](a2ui-component-catalog-contract.md) when\nadding a component: catalog, validation, renderer, styles, edit boundaries,\ntests and authoring guidance must agree. Trusted runtime additions are possible;\nunknown component names in a manifest are rejected.\n\nAcceptance of a component name alone does not establish rendering fidelity,\neditable lifecycle support, or compatibility with every host; those require\nthe component's binding contract and actual runtime verification.\n\nPredefined DSL and A2UI-derived panels share this library, but generated panels\nmay use only the subset with an implemented generation/edit-authority contract.\nAn authored workspace is not automatically promoted into that subset.\nSupported generated results can be deterministically retained as DSL; unsupported\ncapabilities must fail explicitly, never disappear during conversion. This is\nnot an arbitrary bidirectional A2UI protocol converter.\n\n`question_list` is the standard controlled question interaction. Each source\nrecord uses `prompt`, optional `note`, `kind` (`text | single | multiple`),\noptional `choices[]` (`value`, `label`, `recommended`), `answer`, and optional\n`detail`. Text answers render as one multiline input; an existing text-question\n`detail` remains visible as read-only context rather than becoming a second\nanswer box. Single/multiple answers use accessible choice rows and may edit\n`detail`. Existing read-only context and choice supplements use the same\nlocalized label (without the optional-input suffix in reading mode). Cards\nwith a non-empty `answer` collapse to a readable result and can\nbe reopened for editing. The component writes only the fields exposed by that\ninteraction back to the owning record. It does not invent approval state, and an\nempty answer remains unanswered even when `detail` contains context. Native\nproviders may explicitly extend answer-state semantics for attachments, and\nmay add rounds or rejection around this base contract without making those\nextensions mandatory for other Kits.\n\nAuthored `question_list`, `question_rounds`, and `question_workspace` may declare\n`card_groups` with a unique `id`, `title`, and ordered `question_ids`. Members\nmust be contiguous in the existing record order and, for round workspaces, stay\nwithin one round. Invalid groups fall back to ordinary cards with a diagnostic;\ngrouping never reorders canonical records. Generated-origin Panels reject this\nauthored extension.\n\nEach group may declare a `presentation` object containing only optional boolean\n`always_expanded`, `show_detail`, and `show_attachments` properties. These select\nshared component behavior, not Bundle-specific styling. Omission preserves the\nusual collapse, detail, and attachment controls. Hiding a control preserves its\ncanonical data; keeping a card expanded does not grant editing permission.\nRead-only, disabled, protected, historical and rejection guards still apply.\n\n`question_workspace` composes the same question cards with the standard\n`panel_workspace` navigation shell. It groups records by optional numeric\n`round`, shows answer progress, and keeps only the selected group in the main\npane; records without a round form one current group. Its optional\n`description` is rendered through the shared sticky workspace Tip Bar above\nthe main content, never squeezed into the navigation sidebar. `question_rounds` is the\nbackward-compatible alias for this workspace behavior. Optional\n`multimodal_answer[]` entries use the Web App-compatible local reference shape\n(`type`, `file_md5`, `filename`, `mime_type`, `size_bytes`, `artifact_file`).\nThe client keeps pending bytes in a reserved browser-only transport, strips it\nbefore schema validation, and atomically saves only files still referenced by\ncanonical state. The transport is framework state, never a Bundle field.\n\nAuthored `question_workspace` / `question_rounds` nodes may explicitly set\n`question_policy.allow_choice_actions: true`. Expanded editable dynamic single\ncards offer “Switch to multiple choice”; multiple cards offer “Select all” /\n“Deselect all”. Omission or `false` preserves the existing controls. The shared\nruntime owns these actions and their localized styling, not Bundle CSS or an\nauthor-supplied `renderActions` callback. Switching changes only `kind` to\n`multiple`, preserving the exact answer bytes and keeping the editor open.\nSelect-all writes choice values in declared order through the existing\ncomma-separated `answer` contract; deselect-all writes an empty answer. Neither\naction changes detail, attachments, identity, choices or round. Records declared\nin `first_round_ids` are the fixed first-round configuration and do not receive\nthese actions; `protected_ids` still controls rejection only. Read-only,\ndisabled, rejected and read-only historical cards cannot invoke the actions.\nGenerated-origin/A2UI auto Panels reject this configuration, even when `false`;\ntheir existing answer/detail-only write authority and protected `kind` remain\nunchanged. Converting a generated view into an authored reusable panel does not\nsilently grant this capability: the author must opt in under the static contract.\n\n`panel_workspace` is the reusable panel-internal left navigation + main content\nlayout. It standardizes containment, scroll ownership and narrow-panel fallback;\nit does not define domain records or selection semantics. Use it rather than\ncopying a Kit-specific two-column shell.\n\nThe shared runtime `PanelWorkspaceNavigation` accepts optional per-item\n`description`, `supporting`, and `statusLabel` display slots alongside the\nlabel/current row. These are supplied display text, not canonical fields or\nnew DSL expressions. Omitted slots render no empty rows. The `meta` fallback\nremains supported. A marker requires both explicit `statusIndicator: true`\nand an existing `status`; a label-only item never gains an inferred status dot.\nFlat record navigation, question rounds, and future workspace consumers share\nthe same base navigation typography, spacing and selected appearance. Bundle\nCSS is not required. Hierarchical trees retain their separate structure.\nQuestion progress excludes rejected items from answered/completion checks,\nwhile retaining all group records in the displayed total and preserving fixed\nquestion grouping, stable IDs, selection and canonical answers. The original\nWeb App question panel used body round sections, not this sidebar; the shared\nsidebar is an enhanced structure using the original public navigation style,\nnot a claim of one-to-one restoration of a nonexistent original sidebar.\n\n`doc_lifecycle_studio` binds `objects`/`axes`/`actions` sections (validation\nfails loud when one is missing) and renders the fact table (actions × state\naxes, per-cell effects) plus process/derivation/ledger projections derived at\nrender time; unavailable views render disabled with a reason, never hidden.\n`rowview_workbench` renders the residue envelope (below) and requires a\n`source` declaring the add section it owns — the details-envelope schema\ncheck and the renderer are both scoped to that section; a workbench without\n`source` is rejected at compile time.\n\nIn editable mode `bpmn_canvas` edits bidirectionally: each process record's\n`name` and `steps` array (step name, `kind` task/gateway/event, order, add,\nremove) round-trip through the panel Save like any field edit.\n"
|
|
2983
2983
|
}
|
|
@@ -3196,8 +3196,8 @@
|
|
|
3196
3196
|
"sections": [
|
|
3197
3197
|
{
|
|
3198
3198
|
"file": "docs/dsl-spec.md",
|
|
3199
|
-
"line":
|
|
3200
|
-
"endLine":
|
|
3199
|
+
"line": 1170,
|
|
3200
|
+
"endLine": 1219,
|
|
3201
3201
|
"heading": "`execution_log` — embedded Host logs (authored Panels)",
|
|
3202
3202
|
"content": "### `execution_log` — embedded Host logs (authored Panels)\n\n`execution_log` embeds the shared rolling Host log in an authored layout. It is\nread-only runtime observation: it does not create executions, edit Design Files,\nor grant access to arbitrary transcripts. Discover it with\n`design_list_panel_components` before authoring. Generated Panels cannot add it.\n\n```yaml\nui:\n component: stack\n id: research-layout\n children:\n - component: execution_log\n id: producer-progress\n title: Execution progress\n log: {scope: producer, max_entries: 200}\n - component: execution_log\n id: selected-artifact-progress\n title: Artifact progress\n log:\n scope: artifact\n artifact_id_path: selected_artifact_id\n artifact_kind: research_direction\n artifact_file_path: selected_artifact_file\n max_entries: 200\n```\n\n`scope: producer` resolves the current Bundle's root native Producer.\n`scope: artifact` requires exactly one `artifact_id` (literal) or\n`artifact_id_path` (safe dotted path in this Panel's canonical data). Optional\n`artifact_kind` and `artifact_file_path` disambiguate the Host's existing\nassociation; these are selectors, not authorization. Canonical paths are read\nonly, and this component does not infer a selected record from a neighboring\nworkspace. Do not persist a transient selection merely to connect logs.\n\nOnly observations belonging to the owning Bundle are eligible. Native run ids,\ninvocation ids, transcript paths and credentials cannot be authored in `log`.\nThe Host still verifies every read. Main-mode artifact logs require an explicit\nHost focus association; a main conversation must never substitute for an\nunavailable Producer or artifact log. Missing associations/read capability show\nan unavailable message. Support for exact artifact targets depends on the Host\nadapter; a rendered log alone does not prove a native execution succeeded.\n\n`max_entries` is an integer from 1 to 1000 (default 200). The log follows new rows\nwhile the reader remains at the bottom, preserves manual scrolling, expands on\nactive execution and folds when it finishes. A run/target change clears old rows\nand ignores late responses from the previous target. Temporary read failures\nretain the last readable rows and active logs retry through the shared polling\nscheduler. All these surfaces use the same `ExecutionRollingLog` client component.\n"
|
|
3203
3203
|
}
|
|
@@ -3313,8 +3313,8 @@
|
|
|
3313
3313
|
"sections": [
|
|
3314
3314
|
{
|
|
3315
3315
|
"file": "docs/dsl-spec.md",
|
|
3316
|
-
"line":
|
|
3317
|
-
"endLine":
|
|
3316
|
+
"line": 958,
|
|
3317
|
+
"endLine": 1169,
|
|
3318
3318
|
"heading": "`component` (trusted, extensible library)",
|
|
3319
3319
|
"content": "### `component` (trusted, extensible library)\n\nThe authoritative vocabulary is [`PANEL_COMPONENT_CATALOG`](../packages/core/src/panel-component-catalog.ts).\n`COMPONENT_KINDS`, workspace ownership, source bindings and the generated-panel\nsubset are derived from that one registry; this document is not a second\nvalidation whitelist. Bundle data cannot register executable components.\n\nThe shared library includes basic layouts and controls, question workspaces,\nrecord navigation/editing, diagrams, canvases, artifact readers and previews.\nFull-height workspace components preserve scroll and navigation ownership:\n`record_board`, `document_workspace`, `artifact_workspace`, `diagram_workspace`,\n`canvas_workspace`, `preview_workspace` and `navigation_workspace` expose their\nbehavior through explicit data bindings rather than Kit names. These are reusable\ncapabilities, not a guarantee that every record schema fits every workspace.\n\n`record_board.board.detail_sources` can embed exactly one `record_workspace`\nunder the selected card. Each `{section, reference}` binding declares an unordered\ndirect record collection and a readonly `record_select` back to the board's\nparent section. The child workspace sources must belong to those bindings.\nOwner and child storage paths cannot alias or overlap. The renderer filters\nchildren by the selected parent, binds new records to it, and merges hidden\nsibling records back into canonical updates. It refuses sibling-id replacement,\nreparenting and writes outside these collections. This is a view projection,\nnot a second stored copy; it does not support independently ordered child maps,\nnested `fields_path` records or artifact staging in this first composition slice.\nOrdinary `detail_sections` retain their existing same-record nested-form meaning.\n\n`record_board` uses full-width cards and a workspace-covering overview. Optional\n`board.group` binds a real grouping field. When omitted, the sidebar lists records\ndirectly, cards have no artificial group heading, and the overview connects the\nroot directly to records. Do not bind long summaries merely to satisfy grouping;\nthis projection never adds a grouping field to canonical records.\nSidebar selection scrolls to a card; it does not start editing. Description and\nbadge drafts have explicit Save/Cancel, while rejected records remain inspectable\nwithout granting edit access. Optional `board.id_field` binds a declared visible,\nreadonly `text` field and displays its existing string beside the card title and\nat the top of cover details. Inline details retain the same card header. It does\nnot add an ID editor, generate a fallback ID or write state; omission retains the\nexisting title-only presentation. `board.detail_fields` restricts the parent fields\nshown in the detail fold, and `details_title` localizes its heading. Optional nested\ndimensions can be added or removed without replacing unrelated record fields.\n`board.detail_fields_mode: fixed` instead shows every declared nested input and\nremoves dimension-level add/delete controls; collection item add/delete still\nuses its usual editor. Fields remain schema-optional, including empty inputs.\nViewing does not insert missing strings/maps. Omitted/`on_demand` retains the\nexisting optional-dimension behavior. This option grants no new write authority.\n\n`record_workspace.workspace_view: switch` puts the first child canvas over the\nwhole workspace. The edge action opens it, and the return action or a node's\ndetails action returns to the selected record. It does not add form/canvas tabs\nto the sidebar. Covered content stays mounted and inert to preserve selection,\ndrafts and the graph viewport without allowing hidden controls to receive input.\n\n`record_related_editor.record_table` is an authored-only table presentation of\nthe same child collection, not a conversion to a `rows` array. Its finite\n`columns: [{fields: [field_key, ...], label?: string}]` groups existing field\neditors into cells. Every non-hidden field declared for that child section must\nappear exactly once; hidden/foreign/duplicate bindings and unknown column keys\nare rejected. Column labels default to the first field's label and use the usual\nlocale resolution. A cell retains field visibility, help, requiredness, custom\nconditions and existing edit/derived-field rules. Record creation still binds\nthe selected parent, deletion preserves the normal section cleanup rules, and\n`inherit_from_graph` tables remain source-linked and read-only. The shared table\nwrapper owns horizontal scrolling at narrow widths. This does not promote the\ncomponent or this declaration to generated A2UI.\n\nAn authored graph hierarchy with `max_parents: 1` may opt into\n`parent_control: header`. The existing single-parent selector then sits beside\nthe selected record's form title, rather than above the whole inspector. It\nstill updates the same relation edge, rejects cycles, retains the source-record\nnavigation and shows the actual parent in read-only mode. Omission preserves\nthe prior inspector presentation; neither view creates an extra parent field.\n\n`diagram_workspace.diagram.detail_rows` groups declared read-only fields into\nresponsive fact cards. `chip_fields` selects string-list fields rendered as tags;\n`detail_hint_fields` supplies the populated field labels for the details action.\n`tags` maps declared enum fields to labels and finite semantic tones. These are\npresentation declarations, not new edit rights or storage. Diagram details cover\nonly the content pane; the navigator remains available. Leaving an edited diagram\nstill requires successful serialization through the existing save barrier.\n\n`diagram_workspace.diagram.label_source` can read a declared label from another\nsection bound to the same record collection. The optional `inspector` keeps a\ncontext editor alongside the BPMN canvas: `process_sections` edit the selected\nprocess; `nodes` binds `source`, `process_field`, `element_field`, `label_field`\nand same-collection `sections`. Optional `related` groups use a process reference\nand an optional `node_field`; `advanced: true` starts the group collapsed.\nReferences must be declared `record_select` fields targeting the corresponding\ncollection. Clicking an element resolves its exact ID within the selected\nprocess only; absent or duplicate bindings do not guess a record. Existing field\nedit permissions and the atomic artifact save barrier remain authoritative.\nThis is contextual navigation, not automatic synchronization of BPMN structure\nand business facts; authors must explain how structural changes are reconciled.\n\nFor an exact component contract and on-demand local type declarations, use the\nauthoring inspector from the repository root:\n\n```sh\nnode .agents/skills/design-bundle-creator/scripts/inspect-panel-component.mjs . navigation_workspace --type ComponentNode.navigation_map.edges\n```\n\nUse the [component extension contract](a2ui-component-catalog-contract.md) when\nadding a component: catalog, validation, renderer, styles, edit boundaries,\ntests and authoring guidance must agree. Trusted runtime additions are possible;\nunknown component names in a manifest are rejected.\n\nAcceptance of a component name alone does not establish rendering fidelity,\neditable lifecycle support, or compatibility with every host; those require\nthe component's binding contract and actual runtime verification.\n\nPredefined DSL and A2UI-derived panels share this library, but generated panels\nmay use only the subset with an implemented generation/edit-authority contract.\nAn authored workspace is not automatically promoted into that subset.\nSupported generated results can be deterministically retained as DSL; unsupported\ncapabilities must fail explicitly, never disappear during conversion. This is\nnot an arbitrary bidirectional A2UI protocol converter.\n\n`question_list` is the standard controlled question interaction. Each source\nrecord uses `prompt`, optional `note`, `kind` (`text | single | multiple`),\noptional `choices[]` (`value`, `label`, `recommended`), `answer`, and optional\n`detail`. Text answers render as one multiline input; an existing text-question\n`detail` remains visible as read-only context rather than becoming a second\nanswer box. Single/multiple answers use accessible choice rows and may edit\n`detail`. Existing read-only context and choice supplements use the same\nlocalized label (without the optional-input suffix in reading mode). Cards\nwith a non-empty `answer` collapse to a readable result and can\nbe reopened for editing. The component writes only the fields exposed by that\ninteraction back to the owning record. It does not invent approval state, and an\nempty answer remains unanswered even when `detail` contains context. Native\nproviders may explicitly extend answer-state semantics for attachments, and\nmay add rounds or rejection around this base contract without making those\nextensions mandatory for other Kits.\n\nAuthored `question_list`, `question_rounds`, and `question_workspace` may declare\n`card_groups` with a unique `id`, `title`, and ordered `question_ids`. Members\nmust be contiguous in the existing record order and, for round workspaces, stay\nwithin one round. Invalid groups fall back to ordinary cards with a diagnostic;\ngrouping never reorders canonical records. Generated-origin Panels reject this\nauthored extension.\n\nEach group may declare a `presentation` object containing only optional boolean\n`always_expanded`, `show_detail`, and `show_attachments` properties. These select\nshared component behavior, not Bundle-specific styling. Omission preserves the\nusual collapse, detail, and attachment controls. Hiding a control preserves its\ncanonical data; keeping a card expanded does not grant editing permission.\nRead-only, disabled, protected, historical and rejection guards still apply.\n\n`question_workspace` composes the same question cards with the standard\n`panel_workspace` navigation shell. It groups records by optional numeric\n`round`, shows answer progress, and keeps only the selected group in the main\npane; records without a round form one current group. Its optional\n`description` is rendered through the shared sticky workspace Tip Bar above\nthe main content, never squeezed into the navigation sidebar. `question_rounds` is the\nbackward-compatible alias for this workspace behavior. Optional\n`multimodal_answer[]` entries use the Web App-compatible local reference shape\n(`type`, `file_md5`, `filename`, `mime_type`, `size_bytes`, `artifact_file`).\nThe client keeps pending bytes in a reserved browser-only transport, strips it\nbefore schema validation, and atomically saves only files still referenced by\ncanonical state. The transport is framework state, never a Bundle field.\n\nAuthored `question_workspace` / `question_rounds` nodes may explicitly set\n`question_policy.allow_choice_actions: true`. Expanded editable dynamic single\ncards offer “Switch to multiple choice”; multiple cards offer “Select all” /\n“Deselect all”. Omission or `false` preserves the existing controls. The shared\nruntime owns these actions and their localized styling, not Bundle CSS or an\nauthor-supplied `renderActions` callback. Switching changes only `kind` to\n`multiple`, preserving the exact answer bytes and keeping the editor open.\nSelect-all writes choice values in declared order through the existing\ncomma-separated `answer` contract; deselect-all writes an empty answer. Neither\naction changes detail, attachments, identity, choices or round. Records declared\nin `first_round_ids` are the fixed first-round configuration and do not receive\nthese actions; `protected_ids` still controls rejection only. Read-only,\ndisabled, rejected and read-only historical cards cannot invoke the actions.\nGenerated-origin/A2UI auto Panels reject this configuration, even when `false`;\ntheir existing answer/detail-only write authority and protected `kind` remain\nunchanged. Converting a generated view into an authored reusable panel does not\nsilently grant this capability: the author must opt in under the static contract.\n\n`panel_workspace` is the reusable panel-internal left navigation + main content\nlayout. It standardizes containment, scroll ownership and narrow-panel fallback;\nit does not define domain records or selection semantics. Use it rather than\ncopying a Kit-specific two-column shell.\n\nThe shared runtime `PanelWorkspaceNavigation` accepts optional per-item\n`description`, `supporting`, and `statusLabel` display slots alongside the\nlabel/current row. These are supplied display text, not canonical fields or\nnew DSL expressions. Omitted slots render no empty rows. The `meta` fallback\nremains supported. A marker requires both explicit `statusIndicator: true`\nand an existing `status`; a label-only item never gains an inferred status dot.\nFlat record navigation, question rounds, and future workspace consumers share\nthe same base navigation typography, spacing and selected appearance. Bundle\nCSS is not required. Hierarchical trees retain their separate structure.\nQuestion progress excludes rejected items from answered/completion checks,\nwhile retaining all group records in the displayed total and preserving fixed\nquestion grouping, stable IDs, selection and canonical answers. The original\nWeb App question panel used body round sections, not this sidebar; the shared\nsidebar is an enhanced structure using the original public navigation style,\nnot a claim of one-to-one restoration of a nonexistent original sidebar.\n\n`doc_lifecycle_studio` binds `objects`/`axes`/`actions` sections (validation\nfails loud when one is missing) and renders the fact table (actions × state\naxes, per-cell effects) plus process/derivation/ledger projections derived at\nrender time; unavailable views render disabled with a reason, never hidden.\n`rowview_workbench` renders the residue envelope (below) and requires a\n`source` declaring the add section it owns — the details-envelope schema\ncheck and the renderer are both scoped to that section; a workbench without\n`source` is rejected at compile time.\n\nIn editable mode `bpmn_canvas` edits bidirectionally: each process record's\n`name` and `steps` array (step name, `kind` task/gateway/event, order, add,\nremove) round-trip through the panel Save like any field edit.\n"
|
|
3320
3320
|
}
|
|
@@ -3463,8 +3463,8 @@
|
|
|
3463
3463
|
"sections": [
|
|
3464
3464
|
{
|
|
3465
3465
|
"file": "docs/dsl-spec.md",
|
|
3466
|
-
"line":
|
|
3467
|
-
"endLine":
|
|
3466
|
+
"line": 958,
|
|
3467
|
+
"endLine": 1169,
|
|
3468
3468
|
"heading": "`component` (trusted, extensible library)",
|
|
3469
3469
|
"content": "### `component` (trusted, extensible library)\n\nThe authoritative vocabulary is [`PANEL_COMPONENT_CATALOG`](../packages/core/src/panel-component-catalog.ts).\n`COMPONENT_KINDS`, workspace ownership, source bindings and the generated-panel\nsubset are derived from that one registry; this document is not a second\nvalidation whitelist. Bundle data cannot register executable components.\n\nThe shared library includes basic layouts and controls, question workspaces,\nrecord navigation/editing, diagrams, canvases, artifact readers and previews.\nFull-height workspace components preserve scroll and navigation ownership:\n`record_board`, `document_workspace`, `artifact_workspace`, `diagram_workspace`,\n`canvas_workspace`, `preview_workspace` and `navigation_workspace` expose their\nbehavior through explicit data bindings rather than Kit names. These are reusable\ncapabilities, not a guarantee that every record schema fits every workspace.\n\n`record_board.board.detail_sources` can embed exactly one `record_workspace`\nunder the selected card. Each `{section, reference}` binding declares an unordered\ndirect record collection and a readonly `record_select` back to the board's\nparent section. The child workspace sources must belong to those bindings.\nOwner and child storage paths cannot alias or overlap. The renderer filters\nchildren by the selected parent, binds new records to it, and merges hidden\nsibling records back into canonical updates. It refuses sibling-id replacement,\nreparenting and writes outside these collections. This is a view projection,\nnot a second stored copy; it does not support independently ordered child maps,\nnested `fields_path` records or artifact staging in this first composition slice.\nOrdinary `detail_sections` retain their existing same-record nested-form meaning.\n\n`record_board` uses full-width cards and a workspace-covering overview. Optional\n`board.group` binds a real grouping field. When omitted, the sidebar lists records\ndirectly, cards have no artificial group heading, and the overview connects the\nroot directly to records. Do not bind long summaries merely to satisfy grouping;\nthis projection never adds a grouping field to canonical records.\nSidebar selection scrolls to a card; it does not start editing. Description and\nbadge drafts have explicit Save/Cancel, while rejected records remain inspectable\nwithout granting edit access. Optional `board.id_field` binds a declared visible,\nreadonly `text` field and displays its existing string beside the card title and\nat the top of cover details. Inline details retain the same card header. It does\nnot add an ID editor, generate a fallback ID or write state; omission retains the\nexisting title-only presentation. `board.detail_fields` restricts the parent fields\nshown in the detail fold, and `details_title` localizes its heading. Optional nested\ndimensions can be added or removed without replacing unrelated record fields.\n`board.detail_fields_mode: fixed` instead shows every declared nested input and\nremoves dimension-level add/delete controls; collection item add/delete still\nuses its usual editor. Fields remain schema-optional, including empty inputs.\nViewing does not insert missing strings/maps. Omitted/`on_demand` retains the\nexisting optional-dimension behavior. This option grants no new write authority.\n\n`record_workspace.workspace_view: switch` puts the first child canvas over the\nwhole workspace. The edge action opens it, and the return action or a node's\ndetails action returns to the selected record. It does not add form/canvas tabs\nto the sidebar. Covered content stays mounted and inert to preserve selection,\ndrafts and the graph viewport without allowing hidden controls to receive input.\n\n`record_related_editor.record_table` is an authored-only table presentation of\nthe same child collection, not a conversion to a `rows` array. Its finite\n`columns: [{fields: [field_key, ...], label?: string}]` groups existing field\neditors into cells. Every non-hidden field declared for that child section must\nappear exactly once; hidden/foreign/duplicate bindings and unknown column keys\nare rejected. Column labels default to the first field's label and use the usual\nlocale resolution. A cell retains field visibility, help, requiredness, custom\nconditions and existing edit/derived-field rules. Record creation still binds\nthe selected parent, deletion preserves the normal section cleanup rules, and\n`inherit_from_graph` tables remain source-linked and read-only. The shared table\nwrapper owns horizontal scrolling at narrow widths. This does not promote the\ncomponent or this declaration to generated A2UI.\n\nAn authored graph hierarchy with `max_parents: 1` may opt into\n`parent_control: header`. The existing single-parent selector then sits beside\nthe selected record's form title, rather than above the whole inspector. It\nstill updates the same relation edge, rejects cycles, retains the source-record\nnavigation and shows the actual parent in read-only mode. Omission preserves\nthe prior inspector presentation; neither view creates an extra parent field.\n\n`diagram_workspace.diagram.detail_rows` groups declared read-only fields into\nresponsive fact cards. `chip_fields` selects string-list fields rendered as tags;\n`detail_hint_fields` supplies the populated field labels for the details action.\n`tags` maps declared enum fields to labels and finite semantic tones. These are\npresentation declarations, not new edit rights or storage. Diagram details cover\nonly the content pane; the navigator remains available. Leaving an edited diagram\nstill requires successful serialization through the existing save barrier.\n\n`diagram_workspace.diagram.label_source` can read a declared label from another\nsection bound to the same record collection. The optional `inspector` keeps a\ncontext editor alongside the BPMN canvas: `process_sections` edit the selected\nprocess; `nodes` binds `source`, `process_field`, `element_field`, `label_field`\nand same-collection `sections`. Optional `related` groups use a process reference\nand an optional `node_field`; `advanced: true` starts the group collapsed.\nReferences must be declared `record_select` fields targeting the corresponding\ncollection. Clicking an element resolves its exact ID within the selected\nprocess only; absent or duplicate bindings do not guess a record. Existing field\nedit permissions and the atomic artifact save barrier remain authoritative.\nThis is contextual navigation, not automatic synchronization of BPMN structure\nand business facts; authors must explain how structural changes are reconciled.\n\nFor an exact component contract and on-demand local type declarations, use the\nauthoring inspector from the repository root:\n\n```sh\nnode .agents/skills/design-bundle-creator/scripts/inspect-panel-component.mjs . navigation_workspace --type ComponentNode.navigation_map.edges\n```\n\nUse the [component extension contract](a2ui-component-catalog-contract.md) when\nadding a component: catalog, validation, renderer, styles, edit boundaries,\ntests and authoring guidance must agree. Trusted runtime additions are possible;\nunknown component names in a manifest are rejected.\n\nAcceptance of a component name alone does not establish rendering fidelity,\neditable lifecycle support, or compatibility with every host; those require\nthe component's binding contract and actual runtime verification.\n\nPredefined DSL and A2UI-derived panels share this library, but generated panels\nmay use only the subset with an implemented generation/edit-authority contract.\nAn authored workspace is not automatically promoted into that subset.\nSupported generated results can be deterministically retained as DSL; unsupported\ncapabilities must fail explicitly, never disappear during conversion. This is\nnot an arbitrary bidirectional A2UI protocol converter.\n\n`question_list` is the standard controlled question interaction. Each source\nrecord uses `prompt`, optional `note`, `kind` (`text | single | multiple`),\noptional `choices[]` (`value`, `label`, `recommended`), `answer`, and optional\n`detail`. Text answers render as one multiline input; an existing text-question\n`detail` remains visible as read-only context rather than becoming a second\nanswer box. Single/multiple answers use accessible choice rows and may edit\n`detail`. Existing read-only context and choice supplements use the same\nlocalized label (without the optional-input suffix in reading mode). Cards\nwith a non-empty `answer` collapse to a readable result and can\nbe reopened for editing. The component writes only the fields exposed by that\ninteraction back to the owning record. It does not invent approval state, and an\nempty answer remains unanswered even when `detail` contains context. Native\nproviders may explicitly extend answer-state semantics for attachments, and\nmay add rounds or rejection around this base contract without making those\nextensions mandatory for other Kits.\n\nAuthored `question_list`, `question_rounds`, and `question_workspace` may declare\n`card_groups` with a unique `id`, `title`, and ordered `question_ids`. Members\nmust be contiguous in the existing record order and, for round workspaces, stay\nwithin one round. Invalid groups fall back to ordinary cards with a diagnostic;\ngrouping never reorders canonical records. Generated-origin Panels reject this\nauthored extension.\n\nEach group may declare a `presentation` object containing only optional boolean\n`always_expanded`, `show_detail`, and `show_attachments` properties. These select\nshared component behavior, not Bundle-specific styling. Omission preserves the\nusual collapse, detail, and attachment controls. Hiding a control preserves its\ncanonical data; keeping a card expanded does not grant editing permission.\nRead-only, disabled, protected, historical and rejection guards still apply.\n\n`question_workspace` composes the same question cards with the standard\n`panel_workspace` navigation shell. It groups records by optional numeric\n`round`, shows answer progress, and keeps only the selected group in the main\npane; records without a round form one current group. Its optional\n`description` is rendered through the shared sticky workspace Tip Bar above\nthe main content, never squeezed into the navigation sidebar. `question_rounds` is the\nbackward-compatible alias for this workspace behavior. Optional\n`multimodal_answer[]` entries use the Web App-compatible local reference shape\n(`type`, `file_md5`, `filename`, `mime_type`, `size_bytes`, `artifact_file`).\nThe client keeps pending bytes in a reserved browser-only transport, strips it\nbefore schema validation, and atomically saves only files still referenced by\ncanonical state. The transport is framework state, never a Bundle field.\n\nAuthored `question_workspace` / `question_rounds` nodes may explicitly set\n`question_policy.allow_choice_actions: true`. Expanded editable dynamic single\ncards offer “Switch to multiple choice”; multiple cards offer “Select all” /\n“Deselect all”. Omission or `false` preserves the existing controls. The shared\nruntime owns these actions and their localized styling, not Bundle CSS or an\nauthor-supplied `renderActions` callback. Switching changes only `kind` to\n`multiple`, preserving the exact answer bytes and keeping the editor open.\nSelect-all writes choice values in declared order through the existing\ncomma-separated `answer` contract; deselect-all writes an empty answer. Neither\naction changes detail, attachments, identity, choices or round. Records declared\nin `first_round_ids` are the fixed first-round configuration and do not receive\nthese actions; `protected_ids` still controls rejection only. Read-only,\ndisabled, rejected and read-only historical cards cannot invoke the actions.\nGenerated-origin/A2UI auto Panels reject this configuration, even when `false`;\ntheir existing answer/detail-only write authority and protected `kind` remain\nunchanged. Converting a generated view into an authored reusable panel does not\nsilently grant this capability: the author must opt in under the static contract.\n\n`panel_workspace` is the reusable panel-internal left navigation + main content\nlayout. It standardizes containment, scroll ownership and narrow-panel fallback;\nit does not define domain records or selection semantics. Use it rather than\ncopying a Kit-specific two-column shell.\n\nThe shared runtime `PanelWorkspaceNavigation` accepts optional per-item\n`description`, `supporting`, and `statusLabel` display slots alongside the\nlabel/current row. These are supplied display text, not canonical fields or\nnew DSL expressions. Omitted slots render no empty rows. The `meta` fallback\nremains supported. A marker requires both explicit `statusIndicator: true`\nand an existing `status`; a label-only item never gains an inferred status dot.\nFlat record navigation, question rounds, and future workspace consumers share\nthe same base navigation typography, spacing and selected appearance. Bundle\nCSS is not required. Hierarchical trees retain their separate structure.\nQuestion progress excludes rejected items from answered/completion checks,\nwhile retaining all group records in the displayed total and preserving fixed\nquestion grouping, stable IDs, selection and canonical answers. The original\nWeb App question panel used body round sections, not this sidebar; the shared\nsidebar is an enhanced structure using the original public navigation style,\nnot a claim of one-to-one restoration of a nonexistent original sidebar.\n\n`doc_lifecycle_studio` binds `objects`/`axes`/`actions` sections (validation\nfails loud when one is missing) and renders the fact table (actions × state\naxes, per-cell effects) plus process/derivation/ledger projections derived at\nrender time; unavailable views render disabled with a reason, never hidden.\n`rowview_workbench` renders the residue envelope (below) and requires a\n`source` declaring the add section it owns — the details-envelope schema\ncheck and the renderer are both scoped to that section; a workbench without\n`source` is rejected at compile time.\n\nIn editable mode `bpmn_canvas` edits bidirectionally: each process record's\n`name` and `steps` array (step name, `kind` task/gateway/event, order, add,\nremove) round-trip through the panel Save like any field edit.\n"
|
|
3470
3470
|
}
|
|
@@ -3651,8 +3651,8 @@
|
|
|
3651
3651
|
"sections": [
|
|
3652
3652
|
{
|
|
3653
3653
|
"file": "docs/dsl-spec.md",
|
|
3654
|
-
"line":
|
|
3655
|
-
"endLine":
|
|
3654
|
+
"line": 958,
|
|
3655
|
+
"endLine": 1169,
|
|
3656
3656
|
"heading": "`component` (trusted, extensible library)",
|
|
3657
3657
|
"content": "### `component` (trusted, extensible library)\n\nThe authoritative vocabulary is [`PANEL_COMPONENT_CATALOG`](../packages/core/src/panel-component-catalog.ts).\n`COMPONENT_KINDS`, workspace ownership, source bindings and the generated-panel\nsubset are derived from that one registry; this document is not a second\nvalidation whitelist. Bundle data cannot register executable components.\n\nThe shared library includes basic layouts and controls, question workspaces,\nrecord navigation/editing, diagrams, canvases, artifact readers and previews.\nFull-height workspace components preserve scroll and navigation ownership:\n`record_board`, `document_workspace`, `artifact_workspace`, `diagram_workspace`,\n`canvas_workspace`, `preview_workspace` and `navigation_workspace` expose their\nbehavior through explicit data bindings rather than Kit names. These are reusable\ncapabilities, not a guarantee that every record schema fits every workspace.\n\n`record_board.board.detail_sources` can embed exactly one `record_workspace`\nunder the selected card. Each `{section, reference}` binding declares an unordered\ndirect record collection and a readonly `record_select` back to the board's\nparent section. The child workspace sources must belong to those bindings.\nOwner and child storage paths cannot alias or overlap. The renderer filters\nchildren by the selected parent, binds new records to it, and merges hidden\nsibling records back into canonical updates. It refuses sibling-id replacement,\nreparenting and writes outside these collections. This is a view projection,\nnot a second stored copy; it does not support independently ordered child maps,\nnested `fields_path` records or artifact staging in this first composition slice.\nOrdinary `detail_sections` retain their existing same-record nested-form meaning.\n\n`record_board` uses full-width cards and a workspace-covering overview. Optional\n`board.group` binds a real grouping field. When omitted, the sidebar lists records\ndirectly, cards have no artificial group heading, and the overview connects the\nroot directly to records. Do not bind long summaries merely to satisfy grouping;\nthis projection never adds a grouping field to canonical records.\nSidebar selection scrolls to a card; it does not start editing. Description and\nbadge drafts have explicit Save/Cancel, while rejected records remain inspectable\nwithout granting edit access. Optional `board.id_field` binds a declared visible,\nreadonly `text` field and displays its existing string beside the card title and\nat the top of cover details. Inline details retain the same card header. It does\nnot add an ID editor, generate a fallback ID or write state; omission retains the\nexisting title-only presentation. `board.detail_fields` restricts the parent fields\nshown in the detail fold, and `details_title` localizes its heading. Optional nested\ndimensions can be added or removed without replacing unrelated record fields.\n`board.detail_fields_mode: fixed` instead shows every declared nested input and\nremoves dimension-level add/delete controls; collection item add/delete still\nuses its usual editor. Fields remain schema-optional, including empty inputs.\nViewing does not insert missing strings/maps. Omitted/`on_demand` retains the\nexisting optional-dimension behavior. This option grants no new write authority.\n\n`record_workspace.workspace_view: switch` puts the first child canvas over the\nwhole workspace. The edge action opens it, and the return action or a node's\ndetails action returns to the selected record. It does not add form/canvas tabs\nto the sidebar. Covered content stays mounted and inert to preserve selection,\ndrafts and the graph viewport without allowing hidden controls to receive input.\n\n`record_related_editor.record_table` is an authored-only table presentation of\nthe same child collection, not a conversion to a `rows` array. Its finite\n`columns: [{fields: [field_key, ...], label?: string}]` groups existing field\neditors into cells. Every non-hidden field declared for that child section must\nappear exactly once; hidden/foreign/duplicate bindings and unknown column keys\nare rejected. Column labels default to the first field's label and use the usual\nlocale resolution. A cell retains field visibility, help, requiredness, custom\nconditions and existing edit/derived-field rules. Record creation still binds\nthe selected parent, deletion preserves the normal section cleanup rules, and\n`inherit_from_graph` tables remain source-linked and read-only. The shared table\nwrapper owns horizontal scrolling at narrow widths. This does not promote the\ncomponent or this declaration to generated A2UI.\n\nAn authored graph hierarchy with `max_parents: 1` may opt into\n`parent_control: header`. The existing single-parent selector then sits beside\nthe selected record's form title, rather than above the whole inspector. It\nstill updates the same relation edge, rejects cycles, retains the source-record\nnavigation and shows the actual parent in read-only mode. Omission preserves\nthe prior inspector presentation; neither view creates an extra parent field.\n\n`diagram_workspace.diagram.detail_rows` groups declared read-only fields into\nresponsive fact cards. `chip_fields` selects string-list fields rendered as tags;\n`detail_hint_fields` supplies the populated field labels for the details action.\n`tags` maps declared enum fields to labels and finite semantic tones. These are\npresentation declarations, not new edit rights or storage. Diagram details cover\nonly the content pane; the navigator remains available. Leaving an edited diagram\nstill requires successful serialization through the existing save barrier.\n\n`diagram_workspace.diagram.label_source` can read a declared label from another\nsection bound to the same record collection. The optional `inspector` keeps a\ncontext editor alongside the BPMN canvas: `process_sections` edit the selected\nprocess; `nodes` binds `source`, `process_field`, `element_field`, `label_field`\nand same-collection `sections`. Optional `related` groups use a process reference\nand an optional `node_field`; `advanced: true` starts the group collapsed.\nReferences must be declared `record_select` fields targeting the corresponding\ncollection. Clicking an element resolves its exact ID within the selected\nprocess only; absent or duplicate bindings do not guess a record. Existing field\nedit permissions and the atomic artifact save barrier remain authoritative.\nThis is contextual navigation, not automatic synchronization of BPMN structure\nand business facts; authors must explain how structural changes are reconciled.\n\nFor an exact component contract and on-demand local type declarations, use the\nauthoring inspector from the repository root:\n\n```sh\nnode .agents/skills/design-bundle-creator/scripts/inspect-panel-component.mjs . navigation_workspace --type ComponentNode.navigation_map.edges\n```\n\nUse the [component extension contract](a2ui-component-catalog-contract.md) when\nadding a component: catalog, validation, renderer, styles, edit boundaries,\ntests and authoring guidance must agree. Trusted runtime additions are possible;\nunknown component names in a manifest are rejected.\n\nAcceptance of a component name alone does not establish rendering fidelity,\neditable lifecycle support, or compatibility with every host; those require\nthe component's binding contract and actual runtime verification.\n\nPredefined DSL and A2UI-derived panels share this library, but generated panels\nmay use only the subset with an implemented generation/edit-authority contract.\nAn authored workspace is not automatically promoted into that subset.\nSupported generated results can be deterministically retained as DSL; unsupported\ncapabilities must fail explicitly, never disappear during conversion. This is\nnot an arbitrary bidirectional A2UI protocol converter.\n\n`question_list` is the standard controlled question interaction. Each source\nrecord uses `prompt`, optional `note`, `kind` (`text | single | multiple`),\noptional `choices[]` (`value`, `label`, `recommended`), `answer`, and optional\n`detail`. Text answers render as one multiline input; an existing text-question\n`detail` remains visible as read-only context rather than becoming a second\nanswer box. Single/multiple answers use accessible choice rows and may edit\n`detail`. Existing read-only context and choice supplements use the same\nlocalized label (without the optional-input suffix in reading mode). Cards\nwith a non-empty `answer` collapse to a readable result and can\nbe reopened for editing. The component writes only the fields exposed by that\ninteraction back to the owning record. It does not invent approval state, and an\nempty answer remains unanswered even when `detail` contains context. Native\nproviders may explicitly extend answer-state semantics for attachments, and\nmay add rounds or rejection around this base contract without making those\nextensions mandatory for other Kits.\n\nAuthored `question_list`, `question_rounds`, and `question_workspace` may declare\n`card_groups` with a unique `id`, `title`, and ordered `question_ids`. Members\nmust be contiguous in the existing record order and, for round workspaces, stay\nwithin one round. Invalid groups fall back to ordinary cards with a diagnostic;\ngrouping never reorders canonical records. Generated-origin Panels reject this\nauthored extension.\n\nEach group may declare a `presentation` object containing only optional boolean\n`always_expanded`, `show_detail`, and `show_attachments` properties. These select\nshared component behavior, not Bundle-specific styling. Omission preserves the\nusual collapse, detail, and attachment controls. Hiding a control preserves its\ncanonical data; keeping a card expanded does not grant editing permission.\nRead-only, disabled, protected, historical and rejection guards still apply.\n\n`question_workspace` composes the same question cards with the standard\n`panel_workspace` navigation shell. It groups records by optional numeric\n`round`, shows answer progress, and keeps only the selected group in the main\npane; records without a round form one current group. Its optional\n`description` is rendered through the shared sticky workspace Tip Bar above\nthe main content, never squeezed into the navigation sidebar. `question_rounds` is the\nbackward-compatible alias for this workspace behavior. Optional\n`multimodal_answer[]` entries use the Web App-compatible local reference shape\n(`type`, `file_md5`, `filename`, `mime_type`, `size_bytes`, `artifact_file`).\nThe client keeps pending bytes in a reserved browser-only transport, strips it\nbefore schema validation, and atomically saves only files still referenced by\ncanonical state. The transport is framework state, never a Bundle field.\n\nAuthored `question_workspace` / `question_rounds` nodes may explicitly set\n`question_policy.allow_choice_actions: true`. Expanded editable dynamic single\ncards offer “Switch to multiple choice”; multiple cards offer “Select all” /\n“Deselect all”. Omission or `false` preserves the existing controls. The shared\nruntime owns these actions and their localized styling, not Bundle CSS or an\nauthor-supplied `renderActions` callback. Switching changes only `kind` to\n`multiple`, preserving the exact answer bytes and keeping the editor open.\nSelect-all writes choice values in declared order through the existing\ncomma-separated `answer` contract; deselect-all writes an empty answer. Neither\naction changes detail, attachments, identity, choices or round. Records declared\nin `first_round_ids` are the fixed first-round configuration and do not receive\nthese actions; `protected_ids` still controls rejection only. Read-only,\ndisabled, rejected and read-only historical cards cannot invoke the actions.\nGenerated-origin/A2UI auto Panels reject this configuration, even when `false`;\ntheir existing answer/detail-only write authority and protected `kind` remain\nunchanged. Converting a generated view into an authored reusable panel does not\nsilently grant this capability: the author must opt in under the static contract.\n\n`panel_workspace` is the reusable panel-internal left navigation + main content\nlayout. It standardizes containment, scroll ownership and narrow-panel fallback;\nit does not define domain records or selection semantics. Use it rather than\ncopying a Kit-specific two-column shell.\n\nThe shared runtime `PanelWorkspaceNavigation` accepts optional per-item\n`description`, `supporting`, and `statusLabel` display slots alongside the\nlabel/current row. These are supplied display text, not canonical fields or\nnew DSL expressions. Omitted slots render no empty rows. The `meta` fallback\nremains supported. A marker requires both explicit `statusIndicator: true`\nand an existing `status`; a label-only item never gains an inferred status dot.\nFlat record navigation, question rounds, and future workspace consumers share\nthe same base navigation typography, spacing and selected appearance. Bundle\nCSS is not required. Hierarchical trees retain their separate structure.\nQuestion progress excludes rejected items from answered/completion checks,\nwhile retaining all group records in the displayed total and preserving fixed\nquestion grouping, stable IDs, selection and canonical answers. The original\nWeb App question panel used body round sections, not this sidebar; the shared\nsidebar is an enhanced structure using the original public navigation style,\nnot a claim of one-to-one restoration of a nonexistent original sidebar.\n\n`doc_lifecycle_studio` binds `objects`/`axes`/`actions` sections (validation\nfails loud when one is missing) and renders the fact table (actions × state\naxes, per-cell effects) plus process/derivation/ledger projections derived at\nrender time; unavailable views render disabled with a reason, never hidden.\n`rowview_workbench` renders the residue envelope (below) and requires a\n`source` declaring the add section it owns — the details-envelope schema\ncheck and the renderer are both scoped to that section; a workbench without\n`source` is rejected at compile time.\n\nIn editable mode `bpmn_canvas` edits bidirectionally: each process record's\n`name` and `steps` array (step name, `kind` task/gateway/event, order, add,\nremove) round-trip through the panel Save like any field edit.\n"
|
|
3658
3658
|
}
|
|
@@ -3791,8 +3791,8 @@
|
|
|
3791
3791
|
"sections": [
|
|
3792
3792
|
{
|
|
3793
3793
|
"file": "docs/dsl-spec.md",
|
|
3794
|
-
"line":
|
|
3795
|
-
"endLine":
|
|
3794
|
+
"line": 958,
|
|
3795
|
+
"endLine": 1169,
|
|
3796
3796
|
"heading": "`component` (trusted, extensible library)",
|
|
3797
3797
|
"content": "### `component` (trusted, extensible library)\n\nThe authoritative vocabulary is [`PANEL_COMPONENT_CATALOG`](../packages/core/src/panel-component-catalog.ts).\n`COMPONENT_KINDS`, workspace ownership, source bindings and the generated-panel\nsubset are derived from that one registry; this document is not a second\nvalidation whitelist. Bundle data cannot register executable components.\n\nThe shared library includes basic layouts and controls, question workspaces,\nrecord navigation/editing, diagrams, canvases, artifact readers and previews.\nFull-height workspace components preserve scroll and navigation ownership:\n`record_board`, `document_workspace`, `artifact_workspace`, `diagram_workspace`,\n`canvas_workspace`, `preview_workspace` and `navigation_workspace` expose their\nbehavior through explicit data bindings rather than Kit names. These are reusable\ncapabilities, not a guarantee that every record schema fits every workspace.\n\n`record_board.board.detail_sources` can embed exactly one `record_workspace`\nunder the selected card. Each `{section, reference}` binding declares an unordered\ndirect record collection and a readonly `record_select` back to the board's\nparent section. The child workspace sources must belong to those bindings.\nOwner and child storage paths cannot alias or overlap. The renderer filters\nchildren by the selected parent, binds new records to it, and merges hidden\nsibling records back into canonical updates. It refuses sibling-id replacement,\nreparenting and writes outside these collections. This is a view projection,\nnot a second stored copy; it does not support independently ordered child maps,\nnested `fields_path` records or artifact staging in this first composition slice.\nOrdinary `detail_sections` retain their existing same-record nested-form meaning.\n\n`record_board` uses full-width cards and a workspace-covering overview. Optional\n`board.group` binds a real grouping field. When omitted, the sidebar lists records\ndirectly, cards have no artificial group heading, and the overview connects the\nroot directly to records. Do not bind long summaries merely to satisfy grouping;\nthis projection never adds a grouping field to canonical records.\nSidebar selection scrolls to a card; it does not start editing. Description and\nbadge drafts have explicit Save/Cancel, while rejected records remain inspectable\nwithout granting edit access. Optional `board.id_field` binds a declared visible,\nreadonly `text` field and displays its existing string beside the card title and\nat the top of cover details. Inline details retain the same card header. It does\nnot add an ID editor, generate a fallback ID or write state; omission retains the\nexisting title-only presentation. `board.detail_fields` restricts the parent fields\nshown in the detail fold, and `details_title` localizes its heading. Optional nested\ndimensions can be added or removed without replacing unrelated record fields.\n`board.detail_fields_mode: fixed` instead shows every declared nested input and\nremoves dimension-level add/delete controls; collection item add/delete still\nuses its usual editor. Fields remain schema-optional, including empty inputs.\nViewing does not insert missing strings/maps. Omitted/`on_demand` retains the\nexisting optional-dimension behavior. This option grants no new write authority.\n\n`record_workspace.workspace_view: switch` puts the first child canvas over the\nwhole workspace. The edge action opens it, and the return action or a node's\ndetails action returns to the selected record. It does not add form/canvas tabs\nto the sidebar. Covered content stays mounted and inert to preserve selection,\ndrafts and the graph viewport without allowing hidden controls to receive input.\n\n`record_related_editor.record_table` is an authored-only table presentation of\nthe same child collection, not a conversion to a `rows` array. Its finite\n`columns: [{fields: [field_key, ...], label?: string}]` groups existing field\neditors into cells. Every non-hidden field declared for that child section must\nappear exactly once; hidden/foreign/duplicate bindings and unknown column keys\nare rejected. Column labels default to the first field's label and use the usual\nlocale resolution. A cell retains field visibility, help, requiredness, custom\nconditions and existing edit/derived-field rules. Record creation still binds\nthe selected parent, deletion preserves the normal section cleanup rules, and\n`inherit_from_graph` tables remain source-linked and read-only. The shared table\nwrapper owns horizontal scrolling at narrow widths. This does not promote the\ncomponent or this declaration to generated A2UI.\n\nAn authored graph hierarchy with `max_parents: 1` may opt into\n`parent_control: header`. The existing single-parent selector then sits beside\nthe selected record's form title, rather than above the whole inspector. It\nstill updates the same relation edge, rejects cycles, retains the source-record\nnavigation and shows the actual parent in read-only mode. Omission preserves\nthe prior inspector presentation; neither view creates an extra parent field.\n\n`diagram_workspace.diagram.detail_rows` groups declared read-only fields into\nresponsive fact cards. `chip_fields` selects string-list fields rendered as tags;\n`detail_hint_fields` supplies the populated field labels for the details action.\n`tags` maps declared enum fields to labels and finite semantic tones. These are\npresentation declarations, not new edit rights or storage. Diagram details cover\nonly the content pane; the navigator remains available. Leaving an edited diagram\nstill requires successful serialization through the existing save barrier.\n\n`diagram_workspace.diagram.label_source` can read a declared label from another\nsection bound to the same record collection. The optional `inspector` keeps a\ncontext editor alongside the BPMN canvas: `process_sections` edit the selected\nprocess; `nodes` binds `source`, `process_field`, `element_field`, `label_field`\nand same-collection `sections`. Optional `related` groups use a process reference\nand an optional `node_field`; `advanced: true` starts the group collapsed.\nReferences must be declared `record_select` fields targeting the corresponding\ncollection. Clicking an element resolves its exact ID within the selected\nprocess only; absent or duplicate bindings do not guess a record. Existing field\nedit permissions and the atomic artifact save barrier remain authoritative.\nThis is contextual navigation, not automatic synchronization of BPMN structure\nand business facts; authors must explain how structural changes are reconciled.\n\nFor an exact component contract and on-demand local type declarations, use the\nauthoring inspector from the repository root:\n\n```sh\nnode .agents/skills/design-bundle-creator/scripts/inspect-panel-component.mjs . navigation_workspace --type ComponentNode.navigation_map.edges\n```\n\nUse the [component extension contract](a2ui-component-catalog-contract.md) when\nadding a component: catalog, validation, renderer, styles, edit boundaries,\ntests and authoring guidance must agree. Trusted runtime additions are possible;\nunknown component names in a manifest are rejected.\n\nAcceptance of a component name alone does not establish rendering fidelity,\neditable lifecycle support, or compatibility with every host; those require\nthe component's binding contract and actual runtime verification.\n\nPredefined DSL and A2UI-derived panels share this library, but generated panels\nmay use only the subset with an implemented generation/edit-authority contract.\nAn authored workspace is not automatically promoted into that subset.\nSupported generated results can be deterministically retained as DSL; unsupported\ncapabilities must fail explicitly, never disappear during conversion. This is\nnot an arbitrary bidirectional A2UI protocol converter.\n\n`question_list` is the standard controlled question interaction. Each source\nrecord uses `prompt`, optional `note`, `kind` (`text | single | multiple`),\noptional `choices[]` (`value`, `label`, `recommended`), `answer`, and optional\n`detail`. Text answers render as one multiline input; an existing text-question\n`detail` remains visible as read-only context rather than becoming a second\nanswer box. Single/multiple answers use accessible choice rows and may edit\n`detail`. Existing read-only context and choice supplements use the same\nlocalized label (without the optional-input suffix in reading mode). Cards\nwith a non-empty `answer` collapse to a readable result and can\nbe reopened for editing. The component writes only the fields exposed by that\ninteraction back to the owning record. It does not invent approval state, and an\nempty answer remains unanswered even when `detail` contains context. Native\nproviders may explicitly extend answer-state semantics for attachments, and\nmay add rounds or rejection around this base contract without making those\nextensions mandatory for other Kits.\n\nAuthored `question_list`, `question_rounds`, and `question_workspace` may declare\n`card_groups` with a unique `id`, `title`, and ordered `question_ids`. Members\nmust be contiguous in the existing record order and, for round workspaces, stay\nwithin one round. Invalid groups fall back to ordinary cards with a diagnostic;\ngrouping never reorders canonical records. Generated-origin Panels reject this\nauthored extension.\n\nEach group may declare a `presentation` object containing only optional boolean\n`always_expanded`, `show_detail`, and `show_attachments` properties. These select\nshared component behavior, not Bundle-specific styling. Omission preserves the\nusual collapse, detail, and attachment controls. Hiding a control preserves its\ncanonical data; keeping a card expanded does not grant editing permission.\nRead-only, disabled, protected, historical and rejection guards still apply.\n\n`question_workspace` composes the same question cards with the standard\n`panel_workspace` navigation shell. It groups records by optional numeric\n`round`, shows answer progress, and keeps only the selected group in the main\npane; records without a round form one current group. Its optional\n`description` is rendered through the shared sticky workspace Tip Bar above\nthe main content, never squeezed into the navigation sidebar. `question_rounds` is the\nbackward-compatible alias for this workspace behavior. Optional\n`multimodal_answer[]` entries use the Web App-compatible local reference shape\n(`type`, `file_md5`, `filename`, `mime_type`, `size_bytes`, `artifact_file`).\nThe client keeps pending bytes in a reserved browser-only transport, strips it\nbefore schema validation, and atomically saves only files still referenced by\ncanonical state. The transport is framework state, never a Bundle field.\n\nAuthored `question_workspace` / `question_rounds` nodes may explicitly set\n`question_policy.allow_choice_actions: true`. Expanded editable dynamic single\ncards offer “Switch to multiple choice”; multiple cards offer “Select all” /\n“Deselect all”. Omission or `false` preserves the existing controls. The shared\nruntime owns these actions and their localized styling, not Bundle CSS or an\nauthor-supplied `renderActions` callback. Switching changes only `kind` to\n`multiple`, preserving the exact answer bytes and keeping the editor open.\nSelect-all writes choice values in declared order through the existing\ncomma-separated `answer` contract; deselect-all writes an empty answer. Neither\naction changes detail, attachments, identity, choices or round. Records declared\nin `first_round_ids` are the fixed first-round configuration and do not receive\nthese actions; `protected_ids` still controls rejection only. Read-only,\ndisabled, rejected and read-only historical cards cannot invoke the actions.\nGenerated-origin/A2UI auto Panels reject this configuration, even when `false`;\ntheir existing answer/detail-only write authority and protected `kind` remain\nunchanged. Converting a generated view into an authored reusable panel does not\nsilently grant this capability: the author must opt in under the static contract.\n\n`panel_workspace` is the reusable panel-internal left navigation + main content\nlayout. It standardizes containment, scroll ownership and narrow-panel fallback;\nit does not define domain records or selection semantics. Use it rather than\ncopying a Kit-specific two-column shell.\n\nThe shared runtime `PanelWorkspaceNavigation` accepts optional per-item\n`description`, `supporting`, and `statusLabel` display slots alongside the\nlabel/current row. These are supplied display text, not canonical fields or\nnew DSL expressions. Omitted slots render no empty rows. The `meta` fallback\nremains supported. A marker requires both explicit `statusIndicator: true`\nand an existing `status`; a label-only item never gains an inferred status dot.\nFlat record navigation, question rounds, and future workspace consumers share\nthe same base navigation typography, spacing and selected appearance. Bundle\nCSS is not required. Hierarchical trees retain their separate structure.\nQuestion progress excludes rejected items from answered/completion checks,\nwhile retaining all group records in the displayed total and preserving fixed\nquestion grouping, stable IDs, selection and canonical answers. The original\nWeb App question panel used body round sections, not this sidebar; the shared\nsidebar is an enhanced structure using the original public navigation style,\nnot a claim of one-to-one restoration of a nonexistent original sidebar.\n\n`doc_lifecycle_studio` binds `objects`/`axes`/`actions` sections (validation\nfails loud when one is missing) and renders the fact table (actions × state\naxes, per-cell effects) plus process/derivation/ledger projections derived at\nrender time; unavailable views render disabled with a reason, never hidden.\n`rowview_workbench` renders the residue envelope (below) and requires a\n`source` declaring the add section it owns — the details-envelope schema\ncheck and the renderer are both scoped to that section; a workbench without\n`source` is rejected at compile time.\n\nIn editable mode `bpmn_canvas` edits bidirectionally: each process record's\n`name` and `steps` array (step name, `kind` task/gateway/event, order, add,\nremove) round-trip through the panel Save like any field edit.\n"
|
|
3798
3798
|
}
|
|
@@ -4767,8 +4767,8 @@
|
|
|
4767
4767
|
"sections": [
|
|
4768
4768
|
{
|
|
4769
4769
|
"file": "docs/dsl-spec.md",
|
|
4770
|
-
"line":
|
|
4771
|
-
"endLine":
|
|
4770
|
+
"line": 934,
|
|
4771
|
+
"endLine": 957,
|
|
4772
4772
|
"heading": "`navigation_workspace` — creating connections",
|
|
4773
4773
|
"content": "### `navigation_workspace` — creating connections\n\n`navigation_map` binds independent node, edge and frame collections. Optional\n`connection_policy.allow_self` and `allow_parallel` affect only new connections;\nomitting either flag allows that case. Parallel connections have the same\nordered source and target identities, regardless of visual ports. A reverse\nconnection is distinct. Both endpoints must exist. Changing this declaration\nnever removes or rewrites existing connections, including invalid old records.\nThese flags do not express acyclicity, degree limits or arbitrary graph rules.\n\nOptional `navigation_map.edges.new_label` supplies a new connection's initial\nlabel. It accepts literal text or an existing `$t:key` reference, with only\n`{source}` and `{target}` placeholders. Endpoint labels come from `nodes.label`,\nfalling back to record identities; substitution is single-pass plain text.\nResolved labels are validated in each loaded locale with its declared fallback.\nEmpty templates, unknown placeholders, malformed braces and wrong types fail.\nOmission keeps the existing section creation defaults. The declaration never\nrenames saved edges or relabels them after an endpoint changes.\n\nThe workspace checks the same creation policy during preview and again when\ncreating a connection, using current edit permission and canonical endpoints.\nSee `ComponentNode.navigation_map` in [the Core contract](../packages/core/src/panel-dsl.ts)\nand the source-derived component inspector for the complete field bindings.\n"
|
|
4774
4774
|
}
|
|
@@ -4953,8 +4953,8 @@
|
|
|
4953
4953
|
"sections": [
|
|
4954
4954
|
{
|
|
4955
4955
|
"file": "docs/dsl-spec.md",
|
|
4956
|
-
"line":
|
|
4957
|
-
"endLine":
|
|
4956
|
+
"line": 958,
|
|
4957
|
+
"endLine": 1169,
|
|
4958
4958
|
"heading": "`component` (trusted, extensible library)",
|
|
4959
4959
|
"content": "### `component` (trusted, extensible library)\n\nThe authoritative vocabulary is [`PANEL_COMPONENT_CATALOG`](../packages/core/src/panel-component-catalog.ts).\n`COMPONENT_KINDS`, workspace ownership, source bindings and the generated-panel\nsubset are derived from that one registry; this document is not a second\nvalidation whitelist. Bundle data cannot register executable components.\n\nThe shared library includes basic layouts and controls, question workspaces,\nrecord navigation/editing, diagrams, canvases, artifact readers and previews.\nFull-height workspace components preserve scroll and navigation ownership:\n`record_board`, `document_workspace`, `artifact_workspace`, `diagram_workspace`,\n`canvas_workspace`, `preview_workspace` and `navigation_workspace` expose their\nbehavior through explicit data bindings rather than Kit names. These are reusable\ncapabilities, not a guarantee that every record schema fits every workspace.\n\n`record_board.board.detail_sources` can embed exactly one `record_workspace`\nunder the selected card. Each `{section, reference}` binding declares an unordered\ndirect record collection and a readonly `record_select` back to the board's\nparent section. The child workspace sources must belong to those bindings.\nOwner and child storage paths cannot alias or overlap. The renderer filters\nchildren by the selected parent, binds new records to it, and merges hidden\nsibling records back into canonical updates. It refuses sibling-id replacement,\nreparenting and writes outside these collections. This is a view projection,\nnot a second stored copy; it does not support independently ordered child maps,\nnested `fields_path` records or artifact staging in this first composition slice.\nOrdinary `detail_sections` retain their existing same-record nested-form meaning.\n\n`record_board` uses full-width cards and a workspace-covering overview. Optional\n`board.group` binds a real grouping field. When omitted, the sidebar lists records\ndirectly, cards have no artificial group heading, and the overview connects the\nroot directly to records. Do not bind long summaries merely to satisfy grouping;\nthis projection never adds a grouping field to canonical records.\nSidebar selection scrolls to a card; it does not start editing. Description and\nbadge drafts have explicit Save/Cancel, while rejected records remain inspectable\nwithout granting edit access. Optional `board.id_field` binds a declared visible,\nreadonly `text` field and displays its existing string beside the card title and\nat the top of cover details. Inline details retain the same card header. It does\nnot add an ID editor, generate a fallback ID or write state; omission retains the\nexisting title-only presentation. `board.detail_fields` restricts the parent fields\nshown in the detail fold, and `details_title` localizes its heading. Optional nested\ndimensions can be added or removed without replacing unrelated record fields.\n`board.detail_fields_mode: fixed` instead shows every declared nested input and\nremoves dimension-level add/delete controls; collection item add/delete still\nuses its usual editor. Fields remain schema-optional, including empty inputs.\nViewing does not insert missing strings/maps. Omitted/`on_demand` retains the\nexisting optional-dimension behavior. This option grants no new write authority.\n\n`record_workspace.workspace_view: switch` puts the first child canvas over the\nwhole workspace. The edge action opens it, and the return action or a node's\ndetails action returns to the selected record. It does not add form/canvas tabs\nto the sidebar. Covered content stays mounted and inert to preserve selection,\ndrafts and the graph viewport without allowing hidden controls to receive input.\n\n`record_related_editor.record_table` is an authored-only table presentation of\nthe same child collection, not a conversion to a `rows` array. Its finite\n`columns: [{fields: [field_key, ...], label?: string}]` groups existing field\neditors into cells. Every non-hidden field declared for that child section must\nappear exactly once; hidden/foreign/duplicate bindings and unknown column keys\nare rejected. Column labels default to the first field's label and use the usual\nlocale resolution. A cell retains field visibility, help, requiredness, custom\nconditions and existing edit/derived-field rules. Record creation still binds\nthe selected parent, deletion preserves the normal section cleanup rules, and\n`inherit_from_graph` tables remain source-linked and read-only. The shared table\nwrapper owns horizontal scrolling at narrow widths. This does not promote the\ncomponent or this declaration to generated A2UI.\n\nAn authored graph hierarchy with `max_parents: 1` may opt into\n`parent_control: header`. The existing single-parent selector then sits beside\nthe selected record's form title, rather than above the whole inspector. It\nstill updates the same relation edge, rejects cycles, retains the source-record\nnavigation and shows the actual parent in read-only mode. Omission preserves\nthe prior inspector presentation; neither view creates an extra parent field.\n\n`diagram_workspace.diagram.detail_rows` groups declared read-only fields into\nresponsive fact cards. `chip_fields` selects string-list fields rendered as tags;\n`detail_hint_fields` supplies the populated field labels for the details action.\n`tags` maps declared enum fields to labels and finite semantic tones. These are\npresentation declarations, not new edit rights or storage. Diagram details cover\nonly the content pane; the navigator remains available. Leaving an edited diagram\nstill requires successful serialization through the existing save barrier.\n\n`diagram_workspace.diagram.label_source` can read a declared label from another\nsection bound to the same record collection. The optional `inspector` keeps a\ncontext editor alongside the BPMN canvas: `process_sections` edit the selected\nprocess; `nodes` binds `source`, `process_field`, `element_field`, `label_field`\nand same-collection `sections`. Optional `related` groups use a process reference\nand an optional `node_field`; `advanced: true` starts the group collapsed.\nReferences must be declared `record_select` fields targeting the corresponding\ncollection. Clicking an element resolves its exact ID within the selected\nprocess only; absent or duplicate bindings do not guess a record. Existing field\nedit permissions and the atomic artifact save barrier remain authoritative.\nThis is contextual navigation, not automatic synchronization of BPMN structure\nand business facts; authors must explain how structural changes are reconciled.\n\nFor an exact component contract and on-demand local type declarations, use the\nauthoring inspector from the repository root:\n\n```sh\nnode .agents/skills/design-bundle-creator/scripts/inspect-panel-component.mjs . navigation_workspace --type ComponentNode.navigation_map.edges\n```\n\nUse the [component extension contract](a2ui-component-catalog-contract.md) when\nadding a component: catalog, validation, renderer, styles, edit boundaries,\ntests and authoring guidance must agree. Trusted runtime additions are possible;\nunknown component names in a manifest are rejected.\n\nAcceptance of a component name alone does not establish rendering fidelity,\neditable lifecycle support, or compatibility with every host; those require\nthe component's binding contract and actual runtime verification.\n\nPredefined DSL and A2UI-derived panels share this library, but generated panels\nmay use only the subset with an implemented generation/edit-authority contract.\nAn authored workspace is not automatically promoted into that subset.\nSupported generated results can be deterministically retained as DSL; unsupported\ncapabilities must fail explicitly, never disappear during conversion. This is\nnot an arbitrary bidirectional A2UI protocol converter.\n\n`question_list` is the standard controlled question interaction. Each source\nrecord uses `prompt`, optional `note`, `kind` (`text | single | multiple`),\noptional `choices[]` (`value`, `label`, `recommended`), `answer`, and optional\n`detail`. Text answers render as one multiline input; an existing text-question\n`detail` remains visible as read-only context rather than becoming a second\nanswer box. Single/multiple answers use accessible choice rows and may edit\n`detail`. Existing read-only context and choice supplements use the same\nlocalized label (without the optional-input suffix in reading mode). Cards\nwith a non-empty `answer` collapse to a readable result and can\nbe reopened for editing. The component writes only the fields exposed by that\ninteraction back to the owning record. It does not invent approval state, and an\nempty answer remains unanswered even when `detail` contains context. Native\nproviders may explicitly extend answer-state semantics for attachments, and\nmay add rounds or rejection around this base contract without making those\nextensions mandatory for other Kits.\n\nAuthored `question_list`, `question_rounds`, and `question_workspace` may declare\n`card_groups` with a unique `id`, `title`, and ordered `question_ids`. Members\nmust be contiguous in the existing record order and, for round workspaces, stay\nwithin one round. Invalid groups fall back to ordinary cards with a diagnostic;\ngrouping never reorders canonical records. Generated-origin Panels reject this\nauthored extension.\n\nEach group may declare a `presentation` object containing only optional boolean\n`always_expanded`, `show_detail`, and `show_attachments` properties. These select\nshared component behavior, not Bundle-specific styling. Omission preserves the\nusual collapse, detail, and attachment controls. Hiding a control preserves its\ncanonical data; keeping a card expanded does not grant editing permission.\nRead-only, disabled, protected, historical and rejection guards still apply.\n\n`question_workspace` composes the same question cards with the standard\n`panel_workspace` navigation shell. It groups records by optional numeric\n`round`, shows answer progress, and keeps only the selected group in the main\npane; records without a round form one current group. Its optional\n`description` is rendered through the shared sticky workspace Tip Bar above\nthe main content, never squeezed into the navigation sidebar. `question_rounds` is the\nbackward-compatible alias for this workspace behavior. Optional\n`multimodal_answer[]` entries use the Web App-compatible local reference shape\n(`type`, `file_md5`, `filename`, `mime_type`, `size_bytes`, `artifact_file`).\nThe client keeps pending bytes in a reserved browser-only transport, strips it\nbefore schema validation, and atomically saves only files still referenced by\ncanonical state. The transport is framework state, never a Bundle field.\n\nAuthored `question_workspace` / `question_rounds` nodes may explicitly set\n`question_policy.allow_choice_actions: true`. Expanded editable dynamic single\ncards offer “Switch to multiple choice”; multiple cards offer “Select all” /\n“Deselect all”. Omission or `false` preserves the existing controls. The shared\nruntime owns these actions and their localized styling, not Bundle CSS or an\nauthor-supplied `renderActions` callback. Switching changes only `kind` to\n`multiple`, preserving the exact answer bytes and keeping the editor open.\nSelect-all writes choice values in declared order through the existing\ncomma-separated `answer` contract; deselect-all writes an empty answer. Neither\naction changes detail, attachments, identity, choices or round. Records declared\nin `first_round_ids` are the fixed first-round configuration and do not receive\nthese actions; `protected_ids` still controls rejection only. Read-only,\ndisabled, rejected and read-only historical cards cannot invoke the actions.\nGenerated-origin/A2UI auto Panels reject this configuration, even when `false`;\ntheir existing answer/detail-only write authority and protected `kind` remain\nunchanged. Converting a generated view into an authored reusable panel does not\nsilently grant this capability: the author must opt in under the static contract.\n\n`panel_workspace` is the reusable panel-internal left navigation + main content\nlayout. It standardizes containment, scroll ownership and narrow-panel fallback;\nit does not define domain records or selection semantics. Use it rather than\ncopying a Kit-specific two-column shell.\n\nThe shared runtime `PanelWorkspaceNavigation` accepts optional per-item\n`description`, `supporting`, and `statusLabel` display slots alongside the\nlabel/current row. These are supplied display text, not canonical fields or\nnew DSL expressions. Omitted slots render no empty rows. The `meta` fallback\nremains supported. A marker requires both explicit `statusIndicator: true`\nand an existing `status`; a label-only item never gains an inferred status dot.\nFlat record navigation, question rounds, and future workspace consumers share\nthe same base navigation typography, spacing and selected appearance. Bundle\nCSS is not required. Hierarchical trees retain their separate structure.\nQuestion progress excludes rejected items from answered/completion checks,\nwhile retaining all group records in the displayed total and preserving fixed\nquestion grouping, stable IDs, selection and canonical answers. The original\nWeb App question panel used body round sections, not this sidebar; the shared\nsidebar is an enhanced structure using the original public navigation style,\nnot a claim of one-to-one restoration of a nonexistent original sidebar.\n\n`doc_lifecycle_studio` binds `objects`/`axes`/`actions` sections (validation\nfails loud when one is missing) and renders the fact table (actions × state\naxes, per-cell effects) plus process/derivation/ledger projections derived at\nrender time; unavailable views render disabled with a reason, never hidden.\n`rowview_workbench` renders the residue envelope (below) and requires a\n`source` declaring the add section it owns — the details-envelope schema\ncheck and the renderer are both scoped to that section; a workbench without\n`source` is rejected at compile time.\n\nIn editable mode `bpmn_canvas` edits bidirectionally: each process record's\n`name` and `steps` array (step name, `kind` task/gateway/event, order, add,\nremove) round-trip through the panel Save like any field edit.\n"
|
|
4960
4960
|
}
|
|
@@ -5172,8 +5172,8 @@
|
|
|
5172
5172
|
"sections": [
|
|
5173
5173
|
{
|
|
5174
5174
|
"file": "docs/dsl-spec.md",
|
|
5175
|
-
"line":
|
|
5176
|
-
"endLine":
|
|
5175
|
+
"line": 958,
|
|
5176
|
+
"endLine": 1169,
|
|
5177
5177
|
"heading": "`component` (trusted, extensible library)",
|
|
5178
5178
|
"content": "### `component` (trusted, extensible library)\n\nThe authoritative vocabulary is [`PANEL_COMPONENT_CATALOG`](../packages/core/src/panel-component-catalog.ts).\n`COMPONENT_KINDS`, workspace ownership, source bindings and the generated-panel\nsubset are derived from that one registry; this document is not a second\nvalidation whitelist. Bundle data cannot register executable components.\n\nThe shared library includes basic layouts and controls, question workspaces,\nrecord navigation/editing, diagrams, canvases, artifact readers and previews.\nFull-height workspace components preserve scroll and navigation ownership:\n`record_board`, `document_workspace`, `artifact_workspace`, `diagram_workspace`,\n`canvas_workspace`, `preview_workspace` and `navigation_workspace` expose their\nbehavior through explicit data bindings rather than Kit names. These are reusable\ncapabilities, not a guarantee that every record schema fits every workspace.\n\n`record_board.board.detail_sources` can embed exactly one `record_workspace`\nunder the selected card. Each `{section, reference}` binding declares an unordered\ndirect record collection and a readonly `record_select` back to the board's\nparent section. The child workspace sources must belong to those bindings.\nOwner and child storage paths cannot alias or overlap. The renderer filters\nchildren by the selected parent, binds new records to it, and merges hidden\nsibling records back into canonical updates. It refuses sibling-id replacement,\nreparenting and writes outside these collections. This is a view projection,\nnot a second stored copy; it does not support independently ordered child maps,\nnested `fields_path` records or artifact staging in this first composition slice.\nOrdinary `detail_sections` retain their existing same-record nested-form meaning.\n\n`record_board` uses full-width cards and a workspace-covering overview. Optional\n`board.group` binds a real grouping field. When omitted, the sidebar lists records\ndirectly, cards have no artificial group heading, and the overview connects the\nroot directly to records. Do not bind long summaries merely to satisfy grouping;\nthis projection never adds a grouping field to canonical records.\nSidebar selection scrolls to a card; it does not start editing. Description and\nbadge drafts have explicit Save/Cancel, while rejected records remain inspectable\nwithout granting edit access. Optional `board.id_field` binds a declared visible,\nreadonly `text` field and displays its existing string beside the card title and\nat the top of cover details. Inline details retain the same card header. It does\nnot add an ID editor, generate a fallback ID or write state; omission retains the\nexisting title-only presentation. `board.detail_fields` restricts the parent fields\nshown in the detail fold, and `details_title` localizes its heading. Optional nested\ndimensions can be added or removed without replacing unrelated record fields.\n`board.detail_fields_mode: fixed` instead shows every declared nested input and\nremoves dimension-level add/delete controls; collection item add/delete still\nuses its usual editor. Fields remain schema-optional, including empty inputs.\nViewing does not insert missing strings/maps. Omitted/`on_demand` retains the\nexisting optional-dimension behavior. This option grants no new write authority.\n\n`record_workspace.workspace_view: switch` puts the first child canvas over the\nwhole workspace. The edge action opens it, and the return action or a node's\ndetails action returns to the selected record. It does not add form/canvas tabs\nto the sidebar. Covered content stays mounted and inert to preserve selection,\ndrafts and the graph viewport without allowing hidden controls to receive input.\n\n`record_related_editor.record_table` is an authored-only table presentation of\nthe same child collection, not a conversion to a `rows` array. Its finite\n`columns: [{fields: [field_key, ...], label?: string}]` groups existing field\neditors into cells. Every non-hidden field declared for that child section must\nappear exactly once; hidden/foreign/duplicate bindings and unknown column keys\nare rejected. Column labels default to the first field's label and use the usual\nlocale resolution. A cell retains field visibility, help, requiredness, custom\nconditions and existing edit/derived-field rules. Record creation still binds\nthe selected parent, deletion preserves the normal section cleanup rules, and\n`inherit_from_graph` tables remain source-linked and read-only. The shared table\nwrapper owns horizontal scrolling at narrow widths. This does not promote the\ncomponent or this declaration to generated A2UI.\n\nAn authored graph hierarchy with `max_parents: 1` may opt into\n`parent_control: header`. The existing single-parent selector then sits beside\nthe selected record's form title, rather than above the whole inspector. It\nstill updates the same relation edge, rejects cycles, retains the source-record\nnavigation and shows the actual parent in read-only mode. Omission preserves\nthe prior inspector presentation; neither view creates an extra parent field.\n\n`diagram_workspace.diagram.detail_rows` groups declared read-only fields into\nresponsive fact cards. `chip_fields` selects string-list fields rendered as tags;\n`detail_hint_fields` supplies the populated field labels for the details action.\n`tags` maps declared enum fields to labels and finite semantic tones. These are\npresentation declarations, not new edit rights or storage. Diagram details cover\nonly the content pane; the navigator remains available. Leaving an edited diagram\nstill requires successful serialization through the existing save barrier.\n\n`diagram_workspace.diagram.label_source` can read a declared label from another\nsection bound to the same record collection. The optional `inspector` keeps a\ncontext editor alongside the BPMN canvas: `process_sections` edit the selected\nprocess; `nodes` binds `source`, `process_field`, `element_field`, `label_field`\nand same-collection `sections`. Optional `related` groups use a process reference\nand an optional `node_field`; `advanced: true` starts the group collapsed.\nReferences must be declared `record_select` fields targeting the corresponding\ncollection. Clicking an element resolves its exact ID within the selected\nprocess only; absent or duplicate bindings do not guess a record. Existing field\nedit permissions and the atomic artifact save barrier remain authoritative.\nThis is contextual navigation, not automatic synchronization of BPMN structure\nand business facts; authors must explain how structural changes are reconciled.\n\nFor an exact component contract and on-demand local type declarations, use the\nauthoring inspector from the repository root:\n\n```sh\nnode .agents/skills/design-bundle-creator/scripts/inspect-panel-component.mjs . navigation_workspace --type ComponentNode.navigation_map.edges\n```\n\nUse the [component extension contract](a2ui-component-catalog-contract.md) when\nadding a component: catalog, validation, renderer, styles, edit boundaries,\ntests and authoring guidance must agree. Trusted runtime additions are possible;\nunknown component names in a manifest are rejected.\n\nAcceptance of a component name alone does not establish rendering fidelity,\neditable lifecycle support, or compatibility with every host; those require\nthe component's binding contract and actual runtime verification.\n\nPredefined DSL and A2UI-derived panels share this library, but generated panels\nmay use only the subset with an implemented generation/edit-authority contract.\nAn authored workspace is not automatically promoted into that subset.\nSupported generated results can be deterministically retained as DSL; unsupported\ncapabilities must fail explicitly, never disappear during conversion. This is\nnot an arbitrary bidirectional A2UI protocol converter.\n\n`question_list` is the standard controlled question interaction. Each source\nrecord uses `prompt`, optional `note`, `kind` (`text | single | multiple`),\noptional `choices[]` (`value`, `label`, `recommended`), `answer`, and optional\n`detail`. Text answers render as one multiline input; an existing text-question\n`detail` remains visible as read-only context rather than becoming a second\nanswer box. Single/multiple answers use accessible choice rows and may edit\n`detail`. Existing read-only context and choice supplements use the same\nlocalized label (without the optional-input suffix in reading mode). Cards\nwith a non-empty `answer` collapse to a readable result and can\nbe reopened for editing. The component writes only the fields exposed by that\ninteraction back to the owning record. It does not invent approval state, and an\nempty answer remains unanswered even when `detail` contains context. Native\nproviders may explicitly extend answer-state semantics for attachments, and\nmay add rounds or rejection around this base contract without making those\nextensions mandatory for other Kits.\n\nAuthored `question_list`, `question_rounds`, and `question_workspace` may declare\n`card_groups` with a unique `id`, `title`, and ordered `question_ids`. Members\nmust be contiguous in the existing record order and, for round workspaces, stay\nwithin one round. Invalid groups fall back to ordinary cards with a diagnostic;\ngrouping never reorders canonical records. Generated-origin Panels reject this\nauthored extension.\n\nEach group may declare a `presentation` object containing only optional boolean\n`always_expanded`, `show_detail`, and `show_attachments` properties. These select\nshared component behavior, not Bundle-specific styling. Omission preserves the\nusual collapse, detail, and attachment controls. Hiding a control preserves its\ncanonical data; keeping a card expanded does not grant editing permission.\nRead-only, disabled, protected, historical and rejection guards still apply.\n\n`question_workspace` composes the same question cards with the standard\n`panel_workspace` navigation shell. It groups records by optional numeric\n`round`, shows answer progress, and keeps only the selected group in the main\npane; records without a round form one current group. Its optional\n`description` is rendered through the shared sticky workspace Tip Bar above\nthe main content, never squeezed into the navigation sidebar. `question_rounds` is the\nbackward-compatible alias for this workspace behavior. Optional\n`multimodal_answer[]` entries use the Web App-compatible local reference shape\n(`type`, `file_md5`, `filename`, `mime_type`, `size_bytes`, `artifact_file`).\nThe client keeps pending bytes in a reserved browser-only transport, strips it\nbefore schema validation, and atomically saves only files still referenced by\ncanonical state. The transport is framework state, never a Bundle field.\n\nAuthored `question_workspace` / `question_rounds` nodes may explicitly set\n`question_policy.allow_choice_actions: true`. Expanded editable dynamic single\ncards offer “Switch to multiple choice”; multiple cards offer “Select all” /\n“Deselect all”. Omission or `false` preserves the existing controls. The shared\nruntime owns these actions and their localized styling, not Bundle CSS or an\nauthor-supplied `renderActions` callback. Switching changes only `kind` to\n`multiple`, preserving the exact answer bytes and keeping the editor open.\nSelect-all writes choice values in declared order through the existing\ncomma-separated `answer` contract; deselect-all writes an empty answer. Neither\naction changes detail, attachments, identity, choices or round. Records declared\nin `first_round_ids` are the fixed first-round configuration and do not receive\nthese actions; `protected_ids` still controls rejection only. Read-only,\ndisabled, rejected and read-only historical cards cannot invoke the actions.\nGenerated-origin/A2UI auto Panels reject this configuration, even when `false`;\ntheir existing answer/detail-only write authority and protected `kind` remain\nunchanged. Converting a generated view into an authored reusable panel does not\nsilently grant this capability: the author must opt in under the static contract.\n\n`panel_workspace` is the reusable panel-internal left navigation + main content\nlayout. It standardizes containment, scroll ownership and narrow-panel fallback;\nit does not define domain records or selection semantics. Use it rather than\ncopying a Kit-specific two-column shell.\n\nThe shared runtime `PanelWorkspaceNavigation` accepts optional per-item\n`description`, `supporting`, and `statusLabel` display slots alongside the\nlabel/current row. These are supplied display text, not canonical fields or\nnew DSL expressions. Omitted slots render no empty rows. The `meta` fallback\nremains supported. A marker requires both explicit `statusIndicator: true`\nand an existing `status`; a label-only item never gains an inferred status dot.\nFlat record navigation, question rounds, and future workspace consumers share\nthe same base navigation typography, spacing and selected appearance. Bundle\nCSS is not required. Hierarchical trees retain their separate structure.\nQuestion progress excludes rejected items from answered/completion checks,\nwhile retaining all group records in the displayed total and preserving fixed\nquestion grouping, stable IDs, selection and canonical answers. The original\nWeb App question panel used body round sections, not this sidebar; the shared\nsidebar is an enhanced structure using the original public navigation style,\nnot a claim of one-to-one restoration of a nonexistent original sidebar.\n\n`doc_lifecycle_studio` binds `objects`/`axes`/`actions` sections (validation\nfails loud when one is missing) and renders the fact table (actions × state\naxes, per-cell effects) plus process/derivation/ledger projections derived at\nrender time; unavailable views render disabled with a reason, never hidden.\n`rowview_workbench` renders the residue envelope (below) and requires a\n`source` declaring the add section it owns — the details-envelope schema\ncheck and the renderer are both scoped to that section; a workbench without\n`source` is rejected at compile time.\n\nIn editable mode `bpmn_canvas` edits bidirectionally: each process record's\n`name` and `steps` array (step name, `kind` task/gateway/event, order, add,\nremove) round-trip through the panel Save like any field edit.\n"
|
|
5179
5179
|
}
|
|
@@ -5287,8 +5287,8 @@
|
|
|
5287
5287
|
"sections": [
|
|
5288
5288
|
{
|
|
5289
5289
|
"file": "docs/dsl-spec.md",
|
|
5290
|
-
"line":
|
|
5291
|
-
"endLine":
|
|
5290
|
+
"line": 958,
|
|
5291
|
+
"endLine": 1169,
|
|
5292
5292
|
"heading": "`component` (trusted, extensible library)",
|
|
5293
5293
|
"content": "### `component` (trusted, extensible library)\n\nThe authoritative vocabulary is [`PANEL_COMPONENT_CATALOG`](../packages/core/src/panel-component-catalog.ts).\n`COMPONENT_KINDS`, workspace ownership, source bindings and the generated-panel\nsubset are derived from that one registry; this document is not a second\nvalidation whitelist. Bundle data cannot register executable components.\n\nThe shared library includes basic layouts and controls, question workspaces,\nrecord navigation/editing, diagrams, canvases, artifact readers and previews.\nFull-height workspace components preserve scroll and navigation ownership:\n`record_board`, `document_workspace`, `artifact_workspace`, `diagram_workspace`,\n`canvas_workspace`, `preview_workspace` and `navigation_workspace` expose their\nbehavior through explicit data bindings rather than Kit names. These are reusable\ncapabilities, not a guarantee that every record schema fits every workspace.\n\n`record_board.board.detail_sources` can embed exactly one `record_workspace`\nunder the selected card. Each `{section, reference}` binding declares an unordered\ndirect record collection and a readonly `record_select` back to the board's\nparent section. The child workspace sources must belong to those bindings.\nOwner and child storage paths cannot alias or overlap. The renderer filters\nchildren by the selected parent, binds new records to it, and merges hidden\nsibling records back into canonical updates. It refuses sibling-id replacement,\nreparenting and writes outside these collections. This is a view projection,\nnot a second stored copy; it does not support independently ordered child maps,\nnested `fields_path` records or artifact staging in this first composition slice.\nOrdinary `detail_sections` retain their existing same-record nested-form meaning.\n\n`record_board` uses full-width cards and a workspace-covering overview. Optional\n`board.group` binds a real grouping field. When omitted, the sidebar lists records\ndirectly, cards have no artificial group heading, and the overview connects the\nroot directly to records. Do not bind long summaries merely to satisfy grouping;\nthis projection never adds a grouping field to canonical records.\nSidebar selection scrolls to a card; it does not start editing. Description and\nbadge drafts have explicit Save/Cancel, while rejected records remain inspectable\nwithout granting edit access. Optional `board.id_field` binds a declared visible,\nreadonly `text` field and displays its existing string beside the card title and\nat the top of cover details. Inline details retain the same card header. It does\nnot add an ID editor, generate a fallback ID or write state; omission retains the\nexisting title-only presentation. `board.detail_fields` restricts the parent fields\nshown in the detail fold, and `details_title` localizes its heading. Optional nested\ndimensions can be added or removed without replacing unrelated record fields.\n`board.detail_fields_mode: fixed` instead shows every declared nested input and\nremoves dimension-level add/delete controls; collection item add/delete still\nuses its usual editor. Fields remain schema-optional, including empty inputs.\nViewing does not insert missing strings/maps. Omitted/`on_demand` retains the\nexisting optional-dimension behavior. This option grants no new write authority.\n\n`record_workspace.workspace_view: switch` puts the first child canvas over the\nwhole workspace. The edge action opens it, and the return action or a node's\ndetails action returns to the selected record. It does not add form/canvas tabs\nto the sidebar. Covered content stays mounted and inert to preserve selection,\ndrafts and the graph viewport without allowing hidden controls to receive input.\n\n`record_related_editor.record_table` is an authored-only table presentation of\nthe same child collection, not a conversion to a `rows` array. Its finite\n`columns: [{fields: [field_key, ...], label?: string}]` groups existing field\neditors into cells. Every non-hidden field declared for that child section must\nappear exactly once; hidden/foreign/duplicate bindings and unknown column keys\nare rejected. Column labels default to the first field's label and use the usual\nlocale resolution. A cell retains field visibility, help, requiredness, custom\nconditions and existing edit/derived-field rules. Record creation still binds\nthe selected parent, deletion preserves the normal section cleanup rules, and\n`inherit_from_graph` tables remain source-linked and read-only. The shared table\nwrapper owns horizontal scrolling at narrow widths. This does not promote the\ncomponent or this declaration to generated A2UI.\n\nAn authored graph hierarchy with `max_parents: 1` may opt into\n`parent_control: header`. The existing single-parent selector then sits beside\nthe selected record's form title, rather than above the whole inspector. It\nstill updates the same relation edge, rejects cycles, retains the source-record\nnavigation and shows the actual parent in read-only mode. Omission preserves\nthe prior inspector presentation; neither view creates an extra parent field.\n\n`diagram_workspace.diagram.detail_rows` groups declared read-only fields into\nresponsive fact cards. `chip_fields` selects string-list fields rendered as tags;\n`detail_hint_fields` supplies the populated field labels for the details action.\n`tags` maps declared enum fields to labels and finite semantic tones. These are\npresentation declarations, not new edit rights or storage. Diagram details cover\nonly the content pane; the navigator remains available. Leaving an edited diagram\nstill requires successful serialization through the existing save barrier.\n\n`diagram_workspace.diagram.label_source` can read a declared label from another\nsection bound to the same record collection. The optional `inspector` keeps a\ncontext editor alongside the BPMN canvas: `process_sections` edit the selected\nprocess; `nodes` binds `source`, `process_field`, `element_field`, `label_field`\nand same-collection `sections`. Optional `related` groups use a process reference\nand an optional `node_field`; `advanced: true` starts the group collapsed.\nReferences must be declared `record_select` fields targeting the corresponding\ncollection. Clicking an element resolves its exact ID within the selected\nprocess only; absent or duplicate bindings do not guess a record. Existing field\nedit permissions and the atomic artifact save barrier remain authoritative.\nThis is contextual navigation, not automatic synchronization of BPMN structure\nand business facts; authors must explain how structural changes are reconciled.\n\nFor an exact component contract and on-demand local type declarations, use the\nauthoring inspector from the repository root:\n\n```sh\nnode .agents/skills/design-bundle-creator/scripts/inspect-panel-component.mjs . navigation_workspace --type ComponentNode.navigation_map.edges\n```\n\nUse the [component extension contract](a2ui-component-catalog-contract.md) when\nadding a component: catalog, validation, renderer, styles, edit boundaries,\ntests and authoring guidance must agree. Trusted runtime additions are possible;\nunknown component names in a manifest are rejected.\n\nAcceptance of a component name alone does not establish rendering fidelity,\neditable lifecycle support, or compatibility with every host; those require\nthe component's binding contract and actual runtime verification.\n\nPredefined DSL and A2UI-derived panels share this library, but generated panels\nmay use only the subset with an implemented generation/edit-authority contract.\nAn authored workspace is not automatically promoted into that subset.\nSupported generated results can be deterministically retained as DSL; unsupported\ncapabilities must fail explicitly, never disappear during conversion. This is\nnot an arbitrary bidirectional A2UI protocol converter.\n\n`question_list` is the standard controlled question interaction. Each source\nrecord uses `prompt`, optional `note`, `kind` (`text | single | multiple`),\noptional `choices[]` (`value`, `label`, `recommended`), `answer`, and optional\n`detail`. Text answers render as one multiline input; an existing text-question\n`detail` remains visible as read-only context rather than becoming a second\nanswer box. Single/multiple answers use accessible choice rows and may edit\n`detail`. Existing read-only context and choice supplements use the same\nlocalized label (without the optional-input suffix in reading mode). Cards\nwith a non-empty `answer` collapse to a readable result and can\nbe reopened for editing. The component writes only the fields exposed by that\ninteraction back to the owning record. It does not invent approval state, and an\nempty answer remains unanswered even when `detail` contains context. Native\nproviders may explicitly extend answer-state semantics for attachments, and\nmay add rounds or rejection around this base contract without making those\nextensions mandatory for other Kits.\n\nAuthored `question_list`, `question_rounds`, and `question_workspace` may declare\n`card_groups` with a unique `id`, `title`, and ordered `question_ids`. Members\nmust be contiguous in the existing record order and, for round workspaces, stay\nwithin one round. Invalid groups fall back to ordinary cards with a diagnostic;\ngrouping never reorders canonical records. Generated-origin Panels reject this\nauthored extension.\n\nEach group may declare a `presentation` object containing only optional boolean\n`always_expanded`, `show_detail`, and `show_attachments` properties. These select\nshared component behavior, not Bundle-specific styling. Omission preserves the\nusual collapse, detail, and attachment controls. Hiding a control preserves its\ncanonical data; keeping a card expanded does not grant editing permission.\nRead-only, disabled, protected, historical and rejection guards still apply.\n\n`question_workspace` composes the same question cards with the standard\n`panel_workspace` navigation shell. It groups records by optional numeric\n`round`, shows answer progress, and keeps only the selected group in the main\npane; records without a round form one current group. Its optional\n`description` is rendered through the shared sticky workspace Tip Bar above\nthe main content, never squeezed into the navigation sidebar. `question_rounds` is the\nbackward-compatible alias for this workspace behavior. Optional\n`multimodal_answer[]` entries use the Web App-compatible local reference shape\n(`type`, `file_md5`, `filename`, `mime_type`, `size_bytes`, `artifact_file`).\nThe client keeps pending bytes in a reserved browser-only transport, strips it\nbefore schema validation, and atomically saves only files still referenced by\ncanonical state. The transport is framework state, never a Bundle field.\n\nAuthored `question_workspace` / `question_rounds` nodes may explicitly set\n`question_policy.allow_choice_actions: true`. Expanded editable dynamic single\ncards offer “Switch to multiple choice”; multiple cards offer “Select all” /\n“Deselect all”. Omission or `false` preserves the existing controls. The shared\nruntime owns these actions and their localized styling, not Bundle CSS or an\nauthor-supplied `renderActions` callback. Switching changes only `kind` to\n`multiple`, preserving the exact answer bytes and keeping the editor open.\nSelect-all writes choice values in declared order through the existing\ncomma-separated `answer` contract; deselect-all writes an empty answer. Neither\naction changes detail, attachments, identity, choices or round. Records declared\nin `first_round_ids` are the fixed first-round configuration and do not receive\nthese actions; `protected_ids` still controls rejection only. Read-only,\ndisabled, rejected and read-only historical cards cannot invoke the actions.\nGenerated-origin/A2UI auto Panels reject this configuration, even when `false`;\ntheir existing answer/detail-only write authority and protected `kind` remain\nunchanged. Converting a generated view into an authored reusable panel does not\nsilently grant this capability: the author must opt in under the static contract.\n\n`panel_workspace` is the reusable panel-internal left navigation + main content\nlayout. It standardizes containment, scroll ownership and narrow-panel fallback;\nit does not define domain records or selection semantics. Use it rather than\ncopying a Kit-specific two-column shell.\n\nThe shared runtime `PanelWorkspaceNavigation` accepts optional per-item\n`description`, `supporting`, and `statusLabel` display slots alongside the\nlabel/current row. These are supplied display text, not canonical fields or\nnew DSL expressions. Omitted slots render no empty rows. The `meta` fallback\nremains supported. A marker requires both explicit `statusIndicator: true`\nand an existing `status`; a label-only item never gains an inferred status dot.\nFlat record navigation, question rounds, and future workspace consumers share\nthe same base navigation typography, spacing and selected appearance. Bundle\nCSS is not required. Hierarchical trees retain their separate structure.\nQuestion progress excludes rejected items from answered/completion checks,\nwhile retaining all group records in the displayed total and preserving fixed\nquestion grouping, stable IDs, selection and canonical answers. The original\nWeb App question panel used body round sections, not this sidebar; the shared\nsidebar is an enhanced structure using the original public navigation style,\nnot a claim of one-to-one restoration of a nonexistent original sidebar.\n\n`doc_lifecycle_studio` binds `objects`/`axes`/`actions` sections (validation\nfails loud when one is missing) and renders the fact table (actions × state\naxes, per-cell effects) plus process/derivation/ledger projections derived at\nrender time; unavailable views render disabled with a reason, never hidden.\n`rowview_workbench` renders the residue envelope (below) and requires a\n`source` declaring the add section it owns — the details-envelope schema\ncheck and the renderer are both scoped to that section; a workbench without\n`source` is rejected at compile time.\n\nIn editable mode `bpmn_canvas` edits bidirectionally: each process record's\n`name` and `steps` array (step name, `kind` task/gateway/event, order, add,\nremove) round-trip through the panel Save like any field edit.\n"
|
|
5294
5294
|
}
|
|
@@ -5419,8 +5419,8 @@
|
|
|
5419
5419
|
"sections": [
|
|
5420
5420
|
{
|
|
5421
5421
|
"file": "docs/dsl-spec.md",
|
|
5422
|
-
"line":
|
|
5423
|
-
"endLine":
|
|
5422
|
+
"line": 958,
|
|
5423
|
+
"endLine": 1169,
|
|
5424
5424
|
"heading": "`component` (trusted, extensible library)",
|
|
5425
5425
|
"content": "### `component` (trusted, extensible library)\n\nThe authoritative vocabulary is [`PANEL_COMPONENT_CATALOG`](../packages/core/src/panel-component-catalog.ts).\n`COMPONENT_KINDS`, workspace ownership, source bindings and the generated-panel\nsubset are derived from that one registry; this document is not a second\nvalidation whitelist. Bundle data cannot register executable components.\n\nThe shared library includes basic layouts and controls, question workspaces,\nrecord navigation/editing, diagrams, canvases, artifact readers and previews.\nFull-height workspace components preserve scroll and navigation ownership:\n`record_board`, `document_workspace`, `artifact_workspace`, `diagram_workspace`,\n`canvas_workspace`, `preview_workspace` and `navigation_workspace` expose their\nbehavior through explicit data bindings rather than Kit names. These are reusable\ncapabilities, not a guarantee that every record schema fits every workspace.\n\n`record_board.board.detail_sources` can embed exactly one `record_workspace`\nunder the selected card. Each `{section, reference}` binding declares an unordered\ndirect record collection and a readonly `record_select` back to the board's\nparent section. The child workspace sources must belong to those bindings.\nOwner and child storage paths cannot alias or overlap. The renderer filters\nchildren by the selected parent, binds new records to it, and merges hidden\nsibling records back into canonical updates. It refuses sibling-id replacement,\nreparenting and writes outside these collections. This is a view projection,\nnot a second stored copy; it does not support independently ordered child maps,\nnested `fields_path` records or artifact staging in this first composition slice.\nOrdinary `detail_sections` retain their existing same-record nested-form meaning.\n\n`record_board` uses full-width cards and a workspace-covering overview. Optional\n`board.group` binds a real grouping field. When omitted, the sidebar lists records\ndirectly, cards have no artificial group heading, and the overview connects the\nroot directly to records. Do not bind long summaries merely to satisfy grouping;\nthis projection never adds a grouping field to canonical records.\nSidebar selection scrolls to a card; it does not start editing. Description and\nbadge drafts have explicit Save/Cancel, while rejected records remain inspectable\nwithout granting edit access. Optional `board.id_field` binds a declared visible,\nreadonly `text` field and displays its existing string beside the card title and\nat the top of cover details. Inline details retain the same card header. It does\nnot add an ID editor, generate a fallback ID or write state; omission retains the\nexisting title-only presentation. `board.detail_fields` restricts the parent fields\nshown in the detail fold, and `details_title` localizes its heading. Optional nested\ndimensions can be added or removed without replacing unrelated record fields.\n`board.detail_fields_mode: fixed` instead shows every declared nested input and\nremoves dimension-level add/delete controls; collection item add/delete still\nuses its usual editor. Fields remain schema-optional, including empty inputs.\nViewing does not insert missing strings/maps. Omitted/`on_demand` retains the\nexisting optional-dimension behavior. This option grants no new write authority.\n\n`record_workspace.workspace_view: switch` puts the first child canvas over the\nwhole workspace. The edge action opens it, and the return action or a node's\ndetails action returns to the selected record. It does not add form/canvas tabs\nto the sidebar. Covered content stays mounted and inert to preserve selection,\ndrafts and the graph viewport without allowing hidden controls to receive input.\n\n`record_related_editor.record_table` is an authored-only table presentation of\nthe same child collection, not a conversion to a `rows` array. Its finite\n`columns: [{fields: [field_key, ...], label?: string}]` groups existing field\neditors into cells. Every non-hidden field declared for that child section must\nappear exactly once; hidden/foreign/duplicate bindings and unknown column keys\nare rejected. Column labels default to the first field's label and use the usual\nlocale resolution. A cell retains field visibility, help, requiredness, custom\nconditions and existing edit/derived-field rules. Record creation still binds\nthe selected parent, deletion preserves the normal section cleanup rules, and\n`inherit_from_graph` tables remain source-linked and read-only. The shared table\nwrapper owns horizontal scrolling at narrow widths. This does not promote the\ncomponent or this declaration to generated A2UI.\n\nAn authored graph hierarchy with `max_parents: 1` may opt into\n`parent_control: header`. The existing single-parent selector then sits beside\nthe selected record's form title, rather than above the whole inspector. It\nstill updates the same relation edge, rejects cycles, retains the source-record\nnavigation and shows the actual parent in read-only mode. Omission preserves\nthe prior inspector presentation; neither view creates an extra parent field.\n\n`diagram_workspace.diagram.detail_rows` groups declared read-only fields into\nresponsive fact cards. `chip_fields` selects string-list fields rendered as tags;\n`detail_hint_fields` supplies the populated field labels for the details action.\n`tags` maps declared enum fields to labels and finite semantic tones. These are\npresentation declarations, not new edit rights or storage. Diagram details cover\nonly the content pane; the navigator remains available. Leaving an edited diagram\nstill requires successful serialization through the existing save barrier.\n\n`diagram_workspace.diagram.label_source` can read a declared label from another\nsection bound to the same record collection. The optional `inspector` keeps a\ncontext editor alongside the BPMN canvas: `process_sections` edit the selected\nprocess; `nodes` binds `source`, `process_field`, `element_field`, `label_field`\nand same-collection `sections`. Optional `related` groups use a process reference\nand an optional `node_field`; `advanced: true` starts the group collapsed.\nReferences must be declared `record_select` fields targeting the corresponding\ncollection. Clicking an element resolves its exact ID within the selected\nprocess only; absent or duplicate bindings do not guess a record. Existing field\nedit permissions and the atomic artifact save barrier remain authoritative.\nThis is contextual navigation, not automatic synchronization of BPMN structure\nand business facts; authors must explain how structural changes are reconciled.\n\nFor an exact component contract and on-demand local type declarations, use the\nauthoring inspector from the repository root:\n\n```sh\nnode .agents/skills/design-bundle-creator/scripts/inspect-panel-component.mjs . navigation_workspace --type ComponentNode.navigation_map.edges\n```\n\nUse the [component extension contract](a2ui-component-catalog-contract.md) when\nadding a component: catalog, validation, renderer, styles, edit boundaries,\ntests and authoring guidance must agree. Trusted runtime additions are possible;\nunknown component names in a manifest are rejected.\n\nAcceptance of a component name alone does not establish rendering fidelity,\neditable lifecycle support, or compatibility with every host; those require\nthe component's binding contract and actual runtime verification.\n\nPredefined DSL and A2UI-derived panels share this library, but generated panels\nmay use only the subset with an implemented generation/edit-authority contract.\nAn authored workspace is not automatically promoted into that subset.\nSupported generated results can be deterministically retained as DSL; unsupported\ncapabilities must fail explicitly, never disappear during conversion. This is\nnot an arbitrary bidirectional A2UI protocol converter.\n\n`question_list` is the standard controlled question interaction. Each source\nrecord uses `prompt`, optional `note`, `kind` (`text | single | multiple`),\noptional `choices[]` (`value`, `label`, `recommended`), `answer`, and optional\n`detail`. Text answers render as one multiline input; an existing text-question\n`detail` remains visible as read-only context rather than becoming a second\nanswer box. Single/multiple answers use accessible choice rows and may edit\n`detail`. Existing read-only context and choice supplements use the same\nlocalized label (without the optional-input suffix in reading mode). Cards\nwith a non-empty `answer` collapse to a readable result and can\nbe reopened for editing. The component writes only the fields exposed by that\ninteraction back to the owning record. It does not invent approval state, and an\nempty answer remains unanswered even when `detail` contains context. Native\nproviders may explicitly extend answer-state semantics for attachments, and\nmay add rounds or rejection around this base contract without making those\nextensions mandatory for other Kits.\n\nAuthored `question_list`, `question_rounds`, and `question_workspace` may declare\n`card_groups` with a unique `id`, `title`, and ordered `question_ids`. Members\nmust be contiguous in the existing record order and, for round workspaces, stay\nwithin one round. Invalid groups fall back to ordinary cards with a diagnostic;\ngrouping never reorders canonical records. Generated-origin Panels reject this\nauthored extension.\n\nEach group may declare a `presentation` object containing only optional boolean\n`always_expanded`, `show_detail`, and `show_attachments` properties. These select\nshared component behavior, not Bundle-specific styling. Omission preserves the\nusual collapse, detail, and attachment controls. Hiding a control preserves its\ncanonical data; keeping a card expanded does not grant editing permission.\nRead-only, disabled, protected, historical and rejection guards still apply.\n\n`question_workspace` composes the same question cards with the standard\n`panel_workspace` navigation shell. It groups records by optional numeric\n`round`, shows answer progress, and keeps only the selected group in the main\npane; records without a round form one current group. Its optional\n`description` is rendered through the shared sticky workspace Tip Bar above\nthe main content, never squeezed into the navigation sidebar. `question_rounds` is the\nbackward-compatible alias for this workspace behavior. Optional\n`multimodal_answer[]` entries use the Web App-compatible local reference shape\n(`type`, `file_md5`, `filename`, `mime_type`, `size_bytes`, `artifact_file`).\nThe client keeps pending bytes in a reserved browser-only transport, strips it\nbefore schema validation, and atomically saves only files still referenced by\ncanonical state. The transport is framework state, never a Bundle field.\n\nAuthored `question_workspace` / `question_rounds` nodes may explicitly set\n`question_policy.allow_choice_actions: true`. Expanded editable dynamic single\ncards offer “Switch to multiple choice”; multiple cards offer “Select all” /\n“Deselect all”. Omission or `false` preserves the existing controls. The shared\nruntime owns these actions and their localized styling, not Bundle CSS or an\nauthor-supplied `renderActions` callback. Switching changes only `kind` to\n`multiple`, preserving the exact answer bytes and keeping the editor open.\nSelect-all writes choice values in declared order through the existing\ncomma-separated `answer` contract; deselect-all writes an empty answer. Neither\naction changes detail, attachments, identity, choices or round. Records declared\nin `first_round_ids` are the fixed first-round configuration and do not receive\nthese actions; `protected_ids` still controls rejection only. Read-only,\ndisabled, rejected and read-only historical cards cannot invoke the actions.\nGenerated-origin/A2UI auto Panels reject this configuration, even when `false`;\ntheir existing answer/detail-only write authority and protected `kind` remain\nunchanged. Converting a generated view into an authored reusable panel does not\nsilently grant this capability: the author must opt in under the static contract.\n\n`panel_workspace` is the reusable panel-internal left navigation + main content\nlayout. It standardizes containment, scroll ownership and narrow-panel fallback;\nit does not define domain records or selection semantics. Use it rather than\ncopying a Kit-specific two-column shell.\n\nThe shared runtime `PanelWorkspaceNavigation` accepts optional per-item\n`description`, `supporting`, and `statusLabel` display slots alongside the\nlabel/current row. These are supplied display text, not canonical fields or\nnew DSL expressions. Omitted slots render no empty rows. The `meta` fallback\nremains supported. A marker requires both explicit `statusIndicator: true`\nand an existing `status`; a label-only item never gains an inferred status dot.\nFlat record navigation, question rounds, and future workspace consumers share\nthe same base navigation typography, spacing and selected appearance. Bundle\nCSS is not required. Hierarchical trees retain their separate structure.\nQuestion progress excludes rejected items from answered/completion checks,\nwhile retaining all group records in the displayed total and preserving fixed\nquestion grouping, stable IDs, selection and canonical answers. The original\nWeb App question panel used body round sections, not this sidebar; the shared\nsidebar is an enhanced structure using the original public navigation style,\nnot a claim of one-to-one restoration of a nonexistent original sidebar.\n\n`doc_lifecycle_studio` binds `objects`/`axes`/`actions` sections (validation\nfails loud when one is missing) and renders the fact table (actions × state\naxes, per-cell effects) plus process/derivation/ledger projections derived at\nrender time; unavailable views render disabled with a reason, never hidden.\n`rowview_workbench` renders the residue envelope (below) and requires a\n`source` declaring the add section it owns — the details-envelope schema\ncheck and the renderer are both scoped to that section; a workbench without\n`source` is rejected at compile time.\n\nIn editable mode `bpmn_canvas` edits bidirectionally: each process record's\n`name` and `steps` array (step name, `kind` task/gateway/event, order, add,\nremove) round-trip through the panel Save like any field edit.\n"
|
|
5426
5426
|
}
|
|
@@ -5577,8 +5577,8 @@
|
|
|
5577
5577
|
"sections": [
|
|
5578
5578
|
{
|
|
5579
5579
|
"file": "docs/dsl-spec.md",
|
|
5580
|
-
"line":
|
|
5581
|
-
"endLine":
|
|
5580
|
+
"line": 958,
|
|
5581
|
+
"endLine": 1169,
|
|
5582
5582
|
"heading": "`component` (trusted, extensible library)",
|
|
5583
5583
|
"content": "### `component` (trusted, extensible library)\n\nThe authoritative vocabulary is [`PANEL_COMPONENT_CATALOG`](../packages/core/src/panel-component-catalog.ts).\n`COMPONENT_KINDS`, workspace ownership, source bindings and the generated-panel\nsubset are derived from that one registry; this document is not a second\nvalidation whitelist. Bundle data cannot register executable components.\n\nThe shared library includes basic layouts and controls, question workspaces,\nrecord navigation/editing, diagrams, canvases, artifact readers and previews.\nFull-height workspace components preserve scroll and navigation ownership:\n`record_board`, `document_workspace`, `artifact_workspace`, `diagram_workspace`,\n`canvas_workspace`, `preview_workspace` and `navigation_workspace` expose their\nbehavior through explicit data bindings rather than Kit names. These are reusable\ncapabilities, not a guarantee that every record schema fits every workspace.\n\n`record_board.board.detail_sources` can embed exactly one `record_workspace`\nunder the selected card. Each `{section, reference}` binding declares an unordered\ndirect record collection and a readonly `record_select` back to the board's\nparent section. The child workspace sources must belong to those bindings.\nOwner and child storage paths cannot alias or overlap. The renderer filters\nchildren by the selected parent, binds new records to it, and merges hidden\nsibling records back into canonical updates. It refuses sibling-id replacement,\nreparenting and writes outside these collections. This is a view projection,\nnot a second stored copy; it does not support independently ordered child maps,\nnested `fields_path` records or artifact staging in this first composition slice.\nOrdinary `detail_sections` retain their existing same-record nested-form meaning.\n\n`record_board` uses full-width cards and a workspace-covering overview. Optional\n`board.group` binds a real grouping field. When omitted, the sidebar lists records\ndirectly, cards have no artificial group heading, and the overview connects the\nroot directly to records. Do not bind long summaries merely to satisfy grouping;\nthis projection never adds a grouping field to canonical records.\nSidebar selection scrolls to a card; it does not start editing. Description and\nbadge drafts have explicit Save/Cancel, while rejected records remain inspectable\nwithout granting edit access. Optional `board.id_field` binds a declared visible,\nreadonly `text` field and displays its existing string beside the card title and\nat the top of cover details. Inline details retain the same card header. It does\nnot add an ID editor, generate a fallback ID or write state; omission retains the\nexisting title-only presentation. `board.detail_fields` restricts the parent fields\nshown in the detail fold, and `details_title` localizes its heading. Optional nested\ndimensions can be added or removed without replacing unrelated record fields.\n`board.detail_fields_mode: fixed` instead shows every declared nested input and\nremoves dimension-level add/delete controls; collection item add/delete still\nuses its usual editor. Fields remain schema-optional, including empty inputs.\nViewing does not insert missing strings/maps. Omitted/`on_demand` retains the\nexisting optional-dimension behavior. This option grants no new write authority.\n\n`record_workspace.workspace_view: switch` puts the first child canvas over the\nwhole workspace. The edge action opens it, and the return action or a node's\ndetails action returns to the selected record. It does not add form/canvas tabs\nto the sidebar. Covered content stays mounted and inert to preserve selection,\ndrafts and the graph viewport without allowing hidden controls to receive input.\n\n`record_related_editor.record_table` is an authored-only table presentation of\nthe same child collection, not a conversion to a `rows` array. Its finite\n`columns: [{fields: [field_key, ...], label?: string}]` groups existing field\neditors into cells. Every non-hidden field declared for that child section must\nappear exactly once; hidden/foreign/duplicate bindings and unknown column keys\nare rejected. Column labels default to the first field's label and use the usual\nlocale resolution. A cell retains field visibility, help, requiredness, custom\nconditions and existing edit/derived-field rules. Record creation still binds\nthe selected parent, deletion preserves the normal section cleanup rules, and\n`inherit_from_graph` tables remain source-linked and read-only. The shared table\nwrapper owns horizontal scrolling at narrow widths. This does not promote the\ncomponent or this declaration to generated A2UI.\n\nAn authored graph hierarchy with `max_parents: 1` may opt into\n`parent_control: header`. The existing single-parent selector then sits beside\nthe selected record's form title, rather than above the whole inspector. It\nstill updates the same relation edge, rejects cycles, retains the source-record\nnavigation and shows the actual parent in read-only mode. Omission preserves\nthe prior inspector presentation; neither view creates an extra parent field.\n\n`diagram_workspace.diagram.detail_rows` groups declared read-only fields into\nresponsive fact cards. `chip_fields` selects string-list fields rendered as tags;\n`detail_hint_fields` supplies the populated field labels for the details action.\n`tags` maps declared enum fields to labels and finite semantic tones. These are\npresentation declarations, not new edit rights or storage. Diagram details cover\nonly the content pane; the navigator remains available. Leaving an edited diagram\nstill requires successful serialization through the existing save barrier.\n\n`diagram_workspace.diagram.label_source` can read a declared label from another\nsection bound to the same record collection. The optional `inspector` keeps a\ncontext editor alongside the BPMN canvas: `process_sections` edit the selected\nprocess; `nodes` binds `source`, `process_field`, `element_field`, `label_field`\nand same-collection `sections`. Optional `related` groups use a process reference\nand an optional `node_field`; `advanced: true` starts the group collapsed.\nReferences must be declared `record_select` fields targeting the corresponding\ncollection. Clicking an element resolves its exact ID within the selected\nprocess only; absent or duplicate bindings do not guess a record. Existing field\nedit permissions and the atomic artifact save barrier remain authoritative.\nThis is contextual navigation, not automatic synchronization of BPMN structure\nand business facts; authors must explain how structural changes are reconciled.\n\nFor an exact component contract and on-demand local type declarations, use the\nauthoring inspector from the repository root:\n\n```sh\nnode .agents/skills/design-bundle-creator/scripts/inspect-panel-component.mjs . navigation_workspace --type ComponentNode.navigation_map.edges\n```\n\nUse the [component extension contract](a2ui-component-catalog-contract.md) when\nadding a component: catalog, validation, renderer, styles, edit boundaries,\ntests and authoring guidance must agree. Trusted runtime additions are possible;\nunknown component names in a manifest are rejected.\n\nAcceptance of a component name alone does not establish rendering fidelity,\neditable lifecycle support, or compatibility with every host; those require\nthe component's binding contract and actual runtime verification.\n\nPredefined DSL and A2UI-derived panels share this library, but generated panels\nmay use only the subset with an implemented generation/edit-authority contract.\nAn authored workspace is not automatically promoted into that subset.\nSupported generated results can be deterministically retained as DSL; unsupported\ncapabilities must fail explicitly, never disappear during conversion. This is\nnot an arbitrary bidirectional A2UI protocol converter.\n\n`question_list` is the standard controlled question interaction. Each source\nrecord uses `prompt`, optional `note`, `kind` (`text | single | multiple`),\noptional `choices[]` (`value`, `label`, `recommended`), `answer`, and optional\n`detail`. Text answers render as one multiline input; an existing text-question\n`detail` remains visible as read-only context rather than becoming a second\nanswer box. Single/multiple answers use accessible choice rows and may edit\n`detail`. Existing read-only context and choice supplements use the same\nlocalized label (without the optional-input suffix in reading mode). Cards\nwith a non-empty `answer` collapse to a readable result and can\nbe reopened for editing. The component writes only the fields exposed by that\ninteraction back to the owning record. It does not invent approval state, and an\nempty answer remains unanswered even when `detail` contains context. Native\nproviders may explicitly extend answer-state semantics for attachments, and\nmay add rounds or rejection around this base contract without making those\nextensions mandatory for other Kits.\n\nAuthored `question_list`, `question_rounds`, and `question_workspace` may declare\n`card_groups` with a unique `id`, `title`, and ordered `question_ids`. Members\nmust be contiguous in the existing record order and, for round workspaces, stay\nwithin one round. Invalid groups fall back to ordinary cards with a diagnostic;\ngrouping never reorders canonical records. Generated-origin Panels reject this\nauthored extension.\n\nEach group may declare a `presentation` object containing only optional boolean\n`always_expanded`, `show_detail`, and `show_attachments` properties. These select\nshared component behavior, not Bundle-specific styling. Omission preserves the\nusual collapse, detail, and attachment controls. Hiding a control preserves its\ncanonical data; keeping a card expanded does not grant editing permission.\nRead-only, disabled, protected, historical and rejection guards still apply.\n\n`question_workspace` composes the same question cards with the standard\n`panel_workspace` navigation shell. It groups records by optional numeric\n`round`, shows answer progress, and keeps only the selected group in the main\npane; records without a round form one current group. Its optional\n`description` is rendered through the shared sticky workspace Tip Bar above\nthe main content, never squeezed into the navigation sidebar. `question_rounds` is the\nbackward-compatible alias for this workspace behavior. Optional\n`multimodal_answer[]` entries use the Web App-compatible local reference shape\n(`type`, `file_md5`, `filename`, `mime_type`, `size_bytes`, `artifact_file`).\nThe client keeps pending bytes in a reserved browser-only transport, strips it\nbefore schema validation, and atomically saves only files still referenced by\ncanonical state. The transport is framework state, never a Bundle field.\n\nAuthored `question_workspace` / `question_rounds` nodes may explicitly set\n`question_policy.allow_choice_actions: true`. Expanded editable dynamic single\ncards offer “Switch to multiple choice”; multiple cards offer “Select all” /\n“Deselect all”. Omission or `false` preserves the existing controls. The shared\nruntime owns these actions and their localized styling, not Bundle CSS or an\nauthor-supplied `renderActions` callback. Switching changes only `kind` to\n`multiple`, preserving the exact answer bytes and keeping the editor open.\nSelect-all writes choice values in declared order through the existing\ncomma-separated `answer` contract; deselect-all writes an empty answer. Neither\naction changes detail, attachments, identity, choices or round. Records declared\nin `first_round_ids` are the fixed first-round configuration and do not receive\nthese actions; `protected_ids` still controls rejection only. Read-only,\ndisabled, rejected and read-only historical cards cannot invoke the actions.\nGenerated-origin/A2UI auto Panels reject this configuration, even when `false`;\ntheir existing answer/detail-only write authority and protected `kind` remain\nunchanged. Converting a generated view into an authored reusable panel does not\nsilently grant this capability: the author must opt in under the static contract.\n\n`panel_workspace` is the reusable panel-internal left navigation + main content\nlayout. It standardizes containment, scroll ownership and narrow-panel fallback;\nit does not define domain records or selection semantics. Use it rather than\ncopying a Kit-specific two-column shell.\n\nThe shared runtime `PanelWorkspaceNavigation` accepts optional per-item\n`description`, `supporting`, and `statusLabel` display slots alongside the\nlabel/current row. These are supplied display text, not canonical fields or\nnew DSL expressions. Omitted slots render no empty rows. The `meta` fallback\nremains supported. A marker requires both explicit `statusIndicator: true`\nand an existing `status`; a label-only item never gains an inferred status dot.\nFlat record navigation, question rounds, and future workspace consumers share\nthe same base navigation typography, spacing and selected appearance. Bundle\nCSS is not required. Hierarchical trees retain their separate structure.\nQuestion progress excludes rejected items from answered/completion checks,\nwhile retaining all group records in the displayed total and preserving fixed\nquestion grouping, stable IDs, selection and canonical answers. The original\nWeb App question panel used body round sections, not this sidebar; the shared\nsidebar is an enhanced structure using the original public navigation style,\nnot a claim of one-to-one restoration of a nonexistent original sidebar.\n\n`doc_lifecycle_studio` binds `objects`/`axes`/`actions` sections (validation\nfails loud when one is missing) and renders the fact table (actions × state\naxes, per-cell effects) plus process/derivation/ledger projections derived at\nrender time; unavailable views render disabled with a reason, never hidden.\n`rowview_workbench` renders the residue envelope (below) and requires a\n`source` declaring the add section it owns — the details-envelope schema\ncheck and the renderer are both scoped to that section; a workbench without\n`source` is rejected at compile time.\n\nIn editable mode `bpmn_canvas` edits bidirectionally: each process record's\n`name` and `steps` array (step name, `kind` task/gateway/event, order, add,\nremove) round-trip through the panel Save like any field edit.\n"
|
|
5584
5584
|
}
|
|
@@ -5775,8 +5775,8 @@
|
|
|
5775
5775
|
"sections": [
|
|
5776
5776
|
{
|
|
5777
5777
|
"file": "docs/dsl-spec.md",
|
|
5778
|
-
"line":
|
|
5779
|
-
"endLine":
|
|
5778
|
+
"line": 958,
|
|
5779
|
+
"endLine": 1169,
|
|
5780
5780
|
"heading": "`component` (trusted, extensible library)",
|
|
5781
5781
|
"content": "### `component` (trusted, extensible library)\n\nThe authoritative vocabulary is [`PANEL_COMPONENT_CATALOG`](../packages/core/src/panel-component-catalog.ts).\n`COMPONENT_KINDS`, workspace ownership, source bindings and the generated-panel\nsubset are derived from that one registry; this document is not a second\nvalidation whitelist. Bundle data cannot register executable components.\n\nThe shared library includes basic layouts and controls, question workspaces,\nrecord navigation/editing, diagrams, canvases, artifact readers and previews.\nFull-height workspace components preserve scroll and navigation ownership:\n`record_board`, `document_workspace`, `artifact_workspace`, `diagram_workspace`,\n`canvas_workspace`, `preview_workspace` and `navigation_workspace` expose their\nbehavior through explicit data bindings rather than Kit names. These are reusable\ncapabilities, not a guarantee that every record schema fits every workspace.\n\n`record_board.board.detail_sources` can embed exactly one `record_workspace`\nunder the selected card. Each `{section, reference}` binding declares an unordered\ndirect record collection and a readonly `record_select` back to the board's\nparent section. The child workspace sources must belong to those bindings.\nOwner and child storage paths cannot alias or overlap. The renderer filters\nchildren by the selected parent, binds new records to it, and merges hidden\nsibling records back into canonical updates. It refuses sibling-id replacement,\nreparenting and writes outside these collections. This is a view projection,\nnot a second stored copy; it does not support independently ordered child maps,\nnested `fields_path` records or artifact staging in this first composition slice.\nOrdinary `detail_sections` retain their existing same-record nested-form meaning.\n\n`record_board` uses full-width cards and a workspace-covering overview. Optional\n`board.group` binds a real grouping field. When omitted, the sidebar lists records\ndirectly, cards have no artificial group heading, and the overview connects the\nroot directly to records. Do not bind long summaries merely to satisfy grouping;\nthis projection never adds a grouping field to canonical records.\nSidebar selection scrolls to a card; it does not start editing. Description and\nbadge drafts have explicit Save/Cancel, while rejected records remain inspectable\nwithout granting edit access. Optional `board.id_field` binds a declared visible,\nreadonly `text` field and displays its existing string beside the card title and\nat the top of cover details. Inline details retain the same card header. It does\nnot add an ID editor, generate a fallback ID or write state; omission retains the\nexisting title-only presentation. `board.detail_fields` restricts the parent fields\nshown in the detail fold, and `details_title` localizes its heading. Optional nested\ndimensions can be added or removed without replacing unrelated record fields.\n`board.detail_fields_mode: fixed` instead shows every declared nested input and\nremoves dimension-level add/delete controls; collection item add/delete still\nuses its usual editor. Fields remain schema-optional, including empty inputs.\nViewing does not insert missing strings/maps. Omitted/`on_demand` retains the\nexisting optional-dimension behavior. This option grants no new write authority.\n\n`record_workspace.workspace_view: switch` puts the first child canvas over the\nwhole workspace. The edge action opens it, and the return action or a node's\ndetails action returns to the selected record. It does not add form/canvas tabs\nto the sidebar. Covered content stays mounted and inert to preserve selection,\ndrafts and the graph viewport without allowing hidden controls to receive input.\n\n`record_related_editor.record_table` is an authored-only table presentation of\nthe same child collection, not a conversion to a `rows` array. Its finite\n`columns: [{fields: [field_key, ...], label?: string}]` groups existing field\neditors into cells. Every non-hidden field declared for that child section must\nappear exactly once; hidden/foreign/duplicate bindings and unknown column keys\nare rejected. Column labels default to the first field's label and use the usual\nlocale resolution. A cell retains field visibility, help, requiredness, custom\nconditions and existing edit/derived-field rules. Record creation still binds\nthe selected parent, deletion preserves the normal section cleanup rules, and\n`inherit_from_graph` tables remain source-linked and read-only. The shared table\nwrapper owns horizontal scrolling at narrow widths. This does not promote the\ncomponent or this declaration to generated A2UI.\n\nAn authored graph hierarchy with `max_parents: 1` may opt into\n`parent_control: header`. The existing single-parent selector then sits beside\nthe selected record's form title, rather than above the whole inspector. It\nstill updates the same relation edge, rejects cycles, retains the source-record\nnavigation and shows the actual parent in read-only mode. Omission preserves\nthe prior inspector presentation; neither view creates an extra parent field.\n\n`diagram_workspace.diagram.detail_rows` groups declared read-only fields into\nresponsive fact cards. `chip_fields` selects string-list fields rendered as tags;\n`detail_hint_fields` supplies the populated field labels for the details action.\n`tags` maps declared enum fields to labels and finite semantic tones. These are\npresentation declarations, not new edit rights or storage. Diagram details cover\nonly the content pane; the navigator remains available. Leaving an edited diagram\nstill requires successful serialization through the existing save barrier.\n\n`diagram_workspace.diagram.label_source` can read a declared label from another\nsection bound to the same record collection. The optional `inspector` keeps a\ncontext editor alongside the BPMN canvas: `process_sections` edit the selected\nprocess; `nodes` binds `source`, `process_field`, `element_field`, `label_field`\nand same-collection `sections`. Optional `related` groups use a process reference\nand an optional `node_field`; `advanced: true` starts the group collapsed.\nReferences must be declared `record_select` fields targeting the corresponding\ncollection. Clicking an element resolves its exact ID within the selected\nprocess only; absent or duplicate bindings do not guess a record. Existing field\nedit permissions and the atomic artifact save barrier remain authoritative.\nThis is contextual navigation, not automatic synchronization of BPMN structure\nand business facts; authors must explain how structural changes are reconciled.\n\nFor an exact component contract and on-demand local type declarations, use the\nauthoring inspector from the repository root:\n\n```sh\nnode .agents/skills/design-bundle-creator/scripts/inspect-panel-component.mjs . navigation_workspace --type ComponentNode.navigation_map.edges\n```\n\nUse the [component extension contract](a2ui-component-catalog-contract.md) when\nadding a component: catalog, validation, renderer, styles, edit boundaries,\ntests and authoring guidance must agree. Trusted runtime additions are possible;\nunknown component names in a manifest are rejected.\n\nAcceptance of a component name alone does not establish rendering fidelity,\neditable lifecycle support, or compatibility with every host; those require\nthe component's binding contract and actual runtime verification.\n\nPredefined DSL and A2UI-derived panels share this library, but generated panels\nmay use only the subset with an implemented generation/edit-authority contract.\nAn authored workspace is not automatically promoted into that subset.\nSupported generated results can be deterministically retained as DSL; unsupported\ncapabilities must fail explicitly, never disappear during conversion. This is\nnot an arbitrary bidirectional A2UI protocol converter.\n\n`question_list` is the standard controlled question interaction. Each source\nrecord uses `prompt`, optional `note`, `kind` (`text | single | multiple`),\noptional `choices[]` (`value`, `label`, `recommended`), `answer`, and optional\n`detail`. Text answers render as one multiline input; an existing text-question\n`detail` remains visible as read-only context rather than becoming a second\nanswer box. Single/multiple answers use accessible choice rows and may edit\n`detail`. Existing read-only context and choice supplements use the same\nlocalized label (without the optional-input suffix in reading mode). Cards\nwith a non-empty `answer` collapse to a readable result and can\nbe reopened for editing. The component writes only the fields exposed by that\ninteraction back to the owning record. It does not invent approval state, and an\nempty answer remains unanswered even when `detail` contains context. Native\nproviders may explicitly extend answer-state semantics for attachments, and\nmay add rounds or rejection around this base contract without making those\nextensions mandatory for other Kits.\n\nAuthored `question_list`, `question_rounds`, and `question_workspace` may declare\n`card_groups` with a unique `id`, `title`, and ordered `question_ids`. Members\nmust be contiguous in the existing record order and, for round workspaces, stay\nwithin one round. Invalid groups fall back to ordinary cards with a diagnostic;\ngrouping never reorders canonical records. Generated-origin Panels reject this\nauthored extension.\n\nEach group may declare a `presentation` object containing only optional boolean\n`always_expanded`, `show_detail`, and `show_attachments` properties. These select\nshared component behavior, not Bundle-specific styling. Omission preserves the\nusual collapse, detail, and attachment controls. Hiding a control preserves its\ncanonical data; keeping a card expanded does not grant editing permission.\nRead-only, disabled, protected, historical and rejection guards still apply.\n\n`question_workspace` composes the same question cards with the standard\n`panel_workspace` navigation shell. It groups records by optional numeric\n`round`, shows answer progress, and keeps only the selected group in the main\npane; records without a round form one current group. Its optional\n`description` is rendered through the shared sticky workspace Tip Bar above\nthe main content, never squeezed into the navigation sidebar. `question_rounds` is the\nbackward-compatible alias for this workspace behavior. Optional\n`multimodal_answer[]` entries use the Web App-compatible local reference shape\n(`type`, `file_md5`, `filename`, `mime_type`, `size_bytes`, `artifact_file`).\nThe client keeps pending bytes in a reserved browser-only transport, strips it\nbefore schema validation, and atomically saves only files still referenced by\ncanonical state. The transport is framework state, never a Bundle field.\n\nAuthored `question_workspace` / `question_rounds` nodes may explicitly set\n`question_policy.allow_choice_actions: true`. Expanded editable dynamic single\ncards offer “Switch to multiple choice”; multiple cards offer “Select all” /\n“Deselect all”. Omission or `false` preserves the existing controls. The shared\nruntime owns these actions and their localized styling, not Bundle CSS or an\nauthor-supplied `renderActions` callback. Switching changes only `kind` to\n`multiple`, preserving the exact answer bytes and keeping the editor open.\nSelect-all writes choice values in declared order through the existing\ncomma-separated `answer` contract; deselect-all writes an empty answer. Neither\naction changes detail, attachments, identity, choices or round. Records declared\nin `first_round_ids` are the fixed first-round configuration and do not receive\nthese actions; `protected_ids` still controls rejection only. Read-only,\ndisabled, rejected and read-only historical cards cannot invoke the actions.\nGenerated-origin/A2UI auto Panels reject this configuration, even when `false`;\ntheir existing answer/detail-only write authority and protected `kind` remain\nunchanged. Converting a generated view into an authored reusable panel does not\nsilently grant this capability: the author must opt in under the static contract.\n\n`panel_workspace` is the reusable panel-internal left navigation + main content\nlayout. It standardizes containment, scroll ownership and narrow-panel fallback;\nit does not define domain records or selection semantics. Use it rather than\ncopying a Kit-specific two-column shell.\n\nThe shared runtime `PanelWorkspaceNavigation` accepts optional per-item\n`description`, `supporting`, and `statusLabel` display slots alongside the\nlabel/current row. These are supplied display text, not canonical fields or\nnew DSL expressions. Omitted slots render no empty rows. The `meta` fallback\nremains supported. A marker requires both explicit `statusIndicator: true`\nand an existing `status`; a label-only item never gains an inferred status dot.\nFlat record navigation, question rounds, and future workspace consumers share\nthe same base navigation typography, spacing and selected appearance. Bundle\nCSS is not required. Hierarchical trees retain their separate structure.\nQuestion progress excludes rejected items from answered/completion checks,\nwhile retaining all group records in the displayed total and preserving fixed\nquestion grouping, stable IDs, selection and canonical answers. The original\nWeb App question panel used body round sections, not this sidebar; the shared\nsidebar is an enhanced structure using the original public navigation style,\nnot a claim of one-to-one restoration of a nonexistent original sidebar.\n\n`doc_lifecycle_studio` binds `objects`/`axes`/`actions` sections (validation\nfails loud when one is missing) and renders the fact table (actions × state\naxes, per-cell effects) plus process/derivation/ledger projections derived at\nrender time; unavailable views render disabled with a reason, never hidden.\n`rowview_workbench` renders the residue envelope (below) and requires a\n`source` declaring the add section it owns — the details-envelope schema\ncheck and the renderer are both scoped to that section; a workbench without\n`source` is rejected at compile time.\n\nIn editable mode `bpmn_canvas` edits bidirectionally: each process record's\n`name` and `steps` array (step name, `kind` task/gateway/event, order, add,\nremove) round-trip through the panel Save like any field edit.\n"
|
|
5782
5782
|
}
|
|
@@ -5997,8 +5997,8 @@
|
|
|
5997
5997
|
"sections": [
|
|
5998
5998
|
{
|
|
5999
5999
|
"file": "docs/dsl-spec.md",
|
|
6000
|
-
"line":
|
|
6001
|
-
"endLine":
|
|
6000
|
+
"line": 958,
|
|
6001
|
+
"endLine": 1169,
|
|
6002
6002
|
"heading": "`component` (trusted, extensible library)",
|
|
6003
6003
|
"content": "### `component` (trusted, extensible library)\n\nThe authoritative vocabulary is [`PANEL_COMPONENT_CATALOG`](../packages/core/src/panel-component-catalog.ts).\n`COMPONENT_KINDS`, workspace ownership, source bindings and the generated-panel\nsubset are derived from that one registry; this document is not a second\nvalidation whitelist. Bundle data cannot register executable components.\n\nThe shared library includes basic layouts and controls, question workspaces,\nrecord navigation/editing, diagrams, canvases, artifact readers and previews.\nFull-height workspace components preserve scroll and navigation ownership:\n`record_board`, `document_workspace`, `artifact_workspace`, `diagram_workspace`,\n`canvas_workspace`, `preview_workspace` and `navigation_workspace` expose their\nbehavior through explicit data bindings rather than Kit names. These are reusable\ncapabilities, not a guarantee that every record schema fits every workspace.\n\n`record_board.board.detail_sources` can embed exactly one `record_workspace`\nunder the selected card. Each `{section, reference}` binding declares an unordered\ndirect record collection and a readonly `record_select` back to the board's\nparent section. The child workspace sources must belong to those bindings.\nOwner and child storage paths cannot alias or overlap. The renderer filters\nchildren by the selected parent, binds new records to it, and merges hidden\nsibling records back into canonical updates. It refuses sibling-id replacement,\nreparenting and writes outside these collections. This is a view projection,\nnot a second stored copy; it does not support independently ordered child maps,\nnested `fields_path` records or artifact staging in this first composition slice.\nOrdinary `detail_sections` retain their existing same-record nested-form meaning.\n\n`record_board` uses full-width cards and a workspace-covering overview. Optional\n`board.group` binds a real grouping field. When omitted, the sidebar lists records\ndirectly, cards have no artificial group heading, and the overview connects the\nroot directly to records. Do not bind long summaries merely to satisfy grouping;\nthis projection never adds a grouping field to canonical records.\nSidebar selection scrolls to a card; it does not start editing. Description and\nbadge drafts have explicit Save/Cancel, while rejected records remain inspectable\nwithout granting edit access. Optional `board.id_field` binds a declared visible,\nreadonly `text` field and displays its existing string beside the card title and\nat the top of cover details. Inline details retain the same card header. It does\nnot add an ID editor, generate a fallback ID or write state; omission retains the\nexisting title-only presentation. `board.detail_fields` restricts the parent fields\nshown in the detail fold, and `details_title` localizes its heading. Optional nested\ndimensions can be added or removed without replacing unrelated record fields.\n`board.detail_fields_mode: fixed` instead shows every declared nested input and\nremoves dimension-level add/delete controls; collection item add/delete still\nuses its usual editor. Fields remain schema-optional, including empty inputs.\nViewing does not insert missing strings/maps. Omitted/`on_demand` retains the\nexisting optional-dimension behavior. This option grants no new write authority.\n\n`record_workspace.workspace_view: switch` puts the first child canvas over the\nwhole workspace. The edge action opens it, and the return action or a node's\ndetails action returns to the selected record. It does not add form/canvas tabs\nto the sidebar. Covered content stays mounted and inert to preserve selection,\ndrafts and the graph viewport without allowing hidden controls to receive input.\n\n`record_related_editor.record_table` is an authored-only table presentation of\nthe same child collection, not a conversion to a `rows` array. Its finite\n`columns: [{fields: [field_key, ...], label?: string}]` groups existing field\neditors into cells. Every non-hidden field declared for that child section must\nappear exactly once; hidden/foreign/duplicate bindings and unknown column keys\nare rejected. Column labels default to the first field's label and use the usual\nlocale resolution. A cell retains field visibility, help, requiredness, custom\nconditions and existing edit/derived-field rules. Record creation still binds\nthe selected parent, deletion preserves the normal section cleanup rules, and\n`inherit_from_graph` tables remain source-linked and read-only. The shared table\nwrapper owns horizontal scrolling at narrow widths. This does not promote the\ncomponent or this declaration to generated A2UI.\n\nAn authored graph hierarchy with `max_parents: 1` may opt into\n`parent_control: header`. The existing single-parent selector then sits beside\nthe selected record's form title, rather than above the whole inspector. It\nstill updates the same relation edge, rejects cycles, retains the source-record\nnavigation and shows the actual parent in read-only mode. Omission preserves\nthe prior inspector presentation; neither view creates an extra parent field.\n\n`diagram_workspace.diagram.detail_rows` groups declared read-only fields into\nresponsive fact cards. `chip_fields` selects string-list fields rendered as tags;\n`detail_hint_fields` supplies the populated field labels for the details action.\n`tags` maps declared enum fields to labels and finite semantic tones. These are\npresentation declarations, not new edit rights or storage. Diagram details cover\nonly the content pane; the navigator remains available. Leaving an edited diagram\nstill requires successful serialization through the existing save barrier.\n\n`diagram_workspace.diagram.label_source` can read a declared label from another\nsection bound to the same record collection. The optional `inspector` keeps a\ncontext editor alongside the BPMN canvas: `process_sections` edit the selected\nprocess; `nodes` binds `source`, `process_field`, `element_field`, `label_field`\nand same-collection `sections`. Optional `related` groups use a process reference\nand an optional `node_field`; `advanced: true` starts the group collapsed.\nReferences must be declared `record_select` fields targeting the corresponding\ncollection. Clicking an element resolves its exact ID within the selected\nprocess only; absent or duplicate bindings do not guess a record. Existing field\nedit permissions and the atomic artifact save barrier remain authoritative.\nThis is contextual navigation, not automatic synchronization of BPMN structure\nand business facts; authors must explain how structural changes are reconciled.\n\nFor an exact component contract and on-demand local type declarations, use the\nauthoring inspector from the repository root:\n\n```sh\nnode .agents/skills/design-bundle-creator/scripts/inspect-panel-component.mjs . navigation_workspace --type ComponentNode.navigation_map.edges\n```\n\nUse the [component extension contract](a2ui-component-catalog-contract.md) when\nadding a component: catalog, validation, renderer, styles, edit boundaries,\ntests and authoring guidance must agree. Trusted runtime additions are possible;\nunknown component names in a manifest are rejected.\n\nAcceptance of a component name alone does not establish rendering fidelity,\neditable lifecycle support, or compatibility with every host; those require\nthe component's binding contract and actual runtime verification.\n\nPredefined DSL and A2UI-derived panels share this library, but generated panels\nmay use only the subset with an implemented generation/edit-authority contract.\nAn authored workspace is not automatically promoted into that subset.\nSupported generated results can be deterministically retained as DSL; unsupported\ncapabilities must fail explicitly, never disappear during conversion. This is\nnot an arbitrary bidirectional A2UI protocol converter.\n\n`question_list` is the standard controlled question interaction. Each source\nrecord uses `prompt`, optional `note`, `kind` (`text | single | multiple`),\noptional `choices[]` (`value`, `label`, `recommended`), `answer`, and optional\n`detail`. Text answers render as one multiline input; an existing text-question\n`detail` remains visible as read-only context rather than becoming a second\nanswer box. Single/multiple answers use accessible choice rows and may edit\n`detail`. Existing read-only context and choice supplements use the same\nlocalized label (without the optional-input suffix in reading mode). Cards\nwith a non-empty `answer` collapse to a readable result and can\nbe reopened for editing. The component writes only the fields exposed by that\ninteraction back to the owning record. It does not invent approval state, and an\nempty answer remains unanswered even when `detail` contains context. Native\nproviders may explicitly extend answer-state semantics for attachments, and\nmay add rounds or rejection around this base contract without making those\nextensions mandatory for other Kits.\n\nAuthored `question_list`, `question_rounds`, and `question_workspace` may declare\n`card_groups` with a unique `id`, `title`, and ordered `question_ids`. Members\nmust be contiguous in the existing record order and, for round workspaces, stay\nwithin one round. Invalid groups fall back to ordinary cards with a diagnostic;\ngrouping never reorders canonical records. Generated-origin Panels reject this\nauthored extension.\n\nEach group may declare a `presentation` object containing only optional boolean\n`always_expanded`, `show_detail`, and `show_attachments` properties. These select\nshared component behavior, not Bundle-specific styling. Omission preserves the\nusual collapse, detail, and attachment controls. Hiding a control preserves its\ncanonical data; keeping a card expanded does not grant editing permission.\nRead-only, disabled, protected, historical and rejection guards still apply.\n\n`question_workspace` composes the same question cards with the standard\n`panel_workspace` navigation shell. It groups records by optional numeric\n`round`, shows answer progress, and keeps only the selected group in the main\npane; records without a round form one current group. Its optional\n`description` is rendered through the shared sticky workspace Tip Bar above\nthe main content, never squeezed into the navigation sidebar. `question_rounds` is the\nbackward-compatible alias for this workspace behavior. Optional\n`multimodal_answer[]` entries use the Web App-compatible local reference shape\n(`type`, `file_md5`, `filename`, `mime_type`, `size_bytes`, `artifact_file`).\nThe client keeps pending bytes in a reserved browser-only transport, strips it\nbefore schema validation, and atomically saves only files still referenced by\ncanonical state. The transport is framework state, never a Bundle field.\n\nAuthored `question_workspace` / `question_rounds` nodes may explicitly set\n`question_policy.allow_choice_actions: true`. Expanded editable dynamic single\ncards offer “Switch to multiple choice”; multiple cards offer “Select all” /\n“Deselect all”. Omission or `false` preserves the existing controls. The shared\nruntime owns these actions and their localized styling, not Bundle CSS or an\nauthor-supplied `renderActions` callback. Switching changes only `kind` to\n`multiple`, preserving the exact answer bytes and keeping the editor open.\nSelect-all writes choice values in declared order through the existing\ncomma-separated `answer` contract; deselect-all writes an empty answer. Neither\naction changes detail, attachments, identity, choices or round. Records declared\nin `first_round_ids` are the fixed first-round configuration and do not receive\nthese actions; `protected_ids` still controls rejection only. Read-only,\ndisabled, rejected and read-only historical cards cannot invoke the actions.\nGenerated-origin/A2UI auto Panels reject this configuration, even when `false`;\ntheir existing answer/detail-only write authority and protected `kind` remain\nunchanged. Converting a generated view into an authored reusable panel does not\nsilently grant this capability: the author must opt in under the static contract.\n\n`panel_workspace` is the reusable panel-internal left navigation + main content\nlayout. It standardizes containment, scroll ownership and narrow-panel fallback;\nit does not define domain records or selection semantics. Use it rather than\ncopying a Kit-specific two-column shell.\n\nThe shared runtime `PanelWorkspaceNavigation` accepts optional per-item\n`description`, `supporting`, and `statusLabel` display slots alongside the\nlabel/current row. These are supplied display text, not canonical fields or\nnew DSL expressions. Omitted slots render no empty rows. The `meta` fallback\nremains supported. A marker requires both explicit `statusIndicator: true`\nand an existing `status`; a label-only item never gains an inferred status dot.\nFlat record navigation, question rounds, and future workspace consumers share\nthe same base navigation typography, spacing and selected appearance. Bundle\nCSS is not required. Hierarchical trees retain their separate structure.\nQuestion progress excludes rejected items from answered/completion checks,\nwhile retaining all group records in the displayed total and preserving fixed\nquestion grouping, stable IDs, selection and canonical answers. The original\nWeb App question panel used body round sections, not this sidebar; the shared\nsidebar is an enhanced structure using the original public navigation style,\nnot a claim of one-to-one restoration of a nonexistent original sidebar.\n\n`doc_lifecycle_studio` binds `objects`/`axes`/`actions` sections (validation\nfails loud when one is missing) and renders the fact table (actions × state\naxes, per-cell effects) plus process/derivation/ledger projections derived at\nrender time; unavailable views render disabled with a reason, never hidden.\n`rowview_workbench` renders the residue envelope (below) and requires a\n`source` declaring the add section it owns — the details-envelope schema\ncheck and the renderer are both scoped to that section; a workbench without\n`source` is rejected at compile time.\n\nIn editable mode `bpmn_canvas` edits bidirectionally: each process record's\n`name` and `steps` array (step name, `kind` task/gateway/event, order, add,\nremove) round-trip through the panel Save like any field edit.\n"
|
|
6004
6004
|
}
|
|
@@ -6112,8 +6112,8 @@
|
|
|
6112
6112
|
"sections": [
|
|
6113
6113
|
{
|
|
6114
6114
|
"file": "docs/dsl-spec.md",
|
|
6115
|
-
"line":
|
|
6116
|
-
"endLine":
|
|
6115
|
+
"line": 958,
|
|
6116
|
+
"endLine": 1169,
|
|
6117
6117
|
"heading": "`component` (trusted, extensible library)",
|
|
6118
6118
|
"content": "### `component` (trusted, extensible library)\n\nThe authoritative vocabulary is [`PANEL_COMPONENT_CATALOG`](../packages/core/src/panel-component-catalog.ts).\n`COMPONENT_KINDS`, workspace ownership, source bindings and the generated-panel\nsubset are derived from that one registry; this document is not a second\nvalidation whitelist. Bundle data cannot register executable components.\n\nThe shared library includes basic layouts and controls, question workspaces,\nrecord navigation/editing, diagrams, canvases, artifact readers and previews.\nFull-height workspace components preserve scroll and navigation ownership:\n`record_board`, `document_workspace`, `artifact_workspace`, `diagram_workspace`,\n`canvas_workspace`, `preview_workspace` and `navigation_workspace` expose their\nbehavior through explicit data bindings rather than Kit names. These are reusable\ncapabilities, not a guarantee that every record schema fits every workspace.\n\n`record_board.board.detail_sources` can embed exactly one `record_workspace`\nunder the selected card. Each `{section, reference}` binding declares an unordered\ndirect record collection and a readonly `record_select` back to the board's\nparent section. The child workspace sources must belong to those bindings.\nOwner and child storage paths cannot alias or overlap. The renderer filters\nchildren by the selected parent, binds new records to it, and merges hidden\nsibling records back into canonical updates. It refuses sibling-id replacement,\nreparenting and writes outside these collections. This is a view projection,\nnot a second stored copy; it does not support independently ordered child maps,\nnested `fields_path` records or artifact staging in this first composition slice.\nOrdinary `detail_sections` retain their existing same-record nested-form meaning.\n\n`record_board` uses full-width cards and a workspace-covering overview. Optional\n`board.group` binds a real grouping field. When omitted, the sidebar lists records\ndirectly, cards have no artificial group heading, and the overview connects the\nroot directly to records. Do not bind long summaries merely to satisfy grouping;\nthis projection never adds a grouping field to canonical records.\nSidebar selection scrolls to a card; it does not start editing. Description and\nbadge drafts have explicit Save/Cancel, while rejected records remain inspectable\nwithout granting edit access. Optional `board.id_field` binds a declared visible,\nreadonly `text` field and displays its existing string beside the card title and\nat the top of cover details. Inline details retain the same card header. It does\nnot add an ID editor, generate a fallback ID or write state; omission retains the\nexisting title-only presentation. `board.detail_fields` restricts the parent fields\nshown in the detail fold, and `details_title` localizes its heading. Optional nested\ndimensions can be added or removed without replacing unrelated record fields.\n`board.detail_fields_mode: fixed` instead shows every declared nested input and\nremoves dimension-level add/delete controls; collection item add/delete still\nuses its usual editor. Fields remain schema-optional, including empty inputs.\nViewing does not insert missing strings/maps. Omitted/`on_demand` retains the\nexisting optional-dimension behavior. This option grants no new write authority.\n\n`record_workspace.workspace_view: switch` puts the first child canvas over the\nwhole workspace. The edge action opens it, and the return action or a node's\ndetails action returns to the selected record. It does not add form/canvas tabs\nto the sidebar. Covered content stays mounted and inert to preserve selection,\ndrafts and the graph viewport without allowing hidden controls to receive input.\n\n`record_related_editor.record_table` is an authored-only table presentation of\nthe same child collection, not a conversion to a `rows` array. Its finite\n`columns: [{fields: [field_key, ...], label?: string}]` groups existing field\neditors into cells. Every non-hidden field declared for that child section must\nappear exactly once; hidden/foreign/duplicate bindings and unknown column keys\nare rejected. Column labels default to the first field's label and use the usual\nlocale resolution. A cell retains field visibility, help, requiredness, custom\nconditions and existing edit/derived-field rules. Record creation still binds\nthe selected parent, deletion preserves the normal section cleanup rules, and\n`inherit_from_graph` tables remain source-linked and read-only. The shared table\nwrapper owns horizontal scrolling at narrow widths. This does not promote the\ncomponent or this declaration to generated A2UI.\n\nAn authored graph hierarchy with `max_parents: 1` may opt into\n`parent_control: header`. The existing single-parent selector then sits beside\nthe selected record's form title, rather than above the whole inspector. It\nstill updates the same relation edge, rejects cycles, retains the source-record\nnavigation and shows the actual parent in read-only mode. Omission preserves\nthe prior inspector presentation; neither view creates an extra parent field.\n\n`diagram_workspace.diagram.detail_rows` groups declared read-only fields into\nresponsive fact cards. `chip_fields` selects string-list fields rendered as tags;\n`detail_hint_fields` supplies the populated field labels for the details action.\n`tags` maps declared enum fields to labels and finite semantic tones. These are\npresentation declarations, not new edit rights or storage. Diagram details cover\nonly the content pane; the navigator remains available. Leaving an edited diagram\nstill requires successful serialization through the existing save barrier.\n\n`diagram_workspace.diagram.label_source` can read a declared label from another\nsection bound to the same record collection. The optional `inspector` keeps a\ncontext editor alongside the BPMN canvas: `process_sections` edit the selected\nprocess; `nodes` binds `source`, `process_field`, `element_field`, `label_field`\nand same-collection `sections`. Optional `related` groups use a process reference\nand an optional `node_field`; `advanced: true` starts the group collapsed.\nReferences must be declared `record_select` fields targeting the corresponding\ncollection. Clicking an element resolves its exact ID within the selected\nprocess only; absent or duplicate bindings do not guess a record. Existing field\nedit permissions and the atomic artifact save barrier remain authoritative.\nThis is contextual navigation, not automatic synchronization of BPMN structure\nand business facts; authors must explain how structural changes are reconciled.\n\nFor an exact component contract and on-demand local type declarations, use the\nauthoring inspector from the repository root:\n\n```sh\nnode .agents/skills/design-bundle-creator/scripts/inspect-panel-component.mjs . navigation_workspace --type ComponentNode.navigation_map.edges\n```\n\nUse the [component extension contract](a2ui-component-catalog-contract.md) when\nadding a component: catalog, validation, renderer, styles, edit boundaries,\ntests and authoring guidance must agree. Trusted runtime additions are possible;\nunknown component names in a manifest are rejected.\n\nAcceptance of a component name alone does not establish rendering fidelity,\neditable lifecycle support, or compatibility with every host; those require\nthe component's binding contract and actual runtime verification.\n\nPredefined DSL and A2UI-derived panels share this library, but generated panels\nmay use only the subset with an implemented generation/edit-authority contract.\nAn authored workspace is not automatically promoted into that subset.\nSupported generated results can be deterministically retained as DSL; unsupported\ncapabilities must fail explicitly, never disappear during conversion. This is\nnot an arbitrary bidirectional A2UI protocol converter.\n\n`question_list` is the standard controlled question interaction. Each source\nrecord uses `prompt`, optional `note`, `kind` (`text | single | multiple`),\noptional `choices[]` (`value`, `label`, `recommended`), `answer`, and optional\n`detail`. Text answers render as one multiline input; an existing text-question\n`detail` remains visible as read-only context rather than becoming a second\nanswer box. Single/multiple answers use accessible choice rows and may edit\n`detail`. Existing read-only context and choice supplements use the same\nlocalized label (without the optional-input suffix in reading mode). Cards\nwith a non-empty `answer` collapse to a readable result and can\nbe reopened for editing. The component writes only the fields exposed by that\ninteraction back to the owning record. It does not invent approval state, and an\nempty answer remains unanswered even when `detail` contains context. Native\nproviders may explicitly extend answer-state semantics for attachments, and\nmay add rounds or rejection around this base contract without making those\nextensions mandatory for other Kits.\n\nAuthored `question_list`, `question_rounds`, and `question_workspace` may declare\n`card_groups` with a unique `id`, `title`, and ordered `question_ids`. Members\nmust be contiguous in the existing record order and, for round workspaces, stay\nwithin one round. Invalid groups fall back to ordinary cards with a diagnostic;\ngrouping never reorders canonical records. Generated-origin Panels reject this\nauthored extension.\n\nEach group may declare a `presentation` object containing only optional boolean\n`always_expanded`, `show_detail`, and `show_attachments` properties. These select\nshared component behavior, not Bundle-specific styling. Omission preserves the\nusual collapse, detail, and attachment controls. Hiding a control preserves its\ncanonical data; keeping a card expanded does not grant editing permission.\nRead-only, disabled, protected, historical and rejection guards still apply.\n\n`question_workspace` composes the same question cards with the standard\n`panel_workspace` navigation shell. It groups records by optional numeric\n`round`, shows answer progress, and keeps only the selected group in the main\npane; records without a round form one current group. Its optional\n`description` is rendered through the shared sticky workspace Tip Bar above\nthe main content, never squeezed into the navigation sidebar. `question_rounds` is the\nbackward-compatible alias for this workspace behavior. Optional\n`multimodal_answer[]` entries use the Web App-compatible local reference shape\n(`type`, `file_md5`, `filename`, `mime_type`, `size_bytes`, `artifact_file`).\nThe client keeps pending bytes in a reserved browser-only transport, strips it\nbefore schema validation, and atomically saves only files still referenced by\ncanonical state. The transport is framework state, never a Bundle field.\n\nAuthored `question_workspace` / `question_rounds` nodes may explicitly set\n`question_policy.allow_choice_actions: true`. Expanded editable dynamic single\ncards offer “Switch to multiple choice”; multiple cards offer “Select all” /\n“Deselect all”. Omission or `false` preserves the existing controls. The shared\nruntime owns these actions and their localized styling, not Bundle CSS or an\nauthor-supplied `renderActions` callback. Switching changes only `kind` to\n`multiple`, preserving the exact answer bytes and keeping the editor open.\nSelect-all writes choice values in declared order through the existing\ncomma-separated `answer` contract; deselect-all writes an empty answer. Neither\naction changes detail, attachments, identity, choices or round. Records declared\nin `first_round_ids` are the fixed first-round configuration and do not receive\nthese actions; `protected_ids` still controls rejection only. Read-only,\ndisabled, rejected and read-only historical cards cannot invoke the actions.\nGenerated-origin/A2UI auto Panels reject this configuration, even when `false`;\ntheir existing answer/detail-only write authority and protected `kind` remain\nunchanged. Converting a generated view into an authored reusable panel does not\nsilently grant this capability: the author must opt in under the static contract.\n\n`panel_workspace` is the reusable panel-internal left navigation + main content\nlayout. It standardizes containment, scroll ownership and narrow-panel fallback;\nit does not define domain records or selection semantics. Use it rather than\ncopying a Kit-specific two-column shell.\n\nThe shared runtime `PanelWorkspaceNavigation` accepts optional per-item\n`description`, `supporting`, and `statusLabel` display slots alongside the\nlabel/current row. These are supplied display text, not canonical fields or\nnew DSL expressions. Omitted slots render no empty rows. The `meta` fallback\nremains supported. A marker requires both explicit `statusIndicator: true`\nand an existing `status`; a label-only item never gains an inferred status dot.\nFlat record navigation, question rounds, and future workspace consumers share\nthe same base navigation typography, spacing and selected appearance. Bundle\nCSS is not required. Hierarchical trees retain their separate structure.\nQuestion progress excludes rejected items from answered/completion checks,\nwhile retaining all group records in the displayed total and preserving fixed\nquestion grouping, stable IDs, selection and canonical answers. The original\nWeb App question panel used body round sections, not this sidebar; the shared\nsidebar is an enhanced structure using the original public navigation style,\nnot a claim of one-to-one restoration of a nonexistent original sidebar.\n\n`doc_lifecycle_studio` binds `objects`/`axes`/`actions` sections (validation\nfails loud when one is missing) and renders the fact table (actions × state\naxes, per-cell effects) plus process/derivation/ledger projections derived at\nrender time; unavailable views render disabled with a reason, never hidden.\n`rowview_workbench` renders the residue envelope (below) and requires a\n`source` declaring the add section it owns — the details-envelope schema\ncheck and the renderer are both scoped to that section; a workbench without\n`source` is rejected at compile time.\n\nIn editable mode `bpmn_canvas` edits bidirectionally: each process record's\n`name` and `steps` array (step name, `kind` task/gateway/event, order, add,\nremove) round-trip through the panel Save like any field edit.\n"
|
|
6119
6119
|
}
|
|
@@ -6227,8 +6227,8 @@
|
|
|
6227
6227
|
"sections": [
|
|
6228
6228
|
{
|
|
6229
6229
|
"file": "docs/dsl-spec.md",
|
|
6230
|
-
"line":
|
|
6231
|
-
"endLine":
|
|
6230
|
+
"line": 958,
|
|
6231
|
+
"endLine": 1169,
|
|
6232
6232
|
"heading": "`component` (trusted, extensible library)",
|
|
6233
6233
|
"content": "### `component` (trusted, extensible library)\n\nThe authoritative vocabulary is [`PANEL_COMPONENT_CATALOG`](../packages/core/src/panel-component-catalog.ts).\n`COMPONENT_KINDS`, workspace ownership, source bindings and the generated-panel\nsubset are derived from that one registry; this document is not a second\nvalidation whitelist. Bundle data cannot register executable components.\n\nThe shared library includes basic layouts and controls, question workspaces,\nrecord navigation/editing, diagrams, canvases, artifact readers and previews.\nFull-height workspace components preserve scroll and navigation ownership:\n`record_board`, `document_workspace`, `artifact_workspace`, `diagram_workspace`,\n`canvas_workspace`, `preview_workspace` and `navigation_workspace` expose their\nbehavior through explicit data bindings rather than Kit names. These are reusable\ncapabilities, not a guarantee that every record schema fits every workspace.\n\n`record_board.board.detail_sources` can embed exactly one `record_workspace`\nunder the selected card. Each `{section, reference}` binding declares an unordered\ndirect record collection and a readonly `record_select` back to the board's\nparent section. The child workspace sources must belong to those bindings.\nOwner and child storage paths cannot alias or overlap. The renderer filters\nchildren by the selected parent, binds new records to it, and merges hidden\nsibling records back into canonical updates. It refuses sibling-id replacement,\nreparenting and writes outside these collections. This is a view projection,\nnot a second stored copy; it does not support independently ordered child maps,\nnested `fields_path` records or artifact staging in this first composition slice.\nOrdinary `detail_sections` retain their existing same-record nested-form meaning.\n\n`record_board` uses full-width cards and a workspace-covering overview. Optional\n`board.group` binds a real grouping field. When omitted, the sidebar lists records\ndirectly, cards have no artificial group heading, and the overview connects the\nroot directly to records. Do not bind long summaries merely to satisfy grouping;\nthis projection never adds a grouping field to canonical records.\nSidebar selection scrolls to a card; it does not start editing. Description and\nbadge drafts have explicit Save/Cancel, while rejected records remain inspectable\nwithout granting edit access. Optional `board.id_field` binds a declared visible,\nreadonly `text` field and displays its existing string beside the card title and\nat the top of cover details. Inline details retain the same card header. It does\nnot add an ID editor, generate a fallback ID or write state; omission retains the\nexisting title-only presentation. `board.detail_fields` restricts the parent fields\nshown in the detail fold, and `details_title` localizes its heading. Optional nested\ndimensions can be added or removed without replacing unrelated record fields.\n`board.detail_fields_mode: fixed` instead shows every declared nested input and\nremoves dimension-level add/delete controls; collection item add/delete still\nuses its usual editor. Fields remain schema-optional, including empty inputs.\nViewing does not insert missing strings/maps. Omitted/`on_demand` retains the\nexisting optional-dimension behavior. This option grants no new write authority.\n\n`record_workspace.workspace_view: switch` puts the first child canvas over the\nwhole workspace. The edge action opens it, and the return action or a node's\ndetails action returns to the selected record. It does not add form/canvas tabs\nto the sidebar. Covered content stays mounted and inert to preserve selection,\ndrafts and the graph viewport without allowing hidden controls to receive input.\n\n`record_related_editor.record_table` is an authored-only table presentation of\nthe same child collection, not a conversion to a `rows` array. Its finite\n`columns: [{fields: [field_key, ...], label?: string}]` groups existing field\neditors into cells. Every non-hidden field declared for that child section must\nappear exactly once; hidden/foreign/duplicate bindings and unknown column keys\nare rejected. Column labels default to the first field's label and use the usual\nlocale resolution. A cell retains field visibility, help, requiredness, custom\nconditions and existing edit/derived-field rules. Record creation still binds\nthe selected parent, deletion preserves the normal section cleanup rules, and\n`inherit_from_graph` tables remain source-linked and read-only. The shared table\nwrapper owns horizontal scrolling at narrow widths. This does not promote the\ncomponent or this declaration to generated A2UI.\n\nAn authored graph hierarchy with `max_parents: 1` may opt into\n`parent_control: header`. The existing single-parent selector then sits beside\nthe selected record's form title, rather than above the whole inspector. It\nstill updates the same relation edge, rejects cycles, retains the source-record\nnavigation and shows the actual parent in read-only mode. Omission preserves\nthe prior inspector presentation; neither view creates an extra parent field.\n\n`diagram_workspace.diagram.detail_rows` groups declared read-only fields into\nresponsive fact cards. `chip_fields` selects string-list fields rendered as tags;\n`detail_hint_fields` supplies the populated field labels for the details action.\n`tags` maps declared enum fields to labels and finite semantic tones. These are\npresentation declarations, not new edit rights or storage. Diagram details cover\nonly the content pane; the navigator remains available. Leaving an edited diagram\nstill requires successful serialization through the existing save barrier.\n\n`diagram_workspace.diagram.label_source` can read a declared label from another\nsection bound to the same record collection. The optional `inspector` keeps a\ncontext editor alongside the BPMN canvas: `process_sections` edit the selected\nprocess; `nodes` binds `source`, `process_field`, `element_field`, `label_field`\nand same-collection `sections`. Optional `related` groups use a process reference\nand an optional `node_field`; `advanced: true` starts the group collapsed.\nReferences must be declared `record_select` fields targeting the corresponding\ncollection. Clicking an element resolves its exact ID within the selected\nprocess only; absent or duplicate bindings do not guess a record. Existing field\nedit permissions and the atomic artifact save barrier remain authoritative.\nThis is contextual navigation, not automatic synchronization of BPMN structure\nand business facts; authors must explain how structural changes are reconciled.\n\nFor an exact component contract and on-demand local type declarations, use the\nauthoring inspector from the repository root:\n\n```sh\nnode .agents/skills/design-bundle-creator/scripts/inspect-panel-component.mjs . navigation_workspace --type ComponentNode.navigation_map.edges\n```\n\nUse the [component extension contract](a2ui-component-catalog-contract.md) when\nadding a component: catalog, validation, renderer, styles, edit boundaries,\ntests and authoring guidance must agree. Trusted runtime additions are possible;\nunknown component names in a manifest are rejected.\n\nAcceptance of a component name alone does not establish rendering fidelity,\neditable lifecycle support, or compatibility with every host; those require\nthe component's binding contract and actual runtime verification.\n\nPredefined DSL and A2UI-derived panels share this library, but generated panels\nmay use only the subset with an implemented generation/edit-authority contract.\nAn authored workspace is not automatically promoted into that subset.\nSupported generated results can be deterministically retained as DSL; unsupported\ncapabilities must fail explicitly, never disappear during conversion. This is\nnot an arbitrary bidirectional A2UI protocol converter.\n\n`question_list` is the standard controlled question interaction. Each source\nrecord uses `prompt`, optional `note`, `kind` (`text | single | multiple`),\noptional `choices[]` (`value`, `label`, `recommended`), `answer`, and optional\n`detail`. Text answers render as one multiline input; an existing text-question\n`detail` remains visible as read-only context rather than becoming a second\nanswer box. Single/multiple answers use accessible choice rows and may edit\n`detail`. Existing read-only context and choice supplements use the same\nlocalized label (without the optional-input suffix in reading mode). Cards\nwith a non-empty `answer` collapse to a readable result and can\nbe reopened for editing. The component writes only the fields exposed by that\ninteraction back to the owning record. It does not invent approval state, and an\nempty answer remains unanswered even when `detail` contains context. Native\nproviders may explicitly extend answer-state semantics for attachments, and\nmay add rounds or rejection around this base contract without making those\nextensions mandatory for other Kits.\n\nAuthored `question_list`, `question_rounds`, and `question_workspace` may declare\n`card_groups` with a unique `id`, `title`, and ordered `question_ids`. Members\nmust be contiguous in the existing record order and, for round workspaces, stay\nwithin one round. Invalid groups fall back to ordinary cards with a diagnostic;\ngrouping never reorders canonical records. Generated-origin Panels reject this\nauthored extension.\n\nEach group may declare a `presentation` object containing only optional boolean\n`always_expanded`, `show_detail`, and `show_attachments` properties. These select\nshared component behavior, not Bundle-specific styling. Omission preserves the\nusual collapse, detail, and attachment controls. Hiding a control preserves its\ncanonical data; keeping a card expanded does not grant editing permission.\nRead-only, disabled, protected, historical and rejection guards still apply.\n\n`question_workspace` composes the same question cards with the standard\n`panel_workspace` navigation shell. It groups records by optional numeric\n`round`, shows answer progress, and keeps only the selected group in the main\npane; records without a round form one current group. Its optional\n`description` is rendered through the shared sticky workspace Tip Bar above\nthe main content, never squeezed into the navigation sidebar. `question_rounds` is the\nbackward-compatible alias for this workspace behavior. Optional\n`multimodal_answer[]` entries use the Web App-compatible local reference shape\n(`type`, `file_md5`, `filename`, `mime_type`, `size_bytes`, `artifact_file`).\nThe client keeps pending bytes in a reserved browser-only transport, strips it\nbefore schema validation, and atomically saves only files still referenced by\ncanonical state. The transport is framework state, never a Bundle field.\n\nAuthored `question_workspace` / `question_rounds` nodes may explicitly set\n`question_policy.allow_choice_actions: true`. Expanded editable dynamic single\ncards offer “Switch to multiple choice”; multiple cards offer “Select all” /\n“Deselect all”. Omission or `false` preserves the existing controls. The shared\nruntime owns these actions and their localized styling, not Bundle CSS or an\nauthor-supplied `renderActions` callback. Switching changes only `kind` to\n`multiple`, preserving the exact answer bytes and keeping the editor open.\nSelect-all writes choice values in declared order through the existing\ncomma-separated `answer` contract; deselect-all writes an empty answer. Neither\naction changes detail, attachments, identity, choices or round. Records declared\nin `first_round_ids` are the fixed first-round configuration and do not receive\nthese actions; `protected_ids` still controls rejection only. Read-only,\ndisabled, rejected and read-only historical cards cannot invoke the actions.\nGenerated-origin/A2UI auto Panels reject this configuration, even when `false`;\ntheir existing answer/detail-only write authority and protected `kind` remain\nunchanged. Converting a generated view into an authored reusable panel does not\nsilently grant this capability: the author must opt in under the static contract.\n\n`panel_workspace` is the reusable panel-internal left navigation + main content\nlayout. It standardizes containment, scroll ownership and narrow-panel fallback;\nit does not define domain records or selection semantics. Use it rather than\ncopying a Kit-specific two-column shell.\n\nThe shared runtime `PanelWorkspaceNavigation` accepts optional per-item\n`description`, `supporting`, and `statusLabel` display slots alongside the\nlabel/current row. These are supplied display text, not canonical fields or\nnew DSL expressions. Omitted slots render no empty rows. The `meta` fallback\nremains supported. A marker requires both explicit `statusIndicator: true`\nand an existing `status`; a label-only item never gains an inferred status dot.\nFlat record navigation, question rounds, and future workspace consumers share\nthe same base navigation typography, spacing and selected appearance. Bundle\nCSS is not required. Hierarchical trees retain their separate structure.\nQuestion progress excludes rejected items from answered/completion checks,\nwhile retaining all group records in the displayed total and preserving fixed\nquestion grouping, stable IDs, selection and canonical answers. The original\nWeb App question panel used body round sections, not this sidebar; the shared\nsidebar is an enhanced structure using the original public navigation style,\nnot a claim of one-to-one restoration of a nonexistent original sidebar.\n\n`doc_lifecycle_studio` binds `objects`/`axes`/`actions` sections (validation\nfails loud when one is missing) and renders the fact table (actions × state\naxes, per-cell effects) plus process/derivation/ledger projections derived at\nrender time; unavailable views render disabled with a reason, never hidden.\n`rowview_workbench` renders the residue envelope (below) and requires a\n`source` declaring the add section it owns — the details-envelope schema\ncheck and the renderer are both scoped to that section; a workbench without\n`source` is rejected at compile time.\n\nIn editable mode `bpmn_canvas` edits bidirectionally: each process record's\n`name` and `steps` array (step name, `kind` task/gateway/event, order, add,\nremove) round-trip through the panel Save like any field edit.\n"
|
|
6234
6234
|
}
|
|
@@ -6343,8 +6343,8 @@
|
|
|
6343
6343
|
"sections": [
|
|
6344
6344
|
{
|
|
6345
6345
|
"file": "docs/dsl-spec.md",
|
|
6346
|
-
"line":
|
|
6347
|
-
"endLine":
|
|
6346
|
+
"line": 958,
|
|
6347
|
+
"endLine": 1169,
|
|
6348
6348
|
"heading": "`component` (trusted, extensible library)",
|
|
6349
6349
|
"content": "### `component` (trusted, extensible library)\n\nThe authoritative vocabulary is [`PANEL_COMPONENT_CATALOG`](../packages/core/src/panel-component-catalog.ts).\n`COMPONENT_KINDS`, workspace ownership, source bindings and the generated-panel\nsubset are derived from that one registry; this document is not a second\nvalidation whitelist. Bundle data cannot register executable components.\n\nThe shared library includes basic layouts and controls, question workspaces,\nrecord navigation/editing, diagrams, canvases, artifact readers and previews.\nFull-height workspace components preserve scroll and navigation ownership:\n`record_board`, `document_workspace`, `artifact_workspace`, `diagram_workspace`,\n`canvas_workspace`, `preview_workspace` and `navigation_workspace` expose their\nbehavior through explicit data bindings rather than Kit names. These are reusable\ncapabilities, not a guarantee that every record schema fits every workspace.\n\n`record_board.board.detail_sources` can embed exactly one `record_workspace`\nunder the selected card. Each `{section, reference}` binding declares an unordered\ndirect record collection and a readonly `record_select` back to the board's\nparent section. The child workspace sources must belong to those bindings.\nOwner and child storage paths cannot alias or overlap. The renderer filters\nchildren by the selected parent, binds new records to it, and merges hidden\nsibling records back into canonical updates. It refuses sibling-id replacement,\nreparenting and writes outside these collections. This is a view projection,\nnot a second stored copy; it does not support independently ordered child maps,\nnested `fields_path` records or artifact staging in this first composition slice.\nOrdinary `detail_sections` retain their existing same-record nested-form meaning.\n\n`record_board` uses full-width cards and a workspace-covering overview. Optional\n`board.group` binds a real grouping field. When omitted, the sidebar lists records\ndirectly, cards have no artificial group heading, and the overview connects the\nroot directly to records. Do not bind long summaries merely to satisfy grouping;\nthis projection never adds a grouping field to canonical records.\nSidebar selection scrolls to a card; it does not start editing. Description and\nbadge drafts have explicit Save/Cancel, while rejected records remain inspectable\nwithout granting edit access. Optional `board.id_field` binds a declared visible,\nreadonly `text` field and displays its existing string beside the card title and\nat the top of cover details. Inline details retain the same card header. It does\nnot add an ID editor, generate a fallback ID or write state; omission retains the\nexisting title-only presentation. `board.detail_fields` restricts the parent fields\nshown in the detail fold, and `details_title` localizes its heading. Optional nested\ndimensions can be added or removed without replacing unrelated record fields.\n`board.detail_fields_mode: fixed` instead shows every declared nested input and\nremoves dimension-level add/delete controls; collection item add/delete still\nuses its usual editor. Fields remain schema-optional, including empty inputs.\nViewing does not insert missing strings/maps. Omitted/`on_demand` retains the\nexisting optional-dimension behavior. This option grants no new write authority.\n\n`record_workspace.workspace_view: switch` puts the first child canvas over the\nwhole workspace. The edge action opens it, and the return action or a node's\ndetails action returns to the selected record. It does not add form/canvas tabs\nto the sidebar. Covered content stays mounted and inert to preserve selection,\ndrafts and the graph viewport without allowing hidden controls to receive input.\n\n`record_related_editor.record_table` is an authored-only table presentation of\nthe same child collection, not a conversion to a `rows` array. Its finite\n`columns: [{fields: [field_key, ...], label?: string}]` groups existing field\neditors into cells. Every non-hidden field declared for that child section must\nappear exactly once; hidden/foreign/duplicate bindings and unknown column keys\nare rejected. Column labels default to the first field's label and use the usual\nlocale resolution. A cell retains field visibility, help, requiredness, custom\nconditions and existing edit/derived-field rules. Record creation still binds\nthe selected parent, deletion preserves the normal section cleanup rules, and\n`inherit_from_graph` tables remain source-linked and read-only. The shared table\nwrapper owns horizontal scrolling at narrow widths. This does not promote the\ncomponent or this declaration to generated A2UI.\n\nAn authored graph hierarchy with `max_parents: 1` may opt into\n`parent_control: header`. The existing single-parent selector then sits beside\nthe selected record's form title, rather than above the whole inspector. It\nstill updates the same relation edge, rejects cycles, retains the source-record\nnavigation and shows the actual parent in read-only mode. Omission preserves\nthe prior inspector presentation; neither view creates an extra parent field.\n\n`diagram_workspace.diagram.detail_rows` groups declared read-only fields into\nresponsive fact cards. `chip_fields` selects string-list fields rendered as tags;\n`detail_hint_fields` supplies the populated field labels for the details action.\n`tags` maps declared enum fields to labels and finite semantic tones. These are\npresentation declarations, not new edit rights or storage. Diagram details cover\nonly the content pane; the navigator remains available. Leaving an edited diagram\nstill requires successful serialization through the existing save barrier.\n\n`diagram_workspace.diagram.label_source` can read a declared label from another\nsection bound to the same record collection. The optional `inspector` keeps a\ncontext editor alongside the BPMN canvas: `process_sections` edit the selected\nprocess; `nodes` binds `source`, `process_field`, `element_field`, `label_field`\nand same-collection `sections`. Optional `related` groups use a process reference\nand an optional `node_field`; `advanced: true` starts the group collapsed.\nReferences must be declared `record_select` fields targeting the corresponding\ncollection. Clicking an element resolves its exact ID within the selected\nprocess only; absent or duplicate bindings do not guess a record. Existing field\nedit permissions and the atomic artifact save barrier remain authoritative.\nThis is contextual navigation, not automatic synchronization of BPMN structure\nand business facts; authors must explain how structural changes are reconciled.\n\nFor an exact component contract and on-demand local type declarations, use the\nauthoring inspector from the repository root:\n\n```sh\nnode .agents/skills/design-bundle-creator/scripts/inspect-panel-component.mjs . navigation_workspace --type ComponentNode.navigation_map.edges\n```\n\nUse the [component extension contract](a2ui-component-catalog-contract.md) when\nadding a component: catalog, validation, renderer, styles, edit boundaries,\ntests and authoring guidance must agree. Trusted runtime additions are possible;\nunknown component names in a manifest are rejected.\n\nAcceptance of a component name alone does not establish rendering fidelity,\neditable lifecycle support, or compatibility with every host; those require\nthe component's binding contract and actual runtime verification.\n\nPredefined DSL and A2UI-derived panels share this library, but generated panels\nmay use only the subset with an implemented generation/edit-authority contract.\nAn authored workspace is not automatically promoted into that subset.\nSupported generated results can be deterministically retained as DSL; unsupported\ncapabilities must fail explicitly, never disappear during conversion. This is\nnot an arbitrary bidirectional A2UI protocol converter.\n\n`question_list` is the standard controlled question interaction. Each source\nrecord uses `prompt`, optional `note`, `kind` (`text | single | multiple`),\noptional `choices[]` (`value`, `label`, `recommended`), `answer`, and optional\n`detail`. Text answers render as one multiline input; an existing text-question\n`detail` remains visible as read-only context rather than becoming a second\nanswer box. Single/multiple answers use accessible choice rows and may edit\n`detail`. Existing read-only context and choice supplements use the same\nlocalized label (without the optional-input suffix in reading mode). Cards\nwith a non-empty `answer` collapse to a readable result and can\nbe reopened for editing. The component writes only the fields exposed by that\ninteraction back to the owning record. It does not invent approval state, and an\nempty answer remains unanswered even when `detail` contains context. Native\nproviders may explicitly extend answer-state semantics for attachments, and\nmay add rounds or rejection around this base contract without making those\nextensions mandatory for other Kits.\n\nAuthored `question_list`, `question_rounds`, and `question_workspace` may declare\n`card_groups` with a unique `id`, `title`, and ordered `question_ids`. Members\nmust be contiguous in the existing record order and, for round workspaces, stay\nwithin one round. Invalid groups fall back to ordinary cards with a diagnostic;\ngrouping never reorders canonical records. Generated-origin Panels reject this\nauthored extension.\n\nEach group may declare a `presentation` object containing only optional boolean\n`always_expanded`, `show_detail`, and `show_attachments` properties. These select\nshared component behavior, not Bundle-specific styling. Omission preserves the\nusual collapse, detail, and attachment controls. Hiding a control preserves its\ncanonical data; keeping a card expanded does not grant editing permission.\nRead-only, disabled, protected, historical and rejection guards still apply.\n\n`question_workspace` composes the same question cards with the standard\n`panel_workspace` navigation shell. It groups records by optional numeric\n`round`, shows answer progress, and keeps only the selected group in the main\npane; records without a round form one current group. Its optional\n`description` is rendered through the shared sticky workspace Tip Bar above\nthe main content, never squeezed into the navigation sidebar. `question_rounds` is the\nbackward-compatible alias for this workspace behavior. Optional\n`multimodal_answer[]` entries use the Web App-compatible local reference shape\n(`type`, `file_md5`, `filename`, `mime_type`, `size_bytes`, `artifact_file`).\nThe client keeps pending bytes in a reserved browser-only transport, strips it\nbefore schema validation, and atomically saves only files still referenced by\ncanonical state. The transport is framework state, never a Bundle field.\n\nAuthored `question_workspace` / `question_rounds` nodes may explicitly set\n`question_policy.allow_choice_actions: true`. Expanded editable dynamic single\ncards offer “Switch to multiple choice”; multiple cards offer “Select all” /\n“Deselect all”. Omission or `false` preserves the existing controls. The shared\nruntime owns these actions and their localized styling, not Bundle CSS or an\nauthor-supplied `renderActions` callback. Switching changes only `kind` to\n`multiple`, preserving the exact answer bytes and keeping the editor open.\nSelect-all writes choice values in declared order through the existing\ncomma-separated `answer` contract; deselect-all writes an empty answer. Neither\naction changes detail, attachments, identity, choices or round. Records declared\nin `first_round_ids` are the fixed first-round configuration and do not receive\nthese actions; `protected_ids` still controls rejection only. Read-only,\ndisabled, rejected and read-only historical cards cannot invoke the actions.\nGenerated-origin/A2UI auto Panels reject this configuration, even when `false`;\ntheir existing answer/detail-only write authority and protected `kind` remain\nunchanged. Converting a generated view into an authored reusable panel does not\nsilently grant this capability: the author must opt in under the static contract.\n\n`panel_workspace` is the reusable panel-internal left navigation + main content\nlayout. It standardizes containment, scroll ownership and narrow-panel fallback;\nit does not define domain records or selection semantics. Use it rather than\ncopying a Kit-specific two-column shell.\n\nThe shared runtime `PanelWorkspaceNavigation` accepts optional per-item\n`description`, `supporting`, and `statusLabel` display slots alongside the\nlabel/current row. These are supplied display text, not canonical fields or\nnew DSL expressions. Omitted slots render no empty rows. The `meta` fallback\nremains supported. A marker requires both explicit `statusIndicator: true`\nand an existing `status`; a label-only item never gains an inferred status dot.\nFlat record navigation, question rounds, and future workspace consumers share\nthe same base navigation typography, spacing and selected appearance. Bundle\nCSS is not required. Hierarchical trees retain their separate structure.\nQuestion progress excludes rejected items from answered/completion checks,\nwhile retaining all group records in the displayed total and preserving fixed\nquestion grouping, stable IDs, selection and canonical answers. The original\nWeb App question panel used body round sections, not this sidebar; the shared\nsidebar is an enhanced structure using the original public navigation style,\nnot a claim of one-to-one restoration of a nonexistent original sidebar.\n\n`doc_lifecycle_studio` binds `objects`/`axes`/`actions` sections (validation\nfails loud when one is missing) and renders the fact table (actions × state\naxes, per-cell effects) plus process/derivation/ledger projections derived at\nrender time; unavailable views render disabled with a reason, never hidden.\n`rowview_workbench` renders the residue envelope (below) and requires a\n`source` declaring the add section it owns — the details-envelope schema\ncheck and the renderer are both scoped to that section; a workbench without\n`source` is rejected at compile time.\n\nIn editable mode `bpmn_canvas` edits bidirectionally: each process record's\n`name` and `steps` array (step name, `kind` task/gateway/event, order, add,\nremove) round-trip through the panel Save like any field edit.\n"
|
|
6350
6350
|
}
|
|
@@ -6471,8 +6471,8 @@
|
|
|
6471
6471
|
"sections": [
|
|
6472
6472
|
{
|
|
6473
6473
|
"file": "docs/dsl-spec.md",
|
|
6474
|
-
"line":
|
|
6475
|
-
"endLine":
|
|
6474
|
+
"line": 958,
|
|
6475
|
+
"endLine": 1169,
|
|
6476
6476
|
"heading": "`component` (trusted, extensible library)",
|
|
6477
6477
|
"content": "### `component` (trusted, extensible library)\n\nThe authoritative vocabulary is [`PANEL_COMPONENT_CATALOG`](../packages/core/src/panel-component-catalog.ts).\n`COMPONENT_KINDS`, workspace ownership, source bindings and the generated-panel\nsubset are derived from that one registry; this document is not a second\nvalidation whitelist. Bundle data cannot register executable components.\n\nThe shared library includes basic layouts and controls, question workspaces,\nrecord navigation/editing, diagrams, canvases, artifact readers and previews.\nFull-height workspace components preserve scroll and navigation ownership:\n`record_board`, `document_workspace`, `artifact_workspace`, `diagram_workspace`,\n`canvas_workspace`, `preview_workspace` and `navigation_workspace` expose their\nbehavior through explicit data bindings rather than Kit names. These are reusable\ncapabilities, not a guarantee that every record schema fits every workspace.\n\n`record_board.board.detail_sources` can embed exactly one `record_workspace`\nunder the selected card. Each `{section, reference}` binding declares an unordered\ndirect record collection and a readonly `record_select` back to the board's\nparent section. The child workspace sources must belong to those bindings.\nOwner and child storage paths cannot alias or overlap. The renderer filters\nchildren by the selected parent, binds new records to it, and merges hidden\nsibling records back into canonical updates. It refuses sibling-id replacement,\nreparenting and writes outside these collections. This is a view projection,\nnot a second stored copy; it does not support independently ordered child maps,\nnested `fields_path` records or artifact staging in this first composition slice.\nOrdinary `detail_sections` retain their existing same-record nested-form meaning.\n\n`record_board` uses full-width cards and a workspace-covering overview. Optional\n`board.group` binds a real grouping field. When omitted, the sidebar lists records\ndirectly, cards have no artificial group heading, and the overview connects the\nroot directly to records. Do not bind long summaries merely to satisfy grouping;\nthis projection never adds a grouping field to canonical records.\nSidebar selection scrolls to a card; it does not start editing. Description and\nbadge drafts have explicit Save/Cancel, while rejected records remain inspectable\nwithout granting edit access. Optional `board.id_field` binds a declared visible,\nreadonly `text` field and displays its existing string beside the card title and\nat the top of cover details. Inline details retain the same card header. It does\nnot add an ID editor, generate a fallback ID or write state; omission retains the\nexisting title-only presentation. `board.detail_fields` restricts the parent fields\nshown in the detail fold, and `details_title` localizes its heading. Optional nested\ndimensions can be added or removed without replacing unrelated record fields.\n`board.detail_fields_mode: fixed` instead shows every declared nested input and\nremoves dimension-level add/delete controls; collection item add/delete still\nuses its usual editor. Fields remain schema-optional, including empty inputs.\nViewing does not insert missing strings/maps. Omitted/`on_demand` retains the\nexisting optional-dimension behavior. This option grants no new write authority.\n\n`record_workspace.workspace_view: switch` puts the first child canvas over the\nwhole workspace. The edge action opens it, and the return action or a node's\ndetails action returns to the selected record. It does not add form/canvas tabs\nto the sidebar. Covered content stays mounted and inert to preserve selection,\ndrafts and the graph viewport without allowing hidden controls to receive input.\n\n`record_related_editor.record_table` is an authored-only table presentation of\nthe same child collection, not a conversion to a `rows` array. Its finite\n`columns: [{fields: [field_key, ...], label?: string}]` groups existing field\neditors into cells. Every non-hidden field declared for that child section must\nappear exactly once; hidden/foreign/duplicate bindings and unknown column keys\nare rejected. Column labels default to the first field's label and use the usual\nlocale resolution. A cell retains field visibility, help, requiredness, custom\nconditions and existing edit/derived-field rules. Record creation still binds\nthe selected parent, deletion preserves the normal section cleanup rules, and\n`inherit_from_graph` tables remain source-linked and read-only. The shared table\nwrapper owns horizontal scrolling at narrow widths. This does not promote the\ncomponent or this declaration to generated A2UI.\n\nAn authored graph hierarchy with `max_parents: 1` may opt into\n`parent_control: header`. The existing single-parent selector then sits beside\nthe selected record's form title, rather than above the whole inspector. It\nstill updates the same relation edge, rejects cycles, retains the source-record\nnavigation and shows the actual parent in read-only mode. Omission preserves\nthe prior inspector presentation; neither view creates an extra parent field.\n\n`diagram_workspace.diagram.detail_rows` groups declared read-only fields into\nresponsive fact cards. `chip_fields` selects string-list fields rendered as tags;\n`detail_hint_fields` supplies the populated field labels for the details action.\n`tags` maps declared enum fields to labels and finite semantic tones. These are\npresentation declarations, not new edit rights or storage. Diagram details cover\nonly the content pane; the navigator remains available. Leaving an edited diagram\nstill requires successful serialization through the existing save barrier.\n\n`diagram_workspace.diagram.label_source` can read a declared label from another\nsection bound to the same record collection. The optional `inspector` keeps a\ncontext editor alongside the BPMN canvas: `process_sections` edit the selected\nprocess; `nodes` binds `source`, `process_field`, `element_field`, `label_field`\nand same-collection `sections`. Optional `related` groups use a process reference\nand an optional `node_field`; `advanced: true` starts the group collapsed.\nReferences must be declared `record_select` fields targeting the corresponding\ncollection. Clicking an element resolves its exact ID within the selected\nprocess only; absent or duplicate bindings do not guess a record. Existing field\nedit permissions and the atomic artifact save barrier remain authoritative.\nThis is contextual navigation, not automatic synchronization of BPMN structure\nand business facts; authors must explain how structural changes are reconciled.\n\nFor an exact component contract and on-demand local type declarations, use the\nauthoring inspector from the repository root:\n\n```sh\nnode .agents/skills/design-bundle-creator/scripts/inspect-panel-component.mjs . navigation_workspace --type ComponentNode.navigation_map.edges\n```\n\nUse the [component extension contract](a2ui-component-catalog-contract.md) when\nadding a component: catalog, validation, renderer, styles, edit boundaries,\ntests and authoring guidance must agree. Trusted runtime additions are possible;\nunknown component names in a manifest are rejected.\n\nAcceptance of a component name alone does not establish rendering fidelity,\neditable lifecycle support, or compatibility with every host; those require\nthe component's binding contract and actual runtime verification.\n\nPredefined DSL and A2UI-derived panels share this library, but generated panels\nmay use only the subset with an implemented generation/edit-authority contract.\nAn authored workspace is not automatically promoted into that subset.\nSupported generated results can be deterministically retained as DSL; unsupported\ncapabilities must fail explicitly, never disappear during conversion. This is\nnot an arbitrary bidirectional A2UI protocol converter.\n\n`question_list` is the standard controlled question interaction. Each source\nrecord uses `prompt`, optional `note`, `kind` (`text | single | multiple`),\noptional `choices[]` (`value`, `label`, `recommended`), `answer`, and optional\n`detail`. Text answers render as one multiline input; an existing text-question\n`detail` remains visible as read-only context rather than becoming a second\nanswer box. Single/multiple answers use accessible choice rows and may edit\n`detail`. Existing read-only context and choice supplements use the same\nlocalized label (without the optional-input suffix in reading mode). Cards\nwith a non-empty `answer` collapse to a readable result and can\nbe reopened for editing. The component writes only the fields exposed by that\ninteraction back to the owning record. It does not invent approval state, and an\nempty answer remains unanswered even when `detail` contains context. Native\nproviders may explicitly extend answer-state semantics for attachments, and\nmay add rounds or rejection around this base contract without making those\nextensions mandatory for other Kits.\n\nAuthored `question_list`, `question_rounds`, and `question_workspace` may declare\n`card_groups` with a unique `id`, `title`, and ordered `question_ids`. Members\nmust be contiguous in the existing record order and, for round workspaces, stay\nwithin one round. Invalid groups fall back to ordinary cards with a diagnostic;\ngrouping never reorders canonical records. Generated-origin Panels reject this\nauthored extension.\n\nEach group may declare a `presentation` object containing only optional boolean\n`always_expanded`, `show_detail`, and `show_attachments` properties. These select\nshared component behavior, not Bundle-specific styling. Omission preserves the\nusual collapse, detail, and attachment controls. Hiding a control preserves its\ncanonical data; keeping a card expanded does not grant editing permission.\nRead-only, disabled, protected, historical and rejection guards still apply.\n\n`question_workspace` composes the same question cards with the standard\n`panel_workspace` navigation shell. It groups records by optional numeric\n`round`, shows answer progress, and keeps only the selected group in the main\npane; records without a round form one current group. Its optional\n`description` is rendered through the shared sticky workspace Tip Bar above\nthe main content, never squeezed into the navigation sidebar. `question_rounds` is the\nbackward-compatible alias for this workspace behavior. Optional\n`multimodal_answer[]` entries use the Web App-compatible local reference shape\n(`type`, `file_md5`, `filename`, `mime_type`, `size_bytes`, `artifact_file`).\nThe client keeps pending bytes in a reserved browser-only transport, strips it\nbefore schema validation, and atomically saves only files still referenced by\ncanonical state. The transport is framework state, never a Bundle field.\n\nAuthored `question_workspace` / `question_rounds` nodes may explicitly set\n`question_policy.allow_choice_actions: true`. Expanded editable dynamic single\ncards offer “Switch to multiple choice”; multiple cards offer “Select all” /\n“Deselect all”. Omission or `false` preserves the existing controls. The shared\nruntime owns these actions and their localized styling, not Bundle CSS or an\nauthor-supplied `renderActions` callback. Switching changes only `kind` to\n`multiple`, preserving the exact answer bytes and keeping the editor open.\nSelect-all writes choice values in declared order through the existing\ncomma-separated `answer` contract; deselect-all writes an empty answer. Neither\naction changes detail, attachments, identity, choices or round. Records declared\nin `first_round_ids` are the fixed first-round configuration and do not receive\nthese actions; `protected_ids` still controls rejection only. Read-only,\ndisabled, rejected and read-only historical cards cannot invoke the actions.\nGenerated-origin/A2UI auto Panels reject this configuration, even when `false`;\ntheir existing answer/detail-only write authority and protected `kind` remain\nunchanged. Converting a generated view into an authored reusable panel does not\nsilently grant this capability: the author must opt in under the static contract.\n\n`panel_workspace` is the reusable panel-internal left navigation + main content\nlayout. It standardizes containment, scroll ownership and narrow-panel fallback;\nit does not define domain records or selection semantics. Use it rather than\ncopying a Kit-specific two-column shell.\n\nThe shared runtime `PanelWorkspaceNavigation` accepts optional per-item\n`description`, `supporting`, and `statusLabel` display slots alongside the\nlabel/current row. These are supplied display text, not canonical fields or\nnew DSL expressions. Omitted slots render no empty rows. The `meta` fallback\nremains supported. A marker requires both explicit `statusIndicator: true`\nand an existing `status`; a label-only item never gains an inferred status dot.\nFlat record navigation, question rounds, and future workspace consumers share\nthe same base navigation typography, spacing and selected appearance. Bundle\nCSS is not required. Hierarchical trees retain their separate structure.\nQuestion progress excludes rejected items from answered/completion checks,\nwhile retaining all group records in the displayed total and preserving fixed\nquestion grouping, stable IDs, selection and canonical answers. The original\nWeb App question panel used body round sections, not this sidebar; the shared\nsidebar is an enhanced structure using the original public navigation style,\nnot a claim of one-to-one restoration of a nonexistent original sidebar.\n\n`doc_lifecycle_studio` binds `objects`/`axes`/`actions` sections (validation\nfails loud when one is missing) and renders the fact table (actions × state\naxes, per-cell effects) plus process/derivation/ledger projections derived at\nrender time; unavailable views render disabled with a reason, never hidden.\n`rowview_workbench` renders the residue envelope (below) and requires a\n`source` declaring the add section it owns — the details-envelope schema\ncheck and the renderer are both scoped to that section; a workbench without\n`source` is rejected at compile time.\n\nIn editable mode `bpmn_canvas` edits bidirectionally: each process record's\n`name` and `steps` array (step name, `kind` task/gateway/event, order, add,\nremove) round-trip through the panel Save like any field edit.\n"
|
|
6478
6478
|
}
|
|
@@ -6587,8 +6587,8 @@
|
|
|
6587
6587
|
"sections": [
|
|
6588
6588
|
{
|
|
6589
6589
|
"file": "docs/dsl-spec.md",
|
|
6590
|
-
"line":
|
|
6591
|
-
"endLine":
|
|
6590
|
+
"line": 958,
|
|
6591
|
+
"endLine": 1169,
|
|
6592
6592
|
"heading": "`component` (trusted, extensible library)",
|
|
6593
6593
|
"content": "### `component` (trusted, extensible library)\n\nThe authoritative vocabulary is [`PANEL_COMPONENT_CATALOG`](../packages/core/src/panel-component-catalog.ts).\n`COMPONENT_KINDS`, workspace ownership, source bindings and the generated-panel\nsubset are derived from that one registry; this document is not a second\nvalidation whitelist. Bundle data cannot register executable components.\n\nThe shared library includes basic layouts and controls, question workspaces,\nrecord navigation/editing, diagrams, canvases, artifact readers and previews.\nFull-height workspace components preserve scroll and navigation ownership:\n`record_board`, `document_workspace`, `artifact_workspace`, `diagram_workspace`,\n`canvas_workspace`, `preview_workspace` and `navigation_workspace` expose their\nbehavior through explicit data bindings rather than Kit names. These are reusable\ncapabilities, not a guarantee that every record schema fits every workspace.\n\n`record_board.board.detail_sources` can embed exactly one `record_workspace`\nunder the selected card. Each `{section, reference}` binding declares an unordered\ndirect record collection and a readonly `record_select` back to the board's\nparent section. The child workspace sources must belong to those bindings.\nOwner and child storage paths cannot alias or overlap. The renderer filters\nchildren by the selected parent, binds new records to it, and merges hidden\nsibling records back into canonical updates. It refuses sibling-id replacement,\nreparenting and writes outside these collections. This is a view projection,\nnot a second stored copy; it does not support independently ordered child maps,\nnested `fields_path` records or artifact staging in this first composition slice.\nOrdinary `detail_sections` retain their existing same-record nested-form meaning.\n\n`record_board` uses full-width cards and a workspace-covering overview. Optional\n`board.group` binds a real grouping field. When omitted, the sidebar lists records\ndirectly, cards have no artificial group heading, and the overview connects the\nroot directly to records. Do not bind long summaries merely to satisfy grouping;\nthis projection never adds a grouping field to canonical records.\nSidebar selection scrolls to a card; it does not start editing. Description and\nbadge drafts have explicit Save/Cancel, while rejected records remain inspectable\nwithout granting edit access. Optional `board.id_field` binds a declared visible,\nreadonly `text` field and displays its existing string beside the card title and\nat the top of cover details. Inline details retain the same card header. It does\nnot add an ID editor, generate a fallback ID or write state; omission retains the\nexisting title-only presentation. `board.detail_fields` restricts the parent fields\nshown in the detail fold, and `details_title` localizes its heading. Optional nested\ndimensions can be added or removed without replacing unrelated record fields.\n`board.detail_fields_mode: fixed` instead shows every declared nested input and\nremoves dimension-level add/delete controls; collection item add/delete still\nuses its usual editor. Fields remain schema-optional, including empty inputs.\nViewing does not insert missing strings/maps. Omitted/`on_demand` retains the\nexisting optional-dimension behavior. This option grants no new write authority.\n\n`record_workspace.workspace_view: switch` puts the first child canvas over the\nwhole workspace. The edge action opens it, and the return action or a node's\ndetails action returns to the selected record. It does not add form/canvas tabs\nto the sidebar. Covered content stays mounted and inert to preserve selection,\ndrafts and the graph viewport without allowing hidden controls to receive input.\n\n`record_related_editor.record_table` is an authored-only table presentation of\nthe same child collection, not a conversion to a `rows` array. Its finite\n`columns: [{fields: [field_key, ...], label?: string}]` groups existing field\neditors into cells. Every non-hidden field declared for that child section must\nappear exactly once; hidden/foreign/duplicate bindings and unknown column keys\nare rejected. Column labels default to the first field's label and use the usual\nlocale resolution. A cell retains field visibility, help, requiredness, custom\nconditions and existing edit/derived-field rules. Record creation still binds\nthe selected parent, deletion preserves the normal section cleanup rules, and\n`inherit_from_graph` tables remain source-linked and read-only. The shared table\nwrapper owns horizontal scrolling at narrow widths. This does not promote the\ncomponent or this declaration to generated A2UI.\n\nAn authored graph hierarchy with `max_parents: 1` may opt into\n`parent_control: header`. The existing single-parent selector then sits beside\nthe selected record's form title, rather than above the whole inspector. It\nstill updates the same relation edge, rejects cycles, retains the source-record\nnavigation and shows the actual parent in read-only mode. Omission preserves\nthe prior inspector presentation; neither view creates an extra parent field.\n\n`diagram_workspace.diagram.detail_rows` groups declared read-only fields into\nresponsive fact cards. `chip_fields` selects string-list fields rendered as tags;\n`detail_hint_fields` supplies the populated field labels for the details action.\n`tags` maps declared enum fields to labels and finite semantic tones. These are\npresentation declarations, not new edit rights or storage. Diagram details cover\nonly the content pane; the navigator remains available. Leaving an edited diagram\nstill requires successful serialization through the existing save barrier.\n\n`diagram_workspace.diagram.label_source` can read a declared label from another\nsection bound to the same record collection. The optional `inspector` keeps a\ncontext editor alongside the BPMN canvas: `process_sections` edit the selected\nprocess; `nodes` binds `source`, `process_field`, `element_field`, `label_field`\nand same-collection `sections`. Optional `related` groups use a process reference\nand an optional `node_field`; `advanced: true` starts the group collapsed.\nReferences must be declared `record_select` fields targeting the corresponding\ncollection. Clicking an element resolves its exact ID within the selected\nprocess only; absent or duplicate bindings do not guess a record. Existing field\nedit permissions and the atomic artifact save barrier remain authoritative.\nThis is contextual navigation, not automatic synchronization of BPMN structure\nand business facts; authors must explain how structural changes are reconciled.\n\nFor an exact component contract and on-demand local type declarations, use the\nauthoring inspector from the repository root:\n\n```sh\nnode .agents/skills/design-bundle-creator/scripts/inspect-panel-component.mjs . navigation_workspace --type ComponentNode.navigation_map.edges\n```\n\nUse the [component extension contract](a2ui-component-catalog-contract.md) when\nadding a component: catalog, validation, renderer, styles, edit boundaries,\ntests and authoring guidance must agree. Trusted runtime additions are possible;\nunknown component names in a manifest are rejected.\n\nAcceptance of a component name alone does not establish rendering fidelity,\neditable lifecycle support, or compatibility with every host; those require\nthe component's binding contract and actual runtime verification.\n\nPredefined DSL and A2UI-derived panels share this library, but generated panels\nmay use only the subset with an implemented generation/edit-authority contract.\nAn authored workspace is not automatically promoted into that subset.\nSupported generated results can be deterministically retained as DSL; unsupported\ncapabilities must fail explicitly, never disappear during conversion. This is\nnot an arbitrary bidirectional A2UI protocol converter.\n\n`question_list` is the standard controlled question interaction. Each source\nrecord uses `prompt`, optional `note`, `kind` (`text | single | multiple`),\noptional `choices[]` (`value`, `label`, `recommended`), `answer`, and optional\n`detail`. Text answers render as one multiline input; an existing text-question\n`detail` remains visible as read-only context rather than becoming a second\nanswer box. Single/multiple answers use accessible choice rows and may edit\n`detail`. Existing read-only context and choice supplements use the same\nlocalized label (without the optional-input suffix in reading mode). Cards\nwith a non-empty `answer` collapse to a readable result and can\nbe reopened for editing. The component writes only the fields exposed by that\ninteraction back to the owning record. It does not invent approval state, and an\nempty answer remains unanswered even when `detail` contains context. Native\nproviders may explicitly extend answer-state semantics for attachments, and\nmay add rounds or rejection around this base contract without making those\nextensions mandatory for other Kits.\n\nAuthored `question_list`, `question_rounds`, and `question_workspace` may declare\n`card_groups` with a unique `id`, `title`, and ordered `question_ids`. Members\nmust be contiguous in the existing record order and, for round workspaces, stay\nwithin one round. Invalid groups fall back to ordinary cards with a diagnostic;\ngrouping never reorders canonical records. Generated-origin Panels reject this\nauthored extension.\n\nEach group may declare a `presentation` object containing only optional boolean\n`always_expanded`, `show_detail`, and `show_attachments` properties. These select\nshared component behavior, not Bundle-specific styling. Omission preserves the\nusual collapse, detail, and attachment controls. Hiding a control preserves its\ncanonical data; keeping a card expanded does not grant editing permission.\nRead-only, disabled, protected, historical and rejection guards still apply.\n\n`question_workspace` composes the same question cards with the standard\n`panel_workspace` navigation shell. It groups records by optional numeric\n`round`, shows answer progress, and keeps only the selected group in the main\npane; records without a round form one current group. Its optional\n`description` is rendered through the shared sticky workspace Tip Bar above\nthe main content, never squeezed into the navigation sidebar. `question_rounds` is the\nbackward-compatible alias for this workspace behavior. Optional\n`multimodal_answer[]` entries use the Web App-compatible local reference shape\n(`type`, `file_md5`, `filename`, `mime_type`, `size_bytes`, `artifact_file`).\nThe client keeps pending bytes in a reserved browser-only transport, strips it\nbefore schema validation, and atomically saves only files still referenced by\ncanonical state. The transport is framework state, never a Bundle field.\n\nAuthored `question_workspace` / `question_rounds` nodes may explicitly set\n`question_policy.allow_choice_actions: true`. Expanded editable dynamic single\ncards offer “Switch to multiple choice”; multiple cards offer “Select all” /\n“Deselect all”. Omission or `false` preserves the existing controls. The shared\nruntime owns these actions and their localized styling, not Bundle CSS or an\nauthor-supplied `renderActions` callback. Switching changes only `kind` to\n`multiple`, preserving the exact answer bytes and keeping the editor open.\nSelect-all writes choice values in declared order through the existing\ncomma-separated `answer` contract; deselect-all writes an empty answer. Neither\naction changes detail, attachments, identity, choices or round. Records declared\nin `first_round_ids` are the fixed first-round configuration and do not receive\nthese actions; `protected_ids` still controls rejection only. Read-only,\ndisabled, rejected and read-only historical cards cannot invoke the actions.\nGenerated-origin/A2UI auto Panels reject this configuration, even when `false`;\ntheir existing answer/detail-only write authority and protected `kind` remain\nunchanged. Converting a generated view into an authored reusable panel does not\nsilently grant this capability: the author must opt in under the static contract.\n\n`panel_workspace` is the reusable panel-internal left navigation + main content\nlayout. It standardizes containment, scroll ownership and narrow-panel fallback;\nit does not define domain records or selection semantics. Use it rather than\ncopying a Kit-specific two-column shell.\n\nThe shared runtime `PanelWorkspaceNavigation` accepts optional per-item\n`description`, `supporting`, and `statusLabel` display slots alongside the\nlabel/current row. These are supplied display text, not canonical fields or\nnew DSL expressions. Omitted slots render no empty rows. The `meta` fallback\nremains supported. A marker requires both explicit `statusIndicator: true`\nand an existing `status`; a label-only item never gains an inferred status dot.\nFlat record navigation, question rounds, and future workspace consumers share\nthe same base navigation typography, spacing and selected appearance. Bundle\nCSS is not required. Hierarchical trees retain their separate structure.\nQuestion progress excludes rejected items from answered/completion checks,\nwhile retaining all group records in the displayed total and preserving fixed\nquestion grouping, stable IDs, selection and canonical answers. The original\nWeb App question panel used body round sections, not this sidebar; the shared\nsidebar is an enhanced structure using the original public navigation style,\nnot a claim of one-to-one restoration of a nonexistent original sidebar.\n\n`doc_lifecycle_studio` binds `objects`/`axes`/`actions` sections (validation\nfails loud when one is missing) and renders the fact table (actions × state\naxes, per-cell effects) plus process/derivation/ledger projections derived at\nrender time; unavailable views render disabled with a reason, never hidden.\n`rowview_workbench` renders the residue envelope (below) and requires a\n`source` declaring the add section it owns — the details-envelope schema\ncheck and the renderer are both scoped to that section; a workbench without\n`source` is rejected at compile time.\n\nIn editable mode `bpmn_canvas` edits bidirectionally: each process record's\n`name` and `steps` array (step name, `kind` task/gateway/event, order, add,\nremove) round-trip through the panel Save like any field edit.\n"
|
|
6594
6594
|
}
|
|
@@ -6703,8 +6703,8 @@
|
|
|
6703
6703
|
"sections": [
|
|
6704
6704
|
{
|
|
6705
6705
|
"file": "docs/dsl-spec.md",
|
|
6706
|
-
"line":
|
|
6707
|
-
"endLine":
|
|
6706
|
+
"line": 958,
|
|
6707
|
+
"endLine": 1169,
|
|
6708
6708
|
"heading": "`component` (trusted, extensible library)",
|
|
6709
6709
|
"content": "### `component` (trusted, extensible library)\n\nThe authoritative vocabulary is [`PANEL_COMPONENT_CATALOG`](../packages/core/src/panel-component-catalog.ts).\n`COMPONENT_KINDS`, workspace ownership, source bindings and the generated-panel\nsubset are derived from that one registry; this document is not a second\nvalidation whitelist. Bundle data cannot register executable components.\n\nThe shared library includes basic layouts and controls, question workspaces,\nrecord navigation/editing, diagrams, canvases, artifact readers and previews.\nFull-height workspace components preserve scroll and navigation ownership:\n`record_board`, `document_workspace`, `artifact_workspace`, `diagram_workspace`,\n`canvas_workspace`, `preview_workspace` and `navigation_workspace` expose their\nbehavior through explicit data bindings rather than Kit names. These are reusable\ncapabilities, not a guarantee that every record schema fits every workspace.\n\n`record_board.board.detail_sources` can embed exactly one `record_workspace`\nunder the selected card. Each `{section, reference}` binding declares an unordered\ndirect record collection and a readonly `record_select` back to the board's\nparent section. The child workspace sources must belong to those bindings.\nOwner and child storage paths cannot alias or overlap. The renderer filters\nchildren by the selected parent, binds new records to it, and merges hidden\nsibling records back into canonical updates. It refuses sibling-id replacement,\nreparenting and writes outside these collections. This is a view projection,\nnot a second stored copy; it does not support independently ordered child maps,\nnested `fields_path` records or artifact staging in this first composition slice.\nOrdinary `detail_sections` retain their existing same-record nested-form meaning.\n\n`record_board` uses full-width cards and a workspace-covering overview. Optional\n`board.group` binds a real grouping field. When omitted, the sidebar lists records\ndirectly, cards have no artificial group heading, and the overview connects the\nroot directly to records. Do not bind long summaries merely to satisfy grouping;\nthis projection never adds a grouping field to canonical records.\nSidebar selection scrolls to a card; it does not start editing. Description and\nbadge drafts have explicit Save/Cancel, while rejected records remain inspectable\nwithout granting edit access. Optional `board.id_field` binds a declared visible,\nreadonly `text` field and displays its existing string beside the card title and\nat the top of cover details. Inline details retain the same card header. It does\nnot add an ID editor, generate a fallback ID or write state; omission retains the\nexisting title-only presentation. `board.detail_fields` restricts the parent fields\nshown in the detail fold, and `details_title` localizes its heading. Optional nested\ndimensions can be added or removed without replacing unrelated record fields.\n`board.detail_fields_mode: fixed` instead shows every declared nested input and\nremoves dimension-level add/delete controls; collection item add/delete still\nuses its usual editor. Fields remain schema-optional, including empty inputs.\nViewing does not insert missing strings/maps. Omitted/`on_demand` retains the\nexisting optional-dimension behavior. This option grants no new write authority.\n\n`record_workspace.workspace_view: switch` puts the first child canvas over the\nwhole workspace. The edge action opens it, and the return action or a node's\ndetails action returns to the selected record. It does not add form/canvas tabs\nto the sidebar. Covered content stays mounted and inert to preserve selection,\ndrafts and the graph viewport without allowing hidden controls to receive input.\n\n`record_related_editor.record_table` is an authored-only table presentation of\nthe same child collection, not a conversion to a `rows` array. Its finite\n`columns: [{fields: [field_key, ...], label?: string}]` groups existing field\neditors into cells. Every non-hidden field declared for that child section must\nappear exactly once; hidden/foreign/duplicate bindings and unknown column keys\nare rejected. Column labels default to the first field's label and use the usual\nlocale resolution. A cell retains field visibility, help, requiredness, custom\nconditions and existing edit/derived-field rules. Record creation still binds\nthe selected parent, deletion preserves the normal section cleanup rules, and\n`inherit_from_graph` tables remain source-linked and read-only. The shared table\nwrapper owns horizontal scrolling at narrow widths. This does not promote the\ncomponent or this declaration to generated A2UI.\n\nAn authored graph hierarchy with `max_parents: 1` may opt into\n`parent_control: header`. The existing single-parent selector then sits beside\nthe selected record's form title, rather than above the whole inspector. It\nstill updates the same relation edge, rejects cycles, retains the source-record\nnavigation and shows the actual parent in read-only mode. Omission preserves\nthe prior inspector presentation; neither view creates an extra parent field.\n\n`diagram_workspace.diagram.detail_rows` groups declared read-only fields into\nresponsive fact cards. `chip_fields` selects string-list fields rendered as tags;\n`detail_hint_fields` supplies the populated field labels for the details action.\n`tags` maps declared enum fields to labels and finite semantic tones. These are\npresentation declarations, not new edit rights or storage. Diagram details cover\nonly the content pane; the navigator remains available. Leaving an edited diagram\nstill requires successful serialization through the existing save barrier.\n\n`diagram_workspace.diagram.label_source` can read a declared label from another\nsection bound to the same record collection. The optional `inspector` keeps a\ncontext editor alongside the BPMN canvas: `process_sections` edit the selected\nprocess; `nodes` binds `source`, `process_field`, `element_field`, `label_field`\nand same-collection `sections`. Optional `related` groups use a process reference\nand an optional `node_field`; `advanced: true` starts the group collapsed.\nReferences must be declared `record_select` fields targeting the corresponding\ncollection. Clicking an element resolves its exact ID within the selected\nprocess only; absent or duplicate bindings do not guess a record. Existing field\nedit permissions and the atomic artifact save barrier remain authoritative.\nThis is contextual navigation, not automatic synchronization of BPMN structure\nand business facts; authors must explain how structural changes are reconciled.\n\nFor an exact component contract and on-demand local type declarations, use the\nauthoring inspector from the repository root:\n\n```sh\nnode .agents/skills/design-bundle-creator/scripts/inspect-panel-component.mjs . navigation_workspace --type ComponentNode.navigation_map.edges\n```\n\nUse the [component extension contract](a2ui-component-catalog-contract.md) when\nadding a component: catalog, validation, renderer, styles, edit boundaries,\ntests and authoring guidance must agree. Trusted runtime additions are possible;\nunknown component names in a manifest are rejected.\n\nAcceptance of a component name alone does not establish rendering fidelity,\neditable lifecycle support, or compatibility with every host; those require\nthe component's binding contract and actual runtime verification.\n\nPredefined DSL and A2UI-derived panels share this library, but generated panels\nmay use only the subset with an implemented generation/edit-authority contract.\nAn authored workspace is not automatically promoted into that subset.\nSupported generated results can be deterministically retained as DSL; unsupported\ncapabilities must fail explicitly, never disappear during conversion. This is\nnot an arbitrary bidirectional A2UI protocol converter.\n\n`question_list` is the standard controlled question interaction. Each source\nrecord uses `prompt`, optional `note`, `kind` (`text | single | multiple`),\noptional `choices[]` (`value`, `label`, `recommended`), `answer`, and optional\n`detail`. Text answers render as one multiline input; an existing text-question\n`detail` remains visible as read-only context rather than becoming a second\nanswer box. Single/multiple answers use accessible choice rows and may edit\n`detail`. Existing read-only context and choice supplements use the same\nlocalized label (without the optional-input suffix in reading mode). Cards\nwith a non-empty `answer` collapse to a readable result and can\nbe reopened for editing. The component writes only the fields exposed by that\ninteraction back to the owning record. It does not invent approval state, and an\nempty answer remains unanswered even when `detail` contains context. Native\nproviders may explicitly extend answer-state semantics for attachments, and\nmay add rounds or rejection around this base contract without making those\nextensions mandatory for other Kits.\n\nAuthored `question_list`, `question_rounds`, and `question_workspace` may declare\n`card_groups` with a unique `id`, `title`, and ordered `question_ids`. Members\nmust be contiguous in the existing record order and, for round workspaces, stay\nwithin one round. Invalid groups fall back to ordinary cards with a diagnostic;\ngrouping never reorders canonical records. Generated-origin Panels reject this\nauthored extension.\n\nEach group may declare a `presentation` object containing only optional boolean\n`always_expanded`, `show_detail`, and `show_attachments` properties. These select\nshared component behavior, not Bundle-specific styling. Omission preserves the\nusual collapse, detail, and attachment controls. Hiding a control preserves its\ncanonical data; keeping a card expanded does not grant editing permission.\nRead-only, disabled, protected, historical and rejection guards still apply.\n\n`question_workspace` composes the same question cards with the standard\n`panel_workspace` navigation shell. It groups records by optional numeric\n`round`, shows answer progress, and keeps only the selected group in the main\npane; records without a round form one current group. Its optional\n`description` is rendered through the shared sticky workspace Tip Bar above\nthe main content, never squeezed into the navigation sidebar. `question_rounds` is the\nbackward-compatible alias for this workspace behavior. Optional\n`multimodal_answer[]` entries use the Web App-compatible local reference shape\n(`type`, `file_md5`, `filename`, `mime_type`, `size_bytes`, `artifact_file`).\nThe client keeps pending bytes in a reserved browser-only transport, strips it\nbefore schema validation, and atomically saves only files still referenced by\ncanonical state. The transport is framework state, never a Bundle field.\n\nAuthored `question_workspace` / `question_rounds` nodes may explicitly set\n`question_policy.allow_choice_actions: true`. Expanded editable dynamic single\ncards offer “Switch to multiple choice”; multiple cards offer “Select all” /\n“Deselect all”. Omission or `false` preserves the existing controls. The shared\nruntime owns these actions and their localized styling, not Bundle CSS or an\nauthor-supplied `renderActions` callback. Switching changes only `kind` to\n`multiple`, preserving the exact answer bytes and keeping the editor open.\nSelect-all writes choice values in declared order through the existing\ncomma-separated `answer` contract; deselect-all writes an empty answer. Neither\naction changes detail, attachments, identity, choices or round. Records declared\nin `first_round_ids` are the fixed first-round configuration and do not receive\nthese actions; `protected_ids` still controls rejection only. Read-only,\ndisabled, rejected and read-only historical cards cannot invoke the actions.\nGenerated-origin/A2UI auto Panels reject this configuration, even when `false`;\ntheir existing answer/detail-only write authority and protected `kind` remain\nunchanged. Converting a generated view into an authored reusable panel does not\nsilently grant this capability: the author must opt in under the static contract.\n\n`panel_workspace` is the reusable panel-internal left navigation + main content\nlayout. It standardizes containment, scroll ownership and narrow-panel fallback;\nit does not define domain records or selection semantics. Use it rather than\ncopying a Kit-specific two-column shell.\n\nThe shared runtime `PanelWorkspaceNavigation` accepts optional per-item\n`description`, `supporting`, and `statusLabel` display slots alongside the\nlabel/current row. These are supplied display text, not canonical fields or\nnew DSL expressions. Omitted slots render no empty rows. The `meta` fallback\nremains supported. A marker requires both explicit `statusIndicator: true`\nand an existing `status`; a label-only item never gains an inferred status dot.\nFlat record navigation, question rounds, and future workspace consumers share\nthe same base navigation typography, spacing and selected appearance. Bundle\nCSS is not required. Hierarchical trees retain their separate structure.\nQuestion progress excludes rejected items from answered/completion checks,\nwhile retaining all group records in the displayed total and preserving fixed\nquestion grouping, stable IDs, selection and canonical answers. The original\nWeb App question panel used body round sections, not this sidebar; the shared\nsidebar is an enhanced structure using the original public navigation style,\nnot a claim of one-to-one restoration of a nonexistent original sidebar.\n\n`doc_lifecycle_studio` binds `objects`/`axes`/`actions` sections (validation\nfails loud when one is missing) and renders the fact table (actions × state\naxes, per-cell effects) plus process/derivation/ledger projections derived at\nrender time; unavailable views render disabled with a reason, never hidden.\n`rowview_workbench` renders the residue envelope (below) and requires a\n`source` declaring the add section it owns — the details-envelope schema\ncheck and the renderer are both scoped to that section; a workbench without\n`source` is rejected at compile time.\n\nIn editable mode `bpmn_canvas` edits bidirectionally: each process record's\n`name` and `steps` array (step name, `kind` task/gateway/event, order, add,\nremove) round-trip through the panel Save like any field edit.\n"
|
|
6710
6710
|
}
|
|
@@ -6819,8 +6819,8 @@
|
|
|
6819
6819
|
"sections": [
|
|
6820
6820
|
{
|
|
6821
6821
|
"file": "docs/dsl-spec.md",
|
|
6822
|
-
"line":
|
|
6823
|
-
"endLine":
|
|
6822
|
+
"line": 958,
|
|
6823
|
+
"endLine": 1169,
|
|
6824
6824
|
"heading": "`component` (trusted, extensible library)",
|
|
6825
6825
|
"content": "### `component` (trusted, extensible library)\n\nThe authoritative vocabulary is [`PANEL_COMPONENT_CATALOG`](../packages/core/src/panel-component-catalog.ts).\n`COMPONENT_KINDS`, workspace ownership, source bindings and the generated-panel\nsubset are derived from that one registry; this document is not a second\nvalidation whitelist. Bundle data cannot register executable components.\n\nThe shared library includes basic layouts and controls, question workspaces,\nrecord navigation/editing, diagrams, canvases, artifact readers and previews.\nFull-height workspace components preserve scroll and navigation ownership:\n`record_board`, `document_workspace`, `artifact_workspace`, `diagram_workspace`,\n`canvas_workspace`, `preview_workspace` and `navigation_workspace` expose their\nbehavior through explicit data bindings rather than Kit names. These are reusable\ncapabilities, not a guarantee that every record schema fits every workspace.\n\n`record_board.board.detail_sources` can embed exactly one `record_workspace`\nunder the selected card. Each `{section, reference}` binding declares an unordered\ndirect record collection and a readonly `record_select` back to the board's\nparent section. The child workspace sources must belong to those bindings.\nOwner and child storage paths cannot alias or overlap. The renderer filters\nchildren by the selected parent, binds new records to it, and merges hidden\nsibling records back into canonical updates. It refuses sibling-id replacement,\nreparenting and writes outside these collections. This is a view projection,\nnot a second stored copy; it does not support independently ordered child maps,\nnested `fields_path` records or artifact staging in this first composition slice.\nOrdinary `detail_sections` retain their existing same-record nested-form meaning.\n\n`record_board` uses full-width cards and a workspace-covering overview. Optional\n`board.group` binds a real grouping field. When omitted, the sidebar lists records\ndirectly, cards have no artificial group heading, and the overview connects the\nroot directly to records. Do not bind long summaries merely to satisfy grouping;\nthis projection never adds a grouping field to canonical records.\nSidebar selection scrolls to a card; it does not start editing. Description and\nbadge drafts have explicit Save/Cancel, while rejected records remain inspectable\nwithout granting edit access. Optional `board.id_field` binds a declared visible,\nreadonly `text` field and displays its existing string beside the card title and\nat the top of cover details. Inline details retain the same card header. It does\nnot add an ID editor, generate a fallback ID or write state; omission retains the\nexisting title-only presentation. `board.detail_fields` restricts the parent fields\nshown in the detail fold, and `details_title` localizes its heading. Optional nested\ndimensions can be added or removed without replacing unrelated record fields.\n`board.detail_fields_mode: fixed` instead shows every declared nested input and\nremoves dimension-level add/delete controls; collection item add/delete still\nuses its usual editor. Fields remain schema-optional, including empty inputs.\nViewing does not insert missing strings/maps. Omitted/`on_demand` retains the\nexisting optional-dimension behavior. This option grants no new write authority.\n\n`record_workspace.workspace_view: switch` puts the first child canvas over the\nwhole workspace. The edge action opens it, and the return action or a node's\ndetails action returns to the selected record. It does not add form/canvas tabs\nto the sidebar. Covered content stays mounted and inert to preserve selection,\ndrafts and the graph viewport without allowing hidden controls to receive input.\n\n`record_related_editor.record_table` is an authored-only table presentation of\nthe same child collection, not a conversion to a `rows` array. Its finite\n`columns: [{fields: [field_key, ...], label?: string}]` groups existing field\neditors into cells. Every non-hidden field declared for that child section must\nappear exactly once; hidden/foreign/duplicate bindings and unknown column keys\nare rejected. Column labels default to the first field's label and use the usual\nlocale resolution. A cell retains field visibility, help, requiredness, custom\nconditions and existing edit/derived-field rules. Record creation still binds\nthe selected parent, deletion preserves the normal section cleanup rules, and\n`inherit_from_graph` tables remain source-linked and read-only. The shared table\nwrapper owns horizontal scrolling at narrow widths. This does not promote the\ncomponent or this declaration to generated A2UI.\n\nAn authored graph hierarchy with `max_parents: 1` may opt into\n`parent_control: header`. The existing single-parent selector then sits beside\nthe selected record's form title, rather than above the whole inspector. It\nstill updates the same relation edge, rejects cycles, retains the source-record\nnavigation and shows the actual parent in read-only mode. Omission preserves\nthe prior inspector presentation; neither view creates an extra parent field.\n\n`diagram_workspace.diagram.detail_rows` groups declared read-only fields into\nresponsive fact cards. `chip_fields` selects string-list fields rendered as tags;\n`detail_hint_fields` supplies the populated field labels for the details action.\n`tags` maps declared enum fields to labels and finite semantic tones. These are\npresentation declarations, not new edit rights or storage. Diagram details cover\nonly the content pane; the navigator remains available. Leaving an edited diagram\nstill requires successful serialization through the existing save barrier.\n\n`diagram_workspace.diagram.label_source` can read a declared label from another\nsection bound to the same record collection. The optional `inspector` keeps a\ncontext editor alongside the BPMN canvas: `process_sections` edit the selected\nprocess; `nodes` binds `source`, `process_field`, `element_field`, `label_field`\nand same-collection `sections`. Optional `related` groups use a process reference\nand an optional `node_field`; `advanced: true` starts the group collapsed.\nReferences must be declared `record_select` fields targeting the corresponding\ncollection. Clicking an element resolves its exact ID within the selected\nprocess only; absent or duplicate bindings do not guess a record. Existing field\nedit permissions and the atomic artifact save barrier remain authoritative.\nThis is contextual navigation, not automatic synchronization of BPMN structure\nand business facts; authors must explain how structural changes are reconciled.\n\nFor an exact component contract and on-demand local type declarations, use the\nauthoring inspector from the repository root:\n\n```sh\nnode .agents/skills/design-bundle-creator/scripts/inspect-panel-component.mjs . navigation_workspace --type ComponentNode.navigation_map.edges\n```\n\nUse the [component extension contract](a2ui-component-catalog-contract.md) when\nadding a component: catalog, validation, renderer, styles, edit boundaries,\ntests and authoring guidance must agree. Trusted runtime additions are possible;\nunknown component names in a manifest are rejected.\n\nAcceptance of a component name alone does not establish rendering fidelity,\neditable lifecycle support, or compatibility with every host; those require\nthe component's binding contract and actual runtime verification.\n\nPredefined DSL and A2UI-derived panels share this library, but generated panels\nmay use only the subset with an implemented generation/edit-authority contract.\nAn authored workspace is not automatically promoted into that subset.\nSupported generated results can be deterministically retained as DSL; unsupported\ncapabilities must fail explicitly, never disappear during conversion. This is\nnot an arbitrary bidirectional A2UI protocol converter.\n\n`question_list` is the standard controlled question interaction. Each source\nrecord uses `prompt`, optional `note`, `kind` (`text | single | multiple`),\noptional `choices[]` (`value`, `label`, `recommended`), `answer`, and optional\n`detail`. Text answers render as one multiline input; an existing text-question\n`detail` remains visible as read-only context rather than becoming a second\nanswer box. Single/multiple answers use accessible choice rows and may edit\n`detail`. Existing read-only context and choice supplements use the same\nlocalized label (without the optional-input suffix in reading mode). Cards\nwith a non-empty `answer` collapse to a readable result and can\nbe reopened for editing. The component writes only the fields exposed by that\ninteraction back to the owning record. It does not invent approval state, and an\nempty answer remains unanswered even when `detail` contains context. Native\nproviders may explicitly extend answer-state semantics for attachments, and\nmay add rounds or rejection around this base contract without making those\nextensions mandatory for other Kits.\n\nAuthored `question_list`, `question_rounds`, and `question_workspace` may declare\n`card_groups` with a unique `id`, `title`, and ordered `question_ids`. Members\nmust be contiguous in the existing record order and, for round workspaces, stay\nwithin one round. Invalid groups fall back to ordinary cards with a diagnostic;\ngrouping never reorders canonical records. Generated-origin Panels reject this\nauthored extension.\n\nEach group may declare a `presentation` object containing only optional boolean\n`always_expanded`, `show_detail`, and `show_attachments` properties. These select\nshared component behavior, not Bundle-specific styling. Omission preserves the\nusual collapse, detail, and attachment controls. Hiding a control preserves its\ncanonical data; keeping a card expanded does not grant editing permission.\nRead-only, disabled, protected, historical and rejection guards still apply.\n\n`question_workspace` composes the same question cards with the standard\n`panel_workspace` navigation shell. It groups records by optional numeric\n`round`, shows answer progress, and keeps only the selected group in the main\npane; records without a round form one current group. Its optional\n`description` is rendered through the shared sticky workspace Tip Bar above\nthe main content, never squeezed into the navigation sidebar. `question_rounds` is the\nbackward-compatible alias for this workspace behavior. Optional\n`multimodal_answer[]` entries use the Web App-compatible local reference shape\n(`type`, `file_md5`, `filename`, `mime_type`, `size_bytes`, `artifact_file`).\nThe client keeps pending bytes in a reserved browser-only transport, strips it\nbefore schema validation, and atomically saves only files still referenced by\ncanonical state. The transport is framework state, never a Bundle field.\n\nAuthored `question_workspace` / `question_rounds` nodes may explicitly set\n`question_policy.allow_choice_actions: true`. Expanded editable dynamic single\ncards offer “Switch to multiple choice”; multiple cards offer “Select all” /\n“Deselect all”. Omission or `false` preserves the existing controls. The shared\nruntime owns these actions and their localized styling, not Bundle CSS or an\nauthor-supplied `renderActions` callback. Switching changes only `kind` to\n`multiple`, preserving the exact answer bytes and keeping the editor open.\nSelect-all writes choice values in declared order through the existing\ncomma-separated `answer` contract; deselect-all writes an empty answer. Neither\naction changes detail, attachments, identity, choices or round. Records declared\nin `first_round_ids` are the fixed first-round configuration and do not receive\nthese actions; `protected_ids` still controls rejection only. Read-only,\ndisabled, rejected and read-only historical cards cannot invoke the actions.\nGenerated-origin/A2UI auto Panels reject this configuration, even when `false`;\ntheir existing answer/detail-only write authority and protected `kind` remain\nunchanged. Converting a generated view into an authored reusable panel does not\nsilently grant this capability: the author must opt in under the static contract.\n\n`panel_workspace` is the reusable panel-internal left navigation + main content\nlayout. It standardizes containment, scroll ownership and narrow-panel fallback;\nit does not define domain records or selection semantics. Use it rather than\ncopying a Kit-specific two-column shell.\n\nThe shared runtime `PanelWorkspaceNavigation` accepts optional per-item\n`description`, `supporting`, and `statusLabel` display slots alongside the\nlabel/current row. These are supplied display text, not canonical fields or\nnew DSL expressions. Omitted slots render no empty rows. The `meta` fallback\nremains supported. A marker requires both explicit `statusIndicator: true`\nand an existing `status`; a label-only item never gains an inferred status dot.\nFlat record navigation, question rounds, and future workspace consumers share\nthe same base navigation typography, spacing and selected appearance. Bundle\nCSS is not required. Hierarchical trees retain their separate structure.\nQuestion progress excludes rejected items from answered/completion checks,\nwhile retaining all group records in the displayed total and preserving fixed\nquestion grouping, stable IDs, selection and canonical answers. The original\nWeb App question panel used body round sections, not this sidebar; the shared\nsidebar is an enhanced structure using the original public navigation style,\nnot a claim of one-to-one restoration of a nonexistent original sidebar.\n\n`doc_lifecycle_studio` binds `objects`/`axes`/`actions` sections (validation\nfails loud when one is missing) and renders the fact table (actions × state\naxes, per-cell effects) plus process/derivation/ledger projections derived at\nrender time; unavailable views render disabled with a reason, never hidden.\n`rowview_workbench` renders the residue envelope (below) and requires a\n`source` declaring the add section it owns — the details-envelope schema\ncheck and the renderer are both scoped to that section; a workbench without\n`source` is rejected at compile time.\n\nIn editable mode `bpmn_canvas` edits bidirectionally: each process record's\n`name` and `steps` array (step name, `kind` task/gateway/event, order, add,\nremove) round-trip through the panel Save like any field edit.\n"
|
|
6826
6826
|
}
|
|
@@ -6935,8 +6935,8 @@
|
|
|
6935
6935
|
"sections": [
|
|
6936
6936
|
{
|
|
6937
6937
|
"file": "docs/dsl-spec.md",
|
|
6938
|
-
"line":
|
|
6939
|
-
"endLine":
|
|
6938
|
+
"line": 958,
|
|
6939
|
+
"endLine": 1169,
|
|
6940
6940
|
"heading": "`component` (trusted, extensible library)",
|
|
6941
6941
|
"content": "### `component` (trusted, extensible library)\n\nThe authoritative vocabulary is [`PANEL_COMPONENT_CATALOG`](../packages/core/src/panel-component-catalog.ts).\n`COMPONENT_KINDS`, workspace ownership, source bindings and the generated-panel\nsubset are derived from that one registry; this document is not a second\nvalidation whitelist. Bundle data cannot register executable components.\n\nThe shared library includes basic layouts and controls, question workspaces,\nrecord navigation/editing, diagrams, canvases, artifact readers and previews.\nFull-height workspace components preserve scroll and navigation ownership:\n`record_board`, `document_workspace`, `artifact_workspace`, `diagram_workspace`,\n`canvas_workspace`, `preview_workspace` and `navigation_workspace` expose their\nbehavior through explicit data bindings rather than Kit names. These are reusable\ncapabilities, not a guarantee that every record schema fits every workspace.\n\n`record_board.board.detail_sources` can embed exactly one `record_workspace`\nunder the selected card. Each `{section, reference}` binding declares an unordered\ndirect record collection and a readonly `record_select` back to the board's\nparent section. The child workspace sources must belong to those bindings.\nOwner and child storage paths cannot alias or overlap. The renderer filters\nchildren by the selected parent, binds new records to it, and merges hidden\nsibling records back into canonical updates. It refuses sibling-id replacement,\nreparenting and writes outside these collections. This is a view projection,\nnot a second stored copy; it does not support independently ordered child maps,\nnested `fields_path` records or artifact staging in this first composition slice.\nOrdinary `detail_sections` retain their existing same-record nested-form meaning.\n\n`record_board` uses full-width cards and a workspace-covering overview. Optional\n`board.group` binds a real grouping field. When omitted, the sidebar lists records\ndirectly, cards have no artificial group heading, and the overview connects the\nroot directly to records. Do not bind long summaries merely to satisfy grouping;\nthis projection never adds a grouping field to canonical records.\nSidebar selection scrolls to a card; it does not start editing. Description and\nbadge drafts have explicit Save/Cancel, while rejected records remain inspectable\nwithout granting edit access. Optional `board.id_field` binds a declared visible,\nreadonly `text` field and displays its existing string beside the card title and\nat the top of cover details. Inline details retain the same card header. It does\nnot add an ID editor, generate a fallback ID or write state; omission retains the\nexisting title-only presentation. `board.detail_fields` restricts the parent fields\nshown in the detail fold, and `details_title` localizes its heading. Optional nested\ndimensions can be added or removed without replacing unrelated record fields.\n`board.detail_fields_mode: fixed` instead shows every declared nested input and\nremoves dimension-level add/delete controls; collection item add/delete still\nuses its usual editor. Fields remain schema-optional, including empty inputs.\nViewing does not insert missing strings/maps. Omitted/`on_demand` retains the\nexisting optional-dimension behavior. This option grants no new write authority.\n\n`record_workspace.workspace_view: switch` puts the first child canvas over the\nwhole workspace. The edge action opens it, and the return action or a node's\ndetails action returns to the selected record. It does not add form/canvas tabs\nto the sidebar. Covered content stays mounted and inert to preserve selection,\ndrafts and the graph viewport without allowing hidden controls to receive input.\n\n`record_related_editor.record_table` is an authored-only table presentation of\nthe same child collection, not a conversion to a `rows` array. Its finite\n`columns: [{fields: [field_key, ...], label?: string}]` groups existing field\neditors into cells. Every non-hidden field declared for that child section must\nappear exactly once; hidden/foreign/duplicate bindings and unknown column keys\nare rejected. Column labels default to the first field's label and use the usual\nlocale resolution. A cell retains field visibility, help, requiredness, custom\nconditions and existing edit/derived-field rules. Record creation still binds\nthe selected parent, deletion preserves the normal section cleanup rules, and\n`inherit_from_graph` tables remain source-linked and read-only. The shared table\nwrapper owns horizontal scrolling at narrow widths. This does not promote the\ncomponent or this declaration to generated A2UI.\n\nAn authored graph hierarchy with `max_parents: 1` may opt into\n`parent_control: header`. The existing single-parent selector then sits beside\nthe selected record's form title, rather than above the whole inspector. It\nstill updates the same relation edge, rejects cycles, retains the source-record\nnavigation and shows the actual parent in read-only mode. Omission preserves\nthe prior inspector presentation; neither view creates an extra parent field.\n\n`diagram_workspace.diagram.detail_rows` groups declared read-only fields into\nresponsive fact cards. `chip_fields` selects string-list fields rendered as tags;\n`detail_hint_fields` supplies the populated field labels for the details action.\n`tags` maps declared enum fields to labels and finite semantic tones. These are\npresentation declarations, not new edit rights or storage. Diagram details cover\nonly the content pane; the navigator remains available. Leaving an edited diagram\nstill requires successful serialization through the existing save barrier.\n\n`diagram_workspace.diagram.label_source` can read a declared label from another\nsection bound to the same record collection. The optional `inspector` keeps a\ncontext editor alongside the BPMN canvas: `process_sections` edit the selected\nprocess; `nodes` binds `source`, `process_field`, `element_field`, `label_field`\nand same-collection `sections`. Optional `related` groups use a process reference\nand an optional `node_field`; `advanced: true` starts the group collapsed.\nReferences must be declared `record_select` fields targeting the corresponding\ncollection. Clicking an element resolves its exact ID within the selected\nprocess only; absent or duplicate bindings do not guess a record. Existing field\nedit permissions and the atomic artifact save barrier remain authoritative.\nThis is contextual navigation, not automatic synchronization of BPMN structure\nand business facts; authors must explain how structural changes are reconciled.\n\nFor an exact component contract and on-demand local type declarations, use the\nauthoring inspector from the repository root:\n\n```sh\nnode .agents/skills/design-bundle-creator/scripts/inspect-panel-component.mjs . navigation_workspace --type ComponentNode.navigation_map.edges\n```\n\nUse the [component extension contract](a2ui-component-catalog-contract.md) when\nadding a component: catalog, validation, renderer, styles, edit boundaries,\ntests and authoring guidance must agree. Trusted runtime additions are possible;\nunknown component names in a manifest are rejected.\n\nAcceptance of a component name alone does not establish rendering fidelity,\neditable lifecycle support, or compatibility with every host; those require\nthe component's binding contract and actual runtime verification.\n\nPredefined DSL and A2UI-derived panels share this library, but generated panels\nmay use only the subset with an implemented generation/edit-authority contract.\nAn authored workspace is not automatically promoted into that subset.\nSupported generated results can be deterministically retained as DSL; unsupported\ncapabilities must fail explicitly, never disappear during conversion. This is\nnot an arbitrary bidirectional A2UI protocol converter.\n\n`question_list` is the standard controlled question interaction. Each source\nrecord uses `prompt`, optional `note`, `kind` (`text | single | multiple`),\noptional `choices[]` (`value`, `label`, `recommended`), `answer`, and optional\n`detail`. Text answers render as one multiline input; an existing text-question\n`detail` remains visible as read-only context rather than becoming a second\nanswer box. Single/multiple answers use accessible choice rows and may edit\n`detail`. Existing read-only context and choice supplements use the same\nlocalized label (without the optional-input suffix in reading mode). Cards\nwith a non-empty `answer` collapse to a readable result and can\nbe reopened for editing. The component writes only the fields exposed by that\ninteraction back to the owning record. It does not invent approval state, and an\nempty answer remains unanswered even when `detail` contains context. Native\nproviders may explicitly extend answer-state semantics for attachments, and\nmay add rounds or rejection around this base contract without making those\nextensions mandatory for other Kits.\n\nAuthored `question_list`, `question_rounds`, and `question_workspace` may declare\n`card_groups` with a unique `id`, `title`, and ordered `question_ids`. Members\nmust be contiguous in the existing record order and, for round workspaces, stay\nwithin one round. Invalid groups fall back to ordinary cards with a diagnostic;\ngrouping never reorders canonical records. Generated-origin Panels reject this\nauthored extension.\n\nEach group may declare a `presentation` object containing only optional boolean\n`always_expanded`, `show_detail`, and `show_attachments` properties. These select\nshared component behavior, not Bundle-specific styling. Omission preserves the\nusual collapse, detail, and attachment controls. Hiding a control preserves its\ncanonical data; keeping a card expanded does not grant editing permission.\nRead-only, disabled, protected, historical and rejection guards still apply.\n\n`question_workspace` composes the same question cards with the standard\n`panel_workspace` navigation shell. It groups records by optional numeric\n`round`, shows answer progress, and keeps only the selected group in the main\npane; records without a round form one current group. Its optional\n`description` is rendered through the shared sticky workspace Tip Bar above\nthe main content, never squeezed into the navigation sidebar. `question_rounds` is the\nbackward-compatible alias for this workspace behavior. Optional\n`multimodal_answer[]` entries use the Web App-compatible local reference shape\n(`type`, `file_md5`, `filename`, `mime_type`, `size_bytes`, `artifact_file`).\nThe client keeps pending bytes in a reserved browser-only transport, strips it\nbefore schema validation, and atomically saves only files still referenced by\ncanonical state. The transport is framework state, never a Bundle field.\n\nAuthored `question_workspace` / `question_rounds` nodes may explicitly set\n`question_policy.allow_choice_actions: true`. Expanded editable dynamic single\ncards offer “Switch to multiple choice”; multiple cards offer “Select all” /\n“Deselect all”. Omission or `false` preserves the existing controls. The shared\nruntime owns these actions and their localized styling, not Bundle CSS or an\nauthor-supplied `renderActions` callback. Switching changes only `kind` to\n`multiple`, preserving the exact answer bytes and keeping the editor open.\nSelect-all writes choice values in declared order through the existing\ncomma-separated `answer` contract; deselect-all writes an empty answer. Neither\naction changes detail, attachments, identity, choices or round. Records declared\nin `first_round_ids` are the fixed first-round configuration and do not receive\nthese actions; `protected_ids` still controls rejection only. Read-only,\ndisabled, rejected and read-only historical cards cannot invoke the actions.\nGenerated-origin/A2UI auto Panels reject this configuration, even when `false`;\ntheir existing answer/detail-only write authority and protected `kind` remain\nunchanged. Converting a generated view into an authored reusable panel does not\nsilently grant this capability: the author must opt in under the static contract.\n\n`panel_workspace` is the reusable panel-internal left navigation + main content\nlayout. It standardizes containment, scroll ownership and narrow-panel fallback;\nit does not define domain records or selection semantics. Use it rather than\ncopying a Kit-specific two-column shell.\n\nThe shared runtime `PanelWorkspaceNavigation` accepts optional per-item\n`description`, `supporting`, and `statusLabel` display slots alongside the\nlabel/current row. These are supplied display text, not canonical fields or\nnew DSL expressions. Omitted slots render no empty rows. The `meta` fallback\nremains supported. A marker requires both explicit `statusIndicator: true`\nand an existing `status`; a label-only item never gains an inferred status dot.\nFlat record navigation, question rounds, and future workspace consumers share\nthe same base navigation typography, spacing and selected appearance. Bundle\nCSS is not required. Hierarchical trees retain their separate structure.\nQuestion progress excludes rejected items from answered/completion checks,\nwhile retaining all group records in the displayed total and preserving fixed\nquestion grouping, stable IDs, selection and canonical answers. The original\nWeb App question panel used body round sections, not this sidebar; the shared\nsidebar is an enhanced structure using the original public navigation style,\nnot a claim of one-to-one restoration of a nonexistent original sidebar.\n\n`doc_lifecycle_studio` binds `objects`/`axes`/`actions` sections (validation\nfails loud when one is missing) and renders the fact table (actions × state\naxes, per-cell effects) plus process/derivation/ledger projections derived at\nrender time; unavailable views render disabled with a reason, never hidden.\n`rowview_workbench` renders the residue envelope (below) and requires a\n`source` declaring the add section it owns — the details-envelope schema\ncheck and the renderer are both scoped to that section; a workbench without\n`source` is rejected at compile time.\n\nIn editable mode `bpmn_canvas` edits bidirectionally: each process record's\n`name` and `steps` array (step name, `kind` task/gateway/event, order, add,\nremove) round-trip through the panel Save like any field edit.\n"
|
|
6942
6942
|
}
|
|
@@ -10658,6 +10658,10 @@
|
|
|
10658
10658
|
{
|
|
10659
10659
|
"name": "PanelSection",
|
|
10660
10660
|
"read": "--type PanelSection"
|
|
10661
|
+
},
|
|
10662
|
+
{
|
|
10663
|
+
"name": "PanelTranslations",
|
|
10664
|
+
"read": "--type PanelTranslations"
|
|
10661
10665
|
}
|
|
10662
10666
|
]
|
|
10663
10667
|
},
|
|
@@ -10666,7 +10670,12 @@
|
|
|
10666
10670
|
"file": "packages/core/src/panel-dsl.ts",
|
|
10667
10671
|
"line": 498,
|
|
10668
10672
|
"declaration": "i18n?: PanelTranslations",
|
|
10669
|
-
"references": [
|
|
10673
|
+
"references": [
|
|
10674
|
+
{
|
|
10675
|
+
"name": "PanelTranslations",
|
|
10676
|
+
"read": "--type PanelTranslations"
|
|
10677
|
+
}
|
|
10678
|
+
]
|
|
10670
10679
|
},
|
|
10671
10680
|
"PanelManifest.version": {
|
|
10672
10681
|
"name": "PanelManifest.version",
|
|
@@ -10751,6 +10760,34 @@
|
|
|
10751
10760
|
}
|
|
10752
10761
|
]
|
|
10753
10762
|
},
|
|
10763
|
+
"PanelTranslations": {
|
|
10764
|
+
"name": "PanelTranslations",
|
|
10765
|
+
"file": "packages/core/src/panel-i18n.ts",
|
|
10766
|
+
"line": 3,
|
|
10767
|
+
"declaration": "export interface PanelTranslations {\n default_locale: string\n /** Bundle-relative JSON resources, expanded by the Kit loader. */\n locales: Record<string, string>\n messages?: Record<string, Record<string, string>>\n}",
|
|
10768
|
+
"references": []
|
|
10769
|
+
},
|
|
10770
|
+
"PanelTranslations.default_locale": {
|
|
10771
|
+
"name": "PanelTranslations.default_locale",
|
|
10772
|
+
"file": "packages/core/src/panel-i18n.ts",
|
|
10773
|
+
"line": 4,
|
|
10774
|
+
"declaration": "default_locale: string",
|
|
10775
|
+
"references": []
|
|
10776
|
+
},
|
|
10777
|
+
"PanelTranslations.locales": {
|
|
10778
|
+
"name": "PanelTranslations.locales",
|
|
10779
|
+
"file": "packages/core/src/panel-i18n.ts",
|
|
10780
|
+
"line": 6,
|
|
10781
|
+
"declaration": "locales: Record<string, string>",
|
|
10782
|
+
"references": []
|
|
10783
|
+
},
|
|
10784
|
+
"PanelTranslations.messages": {
|
|
10785
|
+
"name": "PanelTranslations.messages",
|
|
10786
|
+
"file": "packages/core/src/panel-i18n.ts",
|
|
10787
|
+
"line": 7,
|
|
10788
|
+
"declaration": "messages?: Record<string, Record<string, string>>",
|
|
10789
|
+
"references": []
|
|
10790
|
+
},
|
|
10754
10791
|
"PANEL_KINDS": {
|
|
10755
10792
|
"name": "PANEL_KINDS",
|
|
10756
10793
|
"file": "packages/core/src/panel-dsl.ts",
|