@praxisui/page-builder 9.0.5-rc.3 → 9.0.5-rc.4

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.
@@ -12541,7 +12541,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
12541
12541
  * Capabilities catalog for the canonical dynamic page builder/runtime.
12542
12542
  */
12543
12543
  const PAGE_BUILDER_AI_CAPABILITIES = {
12544
- version: 'v1.2',
12544
+ version: 'v1.3',
12545
12545
  enums: {},
12546
12546
  targets: [
12547
12547
  'page-builder',
@@ -12558,7 +12558,7 @@ const PAGE_BUILDER_AI_CAPABILITIES = {
12558
12558
  'Canvas e o modelo espacial canonico da pagina quando houver posicionamento explicito.',
12559
12559
  'Taxonomia editorial: condition usa Json Logic canonico; transform usa pipeline declarativo; policy cobre apenas comportamento operacional.',
12560
12560
  '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.',
12561
- 'UiCompositionPlan usa widgets[].componentId e bindings declarativos. O JSON persistido continua sendo page.widgets[].definition.id e page.composition.links.',
12561
+ 'UiCompositionPlan usa widgets[].componentId e bindings declarativos. UiCompositionPlanTemplateReference pode piná-lo por registryKey + configSha256, mas precisa ser resolvido pelo backend governado antes da compilação. O JSON persistido continua sendo page.widgets[].definition.id e page.composition.links.',
12562
12562
  '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.',
12563
12563
  '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.',
12564
12564
  'Payloads legados de layout ainda podem ser ingeridos, mas sao normalizados para canvas e nao devem ser reemitidos.',
@@ -12568,7 +12568,7 @@ const PAGE_BUILDER_AI_CAPABILITIES = {
12568
12568
  { path: 'uiCompositionPlan', category: 'page', valueKind: 'object', description: 'Plano declarativo intermediario aceito em preview agentic antes do WidgetPageDefinition.' },
12569
12569
  { path: 'uiCompositionPlan.version', category: 'page', valueKind: 'string', description: 'Versao do plano. Valor atual: 1.0.' },
12570
12570
  { path: 'uiCompositionPlan.kind', category: 'page', valueKind: 'string', description: 'Discriminador do plano. Valor atual: praxis.ui-composition-plan.' },
12571
- { path: 'uiCompositionPlan.i18n', category: 'page', valueKind: 'object', description: 'Catalogo de textos de negocio da pagina, compilado para page.i18n sem criar copy no runtime.' },
12571
+ { path: 'uiCompositionPlan.i18n', category: 'page', valueKind: 'object', description: 'Catalogo de textos de negocio da pagina, compilado para page.i18n. Descritores PraxisTextValue podem declarar apenas key quando a chave existir no dicionario do fallbackLocale; o compilador materializa text no documento executavel.' },
12572
12572
  { path: 'uiCompositionPlan.context', category: 'context', valueKind: 'object', description: 'Contexto explicito da pagina, compilado para page.context; nao substitui contextScopes de autoria.' },
12573
12573
  { path: 'uiCompositionPlan.layout', category: 'layout', valueKind: 'object', description: 'Layout responsivo canonico compilado para page.layout quando a pagina nao usa apenas canvas/preset.' },
12574
12574
  { path: 'uiCompositionPlan.layoutPreset', category: 'layout', valueKind: 'string', description: 'Preset semantico opcional da composicao planejada.' },
@@ -12584,6 +12584,11 @@ const PAGE_BUILDER_AI_CAPABILITIES = {
12584
12584
  { path: 'uiCompositionPlan.widgets[].shell', category: 'widgets', valueKind: 'object', description: 'Moldura governada do widget, compilada para page.widgets[].shell sem enriquecimento do host.' },
12585
12585
  { path: 'uiCompositionPlan.widgets[].inputs', category: 'widgets', valueKind: 'object', description: 'Inputs canonicos do componente, compilados para definition.inputs.' },
12586
12586
  { path: 'uiCompositionPlan.widgets[].bindingOrder', category: 'widgets', valueKind: 'array', description: 'Ordem declarativa de binding, compilada para definition.bindingOrder.' },
12587
+ { path: 'uiCompositionPlan.selectionSyncs', category: 'connections', valueKind: 'array', description: 'Atalhos declarativos para projetar o mesmo contexto de selecao a partir de varias portas; sempre compilam para links canonicos explicitos.' },
12588
+ { path: 'uiCompositionPlan.contextScopes', category: 'context', valueKind: 'array', description: 'Escopos de autoria que distribuem contexto explicito a widgets top-level ou nested; nao criam heranca ambiente no runtime.' },
12589
+ { path: 'uiCompositionPlan.contextScopes[].context', category: 'context', valueKind: 'object', description: 'Mapa input -> constant ou state. Constant e state.initial viram inputs explicitos; state tambem gera link state-read canonico.' },
12590
+ { path: 'uiCompositionPlan.contextScopes[].context.<token>', category: 'context', valueKind: 'object', description: 'Descritor constant ou state. Em state, initial aceita um valor JSON opcional materializado no input antes da primeira propagacao; nao cria um segundo state store.' },
12591
+ { path: 'uiCompositionPlan.contextScopes[].targets', category: 'context', valueKind: 'array', description: 'Destinos explicitos do escopo, identificados por widget owner e nestedPath canonico opcional.' },
12587
12592
  { path: 'uiCompositionPlan.bindings', category: 'connections', valueKind: 'array', description: 'Bindings declarativos que serao compilados para page.composition.links.' },
12588
12593
  { path: 'uiCompositionPlan.bindings[].id', category: 'connections', valueKind: 'string', description: 'Identificador estavel do binding planejado.' },
12589
12594
  { path: 'uiCompositionPlan.bindings[].from', category: 'connections', valueKind: 'object', description: 'Endpoint de origem: component-port ou state.' },
@@ -13230,9 +13235,9 @@ const PAGE_BUILDER_COMPONENT_CONTEXT_PACK = {
13230
13235
  },
13231
13236
  hints: [
13232
13237
  'For agentic page creation, prefer returning uiCompositionPlan in the preview envelope and let the page-builder compiler emit WidgetPageDefinition.',
13233
- 'Carry page-owned i18n, explicit context, canonical layout and governed widget shell in uiCompositionPlan; do not depend on host-only enrichment after compilation.',
13238
+ 'Carry page-owned i18n, explicit context, canonical layout and governed widget shell in uiCompositionPlan; when a PraxisTextValue key exists in the fallbackLocale dictionary, omit repeated text and let the compiler materialize the executable fallback.',
13234
13239
  'Use uiCompositionPlan.widgets[].componentId in plans; the compiler maps it to page.widgets[].definition.id.',
13235
- 'Use uiCompositionPlan.selectionSyncs for repeated selection projections, contextScopes for repeated explicit widget context, and bindings for remaining wiring; the compiler emits page.composition.links.',
13240
+ 'Use uiCompositionPlan.selectionSyncs for repeated selection projections, contextScopes for repeated explicit widget context, and bindings for remaining wiring; constant values and state.initial become explicit inputs, while state references compile to page.composition.links.',
13236
13241
  'For nested component ports, use component-port endpoints with nestedPath in uiCompositionPlan.bindings; keep widget as the top-level owner and put the real child port in port/direction.',
13237
13242
  'NestedPath must be relative to the owner widget and must end with a widget segment containing a stable key. Do not use index as the only identity.',
13238
13243
  'Do not author nested links through owner.widgetEvent, deep bindingPath, page.connections, or host-specific wrapper outputs; those are legacy or bridge mechanisms.',
@@ -13579,7 +13584,7 @@ const PRAXIS_PAGE_BUILDER_AUTHORING_MANIFEST = {
13579
13584
  componentId: 'praxis-page-builder',
13580
13585
  ownerPackage: '@praxisui/page-builder',
13581
13586
  configSchemaId: 'WidgetPageDefinition',
13582
- manifestVersion: '1.0.0',
13587
+ manifestVersion: '1.1.0',
13583
13588
  runtimeInputs: [
13584
13589
  { name: 'page', type: 'WidgetPageDefinition', description: 'Canonical renderable page document consumed by praxis-dynamic-page.' },
13585
13590
  { name: 'pageIdentity', type: 'PageIdentity | null', description: 'Persistence identity for ui_user_config save/apply flows; not persisted inside page.' },
@@ -13770,11 +13775,11 @@ const PRAXIS_PAGE_BUILDER_AUTHORING_MANIFEST = {
13770
13775
  target: { kind: 'agenticPreview', resolver: 'agentic-preview-result', ambiguityPolicy: 'fail', required: true },
13771
13776
  inputSchema: { type: 'object', required: ['uiCompositionPlan'], properties: { uiCompositionPlan: { type: 'object' } } },
13772
13777
  effects: [{ kind: 'compile-domain-patch', handler: 'page-builder-ui-composition-plan-compile', handlerContract: {
13773
- reads: ['UiCompositionPlan', 'UiCompositionPlan.i18n', 'UiCompositionPlan.context', 'UiCompositionPlan.layout', 'UiCompositionPlan.selectionSyncs', 'UiCompositionPlan.contextScopes', 'compileUiCompositionPlan', 'PAGE_BUILDER_WIDGET_AI_CATALOGS', 'ComponentDocMeta.configEditor'],
13778
+ reads: ['UiCompositionPlanAuthoringInput', 'UiCompositionPlan', 'UiCompositionPlanTemplateReference', 'UiCompositionPlanTemplateMaterialization', 'UiCompositionPlan.i18n', 'UiCompositionPlan.context', 'UiCompositionPlan.layout', 'UiCompositionPlan.selectionSyncs', 'UiCompositionPlan.contextScopes', 'resolveUiCompositionPlanTemplate', 'compileUiCompositionPlan', 'PAGE_BUILDER_WIDGET_AI_CATALOGS', 'ComponentDocMeta.configEditor'],
13774
13779
  writes: ['compiledFormPatch.patch.page'],
13775
13780
  identityKeys: ['uiCompositionPlan.id', 'widgetKey', 'uiCompositionPlan.bindings[].id', 'uiCompositionPlan.selectionSyncs[].id', 'uiCompositionPlan.contextScopes[].id'],
13776
- failureModes: ['ui-composition-plan-invalid', 'widget-catalog-missing', 'compiled-page-invalid', 'child-config-editor-missing'],
13777
- description: 'Compiles the agentic intermediate UiCompositionPlan into a renderable WidgetPageDefinition patch.page.',
13781
+ failureModes: ['ui-composition-plan-invalid', 'ui-composition-template-reference-invalid', 'ui-composition-template-not-found', 'ui-composition-template-hash-mismatch', 'ui-composition-template-overrides-unsupported', 'widget-catalog-missing', 'compiled-page-invalid', 'child-config-editor-missing'],
13782
+ description: 'Resolves an optional exact governed template reference and compiles the expanded UiCompositionPlan into a renderable WidgetPageDefinition patch.page.',
13778
13783
  } }],
13779
13784
  validators: ['ui-composition-plan-valid', 'compiled-page-valid', 'widget-keys-unique', 'composition-endpoints-resolve', 'canvas-items-reference-existing-widgets'],
13780
13785
  affectedPaths: ['uiCompositionPlan', 'compiledFormPatch.patch.page'],
@@ -13909,9 +13914,9 @@ const PRAXIS_PAGE_BUILDER_AUTHORING_MANIFEST = {
13909
13914
  roundTripRequirements: [
13910
13915
  'WidgetPageDefinition is the canonical persisted runtime page shape for page-builder.',
13911
13916
  'UiCompositionPlan is an intermediate agentic plan and must compile before local preview/apply.',
13912
- 'UiCompositionPlan.i18n, context and layout compile into the corresponding WidgetPageDefinition fields so a complete page never depends on host-only enrichment.',
13917
+ 'UiCompositionPlan.i18n, context and layout compile into the corresponding WidgetPageDefinition fields so a complete page never depends on host-only enrichment. A key-only PraxisTextValue receives text from the fallbackLocale dictionary when available.',
13913
13918
  'UiCompositionPlan.selectionSyncs is an authoring shorthand that compiles into explicit canonical page.composition.links and is never persisted in WidgetPageDefinition.',
13914
- 'UiCompositionPlan.contextScopes compiles constant context into explicit widget inputs and state context into explicit page.composition.links; runtime inheritance is never ambient.',
13919
+ 'UiCompositionPlan.contextScopes compiles constants and state.initial into explicit widget inputs, and state context into explicit page.composition.links; runtime inheritance is never ambient.',
13915
13920
  'Widget keys and composition link ids are stable identities; array indexes are never canonical identities.',
13916
13921
  'Persisted wiring uses page.composition.links and must not write legacy connections.',
13917
13922
  'Nested component ports use component-port refs with nestedPath ending in a stable widget key.',
@@ -14043,6 +14048,56 @@ const PRAXIS_PAGE_BUILDER_AUTHORING_MANIFEST = {
14043
14048
  ],
14044
14049
  };
14045
14050
 
14051
+ /**
14052
+ * Pure, fail-closed normalization for an exact template reference.
14053
+ *
14054
+ * The function performs no HTTP, registry search or template selection. The governed backend must
14055
+ * supply the exact materialization and its revision evidence before the existing compiler runs.
14056
+ */
14057
+ function resolveUiCompositionPlanTemplate(input, materialization) {
14058
+ if (!hasTemplateReference(input)) {
14059
+ return { valid: true, referenced: false, plan: input, diagnostics: [] };
14060
+ }
14061
+ const diagnostics = validateTemplateReference(input);
14062
+ if (diagnostics.length) {
14063
+ return { valid: false, referenced: true, plan: null, diagnostics };
14064
+ }
14065
+ if (!materialization || materialization.registryKey !== input.templateRef.registryKey) {
14066
+ return invalidTemplateResolution('ui-composition-template-not-found', 'The exact governed template was not supplied.');
14067
+ }
14068
+ if (!SHA_256_PATTERN.test(materialization.revision?.configSha256 ?? '')) {
14069
+ return invalidTemplateResolution('ui-composition-template-revision-invalid', 'The governed template revision is invalid.');
14070
+ }
14071
+ if (materialization.revision.configSha256 !== input.templateRef.configSha256) {
14072
+ return invalidTemplateResolution('ui-composition-template-hash-mismatch', 'The governed template content no longer matches the pinned hash.');
14073
+ }
14074
+ if (materialization.authoringPlan?.kind !== 'praxis.ui-composition-plan') {
14075
+ return invalidTemplateResolution('ui-composition-template-authoring-plan-kind-invalid', 'The governed artifact is not a UI composition plan.');
14076
+ }
14077
+ if (materialization.authoringPlan.version !== '1.0') {
14078
+ return invalidTemplateResolution('ui-composition-template-authoring-plan-version-invalid', 'The governed UI composition plan version is unsupported.');
14079
+ }
14080
+ const plan = clone(materialization.authoringPlan);
14081
+ plan.diagnostics = {
14082
+ ...(plan.diagnostics ?? {}),
14083
+ templateResolution: {
14084
+ registryKey: materialization.registryKey,
14085
+ configSha256: materialization.revision.configSha256,
14086
+ ...(materialization.revision.version == null ? {} : { version: materialization.revision.version }),
14087
+ ...(materialization.revision.etag ? { etag: materialization.revision.etag } : {}),
14088
+ },
14089
+ };
14090
+ return {
14091
+ valid: true,
14092
+ referenced: true,
14093
+ plan,
14094
+ diagnostics: [{
14095
+ code: 'ui-composition-template-reference-resolved',
14096
+ message: 'The exact governed template reference was resolved.',
14097
+ path: 'templateRef',
14098
+ }],
14099
+ };
14100
+ }
14046
14101
  function compileUiCompositionPlan(plan) {
14047
14102
  const diagnostics = validateUiCompositionPlan(plan);
14048
14103
  if (diagnostics.length) {
@@ -14053,30 +14108,115 @@ function compileUiCompositionPlan(plan) {
14053
14108
  };
14054
14109
  }
14055
14110
  const bindings = expandedBindings(plan);
14056
- const widgets = materializeContextScopeConstants(plan, plan.widgets.map((widget) => toWidgetInstance(widget, bindings)));
14111
+ const widgets = materializeContextScopeInputs(plan, plan.widgets.map((widget) => toWidgetInstance(widget, bindings)));
14112
+ const page = {
14113
+ i18n: clone(plan.i18n),
14114
+ context: clone(plan.context),
14115
+ layout: clone(plan.layout),
14116
+ layoutPreset: plan.layoutPreset,
14117
+ layoutPresetOptions: clone(plan.layoutPresetOptions),
14118
+ canvas: resolveCanvas(plan),
14119
+ deviceLayouts: clone(plan.deviceLayouts),
14120
+ grouping: clone(plan.grouping),
14121
+ slotAssignments: clone(plan.slotAssignments),
14122
+ state: clone(plan.state),
14123
+ themePreset: plan.themePreset,
14124
+ widgets,
14125
+ composition: {
14126
+ version: '1.0.0',
14127
+ links: bindings.map(toCompositionLink),
14128
+ },
14129
+ };
14057
14130
  return {
14058
14131
  valid: true,
14059
- page: {
14060
- i18n: clone(plan.i18n),
14061
- context: clone(plan.context),
14062
- layout: clone(plan.layout),
14063
- layoutPreset: plan.layoutPreset,
14064
- layoutPresetOptions: clone(plan.layoutPresetOptions),
14065
- canvas: resolveCanvas(plan),
14066
- deviceLayouts: clone(plan.deviceLayouts),
14067
- grouping: clone(plan.grouping),
14068
- slotAssignments: clone(plan.slotAssignments),
14069
- state: clone(plan.state),
14070
- themePreset: plan.themePreset,
14071
- widgets,
14072
- composition: {
14073
- version: '1.0.0',
14074
- links: bindings.map(toCompositionLink),
14075
- },
14076
- },
14132
+ page: materializeLocalizedFallbacks(page),
14077
14133
  diagnostics: [],
14078
14134
  };
14079
14135
  }
14136
+ const SHA_256_PATTERN = /^[0-9a-f]{64}$/;
14137
+ const TEMPLATE_REFERENCE_FIELDS = new Set(['version', 'kind', 'templateRef', 'overrides']);
14138
+ const TEMPLATE_REF_FIELDS = new Set(['registryKey', 'configSha256']);
14139
+ function hasTemplateReference(input) {
14140
+ return input != null && typeof input === 'object' && 'templateRef' in input;
14141
+ }
14142
+ function validateTemplateReference(input) {
14143
+ const diagnostics = [];
14144
+ if (input.kind !== 'praxis.ui-composition-plan') {
14145
+ diagnostics.push(templateDiagnostic('ui-composition-template-reference-kind-invalid', 'kind'));
14146
+ }
14147
+ if (input.version !== '1.0') {
14148
+ diagnostics.push(templateDiagnostic('ui-composition-template-reference-version-invalid', 'version'));
14149
+ }
14150
+ if (!isRecord$1(input.templateRef)) {
14151
+ diagnostics.push(templateDiagnostic('ui-composition-template-reference-object-required', 'templateRef'));
14152
+ return diagnostics;
14153
+ }
14154
+ const registryKey = input.templateRef.registryKey;
14155
+ if (typeof registryKey !== 'string' || !registryKey || registryKey !== registryKey.trim()) {
14156
+ diagnostics.push(templateDiagnostic('ui-composition-template-registry-key-invalid', 'templateRef.registryKey'));
14157
+ }
14158
+ if (typeof input.templateRef.configSha256 !== 'string' || !SHA_256_PATTERN.test(input.templateRef.configSha256)) {
14159
+ diagnostics.push(templateDiagnostic('ui-composition-template-config-sha256-invalid', 'templateRef.configSha256'));
14160
+ }
14161
+ if (Object.keys(input.templateRef).some((field) => !TEMPLATE_REF_FIELDS.has(field))
14162
+ || Object.keys(input.templateRef).length !== TEMPLATE_REF_FIELDS.size) {
14163
+ diagnostics.push(templateDiagnostic('ui-composition-template-reference-fields-invalid', 'templateRef'));
14164
+ }
14165
+ if (input.overrides !== undefined && (!isRecord$1(input.overrides) || Object.keys(input.overrides).length > 0)) {
14166
+ diagnostics.push(templateDiagnostic('ui-composition-template-overrides-unsupported', 'overrides'));
14167
+ }
14168
+ if (Object.keys(input).some((field) => !TEMPLATE_REFERENCE_FIELDS.has(field))) {
14169
+ diagnostics.push(templateDiagnostic('ui-composition-template-reference-mixed-plan'));
14170
+ }
14171
+ return diagnostics;
14172
+ }
14173
+ function invalidTemplateResolution(code, message) {
14174
+ return {
14175
+ valid: false,
14176
+ referenced: true,
14177
+ plan: null,
14178
+ diagnostics: [{ code, message, path: 'templateRef' }],
14179
+ };
14180
+ }
14181
+ function templateDiagnostic(code, path) {
14182
+ return { code, message: 'The governed template reference is invalid.', path };
14183
+ }
14184
+ function isRecord$1(value) {
14185
+ return value != null && typeof value === 'object' && !Array.isArray(value);
14186
+ }
14187
+ /**
14188
+ * Keeps authoring plans compact while preserving a portable executable page.
14189
+ * A descriptor authored as `{ key }` inherits its runtime fallback from the
14190
+ * page-owned fallback-locale dictionary. The source plan remains untouched.
14191
+ */
14192
+ function materializeLocalizedFallbacks(page) {
14193
+ const materialized = clone(page);
14194
+ const fallbackLocale = materialized.i18n?.fallbackLocale?.trim() || 'pt-BR';
14195
+ const dictionary = materialized.i18n?.dictionaries?.[fallbackLocale];
14196
+ if (!dictionary)
14197
+ return materialized;
14198
+ const descriptorKeys = new Set(['key', 'text', 'params']);
14199
+ const visit = (value) => {
14200
+ if (Array.isArray(value)) {
14201
+ value.forEach(visit);
14202
+ return;
14203
+ }
14204
+ if (!value || typeof value !== 'object')
14205
+ return;
14206
+ const record = value;
14207
+ const keys = Object.keys(record);
14208
+ const key = typeof record['key'] === 'string' ? record['key'].trim() : '';
14209
+ if (key
14210
+ && !Object.prototype.hasOwnProperty.call(record, 'text')
14211
+ && keys.every((candidate) => descriptorKeys.has(candidate))
14212
+ && typeof dictionary[key] === 'string') {
14213
+ record['text'] = dictionary[key];
14214
+ }
14215
+ Object.values(record).forEach(visit);
14216
+ };
14217
+ visit(materialized);
14218
+ return materialized;
14219
+ }
14080
14220
  function resolveCanvas(plan) {
14081
14221
  if (plan.canvas) {
14082
14222
  return clone(plan.canvas);
@@ -14084,6 +14224,13 @@ function resolveCanvas(plan) {
14084
14224
  if (!plan.widgets?.length) {
14085
14225
  return undefined;
14086
14226
  }
14227
+ // An explicitly authored flow/grid layout is already a complete spatial
14228
+ // decision. Synthesizing a canvas here would silently take precedence over
14229
+ // that layout in the runtime. Preset- or role-driven plans still opt into
14230
+ // automatic canvas materialization below.
14231
+ if (plan.layout && !plan.layoutPreset?.trim() && !isMasterDetailPlan(plan)) {
14232
+ return undefined;
14233
+ }
14087
14234
  if (isMasterDetailPlan(plan)) {
14088
14235
  return masterDetailCanvas(plan.widgets);
14089
14236
  }
@@ -14256,7 +14403,14 @@ function validateSelectionSync(selectionSync, widgetKeys, diagnostics, path) {
14256
14403
  }
14257
14404
  for (const [sourceIndex, source] of (selectionSync.sources ?? []).entries()) {
14258
14405
  validateEndpoint(source, widgetKeys, diagnostics, `${path}.sources.${sourceIndex}`, false);
14259
- if (source?.kind === 'component-port' && source.direction !== 'output') {
14406
+ if (source?.kind !== 'component-port') {
14407
+ diagnostics.push({
14408
+ code: 'selection-sync-source-component-port-required',
14409
+ message: 'Selection sync sources must be component output ports.',
14410
+ path: `${path}.sources.${sourceIndex}.kind`,
14411
+ });
14412
+ }
14413
+ else if (source.direction !== 'output') {
14260
14414
  diagnostics.push({
14261
14415
  code: 'selection-sync-source-direction-invalid',
14262
14416
  message: 'Selection sync sources must be component output ports.',
@@ -14328,14 +14482,25 @@ function validateContextScope(contextScope, plan, widgetKeys, diagnostics, path)
14328
14482
  path: `${path}.context`,
14329
14483
  });
14330
14484
  }
14331
- if (contextValue?.kind === 'state' && !contextValue.path?.trim()) {
14332
- diagnostics.push({
14333
- code: 'context-scope-state-path-required',
14334
- message: `Context value "${contextKey}" must declare a state path.`,
14335
- path: `${path}.context.${contextKey}.path`,
14336
- });
14485
+ if (contextValue?.kind === 'state') {
14486
+ if (!contextValue.path?.trim()) {
14487
+ diagnostics.push({
14488
+ code: 'context-scope-state-path-required',
14489
+ message: `Context value "${contextKey}" must declare a state path.`,
14490
+ path: `${path}.context.${contextKey}.path`,
14491
+ });
14492
+ }
14493
+ }
14494
+ else if (contextValue?.kind === 'constant') {
14495
+ if (!Object.prototype.hasOwnProperty.call(contextValue, 'value')) {
14496
+ diagnostics.push({
14497
+ code: 'context-scope-constant-value-required',
14498
+ message: `Context value "${contextKey}" must declare a constant value.`,
14499
+ path: `${path}.context.${contextKey}.value`,
14500
+ });
14501
+ }
14337
14502
  }
14338
- else if (contextValue?.kind !== 'state' && contextValue?.kind !== 'constant') {
14503
+ else {
14339
14504
  diagnostics.push({
14340
14505
  code: 'context-scope-value-kind-invalid',
14341
14506
  message: `Context value "${contextKey}" must be constant or state.`,
@@ -14643,7 +14808,7 @@ function expandContextScopeBindings(contextScope) {
14643
14808
  });
14644
14809
  });
14645
14810
  }
14646
- function materializeContextScopeConstants(plan, sourceWidgets) {
14811
+ function materializeContextScopeInputs(plan, sourceWidgets) {
14647
14812
  const accessor = new NestedWidgetConfigAccessor();
14648
14813
  const widgets = sourceWidgets.map((widget) => clone(widget));
14649
14814
  for (const contextScope of plan.contextScopes ?? []) {
@@ -14656,10 +14821,17 @@ function materializeContextScopeConstants(plan, sourceWidgets) {
14656
14821
  : Object.keys(contextScope.context);
14657
14822
  for (const contextKey of inheritedKeys) {
14658
14823
  const contextValue = contextScope.context[contextKey];
14659
- if (!contextValue || contextValue.kind !== 'constant')
14824
+ if (!contextValue)
14825
+ continue;
14826
+ const hasInitial = contextValue.kind === 'state'
14827
+ && Object.prototype.hasOwnProperty.call(contextValue, 'initial');
14828
+ if (contextValue.kind !== 'constant' && !hasInitial)
14660
14829
  continue;
14830
+ const inputValue = contextValue.kind === 'constant'
14831
+ ? contextValue.value
14832
+ : contextValue.initial;
14661
14833
  if (target.nestedPath?.length) {
14662
- const result = accessor.setNestedWidgetInput(widgets[widgetIndex], target.nestedPath, contextKey, contextValue.value);
14834
+ const result = accessor.setNestedWidgetInput(widgets[widgetIndex], target.nestedPath, contextKey, inputValue);
14663
14835
  widgets[widgetIndex] = result.widget;
14664
14836
  }
14665
14837
  else {
@@ -14669,7 +14841,7 @@ function materializeContextScopeConstants(plan, sourceWidgets) {
14669
14841
  ...widgets[widgetIndex].definition,
14670
14842
  inputs: {
14671
14843
  ...(widgets[widgetIndex].definition.inputs ?? {}),
14672
- [contextKey]: clone(contextValue.value),
14844
+ [contextKey]: clone(inputValue),
14673
14845
  },
14674
14846
  },
14675
14847
  };
@@ -25565,4 +25737,4 @@ function providePraxisPageBuilderMetadata() {
25565
25737
  * Generated bundle index. Do not edit.
25566
25738
  */
25567
25739
 
25568
- export { ComponentPaletteDialogComponent, ConfirmDialogComponent, ConnectionEditorComponent, DynamicPageBuilderComponent, DynamicPageConfigEditorComponent, FloatingToolbarComponent, PAGE_BUILDER_AGENTIC_AUTHORING_OPTIONS, PAGE_BUILDER_AI_CAPABILITIES, PAGE_BUILDER_COMPONENT_CONTEXT_PACK, PAGE_BUILDER_WIDGET_AI_CATALOGS, PLACEHOLDER, PRAXIS_PAGE_BUILDER_AUTHORING_MANIFEST, PRAXIS_PAGE_BUILDER_COMPONENT_METADATA, PageBuilderAgenticAuthoringService, PageConfigEditorComponent, TileToolbarComponent, WidgetShellEditorComponent, clearWidgetAiCatalogs, compileUiCompositionPlan, getPageAiCatalog, getWidgetAiCapabilities, providePageBuilderWidgetAiCatalogs, providePraxisPageBuilderMetadata, registerWidgetAiCatalog, registerWidgetAiCatalogs, validateUiCompositionPlan };
25740
+ export { ComponentPaletteDialogComponent, ConfirmDialogComponent, ConnectionEditorComponent, DynamicPageBuilderComponent, DynamicPageConfigEditorComponent, FloatingToolbarComponent, PAGE_BUILDER_AGENTIC_AUTHORING_OPTIONS, PAGE_BUILDER_AI_CAPABILITIES, PAGE_BUILDER_COMPONENT_CONTEXT_PACK, PAGE_BUILDER_WIDGET_AI_CATALOGS, PLACEHOLDER, PRAXIS_PAGE_BUILDER_AUTHORING_MANIFEST, PRAXIS_PAGE_BUILDER_COMPONENT_METADATA, PageBuilderAgenticAuthoringService, PageConfigEditorComponent, TileToolbarComponent, WidgetShellEditorComponent, clearWidgetAiCatalogs, compileUiCompositionPlan, getPageAiCatalog, getWidgetAiCapabilities, providePageBuilderWidgetAiCatalogs, providePraxisPageBuilderMetadata, registerWidgetAiCatalog, registerWidgetAiCatalogs, resolveUiCompositionPlanTemplate, validateUiCompositionPlan };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@praxisui/page-builder",
3
- "version": "9.0.5-rc.3",
3
+ "version": "9.0.5-rc.4",
4
4
  "description": "Page and widget builder utilities for Praxis UI (grid, dynamic widgets, editors).",
5
5
  "peerDependencies": {
6
6
  "@angular/common": "^21.0.0",
@@ -8,9 +8,9 @@
8
8
  "@angular/forms": "^21.0.0",
9
9
  "@angular/cdk": "^21.0.0",
10
10
  "@angular/material": "^21.0.0",
11
- "@praxisui/ai": "^9.0.5-rc.3",
12
- "@praxisui/core": "^9.0.5-rc.3",
13
- "@praxisui/settings-panel": "^9.0.5-rc.3",
11
+ "@praxisui/ai": "^9.0.5-rc.4",
12
+ "@praxisui/core": "^9.0.5-rc.4",
13
+ "@praxisui/settings-panel": "^9.0.5-rc.4",
14
14
  "rxjs": "~7.8.0"
15
15
  },
16
16
  "dependencies": {
@@ -1576,6 +1576,8 @@ type UiCompositionPlanContextValue = {
1576
1576
  path: string;
1577
1577
  layer?: 'values' | 'derived' | 'transient';
1578
1578
  condition?: unknown;
1579
+ /** Explicit value materialized before the first state propagation. */
1580
+ initial?: unknown;
1579
1581
  };
1580
1582
  interface UiCompositionPlanContextScopeTarget {
1581
1583
  widget: string;
@@ -1584,8 +1586,9 @@ interface UiCompositionPlanContextScopeTarget {
1584
1586
  }
1585
1587
  /**
1586
1588
  * Groups reusable parent/resource context for one or more component targets.
1587
- * Constants become explicit widget inputs and state values become explicit
1588
- * canonical links during compilation; no hidden runtime inheritance remains.
1589
+ * Constants and explicit state initial values become widget inputs, while
1590
+ * state values become canonical links during compilation. No hidden runtime
1591
+ * inheritance remains in the executable page.
1589
1592
  */
1590
1593
  interface UiCompositionPlanContextScope {
1591
1594
  id: string;
@@ -1615,7 +1618,43 @@ interface UiCompositionPlan {
1615
1618
  selectionSyncs?: UiCompositionPlanSelectionSync[];
1616
1619
  contextScopes?: UiCompositionPlanContextScope[];
1617
1620
  bindings?: UiCompositionPlanBinding[];
1621
+ /** Non-executable authoring and resolution evidence; never copied into WidgetPageDefinition. */
1622
+ diagnostics?: Record<string, unknown>;
1618
1623
  }
1624
+ interface UiCompositionPlanTemplateRef {
1625
+ registryKey: string;
1626
+ configSha256: string;
1627
+ }
1628
+ /** Compact intermediate authoring input. It is never a runtime persistence shape. */
1629
+ interface UiCompositionPlanTemplateReference {
1630
+ version: '1.0';
1631
+ kind: 'praxis.ui-composition-plan';
1632
+ templateRef: UiCompositionPlanTemplateRef;
1633
+ overrides?: Readonly<Record<string, never>>;
1634
+ }
1635
+ interface UiCompositionPlanTemplateRevision {
1636
+ version?: number;
1637
+ etag?: string;
1638
+ configSha256: string;
1639
+ }
1640
+ /** Exact template body and revision evidence supplied by the governed backend. */
1641
+ interface UiCompositionPlanTemplateMaterialization {
1642
+ registryKey: string;
1643
+ revision: UiCompositionPlanTemplateRevision;
1644
+ authoringPlan: UiCompositionPlan;
1645
+ }
1646
+ type UiCompositionPlanAuthoringInput = UiCompositionPlan | UiCompositionPlanTemplateReference;
1647
+ type UiCompositionPlanTemplateResolutionResult = {
1648
+ valid: true;
1649
+ referenced: boolean;
1650
+ plan: UiCompositionPlan;
1651
+ diagnostics: UiCompositionPlanDiagnostic[];
1652
+ } | {
1653
+ valid: false;
1654
+ referenced: true;
1655
+ plan: null;
1656
+ diagnostics: UiCompositionPlanDiagnostic[];
1657
+ };
1619
1658
  interface UiCompositionPlanDiagnostic {
1620
1659
  code: string;
1621
1660
  message: string;
@@ -1630,6 +1669,13 @@ type UiCompositionPlanCompileResult = {
1630
1669
  page: null;
1631
1670
  diagnostics: UiCompositionPlanDiagnostic[];
1632
1671
  };
1672
+ /**
1673
+ * Pure, fail-closed normalization for an exact template reference.
1674
+ *
1675
+ * The function performs no HTTP, registry search or template selection. The governed backend must
1676
+ * supply the exact materialization and its revision evidence before the existing compiler runs.
1677
+ */
1678
+ declare function resolveUiCompositionPlanTemplate(input: UiCompositionPlanAuthoringInput, materialization?: UiCompositionPlanTemplateMaterialization): UiCompositionPlanTemplateResolutionResult;
1633
1679
  declare function compileUiCompositionPlan(plan: UiCompositionPlan): UiCompositionPlanCompileResult;
1634
1680
  declare function validateUiCompositionPlan(plan: UiCompositionPlan): UiCompositionPlanDiagnostic[];
1635
1681
 
@@ -2140,5 +2186,5 @@ declare const PRAXIS_PAGE_BUILDER_COMPONENT_METADATA: ComponentDocMeta;
2140
2186
  /** Provider para auto-registrar metadados do componente Page Builder. */
2141
2187
  declare function providePraxisPageBuilderMetadata(): Provider;
2142
2188
 
2143
- export { ComponentPaletteDialogComponent, ConfirmDialogComponent, ConnectionEditorComponent, DynamicPageBuilderComponent, DynamicPageConfigEditorComponent, FloatingToolbarComponent, PAGE_BUILDER_AGENTIC_AUTHORING_OPTIONS, PAGE_BUILDER_AI_CAPABILITIES, PAGE_BUILDER_COMPONENT_CONTEXT_PACK, PAGE_BUILDER_WIDGET_AI_CATALOGS, PLACEHOLDER, PRAXIS_PAGE_BUILDER_AUTHORING_MANIFEST, PRAXIS_PAGE_BUILDER_COMPONENT_METADATA, PageBuilderAgenticAuthoringService, PageConfigEditorComponent, TileToolbarComponent, WidgetShellEditorComponent, clearWidgetAiCatalogs, compileUiCompositionPlan, getPageAiCatalog, getWidgetAiCapabilities, providePageBuilderWidgetAiCatalogs, providePraxisPageBuilderMetadata, registerWidgetAiCatalog, registerWidgetAiCatalogs, validateUiCompositionPlan };
2144
- export type { Capability, CapabilityCatalog, CapabilityCategory, ComponentPaletteData, ComponentPaletteSelection, ConfirmDialogData, PageBuilderAgenticAuthoringAttachmentSummary, PageBuilderAgenticAuthoringCandidate, PageBuilderAgenticAuthoringComponentCapabilitiesResult, PageBuilderAgenticAuthoringComponentCapability, PageBuilderAgenticAuthoringComponentCapabilityCatalog, PageBuilderAgenticAuthoringComponentCapabilityExample, PageBuilderAgenticAuthoringComponentFieldAlias, PageBuilderAgenticAuthoringConversationMessage, PageBuilderAgenticAuthoringGateResult, PageBuilderAgenticAuthoringIntentResolutionRequest, PageBuilderAgenticAuthoringIntentResolutionResult, PageBuilderAgenticAuthoringOptions, PageBuilderAgenticAuthoringPendingClarification, PageBuilderAgenticAuthoringPromptRequest, PageBuilderAgenticAuthoringProvider, PageBuilderAgenticAuthoringQuickReply, PageBuilderAgenticAuthoringResourceCandidatesRequest, PageBuilderAgenticAuthoringResourceCandidatesResult, PageBuilderAgenticAuthoringSharedRuleHandoff, PageBuilderAgenticAuthoringTarget, PageBuilderAgenticAuthoringTurnStreamConnectionError, PageBuilderAgenticAuthoringTurnStreamEvent, PageBuilderAgenticAuthoringTurnStreamRequest, PageBuilderAgenticAuthoringTurnStreamStartResponse, PageBuilderApplyRequest, PageBuilderApplyResult, PageBuilderCompiledFormPatch, PageBuilderMinimalFormPlanResult, PageBuilderPreviewDiagnostics, PageBuilderPreviewResult, PageBuilderProjectKnowledgeAudit, UiCompositionPlan, UiCompositionPlanBinding, UiCompositionPlanCompileResult, UiCompositionPlanComponentPortEndpoint, UiCompositionPlanContextScope, UiCompositionPlanContextScopeTarget, UiCompositionPlanContextValue, UiCompositionPlanDiagnostic, UiCompositionPlanEndpoint, UiCompositionPlanGlobalActionEndpoint, UiCompositionPlanInputSource, UiCompositionPlanSelectionSync, UiCompositionPlanSelectionSyncMapping, UiCompositionPlanSourceEndpoint, UiCompositionPlanStateEndpoint, UiCompositionPlanTargetEndpoint, UiCompositionPlanTransform, UiCompositionPlanWidget, ValueKind };
2189
+ export { ComponentPaletteDialogComponent, ConfirmDialogComponent, ConnectionEditorComponent, DynamicPageBuilderComponent, DynamicPageConfigEditorComponent, FloatingToolbarComponent, PAGE_BUILDER_AGENTIC_AUTHORING_OPTIONS, PAGE_BUILDER_AI_CAPABILITIES, PAGE_BUILDER_COMPONENT_CONTEXT_PACK, PAGE_BUILDER_WIDGET_AI_CATALOGS, PLACEHOLDER, PRAXIS_PAGE_BUILDER_AUTHORING_MANIFEST, PRAXIS_PAGE_BUILDER_COMPONENT_METADATA, PageBuilderAgenticAuthoringService, PageConfigEditorComponent, TileToolbarComponent, WidgetShellEditorComponent, clearWidgetAiCatalogs, compileUiCompositionPlan, getPageAiCatalog, getWidgetAiCapabilities, providePageBuilderWidgetAiCatalogs, providePraxisPageBuilderMetadata, registerWidgetAiCatalog, registerWidgetAiCatalogs, resolveUiCompositionPlanTemplate, validateUiCompositionPlan };
2190
+ export type { Capability, CapabilityCatalog, CapabilityCategory, ComponentPaletteData, ComponentPaletteSelection, ConfirmDialogData, PageBuilderAgenticAuthoringAttachmentSummary, PageBuilderAgenticAuthoringCandidate, PageBuilderAgenticAuthoringComponentCapabilitiesResult, PageBuilderAgenticAuthoringComponentCapability, PageBuilderAgenticAuthoringComponentCapabilityCatalog, PageBuilderAgenticAuthoringComponentCapabilityExample, PageBuilderAgenticAuthoringComponentFieldAlias, PageBuilderAgenticAuthoringConversationMessage, PageBuilderAgenticAuthoringGateResult, PageBuilderAgenticAuthoringIntentResolutionRequest, PageBuilderAgenticAuthoringIntentResolutionResult, PageBuilderAgenticAuthoringOptions, PageBuilderAgenticAuthoringPendingClarification, PageBuilderAgenticAuthoringPromptRequest, PageBuilderAgenticAuthoringProvider, PageBuilderAgenticAuthoringQuickReply, PageBuilderAgenticAuthoringResourceCandidatesRequest, PageBuilderAgenticAuthoringResourceCandidatesResult, PageBuilderAgenticAuthoringSharedRuleHandoff, PageBuilderAgenticAuthoringTarget, PageBuilderAgenticAuthoringTurnStreamConnectionError, PageBuilderAgenticAuthoringTurnStreamEvent, PageBuilderAgenticAuthoringTurnStreamRequest, PageBuilderAgenticAuthoringTurnStreamStartResponse, PageBuilderApplyRequest, PageBuilderApplyResult, PageBuilderCompiledFormPatch, PageBuilderMinimalFormPlanResult, PageBuilderPreviewDiagnostics, PageBuilderPreviewResult, PageBuilderProjectKnowledgeAudit, UiCompositionPlan, UiCompositionPlanAuthoringInput, UiCompositionPlanBinding, UiCompositionPlanCompileResult, UiCompositionPlanComponentPortEndpoint, UiCompositionPlanContextScope, UiCompositionPlanContextScopeTarget, UiCompositionPlanContextValue, UiCompositionPlanDiagnostic, UiCompositionPlanEndpoint, UiCompositionPlanGlobalActionEndpoint, UiCompositionPlanInputSource, UiCompositionPlanSelectionSync, UiCompositionPlanSelectionSyncMapping, UiCompositionPlanSourceEndpoint, UiCompositionPlanStateEndpoint, UiCompositionPlanTargetEndpoint, UiCompositionPlanTemplateMaterialization, UiCompositionPlanTemplateRef, UiCompositionPlanTemplateReference, UiCompositionPlanTemplateResolutionResult, UiCompositionPlanTemplateRevision, UiCompositionPlanTransform, UiCompositionPlanWidget, ValueKind };