@praxisui/core 9.0.0-beta.70 → 9.0.0-beta.72

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.
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": "1.0.0",
3
- "generatedAt": "2026-07-10T23:38:40.443Z",
3
+ "generatedAt": "2026-07-12T00:55:35.176Z",
4
4
  "packageName": "@praxisui/core",
5
- "packageVersion": "9.0.0-beta.70",
5
+ "packageVersion": "9.0.0-beta.72",
6
6
  "sourceRegistry": "praxis-component-registry-ingestion",
7
7
  "sourceRegistryVersion": "1.0.0",
8
8
  "componentCount": 4,
@@ -433,7 +433,7 @@
433
433
  "chunkIndex": 0,
434
434
  "chunkKind": "summary",
435
435
  "content": "Component ID: praxis-domain-catalog\nSelector: praxis-domain-catalog\nFriendly Name: Praxis Domain Catalog\nDescription: Context-only registry entry for praxis-domain-catalog.\nCategory: governance\nLib/Package: @praxisui/core\nTags: context-pack, semantic-context, governance, praxis-domain-catalog\n",
436
- "sourcePointer": "praxis-ui-angular/projects/praxis-core/src/lib/ai/domain-catalog-context-pack.ts",
436
+ "sourcePointer": "projects/praxis-core/src/lib/ai/domain-catalog-context-pack.ts",
437
437
  "contentHash": "efeb8e3928786a654db9ba8659f3b27e0646cda91adb834cd611c07bdfe33189",
438
438
  "sourceKind": "component_definition",
439
439
  "sourceId": "praxis-domain-catalog",
@@ -443,7 +443,7 @@
443
443
  "chunkIndex": 1,
444
444
  "chunkKind": "context_pack",
445
445
  "content": "{\n \"componentContext\": {\n \"version\": \"v1.0\",\n \"optionsByPath\": {\n \"domainCatalog.mode\": {\n \"mode\": \"enum\",\n \"options\": [\n {\n \"value\": \"read-only-context\",\n \"label\": \"Read-only semantic context\"\n }\n ]\n },\n \"domainCatalog.items[].type\": {\n \"mode\": \"enum\",\n \"options\": [\n {\n \"value\": \"context\",\n \"label\": \"Runtime semantic context envelope\"\n },\n {\n \"value\": \"node\",\n \"label\": \"Semantic domain node\"\n },\n {\n \"value\": \"edge\",\n \"label\": \"Semantic graph edge\"\n },\n {\n \"value\": \"binding\",\n \"label\": \"Schema, API or UI binding\"\n },\n {\n \"value\": \"evidence\",\n \"label\": \"Evidence supporting semantic interpretation\"\n },\n {\n \"value\": \"governance\",\n \"label\": \"Governance and compliance metadata\"\n },\n {\n \"value\": \"vocabulary\",\n \"label\": \"Domain vocabulary item\"\n },\n {\n \"value\": \"relationship\",\n \"label\": \"Semantic relationship\"\n }\n ]\n },\n \"contextHints.domainCatalog.schemaVersion\": {\n \"mode\": \"enum\",\n \"options\": [\n {\n \"value\": \"praxis.ai.context-hints.domain-catalog/v0.2\",\n \"label\": \"Domain Catalog context hint contract v0.2\"\n }\n ]\n },\n \"contextHints.domainCatalog.type\": {\n \"mode\": \"enum\",\n \"options\": [\n {\n \"value\": \"context\",\n \"label\": \"Retrieve broad runtime context\"\n },\n {\n \"value\": \"node\",\n \"label\": \"Retrieve semantic nodes\"\n },\n {\n \"value\": \"edge\",\n \"label\": \"Retrieve semantic edges\"\n },\n {\n \"value\": \"binding\",\n \"label\": \"Retrieve schema/API/UI bindings\"\n },\n {\n \"value\": \"evidence\",\n \"label\": \"Retrieve supporting evidence\"\n },\n {\n \"value\": \"governance\",\n \"label\": \"Retrieve governance metadata\"\n },\n {\n \"value\": \"vocabulary\",\n \"label\": \"Retrieve vocabulary terms\"\n },\n {\n \"value\": \"relationship\",\n \"label\": \"Retrieve relationship hints\"\n }\n ]\n },\n \"contextHints.domainCatalog.itemTypes[]\": {\n \"mode\": \"enum\",\n \"options\": [\n {\n \"value\": \"context\",\n \"label\": \"Context\"\n },\n {\n \"value\": \"node\",\n \"label\": \"Node\"\n },\n {\n \"value\": \"edge\",\n \"label\": \"Edge\"\n },\n {\n \"value\": \"binding\",\n \"label\": \"Binding\"\n },\n {\n \"value\": \"evidence\",\n \"label\": \"Evidence\"\n },\n {\n \"value\": \"governance\",\n \"label\": \"Governance\"\n },\n {\n \"value\": \"vocabulary\",\n \"label\": \"Vocabulary\"\n },\n {\n \"value\": \"relationship\",\n \"label\": \"Relationship\"\n }\n ]\n },\n \"contextHints.domainCatalog.intent\": {\n \"mode\": \"enum\",\n \"options\": [\n {\n \"value\": \"authoring\",\n \"label\": \"Author a draft or materialization proposal\"\n },\n {\n \"value\": \"explain\",\n \"label\": \"Explain domain semantics\"\n },\n {\n \"value\": \"validate\",\n \"label\": \"Validate a proposed change against domain knowledge\"\n },\n {\n \"value\": \"ai-access-control\",\n \"label\": \"Evaluate AI data visibility and usage constraints\"\n }\n ]\n },\n \"contextHints.domainCatalog.recommendedAuthoringFlow\": {\n \"mode\": \"enum\",\n \"options\": [\n {\n \"value\": \"shared_rule_authoring\",\n \"label\": \"Route the task to shared semantic rule authoring\"\n },\n {\n \"value\": \"component_authoring\",\n \"label\": \"Keep the task in component authoring\"\n },\n {\n \"value\": \"ui_composition_authoring\",\n \"label\": \"Route the task to UI composition authoring\"\n }\n ]\n },\n \"contextHints.domainCatalog.recommendedRuleType\": {\n \"mode\": \"enum\",\n \"options\": [\n {\n \"value\": \"governance\",\n \"label\": \"Governance or compliance shared rule\"\n },\n {\n \"value\": \"selection_eligibility\",\n \"label\": \"Selection eligibility shared rule\"\n }\n ]\n },\n \"contextHints.domainCatalog.relationships\": {\n \"mode\": \"suggested\",\n \"options\": [\n {\n \"value\": \"enabled\",\n \"label\": \"Enable relationship lookup\"\n },\n {\n \"value\": \"federated\",\n \"label\": \"Allow cross-resource or cross-service relationship lookup\"\n },\n {\n \"value\": \"sourceNodeKey\",\n \"label\": \"Limit lookup to a source semantic node\"\n },\n {\n \"value\": \"targetNodeKey\",\n \"label\": \"Limit lookup to a target semantic node\"\n },\n {\n \"value\": \"edgeType\",\n \"label\": \"Limit lookup to a semantic edge type\"\n },\n {\n \"value\": \"query\",\n \"label\": \"Business query for relationship retrieval\"\n },\n {\n \"value\": \"limit\",\n \"label\": \"Maximum number of relationship hints\"\n }\n ]\n },\n \"domainCatalog.items[].payload.classification\": {\n \"mode\": \"suggested\",\n \"options\": [\n {\n \"value\": \"public\",\n \"label\": \"Public\"\n },\n {\n \"value\": \"internal\",\n \"label\": \"Internal\"\n },\n {\n \"value\": \"confidential\",\n \"label\": \"Confidential\"\n },\n {\n \"value\": \"sensitive\",\n \"label\": \"Sensitive\"\n }\n ]\n },\n \"domainCatalog.items[].payload.dataCategory\": {\n \"mode\": \"suggested\",\n \"options\": [\n {\n \"value\": \"personal\",\n \"label\": \"Personal data\"\n },\n {\n \"value\": \"financial\",\n \"label\": \"Financial data\"\n },\n {\n \"value\": \"operational\",\n \"label\": \"Operational data\"\n },\n {\n \"value\": \"security\",\n \"label\": \"Security data\"\n }\n ]\n },\n \"domainCatalog.items[].payload.aiUsage.visibility\": {\n \"mode\": \"suggested\",\n \"options\": [\n {\n \"value\": \"public\",\n \"label\": \"Visible to public AI tasks\"\n },\n {\n \"value\": \"internal\",\n \"label\": \"Visible to internal AI tasks\"\n },\n {\n \"value\": \"restricted\",\n \"label\": \"Restricted AI visibility\"\n },\n {\n \"value\": \"forbidden\",\n \"label\": \"Forbidden for AI use\"\n }\n ]\n }\n },\n \"actionCatalog\": [\n {\n \"id\": \"domainCatalog.release.list\",\n \"operation\": \"read\",\n \"scope\": \"GLOBAL\",\n \"intentExamples\": [\n \"domain catalog releases\",\n \"listar releases de dominio\",\n \"catalogo semantico\"\n ],\n \"patchTemplate\": {},\n \"safetyNotes\": \"Read-only operation. Use DomainCatalogService.listReleases; do not write FormConfig or component config with returned governance rules.\"\n },\n {\n \"id\": \"domainCatalog.governanceContext.read\",\n \"operation\": \"read\",\n \"scope\": \"GLOBAL\",\n \"valueType\": \"OBJECT\",\n \"intentExamples\": [\n \"governanca\",\n \"LGPD\",\n \"GDPR\",\n \"dados sensiveis\",\n \"ai visibility\"\n ],\n \"params\": [\n {\n \"name\": \"resourceKey\",\n \"type\": \"STRING\",\n \"description\": \"Stable semantic resource key, for example human-resources.funcionarios.\"\n },\n {\n \"name\": \"query\",\n \"type\": \"STRING\",\n \"description\": \"Field or concept probe, for example cpf, salario or status.\"\n }\n ],\n \"patchTemplate\": {},\n \"safetyNotes\": \"Read-only operation. Resolve governance through DomainCatalogService.getGovernanceContext(resourceKey, query) before proposing UI, rule or AI-use changes.\"\n },\n {\n \"id\": \"contextHints.domainCatalog.forward\",\n \"operation\": \"read\",\n \"scope\": \"GLOBAL\",\n \"valueType\": \"OBJECT\",\n \"intentExamples\": [\n \"contextHints.domainCatalog\",\n \"authoring hints\",\n \"semantic retrieval hint\",\n \"llm domain context\"\n ],\n \"params\": [\n {\n \"name\": \"serviceKey\",\n \"type\": \"STRING\",\n \"description\": \"Semantic owner service, for example praxis-service.\"\n },\n {\n \"name\": \"resourceKey\",\n \"type\": \"STRING\",\n \"description\": \"Stable semantic resource key, for example human-resources.funcionarios.\"\n },\n {\n \"name\": \"type\",\n \"type\": \"STRING\",\n \"description\": \"Canonical item focus: context, node, edge, binding, evidence, governance, vocabulary or relationship.\"\n },\n {\n \"name\": \"intent\",\n \"type\": \"STRING\",\n \"description\": \"Retrieval purpose: authoring, explain, validate or ai-access-control.\"\n },\n {\n \"name\": \"query\",\n \"type\": \"STRING\",\n \"description\": \"Business query used to retrieve relevant domain context.\"\n }\n ],\n \"patchTemplate\": {\n \"contextHints\": {\n \"domainCatalog\": {\n \"schemaVersion\": \"praxis.ai.context-hints.domain-catalog/v0.2\",\n \"recommendedAuthoringFlow\": \"shared_rule_authoring\",\n \"recommendedRuleType\": \"privacy\",\n \"serviceKey\": \"<serviceKey>\",\n \"resourceKey\": \"<resourceKey>\",\n \"type\": \"governance\",\n \"itemTypes\": [\n \"governance\"\n ],\n \"intent\": \"authoring\",\n \"query\": \"<business query>\",\n \"limit\": 12,\n \"relationships\": {\n \"enabled\": true,\n \"federated\": true,\n \"query\": \"<business query>\",\n \"limit\": 8\n }\n }\n }\n },\n \"safetyNotes\": \"Forward these hints to AI authoring calls as runtime retrieval context. Do not convert them into executable rules or persist them as FormConfig unless an approved backend materialization flow says so.\"\n }\n ],\n \"fieldResolvers\": {\n \"resourceKey\": [\n \"Prefer backend-provided resourceKey from surfaces, actions, capabilities or api_metadata.\",\n \"Do not derive resourceKey from resource.path when discovery already returned a stable semantic key.\"\n ],\n \"governanceProbe\": [\n \"Use the business field/concept name as query: cpf, salario, status, email, documento.\",\n \"Keep probes narrow; request more context instead of loading every governance item into a prompt.\"\n ]\n },\n \"hints\": [\n \"Domain Catalog is a runtime semantic/governance context source, not a FormConfig rule store.\",\n \"Use DomainCatalogService for read-only lookup of domain vocabulary, relationships and governance items.\",\n \"LLM tasks must treat aiUsage.visibility and complianceTags as prompt/data-access constraints before generating patches.\",\n \"Use contextHints.domainCatalog with schemaVersion praxis.ai.context-hints.domain-catalog/v0.2 to share runtime semantic retrieval intent between frontend and backend.\",\n \"Shared domain rules may be referenced by resourceKey and catalog release, but should not be copied into component JSON unless intentionally materialized by a backend policy.\"\n ]\n }\n}",
446
- "sourcePointer": "praxis-ui-angular/projects/praxis-core/src/lib/ai/domain-catalog-context-pack.ts",
446
+ "sourcePointer": "projects/praxis-core/src/lib/ai/domain-catalog-context-pack.ts",
447
447
  "contentHash": "352346805d097ea6d577fa4ceaf1bc4ca847787364fc700f20f8baeb3758277b",
448
448
  "sourceKind": "component_definition",
449
449
  "sourceId": "praxis-domain-catalog",
@@ -459,69 +459,82 @@
459
459
  {
460
460
  "name": "page",
461
461
  "type": "WidgetPageDefinition",
462
- "required": false
462
+ "required": false,
463
+ "description": "Definição da página (widgets, layout e composition.links)."
463
464
  },
464
465
  {
465
466
  "name": "context",
466
467
  "type": "Record<string, any>",
467
- "required": false
468
+ "required": false,
469
+ "description": "Contexto adicional compartilhado entre widgets."
468
470
  },
469
471
  {
470
472
  "name": "strictValidation",
471
473
  "type": "boolean",
472
- "required": false
474
+ "required": false,
475
+ "description": "Habilita validação estrita de inputs."
473
476
  },
474
477
  {
475
478
  "name": "enableCustomization",
476
479
  "type": "boolean",
477
- "required": false
480
+ "required": false,
481
+ "description": "Habilita affordances de edição na página."
478
482
  },
479
483
  {
480
484
  "name": "showPageSettingsButton",
481
485
  "type": "boolean",
482
- "required": false
486
+ "required": false,
487
+ "description": "Exibe botão de configuração da página."
483
488
  },
484
489
  {
485
490
  "name": "shellEditorComponent",
486
491
  "type": "Type<any>",
487
- "required": false
492
+ "required": false,
493
+ "description": "Override do editor de shell dos widgets."
488
494
  },
489
495
  {
490
496
  "name": "pageEditorComponent",
491
497
  "type": "Type<any>",
492
- "required": false
498
+ "required": false,
499
+ "description": "Override do editor de configuração da página."
493
500
  },
494
501
  {
495
502
  "name": "autoPersist",
496
503
  "type": "boolean",
497
- "required": false
504
+ "required": false,
505
+ "description": "Ativa persistência automática (load/save) da página."
498
506
  },
499
507
  {
500
508
  "name": "pageIdentity",
501
509
  "type": "PageIdentity",
502
- "required": false
510
+ "required": false,
511
+ "description": "Identidade de persistência (tenant/usuário/rota/locale)."
503
512
  },
504
513
  {
505
514
  "name": "componentInstanceId",
506
515
  "type": "string",
507
- "required": false
516
+ "required": false,
517
+ "description": "Identificador opcional para múltiplas instâncias na mesma rota."
508
518
  }
509
519
  ],
510
520
  "outputs": [
511
521
  {
512
522
  "name": "pageChange",
513
523
  "type": "WidgetPageDefinition",
514
- "required": false
524
+ "required": false,
525
+ "description": "Emitido ao alterar a definição da página."
515
526
  },
516
527
  {
517
528
  "name": "widgetEvent",
518
529
  "type": "WidgetEventEnvelope",
519
- "required": false
530
+ "required": false,
531
+ "description": "Reemite eventos dos widgets filhos com ownerWidgetKey para integrações do host."
520
532
  },
521
533
  {
522
534
  "name": "widgetDiagnosticsChange",
523
535
  "type": "Record<string, WidgetResolutionDiagnostic>",
524
- "required": false
536
+ "required": false,
537
+ "description": "Emitido quando o runtime detecta widgets resolvidos ou falhos durante o carregamento dinâmico."
525
538
  }
526
539
  ],
527
540
  "configSchemaId": null,
@@ -2890,7 +2903,7 @@
2890
2903
  "chunkIndex": 0,
2891
2904
  "chunkKind": "summary",
2892
2905
  "content": "Component ID: praxis-dynamic-page\nSelector: praxis-dynamic-page\nFriendly Name: Dynamic Page\nDescription: Página dinâmica com widgets e composition.links em layout responsivo, incluindo mediação runtime para rich-content hospedado.\nCategory: page\nLib/Package: @praxisui/core\nTags: widget, page, dynamic, layout\nInputs:\n - page (WidgetPageDefinition)\n - context (Record<string, any>)\n - strictValidation (boolean)\n - enableCustomization (boolean)\n - showPageSettingsButton (boolean)\n - shellEditorComponent (Type<any>)\n - pageEditorComponent (Type<any>)\n - autoPersist (boolean)\n - pageIdentity (PageIdentity)\n - componentInstanceId (string)\nOutputs:\n - pageChange (WidgetPageDefinition)\n - widgetEvent (WidgetEventEnvelope)\n - widgetDiagnosticsChange (Record<string, WidgetResolutionDiagnostic>)\n",
2893
- "sourcePointer": "praxis-ui-angular/projects/praxis-core/src/lib/widgets/dynamic-widget-page.metadata.ts",
2906
+ "sourcePointer": "projects/praxis-core/src/lib/widgets/dynamic-widget-page.metadata.ts",
2894
2907
  "contentHash": "7575dbf241f37111a9acc2367fc82ced61f9ddf28586125b3a3b346d35a1fb7a",
2895
2908
  "sourceKind": "component_definition",
2896
2909
  "sourceId": "praxis-dynamic-page",
@@ -2900,7 +2913,7 @@
2900
2913
  "chunkIndex": 1,
2901
2914
  "chunkKind": "capabilities",
2902
2915
  "content": "Component Capabilities:\n - Path: uiCompositionPlan\n Category: page\n Kind: object\n Description: Plano declarativo intermediario aceito em preview agentic antes do WidgetPageDefinition.\n - Path: uiCompositionPlan.version\n Category: page\n Kind: string\n Description: Versao do plano. Valor atual: 1.0.\n - Path: uiCompositionPlan.kind\n Category: page\n Kind: string\n Description: Discriminador do plano. Valor atual: praxis.ui-composition-plan.\n - Path: uiCompositionPlan.layoutPreset\n Category: layout\n Kind: string\n Description: Preset semantico opcional da composicao planejada.\n - Path: uiCompositionPlan.layoutPresetOptions\n Category: layout\n Kind: object\n Description: Opcoes semanticas opcionais do preset, como familia visual, estrategia responsiva e politica de densidade.\n - Path: uiCompositionPlan.grouping\n Category: layout\n Kind: array\n Description: Agrupamentos semanticos opcionais para organizar widgets em hero, section, tabs ou rail no runtime.\n - Path: uiCompositionPlan.slotAssignments\n Category: layout\n Kind: object\n Description: Mapa opcional widgetKey -> slot semantico para alinhar widgets gerados a presets de layout sem depender de dominio.\n - Path: uiCompositionPlan.deviceLayouts\n Category: layout\n Kind: object\n Description: Variantes responsivas opcionais para desktop, tablet e mobile, incluindo canvas, groupingOverrides e widgetOverrides.\n - Path: uiCompositionPlan.themePreset\n Category: layout\n Kind: string\n Description: Preset visual opcional do runtime, por exemplo analytics-calm, workspace-balanced ou ops-monitoring.\n - Path: uiCompositionPlan.state\n Category: state\n Kind: object\n Description: Estado inicial/declarativo que sera compilado para page.state.\n - Path: uiCompositionPlan.widgets\n Category: widgets\n Kind: array\n Description: Widgets planejados antes da compilacao para page.widgets.\n - Path: uiCompositionPlan.widgets[].key\n Category: widgets\n Kind: string\n Description: ID estavel do widget planejado.\n - Path: uiCompositionPlan.widgets[].componentId\n Category: widgets\n Kind: string\n Description: Componente registrado que sera compilado para definition.id.\n - Path: uiCompositionPlan.widgets[].inputs\n Category: widgets\n Kind: object\n Description: Inputs canonicos do componente, compilados para definition.inputs.\n - Path: uiCompositionPlan.widgets[].bindingOrder\n Category: widgets\n Kind: array\n Description: Ordem declarativa de binding, compilada para definition.bindingOrder.\n - Path: uiCompositionPlan.bindings\n Category: connections\n Kind: array\n Description: Bindings declarativos que serao compilados para page.composition.links.\n - Path: uiCompositionPlan.bindings[].id\n Category: connections\n Kind: string\n Description: Identificador estavel do binding planejado.\n - Path: uiCompositionPlan.bindings[].from\n Category: connections\n Kind: object\n Description: Endpoint de origem: component-port ou state.\n - Path: uiCompositionPlan.bindings[].to\n Category: connections\n Kind: object\n Description: Endpoint de destino: component-port, state ou global-action.\n - Path: uiCompositionPlan.bindings[].to.[actionId]\n Category: connections\n Kind: string\n Description: ID da action global quando uiCompositionPlan.bindings[].to.kind = global-action.\n - Path: uiCompositionPlan.bindings[].to.payload\n Category: connections\n Kind: object\n Description: Payload literal opcional para destino global-action planejado.\n - Path: uiCompositionPlan.bindings[].to.payloadExpr\n Category: connections\n Kind: string\n Description: Path de payload opcional para destino global-action planejado.\n - Path: uiCompositionPlan.bindings[].from.nestedPath\n Category: connections\n Kind: array\n Description: Caminho estruturado para porta nested de origem. Use apenas com endpoint component-port; o owner top-level continua em from.widget.\n - Path: uiCompositionPlan.bindings[].to.nestedPath\n Category: connections\n Kind: array\n Description: Caminho estruturado para porta nested de destino. Use apenas com endpoint component-port; o owner top-level continua em to.widget.\n - Path: uiCompositionPlan.bindings[].from.nestedPath[].kind\n Category: connections\n Kind: string\n Description: Tipo do segmento nested de origem, como tab, nav, link, expansion, panel ou widget. O ultimo segmento deve ser widget.\n - Path: uiCompositionPlan.bindings[].from.nestedPath[].id\n Category: connections\n Kind: string\n Description: Identificador estrutural estavel do container de origem no segmento nested, quando existir.\n - Path: uiCompositionPlan.bindings[].from.nestedPath[].key\n Category: connections\n Kind: string\n Description: Chave estavel do widget filho no segmento terminal widget de origem. Obrigatoria para endpoint nested persistido.\n - Path: uiCompositionPlan.bindings[].from.nestedPath[].index\n Category: connections\n Kind: number\n Description: Indice auxiliar de origem para contexto visual/diagnostico; nao use como identidade primaria persistida.\n - Path: uiCompositionPlan.bindings[].from.nestedPath[].componentType\n Category: connections\n Kind: string\n Description: Tipo do componente real do widget filho de origem, usado como verificacao auxiliar, nao como identidade primaria.\n - Path: uiCompositionPlan.bindings[].to.nestedPath[].kind\n Category: connections\n Kind: string\n Description: Tipo do segmento nested de destino, como tab, nav, link, expansion, panel ou widget. O ultimo segmento deve ser widget.\n - Path: uiCompositionPlan.bindings[].to.nestedPath[].id\n Category: connections\n Kind: string\n Description: Identificador estrutural estavel do container de destino no segmento nested, quando existir.\n - Path: uiCompositionPlan.bindings[].to.nestedPath[].key\n Category: connections\n Kind: string\n Description: Chave estavel do widget filho no segmento terminal widget de destino. Obrigatoria para endpoint nested persistido.\n - Path: uiCompositionPlan.bindings[].to.nestedPath[].index\n Category: connections\n Kind: number\n Description: Indice auxiliar de destino para contexto visual/diagnostico; nao use como identidade primaria persistida.\n - Path: uiCompositionPlan.bindings[].to.nestedPath[].componentType\n Category: connections\n Kind: string\n Description: Tipo do componente real do widget filho de destino, usado como verificacao auxiliar, nao como identidade primaria.\n - Path: uiCompositionPlan.bindings[].intent\n Category: connections\n Kind: string\n Description: Intencao semantica do binding.\n - Path: uiCompositionPlan.bindings[].condition\n Category: connections\n Kind: expression\n Description: Guarda opcional em Json Logic.\n - Path: uiCompositionPlan.bindings[].transform\n Category: connections\n Kind: object\n Description: Transform declarativo: pick-path, query-context, template ou constant.\n - Path: uiCompositionPlan.bindings[].policy\n Category: connections\n Kind: object\n Description: Politica operacional opcional do binding.\n - Path: page\n Category: page\n Kind: object\n Description: Definicao da pagina (WidgetPageDefinition).\n - Path: context\n Category: context\n Kind: object\n Description: Contexto extra mesclado ao page.context.\n - Path: enableCustomization\n Category: behavior\n Kind: boolean\n Description: Habilita modo de edicao.\n - Path: showSettingsButton\n Category: behavior\n Kind: boolean\n Description: Exibe botao de settings.\n - Path: strictValidation\n Category: behavior\n Kind: boolean\n Description: Validacao estrita do widget loader.\n - Path: layoutOptions\n Category: layout\n Kind: object\n Description: Overrides residuais do host aceitos apenas para compatibilidade de migracao.\n - Path: layoutOptions.cols\n Category: layout\n Kind: number\n Description: Compat: numero de colunas usado para derivar canvas padrao.\n - Path: layoutOptions.rowHeight\n Category: layout\n Kind: number\n Description: Compat: altura de linha usada para derivar rowUnit do canvas.\n - Path: layoutOptions.gap\n Category: layout\n Kind: number\n Description: Compat: espacamento usado para derivar gap do canvas.\n - Path: pageIdentity\n Category: identity\n Kind: object\n Description: Identidade de persistencia da pagina.\n - Path: pageIdentity.appId\n Category: identity\n Kind: string\n Description: App id (opcional).\n - Path: pageIdentity.tenantId\n Category: identity\n Kind: string\n Description: Tenant id.\n - Path: pageIdentity.userId\n Category: identity\n Kind: string\n Description: User id.\n - Path: pageIdentity.routePath\n Category: identity\n Kind: string\n Description: Rota base da pagina.\n - Path: pageIdentity.locale\n Category: identity\n Kind: string\n Description: Locale.\n - Path: page.canvas\n Category: layout\n Kind: object\n Description: Canvas espacial canonico da pagina.\n - Path: page.canvas.mode\n Category: layout\n Kind: string\n Description: Modo do canvas. O builder usa grid canonico.\n - Path: page.canvas.columns\n Category: layout\n Kind: number\n Description: Numero de colunas do canvas.\n - Path: page.canvas.rowUnit\n Category: layout\n Kind: string\n Description: Altura base das linhas do canvas (ex: 80px).\n - Path: page.canvas.gap\n Category: layout\n Kind: string\n Description: Espacamento entre itens do canvas.\n - Path: page.canvas.autoRows\n Category: layout\n Kind: string\n Description: Politica de auto rows do canvas.\n - Path: page.canvas.items\n Category: layout\n Kind: object\n Description: Mapa canonico de posicionamento espacial por widget key.\n - Path: page.canvas.items.<widgetKey>.col\n Category: layout\n Kind: number\n Description: Coluna inicial (1-based).\n - Path: page.canvas.items.<widgetKey>.row\n Category: layout\n Kind: number\n Description: Linha inicial (1-based).\n - Path: page.canvas.items.<widgetKey>.colSpan\n Category: layout\n Kind: number\n Description: Colunas ocupadas.\n - Path: page.canvas.items.<widgetKey>.rowSpan\n Category: layout\n Kind: number\n Description: Linhas ocupadas.\n - Path: page.state\n Category: state\n Kind: object\n Description: Estado declarativo opcional da pagina.\n - Path: page.state.values\n Category: state\n Kind: object\n Description: Valores primarios persistiveis do estado da pagina.\n - Path: page.state.schema\n Category: state\n Kind: object\n Description: Descritores dos paths de estado primario.\n - Path: page.state.derived\n Category: state\n Kind: object\n Description: Descritores de estado derivado recomputado pelo runtime.\n - Path: page.widgets\n Category: widgets\n Kind: array\n Description: Widgets da pagina.\n - Path: page.widgets[].key\n Category: widgets\n Kind: string\n Description: ID unico do widget.\n - Path: page.widgets[].className\n Category: widgets\n Kind: string\n Description: Classe CSS do widget.\n - Path: page.widgets[].definition\n Category: widgets\n Kind: object\n Description: Definicao do widget (WidgetDefinition).\n - Path: page.widgets[].definition.id\n Category: widgets\n Kind: string\n Description: ID do componente registrado.\n - Path: page.widgets[].definition.inputs\n Category: widgets\n Kind: object\n Description: Inputs do componente.\n - Path: page.widgets[].definition.inputs.document\n Category: widgets\n Kind: object\n Description: RichContentDocument quando definition.id for praxis-rich-content.\n - Path: page.widgets[].definition.bindingOrder\n Category: widgets\n Kind: array\n Description: Ordem de aplicacao dos inputs.\n - Path: ComponentDocMeta.configEditor\n Category: widgets\n Kind: object\n Description: Editor canonico de inputs publicado pela lib dona do componente e aberto pelo settings-panel do host.\n - Path: ComponentDocMeta.configEditor.component\n Category: widgets\n Kind: object\n Description: Componente standalone que implementa SettingsValueProvider para editar definition.inputs.\n - Path: ComponentDocMeta.configEditor.title\n Category: widgets\n Kind: string\n Description: Titulo opcional usado pelo host ao abrir o editor de inputs do componente.\n - Path: ComponentDocMeta.authoringManifestRef\n Category: widgets\n Kind: object\n Description: Referencia canonica para o manifesto executavel de authoring por IA publicado pela lib dona do componente.\n - Path: ComponentDocMeta.authoringManifestRef.componentId\n Category: widgets\n Kind: string\n Description: ID do componente no registry/backend de manifestos de authoring.\n - Path: ComponentDocMeta.authoringManifestRef.source\n Category: widgets\n Kind: string\n Description: Simbolo, modulo ou registry id estavel do manifesto usado para delegar edicoes governadas.\n - Path: page.composition\n Category: connections\n Kind: object\n Description: Envelope canonico da composicao persistida.\n - Path: page.composition.version\n Category: connections\n Kind: string\n Description: Versao do envelope de composicao.\n - Path: page.composition.links\n Category: connections\n Kind: array\n Description: Links canonicos entre widgets, estado e actions globais.\n - Path: page.composition.links[].id\n Category: connections\n Kind: string\n Description: Identificador estavel do link.\n - Path: page.composition.links[].from\n Category: connections\n Kind: object\n Description: Endpoint de origem do link.\n - Path: page.composition.links[].to\n Category: connections\n Kind: object\n Description: Endpoint de destino do link.\n - Path: page.composition.links[].to.kind\n Category: connections\n Kind: string\n Description: Tipo do endpoint de destino, incluindo global-action para command-dispatch declarativo.\n - Path: page.composition.links[].to.ref.[actionId]\n Category: connections\n Kind: string\n Description: ID da action global quando page.composition.links[].to.kind = global-action.\n - Path: page.composition.links[].to.ref.payload\n Category: connections\n Kind: object\n Description: Payload estruturado opcional da action global persistida; quando omitido, o valor transformado do link segue como delivery value.\n - Path: page.composition.links[].to.ref.payloadExpr\n Category: connections\n Kind: expression\n Description: Escape avancado explicito de payload da action global persistida.\n - Path: page.composition.links[].to.ref.meta\n Category: connections\n Kind: object\n Description: Metadados opcionais do GlobalActionRef persistido, sem criar executor paralelo.\n - Path: page.composition.links[].from.ref.nestedPath\n Category: connections\n Kind: array\n Description: NestedPath canonico em endpoint component-port de origem persistido. Omita para top-level; nao serialize nestedPath: [].\n - Path: page.composition.links[].from.ref.nestedPath[].key\n Category: connections\n Kind: string\n Description: Chave estavel do widget filho no segmento terminal widget de origem. Obrigatoria para endpoint nested persistido.\n - Path: page.composition.links[].to.ref.nestedPath\n Category: connections\n Kind: array\n Description: NestedPath canonico em endpoint component-port de destino persistido. Omita para top-level; nao serialize nestedPath: [].\n - Path: page.composition.links[].to.ref.nestedPath[].key\n Category: connections\n Kind: string\n Description: Chave estavel do widget filho no segmento terminal widget de destino. Obrigatoria para endpoint nested persistido.\n - Path: page.composition.links[].intent\n Category: connections\n Kind: string\n Description: Intencao semantica do link.\n - Path: page.composition.links[].transform\n Category: connections\n Kind: object\n Description: Pipeline de transformacao do link.\n - Path: page.composition.links[].condition\n Category: connections\n Kind: expression\n Description: Guarda semantica opcional do link, expressa como um unico AST Json Logic canonico.\n - Path: page.composition.links[].policy\n Category: connections\n Kind: object\n Description: Politicas operacionais opcionais do link, separadas da condition semantica.\n - Path: page.composition.links[].metadata\n Category: connections\n Kind: object\n Description: Metadados opcionais do link.\n - Path: page.context\n Category: context\n Kind: object\n Description: Contexto da pagina (compartilhado por widgets).\n - Path: page.layoutPreset\n Category: layout\n Kind: string\n Description: ID canônico opcional do preset estrutural da página.\n - Path: page.layoutPresetOptions\n Category: layout\n Kind: object\n Description: Opções específicas do preset estrutural consumidas por builders e runtimes futuros.\n - Path: page.themePreset\n Category: appearance\n Kind: string\n Description: ID opcional do preset de tema para shell, gráficos, densidade e defaults visuais.\n - Path: page.layout\n Category: layout\n Kind: object\n Description: Layout base da página.\n - Path: page.layout.orientation\n Category: layout\n Kind: enum\n Description: Orientacao do grid (vertical/columns).\n - Path: page.layout.columns\n Category: layout\n Kind: number\n Description: Numero de colunas (quando orientation=columns).\n - Path: page.layout.gap\n Category: layout\n Kind: string\n Description: Gap entre widgets (ex: 16px).\n - Path: page.layout.breakpoints\n Category: layout\n Kind: object\n Description: Colunas por breakpoint.\n - Path: page.layout.breakpoints.sm\n Category: layout\n Kind: number\n Description: Colunas para breakpoint sm.\n - Path: page.layout.breakpoints.md\n Category: layout\n Kind: number\n Description: Colunas para breakpoint md.\n - Path: page.layout.breakpoints.lg\n Category: layout\n Kind: number\n Description: Colunas para breakpoint lg.\n - Path: page.layout.breakpoints.xl\n Category: layout\n Kind: number\n Description: Colunas para breakpoint xl.\n - Path: page.canvas.collisionPolicy\n Category: layout\n Kind: enum\n Description: Politica de colisao do canvas espacial.\n - Path: page.canvas.items.<widgetKey>.zIndex\n Category: layout\n Kind: number\n Description: Camada opcional do item no canvas.\n - Path: page.canvas.items.<widgetKey>.constraints\n Category: layout\n Kind: object\n Description: Restricoes opcionais de posicao e tamanho do item no canvas.\n - Path: page.canvas.items.<widgetKey>.constraints.minColSpan\n Category: layout\n Kind: number\n Description: Span mínimo de colunas permitido.\n - Path: page.canvas.items.<widgetKey>.constraints.minRowSpan\n Category: layout\n Kind: number\n Description: Span mínimo de linhas permitido.\n - Path: page.canvas.items.<widgetKey>.constraints.maxColSpan\n Category: layout\n Kind: number\n Description: Span máximo de colunas permitido.\n - Path: page.canvas.items.<widgetKey>.constraints.maxRowSpan\n Category: layout\n Kind: number\n Description: Span máximo de linhas permitido.\n - Path: page.canvas.items.<widgetKey>.constraints.lockPosition\n Category: layout\n Kind: boolean\n Description: Bloqueia alteracao de posicao do item no canvas.\n - Path: page.canvas.items.<widgetKey>.constraints.lockSize\n Category: layout\n Kind: boolean\n Description: Bloqueia alteracao de tamanho do item no canvas.\n - Path: page.widgets[].definition.inputs.hostCapabilities\n Category: widgets\n Kind: object\n Description: Capacidades runtime mediadas pelo host quando definition.id = praxis-rich-content. Não pertence ao JSON persistido.\n - Path: page.widgets[].definition.inputs.hostCapabilities.dispatchAction\n Category: widgets\n Kind: object\n Description: Dispatcher runtime para actionButton e actions declarativas de rich content hospedado na página.\n - Path: page.widgets[].definition.inputs.hostCapabilities.isActionAvailable\n Category: widgets\n Kind: object\n Description: Resolver runtime de disponibilidade de actionId para rich content hospedado na página.\n - Path: page.widgets[].definition.inputs.hostCapabilities.hasCapability\n Category: widgets\n Kind: object\n Description: Resolver runtime de capabilities como page.customization.enabled e page.widget.selected para rich content hospedado na página.\n - Path: page.widgets[].shell\n Category: shell\n Kind: object\n Description: Configuração do shell do widget.\n - Path: page.widgets[].shell.kind\n Category: shell\n Kind: enum\n Description: Tipo de shell.\n - Path: page.widgets[].shell.title\n Category: shell\n Kind: string\n Description: Título do shell.\n - Path: page.widgets[].shell.subtitle\n Category: shell\n Kind: string\n Description: Subtítulo do shell.\n - Path: page.widgets[].shell.icon\n Category: shell\n Kind: string\n Description: Ícone do shell.\n - Path: page.widgets[].shell.showHeader\n Category: shell\n Kind: boolean\n Description: Exibe o header do shell.\n - Path: page.widgets[].shell.actions\n Category: shell\n Kind: array\n Description: Ações do shell.\n - Path: page.widgets[].shell.actions[].id\n Category: shell\n Kind: string\n Description: ID da ação.\n - Path: page.widgets[].shell.actions[].label\n Category: shell\n Kind: string\n Description: Label da ação.\n - Path: page.widgets[].shell.actions[].icon\n Category: shell\n Kind: string\n Description: Ícone da ação.\n - Path: page.widgets[].shell.actions[].variant\n Category: shell\n Kind: enum\n Description: Estilo visual da ação.\n - Path: page.widgets[].shell.actions[].placement\n Category: shell\n Kind: enum\n Description: Posicionamento da ação.\n - Path: page.widgets[].shell.actions[].emit\n Category: shell\n Kind: string\n Description: Evento emitido ao acionar a ação.\n - Path: page.state.schema.<token>.type\n Category: state\n Kind: string\n Description: Tipo semantico opcional do path de estado.\n - Path: page.state.schema.<token>.initial\n Category: state\n Kind: object\n Description: Valor inicial usado quando page.state.values omite o path.\n - Path: page.state.schema.<token>.persist\n Category: state\n Kind: boolean\n Description: Indica se o path primário deve ser persistido com a página.\n - Path: page.state.schema.<token>.mergeStrategy\n Category: state\n Kind: enum\n Description: Como escritas de widget/estado combinam com o valor atual.\n - Path: page.state.schema.<token>.description\n Category: state\n Kind: string\n Description: Descrição opcional do path para builders e catálogos AI.\n - Path: page.state.schema.<token>.tags\n Category: state\n Kind: array\n Description: Tags opcionais para busca e governanca do estado.\n - Path: page.state.derived.<token>.dependsOn\n Category: state\n Kind: array\n Description: Paths de estado que alimentam o valor derivado.\n - Path: page.state.derived.<token>.compute\n Category: state\n Kind: object\n Description: Descritor de computacao do estado derivado.\n - Path: page.state.derived.<token>.compute.kind\n Category: state\n Kind: enum\n Description: Tipo de computacao do estado derivado.\n - Path: page.state.derived.<token>.compute.expression\n Category: state\n Kind: expression\n Description: Expressao Json Logic para compute.kind=json-logic.\n - Path: page.state.derived.<token>.compute.value\n Category: state\n Kind: object\n Description: Valor template para compute.kind=template.\n - Path: page.state.derived.<token>.compute.operator\n Category: state\n Kind: string\n Description: Operador para compute.kind=operator.\n - Path: page.state.derived.<token>.compute.options\n Category: state\n Kind: object\n Description: Opções do operador ou transformer.\n - Path: page.state.derived.<token>.compute.transformerId\n Category: state\n Kind: string\n Description: Identificador do transformer para compute.kind=transformer.\n - Path: page.state.derived.<token>.description\n Category: state\n Kind: string\n Description: Descrição opcional do estado derivado.\n - Path: page.state.derived.<token>.cache\n Category: state\n Kind: boolean\n Description: Permite cache futuro do valor derivado.\n - Path: page.composition.links[].from.kind\n Category: connections\n Kind: string\n Description: Tipo do endpoint de origem, como component-port ou state.\n - Path: page.composition.links[].from.ref\n Category: connections\n Kind: object\n Description: Referencia estruturada do endpoint de origem.\n - Path: page.composition.links[].from.ref.widget\n Category: connections\n Kind: string\n Description: Widget top-level dono do endpoint de origem.\n - Path: page.composition.links[].from.ref.port\n Category: connections\n Kind: string\n Description: Porta de origem do componente.\n - Path: page.composition.links[].from.ref.direction\n Category: connections\n Kind: string\n Description: Direcao da porta de origem.\n - Path: page.composition.links[].from.ref.nestedPath[].kind\n Category: connections\n Kind: string\n Description: Tipo do segmento nested de origem.\n - Path: page.composition.links[].from.ref.nestedPath[].id\n Category: connections\n Kind: string\n Description: Identificador estrutural do segmento nested de origem.\n - Path: page.composition.links[].from.ref.nestedPath[].index\n Category: connections\n Kind: number\n Description: Índice auxiliar para diagnóstico visual; não use como identidade primária.\n - Path: page.composition.links[].from.ref.nestedPath[].componentType\n Category: connections\n Kind: string\n Description: Tipo do componente real do widget filho de origem.\n - Path: page.composition.links[].to.ref\n Category: connections\n Kind: object\n Description: Referencia estruturada do endpoint de destino.\n - Path: page.composition.links[].to.ref.widget\n Category: connections\n Kind: string\n Description: Widget top-level dono do endpoint de destino.\n - Path: page.composition.links[].to.ref.port\n Category: connections\n Kind: string\n Description: Porta de destino do componente.\n - Path: page.composition.links[].to.ref.direction\n Category: connections\n Kind: string\n Description: Direcao da porta de destino.\n - Path: page.composition.links[].to.ref.nestedPath[].kind\n Category: connections\n Kind: string\n Description: Tipo do segmento nested de destino.\n - Path: page.composition.links[].to.ref.nestedPath[].id\n Category: connections\n Kind: string\n Description: Identificador estrutural do segmento nested de destino.\n - Path: page.composition.links[].to.ref.nestedPath[].index\n Category: connections\n Kind: number\n Description: Índice auxiliar para diagnóstico visual; não use como identidade primária.\n - Path: page.composition.links[].to.ref.nestedPath[].componentType\n Category: connections\n Kind: string\n Description: Tipo do componente real do widget filho de destino.\n - Path: page.grouping\n Category: layout\n Kind: array\n Description: Modelo semantico opcional de secoes, abas, areas hero e rails.\n - Path: page.grouping[].kind\n Category: layout\n Kind: enum\n Description: Tipo do agrupamento semantico.\n - Path: page.grouping[].id\n Category: layout\n Kind: string\n Description: Identificador estavel do agrupamento.\n - Path: page.grouping[].label\n Category: layout\n Kind: string\n Description: Rotulo opcional do agrupamento.\n - Path: page.grouping[].widgetKeys\n Category: layout\n Kind: array\n Description: Widgets pertencentes ao agrupamento section, hero ou rail.\n - Path: page.grouping[].layout\n Category: layout\n Kind: enum\n Description: Layout opcional para agrupamento section.\n - Path: page.grouping[].tabs\n Category: layout\n Kind: array\n Description: Abas do agrupamento kind=tabs.\n - Path: page.grouping[].tabs[].id\n Category: layout\n Kind: string\n Description: Identificador estavel da aba.\n - Path: page.grouping[].tabs[].label\n Category: layout\n Kind: string\n Description: Rotulo da aba.\n - Path: page.grouping[].tabs[].widgetKeys\n Category: layout\n Kind: array\n Description: Widgets renderizados dentro da aba.\n - Path: page.grouping[].emphasis\n Category: layout\n Kind: enum\n Description: Enfase opcional para agrupamento hero.\n - Path: page.grouping[].side\n Category: layout\n Kind: enum\n Description: Lado do rail quando kind=rail.\n - Path: page.slotAssignments\n Category: layout\n Kind: object\n Description: Mapa canonico de widget key para slot semantico de preset.\n - Path: page.deviceLayouts\n Category: layout\n Kind: object\n Description: Variantes opcionais de layout por dispositivo.\n - Path: page.deviceLayouts.desktop\n Category: layout\n Kind: object\n Description: Overrides de layout para desktop.\n - Path: page.deviceLayouts.tablet\n Category: layout\n Kind: object\n Description: Overrides de layout para tablet.\n - Path: page.deviceLayouts.mobile\n Category: layout\n Kind: object\n Description: Overrides de layout para mobile.\n - Path: page.deviceLayouts.desktop.layout\n Category: layout\n Kind: object\n Description: Override de WidgetPageLayout para desktop.\n - Path: page.deviceLayouts.desktop.canvas\n Category: layout\n Kind: object\n Description: Override de canvas para desktop.\n - Path: page.deviceLayouts.desktop.groupingOverrides\n Category: layout\n Kind: array\n Description: Overrides de agrupamentos para desktop.\n - Path: page.deviceLayouts.desktop.widgetOverrides\n Category: layout\n Kind: object\n Description: Overrides por widget key para desktop.\n - Path: page.deviceLayouts.desktop.widgetOverrides.<widgetKey>.hidden\n Category: layout\n Kind: boolean\n Description: Oculta o widget em desktop.\n - Path: page.deviceLayouts.tablet.layout\n Category: layout\n Kind: object\n Description: Override de WidgetPageLayout para tablet.\n - Path: page.deviceLayouts.tablet.canvas\n Category: layout\n Kind: object\n Description: Override de canvas para tablet.\n - Path: page.deviceLayouts.tablet.groupingOverrides\n Category: layout\n Kind: array\n Description: Overrides de agrupamentos para tablet.\n - Path: page.deviceLayouts.tablet.widgetOverrides\n Category: layout\n Kind: object\n Description: Overrides por widget key para tablet.\n - Path: page.deviceLayouts.tablet.widgetOverrides.<widgetKey>.hidden\n Category: layout\n Kind: boolean\n Description: Oculta o widget em tablet.\n - Path: page.deviceLayouts.mobile.layout\n Category: layout\n Kind: object\n Description: Override de WidgetPageLayout para mobile.\n - Path: page.deviceLayouts.mobile.canvas\n Category: layout\n Kind: object\n Description: Override de canvas para mobile.\n - Path: page.deviceLayouts.mobile.groupingOverrides\n Category: layout\n Kind: array\n Description: Overrides de agrupamentos para mobile.\n - Path: page.deviceLayouts.mobile.widgetOverrides\n Category: layout\n Kind: object\n Description: Overrides por widget key para mobile.\n - Path: page.deviceLayouts.mobile.widgetOverrides.<widgetKey>.hidden\n Category: layout\n Kind: boolean\n Description: Oculta o widget em mobile.\nCapability Notes:\n - page segue o modelo canonico WidgetPageDefinition (widgets, composition.links, context e state opcional); composition.links tambem pode despachar actions globais via to.kind = global-action.\n - Conteudo editorial rico deve ser modelado como widget praxis-rich-content com definition.inputs.document: RichContentDocument, nao como DSL local do page-builder.\n - Quando definition.id = praxis-rich-content em uma pagina dinamica, definition.inputs.document continua sendo o contrato persistido; hostCapabilities e mediado em runtime pelo host praxis-dynamic-page e nao deve ser serializado no JSON da pagina.\n - Edicao visual de inputs de widget deve usar ComponentDocMeta.configEditor ou ComponentDocMeta.authoringManifestRef publicado pela lib dona do componente; nao criar editor local no page-builder para semantica de outro pacote.\n - Canvas e o modelo espacial canonico da pagina quando houver posicionamento explicito.\n - Taxonomia editorial: condition usa Json Logic canonico; transform usa pipeline declarativo; policy cobre apenas comportamento operacional.\n - Para criacao agentic de paginas, o preview pode trazer uiCompositionPlan como plano intermediario validavel; o page-builder compila esse plano para WidgetPageDefinition antes de aplicar.\n - UiCompositionPlan usa widgets[].componentId e bindings declarativos. O JSON persistido continua sendo page.widgets[].definition.id e page.composition.links.\n - Nested component ports usam endpoint component-port com nestedPath. O owner em ref.widget ou bindings[].*.widget continua sendo o widget top-level; a porta real do filho fica em port/direction e o caminho ate o filho fica em nestedPath.\n - Nao gere links nested via owner.widgetEvent, bindingPath profundo, page.connections ou wrappers host-specific. widgetEvent e bridge legada/avancada, nao contrato principal de authoring.\n - Payloads legados de layout ainda podem ser ingeridos, mas sao normalizados para canvas e nao devem ser reemitidos.\n - pageIdentity identifica o escopo de persistencia e nao pertence ao objeto page.\n - Este catálogo é específico para o runtime praxis-dynamic-page; operações de authoring/mutação pertencem ao manifesto do praxis-page-builder.\n - WidgetPageDefinition e o contrato canonico persistido: widgets, composition.links, state, context, layout, canvas, presets, grouping, slotAssignments, deviceLayouts e themePreset.\n - Widgets e page.composition.links sao arrays; ferramentas de patch legadas fazem merge por key estavel e id estavel.\n - page.canvas.items é um mapa por widget key; não modele canvas.items como array.\n - Taxonomia editorial: condition usa Json Logic canônico; transform usa pipeline declarativo; não trate ambos como a mesma \"expression\".\n - Para remocao/replace, use flags {_remove:true} ou {_replace:true} no item.\n - Para renomear um link, inclua {_beforeKey:\"link-id-anterior\"} no item.\n - Inputs de widgets dependem do componente (ex: praxis-table, praxis-dynamic-form). Evite inventar campos; prefira pedir confirmação.\n - Quando page.widgets[].definition.id for praxis-rich-content, o host praxis-dynamic-page injeta hostCapabilities em runtime para actions e capability gating; não serialize funções nem tente persistir page.widgets[].definition.inputs.hostCapabilities.\n - Use ids estaveis para links e keys estaveis para widgets.\n - Nested component ports usam endpoint component-port com nestedPath; o owner em ref.widget continua sendo o widget top-level.\n - Objetivo: compor widgets e relacionamentos canonicos (ex.: master-detail).\n - Link tipico de master-detail: component-port(table.rowClick) -> component-port(form.resourceId) com transform map payload.row.id.\n",
2903
- "sourcePointer": "praxis-ui-angular/projects/praxis-core/src/lib/ai/dynamic-page-ai-capabilities.ts",
2916
+ "sourcePointer": "projects/praxis-core/src/lib/ai/dynamic-page-ai-capabilities.ts",
2904
2917
  "contentHash": "1ae805862c00c852d72e21ff688836728ba62781aef99b3f2bce6282b1a5b0e0",
2905
2918
  "sourceKind": "component_definition",
2906
2919
  "sourceId": "praxis-dynamic-page",
@@ -2910,7 +2923,7 @@
2910
2923
  "chunkIndex": 2,
2911
2924
  "chunkKind": "context_pack",
2912
2925
  "content": "{\n \"componentContext\": {\n \"version\": \"v1.0\",\n \"optionsByPath\": {\n \"page.layout.orientation\": {\n \"mode\": \"enum\",\n \"options\": [\n {\n \"value\": \"vertical\",\n \"label\": \"Vertical\"\n },\n {\n \"value\": \"columns\",\n \"label\": \"Colunas\"\n }\n ]\n },\n \"page.canvas.mode\": {\n \"mode\": \"enum\",\n \"options\": [\n {\n \"value\": \"grid\",\n \"label\": \"Grid\"\n }\n ]\n },\n \"page.canvas.autoRows\": {\n \"mode\": \"enum\",\n \"options\": [\n {\n \"value\": \"fixed\",\n \"label\": \"Linhas fixas\"\n },\n {\n \"value\": \"content\",\n \"label\": \"Conteúdo\"\n }\n ]\n },\n \"page.canvas.collisionPolicy\": {\n \"mode\": \"enum\",\n \"options\": [\n {\n \"value\": \"block\",\n \"label\": \"Bloquear colisao\"\n },\n {\n \"value\": \"swap\",\n \"label\": \"Trocar posicao\"\n }\n ]\n },\n \"page.grouping[].kind\": {\n \"mode\": \"enum\",\n \"options\": [\n {\n \"value\": \"section\",\n \"label\": \"Secao\"\n },\n {\n \"value\": \"tabs\",\n \"label\": \"Abas\"\n },\n {\n \"value\": \"hero\",\n \"label\": \"Hero\"\n },\n {\n \"value\": \"rail\",\n \"label\": \"Rail\"\n }\n ]\n },\n \"page.grouping[].layout\": {\n \"mode\": \"enum\",\n \"options\": [\n {\n \"value\": \"stack\",\n \"label\": \"Empilhado\"\n },\n {\n \"value\": \"grid\",\n \"label\": \"Grid\"\n },\n {\n \"value\": \"row\",\n \"label\": \"Linha\"\n }\n ]\n },\n \"page.grouping[].emphasis\": {\n \"mode\": \"enum\",\n \"options\": [\n {\n \"value\": \"high\",\n \"label\": \"Alta\"\n },\n {\n \"value\": \"medium\",\n \"label\": \"Media\"\n }\n ]\n },\n \"page.grouping[].side\": {\n \"mode\": \"enum\",\n \"options\": [\n {\n \"value\": \"left\",\n \"label\": \"Esquerda\"\n },\n {\n \"value\": \"right\",\n \"label\": \"Direita\"\n }\n ]\n },\n \"page.state.schema.<token>.mergeStrategy\": {\n \"mode\": \"enum\",\n \"options\": [\n {\n \"value\": \"replace\",\n \"label\": \"Substituir\"\n },\n {\n \"value\": \"merge\",\n \"label\": \"Mesclar\"\n },\n {\n \"value\": \"append\",\n \"label\": \"Acrescentar\"\n },\n {\n \"value\": \"remove-keys\",\n \"label\": \"Remover chaves\"\n }\n ]\n },\n \"page.state.derived.<token>.compute.kind\": {\n \"mode\": \"enum\",\n \"options\": [\n {\n \"value\": \"json-logic\",\n \"label\": \"Json Logic\"\n },\n {\n \"value\": \"template\",\n \"label\": \"Template\"\n },\n {\n \"value\": \"operator\",\n \"label\": \"Operador\"\n },\n {\n \"value\": \"transformer\",\n \"label\": \"Transformer\"\n }\n ]\n },\n \"page.widgets[].shell.kind\": {\n \"mode\": \"enum\",\n \"options\": [\n {\n \"value\": \"dashboard-card\",\n \"label\": \"Dashboard Card\"\n },\n {\n \"value\": \"none\",\n \"label\": \"Sem shell\"\n }\n ]\n },\n \"page.widgets[].shell.actions[].variant\": {\n \"mode\": \"enum\",\n \"options\": [\n {\n \"value\": \"icon\",\n \"label\": \"Ícone\"\n },\n {\n \"value\": \"text\",\n \"label\": \"Texto\"\n },\n {\n \"value\": \"outlined\",\n \"label\": \"Outlined\"\n }\n ]\n },\n \"page.widgets[].shell.actions[].placement\": {\n \"mode\": \"enum\",\n \"options\": [\n {\n \"value\": \"header\",\n \"label\": \"Header\"\n },\n {\n \"value\": \"window\",\n \"label\": \"Janela\"\n }\n ]\n },\n \"page.composition.version\": {\n \"mode\": \"enum\",\n \"options\": [\n {\n \"value\": \"1.0.0\",\n \"label\": \"Schema canonico 1.0.0\"\n }\n ]\n },\n \"page.composition.links[].intent\": {\n \"mode\": \"enum\",\n \"options\": [\n {\n \"value\": \"event-propagation\",\n \"label\": \"Propagacao de evento\"\n },\n {\n \"value\": \"state-read\",\n \"label\": \"Leitura de estado\"\n },\n {\n \"value\": \"state-write\",\n \"label\": \"Escrita de estado\"\n }\n ]\n },\n \"page.composition.links[].from.ref.port\": {\n \"mode\": \"suggested\",\n \"options\": [\n {\n \"value\": \"rowClick\",\n \"label\": \"Clique na linha (praxis-table)\",\n \"example\": \"Usar table.rowClick -> form.resourceId via transform pick-path payload.row.id\"\n },\n {\n \"value\": \"rowAction\",\n \"label\": \"Ação da linha (praxis-table)\"\n },\n {\n \"value\": \"formSubmit\",\n \"label\": \"Submit do formulario (praxis-dynamic-form)\"\n }\n ]\n },\n \"page.composition.links[].to.ref.port\": {\n \"mode\": \"suggested\",\n \"options\": [\n {\n \"value\": \"resourceId\",\n \"label\": \"ID do registro (praxis-dynamic-form)\",\n \"example\": \"transform pick-path payload.row.id\"\n },\n {\n \"value\": \"mode\",\n \"label\": \"Modo do formulario (create|edit|view)\"\n }\n ]\n },\n \"page.composition.links[].transform.steps[].config.path\": {\n \"mode\": \"suggested\",\n \"options\": [\n {\n \"value\": \"payload.row.id\",\n \"label\": \"ID padrão do registro\",\n \"example\": \"rowClick -> resourceId\"\n }\n ]\n }\n },\n \"actionCatalog\": [\n {\n \"id\": \"page.widget.remove\",\n \"intentExamples\": [\n \"remover widget\",\n \"excluir widget\",\n \"apagar widget\"\n ],\n \"requiresExistingTarget\": true,\n \"scope\": \"ROW\",\n \"patchTemplate\": {\n \"page\": {\n \"widgets\": [\n {\n \"key\": \"{{target}}\",\n \"_remove\": true\n }\n ]\n }\n }\n },\n {\n \"id\": \"page.connection.remove\",\n \"intentExamples\": [\n \"remover conexao\",\n \"excluir conexao\",\n \"apagar conexao\"\n ],\n \"requiresExistingTarget\": true,\n \"scope\": \"ROW\",\n \"params\": [\n {\n \"name\": \"id\",\n \"type\": \"STRING\"\n }\n ],\n \"patchTemplate\": {\n \"page\": {\n \"composition\": {\n \"version\": \"1.0.0\",\n \"links\": [\n {\n \"_beforeKey\": \"{{target}}\",\n \"id\": \"{{params.id}}\",\n \"_remove\": true\n }\n ]\n }\n }\n }\n },\n {\n \"id\": \"page.layout.orientation.set\",\n \"intentExamples\": [\n \"orientacao\",\n \"orientation\",\n \"layout vertical\",\n \"layout colunas\"\n ],\n \"patchTemplate\": {\n \"page\": {\n \"layout\": {\n \"orientation\": \"{{value}}\"\n }\n }\n }\n },\n {\n \"id\": \"page.layout.columns.set\",\n \"intentExamples\": [\n \"colunas\",\n \"columns\",\n \"qtde colunas\"\n ],\n \"patchTemplate\": {\n \"page\": {\n \"layout\": {\n \"columns\": \"{{value}}\"\n }\n }\n }\n },\n {\n \"id\": \"page.layout.gap.set\",\n \"intentExamples\": [\n \"gap\",\n \"espacamento\",\n \"espaco entre widgets\"\n ],\n \"patchTemplate\": {\n \"page\": {\n \"layout\": {\n \"gap\": \"{{value}}\"\n }\n }\n }\n },\n {\n \"id\": \"page.layout.breakpoints.sm.set\",\n \"intentExamples\": [\n \"breakpoint sm\",\n \"colunas sm\"\n ],\n \"patchTemplate\": {\n \"page\": {\n \"layout\": {\n \"breakpoints\": {\n \"sm\": \"{{value}}\"\n }\n }\n }\n }\n },\n {\n \"id\": \"page.layout.breakpoints.md.set\",\n \"intentExamples\": [\n \"breakpoint md\",\n \"colunas md\"\n ],\n \"patchTemplate\": {\n \"page\": {\n \"layout\": {\n \"breakpoints\": {\n \"md\": \"{{value}}\"\n }\n }\n }\n }\n },\n {\n \"id\": \"page.layout.breakpoints.lg.set\",\n \"intentExamples\": [\n \"breakpoint lg\",\n \"colunas lg\"\n ],\n \"patchTemplate\": {\n \"page\": {\n \"layout\": {\n \"breakpoints\": {\n \"lg\": \"{{value}}\"\n }\n }\n }\n }\n },\n {\n \"id\": \"page.layout.breakpoints.xl.set\",\n \"intentExamples\": [\n \"breakpoint xl\",\n \"colunas xl\"\n ],\n \"patchTemplate\": {\n \"page\": {\n \"layout\": {\n \"breakpoints\": {\n \"xl\": \"{{value}}\"\n }\n }\n }\n }\n },\n {\n \"id\": \"page.connection.set\",\n \"intentExamples\": [\n \"set connection\",\n \"definir conexao\",\n \"valor fixo\",\n \"set constante\"\n ],\n \"params\": [\n {\n \"name\": \"fromWidget\",\n \"type\": \"STRING\"\n },\n {\n \"name\": \"fromOutput\",\n \"type\": \"STRING\"\n },\n {\n \"name\": \"toWidget\",\n \"type\": \"STRING\"\n },\n {\n \"name\": \"toInput\",\n \"type\": \"STRING\"\n },\n {\n \"name\": \"value\",\n \"type\": \"STRING\"\n }\n ],\n \"patchTemplate\": {\n \"page\": {\n \"composition\": {\n \"version\": \"1.0.0\",\n \"links\": [\n {\n \"id\": \"{{params.fromWidget}}.{{params.fromOutput}}->{{params.toWidget}}.{{params.toInput}}\",\n \"from\": {\n \"kind\": \"component-port\",\n \"ref\": {\n \"widget\": \"{{params.fromWidget}}\",\n \"port\": \"{{params.fromOutput}}\",\n \"direction\": \"output\"\n }\n },\n \"to\": {\n \"kind\": \"component-port\",\n \"ref\": {\n \"widget\": \"{{params.toWidget}}\",\n \"port\": \"{{params.toInput}}\",\n \"direction\": \"input\"\n }\n },\n \"intent\": \"event-propagation\",\n \"transform\": {\n \"version\": \"2.0\",\n \"phase\": \"link-propagation\",\n \"mode\": \"single-value\",\n \"steps\": [\n {\n \"id\": \"constant-value\",\n \"kind\": \"constant\",\n \"phase\": \"link-propagation\",\n \"config\": {\n \"value\": \"{{params.value}}\"\n }\n }\n ]\n },\n \"metadata\": {\n \"source\": \"persisted-composition-link\"\n },\n \"_replace\": true\n }\n ]\n }\n }\n }\n },\n {\n \"id\": \"page.widget.upsert\",\n \"intentExamples\": [\n \"adicionar widget\",\n \"novo widget\",\n \"inserir widget\",\n \"atualizar widget\"\n ],\n \"params\": [\n {\n \"name\": \"widgetKey\",\n \"type\": \"STRING\"\n },\n {\n \"name\": \"widgetType\",\n \"type\": \"STRING\"\n }\n ],\n \"patchTemplate\": {\n \"page\": {\n \"widgets\": [\n {\n \"key\": \"{{params.widgetKey}}\",\n \"definition\": {\n \"id\": \"{{params.widgetType}}\",\n \"inputs\": {},\n \"bindingOrder\": []\n },\n \"_replace\": true\n }\n ]\n }\n }\n },\n {\n \"id\": \"page.connection.move\",\n \"intentExamples\": [\n \"mover conexao\",\n \"alterar conexao\",\n \"editar conexao\",\n \"trocar conexao\"\n ],\n \"params\": [\n {\n \"name\": \"fromWidget\",\n \"type\": \"STRING\"\n },\n {\n \"name\": \"fromOutput\",\n \"type\": \"STRING\"\n },\n {\n \"name\": \"toWidget\",\n \"type\": \"STRING\"\n },\n {\n \"name\": \"toInput\",\n \"type\": \"STRING\"\n },\n {\n \"name\": \"beforeFromWidget\",\n \"type\": \"STRING\"\n },\n {\n \"name\": \"beforeFromOutput\",\n \"type\": \"STRING\"\n },\n {\n \"name\": \"beforeToWidget\",\n \"type\": \"STRING\"\n },\n {\n \"name\": \"beforeToInput\",\n \"type\": \"STRING\"\n }\n ],\n \"patchTemplate\": {\n \"page\": {\n \"composition\": {\n \"version\": \"1.0.0\",\n \"links\": [\n {\n \"_beforeKey\": \"{{params.beforeFromWidget}}.{{params.beforeFromOutput}}->{{params.beforeToWidget}}.{{params.beforeToInput}}\",\n \"id\": \"{{params.fromWidget}}.{{params.fromOutput}}->{{params.toWidget}}.{{params.toInput}}\",\n \"from\": {\n \"kind\": \"component-port\",\n \"ref\": {\n \"widget\": \"{{params.fromWidget}}\",\n \"port\": \"{{params.fromOutput}}\",\n \"direction\": \"output\"\n }\n },\n \"to\": {\n \"kind\": \"component-port\",\n \"ref\": {\n \"widget\": \"{{params.toWidget}}\",\n \"port\": \"{{params.toInput}}\",\n \"direction\": \"input\"\n }\n },\n \"intent\": \"event-propagation\",\n \"metadata\": {\n \"source\": \"persisted-composition-link\"\n }\n }\n ]\n }\n }\n }\n },\n {\n \"id\": \"page.widget.createTable\",\n \"intentExamples\": [\n \"criar tabela\",\n \"adicionar tabela\",\n \"widget tabela\"\n ],\n \"operation\": \"create\",\n \"scope\": \"ROW\",\n \"valueType\": \"OBJECT\",\n \"params\": [\n {\n \"name\": \"widgetKey\",\n \"type\": \"STRING\"\n },\n {\n \"name\": \"resourcePath\",\n \"type\": \"STRING\"\n }\n ],\n \"safetyNotes\": \"Use apenas resourcePath base. Evite inventar colunas; deixe config minima.\",\n \"patchTemplate\": {\n \"page\": {\n \"widgets\": [\n {\n \"key\": \"{{params.widgetKey}}\",\n \"definition\": {\n \"id\": \"praxis-table\",\n \"bindingOrder\": [\n \"config\",\n \"resourcePath\"\n ],\n \"inputs\": {\n \"resourcePath\": \"{{params.resourcePath}}\",\n \"tableId\": \"{{params.widgetKey}}\"\n }\n },\n \"_replace\": true\n }\n ]\n }\n }\n },\n {\n \"id\": \"page.widget.createForm\",\n \"intentExamples\": [\n \"criar formulario\",\n \"adicionar formulario\",\n \"widget formulario\"\n ],\n \"operation\": \"create\",\n \"scope\": \"ROW\",\n \"valueType\": \"OBJECT\",\n \"params\": [\n {\n \"name\": \"widgetKey\",\n \"type\": \"STRING\"\n },\n {\n \"name\": \"resourcePath\",\n \"type\": \"STRING\"\n },\n {\n \"name\": \"mode\",\n \"type\": \"STRING\"\n }\n ],\n \"safetyNotes\": \"Use resourcePath base e mode=create|edit|view. Evite inventar campos.\",\n \"patchTemplate\": {\n \"page\": {\n \"widgets\": [\n {\n \"key\": \"{{params.widgetKey}}\",\n \"definition\": {\n \"id\": \"praxis-dynamic-form\",\n \"bindingOrder\": [\n \"resourcePath\",\n \"formId\",\n \"resourceId\"\n ],\n \"inputs\": {\n \"resourcePath\": \"{{params.resourcePath}}\",\n \"formId\": \"{{params.widgetKey}}\",\n \"mode\": \"{{params.mode}}\"\n }\n },\n \"_replace\": true\n }\n ]\n }\n }\n },\n {\n \"id\": \"page.connection.bindRowToForm\",\n \"intentExamples\": [\n \"conectar tabela ao formulario\",\n \"master detail\",\n \"master-detail\",\n \"detalhe\"\n ],\n \"operation\": \"create\",\n \"scope\": \"ROW\",\n \"valueType\": \"OBJECT\",\n \"params\": [\n {\n \"name\": \"fromWidget\",\n \"type\": \"STRING\"\n },\n {\n \"name\": \"toWidget\",\n \"type\": \"STRING\"\n },\n {\n \"name\": \"fromOutput\",\n \"type\": \"STRING\"\n },\n {\n \"name\": \"toInput\",\n \"type\": \"STRING\"\n },\n {\n \"name\": \"map\",\n \"type\": \"STRING\"\n }\n ],\n \"safetyNotes\": \"Use transform pick-path payload.row.id para master-detail padrão.\",\n \"patchTemplate\": {\n \"page\": {\n \"composition\": {\n \"version\": \"1.0.0\",\n \"links\": [\n {\n \"id\": \"{{params.fromWidget}}.{{params.fromOutput}}->{{params.toWidget}}.{{params.toInput}}\",\n \"from\": {\n \"kind\": \"component-port\",\n \"ref\": {\n \"widget\": \"{{params.fromWidget}}\",\n \"port\": \"{{params.fromOutput}}\",\n \"direction\": \"output\"\n }\n },\n \"to\": {\n \"kind\": \"component-port\",\n \"ref\": {\n \"widget\": \"{{params.toWidget}}\",\n \"port\": \"{{params.toInput}}\",\n \"direction\": \"input\"\n }\n },\n \"intent\": \"event-propagation\",\n \"transform\": {\n \"version\": \"2.0\",\n \"phase\": \"link-propagation\",\n \"mode\": \"single-value\",\n \"steps\": [\n {\n \"id\": \"pick-master-detail-value\",\n \"kind\": \"pick-path\",\n \"phase\": \"link-propagation\",\n \"input\": {\n \"source\": \"event\"\n },\n \"config\": {\n \"path\": \"{{params.map}}\"\n }\n }\n ]\n },\n \"metadata\": {\n \"source\": \"persisted-composition-link\"\n },\n \"_replace\": true\n }\n ]\n }\n }\n }\n },\n {\n \"id\": \"page.connection.bindMasterDetail\",\n \"intentExamples\": [\n \"master detail\",\n \"master-detail\",\n \"conectar tabela ao formulario\",\n \"detalhe\"\n ],\n \"operation\": \"create\",\n \"scope\": \"ROW\",\n \"valueType\": \"OBJECT\",\n \"params\": [\n {\n \"name\": \"fromWidget\",\n \"type\": \"STRING\"\n },\n {\n \"name\": \"toWidget\",\n \"type\": \"STRING\"\n }\n ],\n \"safetyNotes\": \"Padrão master-detail: rowClick -> resourceId com transform pick-path payload.row.id.\",\n \"patchTemplate\": {\n \"page\": {\n \"composition\": {\n \"version\": \"1.0.0\",\n \"links\": [\n {\n \"id\": \"{{params.fromWidget}}.rowClick->{{params.toWidget}}.resourceId\",\n \"from\": {\n \"kind\": \"component-port\",\n \"ref\": {\n \"widget\": \"{{params.fromWidget}}\",\n \"port\": \"rowClick\",\n \"direction\": \"output\"\n }\n },\n \"to\": {\n \"kind\": \"component-port\",\n \"ref\": {\n \"widget\": \"{{params.toWidget}}\",\n \"port\": \"resourceId\",\n \"direction\": \"input\"\n }\n },\n \"intent\": \"event-propagation\",\n \"transform\": {\n \"version\": \"2.0\",\n \"phase\": \"link-propagation\",\n \"mode\": \"single-value\",\n \"steps\": [\n {\n \"id\": \"pick-master-row-id\",\n \"kind\": \"pick-path\",\n \"phase\": \"link-propagation\",\n \"input\": {\n \"source\": \"event\"\n },\n \"config\": {\n \"path\": \"payload.row.id\"\n }\n }\n ]\n },\n \"metadata\": {\n \"source\": \"persisted-composition-link\"\n },\n \"_replace\": true\n }\n ]\n }\n }\n }\n },\n {\n \"id\": \"page.template.applyMasterDetail\",\n \"intentExamples\": [\n \"criar página master detail\",\n \"setup master detail\",\n \"tabela e formulário\",\n \"master-detail\"\n ],\n \"operation\": \"create\",\n \"scope\": \"GLOBAL\",\n \"valueType\": \"OBJECT\",\n \"params\": [\n {\n \"name\": \"tableId\",\n \"type\": \"STRING\"\n },\n {\n \"name\": \"formId\",\n \"type\": \"STRING\"\n },\n {\n \"name\": \"resourcePath\",\n \"type\": \"STRING\"\n }\n ],\n \"safetyNotes\": \"Padrão master-detail: tabela (rowClick) -> formulario (resourceId) com transform pick-path payload.row.id.\",\n \"patchTemplate\": {\n \"page\": {\n \"widgets\": [\n {\n \"key\": \"{{params.tableId}}\",\n \"definition\": {\n \"id\": \"praxis-table\",\n \"bindingOrder\": [\n \"config\",\n \"resourcePath\"\n ],\n \"inputs\": {\n \"tableId\": \"{{params.tableId}}\",\n \"resourcePath\": \"{{params.resourcePath}}\"\n },\n \"outputs\": {\n \"rowClick\": \"emit\"\n }\n },\n \"_replace\": true\n },\n {\n \"key\": \"{{params.formId}}\",\n \"definition\": {\n \"id\": \"praxis-dynamic-form\",\n \"bindingOrder\": [\n \"resourcePath\",\n \"formId\",\n \"resourceId\"\n ],\n \"inputs\": {\n \"formId\": \"{{params.formId}}\",\n \"resourcePath\": \"{{params.resourcePath}}\",\n \"mode\": \"view\"\n }\n },\n \"_replace\": true\n }\n ],\n \"composition\": {\n \"version\": \"1.0.0\",\n \"links\": [\n {\n \"id\": \"{{params.tableId}}.rowClick->{{params.formId}}.resourceId\",\n \"from\": {\n \"kind\": \"component-port\",\n \"ref\": {\n \"widget\": \"{{params.tableId}}\",\n \"port\": \"rowClick\",\n \"direction\": \"output\"\n }\n },\n \"to\": {\n \"kind\": \"component-port\",\n \"ref\": {\n \"widget\": \"{{params.formId}}\",\n \"port\": \"resourceId\",\n \"direction\": \"input\"\n }\n },\n \"intent\": \"event-propagation\",\n \"transform\": {\n \"version\": \"2.0\",\n \"phase\": \"link-propagation\",\n \"mode\": \"single-value\",\n \"steps\": [\n {\n \"id\": \"pick-master-row-id\",\n \"kind\": \"pick-path\",\n \"phase\": \"link-propagation\",\n \"input\": {\n \"source\": \"event\"\n },\n \"config\": {\n \"path\": \"payload.row.id\"\n }\n }\n ]\n },\n \"metadata\": {\n \"source\": \"persisted-composition-link\"\n },\n \"_replace\": true\n }\n ]\n }\n }\n }\n }\n ],\n \"fieldResolvers\": {\n \"page.widgets[]\": [\n \"key\"\n ],\n \"page.composition.links[]\": [\n \"id\"\n ]\n },\n \"hints\": [\n \"praxis-dynamic-page e runtime de composicao: consome WidgetPageDefinition, renderiza widgets e mantem relacoes em page.composition.links.\",\n \"Mutações agentic de página pertencem ao manifesto do praxis-page-builder; use este context pack como descoberta/runtime guidance.\",\n \"WidgetPageDefinition inclui widgets, composition.links, state, context, layout, canvas, layoutPreset, layoutPresetOptions, grouping, slotAssignments, deviceLayouts e themePreset.\",\n \"page.canvas.items é um mapa por widget key, não um array; cada entrada guarda col, row, colSpan, rowSpan, zIndex e constraints opcionais.\",\n \"Widgets e composition.links sao arrays; o patching deve fazer merge por key (widgets) e por id (links).\",\n \"Preferir mudanças incrementais: alterar/estender em vez de substituir toda a página.\",\n \"Para remover um item, envie {_remove: true} junto ao widget/link.\",\n \"Para substituir um item inteiro, envie {_replace: true}.\",\n \"Para alterar origem/destino de link, use {_beforeKey} com o id antigo.\",\n \"Use keys estaveis para widgets e ids estaveis para links ao criar composicoes.\",\n \"resourcePath sempre e o path base do recurso (sem /filter, /all).\",\n \"Praxis Table gera colunas dinamicamente a partir do resourcePath quando columns não forem definidas.\",\n \"Praxis Dynamic Form gera campos dinamicamente a partir do resourcePath quando config não for definida.\",\n \"Quando um widget praxis-rich-content estiver hospedado na página, definition.inputs.document continua sendo o contrato persistido; hostCapabilities é injetado somente em runtime pelo praxis-dynamic-page para actions e capability gating.\",\n \"Praxis List pode filtrar via config.dataSource.query (enviado para /filter).\",\n \"Quando houver recursos secundarios (ex.: enderecos), use contextHints.addressResourcePath.\",\n \"Exemplo master-detail: tabela emite rowClick -> form.resourceId via transform pick-path payload.row.id.\",\n \"Pattern Master-Detail: { \\\"id\\\":\\\"master.rowClick->detail.resourceId\\\", \\\"from\\\":{\\\"kind\\\":\\\"component-port\\\",\\\"ref\\\":{\\\"port\\\":\\\"rowClick\\\",\\\"direction\\\":\\\"output\\\"}}, \\\"to\\\":{\\\"kind\\\":\\\"component-port\\\",\\\"ref\\\":{\\\"port\\\":\\\"resourceId\\\",\\\"direction\\\":\\\"input\\\"}}, \\\"transform\\\":{\\\"steps\\\":[{\\\"kind\\\":\\\"pick-path\\\",\\\"config\\\":{\\\"path\\\":\\\"payload.row.id\\\"}}]}}\",\n \"Ao criar widgets, use inputs minimos e complemente depois (evite inventar campos).\",\n \"Quando widgets ja existem, interpretar ports de origem/destino antes de conectar.\",\n \"Intenção comum: criar página master-detail = criar tabela + criar formulário + conectar seleção via composition.links.\",\n \"Intenção comum: ajustar página existente = modificar apenas widgets/inputs necessários.\",\n \"Exemplo de link canonico (master-detail): { id:\\\"masterTable.rowClick->detailForm.resourceId\\\", from:{kind:\\\"component-port\\\",ref:{widget:\\\"masterTable\\\",port:\\\"rowClick\\\",direction:\\\"output\\\"}}, to:{kind:\\\"component-port\\\",ref:{widget:\\\"detailForm\\\",port:\\\"resourceId\\\",direction:\\\"input\\\"}}, intent:\\\"event-propagation\\\", transform:{version:\\\"2.0\\\",phase:\\\"link-propagation\\\",mode:\\\"single-value\\\",steps:[{kind:\\\"pick-path\\\",phase:\\\"link-propagation\\\",input:{source:\\\"event\\\"},config:{path:\\\"payload.row.id\\\"}}]}}\",\n \"Exemplo de widget tabela (mínimo): { key:\\\"masterTable\\\", definition:{ id:\\\"praxis-table\\\", inputs:{ resourcePath:\\\"/api/x\\\" }}}\",\n \"Exemplo de widget formulário (mínimo): { key:\\\"detailForm\\\", definition:{ id:\\\"praxis-dynamic-form\\\", inputs:{ resourcePath:\\\"/api/x\\\", mode:\\\"view\\\" }}}\",\n \"Se houver idField conhecido, use transform pick-path payload.row.{idField} em links canonicos.\"\n ]\n }\n}",
2913
- "sourcePointer": "praxis-ui-angular/projects/praxis-core/src/lib/ai/dynamic-page-context-pack.ts",
2926
+ "sourcePointer": "projects/praxis-core/src/lib/ai/dynamic-page-context-pack.ts",
2914
2927
  "contentHash": "700715ca6fe6e50f477ffb731a5397282e49c42f00d3cb60e4d3222a94497361",
2915
2928
  "sourceKind": "component_definition",
2916
2929
  "sourceId": "praxis-dynamic-page",
@@ -2920,7 +2933,7 @@
2920
2933
  "chunkIndex": 3,
2921
2934
  "chunkKind": "recipe",
2922
2935
  "content": "{\n \"_comment\": \"Recipe para agentes criarem uma Praxis Dynamic Page que demonstra actions de toolbar, linha, bulk, footer e modais de discovery.\",\n \"_comment2\": \"Use quando a meta for mostrar praxis-table como superficie operacional, nao apenas CRUD basico.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"actions-workspace\",\n \"status\": \"public-example\",\n \"useWhen\": \"Create a metadata-driven table page with toolbar, row, bulk, floating and footer actions.\",\n \"examplePrompts\": [\n \"crie uma tabela com actions de linha e bulk para funcionarios\",\n \"mostre botoes que abrem surfaces e actions em modal\",\n \"gere um exemplo de praxis-table com barra de acoes em cima e embaixo\"\n ]\n },\n \"platformValue\": {\n \"canonicalContract\": \"praxis-metadata-starter publishes /schemas/actions, /schemas/surfaces and resource capabilities.\",\n \"referenceApi\": \"praxis-api-quickstart serves funcionarios metadata, filter data and per-resource capabilities.\",\n \"angularRuntime\": \"@praxisui/table renders toolbar actions, row actions, bulk actions and selection-aware affordances.\",\n \"publicExamples\": \"praxis-ui-landing-page exposes the JSON envelope, runtime preview and modal discovery.\",\n \"agentCorpus\": \"This recipe keeps action semantics explicit so LLMs can compose richer operational pages.\"\n },\n \"operationalEvidence\": {\n \"baseUrl\": \"https://praxis-api-quickstart.onrender.com\",\n \"safeFirstIds\": [\n \"filtered-schema-response-funcionarios\",\n \"funcionarios-filter-basic\",\n \"schemas-surfaces-human-resources-funcionarios\"\n ],\n \"httpExamples\": [\n \"praxisui-http-examples/http/metadata/filtered_schema_response_funcionarios.http\",\n \"praxisui-http-examples/http/resources/funcionarios_filter_basic.http\",\n \"praxisui-http-examples/http/metadata/schemas_surfaces_human_resources_funcionarios.http\"\n ],\n \"notes\": [\n \"The published quickstart currently exposes funcionarios surfaces but not a /schemas/actions discovery document for this resource, so discovery previews stay host-authored.\",\n \"The row, bulk, footer and floating actions in this recipe are host-authored UX affordances.\"\n ]\n },\n \"authoringGuidance\": [\n \"Use toolbar.actions for primary page-level affordances such as refresh, create and discovery.\",\n \"Use toolbar.actionsPosition = both when the same action bar should remain available below the table.\",\n \"Use actions.row for row-specific affordances and include discovery metadata when the host should open runtime previews.\",\n \"Use actions.bulk for selection-aware workflows; pair it with behavior.selection and visibleWhen selectedCount rules.\",\n \"Restrict row-specific detail actions such as profile opening to selectedCount = 1.\",\n \"Emit rowAction, bulkAction and toolbarAction when the host needs to govern modals, policy checks or workflow openings.\",\n \"Treat host-authored actions as UX affordances and reconcile destructive or policy-sensitive execution against backend capabilities.\"\n ],\n \"teaches\": [\n \"table.toolbar.actions\",\n \"table.toolbar.actionsPosition\",\n \"table.actions.row\",\n \"table.actions.bulk\",\n \"table.actions.floating\",\n \"visibleWhen\",\n \"shortcuts\",\n \"surfaces-actions-capabilities\"\n ],\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 1,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"funcionariosActionsWorkspace\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"bolt\",\n \"title\": \"Funcionarios actions workspace\",\n \"subtitle\": \"Toolbar, row, bulk, floating and footer actions\"\n },\n \"definition\": {\n \"id\": \"praxis-table\",\n \"bindingOrder\": [\n \"config\",\n \"resourcePath\"\n ],\n \"inputs\": {\n \"resourcePath\": \"human-resources/funcionarios\",\n \"tableId\": \"human-resources-funcionarios-actions-workspace\",\n \"config\": {\n \"toolbar\": {\n \"visible\": true,\n \"title\": \"Funcionarios\",\n \"subtitle\": \"Action surfaces and workflow affordances\",\n \"actionsPosition\": \"both\",\n \"actions\": [\n {\n \"id\": \"refresh-table\",\n \"action\": \"refresh-table\",\n \"label\": \"Refresh\",\n \"icon\": \"refresh\",\n \"type\": \"icon\",\n \"position\": \"start\",\n \"order\": 10,\n \"tooltip\": \"Refresh current table data\",\n \"shortcut\": \"Ctrl+R\",\n \"shortcutScope\": \"toolbar\"\n },\n {\n \"id\": \"create-funcionario\",\n \"action\": \"create\",\n \"label\": \"Create\",\n \"icon\": \"add\",\n \"appearance\": \"elevated\",\n \"color\": \"primary\",\n \"position\": \"end\",\n \"order\": 20,\n \"tooltip\": \"Create through a host-governed opening\"\n },\n {\n \"id\": \"selected-actions\",\n \"action\": \"selected-actions\",\n \"label\": \"Selected\",\n \"icon\": \"task_alt\",\n \"type\": \"menu\",\n \"appearance\": \"outlined\",\n \"position\": \"end\",\n \"order\": 30,\n \"visibleWhen\": {\n \">\": [\n {\n \"var\": \"selectedCount\"\n },\n 0\n ]\n },\n \"children\": [\n {\n \"id\": \"inspect-selected-capabilities\",\n \"action\": \"inspect-actions\",\n \"label\": \"Inspect capabilities\",\n \"icon\": \"bolt\",\n \"order\": 10,\n \"discovery\": {\n \"rel\": \"actions\",\n \"scope\": \"resource\",\n \"resourcePath\": \"human-resources/funcionarios\",\n \"resourceKey\": \"human-resources.funcionarios\"\n }\n },\n {\n \"id\": \"open-selected-profile\",\n \"action\": \"profile\",\n \"label\": \"Open profile\",\n \"icon\": \"badge\",\n \"order\": 20,\n \"shortcut\": \"Ctrl+Enter\",\n \"visibleWhen\": {\n \"==\": [\n {\n \"var\": \"selectedCount\"\n },\n 1\n ]\n }\n }\n ]\n },\n {\n \"id\": \"inspect-surfaces\",\n \"action\": \"inspect-surfaces\",\n \"label\": \"Surfaces\",\n \"icon\": \"layers\",\n \"type\": \"button\",\n \"appearance\": \"outlined\",\n \"position\": \"end\",\n \"order\": 90,\n \"tooltip\": \"Inspect published resource surfaces\",\n \"discovery\": {\n \"rel\": \"surfaces\",\n \"scope\": \"resource\",\n \"resourcePath\": \"human-resources/funcionarios\",\n \"resourceKey\": \"human-resources.funcionarios\"\n }\n },\n {\n \"id\": \"inspect-actions\",\n \"action\": \"inspect-actions\",\n \"label\": \"Actions\",\n \"icon\": \"bolt\",\n \"type\": \"button\",\n \"appearance\": \"outlined\",\n \"position\": \"end\",\n \"order\": 100,\n \"tooltip\": \"Inspect published resource actions and capabilities\",\n \"discovery\": {\n \"rel\": \"actions\",\n \"scope\": \"resource\",\n \"resourcePath\": \"human-resources/funcionarios\",\n \"resourceKey\": \"human-resources.funcionarios\"\n }\n }\n ]\n },\n \"columns\": [\n {\n \"field\": \"nomeCompleto\",\n \"header\": \"Funcionario\",\n \"type\": \"text\",\n \"sticky\": \"start\",\n \"width\": \"220px\"\n },\n {\n \"field\": \"email\",\n \"header\": \"Email\",\n \"type\": \"string\",\n \"width\": \"260px\"\n },\n {\n \"field\": \"cargoNome\",\n \"header\": \"Cargo\",\n \"type\": \"chip\",\n \"width\": \"180px\"\n },\n {\n \"field\": \"departamentoNome\",\n \"header\": \"Departamento\",\n \"type\": \"badge\",\n \"width\": \"190px\"\n },\n {\n \"field\": \"ativo\",\n \"header\": \"Status\",\n \"type\": \"boolean\",\n \"align\": \"center\",\n \"format\": \"active-inactive\",\n \"width\": \"130px\",\n \"conditionalRenderers\": [\n {\n \"condition\": { \"==\": [{ \"var\": \"ativo\" }, true] },\n \"renderer\": {\n \"type\": \"badge\",\n \"badge\": {\n \"text\": \"Ativo\",\n \"color\": \"success\",\n \"variant\": \"filled\",\n \"icon\": \"check_circle\"\n }\n }\n },\n {\n \"condition\": { \"==\": [{ \"var\": \"ativo\" }, false] },\n \"renderer\": {\n \"type\": \"badge\",\n \"badge\": {\n \"text\": \"Inativo\",\n \"color\": \"warn\",\n \"variant\": \"outlined\",\n \"icon\": \"block\"\n }\n }\n }\n ]\n }\n ],\n \"export\": {\n \"enabled\": true,\n \"formats\": [\"csv\"],\n \"general\": {\n \"includeHeaders\": true,\n \"scope\": \"selected\",\n \"defaultFileName\": \"funcionarios-selected\",\n \"includeColumns\": \"visible\",\n \"applyFormatting\": true\n }\n },\n \"actions\": {\n \"row\": {\n \"enabled\": true,\n \"display\": \"icons\",\n \"position\": \"end\",\n \"sticky\": \"end\",\n \"width\": \"168px\",\n \"header\": {\n \"label\": \"Workflow\",\n \"icon\": \"bolt\",\n \"tooltip\": \"Inline and overflow row actions\"\n },\n \"behavior\": {\n \"maxInline\": 2\n },\n \"menu\": {\n \"icon\": \"more_vert\",\n \"tooltip\": \"More row actions\",\n \"color\": \"primary\"\n },\n \"actions\": [\n {\n \"id\": \"view\",\n \"action\": \"view\",\n \"label\": \"View\",\n \"icon\": \"visibility\",\n \"color\": \"primary\",\n \"tooltip\": \"Open detail surface\"\n },\n {\n \"id\": \"edit\",\n \"action\": \"edit\",\n \"label\": \"Edit\",\n \"icon\": \"edit\",\n \"color\": \"accent\",\n \"tooltip\": \"Open edit workflow when allowed\"\n },\n {\n \"id\": \"inspect-row-capabilities\",\n \"action\": \"inspect-actions\",\n \"label\": \"Capabilities\",\n \"icon\": \"policy\",\n \"color\": \"primary\",\n \"tooltip\": \"Inspect row-level capabilities\",\n \"discovery\": {\n \"rel\": \"actions\",\n \"scope\": \"resource\",\n \"resourcePath\": \"human-resources/funcionarios\",\n \"resourceKey\": \"human-resources.funcionarios\"\n }\n },\n {\n \"id\": \"deactivate\",\n \"action\": \"deactivate\",\n \"label\": \"Deactivate\",\n \"icon\": \"block\",\n \"color\": \"warn\",\n \"tooltip\": \"Workflow action gated by backend policy\"\n }\n ]\n },\n \"bulk\": {\n \"enabled\": true,\n \"position\": \"both\",\n \"floating\": {\n \"position\": \"bottom-right\",\n \"hideWhenEmpty\": true\n },\n \"actions\": [\n {\n \"id\": \"bulk-export\",\n \"action\": \"bulk-export\",\n \"label\": \"Export selected\",\n \"icon\": \"download\",\n \"color\": \"primary\",\n \"appearance\": \"outlined\",\n \"exportFormat\": \"csv\",\n \"visibleWhen\": {\n \">\": [\n {\n \"var\": \"selectedCount\"\n },\n 0\n ]\n },\n \"shortcut\": \"Ctrl+Shift+E\"\n },\n {\n \"id\": \"bulk-inspect-capabilities\",\n \"action\": \"inspect-actions\",\n \"label\": \"Inspect selected\",\n \"icon\": \"policy\",\n \"color\": \"accent\",\n \"appearance\": \"tonal\",\n \"visibleWhen\": {\n \">\": [\n {\n \"var\": \"selectedCount\"\n },\n 0\n ]\n },\n \"discovery\": {\n \"rel\": \"actions\",\n \"scope\": \"resource\",\n \"resourcePath\": \"human-resources/funcionarios\",\n \"resourceKey\": \"human-resources.funcionarios\"\n }\n }\n ]\n }\n },\n \"behavior\": {\n \"selection\": {\n \"enabled\": true,\n \"type\": \"multiple\"\n },\n \"pagination\": {\n \"enabled\": true,\n \"position\": \"both\",\n \"style\": \"compact\",\n \"pageSize\": 10\n },\n \"density\": \"compact\"\n }\n }\n },\n \"outputs\": {\n \"rowClick\": \"emit\",\n \"rowAction\": \"emit\",\n \"bulkAction\": \"emit\",\n \"toolbarAction\": \"emit\",\n \"selectionChange\": \"emit\"\n }\n }\n }\n ]\n }\n}\n",
2923
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.actions-workspace.json",
2936
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.actions-workspace.json",
2924
2937
  "contentHash": "8b007a6fd6e2424173df7110cc1cfcd5c3e37857b081caf4692937a39ec74526",
2925
2938
  "sourceKind": "component_definition",
2926
2939
  "sourceId": "praxis-dynamic-page",
@@ -2930,7 +2943,7 @@
2930
2943
  "chunkIndex": 4,
2931
2944
  "chunkKind": "recipe",
2932
2945
  "content": "{\n \"_comment\": \"Praxis Dynamic Page recipe for an approval audit workbench using portable rich-content blocks for compliance signals, evidence tabs and governed remediation actions.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"approval-audit-workbench\",\n \"status\": \"public-example\",\n \"useWhen\": \"Create an approval audit or compliance workbench with evidence context, policy views and governed remediation actions.\",\n \"examplePrompts\": [\n \"create an approval audit workbench\",\n \"show a governed approval compliance rich content surface\",\n \"generate an approval audit page with evidence packet and remediation actions\"\n ]\n },\n \"platformValue\": {\n \"canonicalRuntime\": \"@praxisui/rich-content owns the portable approval audit surface.\",\n \"hostMediation\": \"The host mediates open, lock, remediate and escalate actions through actionId contracts.\",\n \"publicExamples\": \"praxis-ui-landing-page can expose the same approval audit workbench without serializing runtime helpers.\",\n \"agentCorpus\": \"This recipe keeps audit signals, evidence context, policy notes and remediation actions inside RichContentDocument so agents can reuse the same semantic surface across hosts.\"\n },\n \"authoringGuidance\": [\n \"Use definition.id \\\"praxis-rich-content\\\".\",\n \"Model compliance metrics with statGroup instead of custom host KPI cards.\",\n \"Model the selected audit case with lookupCard when the host already resolved the case context.\",\n \"Use tabs for evidence and policy instead of host-authored audit sections.\",\n \"Use relatedRecord, ctaGroup and actionCard for governed remediation and escalation actions; keep handlers out of the document.\",\n \"Do not serialize hostCapabilities in the page JSON; the host injects runtime mediation only while rendering.\"\n ],\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 1,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"approvalAuditWorkbench\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"policy\",\n \"title\": \"Approval audit workbench\",\n \"subtitle\": \"Portable rich-content surface for governed approval audit flows\"\n },\n \"definition\": {\n \"id\": \"praxis-rich-content\",\n \"bindingOrder\": [\"document\", \"context\", \"layout\", \"rootClassName\"],\n \"inputs\": {\n \"layout\": \"block\",\n \"rootClassName\": \"approval-audit-workbench\",\n \"context\": {\n \"audit\": {\n \"caseId\": \"AUD-771\",\n \"title\": \"Expense delegation exception\",\n \"status\": \"Packet under review\",\n \"exceptions\": \"4\",\n \"sla\": \"6h\",\n \"severity\": \"Critical\",\n \"controlFamily\": \"Delegation of authority\",\n \"submitter\": \"Livia Costa\"\n },\n \"owner\": {\n \"name\": \"Priya Nunes\",\n \"department\": \"Internal controls\"\n }\n },\n \"document\": {\n \"kind\": \"praxis.rich-content\",\n \"version\": \"1.0.0\",\n \"nodes\": [\n {\n \"type\": \"callout\",\n \"tone\": \"warning\",\n \"icon\": \"policy\",\n \"titleExpr\": \"${audit.title}\",\n \"message\": \"Use a portable approval audit surface when the host must expose governed compliance and remediation actions without inventing approval-specific templates.\"\n },\n {\n \"type\": \"statGroup\",\n \"title\": \"Audit signals\",\n \"subtitle\": \"Canonical KPI block for approval audit surfaces\",\n \"layout\": \"grid\",\n \"items\": [\n {\n \"label\": \"Exceptions\",\n \"valueExpr\": \"${audit.exceptions}\",\n \"captionExpr\": \"${audit.caseId}\",\n \"icon\": \"gpp_maybe\"\n },\n {\n \"label\": \"SLA\",\n \"valueExpr\": \"${audit.sla}\",\n \"captionExpr\": \"${audit.status}\",\n \"icon\": \"schedule\"\n },\n {\n \"label\": \"Severity\",\n \"valueExpr\": \"${audit.severity}\",\n \"captionExpr\": \"${audit.controlFamily}\",\n \"icon\": \"priority_high\"\n }\n ]\n },\n {\n \"type\": \"lookupCard\",\n \"title\": \"Selected audit case\",\n \"status\": \"resolved\",\n \"subtitleExpr\": \"${audit.caseId}\",\n \"metaExpr\": \"${audit.title}\",\n \"ctaLabel\": \"Open case\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"approval.audit.case.open\",\n \"payloadExpr\": \"${audit}\"\n },\n \"fields\": [\n {\n \"label\": \"Control family\",\n \"valueExpr\": \"${audit.controlFamily}\"\n },\n {\n \"label\": \"Severity\",\n \"valueExpr\": \"${audit.severity}\"\n }\n ],\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Open evidence packet\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"approval.audit.packet.open\",\n \"payloadExpr\": \"${audit}\"\n }\n }\n ]\n },\n {\n \"type\": \"tabs\",\n \"title\": \"Audit views\",\n \"subtitle\": \"Portable editorial tabs for evidence and policy context.\",\n \"appearance\": \"underline\",\n \"defaultTabId\": \"evidence\",\n \"items\": [\n {\n \"id\": \"evidence\",\n \"label\": \"Evidence\",\n \"icon\": \"inventory_2\",\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": \"Tabs keep audit evidence, policy notes and remediation criteria inside the same RichContentDocument.\"\n }\n ]\n },\n {\n \"id\": \"policy\",\n \"label\": \"Policy\",\n \"icon\": \"policy\",\n \"content\": [\n {\n \"type\": \"keyValueList\",\n \"layout\": \"stacked\",\n \"items\": [\n {\n \"label\": \"Submitter\",\n \"valueExpr\": \"${audit.submitter}\"\n },\n {\n \"label\": \"Control family\",\n \"valueExpr\": \"${audit.controlFamily}\"\n },\n {\n \"label\": \"Remediation rule\",\n \"value\": \"Lock the packet and route to compliance whenever the policy owner is unresolved.\"\n }\n ]\n }\n ]\n }\n ]\n },\n {\n \"type\": \"relatedRecord\",\n \"title\": \"Compliance owner\",\n \"subtitleExpr\": \"${owner.name}\",\n \"relationLabel\": \"Audit lead\",\n \"metaExpr\": \"${owner.department}\",\n \"ctaLabel\": \"Open owner\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"approval.audit.owner.open\",\n \"payloadExpr\": \"${owner}\"\n },\n \"fields\": [\n {\n \"label\": \"Control area\",\n \"value\": \"Finance / delegation\",\n \"hint\": \"Resolved from the current audit assignment context.\"\n }\n ],\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Assign reviewer\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"approval.audit.owner.assignReviewer\",\n \"payloadExpr\": \"${audit}\"\n }\n }\n ]\n },\n {\n \"type\": \"ctaGroup\",\n \"title\": \"Audit actions\",\n \"subtitle\": \"Governed audit and remediation outcomes\",\n \"message\": \"Use semantic audit actions instead of host-authored compliance button bars.\",\n \"layout\": \"split\",\n \"actions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Lock packet\",\n \"icon\": \"lock\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"approval.audit.packet.lock\",\n \"payloadExpr\": \"${audit}\"\n }\n },\n {\n \"type\": \"actionButton\",\n \"label\": \"Request remediation\",\n \"icon\": \"assignment_late\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"approval.audit.remediation.request\",\n \"payloadExpr\": \"${audit}\"\n }\n }\n ]\n },\n {\n \"type\": \"actionCard\",\n \"title\": \"Escalate compliance review\",\n \"subtitleExpr\": \"${audit.caseId}\",\n \"message\": \"Use actionCard when the approval host needs a governed audit escalation flow.\",\n \"metaExpr\": \"${audit.status}\",\n \"ctaLabel\": \"Escalate audit\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"approval.audit.escalate\",\n \"payloadExpr\": \"${audit}\"\n },\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Open evidence packet\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"approval.audit.packet.open\",\n \"payloadExpr\": \"${audit}\"\n }\n }\n ]\n }\n ]\n }\n }\n }\n }\n ]\n }\n}\n",
2933
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.approval-audit-workbench.json",
2946
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.approval-audit-workbench.json",
2934
2947
  "contentHash": "d9d04173eb96355dbfbd523db42c4a8cb0f9d29ac11ffbfb946b8c87431b21d9",
2935
2948
  "sourceKind": "component_definition",
2936
2949
  "sourceId": "praxis-dynamic-page",
@@ -2940,7 +2953,7 @@
2940
2953
  "chunkIndex": 5,
2941
2954
  "chunkKind": "recipe",
2942
2955
  "content": "{\n \"_comment\": \"Praxis Dynamic Page recipe for an approval decision workbench using portable rich-content blocks instead of host-authored markup.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"approval-decision-workbench\",\n \"status\": \"public-example\",\n \"useWhen\": \"Create an approval workbench with governed metrics, approver context and semantic decision actions.\",\n \"examplePrompts\": [\n \"create an approval decision workbench\",\n \"show a governed approval rich content surface\",\n \"generate an approval page with approver summary and decisions\"\n ]\n },\n \"platformValue\": {\n \"canonicalRuntime\": \"@praxisui/rich-content owns the portable approval surface.\",\n \"hostMediation\": \"The host mediates approve, request changes and escalate actions through actionId contracts.\",\n \"publicExamples\": \"praxis-ui-landing-page can expose the same approval workbench without serializing runtime helpers.\",\n \"agentCorpus\": \"This recipe keeps approval guidance, approver summaries and decision actions inside RichContentDocument so agents can reuse the same semantic surface across hosts.\"\n },\n \"authoringGuidance\": [\n \"Use definition.id \\\"praxis-rich-content\\\".\",\n \"Model approval KPIs with statGroup instead of custom host KPI cards.\",\n \"Model the assigned approver with relatedRecord when the record is already resolved in host context.\",\n \"Use ctaGroup and actionCard for governed decision actions; keep handlers out of the document.\",\n \"Do not serialize hostCapabilities in the page JSON; the host injects runtime mediation only while rendering.\"\n ],\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 1,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"approvalDecisionWorkbench\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"approval\",\n \"title\": \"Approval decision workbench\",\n \"subtitle\": \"Portable rich-content surface for governed approval flows\"\n },\n \"definition\": {\n \"id\": \"praxis-rich-content\",\n \"bindingOrder\": [\"document\", \"context\", \"layout\", \"rootClassName\"],\n \"inputs\": {\n \"layout\": \"block\",\n \"rootClassName\": \"approval-decision-workbench\",\n \"context\": {\n \"approval\": {\n \"requestId\": \"APR-2048\",\n \"title\": \"Payroll reconciliation package\",\n \"status\": \"Needs review\",\n \"amount\": \"$182.5k\",\n \"sla\": \"18h\",\n \"lane\": \"Finance / P0\",\n \"risk\": \"High\",\n \"submitter\": \"Ayla Hayes\"\n },\n \"approver\": {\n \"name\": \"Mira Drax\",\n \"department\": \"Finance Governance\"\n }\n },\n \"document\": {\n \"kind\": \"praxis.rich-content\",\n \"version\": \"1.0.0\",\n \"nodes\": [\n {\n \"type\": \"callout\",\n \"tone\": \"warning\",\n \"icon\": \"gavel\",\n \"titleExpr\": \"${approval.title}\",\n \"message\": \"Use a portable approval surface when the host must expose governed decision actions without inventing approval-specific templates.\"\n },\n {\n \"type\": \"statGroup\",\n \"title\": \"Approval signals\",\n \"subtitle\": \"Canonical KPI block for the decision workbench\",\n \"layout\": \"grid\",\n \"items\": [\n {\n \"label\": \"Amount\",\n \"valueExpr\": \"${approval.amount}\",\n \"captionExpr\": \"${approval.requestId}\",\n \"icon\": \"payments\"\n },\n {\n \"label\": \"SLA\",\n \"valueExpr\": \"${approval.sla}\",\n \"captionExpr\": \"${approval.status}\",\n \"icon\": \"schedule\"\n },\n {\n \"label\": \"Risk\",\n \"valueExpr\": \"${approval.risk}\",\n \"captionExpr\": \"${approval.lane}\",\n \"icon\": \"priority_high\"\n }\n ]\n },\n {\n \"type\": \"tabs\",\n \"title\": \"Approval views\",\n \"subtitle\": \"Portable editorial tabs for approval context and rationale.\",\n \"appearance\": \"underline\",\n \"defaultTabId\": \"summary\",\n \"items\": [\n {\n \"id\": \"summary\",\n \"label\": \"Summary\",\n \"icon\": \"dashboard\",\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": \"Tabs keep approval rationale and operational notes inside the same RichContentDocument.\"\n }\n ]\n },\n {\n \"id\": \"rationale\",\n \"label\": \"Rationale\",\n \"icon\": \"rule\",\n \"content\": [\n {\n \"type\": \"keyValueList\",\n \"layout\": \"stacked\",\n \"items\": [\n {\n \"label\": \"Submitter\",\n \"valueExpr\": \"${approval.submitter}\"\n },\n {\n \"label\": \"Approval lane\",\n \"valueExpr\": \"${approval.lane}\"\n },\n {\n \"label\": \"Portability rule\",\n \"value\": \"Keep domain semantics in the rich-content document; keep execution in the host.\"\n }\n ]\n }\n ]\n }\n ]\n },\n {\n \"type\": \"relatedRecord\",\n \"title\": \"Assigned approver\",\n \"subtitleExpr\": \"${approver.name}\",\n \"relationLabel\": \"Current owner\",\n \"metaExpr\": \"${approver.department}\",\n \"ctaLabel\": \"Open approver\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"approval.owner.open\",\n \"payloadExpr\": \"${approver}\"\n },\n \"fields\": [\n {\n \"label\": \"Approval lane\",\n \"valueExpr\": \"${approval.lane}\",\n \"hint\": \"Resolved from the current approval assignment context.\"\n }\n ],\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Reassign\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"approval.owner.reassign\",\n \"payloadExpr\": \"${approval}\"\n }\n }\n ]\n },\n {\n \"type\": \"ctaGroup\",\n \"title\": \"Decision\",\n \"subtitle\": \"Governed approval outcomes\",\n \"message\": \"Use semantic decision actions instead of host-authored approval button bars.\",\n \"layout\": \"split\",\n \"actions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Approve\",\n \"icon\": \"check_circle\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"approval.decision.approve\",\n \"payloadExpr\": \"${approval}\"\n }\n },\n {\n \"type\": \"actionButton\",\n \"label\": \"Request changes\",\n \"icon\": \"edit_note\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"approval.decision.requestChanges\",\n \"payloadExpr\": \"${approval}\"\n }\n }\n ]\n },\n {\n \"type\": \"actionCard\",\n \"title\": \"Inspect approval package\",\n \"subtitleExpr\": \"${approval.requestId}\",\n \"message\": \"Use actionCard when the approval host needs a governed deep-inspection flow.\",\n \"metaExpr\": \"${approval.status}\",\n \"ctaLabel\": \"Inspect package\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"approval.package.inspect\",\n \"payloadExpr\": \"${approval}\"\n },\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Escalate\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"approval.package.escalate\",\n \"payloadExpr\": \"${approval}\"\n }\n }\n ]\n }\n ]\n }\n }\n }\n }\n ]\n }\n}\n",
2943
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.approval-decision-workbench.json",
2956
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.approval-decision-workbench.json",
2944
2957
  "contentHash": "7e301dd7228d3f1a48df2d55c0c9fa6004f7c94e1fc7bc3442be2c71b22e8b32",
2945
2958
  "sourceKind": "component_definition",
2946
2959
  "sourceId": "praxis-dynamic-page",
@@ -2950,7 +2963,7 @@
2950
2963
  "chunkIndex": 6,
2951
2964
  "chunkKind": "recipe",
2952
2965
  "content": "{\n \"_comment\": \"AI recipe: approval delegation exception workbench with portable rich-content blocks and host-mediated actions.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"approval-delegation-exception-workbench\",\n \"status\": \"public-example\",\n \"useWhen\": \"Create an approval delegation exception workbench with substitute coverage signals, selected exception context, policy tabs, delegate context and governed exception actions.\",\n \"examplePrompts\": [\n \"crie um workbench de excecao e delegacao de aprovacoes\",\n \"pagina de continuidade de aprovacao com substituto e acoes governadas\",\n \"approval delegation exception workbench with rich-content\"\n ],\n \"platformValue\": [\n \"Keeps approval exception semantics in a portable praxis.rich-content document instead of host-specific approval markup.\",\n \"Uses lookupCard, relatedRecord, tabs, ctaGroup and actionCard so dynamic pages, dialogs, tabs and AI surfaces can render the same document.\",\n \"Declares actionId contracts for host-mediated execution; no handler, URL or capability snapshot is serialized into the document.\"\n ],\n \"authoringGuidance\": [\n \"Use praxis-rich-content when an approval exception surface needs editorial policy context plus governed action affordances.\",\n \"Model substitute coverage metrics as statGroup, the active exception as lookupCard and the delegate as relatedRecord.\",\n \"Use ctaGroup for primary delegation outcomes and actionCard for escalations that must be mediated by the host.\",\n \"Do not serialize hostCapabilities or arbitrary handlers inside the recipe; hosts resolve capability and execution at runtime.\"\n ]\n },\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 1,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"approvalDelegationExceptionWorkbench\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"rule\",\n \"title\": \"Approval delegation exception workbench\",\n \"subtitle\": \"Portable rich-content surface for substitute approval coverage\"\n },\n \"definition\": {\n \"id\": \"praxis-rich-content\",\n \"bindingOrder\": [\"document\", \"context\", \"layout\", \"rootClassName\"],\n \"inputs\": {\n \"layout\": \"block\",\n \"rootClassName\": \"approval-delegation-exception-workbench\",\n \"context\": {\n \"exception\": {\n \"id\": \"EXC-418\",\n \"title\": \"Unavailable approver coverage\",\n \"state\": \"Delegate nomination pending\",\n \"blockedApprovals\": \"7\",\n \"coverageGaps\": \"3\",\n \"agingRisk\": \"High\",\n \"lane\": \"Procurement approval / substitute required\",\n \"threshold\": \"48h\",\n \"requester\": \"Amanda Rocha\"\n },\n \"delegate\": {\n \"name\": \"Marina Lopes\",\n \"department\": \"Procurement governance\",\n \"scope\": \"Procurement contracts up to BRL 250k\"\n }\n },\n \"document\": {\n \"kind\": \"praxis.rich-content\",\n \"version\": \"1.0.0\",\n \"nodes\": [\n {\n \"type\": \"callout\",\n \"tone\": \"warning\",\n \"icon\": \"rule\",\n \"titleExpr\": \"${exception.title}\",\n \"message\": \"Use a portable approval delegation exception surface when the host must expose substitute coverage and governed approval continuity actions without inventing approval-specific templates.\"\n },\n {\n \"type\": \"statGroup\",\n \"title\": \"Delegation signals\",\n \"subtitle\": \"Canonical KPI block for approval exception coverage surfaces\",\n \"layout\": \"grid\",\n \"items\": [\n {\n \"label\": \"Blocked approvals\",\n \"valueExpr\": \"${exception.blockedApprovals}\",\n \"captionExpr\": \"${exception.state}\",\n \"icon\": \"block\"\n },\n {\n \"label\": \"Coverage gaps\",\n \"valueExpr\": \"${exception.coverageGaps}\",\n \"caption\": \"Policy exceptions\",\n \"icon\": \"rule\"\n },\n {\n \"label\": \"Aging risk\",\n \"valueExpr\": \"${exception.agingRisk}\",\n \"captionExpr\": \"${exception.threshold}\",\n \"icon\": \"priority_high\"\n }\n ]\n },\n {\n \"type\": \"lookupCard\",\n \"title\": \"Selected exception\",\n \"status\": \"resolved\",\n \"subtitleExpr\": \"${exception.id}\",\n \"metaExpr\": \"${exception.title}\",\n \"ctaLabel\": \"Open exception\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"approval.delegation.exception.open\",\n \"payloadExpr\": \"${exception}\"\n },\n \"fields\": [\n {\n \"label\": \"Policy lane\",\n \"valueExpr\": \"${exception.lane}\"\n },\n {\n \"label\": \"Exception state\",\n \"valueExpr\": \"${exception.state}\"\n }\n ],\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Open exception packet\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"approval.delegation.packet.open\",\n \"payloadExpr\": \"${exception}\"\n }\n }\n ]\n },\n {\n \"type\": \"tabs\",\n \"title\": \"Exception views\",\n \"subtitle\": \"Portable editorial tabs for delegation rationale, policy and audit context.\",\n \"appearance\": \"underline\",\n \"defaultTabId\": \"coverage\",\n \"items\": [\n {\n \"id\": \"coverage\",\n \"label\": \"Coverage\",\n \"icon\": \"groups\",\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": \"Keep substitute coverage rationale, approver availability and delegation notes inside the same RichContentDocument.\"\n }\n ]\n },\n {\n \"id\": \"policy\",\n \"label\": \"Policy\",\n \"icon\": \"policy\",\n \"content\": [\n {\n \"type\": \"keyValueList\",\n \"layout\": \"stacked\",\n \"items\": [\n {\n \"label\": \"Requester\",\n \"valueExpr\": \"${exception.requester}\"\n },\n {\n \"label\": \"Delegation rule\",\n \"value\": \"Require a qualified substitute when the primary approver is unavailable and the request age crosses the policy threshold.\"\n },\n {\n \"label\": \"Audit source\",\n \"value\": \"Delegation matrix, approval event history and exception justification.\"\n }\n ]\n }\n ]\n }\n ]\n },\n {\n \"type\": \"relatedRecord\",\n \"title\": \"Proposed delegate\",\n \"relationLabel\": \"Substitute approver\",\n \"subtitleExpr\": \"${delegate.name}\",\n \"metaExpr\": \"${delegate.department}\",\n \"ctaLabel\": \"Open delegate\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"approval.delegation.delegate.open\",\n \"payloadExpr\": \"${delegate}\"\n },\n \"fields\": [\n {\n \"label\": \"Delegation scope\",\n \"valueExpr\": \"${delegate.scope}\",\n \"hint\": \"Resolved from the approval delegation matrix.\"\n }\n ],\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Review delegate fit\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"approval.delegation.delegate.reviewFit\",\n \"payloadExpr\": \"${delegate}\"\n }\n }\n ]\n },\n {\n \"type\": \"ctaGroup\",\n \"title\": \"Delegation actions\",\n \"subtitle\": \"Governed approval exception outcomes\",\n \"message\": \"Use semantic delegation actions instead of host-authored exception button bars.\",\n \"layout\": \"split\",\n \"actions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Approve delegation\",\n \"icon\": \"task_alt\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"approval.delegation.approve\",\n \"payloadExpr\": \"${exception}\"\n }\n },\n {\n \"type\": \"actionButton\",\n \"label\": \"Request alternate delegate\",\n \"icon\": \"sync\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"approval.delegation.requestAlternate\",\n \"payloadExpr\": \"${exception}\"\n }\n }\n ]\n },\n {\n \"type\": \"actionCard\",\n \"title\": \"Escalate delegation exception\",\n \"subtitleExpr\": \"${exception.id}\",\n \"message\": \"Use actionCard when the approval host needs a governed escalation for unresolved delegation coverage gaps.\",\n \"metaExpr\": \"${exception.state}\",\n \"ctaLabel\": \"Escalate exception\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"approval.delegation.exception.escalate\",\n \"payloadExpr\": \"${exception}\"\n },\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Open exception packet\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"approval.delegation.packet.open\",\n \"payloadExpr\": \"${exception}\"\n }\n }\n ]\n }\n ]\n }\n }\n }\n }\n ]\n }\n}\n",
2953
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.approval-delegation-exception-workbench.json",
2966
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.approval-delegation-exception-workbench.json",
2954
2967
  "contentHash": "407ab9ad58e409047881e22ae88e1b6ed823287f4a91c34c96e4e83dd66a2871",
2955
2968
  "sourceKind": "component_definition",
2956
2969
  "sourceId": "praxis-dynamic-page",
@@ -2960,7 +2973,7 @@
2960
2973
  "chunkIndex": 7,
2961
2974
  "chunkKind": "recipe",
2962
2975
  "content": "{\n \"_comment\": \"Praxis Dynamic Page recipe for an approval review workbench using portable rich-content blocks for queue review, evidence tabs and governed escalation actions.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"approval-review-workbench\",\n \"status\": \"public-example\",\n \"useWhen\": \"Create an approval review workbench with queue metrics, selected request context, evidence tabs and governed escalation actions.\",\n \"examplePrompts\": [\n \"create an approval review workbench\",\n \"show a governed approval review rich content surface\",\n \"generate an approval review page with evidence tabs and escalation actions\"\n ]\n },\n \"platformValue\": {\n \"canonicalRuntime\": \"@praxisui/rich-content owns the portable approval review surface.\",\n \"hostMediation\": \"The host mediates open, approve, request evidence and escalate actions through actionId contracts.\",\n \"publicExamples\": \"praxis-ui-landing-page can expose the same approval review workbench without serializing runtime helpers.\",\n \"agentCorpus\": \"This recipe keeps review metrics, selected request context, evidence tabs and escalation actions inside RichContentDocument so agents can reuse the same semantic surface across hosts.\"\n },\n \"authoringGuidance\": [\n \"Use definition.id \\\"praxis-rich-content\\\".\",\n \"Model queue metrics with statGroup instead of custom host dashboard cards.\",\n \"Model the selected approval request with lookupCard when the host already resolved the queue item.\",\n \"Use tabs for summary and evidence instead of host-authored accordion wrappers.\",\n \"Use relatedRecord, ctaGroup and actionCard for governed review and escalation actions; keep handlers out of the document.\",\n \"Do not serialize hostCapabilities in the page JSON; the host injects runtime mediation only while rendering.\"\n ],\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 1,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"approvalReviewWorkbench\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"fact_check\",\n \"title\": \"Approval review workbench\",\n \"subtitle\": \"Portable rich-content surface for governed approval review flows\"\n },\n \"definition\": {\n \"id\": \"praxis-rich-content\",\n \"bindingOrder\": [\"document\", \"context\", \"layout\", \"rootClassName\"],\n \"inputs\": {\n \"layout\": \"block\",\n \"rootClassName\": \"approval-review-workbench\",\n \"context\": {\n \"review\": {\n \"requestId\": \"APR-4096\",\n \"title\": \"Vendor onboarding policy exception\",\n \"status\": \"Escalation candidate\",\n \"pending\": \"12\",\n \"escalations\": \"3\",\n \"risk\": \"High\",\n \"portfolio\": \"Vendor operations\",\n \"reviewWindow\": \"4h\",\n \"submitter\": \"Noemi Vega\"\n },\n \"owner\": {\n \"name\": \"Noah Hart\",\n \"department\": \"Operations governance\"\n }\n },\n \"document\": {\n \"kind\": \"praxis.rich-content\",\n \"version\": \"1.0.0\",\n \"nodes\": [\n {\n \"type\": \"callout\",\n \"tone\": \"warning\",\n \"icon\": \"fact_check\",\n \"titleExpr\": \"${review.title}\",\n \"message\": \"Use a portable approval review surface when the host must expose governed queue review and escalation actions without inventing approval-specific templates.\"\n },\n {\n \"type\": \"statGroup\",\n \"title\": \"Review signals\",\n \"subtitle\": \"Canonical KPI block for approval review surfaces\",\n \"layout\": \"grid\",\n \"items\": [\n {\n \"label\": \"Pending\",\n \"valueExpr\": \"${review.pending}\",\n \"captionExpr\": \"${review.requestId}\",\n \"icon\": \"pending_actions\"\n },\n {\n \"label\": \"Escalations\",\n \"valueExpr\": \"${review.escalations}\",\n \"captionExpr\": \"${review.status}\",\n \"icon\": \"warning\"\n },\n {\n \"label\": \"Review window\",\n \"valueExpr\": \"${review.reviewWindow}\",\n \"captionExpr\": \"${review.risk}\",\n \"icon\": \"schedule\"\n }\n ]\n },\n {\n \"type\": \"lookupCard\",\n \"title\": \"Selected request\",\n \"status\": \"resolved\",\n \"subtitleExpr\": \"${review.requestId}\",\n \"metaExpr\": \"${review.title}\",\n \"ctaLabel\": \"Open request\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"approval.review.open\",\n \"payloadExpr\": \"${review}\"\n },\n \"fields\": [\n {\n \"label\": \"Portfolio\",\n \"valueExpr\": \"${review.portfolio}\"\n },\n {\n \"label\": \"Risk\",\n \"valueExpr\": \"${review.risk}\"\n }\n ],\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Open dossier\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"approval.review.dossier.open\",\n \"payloadExpr\": \"${review}\"\n }\n }\n ]\n },\n {\n \"type\": \"tabs\",\n \"title\": \"Review views\",\n \"subtitle\": \"Portable editorial tabs for approval review context.\",\n \"appearance\": \"underline\",\n \"defaultTabId\": \"summary\",\n \"items\": [\n {\n \"id\": \"summary\",\n \"label\": \"Summary\",\n \"icon\": \"dashboard\",\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": \"Tabs keep approval review rationale, evidence notes and escalation criteria inside the same RichContentDocument.\"\n }\n ]\n },\n {\n \"id\": \"evidence\",\n \"label\": \"Evidence\",\n \"icon\": \"inventory_2\",\n \"content\": [\n {\n \"type\": \"keyValueList\",\n \"layout\": \"stacked\",\n \"items\": [\n {\n \"label\": \"Submitter\",\n \"valueExpr\": \"${review.submitter}\"\n },\n {\n \"label\": \"Portfolio\",\n \"valueExpr\": \"${review.portfolio}\"\n },\n {\n \"label\": \"Escalation rule\",\n \"value\": \"Escalate requests above the policy threshold or unresolved compliance exceptions.\"\n }\n ]\n }\n ]\n }\n ]\n },\n {\n \"type\": \"relatedRecord\",\n \"title\": \"Escalation owner\",\n \"subtitleExpr\": \"${owner.name}\",\n \"relationLabel\": \"Review lead\",\n \"metaExpr\": \"${owner.department}\",\n \"ctaLabel\": \"Open owner\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"approval.review.owner.open\",\n \"payloadExpr\": \"${owner}\"\n },\n \"fields\": [\n {\n \"label\": \"Coverage\",\n \"value\": \"Vendor onboarding / P1\",\n \"hint\": \"Resolved from the current review assignment context.\"\n }\n ],\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Reassign\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"approval.review.owner.reassign\",\n \"payloadExpr\": \"${review}\"\n }\n }\n ]\n },\n {\n \"type\": \"ctaGroup\",\n \"title\": \"Review actions\",\n \"subtitle\": \"Governed approval review outcomes\",\n \"message\": \"Use semantic review actions instead of host-authored approval queue button bars.\",\n \"layout\": \"split\",\n \"actions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Approve review\",\n \"icon\": \"check_circle\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"approval.review.approve\",\n \"payloadExpr\": \"${review}\"\n }\n },\n {\n \"type\": \"actionButton\",\n \"label\": \"Request evidence\",\n \"icon\": \"fact_check\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"approval.review.requestEvidence\",\n \"payloadExpr\": \"${review}\"\n }\n }\n ]\n },\n {\n \"type\": \"actionCard\",\n \"title\": \"Escalate approval case\",\n \"subtitleExpr\": \"${review.requestId}\",\n \"message\": \"Use actionCard when the approval host needs a governed escalation flow.\",\n \"metaExpr\": \"${review.status}\",\n \"ctaLabel\": \"Escalate case\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"approval.review.escalate\",\n \"payloadExpr\": \"${review}\"\n },\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Open dossier\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"approval.review.dossier.open\",\n \"payloadExpr\": \"${review}\"\n }\n }\n ]\n }\n ]\n }\n }\n }\n }\n ]\n }\n}\n",
2963
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.approval-review-workbench.json",
2976
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.approval-review-workbench.json",
2964
2977
  "contentHash": "45e252c13e44b7edb9c829ddf1391ae35bcecd20c835c0489b7544931005df6f",
2965
2978
  "sourceKind": "component_definition",
2966
2979
  "sourceId": "praxis-dynamic-page",
@@ -2970,7 +2983,7 @@
2970
2983
  "chunkIndex": 8,
2971
2984
  "chunkKind": "recipe",
2972
2985
  "content": "{\n \"_comment\": \"Praxis Dynamic Page recipe for an approval SLA triage workbench using portable rich-content blocks for breach signals, queue ownership and governed triage actions.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"approval-sla-triage-workbench\",\n \"status\": \"public-example\",\n \"useWhen\": \"Create an approval SLA or queue triage workbench with breach signals, queue ownership and governed triage actions.\",\n \"examplePrompts\": [\n \"create an approval sla triage workbench\",\n \"show a governed approval queue triage rich content surface\",\n \"generate an approval page with breach signals and queue triage actions\"\n ]\n },\n \"platformValue\": {\n \"canonicalRuntime\": \"@praxisui/rich-content owns the portable approval SLA triage surface.\",\n \"hostMediation\": \"The host mediates open, rebalance, owner handoff and escalation actions through actionId contracts.\",\n \"publicExamples\": \"praxis-ui-landing-page can expose the same approval SLA triage workbench without serializing runtime helpers.\",\n \"agentCorpus\": \"This recipe keeps breach metrics, selected queue case context, SLA policy tabs and triage actions inside RichContentDocument so agents can reuse the same semantic surface across hosts.\"\n },\n \"authoringGuidance\": [\n \"Use definition.id \\\"praxis-rich-content\\\".\",\n \"Model breach metrics with statGroup instead of custom host queue cards.\",\n \"Model the selected queue case with lookupCard when the host already resolved the SLA triage item.\",\n \"Use tabs for summary and policy instead of host-authored accordion wrappers.\",\n \"Use relatedRecord, ctaGroup and actionCard for governed triage and escalation actions; keep handlers out of the document.\",\n \"Do not serialize hostCapabilities in the page JSON; the host injects runtime mediation only while rendering.\"\n ],\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 1,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"approvalSlaTriageWorkbench\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"timer\",\n \"title\": \"Approval SLA triage workbench\",\n \"subtitle\": \"Portable rich-content surface for governed approval queue triage\"\n },\n \"definition\": {\n \"id\": \"praxis-rich-content\",\n \"bindingOrder\": [\"document\", \"context\", \"layout\", \"rootClassName\"],\n \"inputs\": {\n \"layout\": \"block\",\n \"rootClassName\": \"approval-sla-triage-workbench\",\n \"context\": {\n \"triage\": {\n \"caseId\": \"SLA-221\",\n \"title\": \"Procurement contract escalation\",\n \"status\": \"Breach in progress\",\n \"breaches\": \"5\",\n \"p1Queue\": \"11\",\n \"medianAge\": \"9h\",\n \"priority\": \"P1\",\n \"queue\": \"Procurement approvals\",\n \"submitter\": \"Amanda Rocha\"\n },\n \"owner\": {\n \"name\": \"Helena Costa\",\n \"department\": \"Approval operations\"\n }\n },\n \"document\": {\n \"kind\": \"praxis.rich-content\",\n \"version\": \"1.0.0\",\n \"nodes\": [\n {\n \"type\": \"callout\",\n \"tone\": \"warning\",\n \"icon\": \"timer\",\n \"titleExpr\": \"${triage.title}\",\n \"message\": \"Use a portable approval SLA triage surface when the host must expose governed breach intervention and queue triage actions without inventing approval-specific templates.\"\n },\n {\n \"type\": \"statGroup\",\n \"title\": \"Triage signals\",\n \"subtitle\": \"Canonical KPI block for approval SLA triage surfaces\",\n \"layout\": \"grid\",\n \"items\": [\n {\n \"label\": \"Breaches\",\n \"valueExpr\": \"${triage.breaches}\",\n \"captionExpr\": \"${triage.status}\",\n \"icon\": \"timer_off\"\n },\n {\n \"label\": \"P1 queue\",\n \"valueExpr\": \"${triage.p1Queue}\",\n \"captionExpr\": \"${triage.queue}\",\n \"icon\": \"priority_high\"\n },\n {\n \"label\": \"Median age\",\n \"valueExpr\": \"${triage.medianAge}\",\n \"captionExpr\": \"${triage.priority}\",\n \"icon\": \"schedule\"\n }\n ]\n },\n {\n \"type\": \"lookupCard\",\n \"title\": \"Selected queue case\",\n \"status\": \"resolved\",\n \"subtitleExpr\": \"${triage.caseId}\",\n \"metaExpr\": \"${triage.title}\",\n \"ctaLabel\": \"Open case\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"approval.sla.case.open\",\n \"payloadExpr\": \"${triage}\"\n },\n \"fields\": [\n {\n \"label\": \"Queue\",\n \"valueExpr\": \"${triage.queue}\"\n },\n {\n \"label\": \"Priority\",\n \"valueExpr\": \"${triage.priority}\"\n }\n ],\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Open queue packet\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"approval.sla.packet.open\",\n \"payloadExpr\": \"${triage}\"\n }\n }\n ]\n },\n {\n \"type\": \"tabs\",\n \"title\": \"Triage views\",\n \"subtitle\": \"Portable editorial tabs for queue summary and SLA policy context.\",\n \"appearance\": \"underline\",\n \"defaultTabId\": \"summary\",\n \"items\": [\n {\n \"id\": \"summary\",\n \"label\": \"Summary\",\n \"icon\": \"dashboard\",\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": \"Keep queue rationale, breach context and reassignment notes inside the same RichContentDocument.\"\n }\n ]\n },\n {\n \"id\": \"policy\",\n \"label\": \"Policy\",\n \"icon\": \"policy\",\n \"content\": [\n {\n \"type\": \"keyValueList\",\n \"layout\": \"stacked\",\n \"items\": [\n {\n \"label\": \"Submitter\",\n \"valueExpr\": \"${triage.submitter}\"\n },\n {\n \"label\": \"Triage rule\",\n \"value\": \"Escalate any P1 request above the SLA threshold or any queue with missing owner coverage.\"\n },\n {\n \"label\": \"Evidence source\",\n \"value\": \"SLA board snapshot, owner rota and approval event history.\"\n }\n ]\n }\n ]\n }\n ]\n },\n {\n \"type\": \"relatedRecord\",\n \"title\": \"Queue owner\",\n \"subtitleExpr\": \"${owner.name}\",\n \"relationLabel\": \"Triage lead\",\n \"metaExpr\": \"${owner.department}\",\n \"ctaLabel\": \"Open owner\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"approval.sla.owner.open\",\n \"payloadExpr\": \"${owner}\"\n },\n \"fields\": [\n {\n \"label\": \"Coverage\",\n \"value\": \"Procurement / P1 / EMEA\",\n \"hint\": \"Resolved from the queue triage assignment.\"\n }\n ],\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Rebalance queue\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"approval.sla.queue.rebalance\",\n \"payloadExpr\": \"${triage}\"\n }\n }\n ]\n },\n {\n \"type\": \"ctaGroup\",\n \"title\": \"Triage actions\",\n \"subtitle\": \"Governed SLA triage outcomes\",\n \"message\": \"Use semantic triage actions instead of host-authored SLA queue button bars.\",\n \"layout\": \"split\",\n \"actions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Start triage\",\n \"icon\": \"task_alt\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"approval.sla.triage.start\",\n \"payloadExpr\": \"${triage}\"\n }\n },\n {\n \"type\": \"actionButton\",\n \"label\": \"Request owner update\",\n \"icon\": \"sync\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"approval.sla.owner.requestUpdate\",\n \"payloadExpr\": \"${triage}\"\n }\n }\n ]\n },\n {\n \"type\": \"actionCard\",\n \"title\": \"Escalate SLA breach\",\n \"subtitleExpr\": \"${triage.caseId}\",\n \"message\": \"Use actionCard when the approval host needs a governed escalation flow for unresolved SLA breaches.\",\n \"metaExpr\": \"${triage.status}\",\n \"ctaLabel\": \"Escalate breach\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"approval.sla.escalate\",\n \"payloadExpr\": \"${triage}\"\n },\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Open queue packet\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"approval.sla.packet.open\",\n \"payloadExpr\": \"${triage}\"\n }\n }\n ]\n }\n ]\n }\n }\n }\n }\n ]\n }\n}\n",
2973
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.approval-sla-triage-workbench.json",
2986
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.approval-sla-triage-workbench.json",
2974
2987
  "contentHash": "490c42c44ec5534d678ba76ce3e081e796a0c16fb0d0230459ea284e080cc4ce",
2975
2988
  "sourceKind": "component_definition",
2976
2989
  "sourceId": "praxis-dynamic-page",
@@ -2980,7 +2993,7 @@
2980
2993
  "chunkIndex": 9,
2981
2994
  "chunkKind": "recipe",
2982
2995
  "content": "{\n \"_comment\": \"Template base para Praxis Dynamic Page (praxis-dynamic-page) com um widget principal.\",\n \"_comment2\": \"resourcePath deve ser o path base do recurso (sem /filter).\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"base\",\n \"useWhen\": \"Create a dynamic page with a single widget.\",\n \"examplePrompts\": [\n \"create a simple page with a table\",\n \"add a dynamic page with one widget\"\n ]\n },\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 2,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"mainTable\",\n \"definition\": {\n \"id\": \"praxis-table\",\n \"bindingOrder\": [\"config\", \"resourcePath\"],\n \"inputs\": {\n \"resourcePath\": \"{{resourcePath}}\",\n \"tableId\": \"{{resourceKey}}-table\",\n \"config\": {\n \"toolbar\": { \"visible\": true, \"title\": \"{{resourceLabel}}\" }\n }\n },\n \"outputs\": { \"rowClick\": \"emit\" }\n }\n }\n ]\n }\n}\n",
2983
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.base.json",
2996
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.base.json",
2984
2997
  "contentHash": "c1b474ef6a703d28251bc42b987a1860f14d66b9c5d23b0e47f402847b52032f",
2985
2998
  "sourceKind": "component_definition",
2986
2999
  "sourceId": "praxis-dynamic-page",
@@ -2990,7 +3003,7 @@
2990
3003
  "chunkIndex": 10,
2991
3004
  "chunkKind": "recipe",
2992
3005
  "content": "{\n \"_comment\": \"Template de pagina com CRUD (Praxis Dynamic Page), usando acoes canonicas inferidas no metadata do CRUD.\",\n \"_comment2\": \"resourcePath deve ser o path base do recurso (sem /filter).\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"crud\",\n \"useWhen\": \"Create a dynamic page with a CRUD widget.\",\n \"examplePrompts\": [\n \"pagina com crud\",\n \"crie um crud completo\",\n \"tela de cadastro completa\"\n ]\n },\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 2,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"mainCrud\",\n \"definition\": {\n \"id\": \"praxis-crud\",\n \"bindingOrder\": [\"metadata\"],\n \"inputs\": {\n \"crudId\": \"{{resourceKey}}-crud\",\n \"metadata\": {\n \"component\": \"praxis-crud\",\n \"resource\": {\n \"path\": \"{{resourcePath}}\",\n \"idField\": \"{{idField}}\",\n \"endpointKey\": \"{{resourceKey}}\"\n },\n \"table\": {\n \"toolbar\": { \"visible\": true }\n },\n \"actions\": [\n { \"action\": \"create\", \"openMode\": \"modal\" }\n ]\n }\n },\n \"outputs\": { \"afterSave\": \"emit\", \"afterDelete\": \"emit\" }\n }\n }\n ]\n }\n}\n",
2993
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.crud.json",
3006
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.crud.json",
2994
3007
  "contentHash": "b1381463e38f7b2dce38d32ce6c776f0691b338a15a69abcbeb64dd6f0294066",
2995
3008
  "sourceKind": "component_definition",
2996
3009
  "sourceId": "praxis-dynamic-page",
@@ -3000,7 +3013,7 @@
3000
3013
  "chunkIndex": 11,
3001
3014
  "chunkKind": "recipe",
3002
3015
  "content": "{\n \"_comment\": \"Praxis Dynamic Page recipe that demonstrates List actions opening governed Dialog surfaces through structured surface.open global actions.\",\n \"_comment2\": \"Use this when an agent needs a copyable end-to-end contract for modal surfaces: host-provided Praxis Dialog, PraxisSurfaceHostComponent, List actions, Chart, remote List and Rich Text Block.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"dialog-surface-lab\",\n \"useWhen\": \"Create a dynamic page where list actions open modal surfaces with runtime-resolved widgets.\",\n \"examplePrompts\": [\n \"page with buttons that open modal surfaces\",\n \"show a chart in a Praxis Dialog from a list action\",\n \"create a dynamic page that opens remote list and rich text surfaces through surface.open\"\n ],\n \"requires\": [\n \"@praxisui/core\",\n \"@praxisui/list\",\n \"@praxisui/dialog\",\n \"@praxisui/charts\",\n \"@praxisui/rich-content\",\n \"providePraxisDialogGlobalActions()\",\n \"providePraxisSurfaceGlobalActions()\",\n \"GLOBAL_SURFACE_SERVICE\",\n \"surface.open\"\n ]\n },\n \"hostIntegration\": {\n \"providers\": [\n \"providePraxisDialogGlobalActions()\",\n \"providePraxisSurfaceGlobalActions()\"\n ],\n \"styleImports\": [\n \"@angular/cdk/overlay-prebuilt.css\"\n ],\n \"notes\": [\n \"The page payload stays pure JSON. The host owns Dialog registration and global action providers.\",\n \"surface.open resolves the supplied widget through PraxisSurfaceHostComponent inside the dialog body.\",\n \"Use globalAction.payload to pass the complete surface payload from the selected item.\"\n ]\n },\n \"api\": {\n \"origin\": \"https://praxis-api-quickstart.onrender.com\",\n \"baseUrl\": \"https://praxis-api-quickstart.onrender.com/api\",\n \"schemasBaseUrl\": \"https://praxis-api-quickstart.onrender.com/schemas\",\n \"resourcePath\": \"operations/missoes\",\n \"resourceKey\": \"operations.missoes\"\n },\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 1,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"dialogSurfaceLaunchers\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"open_in_new\",\n \"title\": \"Dialog surface launcher\",\n \"subtitle\": \"Actions open modal surfaces with widgets resolved at runtime\"\n },\n \"definition\": {\n \"id\": \"praxis-list\",\n \"bindingOrder\": [\n \"listId\",\n \"config\"\n ],\n \"inputs\": {\n \"listId\": \"dialog-surface-launchers\",\n \"componentInstanceId\": \"dynamic-page-showcase\",\n \"config\": {\n \"id\": \"dialog-surface-launchers-config\",\n \"dataSource\": {\n \"data\": [\n {\n \"id\": \"mission-analytics\",\n \"icon\": \"bar_chart\",\n \"title\": \"Mission analytics modal\",\n \"subtitle\": \"Open a local chart surface without changing the page layout\",\n \"surfaceKind\": \"Chart\",\n \"priority\": \"High\",\n \"surfacePayload\": {\n \"presentation\": \"modal\",\n \"title\": \"Mission analytics\",\n \"icon\": \"bar_chart\",\n \"subtitle\": \"Chart widget rendered inside Praxis Dialog\",\n \"size\": {\n \"width\": \"780px\",\n \"maxWidth\": \"92vw\",\n \"height\": \"620px\",\n \"maxHeight\": \"86vh\"\n },\n \"widget\": {\n \"id\": \"praxis-chart\",\n \"bindingOrder\": [\n \"config\"\n ],\n \"inputs\": {\n \"config\": {\n \"id\": \"dialog-mission-status-chart\",\n \"type\": \"donut\",\n \"title\": \"Mission status mix\",\n \"subtitle\": \"Local chart payload opened by surface.open\",\n \"sizing\": {\n \"height\": 360,\n \"minHeight\": 320\n },\n \"dataSource\": {\n \"kind\": \"local\",\n \"items\": [\n {\n \"status\": \"EM_ANDAMENTO\",\n \"missions\": 11\n },\n {\n \"status\": \"PLANEJADA\",\n \"missions\": 7\n },\n {\n \"status\": \"CONCLUIDA\",\n \"missions\": 18\n },\n {\n \"status\": \"SUSPENSA\",\n \"missions\": 3\n }\n ]\n },\n \"axes\": {\n \"x\": {\n \"field\": \"status\",\n \"type\": \"category\",\n \"label\": \"Status\"\n },\n \"y\": {\n \"field\": \"missions\",\n \"type\": \"value\",\n \"label\": \"Missions\"\n }\n },\n \"series\": [\n {\n \"id\": \"missions\",\n \"name\": \"Missions\",\n \"categoryField\": \"status\",\n \"metric\": {\n \"field\": \"missions\",\n \"aggregation\": \"sum\"\n }\n }\n ],\n \"theme\": {\n \"palette\": [\n \"#0f766e\",\n \"#2563eb\",\n \"#16a34a\",\n \"#dc2626\"\n ],\n \"legend\": {\n \"visible\": true,\n \"position\": \"bottom\"\n },\n \"tooltip\": {\n \"enabled\": true,\n \"trigger\": \"item\"\n }\n }\n }\n }\n }\n }\n },\n {\n \"id\": \"mission-participants\",\n \"icon\": \"groups\",\n \"title\": \"Participant roster modal\",\n \"subtitle\": \"Open a remote List surface backed by the quickstart filter endpoint\",\n \"surfaceKind\": \"Remote list\",\n \"priority\": \"Medium\",\n \"surfacePayload\": {\n \"presentation\": \"modal\",\n \"title\": \"Mission participant roster\",\n \"icon\": \"groups\",\n \"subtitle\": \"Remote list widget rendered inside Praxis Dialog\",\n \"size\": {\n \"width\": \"920px\",\n \"maxWidth\": \"94vw\",\n \"height\": \"660px\",\n \"maxHeight\": \"86vh\"\n },\n \"widget\": {\n \"id\": \"praxis-list\",\n \"bindingOrder\": [\n \"listId\",\n \"config\"\n ],\n \"inputs\": {\n \"listId\": \"dialog-mission-participants-list\",\n \"config\": {\n \"id\": \"dialog-mission-participants-list-config\",\n \"dataSource\": {\n \"resourcePath\": \"operations/missao-participantes\",\n \"sort\": [\n \"id,asc\"\n ]\n },\n \"layout\": {\n \"variant\": \"list\",\n \"density\": \"compact\",\n \"lines\": 3,\n \"dividers\": \"between\",\n \"groupBy\": \"missaoTitulo\",\n \"stickySectionHeader\": true,\n \"pageSize\": 6,\n \"rowLayout\": {\n \"type\": \"grid\",\n \"columns\": [\n {\n \"slot\": \"leading\",\n \"width\": \"44px\",\n \"align\": \"center\"\n },\n {\n \"slot\": \"primary\",\n \"width\": \"minmax(160px, 1fr)\"\n },\n {\n \"slot\": \"secondary\",\n \"width\": \"minmax(180px, 1.1fr)\"\n },\n {\n \"slot\": \"meta\",\n \"width\": \"120px\",\n \"align\": \"start\"\n },\n {\n \"slot\": \"trailing\",\n \"width\": \"110px\",\n \"align\": \"end\"\n }\n ],\n \"gap\": \"12px\",\n \"align\": \"center\"\n }\n },\n \"selection\": {\n \"mode\": \"single\",\n \"compareBy\": \"id\",\n \"return\": \"id\"\n },\n \"templating\": {\n \"leading\": {\n \"type\": \"icon\",\n \"expr\": \"groups\"\n },\n \"primary\": {\n \"type\": \"text\",\n \"expr\": \"${item.funcionarioNome}\"\n },\n \"secondary\": {\n \"type\": \"text\",\n \"expr\": \"${item.missaoTitulo}\"\n },\n \"meta\": {\n \"type\": \"chip\",\n \"expr\": \"${item.papel}\",\n \"variant\": \"outlined\"\n },\n \"trailing\": {\n \"type\": \"chip\",\n \"expr\": \"${item.resultado}\",\n \"variant\": \"filled\"\n },\n \"sectionHeader\": {\n \"type\": \"text\",\n \"expr\": \"${key}\"\n }\n },\n \"ui\": {\n \"showSearch\": false,\n \"showSort\": true,\n \"sortOptions\": [\n {\n \"label\": \"ID\",\n \"value\": \"id,asc\"\n },\n {\n \"label\": \"Role\",\n \"value\": \"papel,asc\"\n }\n ],\n \"showRange\": true\n }\n }\n }\n }\n }\n },\n {\n \"id\": \"policy-note\",\n \"icon\": \"policy\",\n \"title\": \"Operational guidance modal\",\n \"subtitle\": \"Open a rich text surface with policy and agent instructions\",\n \"surfaceKind\": \"Rich text\",\n \"priority\": \"Medium\",\n \"surfacePayload\": {\n \"presentation\": \"modal\",\n \"title\": \"Operational guidance\",\n \"icon\": \"policy\",\n \"subtitle\": \"Rich Text Block rendered inside Praxis Dialog\",\n \"size\": {\n \"width\": \"720px\",\n \"maxWidth\": \"90vw\"\n },\n \"widget\": {\n \"id\": \"widget:rich-text-block\",\n \"inputs\": {\n \"title\": \"Surface action guidance\",\n \"content\": \"Use surface.open when an action should reveal a governed runtime surface without forcing the base page to reserve permanent layout space. The payload remains pure JSON and the host owns the dialog provider.\",\n \"variant\": \"emphasis\"\n }\n }\n }\n }\n ],\n \"sort\": [\n \"priority,asc\"\n ]\n },\n \"layout\": {\n \"variant\": \"cards\",\n \"density\": \"comfortable\",\n \"lines\": 3,\n \"dividers\": \"none\",\n \"pageSize\": 6\n },\n \"skin\": {\n \"type\": \"outline\",\n \"radius\": \"8px\",\n \"border\": \"1px solid rgba(37, 99, 235, 0.28)\"\n },\n \"selection\": {\n \"mode\": \"single\",\n \"compareBy\": \"id\",\n \"return\": \"id\"\n },\n \"templating\": {\n \"leading\": {\n \"type\": \"icon\",\n \"expr\": \"${item.icon}\"\n },\n \"primary\": {\n \"type\": \"text\",\n \"expr\": \"${item.title}\"\n },\n \"secondary\": {\n \"type\": \"text\",\n \"expr\": \"${item.subtitle}\"\n },\n \"trailing\": {\n \"type\": \"chip\",\n \"expr\": \"${item.surfaceKind}\",\n \"variant\": \"outlined\"\n },\n \"features\": [\n {\n \"type\": \"chip\",\n \"expr\": \"${item.priority}\",\n \"variant\": \"filled\"\n },\n {\n \"type\": \"chip\",\n \"expr\": \"surface.open\",\n \"variant\": \"outlined\"\n }\n ],\n \"featuresMode\": \"labels-only\"\n },\n \"actions\": [\n {\n \"id\": \"open-surface-dialog\",\n \"icon\": \"open_in_new\",\n \"label\": \"Open surface\",\n \"kind\": \"button\",\n \"buttonVariant\": \"stroked\",\n \"globalAction\": {\n \"actionId\": \"surface.open\",\n \"payload\": \"${item.surfacePayload}\"\n },\n \"emitLocal\": false,\n \"showLoading\": true,\n \"placement\": \"trailing\"\n }\n ],\n \"ui\": {\n \"showSearch\": false,\n \"showSort\": false,\n \"showRange\": false\n },\n \"a11y\": {\n \"ariaLabel\": \"Dialog surface launcher list\"\n }\n }\n },\n \"outputs\": {\n \"itemClick\": \"emit\",\n \"selectionChange\": \"emit\"\n }\n }\n }\n ]\n }\n}\n",
3003
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.dialog-surface-lab.json",
3016
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.dialog-surface-lab.json",
3004
3017
  "contentHash": "147fb6d551f99991c267c096dc2bb146b0bb697a4540d31fae63e1fc01616a7b",
3005
3018
  "sourceKind": "component_definition",
3006
3019
  "sourceId": "praxis-dynamic-page",
@@ -3010,7 +3023,7 @@
3010
3023
  "chunkIndex": 12,
3011
3024
  "chunkKind": "recipe",
3012
3025
  "content": "{\n \"_comment\": \"Recipe para agentes criarem uma Praxis Dynamic Page que demonstra o catalogo de controles do Dynamic Fields.\",\n \"_comment2\": \"Use quando a meta for mostrar muitos controlType package-owned em um formulario local/transient.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"dynamic-fields-catalog\",\n \"status\": \"public-example\",\n \"useWhen\": \"Create a copyable Dynamic Fields control catalog inside a Dynamic Page.\",\n \"examplePrompts\": [\n \"crie um catalogo de campos do praxis dynamic fields\",\n \"mostre input, email, cpf, telefone, currency, date range, select, chips, upload e avatar\",\n \"gere um recipe de dynamic page com muitos control types\"\n ]\n },\n \"platformValue\": {\n \"canonicalContract\": \"@praxisui/dynamic-fields owns runtime control resolution and editorial metadata for package-owned controls.\",\n \"referenceApi\": \"praxis-api-quickstart can still provide option endpoints for asyncSelect examples.\",\n \"angularRuntime\": \"@praxisui/dynamic-form renders package-owned Dynamic Fields controls from fieldMetadata.\",\n \"publicExamples\": \"praxis-ui-landing-page exposes the JSON envelope, runtime preview and coverage map.\",\n \"agentCorpus\": \"This recipe teaches exact controlType names and grouping patterns for LLM-generated forms.\"\n },\n \"operationalEvidence\": {\n \"baseUrl\": \"https://praxis-api-quickstart.onrender.com\",\n \"safeFirstIds\": [\n \"filtered-schema-response-funcionarios\",\n \"cargos-options-filter\"\n ],\n \"httpExamples\": [\n \"praxisui-http-examples/http/metadata/filtered_schema_response_funcionarios.http\",\n \"praxisui-http-examples/http/resources/cargos_options_filter.http\"\n ],\n \"canonicalFiles\": [\n \"praxis-ui-angular/projects/praxis-dynamic-fields/src/lib/catalog/dynamic-fields-playground.catalog.ts\",\n \"praxis-ui-angular/examples/ai-recipes/praxis-dynamic-form.fields.json\",\n \"praxis-ui-angular/examples/ai-recipes/praxis-dynamic-form.form-config.json\"\n ]\n },\n \"authoringGuidance\": [\n \"Use package-owned controlType names from the Dynamic Fields catalog.\",\n \"Use local transient state when the form is a capability catalog rather than a persisted backend DTO.\",\n \"Group controls by family so agents can copy smaller sections into real forms.\",\n \"Use fieldMetadata for labels, validators, masks, ranges, options and control-specific settings.\",\n \"Use asyncSelect only with a canonical option endpoint or a documented host-provided option source.\",\n \"Do not add new controlType aliases in app examples; add them only through the canonical Dynamic Fields chain.\"\n ],\n \"teaches\": [\n \"dynamic-form.fieldMetadata\",\n \"dynamic-form.sections\",\n \"dynamic-fields.input\",\n \"dynamic-fields.email\",\n \"dynamic-fields.password\",\n \"dynamic-fields.url\",\n \"dynamic-fields.phone\",\n \"dynamic-fields.cpfCnpjInput\",\n \"dynamic-fields.textarea\",\n \"dynamic-fields.currency\",\n \"dynamic-fields.slider\",\n \"dynamic-fields.rating\",\n \"dynamic-fields.date\",\n \"dynamic-fields.dateRange\",\n \"dynamic-fields.timePicker\",\n \"dynamic-fields.select\",\n \"dynamic-fields.asyncSelect\",\n \"dynamic-fields.multiSelect\",\n \"dynamic-fields.radio\",\n \"dynamic-fields.toggle\",\n \"dynamic-fields.checkbox\",\n \"dynamic-fields.chipInput\",\n \"dynamic-fields.colorPicker\",\n \"dynamic-fields.avatar\",\n \"dynamic-fields.upload\"\n ],\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 1,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"dynamicFieldsCatalogForm\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"widgets\",\n \"title\": \"Dynamic Fields catalog\",\n \"subtitle\": \"Package-owned control recipes grouped by family\"\n },\n \"definition\": {\n \"id\": \"praxis-dynamic-form\",\n \"bindingOrder\": [\n \"config\",\n \"formId\",\n \"initialValue\"\n ],\n \"inputs\": {\n \"formId\": \"dynamic-fields-control-catalog\",\n \"mode\": \"edit\",\n \"initialValue\": {\n \"fullName\": \"Ayla Hayes\",\n \"emailAddress\": \"ayla.hayes@blackmesa.com\",\n \"password\": \"Praxis-demo-2026\",\n \"profileUrl\": \"https://praxisplatform.dev\",\n \"phoneNumber\": \"+55 11 97100047\",\n \"documentNumber\": \"99000000047\",\n \"biography\": \"Operational profile used to demonstrate text, mask and validation controls.\",\n \"salaryTarget\": 28500,\n \"allocationPercent\": 72,\n \"readinessRating\": 4,\n \"admissionDate\": \"2022-03-05\",\n \"availabilityWindow\": {\n \"start\": \"2026-04-01\",\n \"end\": \"2026-04-30\"\n },\n \"briefingTime\": \"09:30\",\n \"department\": \"RD\",\n \"cargoLookup\": 2,\n \"skills\": [\n \"ANGULAR\",\n \"SECURITY\"\n ],\n \"workMode\": \"HYBRID\",\n \"activeAssignment\": true,\n \"tags\": [\n \"metadata\",\n \"runtime\",\n \"agent-ready\"\n ],\n \"brandColor\": \"#1263b4\",\n \"avatarUrl\": \"https://api.dicebear.com/7.x/adventurer/png?seed=ayla\"\n },\n \"config\": {\n \"metadata\": {\n \"name\": \"Dynamic Fields control catalog\",\n \"version\": \"1.0.0\"\n },\n \"sections\": [\n {\n \"id\": \"text-family\",\n \"title\": \"Text and identity\",\n \"description\": \"Text, credentials, contact and Brazilian document controls.\",\n \"appearance\": \"outlined\",\n \"rows\": [\n {\n \"id\": \"text-row-1\",\n \"columns\": [\n {\n \"id\": \"text-left\",\n \"span\": {\n \"md\": 6,\n \"lg\": 6\n },\n \"fields\": [\n \"fullName\",\n \"emailAddress\",\n \"password\",\n \"profileUrl\"\n ]\n },\n {\n \"id\": \"text-right\",\n \"span\": {\n \"md\": 6,\n \"lg\": 6\n },\n \"fields\": [\n \"phoneNumber\",\n \"documentNumber\",\n \"biography\"\n ]\n }\n ]\n }\n ]\n },\n {\n \"id\": \"numbers-dates\",\n \"title\": \"Numbers and dates\",\n \"description\": \"Numeric, currency, slider, rating, date range and time controls.\",\n \"appearance\": \"outlined\",\n \"rows\": [\n {\n \"id\": \"numbers-row-1\",\n \"columns\": [\n {\n \"id\": \"numbers-left\",\n \"span\": {\n \"md\": 6,\n \"lg\": 6\n },\n \"fields\": [\n \"salaryTarget\",\n \"allocationPercent\",\n \"readinessRating\"\n ]\n },\n {\n \"id\": \"dates-right\",\n \"span\": {\n \"md\": 6,\n \"lg\": 6\n },\n \"fields\": [\n \"admissionDate\",\n \"availabilityWindow\",\n \"briefingTime\"\n ]\n }\n ]\n }\n ]\n },\n {\n \"id\": \"selection-family\",\n \"title\": \"Selection\",\n \"description\": \"Select, async select, multi select, radio and toggle controls.\",\n \"appearance\": \"outlined\",\n \"rows\": [\n {\n \"id\": \"selection-row-1\",\n \"columns\": [\n {\n \"id\": \"selection-left\",\n \"span\": {\n \"md\": 6,\n \"lg\": 6\n },\n \"fields\": [\n \"department\",\n \"cargoLookup\",\n \"skills\"\n ]\n },\n {\n \"id\": \"selection-right\",\n \"span\": {\n \"md\": 6,\n \"lg\": 6\n },\n \"fields\": [\n \"workMode\",\n \"activeAssignment\",\n \"acceptTerms\"\n ]\n }\n ]\n }\n ]\n },\n {\n \"id\": \"visual-family\",\n \"title\": \"Visual and attachments\",\n \"description\": \"Chips, color, avatar and upload controls.\",\n \"appearance\": \"outlined\",\n \"rows\": [\n {\n \"id\": \"visual-row-1\",\n \"columns\": [\n {\n \"id\": \"visual-left\",\n \"span\": {\n \"md\": 6,\n \"lg\": 6\n },\n \"fields\": [\n \"tags\",\n \"brandColor\"\n ]\n },\n {\n \"id\": \"visual-right\",\n \"span\": {\n \"md\": 6,\n \"lg\": 6\n },\n \"fields\": [\n \"avatarUrl\",\n \"attachments\"\n ]\n }\n ]\n }\n ]\n }\n ],\n \"fieldMetadata\": [\n {\n \"name\": \"fullName\",\n \"label\": \"Full name\",\n \"controlType\": \"input\",\n \"validators\": {\n \"required\": true,\n \"maxLength\": 160\n }\n },\n {\n \"name\": \"emailAddress\",\n \"label\": \"Email\",\n \"controlType\": \"email\",\n \"validators\": {\n \"required\": true,\n \"email\": true\n }\n },\n {\n \"name\": \"password\",\n \"label\": \"Password\",\n \"controlType\": \"password\",\n \"validators\": {\n \"minLength\": 8\n }\n },\n {\n \"name\": \"profileUrl\",\n \"label\": \"Profile URL\",\n \"controlType\": \"url\",\n \"placeholder\": \"https://example.com/profile\"\n },\n {\n \"name\": \"phoneNumber\",\n \"label\": \"Phone\",\n \"controlType\": \"phone\",\n \"maskType\": \"phone\"\n },\n {\n \"name\": \"documentNumber\",\n \"label\": \"CPF\",\n \"controlType\": \"cpfCnpjInput\",\n \"maskType\": \"cpf\",\n \"unmaskOnSubmit\": true\n },\n {\n \"name\": \"biography\",\n \"label\": \"Biography\",\n \"controlType\": \"textarea\",\n \"rows\": 4,\n \"validators\": {\n \"maxLength\": 500\n }\n },\n {\n \"name\": \"salaryTarget\",\n \"label\": \"Salary target\",\n \"controlType\": \"currency\",\n \"currencyCode\": \"BRL\",\n \"locale\": \"pt-BR\",\n \"validators\": {\n \"min\": 0\n }\n },\n {\n \"name\": \"allocationPercent\",\n \"label\": \"Allocation\",\n \"controlType\": \"slider\",\n \"min\": 0,\n \"max\": 100,\n \"step\": 5\n },\n {\n \"name\": \"readinessRating\",\n \"label\": \"Readiness\",\n \"controlType\": \"rating\",\n \"max\": 5\n },\n {\n \"name\": \"admissionDate\",\n \"label\": \"Admission date\",\n \"controlType\": \"date\"\n },\n {\n \"name\": \"availabilityWindow\",\n \"label\": \"Availability window\",\n \"controlType\": \"dateRange\"\n },\n {\n \"name\": \"briefingTime\",\n \"label\": \"Briefing time\",\n \"controlType\": \"timePicker\"\n },\n {\n \"name\": \"department\",\n \"label\": \"Department\",\n \"controlType\": \"select\",\n \"options\": [\n {\n \"label\": \"Research\",\n \"value\": \"RD\"\n },\n {\n \"label\": \"Operations\",\n \"value\": \"OPS\"\n },\n {\n \"label\": \"Security\",\n \"value\": \"SEC\"\n }\n ]\n },\n {\n \"name\": \"cargoLookup\",\n \"label\": \"Cargo lookup\",\n \"controlType\": \"asyncSelect\",\n \"endpoint\": \"/api/human-resources/cargos/options/filter\",\n \"displayField\": \"label\",\n \"valueField\": \"id\"\n },\n {\n \"name\": \"skills\",\n \"label\": \"Skills\",\n \"controlType\": \"multiSelect\",\n \"options\": [\n {\n \"label\": \"Angular\",\n \"value\": \"ANGULAR\"\n },\n {\n \"label\": \"Security\",\n \"value\": \"SECURITY\"\n },\n {\n \"label\": \"Analytics\",\n \"value\": \"ANALYTICS\"\n }\n ]\n },\n {\n \"name\": \"workMode\",\n \"label\": \"Work mode\",\n \"controlType\": \"radio\",\n \"options\": [\n {\n \"label\": \"Remote\",\n \"value\": \"REMOTE\"\n },\n {\n \"label\": \"Hybrid\",\n \"value\": \"HYBRID\"\n },\n {\n \"label\": \"Field\",\n \"value\": \"FIELD\"\n }\n ]\n },\n {\n \"name\": \"activeAssignment\",\n \"label\": \"Active assignment\",\n \"controlType\": \"toggle\"\n },\n {\n \"name\": \"acceptTerms\",\n \"label\": \"Accept operating terms\",\n \"controlType\": \"checkbox\",\n \"validators\": {\n \"requiredChecked\": true\n }\n },\n {\n \"name\": \"tags\",\n \"label\": \"Tags\",\n \"controlType\": \"chipInput\"\n },\n {\n \"name\": \"brandColor\",\n \"label\": \"Brand color\",\n \"controlType\": \"colorPicker\",\n \"format\": \"hex\"\n },\n {\n \"name\": \"avatarUrl\",\n \"label\": \"Avatar\",\n \"controlType\": \"avatar\",\n \"imageField\": \"avatarUrl\"\n },\n {\n \"name\": \"attachments\",\n \"label\": \"Attachments\",\n \"controlType\": \"upload\",\n \"multiple\": true,\n \"accept\": \".pdf,.png,.jpg\"\n }\n ],\n \"actions\": {\n \"submit\": {\n \"id\": \"copy-field-catalog\",\n \"label\": \"Copy control recipe\",\n \"icon\": \"content_copy\",\n \"visible\": true,\n \"type\": \"submit\"\n },\n \"cancel\": {\n \"id\": \"clear-field-catalog\",\n \"label\": \"Clear\",\n \"visible\": true,\n \"type\": \"button\"\n },\n \"reset\": {\n \"id\": \"reset-field-catalog\",\n \"label\": \"Reset\",\n \"visible\": true,\n \"type\": \"reset\"\n },\n \"position\": \"right\",\n \"placement\": \"afterSections\",\n \"spacing\": \"normal\"\n }\n }\n }\n }\n }\n ]\n }\n}\n",
3013
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.dynamic-fields-catalog.json",
3026
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.dynamic-fields-catalog.json",
3014
3027
  "contentHash": "c6a20ddb36b08434179ee9a6e7294bb1defcd824ae411611edd0005996deb379",
3015
3028
  "sourceKind": "component_definition",
3016
3029
  "sourceId": "praxis-dynamic-page",
@@ -3020,7 +3033,7 @@
3020
3033
  "chunkIndex": 13,
3021
3034
  "chunkKind": "recipe",
3022
3035
  "content": "{\n \"_comment\": \"Recipe para agentes criarem uma Praxis Dynamic Page com praxis-dynamic-form renderizando Editable Collection / Array Field.\",\n \"_comment2\": \"Use quando a meta for demonstrar x-ui.array, itemSchema, itemSchemaRef e validacao de colecao vindos de uma action schema do backend.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"editable-collection-form\",\n \"status\": \"public-example\",\n \"useWhen\": \"Create a metadata-driven partial form with an editable array of nested object items.\",\n \"examplePrompts\": [\n \"crie um formulario com editable collection no praxis dynamic form\",\n \"mostre x-ui.array com itemSchema e validacao uniqueBy\",\n \"gere uma dynamic page para planejar equipe de missao com array field\"\n ]\n },\n \"platformValue\": {\n \"canonicalContract\": \"praxis-metadata-starter publishes x-ui.array through the filtered request schema; praxis-api-quickstart owns the mission team-plan resource action.\",\n \"referenceApi\": \"praxis-api-quickstart exposes PATCH /api/operations/missoes/{id}/team-plan and funcionario option lookup.\",\n \"angularRuntime\": \"@praxisui/dynamic-form builds a FormArray and @praxisui/dynamic-fields resolves controlType array to pdx-editable-collection.\",\n \"publicExamples\": \"praxis-ui-landing-page exposes a local mirror of the backend action contract, the JSON envelope, runtime preview and coverage map.\",\n \"agentCorpus\": \"This recipe teaches agents how to model nested repeatable object collections without inventing custom widgets.\"\n },\n \"operationalEvidence\": {\n \"baseUrl\": \"https://praxis-api-quickstart.onrender.com\",\n \"safeFirstIds\": [\n \"filtered-schema-request-missao-team-plan\",\n \"funcionarios-options-filter\"\n ],\n \"pendingHttpIds\": [\n \"missao-team-plan-schema\",\n \"missao-team-plan-patch\"\n ],\n \"canonicalFiles\": [\n \"praxis-api-quickstart/src/main/java/com/example/praxis/apiquickstart/operations/controller/MissaoController.java\",\n \"praxis-api-quickstart/src/main/java/com/example/praxis/apiquickstart/operations/dto/PlanejarEquipeMissaoDTO.java\",\n \"praxis-api-quickstart/src/main/java/com/example/praxis/apiquickstart/operations/dto/PlanejarEquipeMissaoParticipanteDTO.java\",\n \"praxis-ui-angular/projects/praxis-dynamic-fields/src/lib/components/editable-collection/editable-collection.component.ts\",\n \"praxis-ui-angular/projects/praxis-core/src/lib/services/dynamic-form.service.ts\"\n ]\n },\n \"authoringGuidance\": [\n \"Use controlType array for editable object collections.\",\n \"Keep itemSchemaRef aligned to the backend component schema when the backend publishes one.\",\n \"Use array.itemSchema.fields when the runtime needs the nested field definitions inline.\",\n \"Use array.itemIdentityField for persisted item identity and deleteMode removeFromPayload for patch payloads.\",\n \"Use array.operations to govern add, edit and remove affordances.\",\n \"Use array.collectionValidation.uniqueBy and exactlyOne for collection-level business rules.\",\n \"Use asyncSelect only with a canonical option endpoint or a documented host-provided option source.\"\n ],\n \"teaches\": [\n \"dynamic-form.FormArray\",\n \"dynamic-form.fieldMetadata\",\n \"dynamic-fields.array\",\n \"pdx-editable-collection\",\n \"array.itemSchemaRef\",\n \"array.itemSchema.fields\",\n \"array.itemIdentityField\",\n \"array.operations\",\n \"array.collectionValidation.uniqueBy\",\n \"array.collectionValidation.exactlyOne\",\n \"resource-action.partial-form\"\n ],\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 1,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"missionTeamEditableCollectionForm\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"groups\",\n \"title\": \"Mission team plan\",\n \"subtitle\": \"Editable Collection from the quickstart team-plan action\"\n },\n \"definition\": {\n \"id\": \"praxis-dynamic-form\",\n \"bindingOrder\": [\n \"config\",\n \"formId\",\n \"initialValue\",\n \"submitUrl\",\n \"submitMethod\"\n ],\n \"inputs\": {\n \"formId\": \"operations-missoes-team-plan\",\n \"mode\": \"edit\",\n \"submitUrl\": \"/api/operations/missoes/1/team-plan\",\n \"submitMethod\": \"patch\",\n \"initialValue\": {\n \"participantes\": [\n {\n \"id\": 2,\n \"funcionarioId\": 2,\n \"funcionarioNome\": \"Ayla Hayes\",\n \"papel\": \"LIDER\",\n \"ordem\": 1,\n \"principal\": true\n },\n {\n \"id\": 5,\n \"funcionarioId\": 5,\n \"funcionarioNome\": \"Tomas Hayes\",\n \"papel\": \"TECNICO\",\n \"ordem\": 2,\n \"principal\": false\n }\n ]\n },\n \"config\": {\n \"metadata\": {\n \"name\": \"Mission team planning request\",\n \"version\": \"1.0.0\"\n },\n \"sections\": [\n {\n \"id\": \"team-plan\",\n \"title\": \"Team plan\",\n \"description\": \"Edit the mission participant collection published by the quickstart team-plan action schema.\",\n \"appearance\": \"outlined\",\n \"rows\": [\n {\n \"id\": \"team-plan-row\",\n \"columns\": [\n {\n \"id\": \"team-plan-main\",\n \"span\": {\n \"md\": 12,\n \"lg\": 12\n },\n \"fields\": [\n \"participantes\"\n ]\n }\n ]\n }\n ]\n }\n ],\n \"fieldMetadata\": [\n {\n \"name\": \"participantes\",\n \"label\": \"Participantes\",\n \"controlType\": \"array\",\n \"type\": \"array\",\n \"required\": true,\n \"array\": {\n \"itemType\": \"object\",\n \"mode\": \"cards\",\n \"itemSchemaRef\": \"#/components/schemas/PlanejarEquipeMissaoParticipanteDTO\",\n \"itemIdentityField\": \"id\",\n \"minItems\": 1,\n \"maxItems\": 12,\n \"addLabel\": \"Adicionar participante\",\n \"emptyState\": \"Nenhum participante planejado\",\n \"itemTitleTemplate\": \"{{funcionarioNome}} - {{papel}}\",\n \"deleteMode\": \"removeFromPayload\",\n \"operations\": {\n \"add\": true,\n \"edit\": true,\n \"remove\": true\n },\n \"collectionValidation\": {\n \"uniqueBy\": [\n \"funcionarioId\"\n ],\n \"exactlyOne\": {\n \"field\": \"principal\",\n \"value\": true,\n \"message\": \"Defina exatamente um participante principal.\"\n }\n },\n \"itemSchema\": {\n \"fields\": [\n {\n \"name\": \"funcionarioId\",\n \"label\": \"Funcionario\",\n \"controlType\": \"asyncSelect\",\n \"required\": true,\n \"endpoint\": \"/api/human-resources/funcionarios/options/filter\",\n \"displayField\": \"label\",\n \"valueField\": \"id\"\n },\n {\n \"name\": \"funcionarioNome\",\n \"label\": \"Nome\",\n \"controlType\": \"input\",\n \"readOnly\": true\n },\n {\n \"name\": \"papel\",\n \"label\": \"Papel\",\n \"controlType\": \"select\",\n \"required\": true,\n \"options\": [\n {\n \"label\": \"Lider\",\n \"value\": \"LIDER\"\n },\n {\n \"label\": \"Tecnico\",\n \"value\": \"TECNICO\"\n },\n {\n \"label\": \"Analista\",\n \"value\": \"ANALISTA\"\n },\n {\n \"label\": \"Piloto\",\n \"value\": \"PILOTO\"\n },\n {\n \"label\": \"Medico\",\n \"value\": \"MEDICO\"\n }\n ]\n },\n {\n \"name\": \"ordem\",\n \"label\": \"Ordem\",\n \"controlType\": \"numericTextBox\",\n \"readOnly\": true\n },\n {\n \"name\": \"principal\",\n \"label\": \"Principal\",\n \"controlType\": \"toggle\"\n }\n ]\n }\n }\n }\n ],\n \"actions\": {\n \"submit\": {\n \"id\": \"submit-team-plan\",\n \"label\": \"Submit team plan\",\n \"icon\": \"task_alt\",\n \"visible\": true,\n \"type\": \"submit\"\n },\n \"reset\": {\n \"id\": \"reset-team-plan\",\n \"label\": \"Reset\",\n \"visible\": true,\n \"type\": \"reset\"\n },\n \"position\": \"right\",\n \"placement\": \"afterSections\",\n \"spacing\": \"normal\"\n }\n }\n }\n }\n }\n ]\n }\n}\n",
3023
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.editable-collection-form.json",
3036
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.editable-collection-form.json",
3024
3037
  "contentHash": "f5a9d8d5dbbcc0c1183b1f537272a6f3a2f939c51504e62a8f7f516f28421390",
3025
3038
  "sourceKind": "component_definition",
3026
3039
  "sourceId": "praxis-dynamic-page",
@@ -3030,7 +3043,7 @@
3030
3043
  "chunkIndex": 14,
3031
3044
  "chunkKind": "recipe",
3032
3045
  "content": "{\n \"_comment\": \"Praxis Dynamic Page recipe for an HR compensation review workbench using portable rich-content blocks for budget signals, reward partner context and governed compensation actions.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"employee-compensation-review-workbench\",\n \"status\": \"public-example\",\n \"useWhen\": \"Create an HR compensation review workbench with budget signals, reward partner context and governed compensation actions.\",\n \"examplePrompts\": [\n \"create an HR compensation review workbench\",\n \"show a governed compensation review rich content surface\",\n \"generate a people operations page with compensation signals and budget actions\"\n ]\n },\n \"platformValue\": {\n \"canonicalRuntime\": \"@praxisui/rich-content owns the portable HR compensation review surface.\",\n \"hostMediation\": \"The host mediates employee, reward partner, budget and escalation flows through actionId contracts.\",\n \"publicExamples\": \"praxis-ui-landing-page can expose the same compensation review workbench without serializing runtime helpers.\",\n \"agentCorpus\": \"This recipe keeps compensation signals, selected employee context, reward partner ownership and governed compensation actions inside RichContentDocument so agents can reuse the same semantic surface across hosts.\"\n },\n \"authoringGuidance\": [\n \"Use definition.id \\\"praxis-rich-content\\\".\",\n \"Model compensation metrics with statGroup instead of host-authored budget cards.\",\n \"Model the selected employee with lookupCard when the host already resolved the compensation context.\",\n \"Use tabs for summary and budget views instead of host-authored compensation sections.\",\n \"Use relatedRecord, ctaGroup and actionCard for governed compensation and escalation actions; keep handlers out of the document.\",\n \"Do not serialize hostCapabilities in the page JSON; the host injects runtime mediation only while rendering.\"\n ],\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 1,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"employeeCompensationReviewWorkbench\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"payments\",\n \"title\": \"Compensation review workbench\",\n \"subtitle\": \"Portable rich-content surface for governed HR compensation operations\"\n },\n \"definition\": {\n \"id\": \"praxis-rich-content\",\n \"bindingOrder\": [\"document\", \"context\", \"layout\", \"rootClassName\"],\n \"inputs\": {\n \"layout\": \"block\",\n \"rootClassName\": \"employee-compensation-review-workbench\",\n \"context\": {\n \"employee\": {\n \"id\": \"EMP-440\",\n \"name\": \"Daniela Freitas\",\n \"role\": \"Staff Product Manager\",\n \"department\": \"Platform strategy\",\n \"cycle\": \"Q2\",\n \"budget\": \"18%\",\n \"proposedIncrease\": \"8%\",\n \"compaRatio\": \"0.97\",\n \"marketSignal\": \"Midpoint to +5%\",\n \"reviewWindow\": \"2d\"\n },\n \"partner\": {\n \"name\": \"Nadia Costa\",\n \"department\": \"Rewards and mobility\",\n \"budgetLane\": \"Reward council / compensation\"\n }\n },\n \"document\": {\n \"kind\": \"praxis.rich-content\",\n \"version\": \"1.0.0\",\n \"nodes\": [\n {\n \"type\": \"callout\",\n \"tone\": \"info\",\n \"icon\": \"payments\",\n \"titleExpr\": \"${employee.name}\",\n \"message\": \"Use a portable HR compensation review surface when the host must expose budget signals, market context and governed reward actions without inventing people-ops templates.\"\n },\n {\n \"type\": \"statGroup\",\n \"title\": \"Compensation signals\",\n \"subtitle\": \"Canonical KPI block for compensation review workbenches\",\n \"layout\": \"grid\",\n \"items\": [\n {\n \"label\": \"Cycle\",\n \"valueExpr\": \"${employee.cycle}\",\n \"captionExpr\": \"${employee.department}\",\n \"icon\": \"event\"\n },\n {\n \"label\": \"Budget\",\n \"valueExpr\": \"${employee.budget}\",\n \"captionExpr\": \"${employee.reviewWindow}\",\n \"icon\": \"payments\"\n },\n {\n \"label\": \"Increase\",\n \"valueExpr\": \"${employee.proposedIncrease}\",\n \"captionExpr\": \"${employee.marketSignal}\",\n \"icon\": \"trending_up\"\n }\n ]\n },\n {\n \"type\": \"lookupCard\",\n \"title\": \"Selected employee\",\n \"status\": \"resolved\",\n \"subtitleExpr\": \"${employee.name}\",\n \"metaExpr\": \"${employee.role}\",\n \"ctaLabel\": \"Open employee\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"hr.comp.employee.open\",\n \"payloadExpr\": \"${employee}\"\n },\n \"fields\": [\n {\n \"label\": \"Proposed increase\",\n \"valueExpr\": \"${employee.proposedIncrease}\"\n },\n {\n \"label\": \"Compa-ratio\",\n \"valueExpr\": \"${employee.compaRatio}\"\n }\n ],\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Open dossier\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"hr.comp.dossier.open\",\n \"payloadExpr\": \"${employee}\"\n }\n }\n ]\n },\n {\n \"type\": \"tabs\",\n \"title\": \"Compensation views\",\n \"subtitle\": \"Portable editorial tabs for compensation summary and budget context.\",\n \"appearance\": \"underline\",\n \"defaultTabId\": \"summary\",\n \"items\": [\n {\n \"id\": \"summary\",\n \"label\": \"Summary\",\n \"icon\": \"dashboard\",\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": \"Tabs keep reward notes, market context and proposal rationale inside the same RichContentDocument.\"\n }\n ]\n },\n {\n \"id\": \"budget\",\n \"label\": \"Budget\",\n \"icon\": \"account_balance_wallet\",\n \"content\": [\n {\n \"type\": \"keyValueList\",\n \"layout\": \"stacked\",\n \"items\": [\n {\n \"label\": \"Budget rule\",\n \"value\": \"Escalate any compensation proposal above the approved budget lane or any exception requiring leadership approval.\"\n },\n {\n \"label\": \"Evidence source\",\n \"valueExpr\": \"${employee.reviewWindow}\"\n },\n {\n \"label\": \"Portability rule\",\n \"value\": \"Keep compensation semantics in the rich-content document; keep execution in the host.\"\n }\n ]\n }\n ]\n }\n ]\n },\n {\n \"type\": \"relatedRecord\",\n \"title\": \"Reward partner\",\n \"subtitleExpr\": \"${partner.name}\",\n \"relationLabel\": \"Partner\",\n \"metaExpr\": \"${partner.department}\",\n \"ctaLabel\": \"Open partner\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"hr.comp.partner.open\",\n \"payloadExpr\": \"${partner}\"\n },\n \"fields\": [\n {\n \"label\": \"Budget lane\",\n \"valueExpr\": \"${partner.budgetLane}\",\n \"hint\": \"Resolved from the current compensation review assignment.\"\n }\n ],\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Schedule comp review\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"hr.comp.partner.scheduleReview\",\n \"payloadExpr\": \"${employee}\"\n }\n }\n ]\n },\n {\n \"type\": \"ctaGroup\",\n \"title\": \"Compensation actions\",\n \"subtitle\": \"Governed HR compensation outcomes\",\n \"message\": \"Use semantic compensation actions instead of host-authored proposal button bars.\",\n \"layout\": \"split\",\n \"actions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Confirm comp proposal\",\n \"icon\": \"task_alt\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"hr.comp.confirm\",\n \"payloadExpr\": \"${employee}\"\n }\n },\n {\n \"type\": \"actionButton\",\n \"label\": \"Request budget follow-up\",\n \"icon\": \"flag\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"hr.comp.budget.followUp\",\n \"payloadExpr\": \"${employee}\"\n }\n }\n ]\n },\n {\n \"type\": \"actionCard\",\n \"title\": \"Escalate compensation case\",\n \"subtitleExpr\": \"${employee.id}\",\n \"message\": \"Use actionCard when the HR host needs a governed reward escalation or compensation exception flow.\",\n \"metaExpr\": \"${employee.role}\",\n \"ctaLabel\": \"Escalate compensation\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"hr.comp.escalate\",\n \"payloadExpr\": \"${employee}\"\n },\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Open dossier\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"hr.comp.dossier.open\",\n \"payloadExpr\": \"${employee}\"\n }\n }\n ]\n }\n ]\n }\n }\n }\n }\n ]\n }\n}\n",
3033
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.employee-compensation-review-workbench.json",
3046
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.employee-compensation-review-workbench.json",
3034
3047
  "contentHash": "9a01acc1b41267a382a4d765f12178f4725941a4c3aa7e9c88cc7bf1ae2bfd73",
3035
3048
  "sourceKind": "component_definition",
3036
3049
  "sourceId": "praxis-dynamic-page",
@@ -3040,7 +3053,7 @@
3040
3053
  "chunkIndex": 15,
3041
3054
  "chunkKind": "recipe",
3042
3055
  "content": "{\n \"_comment\": \"Praxis Dynamic Page recipe for an HR employee insight workbench using portable rich-content blocks instead of host-authored templates.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"employee-insight-workbench\",\n \"status\": \"public-example\",\n \"useWhen\": \"Create an HR workbench with employee signals, reporting context and governed follow-up actions.\",\n \"examplePrompts\": [\n \"create an employee insight workbench\",\n \"show a governed HR rich content surface\",\n \"generate a people operations page with employee context and follow-up actions\"\n ]\n },\n \"platformValue\": {\n \"canonicalRuntime\": \"@praxisui/rich-content owns the portable HR surface.\",\n \"hostMediation\": \"The host mediates employee lookup, manager navigation and review flows through actionId contracts.\",\n \"publicExamples\": \"praxis-ui-landing-page can expose the same HR workbench without serializing runtime helpers.\",\n \"agentCorpus\": \"This recipe keeps employee insights, manager context and governed actions inside RichContentDocument so agents can reuse the same semantic surface across hosts.\"\n },\n \"authoringGuidance\": [\n \"Use definition.id \\\"praxis-rich-content\\\".\",\n \"Model employee KPIs with statGroup instead of custom host summary cards.\",\n \"Model the selected employee with lookupCard when the record is resolved by host context.\",\n \"Model the reporting manager with relatedRecord instead of host-authored relationship wrappers.\",\n \"Use ctaGroup and actionCard for governed HR actions; keep handlers out of the document.\",\n \"Do not serialize hostCapabilities in the page JSON; the host injects runtime mediation only while rendering.\"\n ],\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 1,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"employeeInsightWorkbench\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"badge\",\n \"title\": \"Employee insight workbench\",\n \"subtitle\": \"Portable rich-content surface for people operations follow-up\"\n },\n \"definition\": {\n \"id\": \"praxis-rich-content\",\n \"bindingOrder\": [\"document\", \"context\", \"layout\", \"rootClassName\"],\n \"inputs\": {\n \"layout\": \"block\",\n \"rootClassName\": \"employee-insight-workbench\",\n \"context\": {\n \"employee\": {\n \"id\": \"EMP-2048\",\n \"name\": \"Carla Mendes\",\n \"role\": \"Senior HRBP\",\n \"department\": \"People Operations\",\n \"tenure\": \"4.2y\",\n \"performance\": \"Exceeds\",\n \"engagement\": \"82\",\n \"nextMilestone\": \"Promotion calibration\",\n \"reviewWindow\": \"6d\"\n },\n \"manager\": {\n \"name\": \"Ana Silva\",\n \"department\": \"People leadership\"\n }\n },\n \"document\": {\n \"kind\": \"praxis.rich-content\",\n \"version\": \"1.0.0\",\n \"nodes\": [\n {\n \"type\": \"callout\",\n \"tone\": \"info\",\n \"icon\": \"groups\",\n \"titleExpr\": \"${employee.name}\",\n \"message\": \"Use a portable HR surface when the host must expose employee insights and governed follow-up actions without inventing people-ops templates.\"\n },\n {\n \"type\": \"statGroup\",\n \"title\": \"Workforce signals\",\n \"subtitle\": \"Canonical KPI block for employee insight surfaces\",\n \"layout\": \"grid\",\n \"items\": [\n {\n \"label\": \"Tenure\",\n \"valueExpr\": \"${employee.tenure}\",\n \"captionExpr\": \"${employee.department}\",\n \"icon\": \"schedule\"\n },\n {\n \"label\": \"Performance\",\n \"valueExpr\": \"${employee.performance}\",\n \"captionExpr\": \"${employee.nextMilestone}\",\n \"icon\": \"military_tech\"\n },\n {\n \"label\": \"Engagement\",\n \"valueExpr\": \"${employee.engagement}\",\n \"caption\": \"Pulse score\",\n \"icon\": \"favorite\"\n }\n ]\n },\n {\n \"type\": \"lookupCard\",\n \"title\": \"Selected employee\",\n \"status\": \"resolved\",\n \"subtitleExpr\": \"${employee.name}\",\n \"metaExpr\": \"${employee.role}\",\n \"ctaLabel\": \"Open employee\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"employee.lookup.open\",\n \"payloadExpr\": \"${employee}\"\n },\n \"fields\": [\n {\n \"label\": \"Department\",\n \"valueExpr\": \"${employee.department}\"\n },\n {\n \"label\": \"Next milestone\",\n \"valueExpr\": \"${employee.nextMilestone}\"\n }\n ],\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Open dossier\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"employee.dossier.open\",\n \"payloadExpr\": \"${employee}\"\n }\n }\n ]\n },\n {\n \"type\": \"tabs\",\n \"title\": \"Employee views\",\n \"subtitle\": \"Portable editorial tabs for people operations context.\",\n \"appearance\": \"underline\",\n \"defaultTabId\": \"overview\",\n \"items\": [\n {\n \"id\": \"overview\",\n \"label\": \"Overview\",\n \"icon\": \"dashboard\",\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": \"Tabs keep coaching notes, org context and review readiness inside the same RichContentDocument.\"\n }\n ]\n },\n {\n \"id\": \"review\",\n \"label\": \"Review\",\n \"icon\": \"assignment\",\n \"content\": [\n {\n \"type\": \"keyValueList\",\n \"layout\": \"stacked\",\n \"items\": [\n {\n \"label\": \"Review window\",\n \"valueExpr\": \"${employee.reviewWindow}\"\n },\n {\n \"label\": \"Next milestone\",\n \"valueExpr\": \"${employee.nextMilestone}\"\n },\n {\n \"label\": \"Portability rule\",\n \"value\": \"Keep domain semantics in the rich-content document; keep execution in the host.\"\n }\n ]\n }\n ]\n }\n ]\n },\n {\n \"type\": \"relatedRecord\",\n \"title\": \"Reporting manager\",\n \"subtitleExpr\": \"${manager.name}\",\n \"relationLabel\": \"Manager\",\n \"metaExpr\": \"${manager.department}\",\n \"ctaLabel\": \"Open manager\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"employee.manager.open\",\n \"payloadExpr\": \"${manager}\"\n },\n \"fields\": [\n {\n \"label\": \"Team\",\n \"valueExpr\": \"${employee.department}\",\n \"hint\": \"Resolved from the reporting chain.\"\n }\n ],\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Plan 1:1\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"employee.manager.planOneOnOne\",\n \"payloadExpr\": \"${employee}\"\n }\n }\n ]\n },\n {\n \"type\": \"ctaGroup\",\n \"title\": \"Guided actions\",\n \"subtitle\": \"Governed HR follow-up actions\",\n \"message\": \"Use semantic action clusters instead of host-authored employee button bars.\",\n \"layout\": \"split\",\n \"actions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Start review\",\n \"icon\": \"fact_check\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"employee.review.start\",\n \"payloadExpr\": \"${employee}\"\n }\n },\n {\n \"type\": \"actionButton\",\n \"label\": \"Plan promotion\",\n \"icon\": \"trending_up\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"employee.promotion.plan\",\n \"payloadExpr\": \"${employee}\"\n }\n }\n ]\n },\n {\n \"type\": \"actionCard\",\n \"title\": \"Open employee dossier\",\n \"subtitleExpr\": \"${employee.id}\",\n \"message\": \"Use actionCard when the HR host needs a governed dossier or case-review flow.\",\n \"metaExpr\": \"${employee.role}\",\n \"ctaLabel\": \"Open dossier\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"employee.dossier.open\",\n \"payloadExpr\": \"${employee}\"\n },\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Start retention plan\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"employee.retention.start\",\n \"payloadExpr\": \"${employee}\"\n }\n }\n ]\n }\n ]\n }\n }\n }\n }\n ]\n }\n}\n",
3043
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.employee-insight-workbench.json",
3056
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.employee-insight-workbench.json",
3044
3057
  "contentHash": "7bbc29a6a91be8398c4b1fbfd65671c9964b96dc68bbac3427d0486c15a49f1b",
3045
3058
  "sourceKind": "component_definition",
3046
3059
  "sourceId": "praxis-dynamic-page",
@@ -3050,7 +3063,7 @@
3050
3063
  "chunkIndex": 16,
3051
3064
  "chunkKind": "recipe",
3052
3065
  "content": "{\n \"_comment\": \"Praxis Dynamic Page recipe for an HR internal mobility workbench using portable rich-content blocks for mobility signals, target role context and governed transition actions.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"employee-internal-mobility-workbench\",\n \"status\": \"public-example\",\n \"useWhen\": \"Create an HR internal mobility workbench with mobility signals, target role context and governed transition actions.\",\n \"examplePrompts\": [\n \"create an HR internal mobility workbench\",\n \"show a governed internal mobility rich content surface\",\n \"generate a people operations page with mobility signals and transition actions\"\n ]\n },\n \"platformValue\": {\n \"canonicalRuntime\": \"@praxisui/rich-content owns the portable HR internal mobility surface.\",\n \"hostMediation\": \"The host mediates employee, target role, panel scheduling and escalation flows through actionId contracts.\",\n \"publicExamples\": \"praxis-ui-landing-page can expose the same internal mobility workbench without serializing runtime helpers.\",\n \"agentCorpus\": \"This recipe keeps mobility signals, selected employee context, target role context and governed mobility actions inside RichContentDocument so agents can reuse the same semantic surface across hosts.\"\n },\n \"authoringGuidance\": [\n \"Use definition.id \\\"praxis-rich-content\\\".\",\n \"Model mobility metrics with statGroup instead of host-authored transition cards.\",\n \"Model the selected employee with lookupCard when the host already resolved the internal mobility context.\",\n \"Use tabs for summary and fit views instead of host-authored mobility sections.\",\n \"Use relatedRecord, ctaGroup and actionCard for governed mobility and escalation actions; keep handlers out of the document.\",\n \"Do not serialize hostCapabilities in the page JSON; the host injects runtime mediation only while rendering.\"\n ],\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 1,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"employeeInternalMobilityWorkbench\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"swap_horiz\",\n \"title\": \"Internal mobility workbench\",\n \"subtitle\": \"Portable rich-content surface for governed HR mobility operations\"\n },\n \"definition\": {\n \"id\": \"praxis-rich-content\",\n \"bindingOrder\": [\"document\", \"context\", \"layout\", \"rootClassName\"],\n \"inputs\": {\n \"layout\": \"block\",\n \"rootClassName\": \"employee-internal-mobility-workbench\",\n \"context\": {\n \"mobility\": {\n \"employeeId\": \"EMP-903\",\n \"employeeName\": \"Rafael Nunes\",\n \"currentRole\": \"Senior Product Analyst\",\n \"currentArea\": \"Digital experience\",\n \"manager\": \"Lucas Almeida\",\n \"readiness\": \"87\",\n \"openRoles\": \"2\",\n \"window\": \"Q3\"\n },\n \"targetRole\": {\n \"name\": \"Staff Product Manager\",\n \"department\": \"Digital experience\",\n \"lane\": \"Product leadership\"\n }\n },\n \"document\": {\n \"kind\": \"praxis.rich-content\",\n \"version\": \"1.0.0\",\n \"nodes\": [\n {\n \"type\": \"callout\",\n \"tone\": \"info\",\n \"icon\": \"swap_horiz\",\n \"titleExpr\": \"${mobility.employeeName}\",\n \"message\": \"Use a portable HR internal mobility surface when the host must expose readiness signals, target role context and governed transition actions without inventing people-ops templates.\"\n },\n {\n \"type\": \"statGroup\",\n \"title\": \"Mobility signals\",\n \"subtitle\": \"Canonical KPI block for internal mobility workbenches\",\n \"layout\": \"grid\",\n \"items\": [\n {\n \"label\": \"Readiness\",\n \"valueExpr\": \"${mobility.readiness}\",\n \"caption\": \"Mobility score\",\n \"icon\": \"monitoring\"\n },\n {\n \"label\": \"Open roles\",\n \"valueExpr\": \"${mobility.openRoles}\",\n \"caption\": \"Matched opportunities\",\n \"icon\": \"workspaces\"\n },\n {\n \"label\": \"Window\",\n \"valueExpr\": \"${mobility.window}\",\n \"caption\": \"Target move\",\n \"icon\": \"calendar_month\"\n }\n ]\n },\n {\n \"type\": \"lookupCard\",\n \"title\": \"Selected employee\",\n \"status\": \"resolved\",\n \"subtitleExpr\": \"${mobility.employeeName}\",\n \"metaExpr\": \"${mobility.currentArea}\",\n \"ctaLabel\": \"Open employee\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"hr.mobility.employee.open\",\n \"payloadExpr\": \"${mobility}\"\n },\n \"fields\": [\n {\n \"label\": \"Current role\",\n \"valueExpr\": \"${mobility.currentRole}\"\n },\n {\n \"label\": \"Manager\",\n \"valueExpr\": \"${mobility.manager}\"\n }\n ],\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Open dossier\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"hr.mobility.dossier.open\",\n \"payloadExpr\": \"${mobility}\"\n }\n }\n ]\n },\n {\n \"type\": \"tabs\",\n \"title\": \"Mobility views\",\n \"subtitle\": \"Portable editorial tabs for fit, readiness and governance context.\",\n \"appearance\": \"underline\",\n \"defaultTabId\": \"summary\",\n \"items\": [\n {\n \"id\": \"summary\",\n \"label\": \"Summary\",\n \"icon\": \"dashboard\",\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": \"Keep readiness rationale, target role notes and move risks inside the same RichContentDocument.\"\n }\n ]\n },\n {\n \"id\": \"fit\",\n \"label\": \"Fit\",\n \"icon\": \"checklist\",\n \"content\": [\n {\n \"type\": \"keyValueList\",\n \"layout\": \"stacked\",\n \"items\": [\n {\n \"label\": \"Fit rule\",\n \"value\": \"Escalate any mobility move that changes compensation band or leaves critical coverage gaps unresolved.\"\n },\n {\n \"label\": \"Evidence source\",\n \"value\": \"Career matrix, calibration notes and manager alignment summary.\"\n }\n ]\n }\n ]\n }\n ]\n },\n {\n \"type\": \"relatedRecord\",\n \"title\": \"Target role\",\n \"relationLabel\": \"Role opportunity\",\n \"subtitleExpr\": \"${targetRole.name}\",\n \"metaExpr\": \"${targetRole.department}\",\n \"ctaLabel\": \"Open role\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"hr.mobility.role.open\",\n \"payloadExpr\": \"${targetRole}\"\n },\n \"fields\": [\n {\n \"label\": \"Mobility lane\",\n \"valueExpr\": \"${targetRole.lane}\",\n \"hint\": \"Resolved from the current mobility assignment.\"\n }\n ],\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Schedule panel review\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"hr.mobility.panel.schedule\",\n \"payloadExpr\": \"${mobility}\"\n }\n }\n ]\n },\n {\n \"type\": \"ctaGroup\",\n \"title\": \"Mobility actions\",\n \"subtitle\": \"Governed HR mobility outcomes\",\n \"message\": \"Use semantic mobility actions instead of host-authored transition button bars.\",\n \"layout\": \"split\",\n \"actions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Start mobility review\",\n \"icon\": \"task_alt\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"hr.mobility.review.start\",\n \"payloadExpr\": \"${mobility}\"\n }\n },\n {\n \"type\": \"actionButton\",\n \"label\": \"Request manager alignment\",\n \"icon\": \"forum\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"hr.mobility.manager.requestAlignment\",\n \"payloadExpr\": \"${mobility}\"\n }\n }\n ]\n },\n {\n \"type\": \"actionCard\",\n \"title\": \"Escalate mobility risk\",\n \"subtitleExpr\": \"${mobility.employeeId}\",\n \"message\": \"Use actionCard when the HR host needs a governed escalation for unresolved mobility blockers or retention risks.\",\n \"metaExpr\": \"${mobility.currentRole}\",\n \"ctaLabel\": \"Escalate mobility risk\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"hr.mobility.escalate\",\n \"payloadExpr\": \"${mobility}\"\n },\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Open dossier\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"hr.mobility.dossier.open\",\n \"payloadExpr\": \"${mobility}\"\n }\n }\n ]\n }\n ]\n }\n }\n }\n }\n ]\n }\n}\n",
3053
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.employee-internal-mobility-workbench.json",
3066
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.employee-internal-mobility-workbench.json",
3054
3067
  "contentHash": "0fb8f9bb9673a9c38558d249df05a13127b1f2f02e5a763898a84143a1bbd330",
3055
3068
  "sourceKind": "component_definition",
3056
3069
  "sourceId": "praxis-dynamic-page",
@@ -3060,7 +3073,7 @@
3060
3073
  "chunkIndex": 17,
3061
3074
  "chunkKind": "recipe",
3062
3075
  "content": "{\n \"_comment\": \"Praxis Dynamic Page recipe for an HR leave and absence workbench using portable rich-content blocks for leave signals, coverage context and governed absence actions.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"employee-leave-absence-workbench\",\n \"status\": \"public-example\",\n \"useWhen\": \"Create an HR leave and absence workbench with leave signals, coverage context and governed absence actions.\",\n \"examplePrompts\": [\n \"create an HR leave tracking workbench\",\n \"show a governed leave and absence rich content surface\",\n \"generate a people operations page with leave signals and coverage actions\"\n ]\n },\n \"platformValue\": {\n \"canonicalRuntime\": \"@praxisui/rich-content owns the portable HR leave and absence surface.\",\n \"hostMediation\": \"The host mediates employee, partner, coverage planning and escalation flows through actionId contracts.\",\n \"publicExamples\": \"praxis-ui-landing-page can expose the same leave and absence workbench without serializing runtime helpers.\",\n \"agentCorpus\": \"This recipe keeps leave signals, selected employee context, coverage ownership and governed leave actions inside RichContentDocument so agents can reuse the same semantic surface across hosts.\"\n },\n \"authoringGuidance\": [\n \"Use definition.id \\\"praxis-rich-content\\\".\",\n \"Model leave metrics with statGroup instead of host-authored absence cards.\",\n \"Model the selected employee with lookupCard when the host already resolved the leave and absence context.\",\n \"Use tabs for summary and compliance views instead of host-authored leave sections.\",\n \"Use relatedRecord, ctaGroup and actionCard for governed leave and escalation actions; keep handlers out of the document.\",\n \"Do not serialize hostCapabilities in the page JSON; the host injects runtime mediation only while rendering.\"\n ],\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 1,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"employeeLeaveAbsenceWorkbench\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"event_available\",\n \"title\": \"Leave and absence workbench\",\n \"subtitle\": \"Portable rich-content surface for governed HR leave operations\"\n },\n \"definition\": {\n \"id\": \"praxis-rich-content\",\n \"bindingOrder\": [\"document\", \"context\", \"layout\", \"rootClassName\"],\n \"inputs\": {\n \"layout\": \"block\",\n \"rootClassName\": \"employee-leave-absence-workbench\",\n \"context\": {\n \"leave\": {\n \"employeeId\": \"EMP-708\",\n \"employeeName\": \"Marina Reis\",\n \"role\": \"Senior Product Analyst\",\n \"leaveType\": \"Parental leave\",\n \"window\": \"12d\",\n \"coverage\": \"1\",\n \"returnDate\": \"2026-06-08\",\n \"coverageOwner\": \"Carla Mendes\"\n },\n \"partner\": {\n \"name\": \"Mariana Torres\",\n \"department\": \"People operations\",\n \"lane\": \"Leave compliance / backfill coordination\"\n }\n },\n \"document\": {\n \"kind\": \"praxis.rich-content\",\n \"version\": \"1.0.0\",\n \"nodes\": [\n {\n \"type\": \"callout\",\n \"tone\": \"info\",\n \"icon\": \"event_available\",\n \"titleExpr\": \"${leave.employeeName}\",\n \"message\": \"Use a portable HR leave and absence surface when the host must expose leave signals, coverage context and governed absence actions without inventing people-ops templates.\"\n },\n {\n \"type\": \"statGroup\",\n \"title\": \"Leave signals\",\n \"subtitle\": \"Canonical KPI block for leave and absence workbenches\",\n \"layout\": \"grid\",\n \"items\": [\n {\n \"label\": \"Window\",\n \"valueExpr\": \"${leave.window}\",\n \"captionExpr\": \"${leave.leaveType}\",\n \"icon\": \"calendar_month\"\n },\n {\n \"label\": \"Coverage\",\n \"valueExpr\": \"${leave.coverage}\",\n \"caption\": \"Open handoffs\",\n \"icon\": \"groups\"\n },\n {\n \"label\": \"Return\",\n \"valueExpr\": \"${leave.returnDate}\",\n \"caption\": \"Expected return\",\n \"icon\": \"event_available\"\n }\n ]\n },\n {\n \"type\": \"lookupCard\",\n \"title\": \"Selected employee\",\n \"status\": \"resolved\",\n \"subtitleExpr\": \"${leave.employeeName}\",\n \"metaExpr\": \"${leave.role}\",\n \"ctaLabel\": \"Open employee\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"hr.leave.employee.open\",\n \"payloadExpr\": \"${leave}\"\n },\n \"fields\": [\n {\n \"label\": \"Leave type\",\n \"valueExpr\": \"${leave.leaveType}\"\n },\n {\n \"label\": \"Coverage owner\",\n \"valueExpr\": \"${leave.coverageOwner}\"\n }\n ],\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Open dossier\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"hr.leave.dossier.open\",\n \"payloadExpr\": \"${leave}\"\n }\n }\n ]\n },\n {\n \"type\": \"tabs\",\n \"title\": \"Leave views\",\n \"subtitle\": \"Portable editorial tabs for leave summary and compliance context.\",\n \"appearance\": \"underline\",\n \"defaultTabId\": \"summary\",\n \"items\": [\n {\n \"id\": \"summary\",\n \"label\": \"Summary\",\n \"icon\": \"dashboard\",\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": \"Keep leave rationale, coverage notes and return planning inside the same RichContentDocument.\"\n }\n ]\n },\n {\n \"id\": \"compliance\",\n \"label\": \"Compliance\",\n \"icon\": \"policy\",\n \"content\": [\n {\n \"type\": \"keyValueList\",\n \"layout\": \"stacked\",\n \"items\": [\n {\n \"label\": \"Policy rule\",\n \"value\": \"Escalate any leave extension or missing coverage handoff before payroll and access deadlines.\"\n },\n {\n \"label\": \"Evidence source\",\n \"value\": \"Leave policy snapshot, manager notes and return-to-work checklist.\"\n }\n ]\n }\n ]\n }\n ]\n },\n {\n \"type\": \"relatedRecord\",\n \"title\": \"Coverage partner\",\n \"relationLabel\": \"HR partner\",\n \"subtitleExpr\": \"${partner.name}\",\n \"metaExpr\": \"${partner.department}\",\n \"ctaLabel\": \"Open partner\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"hr.leave.partner.open\",\n \"payloadExpr\": \"${partner}\"\n },\n \"fields\": [\n {\n \"label\": \"Coverage lane\",\n \"valueExpr\": \"${partner.lane}\",\n \"hint\": \"Resolved from the current leave assignment.\"\n }\n ],\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Schedule return sync\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"hr.leave.return.scheduleSync\",\n \"payloadExpr\": \"${leave}\"\n }\n }\n ]\n },\n {\n \"type\": \"ctaGroup\",\n \"title\": \"Leave actions\",\n \"subtitle\": \"Governed HR leave outcomes\",\n \"message\": \"Use semantic leave actions instead of host-authored absence button bars.\",\n \"layout\": \"split\",\n \"actions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Confirm leave plan\",\n \"icon\": \"task_alt\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"hr.leave.confirm\",\n \"payloadExpr\": \"${leave}\"\n }\n },\n {\n \"type\": \"actionButton\",\n \"label\": \"Request coverage update\",\n \"icon\": \"sync\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"hr.leave.coverage.requestUpdate\",\n \"payloadExpr\": \"${leave}\"\n }\n }\n ]\n },\n {\n \"type\": \"actionCard\",\n \"title\": \"Escalate leave risk\",\n \"subtitleExpr\": \"${leave.employeeId}\",\n \"message\": \"Use actionCard when the HR host needs a governed escalation for unresolved leave blockers or return planning risks.\",\n \"metaExpr\": \"${leave.leaveType}\",\n \"ctaLabel\": \"Escalate leave risk\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"hr.leave.escalate\",\n \"payloadExpr\": \"${leave}\"\n },\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Open dossier\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"hr.leave.dossier.open\",\n \"payloadExpr\": \"${leave}\"\n }\n }\n ]\n }\n ]\n }\n }\n }\n }\n ]\n }\n}\n",
3063
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.employee-leave-absence-workbench.json",
3076
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.employee-leave-absence-workbench.json",
3064
3077
  "contentHash": "75f752c517c72bbcad5bfd64c338b8c435682068218614de1e65829177cce192",
3065
3078
  "sourceKind": "component_definition",
3066
3079
  "sourceId": "praxis-dynamic-page",
@@ -3070,7 +3083,7 @@
3070
3083
  "chunkIndex": 18,
3071
3084
  "chunkKind": "recipe",
3072
3085
  "content": "{\n \"_comment\": \"Praxis Dynamic Page recipe for an HR offboarding workbench using portable rich-content blocks for exit signals, transition ownership and governed departure actions.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"employee-offboarding-workbench\",\n \"status\": \"public-example\",\n \"useWhen\": \"Create an HR offboarding workbench with exit signals, transition ownership and governed departure actions.\",\n \"examplePrompts\": [\n \"create an HR offboarding workbench\",\n \"show a governed offboarding rich content surface\",\n \"generate a people operations page with departure signals and transition actions\"\n ]\n },\n \"platformValue\": {\n \"canonicalRuntime\": \"@praxisui/rich-content owns the portable HR offboarding surface.\",\n \"hostMediation\": \"The host mediates employee, transition-owner, departure planning and escalation flows through actionId contracts.\",\n \"publicExamples\": \"praxis-ui-landing-page can expose the same offboarding workbench without serializing runtime helpers.\",\n \"agentCorpus\": \"This recipe keeps exit signals, selected employee context, transition ownership and governed offboarding actions inside RichContentDocument so agents can reuse the same semantic surface across hosts.\"\n },\n \"authoringGuidance\": [\n \"Use definition.id \\\"praxis-rich-content\\\".\",\n \"Model departure metrics with statGroup instead of host-authored offboarding cards.\",\n \"Model the selected employee with lookupCard when the host already resolved the offboarding context.\",\n \"Use tabs for summary and compliance views instead of host-authored offboarding sections.\",\n \"Use relatedRecord, ctaGroup and actionCard for governed offboarding and escalation actions; keep handlers out of the document.\",\n \"Do not serialize hostCapabilities in the page JSON; the host injects runtime mediation only while rendering.\"\n ],\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 1,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"employeeOffboardingWorkbench\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"exit_to_app\",\n \"title\": \"Offboarding workbench\",\n \"subtitle\": \"Portable rich-content surface for governed HR departure operations\"\n },\n \"definition\": {\n \"id\": \"praxis-rich-content\",\n \"bindingOrder\": [\"document\", \"context\", \"layout\", \"rootClassName\"],\n \"inputs\": {\n \"layout\": \"block\",\n \"rootClassName\": \"employee-offboarding-workbench\",\n \"context\": {\n \"employee\": {\n \"id\": \"EMP-640\",\n \"name\": \"Diego Nunes\",\n \"role\": \"Staff Product Designer\",\n \"department\": \"Product design\",\n \"lastDay\": \"2026-05-12\",\n \"noticeWindow\": \"14d\",\n \"reason\": \"Voluntary departure\",\n \"coverage\": \"3\",\n \"risk\": \"Moderate\"\n },\n \"owner\": {\n \"name\": \"Marina Costa\",\n \"department\": \"People operations\",\n \"lane\": \"Exit compliance / access revocation\"\n }\n },\n \"document\": {\n \"kind\": \"praxis.rich-content\",\n \"version\": \"1.0.0\",\n \"nodes\": [\n {\n \"type\": \"callout\",\n \"tone\": \"info\",\n \"icon\": \"exit_to_app\",\n \"titleExpr\": \"${employee.name}\",\n \"message\": \"Use a portable HR offboarding surface when the host must expose exit signals, transition ownership and governed departure actions without inventing people-ops templates.\"\n },\n {\n \"type\": \"statGroup\",\n \"title\": \"Exit signals\",\n \"subtitle\": \"Canonical KPI block for offboarding workbenches\",\n \"layout\": \"grid\",\n \"items\": [\n {\n \"label\": \"Notice\",\n \"valueExpr\": \"${employee.noticeWindow}\",\n \"captionExpr\": \"${employee.lastDay}\",\n \"icon\": \"event_busy\"\n },\n {\n \"label\": \"Coverage\",\n \"valueExpr\": \"${employee.coverage}\",\n \"caption\": \"Open handoffs\",\n \"icon\": \"handover\"\n },\n {\n \"label\": \"Risk\",\n \"valueExpr\": \"${employee.risk}\",\n \"captionExpr\": \"${employee.reason}\",\n \"icon\": \"warning\"\n }\n ]\n },\n {\n \"type\": \"lookupCard\",\n \"title\": \"Selected employee\",\n \"status\": \"resolved\",\n \"subtitleExpr\": \"${employee.name}\",\n \"metaExpr\": \"${employee.role}\",\n \"ctaLabel\": \"Open employee\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"hr.offboarding.employee.open\",\n \"payloadExpr\": \"${employee}\"\n },\n \"fields\": [\n {\n \"label\": \"Last day\",\n \"valueExpr\": \"${employee.lastDay}\"\n },\n {\n \"label\": \"Reason\",\n \"valueExpr\": \"${employee.reason}\"\n }\n ],\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Open dossier\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"hr.offboarding.dossier.open\",\n \"payloadExpr\": \"${employee}\"\n }\n }\n ]\n },\n {\n \"type\": \"tabs\",\n \"title\": \"Offboarding views\",\n \"subtitle\": \"Portable editorial tabs for transition summary and compliance context.\",\n \"appearance\": \"underline\",\n \"defaultTabId\": \"summary\",\n \"items\": [\n {\n \"id\": \"summary\",\n \"label\": \"Summary\",\n \"icon\": \"dashboard\",\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": \"Keep departure rationale, handoff progress and exit readiness inside the same RichContentDocument.\"\n }\n ]\n },\n {\n \"id\": \"compliance\",\n \"label\": \"Compliance\",\n \"icon\": \"policy\",\n \"content\": [\n {\n \"type\": \"keyValueList\",\n \"layout\": \"stacked\",\n \"items\": [\n {\n \"label\": \"Asset rule\",\n \"value\": \"Escalate any missing asset return or access closure before the final payroll checkpoint.\"\n },\n {\n \"label\": \"Knowledge transfer\",\n \"value\": \"Document ownership transitions and successor coverage inside the same governed surface.\"\n }\n ]\n }\n ]\n }\n ]\n },\n {\n \"type\": \"relatedRecord\",\n \"title\": \"Transition owner\",\n \"relationLabel\": \"HR partner\",\n \"subtitleExpr\": \"${owner.name}\",\n \"metaExpr\": \"${owner.department}\",\n \"ctaLabel\": \"Open owner\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"hr.offboarding.owner.open\",\n \"payloadExpr\": \"${owner}\"\n },\n \"fields\": [\n {\n \"label\": \"Checklist lane\",\n \"valueExpr\": \"${owner.lane}\",\n \"hint\": \"Resolved from the current offboarding assignment.\"\n }\n ],\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Plan exit interview\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"hr.offboarding.exitInterview.plan\",\n \"payloadExpr\": \"${employee}\"\n }\n }\n ]\n },\n {\n \"type\": \"ctaGroup\",\n \"title\": \"Offboarding actions\",\n \"subtitle\": \"Governed HR departure outcomes\",\n \"message\": \"Use semantic offboarding actions instead of host-authored departure button bars.\",\n \"layout\": \"split\",\n \"actions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Confirm offboarding plan\",\n \"icon\": \"task_alt\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"hr.offboarding.confirm\",\n \"payloadExpr\": \"${employee}\"\n }\n },\n {\n \"type\": \"actionButton\",\n \"label\": \"Request handoff update\",\n \"icon\": \"sync\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"hr.offboarding.handoff.requestUpdate\",\n \"payloadExpr\": \"${employee}\"\n }\n }\n ]\n },\n {\n \"type\": \"actionCard\",\n \"title\": \"Escalate departure risk\",\n \"subtitleExpr\": \"${employee.id}\",\n \"message\": \"Use actionCard when the HR host needs a governed escalation for unresolved exit blockers or access closure risks.\",\n \"metaExpr\": \"${employee.role}\",\n \"ctaLabel\": \"Escalate risk\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"hr.offboarding.escalate\",\n \"payloadExpr\": \"${employee}\"\n },\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Open dossier\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"hr.offboarding.dossier.open\",\n \"payloadExpr\": \"${employee}\"\n }\n }\n ]\n }\n ]\n }\n }\n }\n }\n ]\n }\n}\n",
3073
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.employee-offboarding-workbench.json",
3086
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.employee-offboarding-workbench.json",
3074
3087
  "contentHash": "f4f28dbe740e21f88733fabb21089929a9b1bffa24f14c06ee32194881e18267",
3075
3088
  "sourceKind": "component_definition",
3076
3089
  "sourceId": "praxis-dynamic-page",
@@ -3080,7 +3093,7 @@
3080
3093
  "chunkIndex": 19,
3081
3094
  "chunkKind": "recipe",
3082
3095
  "content": "{\n \"_comment\": \"Praxis Dynamic Page recipe for an HR performance review workbench using portable rich-content blocks for review signals, manager context and governed calibration actions.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"employee-performance-review-workbench\",\n \"status\": \"public-example\",\n \"useWhen\": \"Create an HR performance review workbench with review signals, calibration context and governed review actions.\",\n \"examplePrompts\": [\n \"create an HR performance review workbench\",\n \"show a governed performance review rich content surface\",\n \"generate a people operations page with review signals and calibration actions\"\n ]\n },\n \"platformValue\": {\n \"canonicalRuntime\": \"@praxisui/rich-content owns the portable HR performance review surface.\",\n \"hostMediation\": \"The host mediates employee, manager, calibration and escalation flows through actionId contracts.\",\n \"publicExamples\": \"praxis-ui-landing-page can expose the same review workbench without serializing runtime helpers.\",\n \"agentCorpus\": \"This recipe keeps review signals, selected employee context, manager ownership and governed review actions inside RichContentDocument so agents can reuse the same semantic surface across hosts.\"\n },\n \"authoringGuidance\": [\n \"Use definition.id \\\"praxis-rich-content\\\".\",\n \"Model review metrics with statGroup instead of host-authored review cards.\",\n \"Model the selected employee with lookupCard when the host already resolved the review context.\",\n \"Use tabs for summary and calibration views instead of host-authored review sections.\",\n \"Use relatedRecord, ctaGroup and actionCard for governed review and escalation actions; keep handlers out of the document.\",\n \"Do not serialize hostCapabilities in the page JSON; the host injects runtime mediation only while rendering.\"\n ],\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 1,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"employeePerformanceReviewWorkbench\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"military_tech\",\n \"title\": \"Performance review workbench\",\n \"subtitle\": \"Portable rich-content surface for governed HR review operations\"\n },\n \"definition\": {\n \"id\": \"praxis-rich-content\",\n \"bindingOrder\": [\"document\", \"context\", \"layout\", \"rootClassName\"],\n \"inputs\": {\n \"layout\": \"block\",\n \"rootClassName\": \"employee-performance-review-workbench\",\n \"context\": {\n \"employee\": {\n \"id\": \"EMP-320\",\n \"name\": \"Rafaela Nunes\",\n \"role\": \"Senior Product Designer\",\n \"department\": \"Experience Design\",\n \"cycle\": \"Q2\",\n \"calibration\": \"2\",\n \"rating\": \"Exceeds\",\n \"promotionReadiness\": \"Stretch role ready\",\n \"reviewWindow\": \"3d\"\n },\n \"manager\": {\n \"name\": \"Marcos Lima\",\n \"department\": \"Design leadership\",\n \"reviewLane\": \"Design council\"\n }\n },\n \"document\": {\n \"kind\": \"praxis.rich-content\",\n \"version\": \"1.0.0\",\n \"nodes\": [\n {\n \"type\": \"callout\",\n \"tone\": \"info\",\n \"icon\": \"military_tech\",\n \"titleExpr\": \"${employee.name}\",\n \"message\": \"Use a portable HR performance review surface when the host must expose review signals, calibration context and governed actions without inventing people-ops templates.\"\n },\n {\n \"type\": \"statGroup\",\n \"title\": \"Review signals\",\n \"subtitle\": \"Canonical KPI block for performance review workbenches\",\n \"layout\": \"grid\",\n \"items\": [\n {\n \"label\": \"Cycle\",\n \"valueExpr\": \"${employee.cycle}\",\n \"captionExpr\": \"${employee.department}\",\n \"icon\": \"event\"\n },\n {\n \"label\": \"Calibration\",\n \"valueExpr\": \"${employee.calibration}\",\n \"captionExpr\": \"${employee.reviewWindow}\",\n \"icon\": \"balance\"\n },\n {\n \"label\": \"Rating\",\n \"valueExpr\": \"${employee.rating}\",\n \"captionExpr\": \"${employee.promotionReadiness}\",\n \"icon\": \"emoji_events\"\n }\n ]\n },\n {\n \"type\": \"lookupCard\",\n \"title\": \"Selected employee\",\n \"status\": \"resolved\",\n \"subtitleExpr\": \"${employee.name}\",\n \"metaExpr\": \"${employee.role}\",\n \"ctaLabel\": \"Open employee\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"hr.review.employee.open\",\n \"payloadExpr\": \"${employee}\"\n },\n \"fields\": [\n {\n \"label\": \"Current rating\",\n \"valueExpr\": \"${employee.rating}\"\n },\n {\n \"label\": \"Promotion readiness\",\n \"valueExpr\": \"${employee.promotionReadiness}\"\n }\n ],\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Open dossier\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"hr.review.dossier.open\",\n \"payloadExpr\": \"${employee}\"\n }\n }\n ]\n },\n {\n \"type\": \"tabs\",\n \"title\": \"Review views\",\n \"subtitle\": \"Portable editorial tabs for review and calibration context.\",\n \"appearance\": \"underline\",\n \"defaultTabId\": \"summary\",\n \"items\": [\n {\n \"id\": \"summary\",\n \"label\": \"Summary\",\n \"icon\": \"dashboard\",\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": \"Tabs keep review notes, promotion context and calibration rationale inside the same RichContentDocument.\"\n }\n ]\n },\n {\n \"id\": \"calibration\",\n \"label\": \"Calibration\",\n \"icon\": \"tune\",\n \"content\": [\n {\n \"type\": \"keyValueList\",\n \"layout\": \"stacked\",\n \"items\": [\n {\n \"label\": \"Calibration rule\",\n \"value\": \"Escalate any rating change that requires council approval.\"\n },\n {\n \"label\": \"Evidence source\",\n \"valueExpr\": \"${employee.reviewWindow}\"\n },\n {\n \"label\": \"Portability rule\",\n \"value\": \"Keep review semantics in the rich-content document; keep execution in the host.\"\n }\n ]\n }\n ]\n }\n ]\n },\n {\n \"type\": \"relatedRecord\",\n \"title\": \"Review manager\",\n \"subtitleExpr\": \"${manager.name}\",\n \"relationLabel\": \"Manager\",\n \"metaExpr\": \"${manager.department}\",\n \"ctaLabel\": \"Open manager\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"hr.review.manager.open\",\n \"payloadExpr\": \"${manager}\"\n },\n \"fields\": [\n {\n \"label\": \"Review lane\",\n \"valueExpr\": \"${manager.reviewLane}\",\n \"hint\": \"Resolved from the current review assignment.\"\n }\n ],\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Schedule calibration\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"hr.review.manager.scheduleCalibration\",\n \"payloadExpr\": \"${employee}\"\n }\n }\n ]\n },\n {\n \"type\": \"ctaGroup\",\n \"title\": \"Review actions\",\n \"subtitle\": \"Governed HR review outcomes\",\n \"message\": \"Use semantic review actions instead of host-authored performance review button bars.\",\n \"layout\": \"split\",\n \"actions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Confirm review\",\n \"icon\": \"task_alt\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"hr.review.confirm\",\n \"payloadExpr\": \"${employee}\"\n }\n },\n {\n \"type\": \"actionButton\",\n \"label\": \"Request calibration follow-up\",\n \"icon\": \"flag\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"hr.review.calibration.followUp\",\n \"payloadExpr\": \"${employee}\"\n }\n }\n ]\n },\n {\n \"type\": \"actionCard\",\n \"title\": \"Escalate review case\",\n \"subtitleExpr\": \"${employee.id}\",\n \"message\": \"Use actionCard when the HR host needs a governed escalation or calibration flow.\",\n \"metaExpr\": \"${employee.role}\",\n \"ctaLabel\": \"Escalate review\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"hr.review.escalate\",\n \"payloadExpr\": \"${employee}\"\n },\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Open dossier\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"hr.review.dossier.open\",\n \"payloadExpr\": \"${employee}\"\n }\n }\n ]\n }\n ]\n }\n }\n }\n }\n ]\n }\n}\n",
3083
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.employee-performance-review-workbench.json",
3096
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.employee-performance-review-workbench.json",
3084
3097
  "contentHash": "545899cf92db87d413deef00a975cf9cff2ceceaaeb3eebf587d9b038567fa22",
3085
3098
  "sourceKind": "component_definition",
3086
3099
  "sourceId": "praxis-dynamic-page",
@@ -3090,7 +3103,7 @@
3090
3103
  "chunkIndex": 20,
3091
3104
  "chunkKind": "recipe",
3092
3105
  "content": "{\n \"_comment\": \"Praxis Dynamic Page recipe for an HR promotion review workbench using portable rich-content blocks for readiness signals, sponsor context and governed promotion actions.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"employee-promotion-review-workbench\",\n \"status\": \"public-example\",\n \"useWhen\": \"Create an HR promotion review workbench with readiness signals, sponsor context and governed promotion actions.\",\n \"examplePrompts\": [\n \"create an HR promotion review workbench\",\n \"show a governed promotion review rich content surface\",\n \"generate a people operations page with promotion signals and sponsor actions\"\n ]\n },\n \"platformValue\": {\n \"canonicalRuntime\": \"@praxisui/rich-content owns the portable HR promotion review surface.\",\n \"hostMediation\": \"The host mediates employee, sponsor, promotion planning and escalation flows through actionId contracts.\",\n \"publicExamples\": \"praxis-ui-landing-page can expose the same promotion review workbench without serializing runtime helpers.\",\n \"agentCorpus\": \"This recipe keeps promotion signals, selected employee context, sponsor ownership and governed promotion actions inside RichContentDocument so agents can reuse the same semantic surface across hosts.\"\n },\n \"authoringGuidance\": [\n \"Use definition.id \\\"praxis-rich-content\\\".\",\n \"Model promotion metrics with statGroup instead of host-authored readiness cards.\",\n \"Model the selected employee with lookupCard when the host already resolved the promotion context.\",\n \"Use tabs for summary and sponsor views instead of host-authored promotion sections.\",\n \"Use relatedRecord, ctaGroup and actionCard for governed promotion and escalation actions; keep handlers out of the document.\",\n \"Do not serialize hostCapabilities in the page JSON; the host injects runtime mediation only while rendering.\"\n ],\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 1,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"employeePromotionReviewWorkbench\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"north_star\",\n \"title\": \"Promotion review workbench\",\n \"subtitle\": \"Portable rich-content surface for governed HR promotion operations\"\n },\n \"definition\": {\n \"id\": \"praxis-rich-content\",\n \"bindingOrder\": [\"document\", \"context\", \"layout\", \"rootClassName\"],\n \"inputs\": {\n \"layout\": \"block\",\n \"rootClassName\": \"employee-promotion-review-workbench\",\n \"context\": {\n \"employee\": {\n \"id\": \"EMP-512\",\n \"name\": \"Larissa Azevedo\",\n \"role\": \"Senior Platform Engineer\",\n \"department\": \"Platform engineering\",\n \"cycle\": \"Q2\",\n \"readiness\": \"Ready now\",\n \"targetRole\": \"Staff Platform Engineer\",\n \"impactSignal\": \"Cross-team platform leadership\",\n \"reviewWindow\": \"5d\"\n },\n \"sponsor\": {\n \"name\": \"Helena Souza\",\n \"department\": \"Leadership sponsor\",\n \"promotionLane\": \"Leadership council / role leveling\"\n }\n },\n \"document\": {\n \"kind\": \"praxis.rich-content\",\n \"version\": \"1.0.0\",\n \"nodes\": [\n {\n \"type\": \"callout\",\n \"tone\": \"info\",\n \"icon\": \"north_star\",\n \"titleExpr\": \"${employee.name}\",\n \"message\": \"Use a portable HR promotion review surface when the host must expose readiness signals, sponsor context and governed promotion actions without inventing people-ops templates.\"\n },\n {\n \"type\": \"statGroup\",\n \"title\": \"Promotion signals\",\n \"subtitle\": \"Canonical KPI block for promotion review workbenches\",\n \"layout\": \"grid\",\n \"items\": [\n {\n \"label\": \"Cycle\",\n \"valueExpr\": \"${employee.cycle}\",\n \"captionExpr\": \"${employee.department}\",\n \"icon\": \"event\"\n },\n {\n \"label\": \"Readiness\",\n \"valueExpr\": \"${employee.readiness}\",\n \"captionExpr\": \"${employee.reviewWindow}\",\n \"icon\": \"trending_up\"\n },\n {\n \"label\": \"Target role\",\n \"valueExpr\": \"${employee.targetRole}\",\n \"captionExpr\": \"${employee.impactSignal}\",\n \"icon\": \"north\"\n }\n ]\n },\n {\n \"type\": \"lookupCard\",\n \"title\": \"Selected employee\",\n \"status\": \"resolved\",\n \"subtitleExpr\": \"${employee.name}\",\n \"metaExpr\": \"${employee.role}\",\n \"ctaLabel\": \"Open employee\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"hr.promotion.employee.open\",\n \"payloadExpr\": \"${employee}\"\n },\n \"fields\": [\n {\n \"label\": \"Target role\",\n \"valueExpr\": \"${employee.targetRole}\"\n },\n {\n \"label\": \"Impact signal\",\n \"valueExpr\": \"${employee.impactSignal}\"\n }\n ],\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Open dossier\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"hr.promotion.dossier.open\",\n \"payloadExpr\": \"${employee}\"\n }\n }\n ]\n },\n {\n \"type\": \"tabs\",\n \"title\": \"Promotion views\",\n \"subtitle\": \"Portable editorial tabs for promotion summary and sponsor context.\",\n \"appearance\": \"underline\",\n \"defaultTabId\": \"summary\",\n \"items\": [\n {\n \"id\": \"summary\",\n \"label\": \"Summary\",\n \"icon\": \"dashboard\",\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": \"Tabs keep promotion notes, readiness signals and sponsor rationale inside the same RichContentDocument.\"\n }\n ]\n },\n {\n \"id\": \"sponsor\",\n \"label\": \"Sponsor\",\n \"icon\": \"groups\",\n \"content\": [\n {\n \"type\": \"keyValueList\",\n \"layout\": \"stacked\",\n \"items\": [\n {\n \"label\": \"Promotion rule\",\n \"value\": \"Escalate any readiness change that requires panel approval or role leveling exception.\"\n },\n {\n \"label\": \"Evidence source\",\n \"valueExpr\": \"${employee.reviewWindow}\"\n },\n {\n \"label\": \"Portability rule\",\n \"value\": \"Keep promotion semantics in the rich-content document; keep execution in the host.\"\n }\n ]\n }\n ]\n }\n ]\n },\n {\n \"type\": \"relatedRecord\",\n \"title\": \"Promotion sponsor\",\n \"subtitleExpr\": \"${sponsor.name}\",\n \"relationLabel\": \"Sponsor\",\n \"metaExpr\": \"${sponsor.department}\",\n \"ctaLabel\": \"Open sponsor\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"hr.promotion.sponsor.open\",\n \"payloadExpr\": \"${sponsor}\"\n },\n \"fields\": [\n {\n \"label\": \"Promotion lane\",\n \"valueExpr\": \"${sponsor.promotionLane}\",\n \"hint\": \"Resolved from the current promotion review assignment.\"\n }\n ],\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Schedule sponsor review\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"hr.promotion.sponsor.scheduleReview\",\n \"payloadExpr\": \"${employee}\"\n }\n }\n ]\n },\n {\n \"type\": \"ctaGroup\",\n \"title\": \"Promotion actions\",\n \"subtitle\": \"Governed HR promotion outcomes\",\n \"message\": \"Use semantic promotion actions instead of host-authored readiness button bars.\",\n \"layout\": \"split\",\n \"actions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Confirm promotion plan\",\n \"icon\": \"task_alt\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"hr.promotion.confirm\",\n \"payloadExpr\": \"${employee}\"\n }\n },\n {\n \"type\": \"actionButton\",\n \"label\": \"Request sponsor follow-up\",\n \"icon\": \"flag\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"hr.promotion.sponsor.followUp\",\n \"payloadExpr\": \"${employee}\"\n }\n }\n ]\n },\n {\n \"type\": \"actionCard\",\n \"title\": \"Escalate promotion case\",\n \"subtitleExpr\": \"${employee.id}\",\n \"message\": \"Use actionCard when the HR host needs a governed promotion escalation or leveling exception flow.\",\n \"metaExpr\": \"${employee.role}\",\n \"ctaLabel\": \"Escalate promotion\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"hr.promotion.escalate\",\n \"payloadExpr\": \"${employee}\"\n },\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Open dossier\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"hr.promotion.dossier.open\",\n \"payloadExpr\": \"${employee}\"\n }\n }\n ]\n }\n ]\n }\n }\n }\n }\n ]\n }\n}\n",
3093
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.employee-promotion-review-workbench.json",
3106
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.employee-promotion-review-workbench.json",
3094
3107
  "contentHash": "760dd9aabc2ca2375bd40f8a6ff5dc79a770724dc37e59272acf9acb76cbbb7a",
3095
3108
  "sourceKind": "component_definition",
3096
3109
  "sourceId": "praxis-dynamic-page",
@@ -3100,7 +3113,7 @@
3100
3113
  "chunkIndex": 21,
3101
3114
  "chunkKind": "recipe",
3102
3115
  "content": "{\n \"_comment\": \"Praxis Dynamic Page recipe for an HR succession planning workbench using portable rich-content blocks for readiness signals, sponsor context and governed succession actions.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"employee-succession-planning-workbench\",\n \"status\": \"public-example\",\n \"useWhen\": \"Create an HR succession planning workbench with readiness signals, sponsor context and governed succession actions.\",\n \"examplePrompts\": [\n \"create an HR succession planning workbench\",\n \"show a governed succession planning rich content surface\",\n \"generate a people operations page with succession signals and sponsor actions\"\n ]\n },\n \"platformValue\": {\n \"canonicalRuntime\": \"@praxisui/rich-content owns the portable HR succession planning surface.\",\n \"hostMediation\": \"The host mediates role, sponsor, readiness planning and escalation flows through actionId contracts.\",\n \"publicExamples\": \"praxis-ui-landing-page can expose the same succession planning workbench without serializing runtime helpers.\",\n \"agentCorpus\": \"This recipe keeps succession signals, target role context, sponsor ownership and governed succession actions inside RichContentDocument so agents can reuse the same semantic surface across hosts.\"\n },\n \"authoringGuidance\": [\n \"Use definition.id \\\"praxis-rich-content\\\".\",\n \"Model succession metrics with statGroup instead of host-authored readiness cards.\",\n \"Model the target role with lookupCard when the host already resolved the succession planning context.\",\n \"Use tabs for summary and pipeline views instead of host-authored succession sections.\",\n \"Use relatedRecord, ctaGroup and actionCard for governed succession and escalation actions; keep handlers out of the document.\",\n \"Do not serialize hostCapabilities in the page JSON; the host injects runtime mediation only while rendering.\"\n ],\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 1,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"employeeSuccessionPlanningWorkbench\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"account_tree\",\n \"title\": \"Succession planning workbench\",\n \"subtitle\": \"Portable rich-content surface for governed HR succession planning\"\n },\n \"definition\": {\n \"id\": \"praxis-rich-content\",\n \"bindingOrder\": [\"document\", \"context\", \"layout\", \"rootClassName\"],\n \"inputs\": {\n \"layout\": \"block\",\n \"rootClassName\": \"employee-succession-planning-workbench\",\n \"context\": {\n \"plan\": {\n \"role\": \"Principal Platform Lead\",\n \"incumbent\": \"Patricia Almeida\",\n \"bench\": \"2\",\n \"risk\": \"Moderate\",\n \"window\": \"90d\",\n \"readiness\": \"Ready in < 6 months\"\n },\n \"sponsor\": {\n \"name\": \"Helena Souza\",\n \"department\": \"Leadership sponsor\",\n \"lane\": \"Leadership council / critical roles\"\n }\n },\n \"document\": {\n \"kind\": \"praxis.rich-content\",\n \"version\": \"1.0.0\",\n \"nodes\": [\n {\n \"type\": \"callout\",\n \"tone\": \"info\",\n \"icon\": \"account_tree\",\n \"titleExpr\": \"${plan.role}\",\n \"message\": \"Use a portable HR succession planning surface when the host must expose readiness signals, sponsor context and governed succession actions without inventing people-ops templates.\"\n },\n {\n \"type\": \"statGroup\",\n \"title\": \"Succession signals\",\n \"subtitle\": \"Canonical KPI block for succession planning workbenches\",\n \"layout\": \"grid\",\n \"items\": [\n {\n \"label\": \"Bench\",\n \"valueExpr\": \"${plan.bench}\",\n \"caption\": \"Ready successors\",\n \"icon\": \"groups\"\n },\n {\n \"label\": \"Risk\",\n \"valueExpr\": \"${plan.risk}\",\n \"caption\": \"Coverage continuity\",\n \"icon\": \"warning\"\n },\n {\n \"label\": \"Window\",\n \"valueExpr\": \"${plan.window}\",\n \"caption\": \"Planning horizon\",\n \"icon\": \"schedule\"\n }\n ]\n },\n {\n \"type\": \"lookupCard\",\n \"title\": \"Target role\",\n \"status\": \"resolved\",\n \"subtitleExpr\": \"${plan.role}\",\n \"meta\": \"Succession planning\",\n \"ctaLabel\": \"Open successor plan\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"hr.succession.plan.open\",\n \"payloadExpr\": \"${plan}\"\n },\n \"fields\": [\n {\n \"label\": \"Current incumbent\",\n \"valueExpr\": \"${plan.incumbent}\"\n },\n {\n \"label\": \"Readiness\",\n \"valueExpr\": \"${plan.readiness}\"\n }\n ],\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Open dossier\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"hr.succession.dossier.open\",\n \"payloadExpr\": \"${plan}\"\n }\n }\n ]\n },\n {\n \"type\": \"tabs\",\n \"title\": \"Succession views\",\n \"subtitle\": \"Portable editorial tabs for readiness summary and pipeline context.\",\n \"appearance\": \"underline\",\n \"defaultTabId\": \"summary\",\n \"items\": [\n {\n \"id\": \"summary\",\n \"label\": \"Summary\",\n \"icon\": \"dashboard\",\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": \"Keep succession rationale, readiness notes and pipeline context inside the same RichContentDocument.\"\n }\n ]\n },\n {\n \"id\": \"pipeline\",\n \"label\": \"Pipeline\",\n \"icon\": \"account_tree\",\n \"content\": [\n {\n \"type\": \"keyValueList\",\n \"layout\": \"stacked\",\n \"items\": [\n {\n \"label\": \"Planning rule\",\n \"value\": \"Escalate any succession gap with no ready-now successor or no sponsor alignment in the current cycle.\"\n },\n {\n \"label\": \"Evidence source\",\n \"value\": \"Performance history, promotion outlook and sponsor alignment notes.\"\n }\n ]\n }\n ]\n }\n ]\n },\n {\n \"type\": \"relatedRecord\",\n \"title\": \"Succession sponsor\",\n \"relationLabel\": \"Sponsor\",\n \"subtitleExpr\": \"${sponsor.name}\",\n \"metaExpr\": \"${sponsor.department}\",\n \"ctaLabel\": \"Open sponsor\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"hr.succession.sponsor.open\",\n \"payloadExpr\": \"${sponsor}\"\n },\n \"fields\": [\n {\n \"label\": \"Planning lane\",\n \"valueExpr\": \"${sponsor.lane}\",\n \"hint\": \"Resolved from the current succession planning assignment.\"\n }\n ],\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Schedule sponsor sync\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"hr.succession.sponsor.scheduleSync\",\n \"payloadExpr\": \"${plan}\"\n }\n }\n ]\n },\n {\n \"type\": \"ctaGroup\",\n \"title\": \"Succession actions\",\n \"subtitle\": \"Governed HR succession outcomes\",\n \"message\": \"Use semantic succession actions instead of host-authored planning button bars.\",\n \"layout\": \"split\",\n \"actions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Confirm succession plan\",\n \"icon\": \"task_alt\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"hr.succession.confirm\",\n \"payloadExpr\": \"${plan}\"\n }\n },\n {\n \"type\": \"actionButton\",\n \"label\": \"Request readiness follow-up\",\n \"icon\": \"sync\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"hr.succession.readiness.followUp\",\n \"payloadExpr\": \"${plan}\"\n }\n }\n ]\n },\n {\n \"type\": \"actionCard\",\n \"title\": \"Escalate succession gap\",\n \"subtitleExpr\": \"${plan.role}\",\n \"message\": \"Use actionCard when the HR host needs a governed escalation for unresolved succession gaps or sponsor exceptions.\",\n \"metaExpr\": \"${plan.readiness}\",\n \"ctaLabel\": \"Escalate gap\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"hr.succession.escalate\",\n \"payloadExpr\": \"${plan}\"\n },\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Open dossier\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"hr.succession.dossier.open\",\n \"payloadExpr\": \"${plan}\"\n }\n }\n ]\n }\n ]\n }\n }\n }\n }\n ]\n }\n}\n",
3103
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.employee-succession-planning-workbench.json",
3116
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.employee-succession-planning-workbench.json",
3104
3117
  "contentHash": "a4d389c3f8b33ab2069d41601630ac55092ae3dd51a10263440bc34ba4601402",
3105
3118
  "sourceKind": "component_definition",
3106
3119
  "sourceId": "praxis-dynamic-page",
@@ -3110,7 +3123,7 @@
3110
3123
  "chunkIndex": 22,
3111
3124
  "chunkKind": "recipe",
3112
3125
  "content": "{\n \"_comment\": \"Recipe for agents to create a Praxis Dynamic Page with a governed files evidence upload flow.\",\n \"_comment2\": \"Use this when a page needs file intake, validation, metadata, quota/rate-limit feedback and upload lifecycle events.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"files-upload-evidence-flow\",\n \"status\": \"public-example\",\n \"useWhen\": \"Create a metadata-driven page that embeds praxis-files-upload as a governed evidence intake surface.\",\n \"examplePrompts\": [\n \"create a mission evidence upload page\",\n \"show praxis-files-upload with metadata and validation\",\n \"generate an evidence intake dynamic page with upload lifecycle events\"\n ]\n },\n \"platformValue\": {\n \"canonicalRuntime\": \"@praxisui/files-upload owns validation, retry, quota, rate-limit and event semantics.\",\n \"hostBoundary\": \"The host owns the files API provided through baseUrl and must return the documented Praxis envelopes.\",\n \"angularRuntime\": \"@praxisui/core resolves praxis-files-upload and the support widgets from one Dynamic Page contract.\",\n \"publicExamples\": \"praxis-ui-landing-page exposes the live preview and inspector JSON.\",\n \"agentCorpus\": \"This recipe keeps agents on the supported config paths: ui, limits, options, bulk, quotas, rateLimit, headers and messages.\"\n },\n \"authoringGuidance\": [\n \"Use filesUploadId as a stable instance key for persistence and diagnostics.\",\n \"Set baseUrl explicitly to the host files API boundary.\",\n \"Use ui.accept for input hints and options.allowedExtensions plus options.acceptMimeTypes for backend validation.\",\n \"Use limits.maxFileSizeBytes, limits.maxFilesPerBulk and limits.maxBulkSizeBytes for client-side guards.\",\n \"Use manualUpload when metadata or review context should be completed before sending files.\",\n \"Do not use legacy keys such as maxFileSize, endpoint.uploadUrl, valueMode or texts on praxis-files-upload; valueMode belongs to the form field wrapper.\"\n ],\n \"teaches\": [\n \"files-upload.evidence-flow\",\n \"files-upload.validation\",\n \"files-upload.backend-options\",\n \"files-upload.bulk-policy\",\n \"files-upload.rateLimit\",\n \"files-upload.quotas\",\n \"page.composition-links\"\n ],\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 2,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"missionEvidenceUpload\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"upload_file\",\n \"title\": \"Mission evidence intake\",\n \"subtitle\": \"Manual upload, metadata, validation and host API boundary\"\n },\n \"definition\": {\n \"id\": \"praxis-files-upload\",\n \"bindingOrder\": [\"filesUploadId\", \"baseUrl\", \"displayMode\", \"config\", \"context\"],\n \"inputs\": {\n \"filesUploadId\": \"mission-evidence-upload\",\n \"componentInstanceId\": \"dynamic-page-showcase\",\n \"baseUrl\": \"/api/files\",\n \"displayMode\": \"full\",\n \"enableCustomization\": true,\n \"context\": {\n \"resourceKey\": \"operations.missoes\",\n \"resourcePath\": \"operations/missoes\",\n \"evidenceScope\": \"mission-review\"\n },\n \"config\": {\n \"strategy\": \"direct\",\n \"ui\": {\n \"showDropzone\": true,\n \"accept\": [\"application/pdf\", \"image/png\", \"image/jpeg\", \".pdf\", \".png\", \".jpg\"],\n \"dense\": false,\n \"showConflictPolicySelector\": true,\n \"showMetadataForm\": true,\n \"showProgress\": true,\n \"manualUpload\": true,\n \"dropzone\": {\n \"expandOnDragProximity\": true,\n \"proximityPx\": 96,\n \"expandMode\": \"inline\",\n \"expandHeight\": 180,\n \"expandDebounceMs\": 120\n },\n \"list\": {\n \"collapseAfter\": 4,\n \"detailsMode\": \"card\",\n \"detailsShowTechnical\": true,\n \"detailsFields\": [\"id\", \"fileName\", \"contentType\", \"fileSize\", \"uploadedAt\", \"scanStatus\"]\n }\n },\n \"limits\": {\n \"maxFileSizeBytes\": 10485760,\n \"maxFilesPerBulk\": 6,\n \"maxBulkSizeBytes\": 52428800\n },\n \"options\": {\n \"defaultConflictPolicy\": \"MAKE_UNIQUE\",\n \"strictValidation\": true,\n \"maxUploadSizeMb\": 10,\n \"allowedExtensions\": [\"pdf\", \"png\", \"jpg\", \"jpeg\"],\n \"acceptMimeTypes\": [\"application/pdf\", \"image/png\", \"image/jpeg\"],\n \"targetDirectory\": \"mission-evidence\",\n \"enableVirusScanning\": true\n },\n \"bulk\": {\n \"failFast\": false,\n \"parallelUploads\": 2,\n \"retryCount\": 2,\n \"retryBackoffMs\": 600\n },\n \"quotas\": {\n \"showQuotaWarnings\": true,\n \"blockOnExceed\": true\n },\n \"rateLimit\": {\n \"autoRetryOn429\": true,\n \"showBannerOn429\": true,\n \"maxAutoRetry\": 2,\n \"baseBackoffMs\": 1000\n },\n \"headers\": {\n \"tenantHeader\": \"X-Tenant-Id\",\n \"userHeader\": \"X-User-Id\"\n },\n \"messages\": {\n \"successSingle\": \"Evidence uploaded and ready for review.\",\n \"successBulk\": \"Evidence batch processed.\",\n \"errors\": {\n \"QUOTA_EXCEEDED\": \"Evidence quota reached for this mission.\",\n \"TIPO_ARQUIVO_INVALIDO\": \"Only PDF, PNG and JPEG evidence is accepted.\",\n \"FILE_TOO_LARGE\": \"Evidence file exceeds the 10 MB limit.\"\n }\n }\n }\n },\n \"outputs\": {\n \"uploadStart\": \"emit\",\n \"uploadProgress\": \"emit\",\n \"uploadSuccess\": \"emit\",\n \"bulkComplete\": \"emit\",\n \"error\": \"emit\",\n \"rateLimited\": \"emit\",\n \"pendingStateChange\": \"emit\",\n \"retry\": \"emit\",\n \"download\": \"emit\",\n \"copyLink\": \"emit\",\n \"detailsOpened\": \"emit\",\n \"detailsClosed\": \"emit\"\n }\n }\n }\n ]\n }\n}\n",
3113
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.files-upload-evidence-flow.json",
3126
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.files-upload-evidence-flow.json",
3114
3127
  "contentHash": "25fcc62b5d8a8925f0b08462cac6ce78584a55bf855f3635cbb86e99110a7078",
3115
3128
  "sourceKind": "component_definition",
3116
3129
  "sourceId": "praxis-dynamic-page",
@@ -3120,7 +3133,7 @@
3120
3133
  "chunkIndex": 23,
3121
3134
  "chunkKind": "recipe",
3122
3135
  "content": "{\n \"_comment\": \"Template de pagina com formulario unico (Praxis Dynamic Page).\",\n \"_comment2\": \"resourcePath deve ser o path base do recurso (sem /filter).\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"form\",\n \"useWhen\": \"Create a dynamic page with a single form widget.\",\n \"examplePrompts\": [\n \"pagina com formulario\",\n \"crie uma pagina de formulario\",\n \"formulario de detalhes\"\n ]\n },\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 2,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"mainForm\",\n \"definition\": {\n \"id\": \"praxis-dynamic-form\",\n \"bindingOrder\": [\"resourcePath\", \"formId\"],\n \"inputs\": {\n \"formId\": \"{{resourceKey}}-form\",\n \"resourcePath\": \"{{resourcePath}}\",\n \"mode\": \"view\"\n }\n }\n }\n ]\n }\n}\n",
3123
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.form.json",
3136
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.form.json",
3124
3137
  "contentHash": "59479ee48a3b750533e40bcc2fd144f7de739f029003d52dcde3fff924b9826f",
3125
3138
  "sourceKind": "component_definition",
3126
3139
  "sourceId": "praxis-dynamic-page",
@@ -3130,7 +3143,7 @@
3130
3143
  "chunkIndex": 24,
3131
3144
  "chunkKind": "recipe",
3132
3145
  "content": "{\n \"_comment\": \"Recipe for agents that need to author inline table filter fields through the canonical Praxis Metadata Editor.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"inline-filter-editorial-lab\",\n \"status\": \"public-example\",\n \"useWhen\": \"Create an authoring workspace for inline filter field metadata before generating praxis-table advancedFilters.\",\n \"examplePrompts\": [\n \"show an inline filter metadata authoring lab\",\n \"generate metadata editor examples for async select date range currency range and toggle filters\",\n \"teach agents how to author inline table filter fields\"\n ]\n },\n \"platformValue\": {\n \"canonicalContract\": \"@praxisui/core owns inline filter control type tokens and aliases.\",\n \"editorialOwner\": \"@praxisui/metadata-editor maps inline filter control types to package-owned editor properties.\",\n \"runtimeConsumer\": \"@praxisui/table consumes the authored FieldDefinition metadata inside advancedFilters.\",\n \"publicExamples\": \"praxis-ui-landing-page exposes a copyable Dynamic Page contract that renders the metadata editor.\",\n \"agentCorpus\": \"This recipe pairs with praxis-dynamic-page.inline-filter-lab.json, which shows the runtime table filter surface.\"\n },\n \"authoringGuidance\": [\n \"Use praxis-metadata-editor when the goal is to author or inspect FieldDefinition metadata.\",\n \"Set controlType to package-owned inline filter tokens such as inlineAsyncSelect, inlineDateRange, inlineCurrencyRange and inlineToggle.\",\n \"Keep backend filter semantics in the published filter DTO; use metadata editor seeds for field presentation, option loading and inline behavior.\",\n \"For async selects, prefer resourcePath or the canonical option endpoint, plus displayField/valueField or optionLabelKey/optionValueKey.\",\n \"For range controls, include labels, bounds, locale/currency when relevant and inlineAutoSize constraints so the table toolbar remains stable.\",\n \"For boolean filters, use inlineToggle when the field should behave as a toolbar affordance rather than a long form field.\",\n \"After authoring metadata, place the resulting fields under praxis-table behavior.filtering.advancedFilters.settings.alwaysVisibleFieldMetadataOverrides.\"\n ],\n \"teaches\": [\n \"metadata-editor.inline-filter-editorial\",\n \"inline-filter-control-types\",\n \"inlineAsyncSelect.editorial\",\n \"inlineDateRange.editorial\",\n \"inlineCurrencyRange.editorial\",\n \"inlineToggle.editorial\",\n \"praxis-tabs.nested-widgets\",\n \"table.filters.advancedFilters\"\n ],\n \"companionRecipes\": [\n \"praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.inline-filter-lab.json\",\n \"praxis-ui-angular/examples/ai-recipes/praxis-field-metadata-editor.json\"\n ],\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 1,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"inlineFilterEditorialTabs\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"tune\",\n \"title\": \"Inline filter editorial lab\",\n \"subtitle\": \"Author filter field metadata before composing table advancedFilters\"\n },\n \"definition\": {\n \"id\": \"praxis-tabs\",\n \"bindingOrder\": [\"tabsId\", \"config\"],\n \"inputs\": {\n \"tabsId\": \"inline-filter-editorial-lab\",\n \"componentInstanceId\": \"dynamic-page-showcase\",\n \"config\": {\n \"appearance\": {\n \"density\": \"comfortable\",\n \"color\": \"primary\",\n \"stretchTabs\": false,\n \"alignTabs\": \"start\",\n \"dynamicHeight\": true,\n \"fitInkBarToContent\": true\n },\n \"tabs\": [\n {\n \"id\": \"async-select\",\n \"textLabel\": \"Async select\",\n \"icon\": \"manage_search\",\n \"widgets\": [\n {\n \"id\": \"praxis-metadata-editor\",\n \"bindingOrder\": [\"controlType\", \"seed\"],\n \"inputs\": {\n \"controlType\": \"inlineAsyncSelect\",\n \"seed\": {\n \"name\": \"cargoId\",\n \"label\": \"Cargo\",\n \"controlType\": \"inlineAsyncSelect\",\n \"placeholder\": \"Buscar cargo\",\n \"helpText\": \"Remote option filter for the funcionarios table toolbar.\",\n \"resourcePath\": \"human-resources/cargos\",\n \"endpoint\": \"/api/human-resources/cargos/options/filter\",\n \"displayField\": \"label\",\n \"valueField\": \"id\",\n \"optionLabelKey\": \"label\",\n \"optionValueKey\": \"id\",\n \"minSearchLength\": 2,\n \"validationDebounce\": 250,\n \"inlineAutoSize\": {\n \"minWidth\": 220,\n \"maxWidth\": 320\n },\n \"clearButton\": {\n \"enabled\": true,\n \"showOnlyWhenFilled\": true\n }\n }\n },\n \"outputs\": {\n \"applied\": \"emit\",\n \"cancel\": \"emit\"\n }\n }\n ]\n },\n {\n \"id\": \"date-range\",\n \"textLabel\": \"Date range\",\n \"icon\": \"date_range\",\n \"widgets\": [\n {\n \"id\": \"praxis-metadata-editor\",\n \"bindingOrder\": [\"controlType\", \"seed\"],\n \"inputs\": {\n \"controlType\": \"inlineDateRange\",\n \"seed\": {\n \"name\": \"dataAdmissaoRange\",\n \"label\": \"Admissao\",\n \"controlType\": \"inlineDateRange\",\n \"startLabel\": \"Inicio\",\n \"endLabel\": \"Fim\",\n \"placeholder\": \"Periodo de admissao\",\n \"helpText\": \"Date interval filter mapped to the published funcionarios filter DTO.\",\n \"minDate\": \"2020-01-01\",\n \"maxDate\": \"2026-12-31\",\n \"inlinePanelTitle\": \"Periodo de admissao\",\n \"inlineAutoSize\": {\n \"minWidth\": 260,\n \"maxWidth\": 380\n },\n \"clearButton\": {\n \"enabled\": true\n }\n }\n },\n \"outputs\": {\n \"applied\": \"emit\",\n \"cancel\": \"emit\"\n }\n }\n ]\n },\n {\n \"id\": \"currency-range\",\n \"textLabel\": \"Currency range\",\n \"icon\": \"payments\",\n \"widgets\": [\n {\n \"id\": \"praxis-metadata-editor\",\n \"bindingOrder\": [\"controlType\", \"seed\"],\n \"inputs\": {\n \"controlType\": \"inlineCurrencyRange\",\n \"seed\": {\n \"name\": \"salarioBetween\",\n \"label\": \"Salario\",\n \"controlType\": \"inlineCurrencyRange\",\n \"startLabel\": \"Minimo\",\n \"endLabel\": \"Maximo\",\n \"placeholder\": \"Faixa salarial\",\n \"helpText\": \"Currency range filter with locale and bounds for payroll analysis.\",\n \"currency\": \"BRL\",\n \"currencyCode\": \"BRL\",\n \"locale\": \"pt-BR\",\n \"min\": 0,\n \"max\": 50000,\n \"step\": 500,\n \"decimalPlaces\": 2,\n \"inlineAutoSize\": {\n \"minWidth\": 280,\n \"maxWidth\": 420\n }\n }\n },\n \"outputs\": {\n \"applied\": \"emit\",\n \"cancel\": \"emit\"\n }\n }\n ]\n },\n {\n \"id\": \"toggle\",\n \"textLabel\": \"Toggle\",\n \"icon\": \"toggle_on\",\n \"widgets\": [\n {\n \"id\": \"praxis-metadata-editor\",\n \"bindingOrder\": [\"controlType\", \"seed\"],\n \"inputs\": {\n \"controlType\": \"inlineToggle\",\n \"seed\": {\n \"name\": \"ativo\",\n \"label\": \"Ativos\",\n \"controlType\": \"inlineToggle\",\n \"defaultValue\": true,\n \"helpText\": \"Boolean filter that can be rendered as an action-style toolbar affordance.\",\n \"inlineLabelVisible\": true,\n \"trueLabel\": \"Ativos\",\n \"falseLabel\": \"Inativos\",\n \"indeterminateLabel\": \"Todos\",\n \"clearButton\": {\n \"enabled\": true\n },\n \"inlineAutoSize\": {\n \"minWidth\": 128,\n \"maxWidth\": 180\n }\n }\n },\n \"outputs\": {\n \"applied\": \"emit\",\n \"cancel\": \"emit\"\n }\n }\n ]\n }\n ]\n }\n },\n \"outputs\": {\n \"selectedIndexChange\": \"emit\"\n }\n }\n }\n ]\n }\n}\n",
3133
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.inline-filter-editorial-lab.json",
3146
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.inline-filter-editorial-lab.json",
3134
3147
  "contentHash": "e177755bd053e348350f29f278b04e2905fb23d3d4052164aa53479b185d324f",
3135
3148
  "sourceKind": "component_definition",
3136
3149
  "sourceId": "praxis-dynamic-page",
@@ -3140,7 +3153,7 @@
3140
3153
  "chunkIndex": 25,
3141
3154
  "chunkKind": "recipe",
3142
3155
  "content": "{\n \"_comment\": \"Recipe para agentes criarem uma Praxis Dynamic Page com filtros inline avancados em praxis-table.\",\n \"_comment2\": \"Use quando a meta for demonstrar o filter DTO publicado renderizado como controles inline no toolbar da tabela.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"inline-filter-lab\",\n \"status\": \"public-example\",\n \"useWhen\": \"Create a metadata-driven table page that pins filter DTO fields as inline toolbar controls.\",\n \"examplePrompts\": [\n \"crie uma tabela com filtros inline para funcionarios\",\n \"mostre filtros com async select, date range e currency range\",\n \"gere um exemplo de praxis-table com advancedFilters sempre visiveis\"\n ]\n },\n \"platformValue\": {\n \"canonicalContract\": \"praxis-metadata-starter publishes the filter request schema used by praxis-filter.\",\n \"referenceApi\": \"praxis-api-quickstart serves funcionarios data and remote option endpoints.\",\n \"angularRuntime\": \"@praxisui/table hosts praxis-filter in the toolbar and wires filter events into remote table refresh.\",\n \"publicExamples\": \"praxis-ui-landing-page exposes the JSON envelope, runtime preview and coverage map.\",\n \"agentCorpus\": \"praxisui-http-examples provides executable schema and filter evidence.\"\n },\n \"operationalEvidence\": {\n \"baseUrl\": \"https://praxis-api-quickstart.onrender.com\",\n \"safeFirstIds\": [\n \"filtered-schema-request-funcionarios\",\n \"funcionarios-filter-basic\",\n \"cargos-options-filter\",\n \"departamentos-options-filter\"\n ],\n \"pendingHttpIds\": [],\n \"httpExamples\": [\n \"praxisui-http-examples/http/metadata/filtered_schema_request_funcionarios.http\",\n \"praxisui-http-examples/http/resources/funcionarios_filter_basic.http\",\n \"praxisui-http-examples/http/resources/cargos_options_filter.http\",\n \"praxisui-http-examples/http/resources/departamentos_options_filter.http\"\n ]\n },\n \"authoringGuidance\": [\n \"Use behavior.filtering.advancedFilters.settings to pin filter DTO fields in the table toolbar.\",\n \"Prefer alwaysVisibleFields that exist in the published filter request schema.\",\n \"Use alwaysVisibleFieldMetadataOverrides for presentation only; do not redefine backend filter semantics.\",\n \"Use package-owned inline control types such as inlineInput, inlineToggle, inlineAsyncSelect, inlineDateRange and inlineCurrencyRange.\",\n \"Keep option endpoints from the canonical x-ui metadata when using async select filters.\"\n ],\n \"teaches\": [\n \"table.filters.advancedFilters\",\n \"dynamic-fields.inlineInput\",\n \"dynamic-fields.inlineToggle\",\n \"dynamic-fields.inlineAsyncSelect\",\n \"dynamic-fields.inlineDateRange\",\n \"dynamic-fields.inlineCurrencyRange\",\n \"remote-options\",\n \"filter.dto\"\n ],\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 1,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"funcionariosInlineFilterTable\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"filter_alt\",\n \"title\": \"Funcionarios inline filter lab\",\n \"subtitle\": \"Filter DTO rendered as toolbar controls\"\n },\n \"definition\": {\n \"id\": \"praxis-table\",\n \"bindingOrder\": [\"config\", \"resourcePath\"],\n \"inputs\": {\n \"resourcePath\": \"human-resources/funcionarios\",\n \"tableId\": \"human-resources-funcionarios-inline-filter-lab\",\n \"config\": {\n \"toolbar\": {\n \"visible\": true,\n \"title\": \"Funcionarios\",\n \"subtitle\": \"Inline filter controls backed by the quickstart filter DTO\"\n },\n \"columns\": [\n {\n \"field\": \"nomeCompleto\",\n \"header\": \"Funcionario\",\n \"type\": \"text\",\n \"sticky\": \"start\",\n \"width\": \"220px\"\n },\n {\n \"field\": \"cargoNome\",\n \"header\": \"Cargo\",\n \"type\": \"chip\",\n \"width\": \"180px\"\n },\n {\n \"field\": \"departamentoNome\",\n \"header\": \"Departamento\",\n \"type\": \"badge\",\n \"width\": \"190px\"\n },\n {\n \"field\": \"estadoCivil\",\n \"header\": \"Estado Civil\",\n \"type\": \"badge\",\n \"width\": \"150px\"\n },\n {\n \"field\": \"salario\",\n \"header\": \"Salario\",\n \"type\": \"currency\",\n \"align\": \"end\",\n \"format\": {\n \"currency\": \"BRL\",\n \"locale\": \"pt-BR\"\n },\n \"width\": \"150px\"\n },\n {\n \"field\": \"dataAdmissao\",\n \"header\": \"Admissao\",\n \"type\": \"date\",\n \"format\": {\n \"dateStyle\": \"short\",\n \"locale\": \"pt-BR\"\n },\n \"width\": \"140px\"\n },\n {\n \"field\": \"ativo\",\n \"header\": \"Ativo\",\n \"type\": \"toggle\",\n \"align\": \"center\",\n \"width\": \"110px\"\n }\n ],\n \"behavior\": {\n \"filtering\": {\n \"enabled\": true,\n \"strategy\": \"server\",\n \"debounceTime\": 250,\n \"advancedFilters\": {\n \"enabled\": true,\n \"settings\": {\n \"mode\": \"filter\",\n \"showAdvanced\": true,\n \"allowSaveTags\": true,\n \"changeDebounceMs\": 250,\n \"alwaysVisibleFields\": [\n \"nomeCompleto\",\n \"ativo\",\n \"cargoId\",\n \"departamentoId\",\n \"dataAdmissaoRange\",\n \"salarioBetween\",\n \"estadoCivil\"\n ],\n \"selectedFieldIds\": [\"email\", \"telefone\"],\n \"placeBooleansInActions\": true,\n \"showToggleLabels\": true,\n \"alwaysMinWidth\": 180,\n \"alwaysColsMd\": 3,\n \"alwaysColsLg\": 4,\n \"tagColor\": \"primary\",\n \"tagVariant\": \"outlined\",\n \"actionsButtonColor\": \"primary\",\n \"actionsVariant\": \"outlined\",\n \"useInlineSearchableSelectVariant\": true,\n \"useInlineDateRangeVariant\": true,\n \"useInlineRangeVariant\": true,\n \"overlayVariant\": \"card\",\n \"advancedOpenMode\": \"drawer\",\n \"advancedClearButtonsEnabled\": true,\n \"alwaysVisibleFieldMetadataOverrides\": {\n \"nomeCompleto\": {\n \"label\": \"Nome\",\n \"controlType\": \"inlineInput\",\n \"inlineAutoSize\": {\n \"minWidth\": 220,\n \"maxWidth\": 320\n },\n \"clearButton\": {\n \"enabled\": true,\n \"showOnlyWhenFilled\": true\n }\n },\n \"ativo\": {\n \"label\": \"Ativos\",\n \"controlType\": \"inlineToggle\",\n \"inlineAutoSize\": {\n \"minWidth\": 112\n }\n },\n \"cargoId\": {\n \"label\": \"Cargo\",\n \"controlType\": \"inlineAsyncSelect\",\n \"endpoint\": \"/api/human-resources/cargos/options/filter\",\n \"displayField\": \"label\",\n \"valueField\": \"id\",\n \"inlineAutoSize\": {\n \"minWidth\": 190,\n \"maxWidth\": 280\n }\n },\n \"departamentoId\": {\n \"label\": \"Departamento\",\n \"controlType\": \"inlineAsyncSelect\",\n \"endpoint\": \"/api/human-resources/departamentos/options/filter\",\n \"displayField\": \"label\",\n \"valueField\": \"id\",\n \"inlineAutoSize\": {\n \"minWidth\": 210,\n \"maxWidth\": 320\n }\n },\n \"dataAdmissaoRange\": {\n \"label\": \"Admissao\",\n \"controlType\": \"inlineDateRange\",\n \"inlineAutoSize\": {\n \"minWidth\": 260,\n \"maxWidth\": 360\n }\n },\n \"salarioBetween\": {\n \"label\": \"Salario\",\n \"controlType\": \"inlineCurrencyRange\",\n \"currency\": \"BRL\",\n \"locale\": \"pt-BR\",\n \"inlineAutoSize\": {\n \"minWidth\": 250,\n \"maxWidth\": 360\n }\n },\n \"estadoCivil\": {\n \"label\": \"Estado Civil\",\n \"controlType\": \"inlineSelect\",\n \"inlineAutoSize\": {\n \"minWidth\": 160,\n \"maxWidth\": 240\n }\n }\n }\n }\n }\n },\n \"selection\": {\n \"enabled\": true,\n \"type\": \"single\"\n },\n \"density\": \"compact\"\n }\n }\n },\n \"outputs\": {\n \"rowClick\": \"emit\"\n }\n }\n }\n ]\n }\n}\n",
3143
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.inline-filter-lab.json",
3156
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.inline-filter-lab.json",
3144
3157
  "contentHash": "3014c58e3c6d670bedd0baa65d9837bce376f9bc6aaeae892dfac2e2474a8fd6",
3145
3158
  "sourceKind": "component_definition",
3146
3159
  "sourceId": "praxis-dynamic-page",
@@ -3150,7 +3163,7 @@
3150
3163
  "chunkIndex": 26,
3151
3164
  "chunkKind": "recipe",
3152
3165
  "content": "{\n \"_comment\": \"Template base para Praxis Dynamic Page (praxis-dynamic-page) com variantes.\",\n \"_comment2\": \"resourcePath deve ser o path base do recurso (sem /filter).\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"base\",\n \"defaultVariantId\": \"base\",\n \"variants\": [\n {\n \"id\": \"base\",\n \"registryKey\": \"praxis-dynamic-page:base\",\n \"variantId\": \"base\",\n \"label\": \"Base (widget único)\",\n \"description\": \"Cria uma página com um único widget simples.\",\n \"useWhen\": \"Create a dynamic page with a single widget.\"\n },\n {\n \"id\": \"table\",\n \"registryKey\": \"praxis-dynamic-page:table\",\n \"variantId\": \"table\",\n \"label\": \"Tabela\",\n \"description\": \"Cria uma página com uma tabela simples.\",\n \"useWhen\": \"Create a dynamic page with a single table.\"\n },\n {\n \"id\": \"form\",\n \"registryKey\": \"praxis-dynamic-page:form\",\n \"variantId\": \"form\",\n \"label\": \"Formulário\",\n \"description\": \"Cria uma página com formulário de detalhes.\",\n \"useWhen\": \"Create a dynamic page with a single form.\"\n },\n {\n \"id\": \"visual-block-presets-form\",\n \"registryKey\": \"praxis-dynamic-page:visual-block-presets-form\",\n \"variantId\": \"visual-block-presets-form\",\n \"label\": \"Formulário com blocos visuais\",\n \"description\": \"Cria uma página com praxis-dynamic-form usando FormColumn.items para misturar campos da API e blocos visuais estáticos.\",\n \"useWhen\": \"Create a dynamic page form that interleaves API fields with static visual blocks authored from visual block presets.\"\n },\n {\n \"id\": \"list\",\n \"registryKey\": \"praxis-dynamic-page:list\",\n \"variantId\": \"list\",\n \"label\": \"Lista\",\n \"description\": \"Cria uma página com lista de registros.\",\n \"useWhen\": \"Create a dynamic page with a single list.\"\n },\n {\n \"id\": \"master-detail\",\n \"registryKey\": \"praxis-dynamic-page:master-detail\",\n \"variantId\": \"master-detail\",\n \"label\": \"Master-detail (tabela + formulário)\",\n \"description\": \"Cria página com tabela, formulário e contexto editorial governado com rich-content.\",\n \"useWhen\": \"Create a master-detail page with table, form and governed editorial action surfaces.\"\n },\n {\n \"id\": \"master-detail-address\",\n \"registryKey\": \"praxis-dynamic-page:master-detail-address\",\n \"variantId\": \"master-detail-address\",\n \"label\": \"Master-detail + endereços\",\n \"description\": \"Cria master-detail com lista de endereços e formulário de detalhes.\",\n \"useWhen\": \"Create a master-detail page with address list + detail form.\"\n },\n {\n \"id\": \"tabs\",\n \"registryKey\": \"praxis-dynamic-page:tabs\",\n \"variantId\": \"tabs\",\n \"label\": \"Tabs (lista + detalhes)\",\n \"description\": \"Cria uma página com abas e conteúdo interno.\",\n \"useWhen\": \"Create a dynamic page with tabs.\"\n },\n {\n \"id\": \"stepper\",\n \"registryKey\": \"praxis-dynamic-page:stepper\",\n \"variantId\": \"stepper\",\n \"label\": \"Stepper (wizard)\",\n \"description\": \"Cria uma página com fluxo em etapas.\",\n \"useWhen\": \"Create a dynamic page with a stepper wizard.\"\n },\n {\n \"id\": \"nested-path-showcase\",\n \"registryKey\": \"praxis-dynamic-page:nested-path-showcase\",\n \"variantId\": \"nested-path-showcase\",\n \"label\": \"NestedPath showcase\",\n \"description\": \"Cria uma página com tabela, lista, formulário, expansion, chart, stepper e editorial forms conectados por nestedPath.\",\n \"useWhen\": \"Create a dynamic page focused on canonical nested component ports.\"\n },\n {\n \"id\": \"crud\",\n \"registryKey\": \"praxis-dynamic-page:crud\",\n \"variantId\": \"crud\",\n \"label\": \"CRUD\",\n \"description\": \"Cria uma página com widget CRUD completo.\",\n \"useWhen\": \"Create a dynamic page with a CRUD widget.\"\n }\n ],\n \"useWhen\": \"Create a dynamic page layout, including governed editorial action surfaces when the page needs hosted rich-content context or domain workbenches such as approval decisions, approval reviews, approval audits, approval SLA triage workbenches, approval delegation exception workbenches, HR employee insights, HR performance reviews, HR compensation reviews, HR promotion reviews, HR offboarding reviews, HR succession planning workbenches, HR leave and absence tracking workbenches, HR internal mobility workbenches, onboarding journeys, onboarding readiness operations, onboarding manager follow-up workbenches, onboarding equipment/access recovery workbenches and onboarding day-30 coaching workbenches.\",\n \"examplePrompts\": [\n \"crie uma pagina com tabela e formulario conectados\",\n \"pagina master detail com tabela de funcionarios e formulario\",\n \"crie uma pagina dinamica com widgets conectados\",\n \"master-detail com enderecos\",\n \"pagina master-detail com rich-content e actionCard governado\",\n \"workbench de aprovacao com rich-content governado\",\n \"workbench de revisao de aprovacao com rich-content governado\",\n \"workbench de auditoria de aprovacao com rich-content governado\",\n \"workbench de triagem de sla de approval com rich-content governado\",\n \"workbench de excecao e delegacao de aprovacao com rich-content governado\",\n \"workbench de rh com rich-content governado\",\n \"workbench de performance review de rh com rich-content governado\",\n \"workbench de compensation review de rh com rich-content governado\",\n \"workbench de promotion review de rh com rich-content governado\",\n \"workbench de offboarding de rh com rich-content governado\",\n \"workbench de succession planning de rh com rich-content governado\",\n \"workbench de leave tracking de rh com rich-content governado\",\n \"workbench de mobilidade interna de rh com rich-content governado\",\n \"workbench de onboarding com rich-content governado\",\n \"workbench de readiness de onboarding com rich-content governado\",\n \"workbench de follow-up gerencial de onboarding com rich-content governado\",\n \"workbench de recuperacao de acessos e equipamentos de onboarding com rich-content governado\",\n \"workbench de coaching day-30 de onboarding com rich-content governado\"\n ]\n },\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 2,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"mainTable\",\n \"definition\": {\n \"id\": \"praxis-table\",\n \"bindingOrder\": [\n \"config\",\n \"resourcePath\"\n ],\n \"inputs\": {\n \"resourcePath\": \"{{resourcePath}}\",\n \"tableId\": \"{{resourceKey}}-table\",\n \"config\": {\n \"toolbar\": {\n \"visible\": true,\n \"title\": \"{{resourceLabel}}\"\n }\n }\n },\n \"outputs\": {\n \"rowClick\": \"emit\"\n }\n }\n }\n ]\n }\n}\n",
3153
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.json",
3166
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.json",
3154
3167
  "contentHash": "4e962fc20682931dd3fd4926caee55c98bd270004a7e304029f0955f4e5a26d7",
3155
3168
  "sourceKind": "component_definition",
3156
3169
  "sourceId": "praxis-dynamic-page",
@@ -3160,7 +3173,7 @@
3160
3173
  "chunkIndex": 27,
3161
3174
  "chunkKind": "recipe",
3162
3175
  "content": "{\n \"_comment\": \"Recipe para agentes criarem uma Praxis Dynamic Page com formulario de lifecycle usando regras, validacao reativa e actions.\",\n \"_comment2\": \"Use quando a meta for mostrar conditionalDisplay, conditionalRequired, formRules e workflow fields em praxis-dynamic-form.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"lifecycle-form\",\n \"status\": \"public-example\",\n \"useWhen\": \"Create a metadata-driven edit form with lifecycle rules and host-owned workflow fields.\",\n \"examplePrompts\": [\n \"crie um formulario com regras condicionais para funcionario\",\n \"mostre conditionalDisplay e conditionalRequired no dynamic form\",\n \"gere uma pagina de lifecycle com validacao reativa e actions\"\n ]\n },\n \"platformValue\": {\n \"canonicalContract\": \"praxis-metadata-starter publishes the funcionario resource contract; host workflow fields remain explicit UI state.\",\n \"referenceApi\": \"praxis-api-quickstart serves funcionario detail data, options and capabilities.\",\n \"angularRuntime\": \"@praxisui/dynamic-form applies sections, fieldMetadata, conditional rules, validation and action placement.\",\n \"publicExamples\": \"praxis-ui-landing-page exposes this envelope, runtime preview and feature coverage.\",\n \"agentCorpus\": \"This recipe teaches LLMs how to add lifecycle logic without redefining backend resource semantics.\"\n },\n \"operationalEvidence\": {\n \"baseUrl\": \"https://praxis-api-quickstart.onrender.com\",\n \"safeFirstIds\": [\n \"filtered-schema-response-funcionarios\",\n \"funcionarios-get-by-id\",\n \"cargos-options-filter\",\n \"departamentos-options-filter\"\n ],\n \"pendingHttpIds\": [],\n \"httpExamples\": [\n \"praxisui-http-examples/http/metadata/filtered_schema_response_funcionarios.http\",\n \"praxisui-http-examples/http/resources/funcionarios_get_by_id.http\",\n \"praxisui-http-examples/http/resources/cargos_options_filter.http\",\n \"praxisui-http-examples/http/resources/departamentos_options_filter.http\"\n ]\n },\n \"authoringGuidance\": [\n \"Keep persisted resource fields aligned to the published response schema.\",\n \"Use host-owned workflow fields for lifecycle decisions that are not part of the canonical resource DTO.\",\n \"Use conditionalDisplay and conditionalRequired for field-level rules.\",\n \"Use formRules for section, row, column, action or field property patches driven by form state.\",\n \"Use behavior.reactiveValidation or inputs.reactiveValidation when rules should re-evaluate during editing.\",\n \"Use asyncSelect with canonical option endpoints for assignment changes.\"\n ],\n \"teaches\": [\n \"dynamic-form.conditionalDisplay\",\n \"dynamic-form.conditionalRequired\",\n \"dynamic-form.formRules\",\n \"dynamic-form.reactiveValidation\",\n \"dynamic-form.actions.custom\",\n \"dynamic-fields.asyncSelect\",\n \"dynamic-fields.currency\",\n \"remote-options\",\n \"host-workflow-fields\"\n ],\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 1,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"funcionarioLifecycleForm\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"rule\",\n \"title\": \"Funcionario lifecycle\",\n \"subtitle\": \"Rules, validations and workflow-only fields\"\n },\n \"definition\": {\n \"id\": \"praxis-dynamic-form\",\n \"bindingOrder\": [\n \"config\",\n \"resourcePath\",\n \"formId\",\n \"resourceId\",\n \"initialValue\"\n ],\n \"inputs\": {\n \"formId\": \"human-resources-funcionarios-lifecycle\",\n \"resourcePath\": \"human-resources/funcionarios\",\n \"resourceId\": 1,\n \"mode\": \"edit\",\n \"reactiveValidation\": true,\n \"reactiveValidationDebounceMs\": 200,\n \"initialValue\": {\n \"lifecycleAction\": \"UPDATE_ASSIGNMENT\",\n \"keepPayrollActive\": true\n },\n \"config\": {\n \"metadata\": {\n \"name\": \"Funcionario lifecycle workflow\",\n \"version\": \"1.0.0\"\n },\n \"behavior\": {\n \"reactiveValidation\": true,\n \"reactiveValidationDebounceMs\": 200\n },\n \"sections\": [\n {\n \"id\": \"current-state\",\n \"title\": \"Current state\",\n \"description\": \"Read the current employee data before choosing a lifecycle path.\",\n \"appearance\": \"outlined\",\n \"rows\": [\n {\n \"id\": \"current-state-row\",\n \"columns\": [\n {\n \"id\": \"current-identity\",\n \"span\": {\n \"md\": 6,\n \"lg\": 6\n },\n \"fields\": [\n \"nomeCompleto\",\n \"email\",\n \"ativo\"\n ]\n },\n {\n \"id\": \"current-assignment\",\n \"span\": {\n \"md\": 6,\n \"lg\": 6\n },\n \"fields\": [\n \"cargoId\",\n \"departamentoId\",\n \"salario\"\n ]\n }\n ]\n }\n ]\n },\n {\n \"id\": \"workflow-decision\",\n \"title\": \"Lifecycle decision\",\n \"description\": \"Host-owned workflow fields drive conditional display and validation.\",\n \"appearance\": \"outlined\",\n \"rows\": [\n {\n \"id\": \"decision-row-1\",\n \"columns\": [\n {\n \"id\": \"decision-main\",\n \"span\": {\n \"md\": 6,\n \"lg\": 6\n },\n \"fields\": [\n \"lifecycleAction\",\n \"effectiveDate\"\n ]\n },\n {\n \"id\": \"decision-flags\",\n \"span\": {\n \"md\": 6,\n \"lg\": 6\n },\n \"fields\": [\n \"keepPayrollActive\",\n \"requiresManagerApproval\"\n ]\n }\n ]\n }\n ]\n },\n {\n \"id\": \"assignment-change\",\n \"title\": \"Assignment change\",\n \"description\": \"Only required when the selected lifecycle path changes assignment.\",\n \"appearance\": \"outlined\",\n \"rows\": [\n {\n \"id\": \"assignment-change-row\",\n \"columns\": [\n {\n \"id\": \"assignment-change-main\",\n \"span\": {\n \"md\": 6,\n \"lg\": 6\n },\n \"fields\": [\n \"newCargoId\",\n \"newDepartamentoId\"\n ]\n },\n {\n \"id\": \"assignment-change-payroll\",\n \"span\": {\n \"md\": 6,\n \"lg\": 6\n },\n \"fields\": [\n \"newSalary\",\n \"assignmentReason\"\n ]\n }\n ]\n }\n ]\n },\n {\n \"id\": \"deactivation\",\n \"title\": \"Deactivation\",\n \"description\": \"Visible only for deactivation requests.\",\n \"appearance\": \"outlined\",\n \"rows\": [\n {\n \"id\": \"deactivation-row\",\n \"columns\": [\n {\n \"id\": \"deactivation-main\",\n \"fields\": [\n \"deactivationReason\",\n \"deactivationNotes\"\n ]\n }\n ]\n }\n ]\n }\n ],\n \"fieldMetadata\": [\n {\n \"name\": \"nomeCompleto\",\n \"label\": \"Nome Completo\",\n \"controlType\": \"input\",\n \"readonly\": true,\n \"validators\": {\n \"required\": true,\n \"maxLength\": 160\n }\n },\n {\n \"name\": \"email\",\n \"label\": \"Email\",\n \"controlType\": \"email\",\n \"readonly\": true,\n \"validators\": {\n \"email\": true\n }\n },\n {\n \"name\": \"ativo\",\n \"label\": \"Ativo\",\n \"controlType\": \"toggle\",\n \"readonly\": true\n },\n {\n \"name\": \"cargoId\",\n \"label\": \"Cargo atual\",\n \"controlType\": \"asyncSelect\",\n \"endpoint\": \"/api/human-resources/cargos/options/filter\",\n \"displayField\": \"label\",\n \"valueField\": \"id\",\n \"readonly\": true\n },\n {\n \"name\": \"departamentoId\",\n \"label\": \"Departamento atual\",\n \"controlType\": \"asyncSelect\",\n \"endpoint\": \"/api/human-resources/departamentos/options/filter\",\n \"displayField\": \"label\",\n \"valueField\": \"id\",\n \"readonly\": true\n },\n {\n \"name\": \"salario\",\n \"label\": \"Salario atual\",\n \"controlType\": \"currency\",\n \"currencyCode\": \"BRL\",\n \"locale\": \"pt-BR\",\n \"readonly\": true\n },\n {\n \"name\": \"lifecycleAction\",\n \"label\": \"Lifecycle action\",\n \"controlType\": \"select\",\n \"validators\": {\n \"required\": true\n },\n \"options\": [\n {\n \"label\": \"Update assignment\",\n \"value\": \"UPDATE_ASSIGNMENT\"\n },\n {\n \"label\": \"Promote\",\n \"value\": \"PROMOTE\"\n },\n {\n \"label\": \"Deactivate\",\n \"value\": \"DEACTIVATE\"\n }\n ]\n },\n {\n \"name\": \"effectiveDate\",\n \"label\": \"Effective date\",\n \"controlType\": \"date\",\n \"validators\": {\n \"required\": true\n }\n },\n {\n \"name\": \"keepPayrollActive\",\n \"label\": \"Keep payroll active\",\n \"controlType\": \"toggle\",\n \"conditionalDisplay\": {\n \"!=\": [\n {\n \"var\": \"lifecycleAction\"\n },\n \"DEACTIVATE\"\n ]\n }\n },\n {\n \"name\": \"requiresManagerApproval\",\n \"label\": \"Requires manager approval\",\n \"controlType\": \"checkbox\",\n \"conditionalDisplay\": {\n \"or\": [\n {\n \"==\": [\n {\n \"var\": \"lifecycleAction\"\n },\n \"PROMOTE\"\n ]\n },\n {\n \"==\": [\n {\n \"var\": \"lifecycleAction\"\n },\n \"DEACTIVATE\"\n ]\n }\n ]\n },\n \"conditionalRequired\": {\n \"or\": [\n {\n \"==\": [\n {\n \"var\": \"lifecycleAction\"\n },\n \"PROMOTE\"\n ]\n },\n {\n \"==\": [\n {\n \"var\": \"lifecycleAction\"\n },\n \"DEACTIVATE\"\n ]\n }\n ]\n }\n },\n {\n \"name\": \"newCargoId\",\n \"label\": \"New cargo\",\n \"controlType\": \"asyncSelect\",\n \"endpoint\": \"/api/human-resources/cargos/options/filter\",\n \"displayField\": \"label\",\n \"valueField\": \"id\",\n \"conditionalDisplay\": {\n \"or\": [\n {\n \"==\": [\n {\n \"var\": \"lifecycleAction\"\n },\n \"UPDATE_ASSIGNMENT\"\n ]\n },\n {\n \"==\": [\n {\n \"var\": \"lifecycleAction\"\n },\n \"PROMOTE\"\n ]\n }\n ]\n },\n \"conditionalRequired\": {\n \"or\": [\n {\n \"==\": [\n {\n \"var\": \"lifecycleAction\"\n },\n \"UPDATE_ASSIGNMENT\"\n ]\n },\n {\n \"==\": [\n {\n \"var\": \"lifecycleAction\"\n },\n \"PROMOTE\"\n ]\n }\n ]\n }\n },\n {\n \"name\": \"newDepartamentoId\",\n \"label\": \"New departamento\",\n \"controlType\": \"asyncSelect\",\n \"endpoint\": \"/api/human-resources/departamentos/options/filter\",\n \"displayField\": \"label\",\n \"valueField\": \"id\",\n \"conditionalDisplay\": {\n \"or\": [\n {\n \"==\": [\n {\n \"var\": \"lifecycleAction\"\n },\n \"UPDATE_ASSIGNMENT\"\n ]\n },\n {\n \"==\": [\n {\n \"var\": \"lifecycleAction\"\n },\n \"PROMOTE\"\n ]\n }\n ]\n },\n \"conditionalRequired\": {\n \"==\": [\n {\n \"var\": \"lifecycleAction\"\n },\n \"UPDATE_ASSIGNMENT\"\n ]\n }\n },\n {\n \"name\": \"newSalary\",\n \"label\": \"New salary\",\n \"controlType\": \"currency\",\n \"currencyCode\": \"BRL\",\n \"locale\": \"pt-BR\",\n \"validators\": {\n \"min\": 0\n },\n \"conditionalDisplay\": {\n \"==\": [\n {\n \"var\": \"lifecycleAction\"\n },\n \"PROMOTE\"\n ]\n },\n \"conditionalRequired\": {\n \"==\": [\n {\n \"var\": \"lifecycleAction\"\n },\n \"PROMOTE\"\n ]\n }\n },\n {\n \"name\": \"assignmentReason\",\n \"label\": \"Assignment reason\",\n \"controlType\": \"textarea\",\n \"rows\": 3,\n \"validators\": {\n \"minLength\": 12,\n \"maxLength\": 500\n },\n \"conditionalDisplay\": {\n \"or\": [\n {\n \"==\": [\n {\n \"var\": \"lifecycleAction\"\n },\n \"UPDATE_ASSIGNMENT\"\n ]\n },\n {\n \"==\": [\n {\n \"var\": \"lifecycleAction\"\n },\n \"PROMOTE\"\n ]\n }\n ]\n },\n \"conditionalRequired\": {\n \"or\": [\n {\n \"==\": [\n {\n \"var\": \"lifecycleAction\"\n },\n \"UPDATE_ASSIGNMENT\"\n ]\n },\n {\n \"==\": [\n {\n \"var\": \"lifecycleAction\"\n },\n \"PROMOTE\"\n ]\n }\n ]\n }\n },\n {\n \"name\": \"deactivationReason\",\n \"label\": \"Deactivation reason\",\n \"controlType\": \"select\",\n \"options\": [\n {\n \"label\": \"Contract ended\",\n \"value\": \"CONTRACT_ENDED\"\n },\n {\n \"label\": \"Transferred\",\n \"value\": \"TRANSFERRED\"\n },\n {\n \"label\": \"Security hold\",\n \"value\": \"SECURITY_HOLD\"\n }\n ],\n \"conditionalDisplay\": {\n \"==\": [\n {\n \"var\": \"lifecycleAction\"\n },\n \"DEACTIVATE\"\n ]\n },\n \"conditionalRequired\": {\n \"==\": [\n {\n \"var\": \"lifecycleAction\"\n },\n \"DEACTIVATE\"\n ]\n }\n },\n {\n \"name\": \"deactivationNotes\",\n \"label\": \"Deactivation notes\",\n \"controlType\": \"textarea\",\n \"rows\": 4,\n \"validators\": {\n \"minLength\": 20,\n \"maxLength\": 800\n },\n \"conditionalDisplay\": {\n \"==\": [\n {\n \"var\": \"lifecycleAction\"\n },\n \"DEACTIVATE\"\n ]\n },\n \"conditionalRequired\": {\n \"==\": [\n {\n \"var\": \"lifecycleAction\"\n },\n \"DEACTIVATE\"\n ]\n }\n }\n ],\n \"formRules\": [\n {\n \"id\": \"deactivation-hides-assignment-change\",\n \"name\": \"Deactivation hides assignment change section\",\n \"targetType\": \"section\",\n \"targetId\": \"assignment-change\",\n \"condition\": {\n \"==\": [\n {\n \"var\": \"lifecycleAction\"\n },\n \"DEACTIVATE\"\n ]\n },\n \"effect\": {\n \"propertiesWhenTrue\": {\n \"visible\": false\n },\n \"propertiesWhenFalse\": {\n \"visible\": true\n }\n }\n },\n {\n \"id\": \"assignment-path-hides-deactivation-section\",\n \"name\": \"Assignment paths hide deactivation section\",\n \"targetType\": \"section\",\n \"targetId\": \"deactivation\",\n \"condition\": {\n \"==\": [\n {\n \"var\": \"lifecycleAction\"\n },\n \"DEACTIVATE\"\n ]\n },\n \"effect\": {\n \"propertiesWhenTrue\": {\n \"visible\": true\n },\n \"propertiesWhenFalse\": {\n \"visible\": false\n }\n }\n }\n ],\n \"actions\": {\n \"submit\": {\n \"id\": \"submit-lifecycle-request\",\n \"label\": \"Submit request\",\n \"icon\": \"send\",\n \"color\": \"primary\",\n \"visible\": true,\n \"type\": \"submit\"\n },\n \"cancel\": {\n \"id\": \"cancel-lifecycle\",\n \"label\": \"Cancel\",\n \"icon\": \"close\",\n \"visible\": true,\n \"type\": \"button\"\n },\n \"reset\": {\n \"id\": \"reset-lifecycle\",\n \"label\": \"Reset workflow\",\n \"visible\": true,\n \"type\": \"reset\"\n },\n \"custom\": [\n {\n \"id\": \"preview-policy\",\n \"label\": \"Preview policy\",\n \"icon\": \"policy\",\n \"visible\": true,\n \"action\": \"previewPolicy\"\n }\n ],\n \"position\": \"right\",\n \"placement\": \"afterSections\",\n \"spacing\": \"normal\"\n }\n }\n }\n }\n }\n ]\n }\n}\n",
3163
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.lifecycle-form.json",
3176
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.lifecycle-form.json",
3164
3177
  "contentHash": "115707126052afd2661243bf250610e6416a678d9c5f39d82f01682c1b62a098",
3165
3178
  "sourceKind": "component_definition",
3166
3179
  "sourceId": "praxis-dynamic-page",
@@ -3170,7 +3183,7 @@
3170
3183
  "chunkIndex": 28,
3171
3184
  "chunkKind": "recipe",
3172
3185
  "content": "{\n \"_comment\": \"Template de pagina com lista unica (Praxis Dynamic Page).\",\n \"_comment2\": \"resourcePath deve ser o path base do recurso (sem /filter).\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"list\",\n \"useWhen\": \"Create a dynamic page with a single list widget.\",\n \"examplePrompts\": [\n \"pagina com lista\",\n \"crie uma lista simples\",\n \"lista de registros\"\n ]\n },\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 2,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"mainList\",\n \"definition\": {\n \"id\": \"praxis-list\",\n \"inputs\": {\n \"listId\": \"{{resourceKey}}-list\",\n \"config\": {\n \"dataSource\": { \"resourcePath\": \"{{resourcePath}}\" },\n \"layout\": { \"variant\": \"list\", \"lines\": 2, \"dividers\": \"between\", \"pageSize\": 10 }\n }\n },\n \"outputs\": { \"itemClick\": \"emit\", \"selectionChange\": \"emit\" }\n }\n }\n ]\n }\n}\n",
3173
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.list.json",
3186
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.list.json",
3174
3187
  "contentHash": "738b880df63e1e4ba04a65b452d76fd9d8044573d8e177be5f35e69da50ecf62",
3175
3188
  "sourceKind": "component_definition",
3176
3189
  "sourceId": "praxis-dynamic-page",
@@ -3180,7 +3193,7 @@
3180
3193
  "chunkIndex": 29,
3181
3194
  "chunkKind": "recipe",
3182
3195
  "content": "{\n \"_comment\": \"Template master-detail com lista de enderecos e formulario de detalhe.\",\n \"_comment2\": \"resourcePath deve ser o path base do recurso (sem /filter).\",\n \"_comment3\": \"A lista de enderecos usa dataSource.query para filtrar pelo campo de relacao.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"master-detail-address\",\n \"label\": \"Master-detail + enderecos (lista + formulario)\",\n \"description\": \"Cria tabela e formulario do recurso principal e adiciona lista+form de enderecos relacionados.\",\n \"useWhen\": \"Create a master-detail page with address list + address detail form.\",\n \"examplePrompts\": [\n \"master-detail com lista de enderecos\",\n \"tabela funcionarios com detalhes e enderecos\",\n \"master detail + enderecos\"\n ]\n },\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 2,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"_comment\": \"Tabela principal (master). Colunas sao geradas dinamicamente.\",\n \"key\": \"masterTable\",\n \"definition\": {\n \"id\": \"praxis-table\",\n \"bindingOrder\": [\"config\", \"resourcePath\"],\n \"inputs\": {\n \"resourcePath\": \"{{resourcePath}}\",\n \"tableId\": \"{{resourceKey}}-master\",\n \"config\": {\n \"toolbar\": { \"visible\": true, \"title\": \"{{resourceLabel}}\" },\n \"behavior\": { \"selection\": { \"enabled\": true, \"type\": \"single\" } }\n }\n },\n \"outputs\": { \"rowClick\": \"emit\" }\n }\n },\n {\n \"_comment\": \"Formulario de detalhes do recurso principal.\",\n \"key\": \"detailForm\",\n \"definition\": {\n \"id\": \"praxis-dynamic-form\",\n \"bindingOrder\": [\"resourcePath\", \"formId\", \"resourceId\"],\n \"inputs\": {\n \"formId\": \"{{resourceKey}}-detail-view\",\n \"resourcePath\": \"{{resourcePath}}\",\n \"mode\": \"view\"\n }\n }\n },\n {\n \"_comment\": \"Lista de enderecos em cards. O filtro sera preenchido pela relacao.\",\n \"key\": \"addressList\",\n \"definition\": {\n \"id\": \"praxis-list\",\n \"inputs\": {\n \"listId\": \"{{resourceKey}}-address-list\",\n \"config\": {\n \"dataSource\": {\n \"resourcePath\": \"{{addressResourcePath}}\",\n \"query\": {}\n },\n \"layout\": {\n \"variant\": \"cards\",\n \"lines\": 2,\n \"dividers\": \"between\",\n \"pageSize\": 6\n },\n \"selection\": {\n \"mode\": \"single\",\n \"return\": \"id\",\n \"compareBy\": \"id\"\n }\n }\n },\n \"outputs\": { \"selectionChange\": \"emit\", \"itemClick\": \"emit\" }\n }\n },\n {\n \"_comment\": \"Formulario de detalhes do endereco selecionado.\",\n \"key\": \"addressForm\",\n \"definition\": {\n \"id\": \"praxis-dynamic-form\",\n \"bindingOrder\": [\"resourcePath\", \"formId\", \"resourceId\"],\n \"inputs\": {\n \"formId\": \"{{resourceKey}}-address-detail\",\n \"resourcePath\": \"{{addressResourcePath}}\",\n \"mode\": \"view\"\n }\n }\n }\n ],\n \"connections\": [\n {\n \"_comment\": \"Seleciona registro principal no formulario.\",\n \"from\": { \"widget\": \"masterTable\", \"output\": \"rowClick\" },\n \"to\": { \"widget\": \"detailForm\", \"input\": \"resourceId\" },\n \"map\": \"payload.row.{{idField}}\"\n },\n {\n \"_comment\": \"Filtra a lista de enderecos pelo campo de relacao.\",\n \"from\": { \"widget\": \"masterTable\", \"output\": \"rowClick\" },\n \"to\": { \"widget\": \"addressList\", \"input\": \"inputs.config.dataSource.query\" },\n \"map\": \"{\\\"{{relationField}}\\\":\\\"${payload.row.{{idField}}}\\\"}\"\n },\n {\n \"_comment\": \"Quando selecionar um endereco, abre detalhes no formulario.\",\n \"from\": { \"widget\": \"addressList\", \"output\": \"selectionChange\" },\n \"to\": { \"widget\": \"addressForm\", \"input\": \"resourceId\" },\n \"map\": \"payload.value\"\n }\n ]\n }\n}\n",
3183
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.master-detail-address.json",
3196
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.master-detail-address.json",
3184
3197
  "contentHash": "8baf5a6b179c2eb1927d94060df390557b2d133b52cf59366dcdb27dffacc0a6",
3185
3198
  "sourceKind": "component_definition",
3186
3199
  "sourceId": "praxis-dynamic-page",
@@ -3190,7 +3203,7 @@
3190
3203
  "chunkIndex": 30,
3191
3204
  "chunkKind": "recipe",
3192
3205
  "content": "{\n \"_comment\": \"Template master-detail para Praxis Dynamic Page.\",\n \"_comment2\": \"resourcePath deve ser o path base do recurso (sem /filter).\",\n \"_comment3\": \"Tabela e formulario podem gerar campos dinamicamente via resourcePath (nao defina columns/sections se nao precisar).\",\n \"_comment4\": \"Rich content hospedado pela pagina pode expor contexto editorial e actions mediadas por host, mas hostCapabilities nunca deve ser serializado no JSON persistido.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"master-detail\",\n \"useWhen\": \"Create a master-detail page with table, detail form and hosted editorial guidance.\",\n \"examplePrompts\": [\n \"pagina master detail de funcionarios\",\n \"criar tabela + formulario com detalhes\",\n \"conectar tabela ao formulario de detalhes\",\n \"adicionar contexto editorial governado por rich content em uma pagina master-detail\"\n ]\n },\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 3,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"masterTable\",\n \"definition\": {\n \"id\": \"praxis-table\",\n \"bindingOrder\": [\"config\", \"resourcePath\"],\n \"inputs\": {\n \"resourcePath\": \"{{resourcePath}}\",\n \"tableId\": \"{{resourceKey}}-master\",\n \"config\": {\n \"toolbar\": { \"visible\": true, \"title\": \"{{resourceLabel}}\" },\n \"behavior\": { \"selection\": { \"enabled\": true, \"type\": \"single\" } }\n }\n },\n \"outputs\": { \"rowClick\": \"emit\" }\n }\n },\n {\n \"key\": \"detailForm\",\n \"definition\": {\n \"id\": \"praxis-dynamic-form\",\n \"bindingOrder\": [\"resourcePath\", \"formId\", \"resourceId\", \"config\"],\n \"inputs\": {\n \"formId\": \"{{resourceKey}}-detail-view\",\n \"resourcePath\": \"{{resourcePath}}\",\n \"mode\": \"view\",\n \"config\": {\n \"formBlocksBefore\": {\n \"kind\": \"praxis.rich-content\",\n \"version\": \"1.0.0\",\n \"nodes\": [\n {\n \"type\": \"callout\",\n \"tone\": \"info\",\n \"icon\": \"rule\",\n \"title\": \"Formulario metadata-driven\",\n \"message\": \"Use blocos rich-content para contexto, politicas e operacoes auxiliares. O payload persistido continua sendo o do formulario.\",\n \"actions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Abrir detalhes\",\n \"icon\": \"open_in_new\",\n \"variant\": \"stroked\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"openDetails\",\n \"payload\": {\n \"source\": \"dynamic-page-master-detail\",\n \"widgetKey\": \"detailForm\"\n }\n }\n }\n ]\n },\n {\n \"type\": \"disclosure\",\n \"title\": \"Bloco dependente de capability de edicao\",\n \"subtitle\": \"O host do dynamic form decide se este conteudo aparece\",\n \"appearance\": \"card\",\n \"requiresCapabilities\": [\"form.mode.edit\"],\n \"content\": [\n {\n \"type\": \"keyValueList\",\n \"layout\": \"stacked\",\n \"items\": [\n {\n \"label\": \"Capability gate\",\n \"value\": \"form.mode.edit\"\n },\n {\n \"label\": \"Regra de persistencia\",\n \"value\": \"Nao serializar hostCapabilities no config do formulario\"\n }\n ]\n }\n ]\n }\n ]\n }\n }\n },\n \"outputs\": { \"customAction\": \"emit\" }\n }\n },\n {\n \"key\": \"detailGuide\",\n \"definition\": {\n \"id\": \"praxis-rich-content\",\n \"bindingOrder\": [\"document\", \"context\"],\n \"inputs\": {\n \"context\": {\n \"workspace\": {\n \"resourceLabel\": \"{{resourceLabel}}\",\n \"selectionFlow\": \"rowClick -> resourceId\",\n \"runtimeRule\": \"hostCapabilities sao apenas runtime do host\"\n }\n },\n \"document\": {\n \"kind\": \"praxis.rich-content\",\n \"version\": \"1.0.0\",\n \"nodes\": [\n {\n \"type\": \"recordSummary\",\n \"title\": \"Master-detail governed by configuration\",\n \"subtitleExpr\": \"${workspace.resourceLabel}\",\n \"meta\": \"praxis-dynamic-page\",\n \"fields\": [\n {\n \"label\": \"Selection flow\",\n \"valueExpr\": \"${workspace.selectionFlow}\"\n },\n {\n \"label\": \"Runtime note\",\n \"valueExpr\": \"${workspace.runtimeRule}\"\n }\n ]\n },\n {\n \"type\": \"statGroup\",\n \"title\": \"Workspace signals\",\n \"subtitle\": \"Portable summary blocks alongside the master-detail flow\",\n \"layout\": \"inline\",\n \"items\": [\n {\n \"label\": \"Selection flow\",\n \"value\": \"1\",\n \"captionExpr\": \"${workspace.selectionFlow}\",\n \"icon\": \"swap_horiz\"\n },\n {\n \"label\": \"Runtime contract\",\n \"value\": \"host\",\n \"captionExpr\": \"${workspace.runtimeRule}\",\n \"icon\": \"verified_user\"\n }\n ]\n },\n {\n \"type\": \"tabs\",\n \"title\": \"Workspace views\",\n \"subtitle\": \"Canonical editorial tabs hosted alongside the table and detail form.\",\n \"appearance\": \"pills\",\n \"defaultTabId\": \"overview\",\n \"items\": [\n {\n \"id\": \"overview\",\n \"label\": \"Overview\",\n \"icon\": \"dashboard\",\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": \"Use tabs when the same portable rich-content document needs multiple editorial panels near the master-detail flow.\"\n }\n ]\n },\n {\n \"id\": \"runtime\",\n \"label\": \"Runtime\",\n \"icon\": \"verified_user\",\n \"badge\": \"Host\",\n \"content\": [\n {\n \"type\": \"keyValueList\",\n \"layout\": \"stacked\",\n \"items\": [\n {\n \"label\": \"Selection flow\",\n \"valueExpr\": \"${workspace.selectionFlow}\"\n },\n {\n \"label\": \"Runtime rule\",\n \"valueExpr\": \"${workspace.runtimeRule}\"\n },\n {\n \"label\": \"Persistence rule\",\n \"value\": \"hostCapabilities stay outside persisted page JSON.\"\n }\n ]\n }\n ]\n }\n ]\n },\n {\n \"type\": \"ctaGroup\",\n \"title\": \"Next steps\",\n \"subtitle\": \"Governed actions for the selected record\",\n \"message\": \"Cluster primary and secondary host-mediated actions without inventing page-specific markup.\",\n \"layout\": \"split\",\n \"actions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Open selected funcionario\",\n \"icon\": \"open_in_new\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"openDetails\",\n \"payload\": {\n \"source\": \"dynamic-page-master-detail\",\n \"widgetKey\": \"detailGuide\",\n \"resourceKey\": \"{{resourceKey}}\"\n }\n }\n },\n {\n \"type\": \"actionButton\",\n \"label\": \"Inspecionar workspace\",\n \"icon\": \"manage_search\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"inspectMasterDetailWorkspace\",\n \"payload\": {\n \"resourceKey\": \"{{resourceKey}}\"\n }\n }\n }\n ]\n },\n {\n \"type\": \"emptyState\",\n \"icon\": \"integration_instructions\",\n \"title\": \"Use hosted editorial actions for auxiliary flows\",\n \"message\": \"O widget rich-content pode acionar fluxos governados pelo host sem misturar handlers no documento.\",\n \"actions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Inspecionar workspace\",\n \"icon\": \"manage_search\",\n \"variant\": \"flat\",\n \"action\": {\n \"actionId\": \"inspectMasterDetailWorkspace\",\n \"payload\": {\n \"resourceKey\": \"{{resourceKey}}\"\n }\n }\n }\n ]\n },\n {\n \"type\": \"relatedRecord\",\n \"title\": \"Selected related record\",\n \"subtitleExpr\": \"${workspace.resourceLabel}\",\n \"relationLabel\": \"Current selection\",\n \"meta\": \"resolved relationship\",\n \"ctaLabel\": \"Open related funcionario\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"openDetails\",\n \"payload\": {\n \"source\": \"dynamic-page-master-detail\",\n \"widgetKey\": \"detailGuide\",\n \"resourceKey\": \"{{resourceKey}}\"\n }\n },\n \"fields\": [\n {\n \"label\": \"Selection binding\",\n \"valueExpr\": \"${workspace.selectionFlow}\",\n \"hint\": \"Resolved from the same selected record context.\"\n }\n ],\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Inspecionar workspace\",\n \"icon\": \"manage_search\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"inspectMasterDetailWorkspace\",\n \"payload\": {\n \"resourceKey\": \"{{resourceKey}}\"\n }\n }\n }\n ]\n },\n {\n \"type\": \"actionCard\",\n \"title\": \"Open governed funcionario flow\",\n \"subtitleExpr\": \"${workspace.resourceLabel}\",\n \"message\": \"Use the same canonical rich-content document to launch a governed host action from the master-detail workspace.\",\n \"meta\": \"host-mediated action\",\n \"ctaLabel\": \"Open governed funcionario flow\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"openDetails\",\n \"payload\": {\n \"source\": \"dynamic-page-master-detail\",\n \"widgetKey\": \"detailGuide\",\n \"resourceKey\": \"{{resourceKey}}\"\n }\n },\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Inspecionar workspace\",\n \"icon\": \"manage_search\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"inspectMasterDetailWorkspace\",\n \"payload\": {\n \"resourceKey\": \"{{resourceKey}}\"\n }\n }\n }\n ]\n }\n ]\n }\n }\n }\n }\n ],\n \"connections\": [\n {\n \"_comment\": \"Ao clicar na linha, envia o ID para o formulario.\",\n \"from\": { \"widget\": \"masterTable\", \"output\": \"rowClick\" },\n \"to\": { \"widget\": \"detailForm\", \"input\": \"resourceId\" },\n \"map\": \"payload.row.{{idField}}\"\n }\n ]\n }\n}\n",
3193
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.master-detail.json",
3206
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.master-detail.json",
3194
3207
  "contentHash": "0ce142f53a684f2b917e560490a89f0722caa33508bef8e0c0554df3fa3bf770",
3195
3208
  "sourceKind": "component_definition",
3196
3209
  "sourceId": "praxis-dynamic-page",
@@ -3200,7 +3213,7 @@
3200
3213
  "chunkIndex": 31,
3201
3214
  "chunkKind": "recipe",
3202
3215
  "content": "{\n \"_comment\": \"Recipe end-to-end para agentes criarem uma Praxis Dynamic Page rica contra o quickstart publicado.\",\n \"_comment2\": \"Use este recipe quando a meta for demonstrar contrato metadata-driven + runtime Angular + API de referencia + superficies publicas.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"mission-command-center\",\n \"status\": \"golden-fixture\",\n \"useWhen\": \"Create an end-to-end operational page that composes backend metadata, tables, charts, actions, capabilities, and cross-widget state.\",\n \"examplePrompts\": [\n \"crie um command center de missoes com tabelas, graficos e actions\",\n \"monte uma pagina end-to-end usando quickstart, surfaces e capabilities\",\n \"gere um dashboard operacional metadata-driven para missoes\"\n ]\n },\n \"platformValue\": {\n \"canonicalContract\": \"praxis-metadata-starter defines resource, schemas.filtered, surfaces, actions, capabilities, and stats semantics.\",\n \"referenceApi\": \"praxis-api-quickstart exposes operational mission resources on Render.\",\n \"referenceRepository\": \"https://github.com/codexrodrigues/praxis-api-quickstart-public\",\n \"angularRuntime\": \"@praxisui/core resolves praxis-dynamic-page widgets and composes tables/charts without bespoke host code.\",\n \"publicExamples\": \"praxis-ui-landing-page publishes the JSON envelope and runtime preview.\",\n \"agentCorpus\": \"praxisui-http-examples provides executable HTTP evidence for LLMs and agents.\"\n },\n \"operationalEvidence\": {\n \"baseUrl\": \"https://praxis-api-quickstart.onrender.com\",\n \"httpExamples\": [\n \"praxisui-http-examples/http/metadata/schemas_catalog.http\",\n \"praxisui-http-examples/http/metadata/schemas_surfaces_operations_missoes.http\",\n \"praxisui-http-examples/http/metadata/schemas_actions_operations_missoes.http\",\n \"praxisui-http-examples/http/operations/missoes_item_capabilities.http\",\n \"praxisui-http-examples/http/metadata/filtered_schema_response_funcionarios.http\",\n \"praxisui-http-examples/http/views/vw_resumo_missoes_filter_basic.http\",\n \"praxisui-http-examples/http/views/vw_resumo_missoes_stats_status.http\",\n \"praxisui-http-examples/http/operations/missao_participantes_stats_papel.http\",\n \"praxisui-http-examples/http/operations/missao_eventos_stats_ocorrido_em_day.http\"\n ],\n \"safeFirstIds\": [\n \"schemas-catalog\",\n \"schemas-surfaces-operations-missoes\",\n \"schemas-actions-operations-missoes\",\n \"operations-missoes-item-capabilities\",\n \"vw-resumo-missoes-filter-basic\",\n \"vw-resumo-missoes-stats-status\",\n \"missao-participantes-stats-papel\",\n \"missao-eventos-stats-ocorrido-em-day\"\n ],\n \"publishedAnalyticsIds\": [\n \"vw-resumo-missoes-stats-status\",\n \"missao-participantes-stats-papel\",\n \"missao-eventos-stats-ocorrido-em-day\"\n ]\n },\n \"authoringGuidance\": [\n \"Start from metadata discovery before inventing columns or filters.\",\n \"Use resourcePath without /filter in runtime widgets.\",\n \"Use statsPath only inside chart dataSource.query when the backend advertises stats support.\",\n \"Expose backend surfaces and action catalogs as discovery toolbar actions.\",\n \"Executable workflow row actions are allowed in this example because the landing host mediates execution against the published endpoint and shows success, conflict, or protected-command feedback.\",\n \"Use composition links for cross-filtering and state writes; do not duplicate state in unrelated widgets.\"\n ],\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 3,\n \"gap\": \"16px\"\n },\n \"state\": {\n \"values\": {\n \"selection\": {\n \"missionId\": 1\n }\n }\n },\n \"widgets\": [\n {\n \"key\": \"missionStatusChart\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"bar_chart\",\n \"title\": \"Mission status mix\",\n \"subtitle\": \"Remote stats projection from the published quickstart\"\n },\n \"definition\": {\n \"id\": \"praxis-chart\",\n \"bindingOrder\": [\"config\"],\n \"inputs\": {\n \"config\": {\n \"id\": \"mission-status-mix\",\n \"type\": \"horizontal-bar\",\n \"dataSource\": {\n \"kind\": \"remote\",\n \"resourcePath\": \"operations/vw-resumo-missoes\",\n \"query\": {\n \"sourceKind\": \"praxis.stats\",\n \"statsOperation\": \"group-by\",\n \"statsPath\": \"/api/operations/vw-resumo-missoes/stats/group-by\",\n \"statsRequest\": {\n \"filter\": {},\n \"field\": \"status\",\n \"metric\": {\n \"operation\": \"COUNT\",\n \"alias\": \"missions\"\n },\n \"limit\": 10,\n \"orderBy\": \"KEY_ASC\"\n }\n }\n },\n \"axes\": {\n \"x\": {\n \"field\": \"status\",\n \"type\": \"category\",\n \"label\": \"Status\"\n },\n \"y\": {\n \"field\": \"missions\",\n \"type\": \"value\",\n \"label\": \"Missions\"\n }\n },\n \"series\": [\n {\n \"id\": \"missions\",\n \"name\": \"Missions\",\n \"metric\": {\n \"field\": \"missions\",\n \"aggregation\": \"sum\"\n }\n }\n ],\n \"interactions\": {\n \"pointClick\": true,\n \"selection\": true,\n \"crossFilter\": true,\n \"eventActions\": {\n \"selectionChange\": {\n \"action\": \"emit\",\n \"mapping\": {\n \"status\": \"status\"\n }\n },\n \"crossFilter\": {\n \"action\": \"filter-widget\",\n \"target\": \"missionSummary\",\n \"mapping\": {\n \"status\": \"status\"\n }\n }\n }\n }\n }\n },\n \"outputs\": {\n \"pointClick\": \"emit\",\n \"selectionChange\": \"emit\",\n \"crossFilter\": \"emit\"\n }\n }\n },\n {\n \"key\": \"missionSummary\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"radar\",\n \"title\": \"Mission portfolio\",\n \"subtitle\": \"Aggregated mission status and threat context\"\n },\n \"definition\": {\n \"id\": \"praxis-table\",\n \"bindingOrder\": [\"config\", \"resourcePath\"],\n \"inputs\": {\n \"resourcePath\": \"operations/vw-resumo-missoes\",\n \"tableId\": \"operations-vw-resumo-missoes-command-center\",\n \"config\": {\n \"meta\": {\n \"idField\": \"missaoId\"\n },\n \"toolbar\": {\n \"visible\": true,\n \"title\": \"Mission portfolio\",\n \"actions\": [\n {\n \"id\": \"inspect-surfaces\",\n \"label\": \"Surfaces\",\n \"icon\": \"layers\",\n \"action\": \"inspect-surfaces\",\n \"discovery\": {\n \"rel\": \"surfaces\",\n \"scope\": \"resource\",\n \"resourcePath\": \"operations/vw-resumo-missoes\",\n \"resourceKey\": \"operations.vw-resumo-missoes\"\n }\n },\n {\n \"id\": \"inspect-actions\",\n \"label\": \"Actions\",\n \"icon\": \"bolt\",\n \"action\": \"inspect-actions\",\n \"discovery\": {\n \"rel\": \"actions\",\n \"scope\": \"resource\",\n \"resourcePath\": \"operations/vw-resumo-missoes\",\n \"resourceKey\": \"operations.vw-resumo-missoes\"\n }\n }\n ]\n },\n \"columns\": [\n {\n \"field\": \"titulo\",\n \"header\": \"Mission\",\n \"type\": \"text\",\n \"sticky\": \"start\"\n },\n {\n \"field\": \"status\",\n \"header\": \"Status\",\n \"type\": \"badge\"\n },\n {\n \"field\": \"prioridade\",\n \"header\": \"Priority\",\n \"type\": \"badge\"\n },\n {\n \"field\": \"ameaca\",\n \"header\": \"Threat\",\n \"type\": \"text\"\n }\n ],\n \"behavior\": {\n \"selection\": {\n \"enabled\": true,\n \"type\": \"single\"\n }\n }\n }\n },\n \"outputs\": {\n \"rowClick\": \"emit\",\n \"toolbarAction\": \"emit\"\n }\n }\n },\n {\n \"key\": \"missionWorkflow\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"bolt\",\n \"title\": \"Workflow actions\",\n \"subtitle\": \"Host-mediated actions declared by the mission controller contract\"\n },\n \"definition\": {\n \"id\": \"praxis-table\",\n \"bindingOrder\": [\"config\", \"resourcePath\", \"queryContext\"],\n \"inputs\": {\n \"resourcePath\": \"operations/missoes\",\n \"tableId\": \"operations-missoes-workflow-actions\",\n \"queryContext\": {\n \"filters\": {}\n },\n \"config\": {\n \"toolbar\": {\n \"visible\": true,\n \"title\": \"Mission workflow\",\n \"actions\": [\n {\n \"id\": \"inspect-surfaces\",\n \"label\": \"Surfaces\",\n \"icon\": \"layers\",\n \"action\": \"inspect-surfaces\",\n \"discovery\": {\n \"rel\": \"surfaces\",\n \"scope\": \"resource\",\n \"resourcePath\": \"operations/missoes\",\n \"resourceKey\": \"operations.missoes\"\n }\n },\n {\n \"id\": \"inspect-actions\",\n \"label\": \"Actions\",\n \"icon\": \"bolt\",\n \"action\": \"inspect-actions\",\n \"discovery\": {\n \"rel\": \"actions\",\n \"scope\": \"resource\",\n \"resourcePath\": \"operations/missoes\",\n \"resourceKey\": \"operations.missoes\"\n }\n }\n ]\n },\n \"actions\": {\n \"row\": {\n \"enabled\": true,\n \"display\": \"buttons\",\n \"width\": \"360px\",\n \"maxVisibleActions\": 3,\n \"behavior\": {\n \"maxInline\": 3\n },\n \"position\": \"end\",\n \"header\": {\n \"label\": \"Workflow\",\n \"icon\": \"bolt\"\n },\n \"actions\": [\n {\n \"id\": \"start\",\n \"action\": \"start\",\n \"label\": \"Start\",\n \"icon\": \"play_arrow\",\n \"visibleWhen\": {\n \"===\": [\n {\n \"var\": \"status\"\n },\n \"PLANEJADA\"\n ]\n },\n \"endpoint\": {\n \"method\": \"POST\",\n \"pathTemplate\": \"/api/operations/missoes/{id}/actions/start\",\n \"resourcePath\": \"operations/missoes\",\n \"resourceKey\": \"operations.missoes\"\n }\n },\n {\n \"id\": \"pause\",\n \"action\": \"pause\",\n \"label\": \"Pause\",\n \"icon\": \"pause\",\n \"visibleWhen\": {\n \"===\": [\n {\n \"var\": \"status\"\n },\n \"EM_ANDAMENTO\"\n ]\n },\n \"endpoint\": {\n \"method\": \"POST\",\n \"pathTemplate\": \"/api/operations/missoes/{id}/actions/pause\",\n \"resourcePath\": \"operations/missoes\",\n \"resourceKey\": \"operations.missoes\"\n }\n },\n {\n \"id\": \"resume\",\n \"action\": \"resume\",\n \"label\": \"Resume\",\n \"icon\": \"replay\",\n \"visibleWhen\": {\n \"===\": [\n {\n \"var\": \"status\"\n },\n \"PAUSADA\"\n ]\n },\n \"endpoint\": {\n \"method\": \"POST\",\n \"pathTemplate\": \"/api/operations/missoes/{id}/actions/resume\",\n \"resourcePath\": \"operations/missoes\",\n \"resourceKey\": \"operations.missoes\"\n }\n },\n {\n \"id\": \"complete\",\n \"action\": \"complete\",\n \"label\": \"Complete\",\n \"icon\": \"task_alt\",\n \"visibleWhen\": {\n \"===\": [\n {\n \"var\": \"status\"\n },\n \"EM_ANDAMENTO\"\n ]\n },\n \"endpoint\": {\n \"method\": \"POST\",\n \"pathTemplate\": \"/api/operations/missoes/{id}/actions/complete\",\n \"resourcePath\": \"operations/missoes\",\n \"resourceKey\": \"operations.missoes\"\n }\n }\n ]\n }\n },\n \"behavior\": {\n \"selection\": {\n \"enabled\": true,\n \"type\": \"single\"\n }\n }\n }\n },\n \"outputs\": {\n \"rowClick\": \"emit\",\n \"rowAction\": \"emit\",\n \"toolbarAction\": \"emit\"\n }\n }\n },\n {\n \"key\": \"missionTeam\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"groups\",\n \"title\": \"Mission team\",\n \"subtitle\": \"Participants, roles and outcomes\"\n },\n \"definition\": {\n \"id\": \"praxis-table\",\n \"bindingOrder\": [\"config\", \"resourcePath\", \"queryContext\"],\n \"inputs\": {\n \"resourcePath\": \"operations/missao-participantes\",\n \"tableId\": \"operations-missao-participantes-command-center\",\n \"queryContext\": {\n \"filters\": {\n \"missaoId\": 1\n }\n },\n \"config\": {\n \"toolbar\": {\n \"visible\": true,\n \"title\": \"Mission team\"\n },\n \"columns\": [\n {\n \"field\": \"ordem\",\n \"header\": \"Order\",\n \"type\": \"number\"\n },\n {\n \"field\": \"funcionarioNome\",\n \"header\": \"Hero\",\n \"type\": \"text\",\n \"sticky\": \"start\"\n },\n {\n \"field\": \"papel\",\n \"header\": \"Role\",\n \"type\": \"badge\"\n },\n {\n \"field\": \"resultado\",\n \"header\": \"Outcome\",\n \"type\": \"badge\"\n }\n ]\n }\n },\n \"outputs\": {\n \"rowClick\": \"emit\",\n \"toolbarAction\": \"emit\"\n }\n }\n },\n {\n \"key\": \"missionTimeline\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"timeline\",\n \"title\": \"Mission timeline\",\n \"subtitle\": \"Governed event surface for selected mission\"\n },\n \"definition\": {\n \"id\": \"praxis-table\",\n \"bindingOrder\": [\"config\", \"resourcePath\", \"queryContext\"],\n \"inputs\": {\n \"resourcePath\": \"operations/missao-eventos\",\n \"tableId\": \"operations-missao-eventos-command-center\",\n \"queryContext\": {\n \"filters\": {\n \"missaoId\": 1\n }\n },\n \"config\": {\n \"toolbar\": {\n \"visible\": true,\n \"title\": \"Mission timeline\"\n },\n \"columns\": [\n {\n \"field\": \"ordem\",\n \"header\": \"Order\",\n \"type\": \"number\"\n },\n {\n \"field\": \"tipo\",\n \"header\": \"Type\",\n \"type\": \"text\",\n \"sticky\": \"start\"\n },\n {\n \"field\": \"descricao\",\n \"header\": \"Event\",\n \"type\": \"text\"\n },\n {\n \"field\": \"ocorridoEm\",\n \"header\": \"Occurred at\",\n \"type\": \"date-time\"\n }\n ]\n }\n },\n \"outputs\": {\n \"rowClick\": \"emit\",\n \"toolbarAction\": \"emit\"\n }\n }\n }\n ],\n \"composition\": {\n \"version\": \"1.0.0\",\n \"links\": [\n {\n \"id\": \"missions:status-chart-crossFilter->summary.queryContext\",\n \"intent\": \"data-projection\",\n \"from\": {\n \"kind\": \"component-port\",\n \"ref\": {\n \"widget\": \"missionStatusChart\",\n \"port\": \"crossFilter\",\n \"direction\": \"output\",\n \"componentType\": \"praxis-chart\"\n }\n },\n \"to\": {\n \"kind\": \"component-port\",\n \"ref\": {\n \"widget\": \"missionSummary\",\n \"port\": \"queryContext\",\n \"direction\": \"input\",\n \"componentType\": \"praxis-table\"\n }\n },\n \"transform\": {\n \"version\": \"2.0\",\n \"phase\": \"link-propagation\",\n \"mode\": \"object-fragment\",\n \"sourceBindings\": [\n {\n \"source\": \"event\"\n }\n ],\n \"steps\": [\n {\n \"id\": \"missions:pick-status-filter-for-summary\",\n \"kind\": \"object-template\",\n \"phase\": \"link-propagation\",\n \"input\": {\n \"source\": \"event\"\n },\n \"config\": {\n \"template\": {\n \"filters\": {\n \"status\": \"${payload.filters.status}\"\n }\n }\n }\n }\n ]\n }\n },\n {\n \"id\": \"missions:summary-rowClick->state:selection.missionId\",\n \"intent\": \"state-write\",\n \"from\": {\n \"kind\": \"component-port\",\n \"ref\": {\n \"widget\": \"missionSummary\",\n \"port\": \"rowClick\",\n \"direction\": \"output\",\n \"componentType\": \"praxis-table\"\n }\n },\n \"to\": {\n \"kind\": \"state\",\n \"ref\": {\n \"path\": \"selection.missionId\",\n \"layer\": \"values\",\n \"writable\": true\n }\n },\n \"transform\": {\n \"version\": \"2.0\",\n \"phase\": \"link-propagation\",\n \"mode\": \"single-value\",\n \"sourceBindings\": [\n {\n \"source\": \"event\"\n }\n ],\n \"steps\": [\n {\n \"id\": \"missions:pick-mission-id\",\n \"kind\": \"pick-path\",\n \"phase\": \"link-propagation\",\n \"input\": {\n \"source\": \"event\"\n },\n \"config\": {\n \"path\": \"payload.row.id\"\n }\n }\n ]\n }\n },\n {\n \"id\": \"missions:state:selection.missionId->team.queryContext\",\n \"intent\": \"state-read\",\n \"from\": {\n \"kind\": \"state\",\n \"ref\": {\n \"path\": \"selection.missionId\",\n \"layer\": \"values\"\n }\n },\n \"to\": {\n \"kind\": \"component-port\",\n \"ref\": {\n \"widget\": \"missionTeam\",\n \"port\": \"queryContext\",\n \"direction\": \"input\",\n \"componentType\": \"praxis-table\"\n }\n },\n \"transform\": {\n \"version\": \"2.0\",\n \"phase\": \"link-propagation\",\n \"mode\": \"object-fragment\",\n \"sourceBindings\": [\n {\n \"source\": \"state\",\n \"path\": \"selection.missionId\"\n }\n ],\n \"steps\": [\n {\n \"id\": \"missions:mission-id-to-team-filter\",\n \"kind\": \"object-template\",\n \"phase\": \"link-propagation\",\n \"config\": {\n \"template\": {\n \"filters\": {\n \"missaoId\": \"${source}\"\n }\n }\n }\n }\n ]\n }\n },\n {\n \"id\": \"missions:state:selection.missionId->timeline.queryContext\",\n \"intent\": \"state-read\",\n \"from\": {\n \"kind\": \"state\",\n \"ref\": {\n \"path\": \"selection.missionId\",\n \"layer\": \"values\"\n }\n },\n \"to\": {\n \"kind\": \"component-port\",\n \"ref\": {\n \"widget\": \"missionTimeline\",\n \"port\": \"queryContext\",\n \"direction\": \"input\",\n \"componentType\": \"praxis-table\"\n }\n },\n \"transform\": {\n \"version\": \"2.0\",\n \"phase\": \"link-propagation\",\n \"mode\": \"object-fragment\",\n \"sourceBindings\": [\n {\n \"source\": \"state\",\n \"path\": \"selection.missionId\"\n }\n ],\n \"steps\": [\n {\n \"id\": \"missions:mission-id-to-timeline-filter\",\n \"kind\": \"object-template\",\n \"phase\": \"link-propagation\",\n \"config\": {\n \"template\": {\n \"filters\": {\n \"missaoId\": \"${source}\"\n }\n }\n }\n }\n ]\n }\n }\n ]\n }\n }\n}\n",
3203
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.mission-command-center.json",
3216
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.mission-command-center.json",
3204
3217
  "contentHash": "d5a5e27453d59243c508adb9b5c58c6ee18ca594dbd3853383d252e7e96eaeb8",
3205
3218
  "sourceKind": "component_definition",
3206
3219
  "sourceId": "praxis-dynamic-page",
@@ -3210,7 +3223,7 @@
3210
3223
  "chunkIndex": 32,
3211
3224
  "chunkKind": "recipe",
3212
3225
  "content": "{\n \"_comment\": \"Golden recipe for nested component ports in Praxis Dynamic Page.\",\n \"_comment2\": \"Use only composition.links with component-port + nestedPath; do not use page.connections, bindingPath or widgetEvent as the final contract.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"nested-path-showcase\",\n \"status\": \"golden-fixture\",\n \"useWhen\": \"Create a dynamic page that demonstrates canonical nested component ports through an operational mission command workspace.\",\n \"examplePrompts\": [\n \"create a nestedPath example where selecting a mission updates summary, team and timeline tabs\",\n \"build a dynamic page using component-port nestedPath against the published operations quickstart\"\n ]\n },\n \"platformValue\": {\n \"canonicalContract\": \"@praxisui/core owns CompositionLink, component-port endpoints, nestedPath, runtime delivery, validation and serialization.\",\n \"referenceApi\": \"praxis-api-quickstart exposes operations.missoes with summary, team, timeline, actions and capabilities on Render.\",\n \"angularRuntime\": \"Tabs own nested widget placement; child components keep their own public ports.\",\n \"businessFlow\": \"A selected mission becomes the shared state that drives downstream summary and team tables plus a rich-content timeline.\"\n },\n \"operationalEvidence\": {\n \"baseUrl\": \"https://praxis-api-quickstart.onrender.com\",\n \"resources\": [\n \"api/operations/missoes\",\n \"api/operations/vw-resumo-missoes\",\n \"api/operations/missao-participantes\"\n ],\n \"safeFirstIds\": [\n \"schemas-surfaces-operations-missoes\",\n \"schemas-actions-operations-missoes\",\n \"operations-missoes-item-capabilities\",\n \"vw-resumo-missoes-filter-basic\",\n \"missao-participantes-stats-papel\"\n ]\n },\n \"authoringGuidance\": [\n \"Persist links only under page.composition.links.\",\n \"Use ref.kind component-port with ref.nestedPath for ports owned by nested child widgets.\",\n \"Every persisted nestedPath must end with a widget segment containing stable key and componentType.\",\n \"Use state links as the bridge between nested outputs and other nested inputs when the value must be shared.\",\n \"Keep resourcePath values as backend resource paths; the host API_URL supplies the Render origin.\"\n ],\n \"teaches\": [\n \"composition.links\",\n \"component-port.nestedPath\",\n \"tabs.nested-widgets\",\n \"table.rowClick.state-write\",\n \"state-read.nested-input\",\n \"rich-content.timeline\",\n \"transform.object-template\",\n \"lazy-mounted-input.delivery\"\n ],\n \"page\": {\n \"layout\": { \"orientation\": \"columns\", \"columns\": 1, \"gap\": \"16px\" },\n \"state\": {\n \"values\": {\n \"selection\": {\n \"missionId\": 1,\n \"missionTitle\": \"Batalha de Nova York\"\n }\n }\n },\n \"widgets\": [\n {\n \"key\": \"missionNestedWorkspace\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"account_tree\",\n \"title\": \"Mission command nestedPath workspace\",\n \"subtitle\": \"Select a mission once; summary, team and timeline tabs receive mission context through component-port + nestedPath\"\n },\n \"definition\": {\n \"id\": \"praxis-tabs\",\n \"bindingOrder\": [\"tabsId\", \"componentInstanceId\", \"config\", \"selectedIndex\"],\n \"inputs\": {\n \"tabsId\": \"nested-path-mission-workspace\",\n \"componentInstanceId\": \"nested-path-mission-workspace\",\n \"selectedIndex\": 0,\n \"config\": {\n \"appearance\": { \"density\": \"comfortable\", \"dynamicHeight\": true, \"fitInkBarToContent\": true },\n \"behavior\": { \"lazyLoad\": true, \"reorderable\": false, \"closeable\": false },\n \"tabs\": [\n {\n \"id\": \"missions\",\n \"textLabel\": \"Select mission\",\n \"icon\": \"radar\",\n \"widgets\": [\n {\n \"id\": \"praxis-table\",\n \"childWidgetKey\": \"missions-table\",\n \"bindingOrder\": [\"tableId\", \"resourcePath\", \"config\"],\n \"inputs\": {\n \"tableId\": \"nested-path-missions-table\",\n \"resourcePath\": \"operations/missoes\",\n \"config\": {\n \"toolbar\": {\n \"visible\": true,\n \"title\": \"Mission portfolio\",\n \"search\": { \"enabled\": true, \"placeholder\": \"Search by title, threat or location\" },\n \"layout\": { \"alignment\": \"space-between\", \"showSeparator\": true },\n \"actions\": [\n {\n \"id\": \"inspect-surfaces\",\n \"label\": \"Surfaces\",\n \"icon\": \"layers\",\n \"action\": \"inspect-surfaces\",\n \"discovery\": {\n \"rel\": \"surfaces\",\n \"scope\": \"resource\",\n \"resourcePath\": \"operations/missoes\",\n \"resourceKey\": \"operations.missoes\"\n }\n },\n {\n \"id\": \"inspect-actions\",\n \"label\": \"Actions\",\n \"icon\": \"bolt\",\n \"action\": \"inspect-actions\",\n \"discovery\": {\n \"rel\": \"actions\",\n \"scope\": \"resource\",\n \"resourcePath\": \"operations/missoes\",\n \"resourceKey\": \"operations.missoes\"\n }\n }\n ]\n },\n \"columns\": [\n { \"field\": \"id\", \"header\": \"ID\", \"width\": \"80px\", \"align\": \"center\" },\n { \"field\": \"titulo\", \"header\": \"Mission\", \"type\": \"text\", \"sticky\": \"start\" },\n { \"field\": \"status\", \"header\": \"Status\", \"type\": \"badge\" },\n { \"field\": \"prioridade\", \"header\": \"Priority\", \"type\": \"badge\" },\n { \"field\": \"local\", \"header\": \"Location\", \"type\": \"text\" },\n { \"field\": \"ameacaNome\", \"header\": \"Threat\", \"type\": \"text\" }\n ],\n \"behavior\": {\n \"pagination\": { \"enabled\": true, \"strategy\": \"server\", \"pageSize\": 10, \"pageSizeOptions\": [10, 25, 50], \"position\": \"bottom\" },\n \"sorting\": { \"enabled\": true, \"strategy\": \"server\", \"defaultSort\": { \"field\": \"id\", \"direction\": \"asc\" } },\n \"filtering\": { \"enabled\": true, \"strategy\": \"server\", \"advancedFilters\": { \"enabled\": true, \"fields\": [\"titulo\", \"status\", \"prioridade\", \"local\"] } },\n \"selection\": { \"enabled\": true, \"type\": \"single\", \"mode\": \"row\", \"persistSelection\": false }\n }\n }\n },\n \"outputs\": { \"rowClick\": \"emit\", \"selectionChange\": \"emit\", \"toolbarAction\": \"emit\" }\n }\n ]\n },\n {\n \"id\": \"summary\",\n \"textLabel\": \"Summary\",\n \"icon\": \"groups\",\n \"widgets\": [\n {\n \"id\": \"praxis-table\",\n \"childWidgetKey\": \"mission-summary-table\",\n \"bindingOrder\": [\"tableId\", \"resourcePath\", \"queryContext\", \"config\"],\n \"inputs\": {\n \"tableId\": \"nested-path-mission-summary-table\",\n \"resourcePath\": \"operations/vw-resumo-missoes\",\n \"queryContext\": { \"filters\": { \"missaoId\": 1 } },\n \"config\": {\n \"toolbar\": { \"visible\": true, \"title\": \"Selected mission summary\" },\n \"columns\": [\n { \"field\": \"titulo\", \"header\": \"Mission\", \"type\": \"text\", \"sticky\": \"start\" },\n { \"field\": \"status\", \"header\": \"Status\", \"type\": \"badge\" },\n { \"field\": \"prioridade\", \"header\": \"Priority\", \"type\": \"badge\" },\n { \"field\": \"qtdHerois\", \"header\": \"Heroes\", \"type\": \"number\", \"align\": \"end\" },\n { \"field\": \"qtdEventos\", \"header\": \"Events\", \"type\": \"number\", \"align\": \"end\" }\n ],\n \"behavior\": { \"pagination\": { \"enabled\": false } }\n }\n },\n \"outputs\": { \"rowClick\": \"emit\" }\n }\n ]\n },\n {\n \"id\": \"team\",\n \"textLabel\": \"Team\",\n \"icon\": \"groups\",\n \"widgets\": [\n {\n \"id\": \"praxis-table\",\n \"childWidgetKey\": \"mission-team-table\",\n \"bindingOrder\": [\"tableId\", \"resourcePath\", \"queryContext\", \"config\"],\n \"inputs\": {\n \"tableId\": \"nested-path-mission-team-table\",\n \"resourcePath\": \"operations/missao-participantes\",\n \"queryContext\": { \"filters\": { \"missaoId\": 1 } },\n \"config\": {\n \"toolbar\": { \"visible\": true, \"title\": \"Mission team\" },\n \"columns\": [\n { \"field\": \"funcionarioNome\", \"header\": \"Participant\", \"type\": \"text\", \"sticky\": \"start\" },\n { \"field\": \"papel\", \"header\": \"Role\", \"type\": \"badge\" },\n { \"field\": \"principal\", \"header\": \"Lead\", \"type\": \"boolean\", \"width\": \"100px\", \"align\": \"center\" },\n { \"field\": \"resultado\", \"header\": \"Outcome\", \"type\": \"badge\" }\n ],\n \"behavior\": { \"pagination\": { \"enabled\": true, \"strategy\": \"server\", \"pageSize\": 5, \"pageSizeOptions\": [5, 10], \"position\": \"bottom\" } }\n }\n },\n \"outputs\": { \"rowClick\": \"emit\" }\n }\n ]\n },\n {\n \"id\": \"timeline\",\n \"textLabel\": \"Timeline\",\n \"icon\": \"timeline\",\n \"widgets\": [\n {\n \"id\": \"praxis-rich-content\",\n \"childWidgetKey\": \"mission-timeline\",\n \"bindingOrder\": [\"document\", \"context\", \"layout\", \"rootClassName\"],\n \"inputs\": {\n \"layout\": \"block\",\n \"rootClassName\": \"nested-path-mission-timeline\",\n \"context\": {\n \"selection\": {\n \"missionId\": 1,\n \"missionTitle\": \"Batalha de Nova York\"\n }\n },\n \"document\": {\n \"kind\": \"praxis.rich-content\",\n \"version\": \"1.0.0\",\n \"nodes\": [\n {\n \"type\": \"timeline\",\n \"id\": \"mission-command-timeline\",\n \"title\": \"Authored mission timeline\",\n \"emptyText\": \"Select a mission to inspect its authored operational timeline.\",\n \"orientation\": \"vertical\",\n \"position\": \"alternate\",\n \"connectorVariant\": \"dashed\",\n \"connectorColor\": \"neutral\",\n \"markerVariant\": \"icon\",\n \"markerColor\": \"info\",\n \"markerStyle\": \"filled\",\n \"items\": [\n {\n \"id\": \"mission-event-intel\",\n \"icon\": \"travel_explore\",\n \"title\": \"Pacote de inteligência consolidado\",\n \"subtitleExpr\": \"selection.missionTitle\",\n \"meta\": \"INTEL\",\n \"opposite\": \"2025-10-18T02:41:41Z\",\n \"badge\": \"grounding\",\n \"markerColor\": \"info\"\n },\n {\n \"id\": \"mission-event-contact\",\n \"icon\": \"radar\",\n \"title\": \"Contato tático ativo\",\n \"subtitle\": \"Equipe em campo confirmou o ponto de contato operacional.\",\n \"meta\": \"CONTATO\",\n \"opposite\": \"2025-10-18T09:41:42Z\",\n \"badge\": \"signal\",\n \"markerColor\": \"primary\"\n },\n {\n \"id\": \"mission-event-combat\",\n \"icon\": \"shield\",\n \"title\": \"Engajamento inicial\",\n \"subtitle\": \"Civis evacuados e perímetro sob controle.\",\n \"meta\": \"COMBATE\",\n \"opposite\": \"2025-10-18T12:41:42Z\",\n \"badge\": \"operation\",\n \"markerColor\": \"warning\"\n },\n {\n \"id\": \"mission-event-reinforcement\",\n \"icon\": \"verified\",\n \"title\": \"Reforços a caminho\",\n \"subtitle\": \"SHIELD mobilizado para sustentação da missão.\",\n \"meta\": \"EXTRA\",\n \"opposite\": \"2025-10-18T18:41:42Z\",\n \"badge\": \"support\",\n \"markerColor\": \"success\"\n }\n ]\n }\n ]\n }\n }\n }\n ]\n }\n ]\n }\n },\n \"outputs\": { \"selectedIndexChange\": \"emit\" }\n }\n }\n ],\n \"composition\": {\n \"version\": \"1.0.0\",\n \"links\": [\n {\n \"id\": \"nestedPath:missions-table.rowClick->state.selection.missionId\",\n \"intent\": \"state-write\",\n \"from\": { \"kind\": \"component-port\", \"ref\": { \"widget\": \"missionNestedWorkspace\", \"port\": \"rowClick\", \"direction\": \"output\", \"componentType\": \"praxis-table\", \"nestedPath\": [{ \"kind\": \"tab\", \"id\": \"missions\", \"index\": 0 }, { \"kind\": \"widget\", \"key\": \"missions-table\", \"componentType\": \"praxis-table\" }] } },\n \"to\": { \"kind\": \"state\", \"ref\": { \"path\": \"selection.missionId\", \"layer\": \"values\", \"writable\": true } },\n \"condition\": { \">\": [{ \"var\": \"payload.row.id\" }, 0] },\n \"transform\": { \"version\": \"2.0\", \"phase\": \"link-propagation\", \"mode\": \"single-value\", \"sourceBindings\": [{ \"source\": \"event\" }], \"steps\": [{ \"id\": \"nestedPath:pick-mission-id\", \"kind\": \"pick-path\", \"phase\": \"link-propagation\", \"input\": { \"source\": \"event\" }, \"config\": { \"path\": \"payload.row.id\" } }] },\n \"policy\": { \"missingValuePolicy\": \"skip\", \"distinct\": true, \"debounceMs\": 50 }\n },\n {\n \"id\": \"nestedPath:missions-table.rowClick->state.selection.missionTitle\",\n \"intent\": \"state-write\",\n \"from\": { \"kind\": \"component-port\", \"ref\": { \"widget\": \"missionNestedWorkspace\", \"port\": \"rowClick\", \"direction\": \"output\", \"componentType\": \"praxis-table\", \"nestedPath\": [{ \"kind\": \"tab\", \"id\": \"missions\", \"index\": 0 }, { \"kind\": \"widget\", \"key\": \"missions-table\", \"componentType\": \"praxis-table\" }] } },\n \"to\": { \"kind\": \"state\", \"ref\": { \"path\": \"selection.missionTitle\", \"layer\": \"values\", \"writable\": true } },\n \"transform\": { \"version\": \"2.0\", \"phase\": \"link-propagation\", \"mode\": \"single-value\", \"sourceBindings\": [{ \"source\": \"event\" }], \"steps\": [{ \"id\": \"nestedPath:pick-mission-title\", \"kind\": \"pick-path\", \"phase\": \"link-propagation\", \"input\": { \"source\": \"event\" }, \"config\": { \"path\": \"payload.row.titulo\" } }] },\n \"policy\": { \"missingValuePolicy\": \"skip\", \"distinct\": true, \"debounceMs\": 50 }\n },\n {\n \"id\": \"nestedPath:state.selection.missionId->summary-table.queryContext\",\n \"intent\": \"state-read\",\n \"from\": { \"kind\": \"state\", \"ref\": { \"path\": \"selection.missionId\", \"layer\": \"values\" } },\n \"to\": { \"kind\": \"component-port\", \"ref\": { \"widget\": \"missionNestedWorkspace\", \"port\": \"queryContext\", \"direction\": \"input\", \"componentType\": \"praxis-table\", \"nestedPath\": [{ \"kind\": \"tab\", \"id\": \"summary\", \"index\": 1 }, { \"kind\": \"widget\", \"key\": \"mission-summary-table\", \"componentType\": \"praxis-table\" }] } },\n \"condition\": { \">\": [{ \"var\": \"source\" }, 0] },\n \"transform\": { \"version\": \"2.0\", \"phase\": \"link-propagation\", \"mode\": \"object-fragment\", \"sourceBindings\": [{ \"source\": \"state\", \"path\": \"selection.missionId\" }], \"steps\": [{ \"id\": \"nestedPath:mission-id-to-summary-filter\", \"kind\": \"object-template\", \"phase\": \"link-propagation\", \"config\": { \"template\": { \"filters\": { \"missaoId\": \"${source}\" } } } }] },\n \"policy\": { \"missingValuePolicy\": \"skip\", \"distinct\": true }\n },\n {\n \"id\": \"nestedPath:state.selection.missionId->team-table.queryContext\",\n \"intent\": \"state-read\",\n \"from\": { \"kind\": \"state\", \"ref\": { \"path\": \"selection.missionId\", \"layer\": \"values\" } },\n \"to\": { \"kind\": \"component-port\", \"ref\": { \"widget\": \"missionNestedWorkspace\", \"port\": \"queryContext\", \"direction\": \"input\", \"componentType\": \"praxis-table\", \"nestedPath\": [{ \"kind\": \"tab\", \"id\": \"team\", \"index\": 2 }, { \"kind\": \"widget\", \"key\": \"mission-team-table\", \"componentType\": \"praxis-table\" }] } },\n \"condition\": { \">\": [{ \"var\": \"source\" }, 0] },\n \"transform\": { \"version\": \"2.0\", \"phase\": \"link-propagation\", \"mode\": \"object-fragment\", \"sourceBindings\": [{ \"source\": \"state\", \"path\": \"selection.missionId\" }], \"steps\": [{ \"id\": \"nestedPath:mission-id-to-team-filter\", \"kind\": \"object-template\", \"phase\": \"link-propagation\", \"config\": { \"template\": { \"filters\": { \"missaoId\": \"${source}\" } } } }] },\n \"policy\": { \"missingValuePolicy\": \"skip\", \"distinct\": true }\n },\n {\n \"id\": \"nestedPath:state.selection->timeline.context\",\n \"intent\": \"state-read\",\n \"from\": { \"kind\": \"state\", \"ref\": { \"path\": \"selection\", \"layer\": \"values\" } },\n \"to\": { \"kind\": \"component-port\", \"ref\": { \"widget\": \"missionNestedWorkspace\", \"port\": \"context\", \"direction\": \"input\", \"componentType\": \"praxis-rich-content\", \"nestedPath\": [{ \"kind\": \"tab\", \"id\": \"timeline\", \"index\": 3 }, { \"kind\": \"widget\", \"key\": \"mission-timeline\", \"componentType\": \"praxis-rich-content\" }] } },\n \"condition\": { \">\": [{ \"var\": \"source.missionId\" }, 0] },\n \"transform\": { \"version\": \"2.0\", \"phase\": \"link-propagation\", \"mode\": \"object-fragment\", \"sourceBindings\": [{ \"source\": \"state\", \"path\": \"selection\" }], \"steps\": [{ \"id\": \"nestedPath:selection-to-rich-timeline-context\", \"kind\": \"object-template\", \"phase\": \"link-propagation\", \"config\": { \"template\": { \"selection\": \"${source}\" } } }] },\n \"policy\": { \"missingValuePolicy\": \"skip\", \"distinct\": true }\n }\n ]\n }\n }\n}\n",
3213
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.nested-path-showcase.json",
3226
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.nested-path-showcase.json",
3214
3227
  "contentHash": "24a8bdad5fddf5da2ecba4bb8447ca6f92cd27d5ddd43c828ea55280821c3bb9",
3215
3228
  "sourceKind": "component_definition",
3216
3229
  "sourceId": "praxis-dynamic-page",
@@ -3220,7 +3233,7 @@
3220
3233
  "chunkIndex": 33,
3221
3234
  "chunkKind": "recipe",
3222
3235
  "content": "{\n \"_comment\": \"Praxis Dynamic Page recipe for an onboarding day-30 coaching workbench using portable rich-content blocks for coaching signals, manager context and governed development actions.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"onboarding-day-30-coaching-workbench\",\n \"status\": \"public-example\",\n \"useWhen\": \"Create an onboarding day-30 coaching workbench with coaching signals, manager context, goal tabs and governed development actions.\",\n \"examplePrompts\": [\n \"create an onboarding day-30 coaching workbench\",\n \"show a governed onboarding coaching rich content surface\",\n \"generate an onboarding page with day-30 goals and manager coaching actions\"\n ]\n },\n \"platformValue\": {\n \"canonicalRuntime\": \"@praxisui/rich-content owns the portable onboarding day-30 coaching surface.\",\n \"hostMediation\": \"The host mediates open, confirm, update and escalate actions through actionId contracts.\",\n \"publicExamples\": \"praxis-ui-landing-page can expose the same onboarding coaching workbench without serializing runtime helpers.\",\n \"agentCorpus\": \"This recipe keeps coaching signals, selected hire context, manager context and governed coaching actions inside RichContentDocument so agents can reuse the same semantic surface across hosts.\"\n },\n \"authoringGuidance\": [\n \"Use definition.id \\\"praxis-rich-content\\\".\",\n \"Model coaching metrics with statGroup instead of host-authored manager cards.\",\n \"Model the selected hire with lookupCard when the host already resolved the day-30 coaching context.\",\n \"Use tabs for goals and blockers instead of host-authored coaching sections.\",\n \"Use relatedRecord, ctaGroup and actionCard for governed coaching actions; keep handlers out of the document.\",\n \"Do not serialize hostCapabilities in the page JSON; the host injects runtime mediation only while rendering.\"\n ],\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 1,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"onboardingDay30CoachingWorkbench\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"psychology\",\n \"title\": \"Onboarding day-30 coaching workbench\",\n \"subtitle\": \"Portable rich-content surface for governed coaching\"\n },\n \"definition\": {\n \"id\": \"praxis-rich-content\",\n \"bindingOrder\": [\"document\", \"context\", \"layout\", \"rootClassName\"],\n \"inputs\": {\n \"layout\": \"block\",\n \"rootClassName\": \"onboarding-day-30-coaching-workbench\",\n \"context\": {\n \"hire\": {\n \"id\": \"ONB-830\",\n \"name\": \"Tiago Almeida\",\n \"role\": \"Customer Success Engineer\",\n \"department\": \"Customer platform\",\n \"focus\": \"Role clarity and first-month delivery plan\",\n \"confidence\": \"8.1\",\n \"openGoals\": \"4\",\n \"risk\": \"Medium\",\n \"pulse\": \"Needs stakeholder alignment\"\n },\n \"manager\": {\n \"name\": \"Helena Souza\",\n \"department\": \"Engineering leadership\",\n \"lane\": \"First-month development plan\"\n }\n },\n \"document\": {\n \"kind\": \"praxis.rich-content\",\n \"version\": \"1.0.0\",\n \"nodes\": [\n {\n \"type\": \"callout\",\n \"tone\": \"info\",\n \"icon\": \"psychology\",\n \"titleExpr\": \"${hire.name}\",\n \"message\": \"Use a portable onboarding day-30 coaching surface when the host must expose governed coaching and manager development actions without inventing onboarding-specific templates.\"\n },\n {\n \"type\": \"statGroup\",\n \"title\": \"Day-30 coaching signals\",\n \"subtitle\": \"Canonical KPI block for onboarding coaching surfaces\",\n \"layout\": \"grid\",\n \"items\": [\n {\n \"label\": \"Confidence\",\n \"valueExpr\": \"${hire.confidence}\",\n \"captionExpr\": \"${hire.id}\",\n \"icon\": \"psychology\"\n },\n {\n \"label\": \"Open goals\",\n \"valueExpr\": \"${hire.openGoals}\",\n \"caption\": \"Needs manager review\",\n \"icon\": \"flag\"\n },\n {\n \"label\": \"Coaching risk\",\n \"valueExpr\": \"${hire.risk}\",\n \"captionExpr\": \"${hire.pulse}\",\n \"icon\": \"report\"\n }\n ]\n },\n {\n \"type\": \"lookupCard\",\n \"title\": \"Selected hire\",\n \"status\": \"resolved\",\n \"subtitleExpr\": \"${hire.name}\",\n \"metaExpr\": \"${hire.role}\",\n \"ctaLabel\": \"Open hire\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"onboarding.day30.hire.open\",\n \"payloadExpr\": \"${hire}\"\n },\n \"fields\": [\n {\n \"label\": \"Department\",\n \"valueExpr\": \"${hire.department}\"\n },\n {\n \"label\": \"Coaching focus\",\n \"valueExpr\": \"${hire.focus}\"\n }\n ],\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Open dossier\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"onboarding.day30.dossier.open\",\n \"payloadExpr\": \"${hire}\"\n }\n }\n ]\n },\n {\n \"type\": \"tabs\",\n \"title\": \"Coaching views\",\n \"subtitle\": \"Portable editorial tabs for goals, blockers and next steps.\",\n \"appearance\": \"underline\",\n \"defaultTabId\": \"goals\",\n \"items\": [\n {\n \"id\": \"goals\",\n \"label\": \"Goals\",\n \"icon\": \"flag\",\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": \"Keep day-30 goals, first-month outcomes and coaching notes inside the same RichContentDocument.\"\n }\n ]\n },\n {\n \"id\": \"blockers\",\n \"label\": \"Blockers\",\n \"icon\": \"warning\",\n \"content\": [\n {\n \"type\": \"keyValueList\",\n \"layout\": \"stacked\",\n \"items\": [\n {\n \"label\": \"Coaching blocker\",\n \"value\": \"Stakeholder map and role expectations need a manager-led reset.\"\n },\n {\n \"label\": \"Coaching rule\",\n \"value\": \"Escalate when day-30 confidence drops below target or when two coaching goals remain unowned after manager review.\"\n }\n ]\n }\n ]\n }\n ]\n },\n {\n \"type\": \"relatedRecord\",\n \"title\": \"Coaching owner\",\n \"subtitleExpr\": \"${manager.name}\",\n \"relationLabel\": \"Manager\",\n \"metaExpr\": \"${manager.department}\",\n \"ctaLabel\": \"Open manager\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"onboarding.day30.manager.open\",\n \"payloadExpr\": \"${manager}\"\n },\n \"fields\": [\n {\n \"label\": \"Coaching lane\",\n \"valueExpr\": \"${manager.lane}\",\n \"hint\": \"Resolved from the day-30 coaching assignment context.\"\n }\n ],\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Schedule coaching sync\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"onboarding.day30.manager.scheduleSync\",\n \"payloadExpr\": \"${hire}\"\n }\n }\n ]\n },\n {\n \"type\": \"ctaGroup\",\n \"title\": \"Coaching actions\",\n \"subtitle\": \"Governed day-30 coaching outcomes\",\n \"message\": \"Use semantic coaching actions instead of host-authored onboarding manager button bars.\",\n \"layout\": \"split\",\n \"actions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Confirm coaching plan\",\n \"icon\": \"check_circle\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"onboarding.day30.coaching.confirm\",\n \"payloadExpr\": \"${hire}\"\n }\n },\n {\n \"type\": \"actionButton\",\n \"label\": \"Request goal update\",\n \"icon\": \"flag\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"onboarding.day30.goals.requestUpdate\",\n \"payloadExpr\": \"${hire}\"\n }\n }\n ]\n },\n {\n \"type\": \"actionCard\",\n \"title\": \"Escalate coaching risk\",\n \"subtitleExpr\": \"${hire.id}\",\n \"message\": \"Use actionCard when the onboarding host needs a governed escalation flow for unresolved first-month coaching risks.\",\n \"metaExpr\": \"${hire.pulse}\",\n \"ctaLabel\": \"Escalate coaching risk\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"onboarding.day30.coaching.escalate\",\n \"payloadExpr\": \"${hire}\"\n },\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Open dossier\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"onboarding.day30.dossier.open\",\n \"payloadExpr\": \"${hire}\"\n }\n }\n ]\n }\n ]\n }\n }\n }\n }\n ]\n }\n}\n",
3223
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.onboarding-day-30-coaching-workbench.json",
3236
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.onboarding-day-30-coaching-workbench.json",
3224
3237
  "contentHash": "5f1c97bc1cc28995b077cf0212ce5419a7f24c4a6f35b2c7593aebed77397f43",
3225
3238
  "sourceKind": "component_definition",
3226
3239
  "sourceId": "praxis-dynamic-page",
@@ -3230,7 +3243,7 @@
3230
3243
  "chunkIndex": 34,
3231
3244
  "chunkKind": "recipe",
3232
3245
  "content": "{\n \"_comment\": \"Praxis Dynamic Page recipe for an onboarding equipment and access recovery workbench using portable rich-content blocks for recovery signals, access owner context and governed remediation actions.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"onboarding-equipment-access-recovery-workbench\",\n \"status\": \"public-example\",\n \"useWhen\": \"Create an onboarding equipment and access recovery workbench with recovery signals, access owner context, blocker tabs and governed remediation actions.\",\n \"examplePrompts\": [\n \"create an onboarding equipment and access recovery workbench\",\n \"show a governed onboarding recovery rich content surface\",\n \"generate an onboarding page with access blockers and remediation actions\"\n ]\n },\n \"platformValue\": {\n \"canonicalRuntime\": \"@praxisui/rich-content owns the portable onboarding equipment and access recovery surface.\",\n \"hostMediation\": \"The host mediates open, confirm, reset and escalate actions through actionId contracts.\",\n \"publicExamples\": \"praxis-ui-landing-page can expose the same onboarding recovery workbench without serializing runtime helpers.\",\n \"agentCorpus\": \"This recipe keeps recovery signals, selected hire context, access owner context and governed recovery actions inside RichContentDocument so agents can reuse the same semantic surface across hosts.\"\n },\n \"authoringGuidance\": [\n \"Use definition.id \\\"praxis-rich-content\\\".\",\n \"Model recovery metrics with statGroup instead of host-authored access cards.\",\n \"Model the selected hire with lookupCard when the host already resolved the equipment and access recovery context.\",\n \"Use tabs for status and blockers instead of host-authored recovery sections.\",\n \"Use relatedRecord, ctaGroup and actionCard for governed recovery actions; keep handlers out of the document.\",\n \"Do not serialize hostCapabilities in the page JSON; the host injects runtime mediation only while rendering.\"\n ],\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 1,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"onboardingEquipmentAccessRecoveryWorkbench\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"vpn_key\",\n \"title\": \"Onboarding equipment and access recovery workbench\",\n \"subtitle\": \"Portable rich-content surface for governed access recovery\"\n },\n \"definition\": {\n \"id\": \"praxis-rich-content\",\n \"bindingOrder\": [\"document\", \"context\", \"layout\", \"rootClassName\"],\n \"inputs\": {\n \"layout\": \"block\",\n \"rootClassName\": \"onboarding-equipment-access-recovery-workbench\",\n \"context\": {\n \"hire\": {\n \"id\": \"ONB-741\",\n \"name\": \"Rafaela Dias\",\n \"role\": \"Platform Engineer\",\n \"department\": \"Developer experience\",\n \"blocker\": \"VPN and SSO provisioning\",\n \"openBlockers\": \"3\",\n \"criticalApps\": \"2\",\n \"recoverySla\": \"6h\",\n \"deviceState\": \"Laptop delivered / account pending\"\n },\n \"owner\": {\n \"name\": \"Marcos Lima\",\n \"department\": \"IT operations\",\n \"lane\": \"Identity and device setup\"\n }\n },\n \"document\": {\n \"kind\": \"praxis.rich-content\",\n \"version\": \"1.0.0\",\n \"nodes\": [\n {\n \"type\": \"callout\",\n \"tone\": \"warning\",\n \"icon\": \"vpn_key\",\n \"titleExpr\": \"${hire.name}\",\n \"message\": \"Use a portable onboarding equipment and access recovery surface when the host must expose governed access recovery and device remediation actions without inventing onboarding-specific templates.\"\n },\n {\n \"type\": \"statGroup\",\n \"title\": \"Recovery signals\",\n \"subtitle\": \"Canonical KPI block for onboarding recovery surfaces\",\n \"layout\": \"grid\",\n \"items\": [\n {\n \"label\": \"Open blockers\",\n \"valueExpr\": \"${hire.openBlockers}\",\n \"captionExpr\": \"${hire.id}\",\n \"icon\": \"warning\"\n },\n {\n \"label\": \"Critical apps\",\n \"valueExpr\": \"${hire.criticalApps}\",\n \"caption\": \"Still missing\",\n \"icon\": \"apps\"\n },\n {\n \"label\": \"Recovery SLA\",\n \"valueExpr\": \"${hire.recoverySla}\",\n \"captionExpr\": \"${hire.blocker}\",\n \"icon\": \"schedule\"\n }\n ]\n },\n {\n \"type\": \"lookupCard\",\n \"title\": \"Selected hire\",\n \"status\": \"resolved\",\n \"subtitleExpr\": \"${hire.name}\",\n \"metaExpr\": \"${hire.role}\",\n \"ctaLabel\": \"Open hire\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"onboarding.recovery.hire.open\",\n \"payloadExpr\": \"${hire}\"\n },\n \"fields\": [\n {\n \"label\": \"Department\",\n \"valueExpr\": \"${hire.department}\"\n },\n {\n \"label\": \"Device state\",\n \"valueExpr\": \"${hire.deviceState}\"\n }\n ],\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Open dossier\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"onboarding.recovery.dossier.open\",\n \"payloadExpr\": \"${hire}\"\n }\n }\n ]\n },\n {\n \"type\": \"tabs\",\n \"title\": \"Recovery views\",\n \"subtitle\": \"Portable editorial tabs for recovery status and blocker details.\",\n \"appearance\": \"underline\",\n \"defaultTabId\": \"status\",\n \"items\": [\n {\n \"id\": \"status\",\n \"label\": \"Status\",\n \"icon\": \"dashboard\",\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": \"Keep access status, recovery notes and remediation evidence inside the same RichContentDocument.\"\n }\n ]\n },\n {\n \"id\": \"blockers\",\n \"label\": \"Blockers\",\n \"icon\": \"warning\",\n \"content\": [\n {\n \"type\": \"keyValueList\",\n \"layout\": \"stacked\",\n \"items\": [\n {\n \"label\": \"Missing access\",\n \"value\": \"SSO, analytics workspace and VPN group mapping.\"\n },\n {\n \"label\": \"Recovery rule\",\n \"value\": \"Escalate any access or device blocker still unresolved after the first business day or any blocker affecting payroll, identity or secure access.\"\n }\n ]\n }\n ]\n }\n ]\n },\n {\n \"type\": \"relatedRecord\",\n \"title\": \"Access owner\",\n \"subtitleExpr\": \"${owner.name}\",\n \"relationLabel\": \"Ops owner\",\n \"metaExpr\": \"${owner.department}\",\n \"ctaLabel\": \"Open owner\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"onboarding.recovery.owner.open\",\n \"payloadExpr\": \"${owner}\"\n },\n \"fields\": [\n {\n \"label\": \"Recovery lane\",\n \"valueExpr\": \"${owner.lane}\",\n \"hint\": \"Resolved from the recovery assignment context.\"\n }\n ],\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Schedule recovery sync\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"onboarding.recovery.owner.scheduleSync\",\n \"payloadExpr\": \"${hire}\"\n }\n }\n ]\n },\n {\n \"type\": \"ctaGroup\",\n \"title\": \"Recovery actions\",\n \"subtitle\": \"Governed onboarding recovery outcomes\",\n \"message\": \"Use semantic recovery actions instead of host-authored onboarding access button bars.\",\n \"layout\": \"split\",\n \"actions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Confirm recovery plan\",\n \"icon\": \"check_circle\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"onboarding.recovery.confirm\",\n \"payloadExpr\": \"${hire}\"\n }\n },\n {\n \"type\": \"actionButton\",\n \"label\": \"Request access reset\",\n \"icon\": \"restart_alt\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"onboarding.recovery.access.reset\",\n \"payloadExpr\": \"${hire}\"\n }\n }\n ]\n },\n {\n \"type\": \"actionCard\",\n \"title\": \"Escalate recovery risk\",\n \"subtitleExpr\": \"${hire.id}\",\n \"message\": \"Use actionCard when the onboarding host needs a governed escalation flow for unresolved access or equipment blockers.\",\n \"metaExpr\": \"${hire.blocker}\",\n \"ctaLabel\": \"Escalate recovery risk\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"onboarding.recovery.escalate\",\n \"payloadExpr\": \"${hire}\"\n },\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Open dossier\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"onboarding.recovery.dossier.open\",\n \"payloadExpr\": \"${hire}\"\n }\n }\n ]\n }\n ]\n }\n }\n }\n }\n ]\n }\n}\n",
3233
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.onboarding-equipment-access-recovery-workbench.json",
3246
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.onboarding-equipment-access-recovery-workbench.json",
3234
3247
  "contentHash": "68d1ef367050e807868a7cefb4c1e70421f10ede18759963bd988ea98fb1e42a",
3235
3248
  "sourceKind": "component_definition",
3236
3249
  "sourceId": "praxis-dynamic-page",
@@ -3240,7 +3253,7 @@
3240
3253
  "chunkIndex": 35,
3241
3254
  "chunkKind": "recipe",
3242
3255
  "content": "{\n \"_comment\": \"Praxis Dynamic Page recipe for an onboarding journey workbench using portable rich-content blocks instead of host-authored journey templates.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"onboarding-journey-workbench\",\n \"status\": \"public-example\",\n \"useWhen\": \"Create an onboarding workbench with journey signals, assigned buddy context and governed next-step actions.\",\n \"examplePrompts\": [\n \"create an onboarding journey workbench\",\n \"show a governed onboarding rich content surface\",\n \"generate an onboarding page with buddy context and next-step actions\"\n ]\n },\n \"platformValue\": {\n \"canonicalRuntime\": \"@praxisui/rich-content owns the portable onboarding surface.\",\n \"hostMediation\": \"The host mediates hire lookup, buddy navigation and checklist flows through actionId contracts.\",\n \"publicExamples\": \"praxis-ui-landing-page can expose the same onboarding workbench without serializing runtime helpers.\",\n \"agentCorpus\": \"This recipe keeps onboarding signals, buddy context and governed actions inside RichContentDocument so agents can reuse the same semantic surface across hosts.\"\n },\n \"authoringGuidance\": [\n \"Use definition.id \\\"praxis-rich-content\\\".\",\n \"Model journey KPIs with statGroup instead of custom host progress cards.\",\n \"Model the selected hire with lookupCard when the record is resolved by host context.\",\n \"Model the assigned buddy with relatedRecord instead of host-authored relationship wrappers.\",\n \"Use ctaGroup and actionCard for governed onboarding actions; keep handlers out of the document.\",\n \"Do not serialize hostCapabilities in the page JSON; the host injects runtime mediation only while rendering.\"\n ],\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 1,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"onboardingJourneyWorkbench\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"person_add\",\n \"title\": \"Onboarding journey workbench\",\n \"subtitle\": \"Portable rich-content surface for governed onboarding flows\"\n },\n \"definition\": {\n \"id\": \"praxis-rich-content\",\n \"bindingOrder\": [\"document\", \"context\", \"layout\", \"rootClassName\"],\n \"inputs\": {\n \"layout\": \"block\",\n \"rootClassName\": \"onboarding-journey-workbench\",\n \"context\": {\n \"hire\": {\n \"id\": \"ONB-301\",\n \"name\": \"Leonardo Ramos\",\n \"role\": \"Platform Engineer\",\n \"department\": \"Platform Engineering\",\n \"day\": \"D+3\",\n \"pendingTasks\": \"5\",\n \"equipment\": \"Awaiting delivery\",\n \"welcomeTrack\": \"Platform foundation\",\n \"reviewWindow\": \"Friday\"\n },\n \"buddy\": {\n \"name\": \"Marina Costa\",\n \"department\": \"Engineering enablement\"\n }\n },\n \"document\": {\n \"kind\": \"praxis.rich-content\",\n \"version\": \"1.0.0\",\n \"nodes\": [\n {\n \"type\": \"callout\",\n \"tone\": \"info\",\n \"icon\": \"person_add\",\n \"titleExpr\": \"${hire.name}\",\n \"message\": \"Use a portable onboarding surface when the host must expose governed journey actions without inventing onboarding-specific templates.\"\n },\n {\n \"type\": \"statGroup\",\n \"title\": \"Onboarding signals\",\n \"subtitle\": \"Canonical KPI block for onboarding journey surfaces\",\n \"layout\": \"grid\",\n \"items\": [\n {\n \"label\": \"Day\",\n \"valueExpr\": \"${hire.day}\",\n \"captionExpr\": \"${hire.department}\",\n \"icon\": \"event\"\n },\n {\n \"label\": \"Tasks left\",\n \"valueExpr\": \"${hire.pendingTasks}\",\n \"captionExpr\": \"${hire.welcomeTrack}\",\n \"icon\": \"task_alt\"\n },\n {\n \"label\": \"Equipment\",\n \"valueExpr\": \"${hire.equipment}\",\n \"caption\": \"Provisioning status\",\n \"icon\": \"laptop_mac\"\n }\n ]\n },\n {\n \"type\": \"lookupCard\",\n \"title\": \"Selected hire\",\n \"status\": \"resolved\",\n \"subtitleExpr\": \"${hire.name}\",\n \"metaExpr\": \"${hire.role}\",\n \"ctaLabel\": \"Open hire\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"onboarding.hire.open\",\n \"payloadExpr\": \"${hire}\"\n },\n \"fields\": [\n {\n \"label\": \"Department\",\n \"valueExpr\": \"${hire.department}\"\n },\n {\n \"label\": \"Welcome track\",\n \"valueExpr\": \"${hire.welcomeTrack}\"\n }\n ],\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Open dossier\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"onboarding.dossier.open\",\n \"payloadExpr\": \"${hire}\"\n }\n }\n ]\n },\n {\n \"type\": \"tabs\",\n \"title\": \"Journey views\",\n \"subtitle\": \"Portable editorial tabs for onboarding context.\",\n \"appearance\": \"underline\",\n \"defaultTabId\": \"overview\",\n \"items\": [\n {\n \"id\": \"overview\",\n \"label\": \"Overview\",\n \"icon\": \"dashboard\",\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": \"Tabs keep journey notes, provisioning context and first-week readiness inside the same RichContentDocument.\"\n }\n ]\n },\n {\n \"id\": \"readiness\",\n \"label\": \"Readiness\",\n \"icon\": \"assignment_turned_in\",\n \"content\": [\n {\n \"type\": \"keyValueList\",\n \"layout\": \"stacked\",\n \"items\": [\n {\n \"label\": \"Review window\",\n \"valueExpr\": \"${hire.reviewWindow}\"\n },\n {\n \"label\": \"Equipment\",\n \"valueExpr\": \"${hire.equipment}\"\n },\n {\n \"label\": \"Portability rule\",\n \"value\": \"Keep journey semantics in the rich-content document; keep execution in the host.\"\n }\n ]\n }\n ]\n }\n ]\n },\n {\n \"type\": \"relatedRecord\",\n \"title\": \"Assigned buddy\",\n \"subtitleExpr\": \"${buddy.name}\",\n \"relationLabel\": \"Buddy\",\n \"metaExpr\": \"${buddy.department}\",\n \"ctaLabel\": \"Open buddy\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"onboarding.buddy.open\",\n \"payloadExpr\": \"${buddy}\"\n },\n \"fields\": [\n {\n \"label\": \"Welcome track\",\n \"valueExpr\": \"${hire.welcomeTrack}\",\n \"hint\": \"Resolved from the current onboarding plan.\"\n }\n ],\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Schedule intro\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"onboarding.buddy.scheduleIntro\",\n \"payloadExpr\": \"${hire}\"\n }\n }\n ]\n },\n {\n \"type\": \"ctaGroup\",\n \"title\": \"Journey actions\",\n \"subtitle\": \"Governed onboarding follow-up actions\",\n \"message\": \"Use semantic action clusters instead of host-authored onboarding button bars.\",\n \"layout\": \"split\",\n \"actions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Start checklist\",\n \"icon\": \"checklist\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"onboarding.checklist.start\",\n \"payloadExpr\": \"${hire}\"\n }\n },\n {\n \"type\": \"actionButton\",\n \"label\": \"Request equipment\",\n \"icon\": \"inventory_2\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"onboarding.equipment.request\",\n \"payloadExpr\": \"${hire}\"\n }\n }\n ]\n },\n {\n \"type\": \"actionCard\",\n \"title\": \"Open onboarding dossier\",\n \"subtitleExpr\": \"${hire.id}\",\n \"message\": \"Use actionCard when the onboarding host needs a governed dossier or coordinator workflow.\",\n \"metaExpr\": \"${hire.role}\",\n \"ctaLabel\": \"Open dossier\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"onboarding.dossier.open\",\n \"payloadExpr\": \"${hire}\"\n },\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Escalate blocker\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"onboarding.blocker.escalate\",\n \"payloadExpr\": \"${hire}\"\n }\n }\n ]\n }\n ]\n }\n }\n }\n }\n ]\n }\n}\n",
3243
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.onboarding-journey-workbench.json",
3256
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.onboarding-journey-workbench.json",
3244
3257
  "contentHash": "c0478a6b76dd6b8e122816723270dce9a4fd418e887965d068de6326244c174e",
3245
3258
  "sourceKind": "component_definition",
3246
3259
  "sourceId": "praxis-dynamic-page",
@@ -3250,7 +3263,7 @@
3250
3263
  "chunkIndex": 36,
3251
3264
  "chunkKind": "recipe",
3252
3265
  "content": "{\n \"_comment\": \"Praxis Dynamic Page recipe for an onboarding manager follow-up workbench using portable rich-content blocks for follow-up signals, manager context and governed follow-up actions.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"onboarding-manager-follow-up-workbench\",\n \"status\": \"public-example\",\n \"useWhen\": \"Create an onboarding manager follow-up workbench with follow-up signals, manager context, blocker tabs and governed coaching actions.\",\n \"examplePrompts\": [\n \"create an onboarding manager follow-up workbench\",\n \"show a governed onboarding manager follow-up rich content surface\",\n \"generate an onboarding page with follow-up signals and coaching actions\"\n ]\n },\n \"platformValue\": {\n \"canonicalRuntime\": \"@praxisui/rich-content owns the portable onboarding manager follow-up surface.\",\n \"hostMediation\": \"The host mediates open, confirm, coaching and escalate actions through actionId contracts.\",\n \"publicExamples\": \"praxis-ui-landing-page can expose the same onboarding manager follow-up workbench without serializing runtime helpers.\",\n \"agentCorpus\": \"This recipe keeps follow-up signals, selected hire context, manager context and governed follow-up actions inside RichContentDocument so agents can reuse the same semantic surface across hosts.\"\n },\n \"authoringGuidance\": [\n \"Use definition.id \\\"praxis-rich-content\\\".\",\n \"Model follow-up metrics with statGroup instead of host-authored manager cards.\",\n \"Model the selected hire with lookupCard when the host already resolved the follow-up context.\",\n \"Use tabs for summary and blockers instead of host-authored operational sections.\",\n \"Use relatedRecord, ctaGroup and actionCard for governed manager follow-up actions; keep handlers out of the document.\",\n \"Do not serialize hostCapabilities in the page JSON; the host injects runtime mediation only while rendering.\"\n ],\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 1,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"onboardingManagerFollowUpWorkbench\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"supervisor_account\",\n \"title\": \"Onboarding manager follow-up workbench\",\n \"subtitle\": \"Portable rich-content surface for governed manager follow-up\"\n },\n \"definition\": {\n \"id\": \"praxis-rich-content\",\n \"bindingOrder\": [\"document\", \"context\", \"layout\", \"rootClassName\"],\n \"inputs\": {\n \"layout\": \"block\",\n \"rootClassName\": \"onboarding-manager-follow-up-workbench\",\n \"context\": {\n \"hire\": {\n \"id\": \"ONB-680\",\n \"name\": \"Bianca Torres\",\n \"role\": \"Product Analyst\",\n \"department\": \"Platform strategy\",\n \"focus\": \"First 30-day goals\",\n \"checkIns\": \"3\",\n \"openBlockers\": \"2\",\n \"sentiment\": \"7.8\",\n \"pulse\": \"Needs role clarity\"\n },\n \"manager\": {\n \"name\": \"Helena Souza\",\n \"department\": \"Engineering leadership\",\n \"lane\": \"30-day coaching plan\"\n }\n },\n \"document\": {\n \"kind\": \"praxis.rich-content\",\n \"version\": \"1.0.0\",\n \"nodes\": [\n {\n \"type\": \"callout\",\n \"tone\": \"info\",\n \"icon\": \"supervisor_account\",\n \"titleExpr\": \"${hire.name}\",\n \"message\": \"Use a portable onboarding manager follow-up surface when the host must expose governed coaching and manager follow-up actions without inventing onboarding-specific templates.\"\n },\n {\n \"type\": \"statGroup\",\n \"title\": \"Follow-up signals\",\n \"subtitle\": \"Canonical KPI block for onboarding manager follow-up surfaces\",\n \"layout\": \"grid\",\n \"items\": [\n {\n \"label\": \"Check-ins\",\n \"valueExpr\": \"${hire.checkIns}\",\n \"captionExpr\": \"${hire.id}\",\n \"icon\": \"event_note\"\n },\n {\n \"label\": \"Open blockers\",\n \"valueExpr\": \"${hire.openBlockers}\",\n \"caption\": \"Needs manager action\",\n \"icon\": \"warning\"\n },\n {\n \"label\": \"Sentiment\",\n \"valueExpr\": \"${hire.sentiment}\",\n \"captionExpr\": \"${hire.pulse}\",\n \"icon\": \"sentiment_satisfied\"\n }\n ]\n },\n {\n \"type\": \"lookupCard\",\n \"title\": \"Selected hire\",\n \"status\": \"resolved\",\n \"subtitleExpr\": \"${hire.name}\",\n \"metaExpr\": \"${hire.role}\",\n \"ctaLabel\": \"Open hire\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"onboarding.followup.hire.open\",\n \"payloadExpr\": \"${hire}\"\n },\n \"fields\": [\n {\n \"label\": \"Department\",\n \"valueExpr\": \"${hire.department}\"\n },\n {\n \"label\": \"Current focus\",\n \"valueExpr\": \"${hire.focus}\"\n }\n ],\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Open dossier\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"onboarding.followup.dossier.open\",\n \"payloadExpr\": \"${hire}\"\n }\n }\n ]\n },\n {\n \"type\": \"tabs\",\n \"title\": \"Follow-up views\",\n \"subtitle\": \"Portable editorial tabs for manager notes and blockers.\",\n \"appearance\": \"underline\",\n \"defaultTabId\": \"summary\",\n \"items\": [\n {\n \"id\": \"summary\",\n \"label\": \"Summary\",\n \"icon\": \"dashboard\",\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": \"Keep manager follow-up notes, pulse observations and enablement actions inside the same RichContentDocument.\"\n }\n ]\n },\n {\n \"id\": \"blockers\",\n \"label\": \"Blockers\",\n \"icon\": \"warning\",\n \"content\": [\n {\n \"type\": \"keyValueList\",\n \"layout\": \"stacked\",\n \"items\": [\n {\n \"label\": \"Open blocker\",\n \"value\": \"Role expectations and stakeholder map still need clarification.\"\n },\n {\n \"label\": \"Follow-up rule\",\n \"value\": \"Escalate any blocker still unresolved after the second manager follow-up or any sentiment drop below 7.\"\n }\n ]\n }\n ]\n }\n ]\n },\n {\n \"type\": \"relatedRecord\",\n \"title\": \"Assigned manager\",\n \"subtitleExpr\": \"${manager.name}\",\n \"relationLabel\": \"Manager\",\n \"metaExpr\": \"${manager.department}\",\n \"ctaLabel\": \"Open manager\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"onboarding.followup.manager.open\",\n \"payloadExpr\": \"${manager}\"\n },\n \"fields\": [\n {\n \"label\": \"Follow-up lane\",\n \"valueExpr\": \"${manager.lane}\",\n \"hint\": \"Resolved from the follow-up assignment context.\"\n }\n ],\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Schedule manager sync\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"onboarding.followup.manager.scheduleSync\",\n \"payloadExpr\": \"${hire}\"\n }\n }\n ]\n },\n {\n \"type\": \"ctaGroup\",\n \"title\": \"Follow-up actions\",\n \"subtitle\": \"Governed onboarding follow-up outcomes\",\n \"message\": \"Use semantic follow-up actions instead of host-authored onboarding manager button bars.\",\n \"layout\": \"split\",\n \"actions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Confirm follow-up plan\",\n \"icon\": \"check_circle\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"onboarding.followup.confirm\",\n \"payloadExpr\": \"${hire}\"\n }\n },\n {\n \"type\": \"actionButton\",\n \"label\": \"Request coaching update\",\n \"icon\": \"forum\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"onboarding.followup.coaching.requestUpdate\",\n \"payloadExpr\": \"${hire}\"\n }\n }\n ]\n },\n {\n \"type\": \"actionCard\",\n \"title\": \"Escalate onboarding risk\",\n \"subtitleExpr\": \"${hire.id}\",\n \"message\": \"Use actionCard when the onboarding host needs a governed escalation flow for unresolved manager follow-up risks.\",\n \"metaExpr\": \"${hire.pulse}\",\n \"ctaLabel\": \"Escalate follow-up risk\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"onboarding.followup.escalate\",\n \"payloadExpr\": \"${hire}\"\n },\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Open dossier\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"onboarding.followup.dossier.open\",\n \"payloadExpr\": \"${hire}\"\n }\n }\n ]\n }\n ]\n }\n }\n }\n }\n ]\n }\n}\n",
3253
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.onboarding-manager-follow-up-workbench.json",
3266
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.onboarding-manager-follow-up-workbench.json",
3254
3267
  "contentHash": "ee621a8d41d3ba77afef42fa510985e2e8b4c92c4e3b1a0854bd671f77b9494b",
3255
3268
  "sourceKind": "component_definition",
3256
3269
  "sourceId": "praxis-dynamic-page",
@@ -3260,7 +3273,7 @@
3260
3273
  "chunkIndex": 37,
3261
3274
  "chunkKind": "recipe",
3262
3275
  "content": "{\n \"_comment\": \"Praxis Dynamic Page recipe for an onboarding readiness workbench using portable rich-content blocks for first-week readiness, blockers and governed escalation actions.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"onboarding-readiness-workbench\",\n \"status\": \"public-example\",\n \"useWhen\": \"Create an onboarding readiness workbench with first-week signals, manager context, blocker tabs and governed follow-up actions.\",\n \"examplePrompts\": [\n \"create an onboarding readiness workbench\",\n \"show a governed onboarding readiness rich content surface\",\n \"generate an onboarding page with blockers and readiness actions\"\n ]\n },\n \"platformValue\": {\n \"canonicalRuntime\": \"@praxisui/rich-content owns the portable onboarding readiness surface.\",\n \"hostMediation\": \"The host mediates open, confirm, follow-up and escalate actions through actionId contracts.\",\n \"publicExamples\": \"praxis-ui-landing-page can expose the same onboarding readiness workbench without serializing runtime helpers.\",\n \"agentCorpus\": \"This recipe keeps readiness signals, selected hire context, blockers and escalation actions inside RichContentDocument so agents can reuse the same semantic surface across hosts.\"\n },\n \"authoringGuidance\": [\n \"Use definition.id \\\"praxis-rich-content\\\".\",\n \"Model first-week readiness metrics with statGroup instead of custom host progress cards.\",\n \"Model the selected hire with lookupCard when the host already resolved the readiness context.\",\n \"Use tabs for readiness and blockers instead of host-authored operational sections.\",\n \"Use relatedRecord, ctaGroup and actionCard for governed readiness and blocker actions; keep handlers out of the document.\",\n \"Do not serialize hostCapabilities in the page JSON; the host injects runtime mediation only while rendering.\"\n ],\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 1,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"onboardingReadinessWorkbench\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"checklist\",\n \"title\": \"Onboarding readiness workbench\",\n \"subtitle\": \"Portable rich-content surface for governed first-week readiness\"\n },\n \"definition\": {\n \"id\": \"praxis-rich-content\",\n \"bindingOrder\": [\"document\", \"context\", \"layout\", \"rootClassName\"],\n \"inputs\": {\n \"layout\": \"block\",\n \"rootClassName\": \"onboarding-readiness-workbench\",\n \"context\": {\n \"hire\": {\n \"id\": \"ONB-512\",\n \"name\": \"Bianca Torres\",\n \"role\": \"Product Analyst\",\n \"department\": \"Platform strategy\",\n \"startDate\": \"Monday\",\n \"readiness\": \"82%\",\n \"pendingEquipment\": \"2\",\n \"blocker\": \"Badge access and laptop delivery\",\n \"weekPlan\": \"Platform immersion\"\n },\n \"manager\": {\n \"name\": \"Helena Souza\",\n \"department\": \"Engineering leadership\"\n }\n },\n \"document\": {\n \"kind\": \"praxis.rich-content\",\n \"version\": \"1.0.0\",\n \"nodes\": [\n {\n \"type\": \"callout\",\n \"tone\": \"info\",\n \"icon\": \"checklist\",\n \"titleExpr\": \"${hire.name}\",\n \"message\": \"Use a portable onboarding readiness surface when the host must expose governed first-week actions without inventing onboarding-specific templates.\"\n },\n {\n \"type\": \"statGroup\",\n \"title\": \"Readiness signals\",\n \"subtitle\": \"Canonical KPI block for onboarding readiness surfaces\",\n \"layout\": \"grid\",\n \"items\": [\n {\n \"label\": \"Checklist\",\n \"valueExpr\": \"${hire.readiness}\",\n \"captionExpr\": \"${hire.id}\",\n \"icon\": \"checklist\"\n },\n {\n \"label\": \"Equipment\",\n \"valueExpr\": \"${hire.pendingEquipment}\",\n \"caption\": \"Pending deliveries\",\n \"icon\": \"laptop_mac\"\n },\n {\n \"label\": \"Start date\",\n \"valueExpr\": \"${hire.startDate}\",\n \"captionExpr\": \"${hire.department}\",\n \"icon\": \"event\"\n }\n ]\n },\n {\n \"type\": \"lookupCard\",\n \"title\": \"Selected hire\",\n \"status\": \"resolved\",\n \"subtitleExpr\": \"${hire.name}\",\n \"metaExpr\": \"${hire.role}\",\n \"ctaLabel\": \"Open hire\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"onboarding.readiness.hire.open\",\n \"payloadExpr\": \"${hire}\"\n },\n \"fields\": [\n {\n \"label\": \"Department\",\n \"valueExpr\": \"${hire.department}\"\n },\n {\n \"label\": \"Start date\",\n \"valueExpr\": \"${hire.startDate}\"\n }\n ],\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Open dossier\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"onboarding.readiness.dossier.open\",\n \"payloadExpr\": \"${hire}\"\n }\n }\n ]\n },\n {\n \"type\": \"tabs\",\n \"title\": \"Readiness views\",\n \"subtitle\": \"Portable editorial tabs for readiness and blockers.\",\n \"appearance\": \"underline\",\n \"defaultTabId\": \"readiness\",\n \"items\": [\n {\n \"id\": \"readiness\",\n \"label\": \"Readiness\",\n \"icon\": \"task_alt\",\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": \"Tabs keep first-week readiness notes, blockers and operational evidence inside the same RichContentDocument.\"\n }\n ]\n },\n {\n \"id\": \"blockers\",\n \"label\": \"Blockers\",\n \"icon\": \"warning\",\n \"content\": [\n {\n \"type\": \"keyValueList\",\n \"layout\": \"stacked\",\n \"items\": [\n {\n \"label\": \"Pending item\",\n \"valueExpr\": \"${hire.blocker}\"\n },\n {\n \"label\": \"Readiness rule\",\n \"value\": \"Escalate any blocker that still exists by day two or blocks manager onboarding milestones.\"\n }\n ]\n }\n ]\n }\n ]\n },\n {\n \"type\": \"relatedRecord\",\n \"title\": \"Assigned manager\",\n \"subtitleExpr\": \"${manager.name}\",\n \"relationLabel\": \"Manager\",\n \"metaExpr\": \"${manager.department}\",\n \"ctaLabel\": \"Open manager\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"onboarding.readiness.manager.open\",\n \"payloadExpr\": \"${manager}\"\n },\n \"fields\": [\n {\n \"label\": \"Week one plan\",\n \"valueExpr\": \"${hire.weekPlan}\",\n \"hint\": \"Resolved from the readiness assignment context.\"\n }\n ],\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Schedule check-in\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"onboarding.readiness.manager.scheduleCheckIn\",\n \"payloadExpr\": \"${hire}\"\n }\n }\n ]\n },\n {\n \"type\": \"ctaGroup\",\n \"title\": \"Readiness actions\",\n \"subtitle\": \"Governed onboarding readiness outcomes\",\n \"message\": \"Use semantic readiness actions instead of host-authored onboarding button bars.\",\n \"layout\": \"split\",\n \"actions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Confirm readiness\",\n \"icon\": \"check_circle\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"onboarding.readiness.confirm\",\n \"payloadExpr\": \"${hire}\"\n }\n },\n {\n \"type\": \"actionButton\",\n \"label\": \"Request equipment follow-up\",\n \"icon\": \"inventory\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"onboarding.readiness.equipment.followUp\",\n \"payloadExpr\": \"${hire}\"\n }\n }\n ]\n },\n {\n \"type\": \"actionCard\",\n \"title\": \"Escalate onboarding blocker\",\n \"subtitleExpr\": \"${hire.id}\",\n \"message\": \"Use actionCard when the onboarding host needs a governed blocker escalation flow.\",\n \"metaExpr\": \"${hire.blocker}\",\n \"ctaLabel\": \"Escalate blocker\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"onboarding.readiness.blocker.escalate\",\n \"payloadExpr\": \"${hire}\"\n },\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Open dossier\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"onboarding.readiness.dossier.open\",\n \"payloadExpr\": \"${hire}\"\n }\n }\n ]\n }\n ]\n }\n }\n }\n }\n ]\n }\n}\n",
3263
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.onboarding-readiness-workbench.json",
3276
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.onboarding-readiness-workbench.json",
3264
3277
  "contentHash": "ab0859c31da6b4232b68d6b076c9a094d90e5fdbd25c2581dc3cbaf10cdd184d",
3265
3278
  "sourceKind": "component_definition",
3266
3279
  "sourceId": "praxis-dynamic-page",
@@ -3270,7 +3283,7 @@
3270
3283
  "chunkIndex": 38,
3271
3284
  "chunkKind": "recipe",
3272
3285
  "content": "{\n \"_comment\": \"Recipe para agentes criarem uma Praxis Dynamic Page com um perfil rico em praxis-dynamic-form.\",\n \"_comment2\": \"Use quando a meta for demonstrar sections, fieldMetadata, readonly detail, remote options e field-specific controls.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"profile-form\",\n \"status\": \"public-example\",\n \"useWhen\": \"Create a metadata-driven readonly profile page backed by a published resource detail endpoint.\",\n \"examplePrompts\": [\n \"crie um perfil rico de funcionario com dynamic form\",\n \"mostre sections e fieldMetadata no praxis-dynamic-form\",\n \"gere uma pagina de detalhe readonly com avatar, cpf, email, telefone, salario e options remotas\"\n ]\n },\n \"platformValue\": {\n \"canonicalContract\": \"praxis-metadata-starter publishes the resource detail schema and option metadata consumed by the form runtime.\",\n \"referenceApi\": \"praxis-api-quickstart serves funcionarios detail data and cargo/departamento option endpoints.\",\n \"angularRuntime\": \"@praxisui/dynamic-form renders sections, fieldMetadata and action placement; @praxisui/dynamic-fields resolves package-owned controls.\",\n \"publicExamples\": \"praxis-ui-landing-page exposes the JSON envelope, runtime preview and coverage map.\",\n \"agentCorpus\": \"This recipe gives LLMs a copyable end-to-end form profile pattern.\"\n },\n \"operationalEvidence\": {\n \"baseUrl\": \"https://praxis-api-quickstart.onrender.com\",\n \"safeFirstIds\": [\n \"filtered-schema-response-funcionarios\",\n \"funcionarios-get-by-id\",\n \"cargos-options-filter\",\n \"departamentos-options-filter\"\n ],\n \"pendingHttpIds\": [],\n \"httpExamples\": [\n \"praxisui-http-examples/http/metadata/filtered_schema_response_funcionarios.http\",\n \"praxisui-http-examples/http/resources/funcionarios_get_by_id.http\",\n \"praxisui-http-examples/http/resources/cargos_options_filter.http\",\n \"praxisui-http-examples/http/resources/departamentos_options_filter.http\"\n ]\n },\n \"authoringGuidance\": [\n \"Use praxis-dynamic-form config.sections for the visual layout and fieldMetadata for field behavior.\",\n \"Keep fieldMetadata.name aligned to fields present in the published response schema.\",\n \"Use package-owned Dynamic Fields control types already present in the runtime/editorial catalog.\",\n \"Use readonly mode and readonly field metadata for profile/detail surfaces that should not mutate data.\",\n \"Use asyncSelect with canonical option endpoints for foreign-key labels such as cargoId and departamentoId.\",\n \"Use actions.placement and actions.position to show form action bar layout without turning the example into CRUD.\"\n ],\n \"teaches\": [\n \"dynamic-form.sections\",\n \"dynamic-form.fieldMetadata\",\n \"dynamic-form.actions\",\n \"dynamic-fields.avatar\",\n \"dynamic-fields.cpfCnpjInput\",\n \"dynamic-fields.phone\",\n \"dynamic-fields.currency\",\n \"dynamic-fields.asyncSelect\",\n \"dynamic-fields.toggle\",\n \"remote-options\",\n \"readonly-detail\"\n ],\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 1,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"funcionarioProfileForm\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"badge\",\n \"title\": \"Funcionario profile\",\n \"subtitle\": \"Sectioned readonly form with field-specific controls\"\n },\n \"definition\": {\n \"id\": \"praxis-dynamic-form\",\n \"bindingOrder\": [\n \"config\",\n \"resourcePath\",\n \"formId\",\n \"resourceId\"\n ],\n \"inputs\": {\n \"formId\": \"human-resources-funcionarios-profile\",\n \"resourcePath\": \"human-resources/funcionarios\",\n \"resourceId\": 1,\n \"mode\": \"view\",\n \"config\": {\n \"metadata\": {\n \"name\": \"Funcionario profile surface\",\n \"version\": \"1.0.0\"\n },\n \"sections\": [\n {\n \"id\": \"identity\",\n \"title\": \"Identity\",\n \"description\": \"Core employee identity and contact data.\",\n \"appearance\": \"outlined\",\n \"rows\": [\n {\n \"id\": \"identity-row-main\",\n \"columns\": [\n {\n \"id\": \"identity-avatar\",\n \"span\": {\n \"md\": 3,\n \"lg\": 3\n },\n \"fields\": [\n \"fotoPerfilUrl\",\n \"ativo\"\n ]\n },\n {\n \"id\": \"identity-primary\",\n \"span\": {\n \"md\": 9,\n \"lg\": 9\n },\n \"fields\": [\n \"nomeCompleto\",\n \"cpf\",\n \"email\",\n \"telefone\"\n ]\n }\n ]\n }\n ]\n },\n {\n \"id\": \"assignment\",\n \"title\": \"Assignment\",\n \"description\": \"Role, department and compensation metadata.\",\n \"appearance\": \"outlined\",\n \"rows\": [\n {\n \"id\": \"assignment-row-1\",\n \"columns\": [\n {\n \"id\": \"assignment-role\",\n \"span\": {\n \"md\": 6,\n \"lg\": 6\n },\n \"fields\": [\n \"cargoId\",\n \"departamentoId\"\n ]\n },\n {\n \"id\": \"assignment-payroll\",\n \"span\": {\n \"md\": 6,\n \"lg\": 6\n },\n \"fields\": [\n \"salario\",\n \"dataAdmissao\"\n ]\n }\n ]\n }\n ]\n },\n {\n \"id\": \"personal\",\n \"title\": \"Personal\",\n \"description\": \"Civil status and birth metadata kept readonly in this surface.\",\n \"appearance\": \"outlined\",\n \"rows\": [\n {\n \"id\": \"personal-row-1\",\n \"columns\": [\n {\n \"id\": \"personal-main\",\n \"fields\": [\n \"estadoCivil\",\n \"dataNascimento\"\n ]\n }\n ]\n }\n ]\n }\n ],\n \"fieldMetadata\": [\n {\n \"name\": \"fotoPerfilUrl\",\n \"label\": \"Avatar\",\n \"controlType\": \"avatar\",\n \"imageField\": \"fotoPerfilUrl\",\n \"readonly\": true\n },\n {\n \"name\": \"nomeCompleto\",\n \"label\": \"Nome Completo\",\n \"controlType\": \"input\",\n \"validators\": {\n \"required\": true,\n \"maxLength\": 160\n },\n \"readonly\": true\n },\n {\n \"name\": \"cpf\",\n \"label\": \"CPF\",\n \"controlType\": \"cpfCnpjInput\",\n \"maskType\": \"cpf\",\n \"unmaskOnSubmit\": true,\n \"readonly\": true\n },\n {\n \"name\": \"email\",\n \"label\": \"Email\",\n \"controlType\": \"email\",\n \"validators\": {\n \"email\": true\n },\n \"readonly\": true\n },\n {\n \"name\": \"telefone\",\n \"label\": \"Telefone\",\n \"controlType\": \"phone\",\n \"maskType\": \"phone\",\n \"readonly\": true\n },\n {\n \"name\": \"cargoId\",\n \"label\": \"Cargo\",\n \"controlType\": \"asyncSelect\",\n \"endpoint\": \"/api/human-resources/cargos/options/filter\",\n \"displayField\": \"label\",\n \"valueField\": \"id\",\n \"readonly\": true\n },\n {\n \"name\": \"departamentoId\",\n \"label\": \"Departamento\",\n \"controlType\": \"asyncSelect\",\n \"endpoint\": \"/api/human-resources/departamentos/options/filter\",\n \"displayField\": \"label\",\n \"valueField\": \"id\",\n \"readonly\": true\n },\n {\n \"name\": \"salario\",\n \"label\": \"Salario\",\n \"controlType\": \"currency\",\n \"currencyCode\": \"BRL\",\n \"locale\": \"pt-BR\",\n \"readonly\": true\n },\n {\n \"name\": \"dataAdmissao\",\n \"label\": \"Data de Admissao\",\n \"controlType\": \"date\",\n \"readonly\": true\n },\n {\n \"name\": \"estadoCivil\",\n \"label\": \"Estado Civil\",\n \"controlType\": \"select\",\n \"options\": [\n {\n \"label\": \"Solteiro\",\n \"value\": \"SOLTEIRO\"\n },\n {\n \"label\": \"Casado\",\n \"value\": \"CASADO\"\n },\n {\n \"label\": \"Divorciado\",\n \"value\": \"DIVORCIADO\"\n },\n {\n \"label\": \"Viuvo\",\n \"value\": \"VIUVO\"\n }\n ],\n \"readonly\": true\n },\n {\n \"name\": \"dataNascimento\",\n \"label\": \"Data de Nascimento\",\n \"controlType\": \"date\",\n \"readonly\": true\n },\n {\n \"name\": \"ativo\",\n \"label\": \"Ativo\",\n \"controlType\": \"toggle\",\n \"readonly\": true\n }\n ],\n \"actions\": {\n \"submit\": {\n \"id\": \"request-update\",\n \"label\": \"Request update\",\n \"visible\": false,\n \"type\": \"submit\"\n },\n \"cancel\": {\n \"id\": \"close-profile\",\n \"label\": \"Close\",\n \"visible\": true,\n \"type\": \"button\"\n },\n \"reset\": {\n \"id\": \"reset-profile\",\n \"label\": \"Reset\",\n \"visible\": false,\n \"type\": \"reset\"\n },\n \"position\": \"right\",\n \"placement\": \"afterSections\",\n \"spacing\": \"compact\"\n }\n }\n }\n }\n }\n ]\n }\n}\n",
3273
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.profile-form.json",
3286
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.profile-form.json",
3274
3287
  "contentHash": "15468db9c643821551a16b9802f27dad48503417c6fdf42d779ec01cb046c17c",
3275
3288
  "sourceKind": "component_definition",
3276
3289
  "sourceId": "praxis-dynamic-page",
@@ -3280,7 +3293,7 @@
3280
3293
  "chunkIndex": 39,
3281
3294
  "chunkKind": "recipe",
3282
3295
  "content": "{\n \"_comment\": \"Live remote Praxis Dynamic Page recipe with a Praxis List widget backed only by a published quickstart resourcePath.\",\n \"_comment2\": \"Use this when an agent needs an end-to-end copyable contract: Dynamic Page + List + GenericCrudService.filter + rich expansion + HATEOAS follow-up actions.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"remote-list\",\n \"useWhen\": \"Create a dynamic page with a live remote list widget backed by dataSource.resourcePath and rich-content item expansion.\",\n \"examplePrompts\": [\n \"page with remote list from resourcePath\",\n \"list mission participants from the quickstart API\",\n \"copyable dynamic page with Praxis List, backend pagination and rich item expansion\"\n ],\n \"requires\": [\n \"@praxisui/core\",\n \"@praxisui/list\",\n \"GenericCrudService\",\n \"POST /api/{resourcePath}/filter\"\n ]\n },\n \"api\": {\n \"origin\": \"https://praxis-api-quickstart.onrender.com\",\n \"baseUrl\": \"https://praxis-api-quickstart.onrender.com/api\",\n \"schemasBaseUrl\": \"https://praxis-api-quickstart.onrender.com/schemas\",\n \"resourcePath\": \"operations/missao-participantes\",\n \"resourceKey\": \"operations.missao-participantes\"\n },\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 1,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"remoteMissionParticipantList\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"groups\",\n \"title\": \"Mission participants\",\n \"subtitle\": \"Remote quickstart resourcePath with pageable filter data\",\n \"actions\": [\n {\n \"id\": \"toggle-list-customization\",\n \"label\": \"Customize list\",\n \"tooltip\": \"Enable or disable list customization mode\",\n \"icon\": \"toggle_off\",\n \"pressedIcon\": \"toggle_on\",\n \"variant\": \"icon\",\n \"placement\": \"header\",\n \"command\": \"pdx:toggle-input\",\n \"pressed\": \"${widget.inputs.enableCustomization}\",\n \"payload\": {\n \"input\": \"enableCustomization\"\n }\n }\n ]\n },\n \"definition\": {\n \"id\": \"praxis-list\",\n \"bindingOrder\": [\"listId\", \"componentInstanceId\", \"enableCustomization\", \"config\"],\n \"inputs\": {\n \"listId\": \"remote-mission-participant-list-live\",\n \"componentInstanceId\": \"dynamic-page-live-remote\",\n \"enableCustomization\": false,\n \"config\": {\n \"id\": \"remote-mission-participant-list-live-config\",\n \"dataSource\": {\n \"resourcePath\": \"operations/missao-participantes\",\n \"query\": {},\n \"sort\": [\"ordem,asc\"]\n },\n \"layout\": {\n \"variant\": \"list\",\n \"density\": \"comfortable\",\n \"lines\": 3,\n \"dividers\": \"between\",\n \"pageSize\": 8,\n \"rowLayout\": {\n \"type\": \"grid\",\n \"columns\": [\n { \"slot\": \"leading\", \"width\": \"44px\", \"align\": \"center\" },\n { \"slot\": \"primary\", \"width\": \"minmax(180px, 1fr)\" },\n { \"slot\": \"secondary\", \"width\": \"minmax(220px, 1.2fr)\" },\n { \"slot\": \"meta\", \"width\": \"140px\", \"align\": \"center\" },\n { \"slot\": \"trailing\", \"width\": \"120px\", \"align\": \"center\" },\n { \"slot\": \"actions\", \"width\": \"92px\", \"align\": \"center\" }\n ],\n \"gap\": \"12px\",\n \"align\": \"center\"\n }\n },\n \"skin\": {\n \"type\": \"outline\",\n \"radius\": \"8px\",\n \"border\": \"1px solid rgba(20, 184, 166, 0.32)\"\n },\n \"selection\": {\n \"mode\": \"multiple\",\n \"compareBy\": \"funcionarioId\",\n \"return\": \"id\"\n },\n \"interaction\": {\n \"expandable\": true,\n \"expandTrigger\": \"icon\",\n \"expandMode\": \"single\",\n \"expandPlacement\": \"actions\"\n },\n \"templating\": {\n \"leading\": { \"type\": \"icon\", \"expr\": \"groups\" },\n \"primary\": { \"type\": \"text\", \"expr\": \"${item.funcionarioNome}\" },\n \"secondary\": { \"type\": \"text\", \"expr\": \"${item.missaoTitulo}\" },\n \"meta\": { \"type\": \"chip\", \"expr\": \"${item.papel}\", \"variant\": \"outlined\" },\n \"trailing\": { \"type\": \"chip\", \"expr\": \"${item.resultado}\", \"variant\": \"filled\" },\n \"features\": [\n { \"type\": \"chip\", \"expr\": \"missao #${item.missaoId}\", \"variant\": \"outlined\" },\n { \"type\": \"chip\", \"expr\": \"funcionario #${item.funcionarioId}\", \"variant\": \"outlined\" }\n ],\n \"featuresMode\": \"labels-only\",\n \"emptyState\": {\n \"type\": \"text\",\n \"expr\": \"No mission participants returned by the quickstart filter.\"\n }\n },\n \"expansion\": {\n \"sections\": [\n {\n \"id\": \"mission-participant-detail\",\n \"title\": \"Mission participant detail\",\n \"type\": \"rich-content\",\n \"document\": {\n \"kind\": \"praxis.rich-content\",\n \"version\": \"1.0.0\",\n \"nodes\": [\n {\n \"id\": \"relationship-summary\",\n \"type\": \"propertySheet\",\n \"title\": \"Relationship\",\n \"columns\": 2,\n \"items\": [\n {\n \"id\": \"participant\",\n \"label\": \"Participant\",\n \"valueExpr\": \"${item.funcionarioNome}\",\n \"icon\": \"person\"\n },\n {\n \"id\": \"mission\",\n \"label\": \"Mission\",\n \"valueExpr\": \"${item.missaoTitulo}\",\n \"icon\": \"flag\"\n },\n {\n \"id\": \"role\",\n \"label\": \"Role\",\n \"valueExpr\": \"${item.papel}\",\n \"icon\": \"military_tech\",\n \"tone\": \"info\"\n },\n {\n \"id\": \"result\",\n \"label\": \"Result\",\n \"valueExpr\": \"${item.resultado}\",\n \"icon\": \"verified\",\n \"tone\": \"success\"\n }\n ]\n },\n {\n \"id\": \"hateoas-actions\",\n \"type\": \"actionCard\",\n \"title\": \"Governed API context\",\n \"subtitle\": \"HATEOAS links are available for this item without exposing raw JSON in the UI.\",\n \"message\": \"Use the list actions to inspect surfaces or capabilities from the same canonical resource.\",\n \"icon\": \"hub\",\n \"ctaLabel\": \"Inspect capabilities\",\n \"ctaIcon\": \"bolt\",\n \"variant\": \"stroked\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"missionParticipant.inspectCapabilities\",\n \"payloadExpr\": \"${item._links.capabilities.href}\"\n }\n }\n ]\n }\n }\n ],\n \"rendering\": {\n \"shell\": \"attached\",\n \"columns\": 1,\n \"gap\": \"12px\",\n \"padding\": \"12px\"\n }\n },\n \"actions\": [\n {\n \"id\": \"open-participant-surfaces\",\n \"icon\": \"layers\",\n \"label\": \"Surfaces\",\n \"kind\": \"icon\",\n \"globalAction\": {\n \"actionId\": \"surface.open\",\n \"payload\": {\n \"presentation\": \"modal\",\n \"title\": \"Participant surfaces\",\n \"icon\": \"layers\",\n \"subtitle\": \"Governed follow-up surfaces for the selected participant\",\n \"size\": { \"width\": \"720px\", \"maxWidth\": \"90vw\" },\n \"widget\": {\n \"id\": \"widget:rich-text-block\",\n \"inputs\": {\n \"title\": \"Published surfaces for ${item.funcionarioNome}\",\n \"content\": \"The selected participant belongs to ${item.missaoTitulo}. Surface actions should open governed runtime projections instead of leaving row buttons as inert local events. Capability link: ${item._links.capabilities.href}\",\n \"variant\": \"emphasis\"\n }\n }\n }\n },\n \"emitLocal\": false,\n \"showLoading\": true,\n \"placement\": \"actions\"\n },\n {\n \"id\": \"inspect-participant-capabilities\",\n \"icon\": \"bolt\",\n \"label\": \"Capabilities\",\n \"kind\": \"icon\",\n \"globalAction\": {\n \"actionId\": \"surface.open\",\n \"payload\": {\n \"presentation\": \"modal\",\n \"title\": \"Participant capabilities\",\n \"icon\": \"bolt\",\n \"subtitle\": \"Canonical capabilities entrypoint for the selected participant\",\n \"size\": { \"width\": \"720px\", \"maxWidth\": \"90vw\" },\n \"widget\": {\n \"id\": \"widget:rich-text-block\",\n \"inputs\": {\n \"title\": \"Capabilities for ${item.funcionarioNome}\",\n \"content\": \"Use the canonical HATEOAS capabilities link to inspect the operations available for this participant: ${item._links.capabilities.href}. The list action is executed through surface.open, so the runtime gives immediate feedback without host-local action glue.\",\n \"variant\": \"emphasis\"\n }\n }\n }\n },\n \"emitLocal\": false,\n \"showLoading\": true,\n \"placement\": \"actions\"\n }\n ],\n \"ui\": {\n \"showSearch\": false,\n \"showSort\": true,\n \"sortOptions\": [\n { \"label\": \"ID\", \"value\": \"id,asc\" },\n { \"label\": \"Role\", \"value\": \"papel,asc\" }\n ],\n \"showRange\": true\n },\n \"a11y\": {\n \"ariaLabel\": \"Remote mission participants list\"\n }\n }\n },\n \"outputs\": {\n \"itemClick\": \"emit\",\n \"actionClick\": \"emit\",\n \"selectionChange\": \"emit\"\n }\n }\n }\n ]\n }\n}\n",
3283
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.remote-list.json",
3296
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.remote-list.json",
3284
3297
  "contentHash": "af493f4125f52276c7889b1862496f6995addb36bc4941fefc5da0d32caa8dcc",
3285
3298
  "sourceKind": "component_definition",
3286
3299
  "sourceId": "praxis-dynamic-page",
@@ -3290,7 +3303,7 @@
3290
3303
  "chunkIndex": 40,
3291
3304
  "chunkKind": "recipe",
3292
3305
  "content": "{\n \"_comment\": \"Praxis Dynamic Page recipe that demonstrates praxis-rich-content as a reusable knowledge surface for policy, metrics, timelines and AI-readable operational guidance.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"rich-content-knowledge-surface\",\n \"status\": \"public-example\",\n \"useWhen\": \"Create a Dynamic Page with rich presentation surfaces and host-mediated actions instead of custom explanatory Angular templates.\",\n \"examplePrompts\": [\n \"create a dynamic page with a rich policy briefing\",\n \"show praxis-rich-content with metrics and timeline\",\n \"generate an AI-readable knowledge surface\",\n \"show host-mediated rich content actions in dynamic page\"\n ]\n },\n \"platformValue\": {\n \"canonicalRuntime\": \"@praxisui/rich-content owns RichContentDocument rendering.\",\n \"hostMediation\": \"praxis-dynamic-page injects hostCapabilities at runtime for hosted praxis-rich-content widgets.\",\n \"publicExamples\": \"praxis-ui-landing-page exposes the live preview and inspector JSON.\",\n \"agentCorpus\": \"This recipe keeps agents on portable nodes, separates rich presentation from editable data widgets and makes host-mediated actions explicit without serializing runtime helpers.\"\n },\n \"authoringGuidance\": [\n \"Use definition.id \\\"praxis-rich-content\\\".\",\n \"Pass a canonical document through inputs.document for block surfaces.\",\n \"Pass inputs.nodes plus layout \\\"inline\\\" for compact ribbons or cell-style content.\",\n \"Use context and *Expr fields for host-state interpolation.\",\n \"Use actionButton plus action.actionId when the host should mediate an action instead of embedding handler code in the document.\",\n \"Use action.confirmMessage for governed confirmation. Hosted praxis-rich-content calls hostCapabilities.confirmAction first and fails closed without dispatch when the host omits or rejects confirmation.\",\n \"Use requiresCapabilities for nodes that should appear only when the hosting runtime exposes the required capability snapshot.\",\n \"Do not serialize hostCapabilities inside the page JSON; praxis-dynamic-page injects that runtime capability bridge only while rendering hosted praxis-rich-content widgets.\",\n \"Do not use rich-content as a replacement for table rows, form fields or list records.\"\n ],\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 1,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"missionKnowledgeBriefing\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"article\",\n \"title\": \"Mission knowledge briefing\",\n \"subtitle\": \"Policy, metrics and timeline authored as RichContentDocument\"\n },\n \"definition\": {\n \"id\": \"praxis-rich-content\",\n \"bindingOrder\": [\n \"document\",\n \"context\",\n \"layout\",\n \"rootClassName\"\n ],\n \"inputs\": {\n \"layout\": \"block\",\n \"rootClassName\": \"dynamic-page-rich-content-knowledge-surface\",\n \"context\": {\n \"mission\": {\n \"name\": \"Operation Dawn Gate\",\n \"owner\": \"Ariadne Ops\",\n \"readiness\": 82,\n \"risk\": \"Elevated\",\n \"semanticRisk\": \"medium\",\n \"governanceStatus\": \"published\",\n \"region\": \"South Atlantic\"\n },\n \"policy\": {\n \"owner\": \"Platform Governance\",\n \"version\": \"2026.04\",\n \"source\": \"Quickstart reference contract\",\n \"lastReviewed\": \"2026-04-18\",\n \"cueCount\": 3,\n \"cueCaption\": \"governed cues\"\n }\n },\n \"document\": {\n \"kind\": \"praxis.rich-content\",\n \"version\": \"1.0.0\",\n \"nodes\": [\n {\n \"id\": \"governed-decision-brief\",\n \"type\": \"decisionPackage\",\n \"titleExpr\": \"${mission.name}\",\n \"subtitleExpr\": \"${policy.source}\",\n \"summary\": \"Governed semantic briefing authored from the reference contract: readiness, risk, owner and policy version stay portable as one RichContentDocument while the host owns runtime actions.\",\n \"statusExpr\": \"${mission.governanceStatus}\",\n \"ownerExpr\": \"${policy.owner}\",\n \"policySourceExpr\": \"${policy.source}\",\n \"versionExpr\": \"${policy.version}\",\n \"confidenceExpr\": \"${mission.readiness}\",\n \"riskExpr\": \"${mission.semanticRisk}\",\n \"lastReviewedExpr\": \"${policy.lastReviewed}\",\n \"evidence\": [\n {\n \"id\": \"quickstart-contract\",\n \"label\": \"Reference contract\",\n \"source\": \"schemas.filtered\"\n },\n {\n \"id\": \"ai-authoring\",\n \"label\": \"AI-authored decision\",\n \"source\": \"RichContentDocument\"\n }\n ],\n \"primaryAction\": {\n \"type\": \"actionButton\",\n \"label\": \"Inspect decision package\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"mission.decision.inspect\"\n }\n },\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Open evidence\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"mission.evidence.open\"\n }\n }\n ],\n \"accessibility\": {\n \"role\": \"article\",\n \"ariaLabel\": \"Governed semantic decision briefing\"\n }\n },\n {\n \"type\": \"card\",\n \"title\": \"Compact policy note\",\n \"subtitle\": \"Outlined / neutral / compact / leading icon\",\n \"variant\": \"outlined\",\n \"tone\": \"neutral\",\n \"size\": \"sm\",\n \"density\": \"compact\",\n \"orientation\": \"horizontal\",\n \"media\": {\n \"kind\": \"icon\",\n \"icon\": \"policy\",\n \"label\": \"Policy note\",\n \"placement\": \"leading\"\n },\n \"accessibility\": {\n \"role\": \"group\",\n \"ariaLabel\": \"Compact neutral policy card with leading policy icon\"\n },\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": \"Dense policy hints can stay readable when media, tags and body copy are balanced inside one portable card.\"\n },\n {\n \"type\": \"compose\",\n \"wrap\": true,\n \"gap\": \"xs\",\n \"items\": [\n {\n \"type\": \"badge\",\n \"label\": \"policy hint\"\n },\n {\n \"type\": \"badge\",\n \"label\": \"dense\"\n },\n {\n \"type\": \"badge\",\n \"label\": \"portable\"\n }\n ]\n },\n {\n \"type\": \"metric\",\n \"label\": \"Signal\",\n \"valueExpr\": \"${policy.cueCount}\",\n \"captionExpr\": \"${policy.cueCaption}\"\n }\n ]\n },\n {\n \"type\": \"card\",\n \"title\": \"Reusable decision package\",\n \"subtitle\": \"Filled / success / selectable\",\n \"variant\": \"filled\",\n \"tone\": \"success\",\n \"size\": \"md\",\n \"density\": \"comfortable\",\n \"orientation\": \"horizontal\",\n \"active\": true,\n \"media\": {\n \"kind\": \"image\",\n \"src\": \"/examples/rich-content/reusable-decision-package-portrait.png\",\n \"alt\": \"Generated portrait of a verified reusable decision package with approval lineage\",\n \"placement\": \"leading\",\n \"aspectRatio\": \"3 / 4\"\n },\n \"interaction\": {\n \"mode\": \"selectable\",\n \"selected\": true\n },\n \"accessibility\": {\n \"role\": \"button\",\n \"ariaLabel\": \"Selected reusable decision package card\"\n },\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": \"Selectable cards can express governed choices while keeping the host responsible for persistence and action routing.\"\n },\n {\n \"type\": \"compose\",\n \"wrap\": true,\n \"gap\": \"sm\",\n \"items\": [\n {\n \"type\": \"badge\",\n \"label\": \"selected\"\n },\n {\n \"type\": \"badge\",\n \"label\": \"active\"\n },\n {\n \"type\": \"badge\",\n \"label\": \"portrait media\"\n },\n {\n \"type\": \"badge\",\n \"label\": \"92% confidence\"\n }\n ]\n }\n ]\n },\n {\n \"type\": \"card\",\n \"title\": \"Risk review checkpoint\",\n \"subtitle\": \"Transparent / warning / top generated media\",\n \"variant\": \"transparent\",\n \"tone\": \"warning\",\n \"size\": \"md\",\n \"density\": \"comfortable\",\n \"orientation\": \"vertical\",\n \"media\": {\n \"kind\": \"image\",\n \"src\": \"/examples/rich-content/risk-review-checkpoint.png\",\n \"alt\": \"Generated warning checkpoint dashboard with audit trail and review markers\",\n \"placement\": \"top\",\n \"aspectRatio\": \"21 / 9\"\n },\n \"headerAction\": {\n \"type\": \"actionButton\",\n \"label\": \"Review\",\n \"icon\": \"rule\",\n \"variant\": \"stroked\",\n \"color\": \"accent\",\n \"action\": {\n \"actionId\": \"reviewRiskCheckpoint\",\n \"payload\": {\n \"source\": \"rich-content-card-gallery\",\n \"checkpoint\": \"risk-review\"\n }\n }\n },\n \"accessibility\": {\n \"role\": \"article\",\n \"ariaLabel\": \"Risk review checkpoint card with generated warning image\"\n },\n \"content\": [\n {\n \"type\": \"compose\",\n \"wrap\": true,\n \"gap\": \"sm\",\n \"items\": [\n {\n \"type\": \"badge\",\n \"label\": \"warning\"\n },\n {\n \"type\": \"badge\",\n \"label\": \"generated image\"\n },\n {\n \"type\": \"badge\",\n \"label\": \"header action\"\n }\n ]\n },\n {\n \"type\": \"text\",\n \"text\": \"Header actions keep secondary affordances visible without turning every card into a host-specific wrapper.\"\n }\n ]\n },\n {\n \"type\": \"card\",\n \"title\": \"Escalation context\",\n \"subtitle\": \"Plain / danger / background media\",\n \"variant\": \"plain\",\n \"tone\": \"danger\",\n \"size\": \"sm\",\n \"density\": \"compact\",\n \"orientation\": \"vertical\",\n \"media\": {\n \"kind\": \"image\",\n \"src\": \"/examples/rich-content/danger-escalation-gate.png\",\n \"alt\": \"Generated blocked decision package paused behind a red escalation gate\",\n \"placement\": \"background\",\n \"aspectRatio\": \"21 / 9\"\n },\n \"accessibility\": {\n \"role\": \"article\",\n \"ariaLabel\": \"Plain danger escalation context card with background icon\"\n },\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": \"Use danger tone for blocked or escalated decisions that need immediate human attention before publication.\"\n },\n {\n \"type\": \"compose\",\n \"wrap\": true,\n \"gap\": \"xs\",\n \"items\": [\n {\n \"type\": \"icon\",\n \"icon\": \"priority_high\",\n \"ariaLabel\": \"High priority\"\n },\n {\n \"type\": \"badge\",\n \"label\": \"danger\"\n },\n {\n \"type\": \"badge\",\n \"label\": \"generated background\"\n }\n ]\n }\n ]\n },\n {\n \"type\": \"card\",\n \"title\": \"Published visual evidence\",\n \"subtitle\": \"Elevated / info / image media\",\n \"variant\": \"elevated\",\n \"tone\": \"info\",\n \"size\": \"md\",\n \"density\": \"comfortable\",\n \"orientation\": \"vertical\",\n \"media\": {\n \"kind\": \"image\",\n \"src\": \"/examples/rich-content/governed-evidence-publication.png\",\n \"alt\": \"Generated governed evidence publication surface with verified decision document\",\n \"placement\": \"top\",\n \"aspectRatio\": \"21 / 9\"\n },\n \"accessibility\": {\n \"role\": \"article\",\n \"ariaLabel\": \"Info card with top image media\"\n },\n \"content\": [\n {\n \"type\": \"compose\",\n \"wrap\": true,\n \"gap\": \"sm\",\n \"items\": [\n {\n \"type\": \"badge\",\n \"label\": \"image\"\n },\n {\n \"type\": \"badge\",\n \"label\": \"top media\"\n },\n {\n \"type\": \"badge\",\n \"label\": \"elevated\"\n }\n ]\n },\n {\n \"type\": \"text\",\n \"text\": \"Image media is useful for evidence cards, product explainers and visual attachments without leaving the canonical document contract.\"\n }\n ]\n },\n {\n \"type\": \"card\",\n \"title\": \"Governed next step\",\n \"subtitle\": \"Outlined / action mode / button semantics\",\n \"variant\": \"outlined\",\n \"tone\": \"success\",\n \"size\": \"md\",\n \"density\": \"comfortable\",\n \"orientation\": \"horizontal\",\n \"media\": {\n \"kind\": \"icon\",\n \"icon\": \"rocket_launch\",\n \"label\": \"Publish\",\n \"placement\": \"leading\"\n },\n \"interaction\": {\n \"mode\": \"action\",\n \"action\": {\n \"actionId\": \"publishDecisionPreview\",\n \"payload\": {\n \"source\": \"rich-content-card-gallery\",\n \"step\": \"publish-preview\"\n }\n }\n },\n \"accessibility\": {\n \"role\": \"button\",\n \"ariaLabel\": \"Publish decision preview action card\"\n },\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": \"Action cards can be keyboard-focusable semantic buttons while the host still owns authorization, routing and side effects.\"\n },\n {\n \"type\": \"compose\",\n \"wrap\": true,\n \"gap\": \"xs\",\n \"items\": [\n {\n \"type\": \"badge\",\n \"label\": \"action\"\n },\n {\n \"type\": \"badge\",\n \"label\": \"keyboard ready\"\n },\n {\n \"type\": \"badge\",\n \"label\": \"host mediated\"\n }\n ]\n }\n ]\n },\n {\n \"type\": \"card\",\n \"title\": \"Quiet reference card\",\n \"subtitle\": \"Transparent / neutral / trailing avatar\",\n \"variant\": \"transparent\",\n \"tone\": \"neutral\",\n \"size\": \"sm\",\n \"density\": \"compact\",\n \"orientation\": \"horizontal\",\n \"media\": {\n \"kind\": \"avatar\",\n \"label\": \"QA\",\n \"placement\": \"trailing\"\n },\n \"accessibility\": {\n \"role\": \"group\",\n \"ariaLabel\": \"Quiet neutral reference card with trailing avatar\"\n },\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": \"Transparent neutral cards work well for secondary notes, attribution and compact reference material.\"\n }\n ]\n },\n {\n \"type\": \"card\",\n \"title\": \"Approval pending\",\n \"subtitle\": \"Filled / warning / compact leading status\",\n \"variant\": \"filled\",\n \"tone\": \"warning\",\n \"size\": \"sm\",\n \"density\": \"compact\",\n \"orientation\": \"horizontal\",\n \"loading\": true,\n \"media\": {\n \"kind\": \"icon\",\n \"icon\": \"hourglass_top\",\n \"label\": \"Pending\",\n \"placement\": \"leading\"\n },\n \"accessibility\": {\n \"role\": \"article\",\n \"ariaLabel\": \"Warning card showing a pending loading state\"\n },\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": \"Loading state communicates that the card is waiting for a governed publication or approval snapshot.\"\n },\n {\n \"type\": \"compose\",\n \"wrap\": true,\n \"gap\": \"xs\",\n \"items\": [\n {\n \"type\": \"badge\",\n \"label\": \"pending\"\n },\n {\n \"type\": \"badge\",\n \"label\": \"compact status\"\n }\n ]\n }\n ]\n },\n {\n \"id\": \"decision-provenance-note\",\n \"type\": \"mediaBlock\",\n \"avatar\": {\n \"type\": \"avatar\",\n \"initials\": \"AI\",\n \"name\": \"AI-authored decision\"\n },\n \"title\": {\n \"type\": \"text\",\n \"text\": \"Authoring evidence\"\n },\n \"subtitle\": {\n \"type\": \"text\",\n \"text\": \"Policy context, ownership and runtime boundaries travel with the document; editable business data remains in forms, tables and governed host services.\"\n },\n \"meta\": {\n \"type\": \"badge\",\n \"label\": \"runtime-safe JSON\"\n },\n \"trailing\": [\n {\n \"type\": \"icon\",\n \"icon\": \"psychology\",\n \"ariaLabel\": \"AI ready\"\n }\n ]\n },\n {\n \"id\": \"decision-lifecycle\",\n \"type\": \"timeline\",\n \"title\": \"Decision lifecycle\",\n \"orientation\": \"horizontal\",\n \"order\": \"reverse\",\n \"position\": \"alternate\",\n \"connectorVariant\": \"dashed\",\n \"markerVariant\": \"number\",\n \"markerColor\": \"primary\",\n \"emphasis\": \"strong\",\n \"density\": \"spacious\",\n \"textAppearance\": \"prominent\",\n \"style\": {\n \"--prx-rich-timeline-item-body-background\": \"color-mix(in srgb, var(--md-sys-color-primary, #6750a4) 8%, transparent)\",\n \"--prx-rich-timeline-item-body-border\": \"1px solid color-mix(in srgb, var(--md-sys-color-primary, #6750a4) 28%, transparent)\",\n \"--prx-rich-timeline-item-body-border-radius\": \"8px\",\n \"--prx-rich-timeline-item-body-padding\": \"14px\"\n },\n \"items\": [\n {\n \"icon\": \"schema\",\n \"title\": \"Grounded\",\n \"subtitle\": \"Resolve the canonical contract and classify the surface as explanation, data or action before rendering.\",\n \"meta\": \"schemas.filtered + recipes\",\n \"opposite\": \"1. Ground\",\n \"badge\": \"source\"\n },\n {\n \"icon\": \"article\",\n \"title\": \"Authored\",\n \"subtitle\": \"Publish briefing, metrics and evidence as a portable RichContentDocument instead of a local Angular template.\",\n \"meta\": \"praxis-rich-content\",\n \"opposite\": \"2. Author\",\n \"badge\": \"runtime\"\n },\n {\n \"icon\": \"open_in_new\",\n \"title\": \"Materialized\",\n \"subtitle\": \"Reuse the same semantic decision package in tabs, dialogs, steppers, list expansion or dashboard cells.\",\n \"meta\": \"Dynamic Page composition\",\n \"opposite\": \"3. Publish\",\n \"badge\": \"portable\"\n }\n ]\n }\n ]\n }\n }\n }\n },\n {\n \"key\": \"missionKnowledgeStatusRibbon\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"fact_check\",\n \"title\": \"Inline status ribbon\",\n \"subtitle\": \"Compact rich-content nodes for toolbar and table-cell style affordances\"\n },\n \"definition\": {\n \"id\": \"praxis-rich-content\",\n \"bindingOrder\": [\n \"nodes\",\n \"context\",\n \"layout\",\n \"rootClassName\"\n ],\n \"inputs\": {\n \"layout\": \"inline\",\n \"rootClassName\": \"dynamic-page-rich-content-inline-status\",\n \"context\": {\n \"status\": {\n \"icon\": \"verified\",\n \"label\": \"Governed knowledge surface\",\n \"phase\": \"Reusable\"\n }\n },\n \"nodes\": [\n {\n \"type\": \"icon\",\n \"icon\": \"verified\",\n \"ariaLabel\": \"Verified\"\n },\n {\n \"type\": \"text\",\n \"textExpr\": \"${status.label}\"\n },\n {\n \"type\": \"badge\",\n \"labelExpr\": \"${status.phase}\"\n }\n ]\n }\n }\n },\n {\n \"key\": \"missionKnowledgeHostMediation\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"hub\",\n \"title\": \"Host-mediated editorial actions\",\n \"subtitle\": \"Action buttons and capability-gated blocks resolved by praxis-dynamic-page at runtime\"\n },\n \"definition\": {\n \"id\": \"praxis-rich-content\",\n \"bindingOrder\": [\n \"document\",\n \"context\"\n ],\n \"inputs\": {\n \"context\": {\n \"selectedRecord\": {\n \"name\": \"Carla Mendes\",\n \"department\": \"Platform Governance\",\n \"status\": \"Needs review\",\n \"recordId\": \"employee-42\"\n },\n \"pageRuntime\": {\n \"capability\": \"page.widget.configurable\",\n \"actionChannel\": \"customAction or GlobalActionService\"\n }\n },\n \"document\": {\n \"kind\": \"praxis.rich-content\",\n \"version\": \"1.0.0\",\n \"nodes\": [\n {\n \"type\": \"callout\",\n \"tone\": \"info\",\n \"icon\": \"hub\",\n \"title\": \"Runtime host mediation\",\n \"message\": \"Hosted praxis-rich-content widgets can trigger governed actions and capability-gated editorial blocks without persisting runtime helpers in WidgetPageDefinition.\",\n \"actions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Open details\",\n \"icon\": \"open_in_new\",\n \"variant\": \"stroked\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"openDetails\",\n \"confirmMessage\": \"Confirm opening the governed details package?\",\n \"payload\": {\n \"source\": \"rich-content-knowledge-surface\",\n \"widgetKey\": \"missionKnowledgeHostMediation\"\n }\n }\n }\n ]\n },\n {\n \"type\": \"recordSummary\",\n \"titleExpr\": \"${selectedRecord.name}\",\n \"subtitleExpr\": \"${selectedRecord.department}\",\n \"metaExpr\": \"${pageRuntime.actionChannel}\",\n \"fields\": [\n {\n \"label\": \"Status\",\n \"valueExpr\": \"${selectedRecord.status}\"\n },\n {\n \"label\": \"Capability gate\",\n \"valueExpr\": \"${pageRuntime.capability}\"\n },\n {\n \"label\": \"Persistence rule\",\n \"value\": \"Persist only document/context; never persist hostCapabilities\"\n }\n ],\n \"actions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Inspect widget settings\",\n \"icon\": \"settings\",\n \"variant\": \"flat\",\n \"color\": \"accent\",\n \"action\": {\n \"actionId\": \"openWidgetSettings\",\n \"payloadExpr\": \"${selectedRecord}\"\n }\n }\n ]\n },\n {\n \"type\": \"statGroup\",\n \"title\": \"Governed host metrics\",\n \"subtitle\": \"Portable KPI summary owned by the rich-content document\",\n \"layout\": \"grid\",\n \"items\": [\n {\n \"label\": \"Capability gates\",\n \"value\": \"1\",\n \"captionExpr\": \"${pageRuntime.capability}\",\n \"icon\": \"shield\"\n },\n {\n \"label\": \"Action channel\",\n \"value\": \"2\",\n \"captionExpr\": \"${pageRuntime.actionChannel}\",\n \"icon\": \"hub\"\n },\n {\n \"label\": \"Selection status\",\n \"valueExpr\": \"${selectedRecord.status}\",\n \"captionExpr\": \"${selectedRecord.recordId}\",\n \"icon\": \"person_search\"\n }\n ]\n },\n {\n \"type\": \"tabs\",\n \"title\": \"Governed host views\",\n \"subtitle\": \"One portable document organizing multiple editorial panels without host-specific tab markup.\",\n \"appearance\": \"underline\",\n \"defaultTabId\": \"overview\",\n \"items\": [\n {\n \"id\": \"overview\",\n \"label\": \"Overview\",\n \"icon\": \"dashboard\",\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": \"Tabs keep explanatory panels, summaries and governed actions inside the canonical RichContentDocument instead of forcing each host to invent its own tab container.\"\n }\n ]\n },\n {\n \"id\": \"selection\",\n \"label\": \"Selection\",\n \"icon\": \"person_search\",\n \"badgeExpr\": \"${selectedRecord.status}\",\n \"content\": [\n {\n \"type\": \"keyValueList\",\n \"layout\": \"stacked\",\n \"items\": [\n {\n \"label\": \"Selected record\",\n \"valueExpr\": \"${selectedRecord.name}\"\n },\n {\n \"label\": \"Department\",\n \"valueExpr\": \"${selectedRecord.department}\"\n },\n {\n \"label\": \"Portability rule\",\n \"value\": \"Selected record context stays portable across host surfaces.\"\n }\n ]\n }\n ]\n }\n ]\n },\n {\n \"type\": \"ctaGroup\",\n \"title\": \"Next steps\",\n \"subtitle\": \"Choose the governed host action\",\n \"message\": \"Use a semantic CTA cluster when the host must expose multiple governed next steps from one portable document.\",\n \"layout\": \"split\",\n \"actions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Open governed lookup\",\n \"icon\": \"open_in_new\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"openDetails\",\n \"confirmMessage\": \"Confirm opening the governed lookup?\",\n \"payloadExpr\": \"${selectedRecord}\"\n }\n },\n {\n \"type\": \"actionButton\",\n \"label\": \"Inspect widget settings\",\n \"icon\": \"settings\",\n \"variant\": \"stroked\",\n \"action\": {\n \"actionId\": \"openWidgetSettings\",\n \"payloadExpr\": \"${selectedRecord}\"\n }\n }\n ]\n },\n {\n \"type\": \"relatedRecord\",\n \"title\": \"Reports to\",\n \"subtitleExpr\": \"${selectedRecord.name}\",\n \"relationLabel\": \"Manager record\",\n \"metaExpr\": \"${selectedRecord.department}\",\n \"ctaLabel\": \"Open related manager\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"openDetails\",\n \"confirmMessage\": \"Confirm opening the related manager record?\",\n \"payloadExpr\": \"${selectedRecord}\"\n },\n \"fields\": [\n {\n \"label\": \"Selection status\",\n \"valueExpr\": \"${selectedRecord.status}\",\n \"hint\": \"Resolved from the same selected record context.\"\n }\n ],\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Inspect related settings\",\n \"icon\": \"settings\",\n \"variant\": \"stroked\",\n \"color\": \"accent\",\n \"action\": {\n \"actionId\": \"openWidgetSettings\",\n \"payloadExpr\": \"${selectedRecord}\"\n }\n }\n ]\n },\n {\n \"type\": \"actionCard\",\n \"title\": \"Inspect governed package\",\n \"subtitleExpr\": \"${selectedRecord.department}\",\n \"message\": \"Use actionCard when the host must execute a governed workflow from an editorial surface without embedding handlers in the document.\",\n \"metaExpr\": \"${pageRuntime.actionChannel}\",\n \"ctaLabel\": \"Inspect governed package\",\n \"variant\": \"raised\",\n \"color\": \"primary\",\n \"action\": {\n \"actionId\": \"openDetails\",\n \"confirmMessage\": \"Confirm inspecting this governed package?\",\n \"payloadExpr\": \"${selectedRecord}\"\n },\n \"secondaryActions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Inspect widget settings\",\n \"icon\": \"settings\",\n \"variant\": \"stroked\",\n \"color\": \"accent\",\n \"action\": {\n \"actionId\": \"openWidgetSettings\",\n \"payloadExpr\": \"${selectedRecord}\"\n }\n }\n ]\n },\n {\n \"type\": \"disclosure\",\n \"title\": \"Visible only when the page host exposes widget configuration capability\",\n \"subtitle\": \"This block stays in the document but the host decides whether it renders\",\n \"appearance\": \"card\",\n \"defaultExpanded\": true,\n \"requiresCapabilities\": [\n \"page.widget.configurable\"\n ],\n \"content\": [\n {\n \"type\": \"keyValueList\",\n \"layout\": \"stacked\",\n \"items\": [\n {\n \"label\": \"Capability source\",\n \"value\": \"DynamicWidgetPageComponent hostCapabilities.hasCapability\"\n },\n {\n \"label\": \"Action dispatch\",\n \"value\": \"hostCapabilities.dispatchAction resolves GlobalActionService first and falls back to customAction\"\n },\n {\n \"label\": \"Persisted contract\",\n \"value\": \"definition.inputs.document remains the only canonical rich-content payload in the page JSON\"\n }\n ]\n }\n ]\n },\n {\n \"type\": \"emptyState\",\n \"icon\": \"data_object\",\n \"title\": \"Do not serialize runtime bridges\",\n \"message\": \"This recipe intentionally omits hostCapabilities from definition.inputs. Runtime helpers belong to the page host, not to the persisted recipe.\",\n \"actions\": [\n {\n \"type\": \"actionButton\",\n \"label\": \"Refresh host state\",\n \"icon\": \"refresh\",\n \"variant\": \"basic\",\n \"action\": {\n \"actionId\": \"refreshHostState\",\n \"payload\": {\n \"recordId\": \"employee-42\"\n }\n }\n }\n ]\n }\n ]\n }\n }\n }\n }\n ]\n }\n}\n",
3293
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.rich-content-knowledge-surface.json",
3306
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.rich-content-knowledge-surface.json",
3294
3307
  "contentHash": "806441c20f649b84fe5e46a605dbbdbce3d24bda090d947f86a6acb4dc21484b",
3295
3308
  "sourceKind": "component_definition",
3296
3309
  "sourceId": "praxis-dynamic-page",
@@ -3300,7 +3313,7 @@
3300
3313
  "chunkIndex": 41,
3301
3314
  "chunkKind": "recipe",
3302
3315
  "content": "{\n \"_comment\": \"Recipe para agentes criarem uma Praxis Dynamic Page com tabela rica sobre o quickstart publicado.\",\n \"_comment2\": \"Use quando a meta for demonstrar renderers, formatters e configuracao de coluna em praxis-table sem mudar o backend.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"rich-table-surface\",\n \"status\": \"public-example\",\n \"useWhen\": \"Create a metadata-driven page that turns one resource table into a rich operational surface with explicit renderers and formatters.\",\n \"examplePrompts\": [\n \"crie uma tabela rica de funcionarios com avatar, badges, salario e datas\",\n \"gere um exemplo de praxis-table mostrando renderers e formatters\",\n \"monte uma dynamic page com tabela operacional usando o quickstart publicado\"\n ]\n },\n \"platformValue\": {\n \"canonicalContract\": \"praxis-metadata-starter publishes the structural funcionarios schema through /schemas/filtered.\",\n \"referenceApi\": \"praxis-api-quickstart serves funcionarios data and options on Render.\",\n \"angularRuntime\": \"@praxisui/core resolves praxis-dynamic-page and @praxisui/table renders the configured table.\",\n \"publicExamples\": \"praxis-ui-landing-page exposes the JSON envelope, live runtime preview and capability coverage map.\",\n \"agentCorpus\": \"praxisui-http-examples provides executable metadata and filter evidence.\"\n },\n \"operationalEvidence\": {\n \"baseUrl\": \"https://praxis-api-quickstart.onrender.com\",\n \"safeFirstIds\": [\n \"filtered-schema-response-funcionarios\",\n \"funcionarios-filter-basic\"\n ],\n \"httpExamples\": [\n \"praxisui-http-examples/http/metadata/filtered_schema_response_funcionarios.http\",\n \"praxisui-http-examples/http/resources/funcionarios_filter_basic.http\"\n ]\n },\n \"authoringGuidance\": [\n \"Keep resourcePath as the base resource path, without /filter.\",\n \"Let /schemas/filtered provide the canonical field metadata.\",\n \"Use host-authored columns only to demonstrate renderers, formatting, width, sticky columns and visual density.\",\n \"Prefer renderer examples that map to real backend fields; do not invent frontend-only fields for a remote example.\",\n \"Keep status presentation read-only unless a real backend action is configured.\",\n \"Treat salary as sensitive demonstration data; real hosts should gate visibility and exports through policy.\",\n \"Emit rowClick and selectionChange so the page can later compose this table with forms, charts or actions.\"\n ],\n \"teaches\": [\n \"table.renderers.avatar\",\n \"table.renderers.badge\",\n \"table.renderers.chip\",\n \"table.conditional-renderers.status-badge\",\n \"table.formatters.currency\",\n \"table.formatters.date\",\n \"table.selection-state\"\n ],\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 1,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"funcionariosRichTable\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"table\",\n \"title\": \"Funcionarios rich surface\",\n \"subtitle\": \"Renderers, formatters and dense business columns\"\n },\n \"definition\": {\n \"id\": \"praxis-table\",\n \"bindingOrder\": [\"config\", \"resourcePath\"],\n \"inputs\": {\n \"resourcePath\": \"human-resources/funcionarios\",\n \"tableId\": \"human-resources-funcionarios-rich-surface\",\n \"config\": {\n \"toolbar\": {\n \"visible\": true,\n \"title\": \"Funcionarios\",\n \"subtitle\": \"Rich metadata-driven employee surface\"\n },\n \"columns\": [\n {\n \"field\": \"avatarUrl\",\n \"header\": \"Avatar\",\n \"type\": \"string\",\n \"renderer\": {\n \"type\": \"avatar\",\n \"avatar\": {\n \"srcField\": \"avatarUrl\",\n \"altField\": \"nomeCompleto\",\n \"initialsField\": \"nomeCompleto\",\n \"shape\": \"circle\",\n \"size\": 36\n }\n },\n \"width\": \"88px\",\n \"sticky\": \"start\"\n },\n {\n \"field\": \"nomeCompleto\",\n \"header\": \"Nome Completo\",\n \"type\": \"string\",\n \"sticky\": \"start\",\n \"width\": \"220px\"\n },\n {\n \"field\": \"email\",\n \"header\": \"Email\",\n \"type\": \"string\",\n \"width\": \"260px\"\n },\n {\n \"field\": \"telefone\",\n \"header\": \"Telefone\",\n \"type\": \"string\",\n \"width\": \"160px\"\n },\n {\n \"field\": \"salario\",\n \"header\": \"Salario\",\n \"type\": \"currency\",\n \"align\": \"end\",\n \"format\": \"BRL|symbol|2\",\n \"width\": \"150px\"\n },\n {\n \"field\": \"cargoNome\",\n \"header\": \"Cargo\",\n \"type\": \"string\",\n \"renderer\": {\n \"type\": \"chip\",\n \"chip\": {\n \"textField\": \"cargoNome\",\n \"variant\": \"outlined\",\n \"color\": \"primary\"\n }\n },\n \"width\": \"190px\"\n },\n {\n \"field\": \"departamentoNome\",\n \"header\": \"Departamento\",\n \"type\": \"string\",\n \"renderer\": {\n \"type\": \"badge\",\n \"badge\": {\n \"textField\": \"departamentoNome\",\n \"variant\": \"soft\",\n \"color\": \"accent\"\n }\n },\n \"width\": \"180px\"\n },\n {\n \"field\": \"estadoCivil\",\n \"header\": \"Estado Civil\",\n \"type\": \"string\",\n \"renderer\": {\n \"type\": \"badge\",\n \"badge\": {\n \"textField\": \"estadoCivil\",\n \"variant\": \"outlined\",\n \"color\": \"primary\"\n }\n },\n \"width\": \"150px\"\n },\n {\n \"field\": \"dataAdmissao\",\n \"header\": \"Data de Admissao\",\n \"type\": \"date\",\n \"format\": \"dd/MM/yyyy\",\n \"width\": \"170px\"\n },\n {\n \"field\": \"dataNascimento\",\n \"header\": \"Data de Nascimento\",\n \"type\": \"date\",\n \"format\": \"dd/MM/yyyy\",\n \"width\": \"190px\"\n },\n {\n \"field\": \"ativo\",\n \"header\": \"Status\",\n \"type\": \"boolean\",\n \"align\": \"center\",\n \"format\": \"active-inactive\",\n \"width\": \"130px\",\n \"conditionalRenderers\": [\n {\n \"condition\": { \"==\": [{ \"var\": \"ativo\" }, true] },\n \"renderer\": {\n \"type\": \"badge\",\n \"badge\": {\n \"text\": \"Ativo\",\n \"color\": \"success\",\n \"variant\": \"filled\",\n \"icon\": \"check_circle\"\n }\n }\n },\n {\n \"condition\": { \"==\": [{ \"var\": \"ativo\" }, false] },\n \"renderer\": {\n \"type\": \"badge\",\n \"badge\": {\n \"text\": \"Inativo\",\n \"color\": \"warn\",\n \"variant\": \"outlined\",\n \"icon\": \"block\"\n }\n }\n }\n ]\n }\n ],\n \"behavior\": {\n \"selection\": {\n \"enabled\": true,\n \"type\": \"multiple\"\n },\n \"density\": \"compact\"\n }\n }\n },\n \"outputs\": {\n \"rowClick\": \"emit\",\n \"selectionChange\": \"emit\"\n }\n }\n }\n ]\n }\n}\n",
3303
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.rich-table-surface.json",
3316
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.rich-table-surface.json",
3304
3317
  "contentHash": "d692654ac246e7ee384f478c979b84da378f627240e999344a687640a2033587",
3305
3318
  "sourceKind": "component_definition",
3306
3319
  "sourceId": "praxis-dynamic-page",
@@ -3310,7 +3323,7 @@
3310
3323
  "chunkIndex": 42,
3311
3324
  "chunkKind": "recipe",
3312
3325
  "content": "{\n \"_comment\": \"Recipe para agentes criarem uma Praxis Dynamic Page com computed columns e conditional rules em praxis-table.\",\n \"_comment2\": \"Use quando a meta for mostrar regras de tabela, colunas calculadas e feedback visual runtime sobre dados reais.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"rules-computed-table\",\n \"status\": \"public-example\",\n \"useWhen\": \"Create a metadata-driven table example with Json Logic computed columns, conditional styles and conditional renderers.\",\n \"examplePrompts\": [\n \"crie uma tabela com colunas calculadas e regras condicionais\",\n \"mostre funcionarios com tempo de casa calculado e destaque visual\",\n \"gere um exemplo de praxis-table com conditionalRenderers e rowConditionalStyles\"\n ]\n },\n \"platformValue\": {\n \"canonicalContract\": \"praxis-metadata-starter publishes funcionarios schema and data fields; table rules stay in the Angular runtime config.\",\n \"referenceApi\": \"praxis-api-quickstart serves funcionarios rows used by computed columns and rules.\",\n \"angularRuntime\": \"@praxisui/table evaluates computed expressions and conditional table rules without bespoke host code.\",\n \"publicExamples\": \"praxis-ui-landing-page exposes this JSON envelope and coverage status.\",\n \"agentCorpus\": \"praxisui-http-examples provides executable metadata and filter evidence.\"\n },\n \"operationalEvidence\": {\n \"baseUrl\": \"https://praxis-api-quickstart.onrender.com\",\n \"safeFirstIds\": [\n \"filtered-schema-response-funcionarios\",\n \"funcionarios-filter-basic\"\n ],\n \"httpExamples\": [\n \"praxisui-http-examples/http/metadata/filtered_schema_response_funcionarios.http\",\n \"praxisui-http-examples/http/resources/funcionarios_filter_basic.http\"\n ]\n },\n \"authoringGuidance\": [\n \"Use columns[].computed.expression as canonical Json Logic, not JavaScript strings.\",\n \"Use { \\\"var\\\": \\\"field\\\" } for row data and { \\\"var\\\": \\\"computed.field\\\" } when rules depend on computed columns.\",\n \"Keep conditionalStyles focused on cell-level feedback and rowConditionalStyles focused on row-level state.\",\n \"Use conditionalRenderers when the displayed semantic state should change by rule.\",\n \"Keep the remote resourcePath as the base resource path; rules are runtime config over published rows.\"\n ],\n \"teaches\": [\n \"table.computed-columns\",\n \"table.rules.conditionalStyles\",\n \"table.rules.rowConditionalStyles\",\n \"table.rules.conditionalRenderers\",\n \"json-logic\",\n \"table.selection-state\"\n ],\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 1,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"funcionariosRulesComputedTable\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"rule\",\n \"title\": \"Funcionarios rules and computed columns\",\n \"subtitle\": \"Tenure, salary bands and conditional runtime feedback\"\n },\n \"definition\": {\n \"id\": \"praxis-table\",\n \"bindingOrder\": [\"config\", \"resourcePath\"],\n \"inputs\": {\n \"resourcePath\": \"human-resources/funcionarios\",\n \"tableId\": \"human-resources-funcionarios-rules-computed\",\n \"config\": {\n \"toolbar\": {\n \"visible\": true,\n \"title\": \"Funcionarios\",\n \"subtitle\": \"Computed columns and conditional rules\"\n },\n \"columns\": [\n {\n \"field\": \"nomeCompleto\",\n \"header\": \"Funcionario\",\n \"type\": \"text\",\n \"sticky\": \"start\",\n \"width\": \"220px\"\n },\n {\n \"field\": \"dataAdmissao\",\n \"header\": \"Admissao\",\n \"type\": \"date\",\n \"format\": {\n \"dateStyle\": \"short\",\n \"locale\": \"pt-BR\"\n },\n \"width\": \"140px\"\n },\n {\n \"field\": \"tempoCasaAnos\",\n \"header\": \"Tempo de Casa\",\n \"type\": \"number\",\n \"align\": \"end\",\n \"width\": \"150px\",\n \"computed\": {\n \"expression\": {\n \"yearsSince\": [\n {\n \"var\": \"dataAdmissao\"\n }\n ]\n },\n \"outputType\": \"number\",\n \"format\": \"1.0-0\",\n \"dependencies\": [\"dataAdmissao\"]\n },\n \"conditionalStyles\": [\n {\n \"condition\": {\n \">=\": [\n {\n \"var\": \"computed.tempoCasaAnos\"\n },\n 5\n ]\n },\n \"style\": {\n \"color\": \"#166534\",\n \"fontWeight\": \"700\"\n }\n }\n ]\n },\n {\n \"field\": \"salario\",\n \"header\": \"Salario\",\n \"type\": \"currency\",\n \"align\": \"end\",\n \"format\": {\n \"currency\": \"BRL\",\n \"locale\": \"pt-BR\"\n },\n \"width\": \"150px\",\n \"conditionalStyles\": [\n {\n \"condition\": {\n \">=\": [\n {\n \"var\": \"salario\"\n },\n 35000\n ]\n },\n \"style\": {\n \"color\": \"#7c2d12\",\n \"fontWeight\": \"700\"\n }\n }\n ]\n },\n {\n \"field\": \"faixaSalarial\",\n \"header\": \"Faixa\",\n \"type\": \"badge\",\n \"width\": \"130px\",\n \"computed\": {\n \"expression\": {\n \"if\": [\n {\n \">=\": [\n {\n \"var\": \"salario\"\n },\n 35000\n ]\n },\n \"executive\",\n {\n \">=\": [\n {\n \"var\": \"salario\"\n },\n 18000\n ]\n },\n \"senior\",\n \"standard\"\n ]\n },\n \"outputType\": \"text\",\n \"dependencies\": [\"salario\"]\n },\n \"conditionalRenderers\": [\n {\n \"condition\": {\n \"==\": [\n {\n \"var\": \"computed.faixaSalarial\"\n },\n \"executive\"\n ]\n },\n \"renderer\": {\n \"type\": \"badge\",\n \"badge\": {\n \"text\": \"Executive\",\n \"color\": \"warn\",\n \"variant\": \"filled\"\n }\n }\n },\n {\n \"condition\": {\n \"==\": [\n {\n \"var\": \"computed.faixaSalarial\"\n },\n \"senior\"\n ]\n },\n \"renderer\": {\n \"type\": \"badge\",\n \"badge\": {\n \"text\": \"Senior\",\n \"color\": \"primary\",\n \"variant\": \"soft\"\n }\n }\n }\n ]\n },\n {\n \"field\": \"departamentoNome\",\n \"header\": \"Departamento\",\n \"type\": \"chip\",\n \"width\": \"180px\"\n },\n {\n \"field\": \"ativo\",\n \"header\": \"Estado\",\n \"type\": \"badge\",\n \"width\": \"130px\",\n \"conditionalRenderers\": [\n {\n \"condition\": {\n \"==\": [\n {\n \"var\": \"ativo\"\n },\n true\n ]\n },\n \"renderer\": {\n \"type\": \"badge\",\n \"badge\": {\n \"text\": \"Ativo\",\n \"color\": \"success\",\n \"variant\": \"filled\"\n }\n }\n },\n {\n \"condition\": {\n \"==\": [\n {\n \"var\": \"ativo\"\n },\n false\n ]\n },\n \"renderer\": {\n \"type\": \"badge\",\n \"badge\": {\n \"text\": \"Inativo\",\n \"color\": \"warn\",\n \"variant\": \"outlined\"\n }\n }\n }\n ]\n }\n ],\n \"rowConditionalStyles\": [\n {\n \"condition\": {\n \"==\": [\n {\n \"var\": \"ativo\"\n },\n false\n ]\n },\n \"style\": {\n \"opacity\": \"0.68\",\n \"backgroundColor\": \"rgba(239, 68, 68, 0.08)\"\n }\n },\n {\n \"condition\": {\n \">=\": [\n {\n \"var\": \"computed.tempoCasaAnos\"\n },\n 5\n ]\n },\n \"style\": {\n \"borderLeft\": \"4px solid #16a34a\"\n }\n }\n ],\n \"behavior\": {\n \"selection\": {\n \"enabled\": true,\n \"type\": \"single\"\n },\n \"density\": \"comfortable\"\n }\n }\n },\n \"outputs\": {\n \"rowClick\": \"emit\"\n }\n }\n }\n ]\n }\n}\n",
3313
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.rules-computed-table.json",
3326
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.rules-computed-table.json",
3314
3327
  "contentHash": "2ce4e09377937be7adbf5ef32883b0d043356277886cccc8bd0241b959b9d704",
3315
3328
  "sourceKind": "component_definition",
3316
3329
  "sourceId": "praxis-dynamic-page",
@@ -3320,7 +3333,7 @@
3320
3333
  "chunkIndex": 43,
3321
3334
  "chunkKind": "recipe",
3322
3335
  "content": "{\n \"_comment\": \"Recipe for agents to create a Praxis Dynamic Page with a rich Praxis Stepper workflow.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"stepper-onboarding-workflow\",\n \"status\": \"public-example\",\n \"useWhen\": \"Create a dynamic page where praxis-stepper orchestrates form, upload and approval widgets.\",\n \"examplePrompts\": [\n \"create an onboarding workflow page\",\n \"show praxis-stepper inside praxis-dynamic-page\",\n \"generate a stepper workflow with form, files upload and approval checklist\"\n ]\n },\n \"platformValue\": {\n \"canonicalRuntime\": \"@praxisui/stepper owns steps, linear navigation, step forms, rich content and nested widget orchestration.\",\n \"angularRuntime\": \"@praxisui/core resolves the stepper and every nested widget through ComponentMetadataRegistry and DynamicWidgetLoader.\",\n \"publicExamples\": \"praxis-ui-landing-page exposes the envelope, live preview and inspector JSON.\",\n \"agentCorpus\": \"This recipe keeps agents on supported paths: steps[].form, stepBlocksBeforeForm, stepBlocksAfterForm and steps[].widgets.\"\n },\n \"authoringGuidance\": [\n \"Use stable stepperId and componentInstanceId values.\",\n \"Use steps[].form for Dynamic Form integration and put form config under steps[].form.config.\",\n \"Use RichContentDocument nodes in stepBlocksBeforeForm and stepBlocksAfterForm for editorial text and badges.\",\n \"Use steps[].widgets only for real nested runtime components.\",\n \"Do not use legacy steps[].content for runtime rendering.\"\n ],\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 1,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"employeeOnboardingStepper\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"assignment_turned_in\",\n \"title\": \"Employee onboarding workflow\",\n \"subtitle\": \"Stepper with form rules, evidence upload and approval checklist\"\n },\n \"definition\": {\n \"id\": \"praxis-stepper\",\n \"bindingOrder\": [\"stepperId\", \"componentInstanceId\", \"config\", \"stepperContext\"],\n \"inputs\": {\n \"stepperId\": \"employee-onboarding-workflow\",\n \"componentInstanceId\": \"dynamic-page-showcase\",\n \"enableCustomization\": true,\n \"stepperContext\": {\n \"workflowId\": \"employee-onboarding-demo\",\n \"resourcePath\": \"human-resources/funcionarios\",\n \"evidenceBaseUrl\": \"/api/files\"\n },\n \"config\": {\n \"orientation\": \"horizontal\",\n \"linear\": true,\n \"labelPosition\": \"bottom\",\n \"selectedIndex\": 0,\n \"density\": \"comfortable\",\n \"appearance\": {\n \"preset\": \"ft-light\",\n \"icons\": {\n \"number\": \"radio_button_unchecked\",\n \"done\": \"check_circle\",\n \"edit\": \"edit_note\",\n \"error\": \"error\"\n }\n },\n \"navigation\": {\n \"visible\": true,\n \"prevLabel\": \"Back\",\n \"nextLabel\": \"Continue\",\n \"prevIcon\": \"arrow_back\",\n \"nextIcon\": \"arrow_forward\",\n \"variant\": \"stroked\",\n \"color\": \"primary\",\n \"align\": \"space-between\"\n },\n \"steps\": [\n {\n \"id\": \"employee-intake\",\n \"label\": \"Employee\",\n \"description\": \"Capture employee identity, assignment and workflow-only risk fields.\",\n \"stepBlocksBeforeForm\": {\n \"kind\": \"praxis.rich-content\",\n \"version\": \"1.0.0\",\n \"nodes\": [\n {\n \"type\": \"text\",\n \"text\": \"The step owns its local Dynamic Form config. Backend metadata can replace this config later without changing the Stepper host template.\"\n },\n { \"type\": \"badge\", \"label\": \"form rules\" },\n { \"type\": \"badge\", \"label\": \"validators\" }\n ]\n },\n \"form\": {\n \"mode\": \"create\",\n \"formId\": \"employee-onboarding-intake-form\",\n \"schemaSource\": \"resource\",\n \"config\": {\n \"sections\": [\n {\n \"id\": \"identity\",\n \"title\": \"Identity\",\n \"appearance\": \"outlined\",\n \"rows\": [\n {\n \"id\": \"identity-row\",\n \"columns\": [\n { \"id\": \"identity-main\", \"span\": { \"md\": 6, \"lg\": 6 }, \"fields\": [\"nomeCompleto\", \"email\"] },\n { \"id\": \"identity-contact\", \"span\": { \"md\": 6, \"lg\": 6 }, \"fields\": [\"telefone\", \"dataNascimento\"] }\n ]\n }\n ]\n }\n ],\n \"fieldMetadata\": [\n {\n \"name\": \"nomeCompleto\",\n \"label\": \"Nome Completo\",\n \"controlType\": \"input\",\n \"validators\": { \"required\": true, \"minLength\": 3, \"maxLength\": 160 }\n },\n {\n \"name\": \"email\",\n \"label\": \"Email\",\n \"controlType\": \"email\",\n \"validators\": { \"required\": true, \"email\": true }\n },\n {\n \"name\": \"telefone\",\n \"label\": \"Telefone\",\n \"controlType\": \"phone\",\n \"validators\": { \"required\": true }\n },\n {\n \"name\": \"dataNascimento\",\n \"label\": \"Data de Nascimento\",\n \"controlType\": \"date\",\n \"validators\": { \"required\": true }\n }\n ]\n }\n }\n },\n {\n \"id\": \"evidence\",\n \"label\": \"Evidence\",\n \"optional\": true,\n \"widgets\": [\n {\n \"id\": \"praxis-files-upload\",\n \"inputs\": {\n \"filesUploadId\": \"employee-onboarding-evidence\",\n \"baseUrl\": \"/api/files\",\n \"displayMode\": \"compact\",\n \"config\": {\n \"strategy\": \"direct\",\n \"ui\": {\n \"showDropzone\": true,\n \"showConflictPolicySelector\": true,\n \"showMetadataForm\": true,\n \"showProgress\": true,\n \"manualUpload\": true\n },\n \"limits\": {\n \"maxFileSizeBytes\": 10485760,\n \"maxFilesPerBulk\": 4,\n \"maxBulkSizeBytes\": 31457280\n }\n }\n }\n }\n ]\n },\n {\n \"id\": \"approval\",\n \"label\": \"Approval\",\n \"widgets\": [\n {\n \"id\": \"praxis-list\",\n \"inputs\": {\n \"listId\": \"employee-onboarding-approval-checklist\",\n \"config\": {\n \"dataSource\": {\n \"data\": [\n { \"id\": 1, \"title\": \"Identity fields validated\", \"owner\": \"People Ops\", \"status\": \"Required\", \"priority\": \"P0\" },\n { \"id\": 2, \"title\": \"Evidence attached or waived\", \"owner\": \"Hiring Manager\", \"status\": \"Required\", \"priority\": \"P0\" },\n { \"id\": 3, \"title\": \"Security review completed\", \"owner\": \"Security\", \"status\": \"Conditional\", \"priority\": \"P1\" }\n ]\n },\n \"selection\": {\n \"mode\": \"multiple\",\n \"compareBy\": \"id\",\n \"return\": \"id\"\n },\n \"templating\": {\n \"leading\": { \"type\": \"icon\", \"expr\": \"task_alt\" },\n \"primary\": { \"type\": \"text\", \"expr\": \"${item.title}\" },\n \"secondary\": { \"type\": \"text\", \"expr\": \"${item.owner}\" },\n \"meta\": { \"type\": \"chip\", \"expr\": \"${item.priority}\", \"variant\": \"filled\" },\n \"trailing\": { \"type\": \"chip\", \"expr\": \"${item.status}\", \"variant\": \"outlined\" }\n }\n }\n }\n }\n ]\n }\n ]\n }\n },\n \"outputs\": {\n \"selectionChange\": \"emit\",\n \"selectedIndexChange\": \"emit\",\n \"stepFormReady\": \"emit\",\n \"stepFormValueChange\": \"emit\"\n }\n }\n }\n ]\n }\n}\n",
3323
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.stepper-onboarding-workflow.json",
3336
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.stepper-onboarding-workflow.json",
3324
3337
  "contentHash": "0e7a44c3ee8342d594fa467818ce0076ed407aa88fcd9de45338f6108ce63b49",
3325
3338
  "sourceKind": "component_definition",
3326
3339
  "sourceId": "praxis-dynamic-page",
@@ -3330,7 +3343,7 @@
3330
3343
  "chunkIndex": 44,
3331
3344
  "chunkKind": "recipe",
3332
3345
  "content": "{\n \"_comment\": \"Template de pagina com stepper (Praxis Dynamic Page).\",\n \"_comment2\": \"resourcePath deve ser o path base do recurso (sem /filter).\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"stepper\",\n \"useWhen\": \"Create a dynamic page with a stepper wizard.\",\n \"examplePrompts\": [\n \"pagina com stepper\",\n \"wizard de cadastro\",\n \"fluxo em etapas\"\n ]\n },\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 2,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"mainStepper\",\n \"definition\": {\n \"id\": \"praxis-stepper\",\n \"inputs\": {\n \"stepperId\": \"{{resourceKey}}-stepper\",\n \"config\": {\n \"orientation\": \"horizontal\",\n \"linear\": true,\n \"steps\": [\n {\n \"id\": \"step-1\",\n \"label\": \"Dados\",\n \"form\": {\n \"resourcePath\": \"{{resourcePath}}\",\n \"schemaSource\": \"resource\",\n \"mode\": \"edit\",\n \"formId\": \"{{resourceKey}}-step-1\"\n }\n },\n {\n \"id\": \"step-2\",\n \"label\": \"Detalhes\",\n \"optional\": true,\n \"form\": {\n \"resourcePath\": \"{{resourcePath}}\",\n \"schemaSource\": \"resource\",\n \"mode\": \"edit\",\n \"formId\": \"{{resourceKey}}-step-2\"\n }\n }\n ],\n \"navigation\": {\n \"visible\": true,\n \"prevLabel\": \"Voltar\",\n \"nextLabel\": \"Proximo\",\n \"finishLabel\": \"Concluir\"\n }\n }\n }\n }\n }\n ]\n }\n}\n",
3333
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.stepper.json",
3346
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.stepper.json",
3334
3347
  "contentHash": "34b81f2a987b7be601016f729dc3020c9204f1e3212fb50c1a9ddebd8d7347b5",
3335
3348
  "sourceKind": "component_definition",
3336
3349
  "sourceId": "praxis-dynamic-page",
@@ -3340,7 +3353,7 @@
3340
3353
  "chunkIndex": 45,
3341
3354
  "chunkKind": "recipe",
3342
3355
  "content": "{\n \"_comment\": \"Recipe para agentes criarem uma Praxis Dynamic Page que demonstra surfaces, actions e capabilities de ponta a ponta.\",\n \"_comment2\": \"Use quando o objetivo for mostrar contrato metadata-driven, runtime Angular, quickstart API e modais de discovery.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"surfaces-actions-showcase\",\n \"status\": \"public-example\",\n \"useWhen\": \"Create an operational page where table buttons open resource surfaces, actions and item capabilities.\",\n \"examplePrompts\": [\n \"crie uma pagina que demonstre surfaces actions e capabilities\",\n \"mostre botoes de tabela que abrem modais com metadata do backend\",\n \"gere um exemplo para agentes copiarem discovery actions do praxis dynamic page\"\n ]\n },\n \"platformValue\": {\n \"canonicalContract\": \"praxis-metadata-starter defines /schemas/filtered, /schemas/surfaces, /schemas/actions and capabilities semantics.\",\n \"referenceApi\": \"praxis-api-quickstart exposes mission resources, related team/timeline resources and item capabilities on Render.\",\n \"angularRuntime\": \"@praxisui/core resolves praxis-dynamic-page widgets; @praxisui/table emits toolbarAction and rowAction events.\",\n \"publicExamples\": \"praxis-ui-landing-page renders the JSON envelope, runtime preview, floating Inspector and discovery modal.\",\n \"agentCorpus\": \"This recipe keeps resourcePath, resourceKey and discovery metadata explicit so LLMs can preserve the platform handoff.\"\n },\n \"operationalEvidence\": {\n \"baseUrl\": \"https://praxis-api-quickstart.onrender.com\",\n \"safeFirstIds\": [\n \"schemas-catalog\",\n \"schemas-surfaces-operations-missoes\",\n \"schemas-actions-operations-missoes\",\n \"operations-missoes-item-capabilities\",\n \"vw-resumo-missoes-filter-basic\",\n \"missao-participantes-stats-papel\",\n \"missao-eventos-stats-ocorrido-em-day\"\n ],\n \"pendingHttpIds\": []\n },\n \"authoringGuidance\": [\n \"Put resource discovery in toolbar.actions so users can inspect the full resource contract before selecting a row.\",\n \"Put item discovery in actions.row and include discovery.scope = item so the host can hydrate previews with the selected id.\",\n \"Emit toolbarAction and rowAction from the widget when the host owns modal orchestration.\",\n \"Preserve resourcePath and resourceKey inside discovery metadata; do not infer them from labels or routes.\",\n \"Use composition links to keep related surfaces, such as team and timeline, synchronized with selected state.\",\n \"Treat actions in the JSON as affordances; execute policy-sensitive workflows only after checking backend capabilities.\"\n ],\n \"teaches\": [\n \"page.surfaces-actions-capabilities\",\n \"table.toolbar.actions\",\n \"table.actions.row\",\n \"toolbarAction\",\n \"rowAction\",\n \"composition.links\",\n \"state.values\"\n ],\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 3,\n \"gap\": \"16px\"\n },\n \"state\": {\n \"values\": {\n \"selection\": {\n \"missionId\": 1\n }\n }\n },\n \"widgets\": [\n {\n \"key\": \"missionSurface\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"layers\",\n \"title\": \"Mission surface\",\n \"subtitle\": \"Resource and item discovery actions\"\n },\n \"definition\": {\n \"id\": \"praxis-table\",\n \"bindingOrder\": [\n \"config\",\n \"resourcePath\"\n ],\n \"inputs\": {\n \"resourcePath\": \"operations/missoes\",\n \"tableId\": \"operations-missoes-surfaces-actions-showcase\",\n \"config\": {\n \"toolbar\": {\n \"visible\": true,\n \"title\": \"Missions\",\n \"actionsPosition\": \"both\",\n \"actions\": [\n {\n \"id\": \"inspect-surfaces\",\n \"action\": \"inspect-surfaces\",\n \"label\": \"Surfaces\",\n \"icon\": \"layers\",\n \"type\": \"button\",\n \"appearance\": \"outlined\",\n \"discovery\": {\n \"rel\": \"surfaces\",\n \"scope\": \"resource\",\n \"resourcePath\": \"operations/missoes\",\n \"resourceKey\": \"operations.missoes\"\n }\n },\n {\n \"id\": \"inspect-actions\",\n \"action\": \"inspect-actions\",\n \"label\": \"Actions\",\n \"icon\": \"bolt\",\n \"type\": \"button\",\n \"appearance\": \"outlined\",\n \"discovery\": {\n \"rel\": \"actions\",\n \"scope\": \"resource\",\n \"resourcePath\": \"operations/missoes\",\n \"resourceKey\": \"operations.missoes\"\n }\n }\n ]\n },\n \"columns\": [\n {\n \"field\": \"titulo\",\n \"header\": \"Mission\",\n \"type\": \"text\",\n \"sticky\": \"start\"\n },\n {\n \"field\": \"status\",\n \"header\": \"Status\",\n \"type\": \"badge\"\n },\n {\n \"field\": \"prioridade\",\n \"header\": \"Priority\",\n \"type\": \"badge\"\n },\n {\n \"field\": \"local\",\n \"header\": \"Location\",\n \"type\": \"text\"\n }\n ],\n \"actions\": {\n \"row\": {\n \"enabled\": true,\n \"display\": \"icons\",\n \"position\": \"end\",\n \"sticky\": \"end\",\n \"actions\": [\n {\n \"id\": \"inspect-row-surfaces\",\n \"label\": \"Surfaces\",\n \"icon\": \"layers\",\n \"action\": \"inspect-surfaces\",\n \"discovery\": {\n \"rel\": \"surfaces\",\n \"scope\": \"item\",\n \"resourcePath\": \"operations/missoes\",\n \"resourceKey\": \"operations.missoes\"\n }\n },\n {\n \"id\": \"inspect-row-actions\",\n \"label\": \"Actions\",\n \"icon\": \"bolt\",\n \"action\": \"inspect-actions\",\n \"discovery\": {\n \"rel\": \"actions\",\n \"scope\": \"item\",\n \"resourcePath\": \"operations/missoes\",\n \"resourceKey\": \"operations.missoes\"\n }\n }\n ]\n }\n },\n \"behavior\": {\n \"selection\": {\n \"enabled\": true,\n \"type\": \"single\"\n }\n }\n }\n },\n \"outputs\": {\n \"rowClick\": \"emit\",\n \"rowAction\": \"emit\",\n \"toolbarAction\": \"emit\"\n }\n }\n },\n {\n \"key\": \"missionTeamSurface\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"groups\",\n \"title\": \"Team surface\",\n \"subtitle\": \"Related resource filtered by selected mission\"\n },\n \"definition\": {\n \"id\": \"praxis-table\",\n \"bindingOrder\": [\n \"config\",\n \"resourcePath\",\n \"queryContext\"\n ],\n \"inputs\": {\n \"resourcePath\": \"operations/missao-participantes\",\n \"queryContext\": {\n \"filters\": {\n \"missaoId\": 1\n }\n },\n \"config\": {\n \"toolbar\": {\n \"visible\": true,\n \"title\": \"Team\"\n },\n \"columns\": [\n {\n \"field\": \"funcionarioNome\",\n \"header\": \"Hero\",\n \"type\": \"text\",\n \"sticky\": \"start\"\n },\n {\n \"field\": \"papel\",\n \"header\": \"Role\",\n \"type\": \"badge\"\n },\n {\n \"field\": \"resultado\",\n \"header\": \"Outcome\",\n \"type\": \"badge\"\n }\n ]\n }\n },\n \"outputs\": {\n \"rowClick\": \"emit\",\n \"toolbarAction\": \"emit\"\n }\n }\n }\n ],\n \"composition\": {\n \"version\": \"1.0.0\",\n \"links\": [\n {\n \"id\": \"surfaces:mission-rowClick->state:selection.missionId\",\n \"intent\": \"state-write\",\n \"from\": {\n \"kind\": \"component-port\",\n \"ref\": {\n \"widget\": \"missionSurface\",\n \"port\": \"rowClick\",\n \"direction\": \"output\",\n \"componentType\": \"praxis-table\"\n }\n },\n \"to\": {\n \"kind\": \"state\",\n \"ref\": {\n \"path\": \"selection.missionId\",\n \"layer\": \"values\",\n \"writable\": true\n }\n },\n \"transform\": {\n \"version\": \"2.0\",\n \"phase\": \"link-propagation\",\n \"mode\": \"single-value\",\n \"sourceBindings\": [\n {\n \"source\": \"event\"\n }\n ],\n \"steps\": [\n {\n \"id\": \"surfaces:pick-mission-id\",\n \"kind\": \"pick-path\",\n \"phase\": \"link-propagation\",\n \"input\": {\n \"source\": \"event\"\n },\n \"config\": {\n \"path\": \"payload.row.id\"\n }\n }\n ]\n }\n },\n {\n \"id\": \"surfaces:state:selection.missionId->team.queryContext\",\n \"intent\": \"state-read\",\n \"from\": {\n \"kind\": \"state\",\n \"ref\": {\n \"path\": \"selection.missionId\",\n \"layer\": \"values\"\n }\n },\n \"to\": {\n \"kind\": \"component-port\",\n \"ref\": {\n \"widget\": \"missionTeamSurface\",\n \"port\": \"queryContext\",\n \"direction\": \"input\",\n \"componentType\": \"praxis-table\"\n }\n },\n \"transform\": {\n \"version\": \"2.0\",\n \"phase\": \"link-propagation\",\n \"mode\": \"single-value\",\n \"sourceBindings\": [\n {\n \"source\": \"state\",\n \"path\": \"selection.missionId\"\n }\n ],\n \"steps\": [\n {\n \"id\": \"surfaces:team-query-context\",\n \"kind\": \"object-template\",\n \"phase\": \"link-propagation\",\n \"config\": {\n \"template\": {\n \"filters\": {\n \"missaoId\": \"${source}\"\n }\n }\n }\n }\n ]\n },\n \"policy\": {\n \"missingValuePolicy\": \"skip\",\n \"distinct\": true\n }\n }\n ]\n }\n }\n}\n",
3343
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.surfaces-actions-showcase.json",
3356
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.surfaces-actions-showcase.json",
3344
3357
  "contentHash": "c88e52753185f42bb432992398ea03e417464a7186e31b4ce45a1af377a827f0",
3345
3358
  "sourceKind": "component_definition",
3346
3359
  "sourceId": "praxis-dynamic-page",
@@ -3350,7 +3363,7 @@
3350
3363
  "chunkIndex": 46,
3351
3364
  "chunkKind": "recipe",
3352
3365
  "content": "{\n \"_comment\": \"Template de pagina com tabela unica (Praxis Dynamic Page).\",\n \"_comment2\": \"resourcePath deve ser o path base do recurso (sem /filter).\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"table\",\n \"useWhen\": \"Create a dynamic page with a single table widget.\",\n \"examplePrompts\": [\n \"pagina com tabela\",\n \"crie uma pagina com tabela de funcionarios\",\n \"tabela simples\"\n ]\n },\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 2,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"mainTable\",\n \"definition\": {\n \"id\": \"praxis-table\",\n \"bindingOrder\": [\"config\", \"resourcePath\"],\n \"inputs\": {\n \"resourcePath\": \"{{resourcePath}}\",\n \"tableId\": \"{{resourceKey}}-table\",\n \"config\": {\n \"toolbar\": { \"visible\": true, \"title\": \"{{resourceLabel}}\" }\n }\n },\n \"outputs\": { \"rowClick\": \"emit\" }\n }\n }\n ]\n }\n}\n",
3353
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.table.json",
3366
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.table.json",
3354
3367
  "contentHash": "26aef1c8df2cd50ac084b09a7d567ba174634ce71a85c91d9e67871056be4ba2",
3355
3368
  "sourceKind": "component_definition",
3356
3369
  "sourceId": "praxis-dynamic-page",
@@ -3360,7 +3373,7 @@
3360
3373
  "chunkIndex": 47,
3361
3374
  "chunkKind": "recipe",
3362
3375
  "content": "{\n \"_comment\": \"Recipe for agents to create a Praxis Dynamic Page with Praxis Tabs in nav mode.\",\n \"_comment2\": \"Use this when the host shell needs navigation semantics but each link still renders metadata-driven widgets.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"tabs-nav-routing-workspace\",\n \"status\": \"public-example\",\n \"useWhen\": \"Create a dynamic page where Praxis Tabs nav.links switch between nested runtime widgets.\",\n \"examplePrompts\": [\n \"create a navigation tabs workspace with nested widgets\",\n \"show praxis-tabs nav mode inside praxis-dynamic-page\",\n \"generate a tabs nav example with list and rich content widgets\"\n ]\n },\n \"platformValue\": {\n \"canonicalRuntime\": \"@praxisui/tabs owns nav.links and selectedIndexChange; nested widget wiring uses composition.links with component-port + nestedPath.\",\n \"angularRuntime\": \"@praxisui/core resolves nested widgets through the same DynamicWidgetLoader used by top-level page widgets.\",\n \"publicExamples\": \"praxis-ui-landing-page exposes the envelope, live preview and inspector JSON.\",\n \"agentCorpus\": \"This recipe gives agents a copyable nav-mode contract without inventing unsupported route fields.\"\n },\n \"authoringGuidance\": [\n \"Use config.nav.links for nav mode; do not add route fields unless the host explicitly maps them.\",\n \"Put per-link content in widgets or content arrays.\",\n \"Use selectedIndexChange for shell coordination.\",\n \"Use composition.links with component-port + nestedPath when nested widgets need to bubble actions or selections back to the page.\",\n \"Keep tabsId stable so preferences and host diagnostics can identify the instance.\"\n ],\n \"teaches\": [\n \"tabs.nav-mode\",\n \"tabs.nested-widgets\",\n \"tabs.nested-component-ports\",\n \"page.composition-links\",\n \"list.selection-actions\",\n \"rich-content.knowledge-surface\"\n ],\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 1,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"tabsNavRoutingWorkspace\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"alt_route\",\n \"title\": \"Tabs nav workspace\",\n \"subtitle\": \"Navigation links with nested runtime widgets\"\n },\n \"definition\": {\n \"id\": \"praxis-tabs\",\n \"bindingOrder\": [\"tabsId\", \"config\"],\n \"inputs\": {\n \"tabsId\": \"tabs-nav-routing-workspace\",\n \"componentInstanceId\": \"dynamic-page-showcase\",\n \"config\": {\n \"appearance\": {\n \"density\": \"comfortable\",\n \"tokens\": {\n \"active-indicator-color\": \"#0f766e\",\n \"active-label-text-color\": \"#0f172a\",\n \"inactive-label-text-color\": \"#475569\"\n }\n },\n \"behavior\": {\n \"lazyLoad\": true,\n \"closeable\": false,\n \"reorderable\": false\n },\n \"accessibility\": {\n \"ariaLabel\": \"Navigation workspace tabs\",\n \"reduceMotion\": true\n },\n \"nav\": {\n \"selectedIndex\": 0,\n \"fitInkBarToContent\": true,\n \"stretchTabs\": false,\n \"ariaLabel\": \"Operations navigation\",\n \"links\": [\n {\n \"id\": \"briefing\",\n \"label\": \"Briefing\",\n \"widgets\": [\n {\n \"id\": \"widget:rich-text-block\",\n \"inputs\": {\n \"title\": \"Mission operations briefing\",\n \"content\": \"Use nav mode when the host shell needs stable navigation semantics while each link remains metadata-driven content. The runtime changes the active link and renders only the selected link widgets.\",\n \"variant\": \"emphasis\"\n }\n }\n ]\n },\n {\n \"id\": \"queue\",\n \"label\": \"Queue\",\n \"widgets\": [\n {\n \"id\": \"praxis-list\",\n \"bindingOrder\": [\"listId\", \"config\"],\n \"inputs\": {\n \"listId\": \"tabs-nav-routing-queue-list\",\n \"config\": {\n \"id\": \"tabs-nav-routing-queue-list-config\",\n \"dataSource\": {\n \"data\": [\n {\n \"id\": 1,\n \"title\": \"Review mission readiness\",\n \"owner\": \"Sol Drax\",\n \"status\": \"Ready\",\n \"priority\": \"P1\"\n },\n {\n \"id\": 2,\n \"title\": \"Confirm payroll exceptions\",\n \"owner\": \"Mira Drax\",\n \"status\": \"At risk\",\n \"priority\": \"P0\"\n },\n {\n \"id\": 3,\n \"title\": \"Publish capability notes\",\n \"owner\": \"Ravi Almeida\",\n \"status\": \"Blocked\",\n \"priority\": \"P1\"\n }\n ]\n },\n \"layout\": {\n \"variant\": \"list\",\n \"density\": \"compact\",\n \"lines\": 2,\n \"dividers\": \"between\",\n \"pageSize\": 5\n },\n \"selection\": {\n \"mode\": \"single\",\n \"compareBy\": \"id\",\n \"return\": \"id\"\n },\n \"templating\": {\n \"leading\": { \"type\": \"icon\", \"expr\": \"route\" },\n \"primary\": { \"type\": \"text\", \"expr\": \"${item.title}\" },\n \"secondary\": { \"type\": \"text\", \"expr\": \"${item.owner}\" },\n \"meta\": { \"type\": \"chip\", \"expr\": \"${item.priority}\", \"variant\": \"filled\" },\n \"trailing\": { \"type\": \"chip\", \"expr\": \"${item.status}\", \"variant\": \"outlined\" }\n },\n \"ui\": {\n \"showSearch\": false,\n \"showSort\": false,\n \"showRange\": false\n }\n }\n },\n \"outputs\": {\n \"itemClick\": \"emit\",\n \"selectionChange\": \"emit\"\n }\n }\n ]\n },\n {\n \"id\": \"decisions\",\n \"label\": \"Decisions\",\n \"widgets\": [\n {\n \"id\": \"widget:rich-text-block\",\n \"inputs\": {\n \"title\": \"Host-owned routing intent\",\n \"content\": \"Praxis Tabs nav mode owns the selected link. The application shell can map selectedIndexChange to route state, breadcrumbs or inspector context, while nested widget events should be wired through composition.links with component-port + nestedPath.\",\n \"variant\": \"default\"\n }\n }\n ]\n }\n ]\n }\n }\n },\n \"outputs\": {\n \"selectedIndexChange\": \"emit\",\n \"indexFocused\": \"emit\",\n \"selectFocusedIndex\": \"emit\"\n }\n }\n }\n ]\n }\n}\n",
3363
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.tabs-nav-routing-workspace.json",
3376
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.tabs-nav-routing-workspace.json",
3364
3377
  "contentHash": "60ab36eaed9d40ff5d9fbb728c4a394b39cd6538ed6a9e26872f6617c81e5fa5",
3365
3378
  "sourceKind": "component_definition",
3366
3379
  "sourceId": "praxis-dynamic-page",
@@ -3370,7 +3383,7 @@
3370
3383
  "chunkIndex": 48,
3371
3384
  "chunkKind": "recipe",
3372
3385
  "content": "{\n \"_comment\": \"Template de pagina com abas (Praxis Dynamic Page).\",\n \"_comment2\": \"resourcePath deve ser o path base do recurso (sem /filter).\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"tabs\",\n \"useWhen\": \"Create a dynamic page with tabs.\",\n \"examplePrompts\": [\n \"pagina com abas\",\n \"crie tabs com tabela e formulario\",\n \"tela em abas\"\n ]\n },\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 2,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"mainTabs\",\n \"definition\": {\n \"id\": \"praxis-tabs\",\n \"inputs\": {\n \"tabsId\": \"{{resourceKey}}-tabs\",\n \"config\": {\n \"behavior\": { \"lazyLoad\": true, \"reorderable\": false, \"closeable\": false },\n \"tabs\": [\n {\n \"id\": \"tab-list\",\n \"textLabel\": \"Lista\",\n \"widgets\": [\n {\n \"id\": \"praxis-table\",\n \"bindingOrder\": [\"config\", \"resourcePath\"],\n \"inputs\": {\n \"resourcePath\": \"{{resourcePath}}\",\n \"tableId\": \"{{resourceKey}}-tabs-table\",\n \"config\": { \"toolbar\": { \"visible\": true } }\n },\n \"outputs\": { \"rowClick\": \"emit\" }\n }\n ]\n },\n {\n \"id\": \"tab-detail\",\n \"textLabel\": \"Detalhes\",\n \"widgets\": [\n {\n \"id\": \"praxis-dynamic-form\",\n \"bindingOrder\": [\"resourcePath\", \"formId\", \"resourceId\"],\n \"inputs\": {\n \"formId\": \"{{resourceKey}}-tabs-form\",\n \"resourcePath\": \"{{resourcePath}}\",\n \"mode\": \"view\"\n }\n }\n ]\n }\n ]\n }\n }\n }\n }\n ]\n }\n}\n",
3373
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.tabs.json",
3386
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.tabs.json",
3374
3387
  "contentHash": "ddf99001017396d3a392ea76c467db13549fc1080eb26653f7c0d9f28a3df02e",
3375
3388
  "sourceKind": "component_definition",
3376
3389
  "sourceId": "praxis-dynamic-page",
@@ -3380,7 +3393,7 @@
3380
3393
  "chunkIndex": 49,
3381
3394
  "chunkKind": "recipe",
3382
3395
  "content": "{\n \"_comment\": \"Praxis Dynamic Page recipe that demonstrates visual block presets persisted as richContent layout items inside praxis-dynamic-form columns.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-dynamic-page\",\n \"variantId\": \"visual-block-presets-form\",\n \"status\": \"public-example\",\n \"useWhen\": \"Create a Dynamic Page form that keeps API fields aligned while larger visual blocks live on dedicated rows authored from visual block presets.\",\n \"examplePrompts\": [\n \"create a dynamic page form with visual block presets\",\n \"show FormColumn.items with fields and static rich content blocks\",\n \"demonstrate dynamic form layout items using text notice divider info card and timeline\",\n \"show dedicated rows for large guidance cards in a dynamic form layout\"\n ]\n },\n \"platformValue\": {\n \"canonicalContract\": \"@praxisui/dynamic-form owns FormColumn.items and renders field plus richContent layout items in order.\",\n \"visualBlockRuntime\": \"@praxisui/rich-content owns the RichContentDocument rendered by each static visual block.\",\n \"authoringContract\": \"Preset ids are authoring shortcuts only; the persisted config stores kind richContent with a RichContentDocument.\",\n \"publicExamples\": \"praxis-ui-landing-page exposes the live preview and inspector JSON for the complete Dynamic Page envelope.\",\n \"agentCorpus\": \"This recipe gives agents a copyable canonical layout-item example instead of teaching legacy fields-only columns.\"\n },\n \"operationalEvidence\": {\n \"baseUrl\": \"https://praxis-api-quickstart.onrender.com\",\n \"safeFirstIds\": [\n \"filtered-schema-response-funcionarios\",\n \"funcionarios-get-by-id\",\n \"cargos-options-filter\",\n \"departamentos-options-filter\"\n ],\n \"pendingHttpIds\": [],\n \"httpExamples\": [\n \"praxisui-http-examples/http/metadata/filtered_schema_response_funcionarios.http\",\n \"praxisui-http-examples/http/resources/funcionarios_get_by_id.http\",\n \"praxisui-http-examples/http/resources/cargos_options_filter.http\",\n \"praxisui-http-examples/http/resources/departamentos_options_filter.http\"\n ]\n },\n \"authoringGuidance\": [\n \"Use sections[].rows[].columns[].items[] as the canonical ordered column contract.\",\n \"Use kind field items for fields already present in fieldMetadata.\",\n \"Use kind richContent items for static visual blocks and pass a canonical RichContentDocument in document.\",\n \"Keep fields[] synchronized as a projection of the field items only.\",\n \"Do not store visual blocks in fieldMetadata.\",\n \"Do not persist preset ids; presets only create the initial RichContentDocument in the layout editor.\",\n \"Use text, notice, divider, info card and timeline examples as starting documents that can be edited by the Rich Content editor.\",\n \"Place dividers and larger guidance cards on dedicated full-width rows when they separate semantic groups or would otherwise break the field grid rhythm.\",\n \"Use visualBlock formRules for governed text/style changes, and prefer textNodeId/titleNodeId/messageNodeId when the document has more than one textual node.\"\n ],\n \"teaches\": [\n \"dynamic-form.layout-items\",\n \"FormColumn.items\",\n \"FormLayoutItem.kind.field\",\n \"FormLayoutItem.kind.richContent\",\n \"visual-block-presets.text\",\n \"visual-block-presets.notice\",\n \"visual-block-presets.divider\",\n \"visual-block-presets.infoCard\",\n \"visual-block-presets.contractProof\",\n \"rich-content.timeline\",\n \"rich-content.document\",\n \"visualBlock.formRules\",\n \"visualBlock.textNodeId\",\n \"visualBlock.titleNodeId\",\n \"visualBlock.messageNodeId\",\n \"fields-projection\"\n ],\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 1,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"visualBlockPresetBriefing\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"article\",\n \"title\": \"Visual block presets\",\n \"subtitle\": \"Authoring shortcuts that persist as RichContentDocument layout items\"\n },\n \"definition\": {\n \"id\": \"praxis-rich-content\",\n \"bindingOrder\": [\n \"document\",\n \"layout\",\n \"rootClassName\"\n ],\n \"inputs\": {\n \"layout\": \"block\",\n \"rootClassName\": \"dynamic-page-visual-block-presets-briefing\",\n \"document\": {\n \"kind\": \"praxis.rich-content\",\n \"version\": \"1.0.0\",\n \"nodes\": [\n {\n \"type\": \"card\",\n \"title\": \"Static guidance belongs in layout items\",\n \"subtitle\": \"The form stays metadata-driven while explanation, warnings and separators remain governed content.\",\n \"content\": [\n {\n \"type\": \"compose\",\n \"wrap\": true,\n \"gap\": \"sm\",\n \"items\": [\n {\n \"type\": \"badge\",\n \"label\": \"FormColumn.items\"\n },\n {\n \"type\": \"badge\",\n \"label\": \"richContent\"\n },\n {\n \"type\": \"badge\",\n \"label\": \"fields[] projection\"\n }\n ]\n },\n {\n \"type\": \"text\",\n \"text\": \"The examples below show the persisted shape produced by visual block presets: text, notice, divider, info card and contract proof. The preset id is not part of the saved contract.\"\n }\n ]\n }\n ]\n }\n }\n }\n },\n {\n \"key\": \"funcionarioVisualBlocksForm\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"view_agenda\",\n \"title\": \"Funcionario review form\",\n \"subtitle\": \"API fields stay aligned while guidance cards move to dedicated rows\"\n },\n \"definition\": {\n \"id\": \"praxis-dynamic-form\",\n \"bindingOrder\": [\n \"config\",\n \"resourcePath\",\n \"formId\",\n \"resourceId\"\n ],\n \"inputs\": {\n \"formId\": \"human-resources-funcionarios-visual-block-presets\",\n \"resourcePath\": \"human-resources/funcionarios\",\n \"resourceId\": 1,\n \"mode\": \"view\",\n \"config\": {\n \"metadata\": {\n \"name\": \"Funcionario visual block review\",\n \"version\": \"1.0.0\"\n },\n \"editorialContext\": {\n \"review\": {\n \"scope\": 4,\n \"scopeCaption\": \"identity fields\",\n \"readiness\": 80\n }\n },\n \"sections\": [\n {\n \"id\": \"identity-and-context\",\n \"title\": \"Identity and context\",\n \"description\": \"A fields-plus-content layout that keeps larger guidance cards on dedicated rows so the field grid stays aligned.\",\n \"appearance\": \"outlined\",\n \"rows\": [\n {\n \"id\": \"identity-row-main\",\n \"columns\": [\n {\n \"id\": \"identity-main\",\n \"span\": {\n \"md\": 7,\n \"lg\": 7\n },\n \"items\": [\n {\n \"kind\": \"richContent\",\n \"id\": \"identity-introduction-block\",\n \"layout\": \"block\",\n \"rootClassName\": \"visual-block-text\",\n \"document\": {\n \"kind\": \"praxis.rich-content\",\n \"version\": \"1.0.0\",\n \"nodes\": [\n {\n \"type\": \"text\",\n \"text\": \"Review the employee identity before checking assignment and payroll data. This block represents a RichContentDocument created from the Text preset.\"\n }\n ]\n }\n },\n {\n \"kind\": \"field\",\n \"id\": \"field-nomeCompleto\",\n \"fieldName\": \"nomeCompleto\"\n },\n {\n \"kind\": \"field\",\n \"id\": \"field-email\",\n \"fieldName\": \"email\"\n },\n {\n \"kind\": \"richContent\",\n \"id\": \"contact-guidance-notice\",\n \"layout\": \"block\",\n \"rootClassName\": \"visual-block-notice\",\n \"document\": {\n \"kind\": \"praxis.rich-content\",\n \"version\": \"1.0.0\",\n \"nodes\": [\n {\n \"type\": \"compose\",\n \"direction\": \"row\",\n \"gap\": \"sm\",\n \"wrap\": true,\n \"className\": \"praxis-rich-content-notice\",\n \"items\": [\n {\n \"type\": \"icon\",\n \"icon\": \"error_outline\",\n \"ariaLabel\": \"Notice\"\n },\n {\n \"type\": \"text\",\n \"text\": \"Email and phone are operational contact fields. Keep changes aligned with the backend employee record instead of treating this guidance as field metadata.\"\n }\n ]\n }\n ]\n }\n },\n {\n \"kind\": \"field\",\n \"id\": \"field-telefone\",\n \"fieldName\": \"telefone\"\n }\n ],\n \"fields\": [\n \"nomeCompleto\",\n \"email\",\n \"telefone\"\n ]\n },\n {\n \"id\": \"identity-side\",\n \"span\": {\n \"md\": 5,\n \"lg\": 5\n },\n \"items\": [\n {\n \"kind\": \"field\",\n \"id\": \"field-fotoPerfilUrl\",\n \"fieldName\": \"fotoPerfilUrl\"\n },\n {\n \"kind\": \"field\",\n \"id\": \"field-ativo\",\n \"fieldName\": \"ativo\"\n },\n {\n \"kind\": \"field\",\n \"id\": \"field-estadoCivil\",\n \"fieldName\": \"estadoCivil\"\n }\n ],\n \"fields\": [\n \"fotoPerfilUrl\",\n \"ativo\",\n \"estadoCivil\"\n ]\n }\n ]\n },\n {\n \"id\": \"identity-status-row\",\n \"columns\": [\n {\n \"id\": \"identity-status\",\n \"span\": {\n \"md\": 12,\n \"lg\": 12\n },\n \"items\": [\n {\n \"kind\": \"richContent\",\n \"id\": \"profile-status-card\",\n \"layout\": \"block\",\n \"rootClassName\": \"visual-block-info-card\",\n \"document\": {\n \"kind\": \"praxis.rich-content\",\n \"version\": \"1.0.0\",\n \"nodes\": [\n {\n \"type\": \"card\",\n \"id\": \"profile-status-title\",\n \"title\": \"Profile status\",\n \"subtitle\": \"Info card preset placed on a dedicated row to preserve the field rhythm.\",\n \"content\": [\n {\n \"type\": \"compose\",\n \"wrap\": true,\n \"gap\": \"sm\",\n \"items\": [\n {\n \"type\": \"badge\",\n \"label\": \"API field\"\n },\n {\n \"type\": \"badge\",\n \"label\": \"visual guidance\"\n }\n ]\n },\n {\n \"id\": \"profile-status-message\",\n \"type\": \"text\",\n \"text\": \"Keep assignment, department and contact details current.\"\n },\n {\n \"type\": \"metric\",\n \"label\": \"Review scope\",\n \"valueExpr\": \"${review.scope}\",\n \"captionExpr\": \"${review.scopeCaption}\"\n },\n {\n \"type\": \"progress\",\n \"label\": \"Readiness\",\n \"valueExpr\": \"${review.readiness}\",\n \"max\": 100,\n \"showPercent\": true\n }\n ]\n }\n ]\n }\n }\n ]\n }\n ]\n }\n ]\n },\n {\n \"id\": \"assignment-review\",\n \"title\": \"Assignment review\",\n \"description\": \"Divider and card blocks separate assignment data from compensation context while the guidance card stays on its own row.\",\n \"appearance\": \"outlined\",\n \"rows\": [\n {\n \"id\": \"assignment-role-row\",\n \"columns\": [\n {\n \"id\": \"assignment-role\",\n \"span\": {\n \"md\": 6,\n \"lg\": 6\n },\n \"items\": [\n {\n \"kind\": \"field\",\n \"id\": \"field-cargoId\",\n \"fieldName\": \"cargoId\"\n }\n ],\n \"fields\": [\n \"cargoId\"\n ]\n },\n {\n \"id\": \"assignment-department\",\n \"span\": {\n \"md\": 6,\n \"lg\": 6\n },\n \"items\": [\n {\n \"kind\": \"field\",\n \"id\": \"field-departamentoId\",\n \"fieldName\": \"departamentoId\"\n }\n ],\n \"fields\": [\n \"departamentoId\"\n ]\n }\n ]\n },\n {\n \"id\": \"assignment-policy-row\",\n \"columns\": [\n {\n \"id\": \"assignment-policy\",\n \"span\": {\n \"md\": 12,\n \"lg\": 12\n },\n \"items\": [\n {\n \"kind\": \"richContent\",\n \"id\": \"assignment-policy-divider\",\n \"layout\": \"block\",\n \"rootClassName\": \"visual-block-divider\",\n \"document\": {\n \"kind\": \"praxis.rich-content\",\n \"version\": \"1.0.0\",\n \"nodes\": [\n {\n \"type\": \"text\",\n \"id\": \"assignment-policy-divider-text\",\n \"text\": \"Assignment policy checkpoint\",\n \"className\": \"praxis-rich-content-divider\"\n }\n ]\n }\n }\n ]\n }\n ]\n },\n {\n \"id\": \"assignment-compensation-row\",\n \"columns\": [\n {\n \"id\": \"assignment-admission\",\n \"span\": {\n \"md\": 6,\n \"lg\": 6\n },\n \"items\": [\n {\n \"kind\": \"field\",\n \"id\": \"field-dataAdmissao\",\n \"fieldName\": \"dataAdmissao\"\n }\n ],\n \"fields\": [\n \"dataAdmissao\"\n ]\n },\n {\n \"id\": \"assignment-payroll\",\n \"span\": {\n \"md\": 6,\n \"lg\": 6\n },\n \"items\": [\n {\n \"kind\": \"field\",\n \"id\": \"field-salario\",\n \"fieldName\": \"salario\"\n }\n ],\n \"fields\": [\n \"salario\"\n ]\n }\n ]\n },\n {\n \"id\": \"assignment-guidance-row\",\n \"columns\": [\n {\n \"id\": \"assignment-guidance\",\n \"span\": {\n \"md\": 12,\n \"lg\": 12\n },\n \"items\": [\n {\n \"kind\": \"richContent\",\n \"id\": \"assignment-guidance-card\",\n \"layout\": \"block\",\n \"rootClassName\": \"visual-block-guidance-card\",\n \"document\": {\n \"kind\": \"praxis.rich-content\",\n \"version\": \"1.0.0\",\n \"nodes\": [\n {\n \"type\": \"card\",\n \"id\": \"assignment-guidance-title\",\n \"title\": \"Operational assignment\",\n \"subtitle\": \"Confirm role, department and start date before closing the review.\",\n \"content\": [\n {\n \"type\": \"text\",\n \"id\": \"assignment-guidance-message\",\n \"text\": \"This row keeps guidance outside the submit payload while preserving the field rhythm.\"\n }\n ]\n },\n {\n \"type\": \"keyValueList\",\n \"id\": \"assignment-contract-proof\",\n \"title\": \"Contract proof\",\n \"layout\": \"stacked\",\n \"items\": [\n {\n \"label\": \"items[]\",\n \"value\": \"Owns the mixed order of fields and visual blocks.\",\n \"icon\": \"view_week\",\n \"badge\": \"canonical\"\n },\n {\n \"label\": \"fields[]\",\n \"value\": \"Keeps only API field names as a derived projection.\",\n \"icon\": \"schema\",\n \"badge\": \"field projection\"\n }\n ]\n }\n ]\n }\n }\n ]\n }\n ]\n },\n {\n \"id\": \"assignment-timeline-row\",\n \"columns\": [\n {\n \"id\": \"assignment-timeline\",\n \"span\": {\n \"md\": 12,\n \"lg\": 12\n },\n \"items\": [\n {\n \"kind\": \"richContent\",\n \"id\": \"assignment-review-timeline\",\n \"layout\": \"block\",\n \"rootClassName\": \"visual-block-timeline\",\n \"document\": {\n \"kind\": \"praxis.rich-content\",\n \"version\": \"1.0.0\",\n \"nodes\": [\n {\n \"type\": \"timeline\",\n \"id\": \"assignment-review-timeline-node\",\n \"title\": \"Assignment review timeline\",\n \"orientation\": \"horizontal\",\n \"order\": \"normal\",\n \"position\": \"alternate\",\n \"connectorVariant\": \"none\",\n \"connectorColor\": \"neutral\",\n \"markerVariant\": \"number\",\n \"markerColor\": \"primary\",\n \"markerStyle\": \"filled\",\n \"emphasis\": \"hero\",\n \"density\": \"comfortable\",\n \"textAppearance\": \"prominent\",\n \"items\": [\n {\n \"id\": \"identity-check\",\n \"title\": \"Validate identity\",\n \"subtitle\": \"Confirm name, contact data and active status before reviewing assignment.\",\n \"opposite\": \"1. Intake\",\n \"badge\": \"Form data\",\n \"markerColor\": \"success\",\n \"markerStyle\": \"outlined\",\n \"connectorColor\": \"success\",\n \"connectorVariant\": \"solid\"\n },\n {\n \"id\": \"assignment-check\",\n \"title\": \"Review assignment\",\n \"subtitle\": \"Cargo and department stay as API fields; this timeline remains presentation metadata.\",\n \"opposite\": \"2. Assignment\",\n \"badge\": \"Rich content\",\n \"markerColor\": \"warning\",\n \"connectorColor\": \"warning\",\n \"connectorVariant\": \"dashed\"\n },\n {\n \"id\": \"payroll-check\",\n \"title\": \"Confirm payroll readiness\",\n \"subtitle\": \"Salary and admission date remain outside the visual block payload.\",\n \"opposite\": \"3. Payroll\",\n \"badge\": \"No submit payload\",\n \"markerColor\": \"info\",\n \"markerStyle\": \"outlined\",\n \"connectorVariant\": \"none\"\n }\n ]\n }\n ]\n }\n }\n ],\n \"fields\": []\n }\n ]\n }\n ]\n }\n ],\n \"fieldMetadata\": [\n {\n \"name\": \"fotoPerfilUrl\",\n \"label\": \"Avatar\",\n \"controlType\": \"avatar\",\n \"imageField\": \"fotoPerfilUrl\",\n \"readonly\": true\n },\n {\n \"name\": \"nomeCompleto\",\n \"label\": \"Nome Completo\",\n \"controlType\": \"input\",\n \"validators\": {\n \"required\": true,\n \"maxLength\": 160\n },\n \"readonly\": true\n },\n {\n \"name\": \"email\",\n \"label\": \"Email\",\n \"controlType\": \"email\",\n \"validators\": {\n \"email\": true\n },\n \"readonly\": true\n },\n {\n \"name\": \"telefone\",\n \"label\": \"Telefone\",\n \"controlType\": \"phone\",\n \"maskType\": \"phone\",\n \"readonly\": true\n },\n {\n \"name\": \"ativo\",\n \"label\": \"Ativo\",\n \"controlType\": \"toggle\",\n \"readonly\": true\n },\n {\n \"name\": \"cargoId\",\n \"label\": \"Cargo\",\n \"controlType\": \"asyncSelect\",\n \"endpoint\": \"/api/human-resources/cargos/options/filter\",\n \"displayField\": \"label\",\n \"valueField\": \"id\",\n \"readonly\": true\n },\n {\n \"name\": \"departamentoId\",\n \"label\": \"Departamento\",\n \"controlType\": \"asyncSelect\",\n \"endpoint\": \"/api/human-resources/departamentos/options/filter\",\n \"displayField\": \"label\",\n \"valueField\": \"id\",\n \"readonly\": true\n },\n {\n \"name\": \"dataAdmissao\",\n \"label\": \"Data de Admissão\",\n \"controlType\": \"date\",\n \"readonly\": true\n },\n {\n \"name\": \"salario\",\n \"label\": \"Salário\",\n \"controlType\": \"currency\",\n \"currencyCode\": \"BRL\",\n \"locale\": \"pt-BR\",\n \"readonly\": true\n },\n {\n \"name\": \"estadoCivil\",\n \"label\": \"Estado Civil\",\n \"controlType\": \"select\",\n \"options\": [\n {\n \"label\": \"Solteiro\",\n \"value\": \"SOLTEIRO\"\n },\n {\n \"label\": \"Casado\",\n \"value\": \"CASADO\"\n },\n {\n \"label\": \"Divorciado\",\n \"value\": \"DIVORCIADO\"\n },\n {\n \"label\": \"Viúvo\",\n \"value\": \"VIUVO\"\n }\n ],\n \"readonly\": true\n }\n ],\n \"actions\": {\n \"submit\": {\n \"id\": \"submit-visual-block-review\",\n \"label\": \"Submit review\",\n \"visible\": false,\n \"type\": \"submit\"\n },\n \"reset\": {\n \"id\": \"reset-visual-block-review\",\n \"label\": \"Reset\",\n \"visible\": false,\n \"type\": \"reset\"\n },\n \"cancel\": {\n \"id\": \"close-visual-block-review\",\n \"label\": \"Close\",\n \"visible\": false,\n \"type\": \"button\"\n },\n \"position\": \"right\",\n \"placement\": \"afterSections\",\n \"spacing\": \"compact\"\n },\n \"formRules\": [\n {\n \"id\": \"employee-inactive-visual-guidance\",\n \"name\": \"Employee inactive visual guidance\",\n \"targetType\": \"visualBlock\",\n \"targets\": [\n \"profile-status-card\"\n ],\n \"effect\": {\n \"condition\": {\n \"===\": [\n {\n \"var\": \"ativo\"\n },\n false\n ]\n },\n \"properties\": {\n \"title\": \"Employee inactive\",\n \"titleNodeId\": \"profile-status-title\",\n \"message\": \"Review offboarding, access revocation and justification before saving.\",\n \"messageNodeId\": \"profile-status-message\",\n \"className\": \"employee-status-card employee-status-card--warning\"\n },\n \"propertiesWhenFalse\": {\n \"title\": \"Employee active\",\n \"titleNodeId\": \"profile-status-title\",\n \"message\": \"Keep assignment, department and contact details current.\",\n \"messageNodeId\": \"profile-status-message\",\n \"className\": \"employee-status-card employee-status-card--ok\"\n }\n }\n },\n {\n \"id\": \"assignment-guidance-by-role\",\n \"name\": \"Assignment guidance by role\",\n \"targetType\": \"visualBlock\",\n \"targets\": [\n \"assignment-guidance-card\"\n ],\n \"effect\": {\n \"condition\": {\n \"===\": [\n {\n \"var\": \"cargoId\"\n },\n \"gestor\"\n ]\n },\n \"properties\": {\n \"title\": \"Managerial assignment\",\n \"titleNodeId\": \"assignment-guidance-title\",\n \"message\": \"Confirm approval scope, reporting line and department ownership.\",\n \"messageNodeId\": \"assignment-guidance-message\",\n \"rootClassName\": \"visual-block-guidance-card visual-block-guidance-card--manager\"\n },\n \"propertiesWhenFalse\": {\n \"title\": \"Operational assignment\",\n \"titleNodeId\": \"assignment-guidance-title\",\n \"message\": \"This row keeps guidance outside the submit payload while preserving the field rhythm.\",\n \"messageNodeId\": \"assignment-guidance-message\",\n \"rootClassName\": \"visual-block-guidance-card\"\n }\n }\n }\n ]\n }\n }\n }\n }\n ]\n }\n}\n",
3383
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-dynamic-page.visual-block-presets-form.json",
3396
+ "sourcePointer": "examples/ai-recipes/praxis-dynamic-page.visual-block-presets-form.json",
3384
3397
  "contentHash": "aa70f6a9f3c0f81981491462ad3f27dc758049764f3db82b8402cb2cd18276a8",
3385
3398
  "sourceKind": "component_definition",
3386
3399
  "sourceId": "praxis-dynamic-page",
@@ -3395,104 +3408,140 @@
3395
3408
  {
3396
3409
  "name": "surfaceId",
3397
3410
  "type": "string | null",
3398
- "required": false
3411
+ "required": false,
3412
+ "description": "Identidade declarativa da surface quando o outlet deve descobri-la no catálogo do recurso."
3399
3413
  },
3400
3414
  {
3401
3415
  "name": "surfaceCatalog",
3402
3416
  "type": "ResourceSurfaceCatalogResponse | null",
3403
- "required": false
3417
+ "required": false,
3418
+ "description": "Catálogo de surfaces já carregado pelo host; evita nova consulta quando disponível."
3404
3419
  },
3405
3420
  {
3406
3421
  "name": "discoverySource",
3407
3422
  "type": "ResourceLinkSource | null",
3408
- "required": false
3423
+ "required": false,
3424
+ "description": "Resposta HATEOAS ou mapa de links usado para seguir rel surfaces quando surface não foi fornecida."
3409
3425
  },
3410
3426
  {
3411
3427
  "name": "parentLinks",
3412
3428
  "type": "RestApiLinks | RestApiResponse<unknown> | null",
3413
- "required": false
3429
+ "required": false,
3430
+ "description": "Atalho para links do registro pai; tem o mesmo papel de discoverySource para rel surfaces."
3414
3431
  },
3415
3432
  {
3416
3433
  "name": "apiEndpointKey",
3417
3434
  "type": "ApiEndpoint | null",
3418
- "required": false
3435
+ "required": false,
3436
+ "description": "Endpoint Praxis usado pelo ResourceDiscoveryService ao resolver links ou fallback do catálogo."
3419
3437
  },
3420
3438
  {
3421
3439
  "name": "apiUrlEntry",
3422
3440
  "type": "ApiUrlEntry | null",
3423
- "required": false
3441
+ "required": false,
3442
+ "description": "Entrada de API já resolvida para hosts destacados ou integrações remotas."
3424
3443
  },
3425
3444
  {
3426
3445
  "name": "surface",
3427
3446
  "type": "ResourceSurfaceCatalogItem | null",
3428
- "required": false
3447
+ "required": false,
3448
+ "description": "Surface de catálogo que pode publicar relatedResource."
3429
3449
  },
3430
3450
  {
3431
3451
  "name": "parentRecord",
3432
3452
  "type": "Record<string, unknown> | null",
3433
- "required": false
3453
+ "required": false,
3454
+ "description": "Registro pai usado para resolver parentIdPathVariable."
3434
3455
  },
3435
3456
  {
3436
3457
  "name": "parentResourceId",
3437
3458
  "type": "string | number | null",
3438
- "required": false
3459
+ "required": false,
3460
+ "description": "Identificador explícito do registro pai quando não vem do record."
3439
3461
  },
3440
3462
  {
3441
3463
  "name": "parentResourcePath",
3442
3464
  "type": "string | null",
3443
- "required": false
3465
+ "required": false,
3466
+ "description": "ResourcePath do recurso pai para contexto da surface."
3444
3467
  },
3445
3468
  {
3446
3469
  "name": "queryContext",
3447
3470
  "type": "RelatedResourceQueryContext | null",
3448
- "required": false
3471
+ "required": false,
3472
+ "description": "QueryContext base mesclado com o filtro canônico da relação filha."
3449
3473
  },
3450
3474
  {
3451
3475
  "name": "tableConfig",
3452
3476
  "type": "Record<string, unknown> | null",
3453
- "required": false
3477
+ "required": false,
3478
+ "description": "Configuracao parcial da tabela filha materializada, mesclada ao preset canonico."
3454
3479
  },
3455
3480
  {
3456
3481
  "name": "emptyState",
3457
3482
  "type": "Record<string, unknown> | null",
3458
- "required": false
3483
+ "required": false,
3484
+ "description": "Override opcional para behavior.emptyState da tabela filha. Quando omitido, o outlet deriva texto, icone, layout e ação create a partir de surface.relatedResource e dos metadados da surface."
3485
+ },
3486
+ {
3487
+ "name": "enableCustomization",
3488
+ "type": "boolean",
3489
+ "required": false,
3490
+ "description": "Opt-in explicito para authoring governado da tabela filha.",
3491
+ "default": false
3492
+ },
3493
+ {
3494
+ "name": "authoringCapability",
3495
+ "type": "string | null",
3496
+ "required": false,
3497
+ "description": "Capability publica do EnterpriseRuntimeContext exigida quando o authoring da tabela filha estiver habilitado."
3459
3498
  },
3460
3499
  {
3461
3500
  "name": "mode",
3462
3501
  "type": "'inline' | 'open-action'",
3463
- "required": false
3502
+ "required": false,
3503
+ "description": "Renderiza a tabela filha inline ou emite payload para abertura host-mediated.",
3504
+ "default": "inline"
3464
3505
  },
3465
3506
  {
3466
3507
  "name": "state",
3467
3508
  "type": "RelatedResourceResolutionState | null",
3468
- "required": false
3509
+ "required": false,
3510
+ "description": "Override de estado para hosts/outlets que estejam carregando discovery remoto."
3469
3511
  },
3470
3512
  {
3471
3513
  "name": "compact",
3472
3514
  "type": "boolean",
3473
- "required": false
3515
+ "required": false,
3516
+ "description": "Reduz densidade visual dos estados não materializados.",
3517
+ "default": false
3474
3518
  },
3475
3519
  {
3476
3520
  "name": "strictValidation",
3477
3521
  "type": "boolean",
3478
- "required": false
3522
+ "required": false,
3523
+ "description": "Validação estrita do widget materializado pelo DynamicWidgetLoader.",
3524
+ "default": false
3479
3525
  }
3480
3526
  ],
3481
3527
  "outputs": [
3482
3528
  {
3483
3529
  "name": "surfaceOpen",
3484
3530
  "type": "SurfaceOpenPayload",
3485
- "required": false
3531
+ "required": false,
3532
+ "description": "Emitido em modo open-action com o payload pronto de surface.open."
3486
3533
  },
3487
3534
  {
3488
3535
  "name": "widgetEvent",
3489
3536
  "type": "WidgetEventEnvelope",
3490
- "required": false
3537
+ "required": false,
3538
+ "description": "Reemite eventos do widget filho materializado."
3491
3539
  },
3492
3540
  {
3493
3541
  "name": "resourceEvent",
3494
3542
  "type": "PraxisResourceEvent",
3495
- "required": false
3543
+ "required": false,
3544
+ "description": "Promove eventos canonicos emitidos pelo widget filho materializado."
3496
3545
  }
3497
3546
  ],
3498
3547
  "configSchemaId": null,
@@ -3513,9 +3562,9 @@
3513
3562
  {
3514
3563
  "chunkIndex": 0,
3515
3564
  "chunkKind": "summary",
3516
- "content": "Component ID: praxis-related-resource-outlet\nSelector: praxis-related-resource-outlet\nFriendly Name: Related Resource Outlet\nDescription: Runtime genérico para materializar surface.relatedResource como tabela filha governada por metadata.\nLib/Package: @praxisui/core\nTags: resource, surface, related-resource, runtime, metadata-driven\nInputs:\n - surfaceId (string | null)\n - surfaceCatalog (ResourceSurfaceCatalogResponse | null)\n - discoverySource (ResourceLinkSource | null)\n - parentLinks (RestApiLinks | RestApiResponse<unknown> | null)\n - apiEndpointKey (ApiEndpoint | null)\n - apiUrlEntry (ApiUrlEntry | null)\n - surface (ResourceSurfaceCatalogItem | null)\n - parentRecord (Record<string, unknown> | null)\n - parentResourceId (string | number | null)\n - parentResourcePath (string | null)\n - queryContext (RelatedResourceQueryContext | null)\n - tableConfig (Record<string, unknown> | null)\n - emptyState (Record<string, unknown> | null)\n - mode ('inline' | 'open-action')\n - state (RelatedResourceResolutionState | null)\n - compact (boolean)\n - strictValidation (boolean)\nOutputs:\n - surfaceOpen (SurfaceOpenPayload)\n - widgetEvent (WidgetEventEnvelope)\n - resourceEvent (PraxisResourceEvent)\n",
3517
- "sourcePointer": "praxis-ui-angular/projects/praxis-core/src/lib/surfaces/praxis-related-resource-outlet.metadata.ts",
3518
- "contentHash": "ed0e5060deaf28019e48fc89e52c8c0d6e0ab3b1f3b67e05300305ab347d95f8",
3565
+ "content": "Component ID: praxis-related-resource-outlet\nSelector: praxis-related-resource-outlet\nFriendly Name: Related Resource Outlet\nDescription: Runtime genérico para materializar surface.relatedResource como tabela filha governada por metadata.\nLib/Package: @praxisui/core\nTags: resource, surface, related-resource, runtime, metadata-driven\nInputs:\n - surfaceId (string | null)\n - surfaceCatalog (ResourceSurfaceCatalogResponse | null)\n - discoverySource (ResourceLinkSource | null)\n - parentLinks (RestApiLinks | RestApiResponse<unknown> | null)\n - apiEndpointKey (ApiEndpoint | null)\n - apiUrlEntry (ApiUrlEntry | null)\n - surface (ResourceSurfaceCatalogItem | null)\n - parentRecord (Record<string, unknown> | null)\n - parentResourceId (string | number | null)\n - parentResourcePath (string | null)\n - queryContext (RelatedResourceQueryContext | null)\n - tableConfig (Record<string, unknown> | null)\n - emptyState (Record<string, unknown> | null)\n - enableCustomization (boolean)\n - authoringCapability (string | null)\n - mode ('inline' | 'open-action')\n - state (RelatedResourceResolutionState | null)\n - compact (boolean)\n - strictValidation (boolean)\nOutputs:\n - surfaceOpen (SurfaceOpenPayload)\n - widgetEvent (WidgetEventEnvelope)\n - resourceEvent (PraxisResourceEvent)\n",
3566
+ "sourcePointer": "projects/praxis-core/src/lib/surfaces/praxis-related-resource-outlet.metadata.ts",
3567
+ "contentHash": "a292f2206e7693a0615cd98fd9d8822adaf5b4e611920d57e0c97819eed23551",
3519
3568
  "sourceKind": "component_definition",
3520
3569
  "sourceId": "praxis-related-resource-outlet",
3521
3570
  "corpusVersion": "1.0.0"
@@ -3524,7 +3573,7 @@
3524
3573
  "chunkIndex": 1,
3525
3574
  "chunkKind": "recipe",
3526
3575
  "content": "{\n \"_comment\": \"Recipe para agentes usarem surface.relatedResource com o runtime canonico praxis-related-resource-outlet.\",\n \"_comment2\": \"O filtro pai-filho deve vir de relatedResource.childParentField; nao duplique a mesma regra em composition.links quando o outlet puder resolver.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-related-resource-outlet\",\n \"variantId\": \"inline-table-child-resource\",\n \"status\": \"public-example\",\n \"useWhen\": \"Render a related child resource from surfaceId or ResourceSurfaceCatalogItem.relatedResource without hand-writing table filters or host-specific code.\",\n \"examplePrompts\": [\n \"renderize recursos relacionados de uma linha selecionada\",\n \"crie tabela filha a partir de relatedResource\",\n \"mostrar participantes filtrados pela missao selecionada sem composition manual\"\n ]\n },\n \"platformValue\": {\n \"canonicalContract\": \"praxis-metadata-starter publishes ResourceSurfaceCatalogItem.relatedResource in the surfaces catalog.\",\n \"angularRuntime\": \"@praxisui/core discovers the requested surface by surfaceId when needed, resolves relatedResource into a SurfaceOpenPayload and materializes praxis-table through DynamicWidgetLoader.\",\n \"migrationValue\": \"Hosts keep only surfaceId plus parentRecord or parentResourceId in the page; parent-child filtering is declared once in metadata.\",\n \"agentCorpus\": \"This recipe keeps surfaceId, parentResourcePath, parentResourceId and parentRecord explicit so agents do not infer relationships from labels.\"\n },\n \"authoringGuidance\": [\n \"Use praxis-related-resource-outlet with surfaceId when the parent resource publishes item-level surfaces.\",\n \"Pass surface directly only when the host already has the ResourceSurfaceCatalogItem available.\",\n \"Pass parentRecord when the selected row is available; pass parentResourceId when only the id is available.\",\n \"Do not repeat childParentField filters in composition.links unless the page intentionally overrides queryContext.\",\n \"Keep availability fail-closed; permission-limited and not-found states should render as outlet states instead of empty tables.\",\n \"Omit emptyState for the default related-resource empty copy; the runtime derives contextual copy and create action from surface.relatedResource. Pass emptyState only when domain-specific wording must override the platform default.\",\n \"Use mode=open-action when the host owns drawer/dialog orchestration; use mode=inline for embedded child tables.\"\n ],\n \"teaches\": [\n \"surface.relatedResource\",\n \"surfaceId\",\n \"praxis-related-resource-outlet\",\n \"related-resource.childParentField\",\n \"related-resource.childResourcePath\",\n \"resourceEvent\",\n \"surfaceOpen\"\n ],\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 2,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"missionParticipants\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"hub\",\n \"title\": \"Related participants\",\n \"subtitle\": \"Child table resolved from surface.relatedResource\"\n },\n \"definition\": {\n \"id\": \"praxis-related-resource-outlet\",\n \"bindingOrder\": [\n \"surfaceId\",\n \"parentRecord\",\n \"parentResourceId\",\n \"parentResourcePath\",\n \"mode\"\n ],\n \"inputs\": {\n \"mode\": \"inline\",\n \"surfaceId\": \"team\",\n \"parentResourcePath\": \"operations/missoes\",\n \"parentResourceId\": 1,\n \"parentRecord\": {\n \"id\": 1,\n \"titulo\": \"Atlantic Shield\",\n \"status\": \"PLANEJADA\"\n }\n },\n \"outputs\": {\n \"widgetEvent\": \"emit\",\n \"resourceEvent\": \"emit\",\n \"surfaceOpen\": \"emit\"\n }\n }\n }\n ]\n }\n}\n",
3527
- "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-related-resource-outlet.json",
3576
+ "sourcePointer": "examples/ai-recipes/praxis-related-resource-outlet.json",
3528
3577
  "contentHash": "42ae917652755ce436674353d912f7fff6548f61be3e523d940aae6983af3d1a",
3529
3578
  "sourceKind": "component_definition",
3530
3579
  "sourceId": "praxis-related-resource-outlet",
@@ -3594,7 +3643,7 @@
3594
3643
  "chunkIndex": 0,
3595
3644
  "chunkKind": "summary",
3596
3645
  "content": "Component ID: praxis-runtime-component-observation\nSelector: praxis-runtime-component-observation\nFriendly Name: Praxis Runtime Component Observation\nDescription: Canonical runtime component observation contract for exposing active component instance grounding to agentic turns.\nCategory: governance\nLib/Package: @praxisui/core\nTags: runtime-observation, semantic-grounding, component-capabilities, governance\n",
3597
- "sourcePointer": "praxis-ui-angular/projects/praxis-core/src/lib/models/runtime-component-observation.model.ts",
3646
+ "sourcePointer": "projects/praxis-core/src/lib/models/runtime-component-observation.model.ts",
3598
3647
  "contentHash": "c83c824c43e04f027372dc6be8ef59e00a636e0f09de59ef84c27a3de816cffd",
3599
3648
  "sourceKind": "component_definition",
3600
3649
  "sourceId": "praxis-runtime-component-observation",
@@ -3604,7 +3653,7 @@
3604
3653
  "chunkIndex": 1,
3605
3654
  "chunkKind": "runtime_observation_contract",
3606
3655
  "content": "{\n \"schemaVersion\": \"praxis-runtime-component-observation.v1\",\n \"publicType\": \"PraxisRuntimeComponentObservationEnvelope\",\n \"ownerPackage\": \"@praxisui/core\",\n \"registryService\": \"PraxisRuntimeComponentObservationRegistryService\",\n \"purpose\": \"Small runtime observation envelope emitted by components so the agentic runtime can ask what component instances, refs, lifecycle, digests, affordance hints, and claims are currently visible before answering.\",\n \"trustBoundary\": \"untrusted_frontend_observation\",\n \"backendGrounding\": {\n \"canonicalContext\": \"GroundedRuntimeComponentContext\",\n \"requirement\": \"Backend turn orchestration must reconcile the envelope against canonical component registry, page state, resource schema, surfaces, actions, permissions, and available tools before any answer is produced.\"\n },\n \"envelopeFields\": [\n \"schemaVersion\",\n \"identity\",\n \"refs\",\n \"lifecycle\",\n \"snapshot\",\n \"affordances\",\n \"claims\",\n \"diagnostics\"\n ],\n \"semanticRefs\": [\n \"componentMetadataId\",\n \"authoringManifestRef\",\n \"resourcePath\",\n \"resourceKey\",\n \"pageId\",\n \"activeOperationRefs\",\n \"activeSurfaceRefs\",\n \"activeActionRefs\"\n ],\n \"governanceRules\": [\n \"Do not treat the frontend envelope as canonical business truth.\",\n \"Do not include raw rows, full form values, secrets, credentials, tokens, or hidden fields in the envelope.\",\n \"Use stateDigest, dataProfileDigest, selectionDigest, schemaFieldRefs, refs, and claims as grounding hints only.\",\n \"Apply diagnostics.redactionApplied and diagnostics.omittedFields whenever runtime state is summarized or omitted.\",\n \"Resolve intent semantically against the grounded context and consult declared component/resource tools before answering.\"\n ]\n}",
3607
- "sourcePointer": "praxis-ui-angular/projects/praxis-core/src/lib/models/runtime-component-observation.model.ts",
3656
+ "sourcePointer": "projects/praxis-core/src/lib/models/runtime-component-observation.model.ts",
3608
3657
  "contentHash": "08ec1d3be1e4c1ae96a2db7213c131dd32aea2cd87aea19d0d88a18982eedad6",
3609
3658
  "sourceKind": "component_definition",
3610
3659
  "sourceId": "praxis-runtime-component-observation",