@praxisui/settings-panel 9.0.67 → 9.0.68-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -227,7 +227,7 @@ Regras do contrato:
227
227
  - `Apply` emite `applied$` com `getSettingsValue()` e nao fecha o painel.
228
228
  - `Save` usa `onSave()` quando existir, usa `getSettingsValue()` como fallback, emite `saved$` e fecha com motivo `save`.
229
229
  - `Reset` e destrutivo, exige confirmacao, chama `reset()` quando existir e emite `reset$`.
230
- - `Apply` e `Save` continuam bloqueados por `dirty=false`, `valid=false` ou `busy=true`.
230
+ - `Apply` exige rascunho alterado, válido e não ocupado. `Save` exige validade e disponibilidade e aceita tanto um rascunho alterado quanto uma alteração já aplicada nesta abertura. Assim, limpar o rascunho após Aplicar não impede concluir com Salvar. O painel consulta o provider novamente; não repete um payload de expansão guardado.
231
231
  - A validade e a disponibilidade são conferidas novamente depois de produzir o valor,
232
232
  inclusive após resolução de Promise/Observable em `onSave()`. Uma reprovação tardia
233
233
  não emite `applied$`/`saved$`, não marca sucesso e não fecha o rascunho.
@@ -267,6 +267,13 @@ Na pratica:
267
267
  - antes disso, o shell consulta `onBeforeClose`
268
268
  - se `onBeforeClose` retornar `false`, o painel continua aberto e o host nao substitui silenciosamente a sessao atual
269
269
 
270
+ A mensagem de descarte acompanha a sessão: antes de Aplicar, confirma somente o
271
+ descarte das alterações não salvas. Se o painel já emitiu Aplicar e há um novo
272
+ rascunho, explica também que a prévia aplicada permanece. Uma tentativa de
273
+ Aplicar bloqueada pela validação não ativa esse aviso. As duas mensagens usam
274
+ as traduções existentes; a escolha do texto não altera os eventos ou a política
275
+ de fechamento.
276
+
270
277
  ## Exemplo de authoring
271
278
 
272
279
  ```ts
@@ -305,3 +312,139 @@ cd dist/praxis-settings-panel && npm pack
305
312
  ```
306
313
 
307
314
  ## Links
315
+
316
+
317
+ ## Inspecionar o resultado sem fechar o editor
318
+
319
+ `SettingsPanelConfig.previewTarget` recebe uma função que resolve o elemento real da
320
+ prévia. É opcional, transitório e também pode ser encaminhado por `SettingsPanelBridge`.
321
+ O painel oferece **Ver resultado** quando o editor está válido e disponível. A ação
322
+ recolhe o formulário, remove o desfoque somente desse backdrop e destaca o alvo; não
323
+ aplica nem salva. **Voltar às configurações**, Esc ou clique no backdrop retornam ao
324
+ mesmo formulário, mantendo rascunho, aba e largura, e restaurando rolagem e foco.
325
+ A comparação é visual: o backdrop continua protegendo a página contra edição acidental.
326
+ Não substitui um inspetor acoplado à página nem garante caber conteúdo maior que a tela.
327
+
328
+ `SettingsValueProvider.acceptAppliedValue(value)` é opcional. O dono do documento o
329
+ invoca apenas após aceitar a aplicação, para atualizar a referência do rascunho.
330
+ O shell não invoca esse hook apenas porque emitiu `applied$`; isso não prova aceitação
331
+ nem persistência. No editor unificado de widgets, Redefinir descarta a tentativa atual
332
+ para a última versão aplicada. Desfazer último redimensionamento é uma ação separada.
333
+
334
+
335
+ ## Vincular o editor ao ciclo de vida do alvo
336
+
337
+ `SettingsPanelConfig.owner?: DestroyRef` (também disponível no bridge Core) associa
338
+ o painel ao componente que está sendo editado:
339
+
340
+ ```ts
341
+ private readonly destroyRef = inject(DestroyRef);
342
+
343
+ openEditor() {
344
+ return this.settingsPanel.open({
345
+ owner: this.destroyRef,
346
+ content: { component: MyEditorComponent },
347
+ });
348
+ }
349
+ ```
350
+
351
+ Importe `DestroyRef` e `inject` de `@angular/core`. Use o ciclo de vida do alvo real,
352
+ não o de um serviço raiz ou do próprio conteúdo do overlay. A opção é transitória: não
353
+ é encaminhada aos inputs do editor nem persistida.
354
+
355
+ Ao destruir o alvo, o serviço fecha apenas a referência associada com `cancel`, sem
356
+ Save ou confirmação, mesmo com rascunho: o alvo já não existe. Uma abertura pendente
357
+ é cancelada e deixa de observar a confirmação do painel anterior; não o substitui
358
+ se uma resposta chegar depois. Um dono já destruído não abre overlay. O vínculo de
359
+ destruição é removido quando o painel fecha normalmente, protegendo painéis posteriores.
360
+
361
+ `openChild` aceita o mesmo vínculo. Sem `owner`, permanece o gerenciamento existente
362
+ do chamador. Charts adota esse comportamento no editor aberto pelo próprio gráfico;
363
+ esta mudança não migra automaticamente todos os consumidores nem altera autorização.
364
+
365
+
366
+ ### Confirmações de substituição pertencem ao painel de origem
367
+
368
+ Uma abertura que aguarda confirmação só pode substituir o painel que solicitou essa
369
+ confirmação. Se outro painel ou um editor filho estiver ativo quando a resposta chegar,
370
+ a abertura pendente termina com `cancel`; a resposta antiga não autoriza substituir
371
+ o editor atual. Se o painel de origem fechar durante a espera, a abertura pendente
372
+ é cancelada imediatamente e a assinatura da confirmação é liberada.
373
+
374
+ A substituição normal continua passando por `onBeforeClose` e pela confirmação de
375
+ descarte. A proteção vale também para aberturas sem `owner` e não salva rascunhos.
376
+
377
+
378
+ A substituição também revalida o estado depois de fechar o painel anterior: callbacks
379
+ síncronos de `closed$` podem abrir outro editor ou destruir o `owner` solicitante.
380
+ Nesses casos, a abertura anterior termina com `cancel`, sem construir seu conteúdo
381
+ por cima da nova sessão. O controle é interno ao serviço e não integra a configuração
382
+ persistida nem exige mudança nos consumidores.
383
+
384
+
385
+ ### Encerramento de editores aninhados
386
+
387
+ Um painel aberto por `openChild` depende do painel pai, além de seu `owner` opcional.
388
+ Fechar o pai cancela os descendentes com `cancel`, sem emitir Save, inclusive quando
389
+ o fechamento decorre da destruição do alvo. A dependência é removida quando o filho
390
+ fecha normalmente.
391
+
392
+ Ao fechar um nível intermediário, o serviço cancela seus descendentes e devolve a
393
+ interação ao ancestral mais próximo que continua aberto. Referências de pais já
394
+ encerrados não são restauradas. Fechar a raiz encerra toda a árvore. A hierarquia é
395
+ transitória e não altera o documento editado nem a configuração persistida.
396
+
397
+
398
+ ### Retorno de foco ao editor pai
399
+
400
+ Ao suspender um painel para abrir um filho, o Settings Panel preserva o controle
401
+ focado dentro do pai. Ao reativá-lo, devolve foco a esse controle se ele continua
402
+ conectado, visível e habilitado. Caso contrário, usa o primeiro alvo de foco válido
403
+ do próprio painel. A restauração não usa temporizadores nem reposiciona o scroll
404
+ quando o controle de origem continua disponível.
405
+
406
+ A captura automática do CDK ocorre na abertura; reativar o pai não reinicia essa
407
+ captura nem substitui a origem pelo controle de redimensionamento. A mesma regra
408
+ vale para o ancestral vivo restaurado após encerramento de um nível intermediário.
409
+
410
+
411
+ ### Inputs preparados após a mediação
412
+
413
+ `content.inputs` aceita um objeto ou uma função síncrona `() => Record<string, any>`.
414
+ Use a função quando preparar os inputs alterar estado transitório do editor anterior.
415
+ Ela é executada uma única vez, depois da aprovação de `requestClose` e antes de criar
416
+ o conteúdo; veto, cancelamento pendente e owner expirado não a executam. A bridge do
417
+ Core preserva a função para que o serviço controle esse momento. A função deve somente
418
+ preparar os inputs, sem iniciar navegação ou abrir outros painéis. Ela não é serializada
419
+ nem exposta como operação de IA. Objetos existentes continuam sendo aceitos.
420
+
421
+ Substituir um editor filho preserva seu escopo e sua relação com o pai. Fechar o novo
422
+ filho reativa o pai; a substituição não autoriza descartar o rascunho do pai. Respostas
423
+ assíncronas do backdrop só fecham o painel se ele ainda for o atual; fechar o painel
424
+ cancela a assinatura pendente.
425
+
426
+
427
+ ### Escape com editores aninhados
428
+
429
+ A suspensão do pai é sinalizada tanto no diálogo interno quanto no host do componente,
430
+ por `aria-hidden` e `inert`. Essa atualização ocorre sincronamente na troca de interação:
431
+ a arbitragem de overlays consulta o host do portal e não deve considerar o pai suspenso
432
+ como um overlay ativo que consome o Escape do filho. Ao reativar o pai, os atributos
433
+ são removidos antes do retorno de foco. O filho continua passando pela confirmação
434
+ de descarte; essa sinalização não autoriza fechar rascunhos sem mediação.
435
+
436
+ O painel mantém sua participação na arbitragem de teclado do CDK mesmo quando o
437
+ conteúdo medeia Escape. Um menu anterior ainda em animação de saída não pode receber
438
+ o atalho destinado ao editor. Somente overlays ativos acima do painel têm prioridade;
439
+ menus internos continuam consumindo o primeiro Escape antes do fechamento do editor.
440
+
441
+
442
+
443
+ ### Navegação em painéis estreitos
444
+
445
+ A adaptação de authoring considera a largura do contêiner, inclusive quando o
446
+ painel é estreito em uma janela desktop. Table e Dynamic Form exibem “Seção do
447
+ editor” até 768px de largura disponível, mantendo a mesma seleção e os conteúdos
448
+ das abas. Acima desse limite, reaparece a navegação por abas. O Settings Panel
449
+ organiza título, expandir e fechar em uma grade até 599px; a prévia, quando
450
+ suportada, ocupa a linha seguinte. Nenhum documento ou protocolo de Save é alterado.
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": "1.0.0",
3
- "generatedAt": "2026-09-07T00:54:55.301Z",
3
+ "generatedAt": "2026-09-09T10:03:24.330Z",
4
4
  "packageName": "@praxisui/settings-panel",
5
- "packageVersion": "9.0.67",
5
+ "packageVersion": "9.0.68-rc.0",
6
6
  "sourceRegistry": "praxis-component-registry-ingestion",
7
7
  "sourceRegistryVersion": "1.0.0",
8
8
  "componentCount": 1,
@@ -660,7 +660,7 @@
660
660
  "save-result-undefined",
661
661
  "provider-save-rejected"
662
662
  ],
663
- "description": "Keeps Save gated by dirty, valid and busy state, prefers onSave when present, falls back to getSettingsValue and closes with reason save."
663
+ "description": "Save requires a dirty draft or changes already applied in the open panel, plus valid and non-busy state. It obtains a fresh value through onSave or getSettingsValue and closes with reason save; it never replays a cached Apply payload."
664
664
  }
665
665
  }
666
666
  ],
@@ -996,7 +996,7 @@
996
996
  "validatorId": "dirty-valid-busy-gates-preserved",
997
997
  "level": "error",
998
998
  "code": "SETTINGS_PANEL_STATE_GATES_PRESERVED",
999
- "description": "Apply and Save remain gated by dirty, valid and busy state."
999
+ "description": "Apply requires dirty, valid and non-busy state. Save also accepts changes already applied in the open panel when the draft is clean; validity and non-busy state remain mandatory."
1000
1000
  },
1001
1001
  {
1002
1002
  "validatorId": "save-prefers-provider-hook",
@@ -1265,9 +1265,9 @@
1265
1265
  {
1266
1266
  "chunkIndex": 5,
1267
1267
  "chunkKind": "authoring_manifest",
1268
- "content": "{\"operationId\":\"panel.applyBehavior.set\",\"schemaVersion\":\"1.0.0\",\"manifestVersion\":\"1.0.0\",\"componentId\":\"praxis-settings-panel\",\"ownerPackage\":\"@praxisui/settings-panel\",\"configSchemaId\":\"SettingsPanelConfig\",\"chunkSection\":\"operation_card\",\"semanticSummary\":\"Set apply behavior Effects: compile-domain-patch. Apply the editor change without saving or closing.\",\"scope\":\"interaction\",\"target\":{\"kind\":\"applyBehavior\",\"resolver\":\"settings-value-provider-apply-contract\",\"required\":false},\"inputContract\":{\"required\":[],\"properties\":[\"requireDirty\",\"requireValid\",\"blockWhileBusy\",\"useProviderHook\",\"closeAfterSave\"],\"semanticTerms\":[\"requireDirty\",\"requireValid\",\"blockWhileBusy\",\"useProviderHook\",\"closeAfterSave\"]},\"effects\":[\"compile-domain-patch\"],\"affectedPaths\":[\"provider.isDirty$\",\"provider.isValid$\",\"provider.isBusy$\",\"ref.applied$\"],\"validators\":[{\"validatorId\":\"apply-requires-provider-value\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_APPLY_REQUIRES_PROVIDER_VALUE\",\"description\":\"Apply must obtain payloads from SettingsValueProvider.getSettingsValue().\"},{\"validatorId\":\"dirty-valid-busy-gates-preserved\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_STATE_GATES_PRESERVED\",\"description\":\"Apply and Save remain gated by dirty, valid and busy state.\"},{\"validatorId\":\"apply-does-not-close-panel\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_APPLY_DOES_NOT_CLOSE\",\"description\":\"Apply emits preview payloads without closing the panel.\"},{\"validatorId\":\"settings-panel-round-trip\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_ROUND_TRIP\",\"description\":\"Open, edit, apply, save, reset and reopen must preserve the shell protocol without mutating consumer config semantics.\"}],\"preconditions\":[\"settings-value-provider-attached\"],\"submissionImpact\":\"none\",\"presentationAffordances\":[],\"positiveExamples\":[{\"id\":\"apply-preview\",\"request\":\"Apply the editor change without saving or closing.\",\"operationId\":\"panel.applyBehavior.set\",\"params\":{\"requireDirty\":true,\"requireValid\":true,\"blockWhileBusy\":true},\"isPositive\":true}],\"negativeExamples\":[]}",
1268
+ "content": "{\"operationId\":\"panel.applyBehavior.set\",\"schemaVersion\":\"1.0.0\",\"manifestVersion\":\"1.0.0\",\"componentId\":\"praxis-settings-panel\",\"ownerPackage\":\"@praxisui/settings-panel\",\"configSchemaId\":\"SettingsPanelConfig\",\"chunkSection\":\"operation_card\",\"semanticSummary\":\"Set apply behavior Effects: compile-domain-patch. Apply the editor change without saving or closing.\",\"scope\":\"interaction\",\"target\":{\"kind\":\"applyBehavior\",\"resolver\":\"settings-value-provider-apply-contract\",\"required\":false},\"inputContract\":{\"required\":[],\"properties\":[\"requireDirty\",\"requireValid\",\"blockWhileBusy\",\"useProviderHook\",\"closeAfterSave\"],\"semanticTerms\":[\"requireDirty\",\"requireValid\",\"blockWhileBusy\",\"useProviderHook\",\"closeAfterSave\"]},\"effects\":[\"compile-domain-patch\"],\"affectedPaths\":[\"provider.isDirty$\",\"provider.isValid$\",\"provider.isBusy$\",\"ref.applied$\"],\"validators\":[{\"validatorId\":\"apply-requires-provider-value\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_APPLY_REQUIRES_PROVIDER_VALUE\",\"description\":\"Apply must obtain payloads from SettingsValueProvider.getSettingsValue().\"},{\"validatorId\":\"dirty-valid-busy-gates-preserved\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_STATE_GATES_PRESERVED\",\"description\":\"Apply requires dirty, valid and non-busy state. Save also accepts changes already applied in the open panel when the draft is clean; validity and non-busy state remain mandatory.\"},{\"validatorId\":\"apply-does-not-close-panel\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_APPLY_DOES_NOT_CLOSE\",\"description\":\"Apply emits preview payloads without closing the panel.\"},{\"validatorId\":\"settings-panel-round-trip\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_ROUND_TRIP\",\"description\":\"Open, edit, apply, save, reset and reopen must preserve the shell protocol without mutating consumer config semantics.\"}],\"preconditions\":[\"settings-value-provider-attached\"],\"submissionImpact\":\"none\",\"presentationAffordances\":[],\"positiveExamples\":[{\"id\":\"apply-preview\",\"request\":\"Apply the editor change without saving or closing.\",\"operationId\":\"panel.applyBehavior.set\",\"params\":{\"requireDirty\":true,\"requireValid\":true,\"blockWhileBusy\":true},\"isPositive\":true}],\"negativeExamples\":[]}",
1269
1269
  "sourcePointer": "projects/praxis-settings-panel/src/lib/ai/praxis-settings-panel-authoring-manifest.ts",
1270
- "contentHash": "85cb6bfebc2f996189efa526f433cb53a93d047bc83e7d4b7f6b21f948fae9ea",
1270
+ "contentHash": "ff1cebcd9f43d23a6e1b0d5556c08b931952fecdb9cfb581c9599c023797b435",
1271
1271
  "sourceKind": "component_definition",
1272
1272
  "sourceId": "praxis-settings-panel",
1273
1273
  "corpusVersion": "1.0.0"
@@ -1275,9 +1275,9 @@
1275
1275
  {
1276
1276
  "chunkIndex": 6,
1277
1277
  "chunkKind": "authoring_manifest",
1278
- "content": "{\"operationId\":\"panel.saveBehavior.set\",\"schemaVersion\":\"1.0.0\",\"manifestVersion\":\"1.0.0\",\"componentId\":\"praxis-settings-panel\",\"ownerPackage\":\"@praxisui/settings-panel\",\"configSchemaId\":\"SettingsPanelConfig\",\"chunkSection\":\"operation_card\",\"semanticSummary\":\"Set save behavior Effects: compile-domain-patch. Save this editor value and close the panel.\",\"scope\":\"interaction\",\"target\":{\"kind\":\"saveBehavior\",\"resolver\":\"settings-value-provider-save-contract\",\"required\":false},\"inputContract\":{\"required\":[],\"properties\":[\"requireDirty\",\"requireValid\",\"blockWhileBusy\",\"useProviderHook\",\"closeAfterSave\"],\"semanticTerms\":[\"requireDirty\",\"requireValid\",\"blockWhileBusy\",\"useProviderHook\",\"closeAfterSave\"]},\"effects\":[\"compile-domain-patch\"],\"affectedPaths\":[\"provider.onSave\",\"provider.getSettingsValue\",\"ref.saved$\",\"ref.closed$\"],\"validators\":[{\"validatorId\":\"save-prefers-provider-hook\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_SAVE_PREFERS_PROVIDER_HOOK\",\"description\":\"Save must call onSave when provided before falling back to getSettingsValue().\"},{\"validatorId\":\"save-fallback-value-preserved\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_SAVE_FALLBACK_PRESERVED\",\"description\":\"Save fallback must preserve getSettingsValue payload semantics.\"},{\"validatorId\":\"save-closes-with-save-reason\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_SAVE_CLOSE_REASON\",\"description\":\"Successful save must emit saved$ and close with reason save.\"},{\"validatorId\":\"dirty-valid-busy-gates-preserved\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_STATE_GATES_PRESERVED\",\"description\":\"Apply and Save remain gated by dirty, valid and busy state.\"}],\"preconditions\":[\"settings-value-provider-attached\"],\"submissionImpact\":\"config-only\",\"presentationAffordances\":[],\"positiveExamples\":[{\"id\":\"save-and-close\",\"request\":\"Save this editor value and close the panel.\",\"operationId\":\"panel.saveBehavior.set\",\"params\":{\"requireDirty\":true,\"requireValid\":true,\"blockWhileBusy\":true,\"useProviderHook\":true,\"closeAfterSave\":true},\"isPositive\":true}],\"negativeExamples\":[]}",
1278
+ "content": "{\"operationId\":\"panel.saveBehavior.set\",\"schemaVersion\":\"1.0.0\",\"manifestVersion\":\"1.0.0\",\"componentId\":\"praxis-settings-panel\",\"ownerPackage\":\"@praxisui/settings-panel\",\"configSchemaId\":\"SettingsPanelConfig\",\"chunkSection\":\"operation_card\",\"semanticSummary\":\"Set save behavior Effects: compile-domain-patch. Save this editor value and close the panel.\",\"scope\":\"interaction\",\"target\":{\"kind\":\"saveBehavior\",\"resolver\":\"settings-value-provider-save-contract\",\"required\":false},\"inputContract\":{\"required\":[],\"properties\":[\"requireDirty\",\"requireValid\",\"blockWhileBusy\",\"useProviderHook\",\"closeAfterSave\"],\"semanticTerms\":[\"requireDirty\",\"requireValid\",\"blockWhileBusy\",\"useProviderHook\",\"closeAfterSave\"]},\"effects\":[\"compile-domain-patch\"],\"affectedPaths\":[\"provider.onSave\",\"provider.getSettingsValue\",\"ref.saved$\",\"ref.closed$\"],\"validators\":[{\"validatorId\":\"save-prefers-provider-hook\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_SAVE_PREFERS_PROVIDER_HOOK\",\"description\":\"Save must call onSave when provided before falling back to getSettingsValue().\"},{\"validatorId\":\"save-fallback-value-preserved\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_SAVE_FALLBACK_PRESERVED\",\"description\":\"Save fallback must preserve getSettingsValue payload semantics.\"},{\"validatorId\":\"save-closes-with-save-reason\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_SAVE_CLOSE_REASON\",\"description\":\"Successful save must emit saved$ and close with reason save.\"},{\"validatorId\":\"dirty-valid-busy-gates-preserved\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_STATE_GATES_PRESERVED\",\"description\":\"Apply requires dirty, valid and non-busy state. Save also accepts changes already applied in the open panel when the draft is clean; validity and non-busy state remain mandatory.\"}],\"preconditions\":[\"settings-value-provider-attached\"],\"submissionImpact\":\"config-only\",\"presentationAffordances\":[],\"positiveExamples\":[{\"id\":\"save-and-close\",\"request\":\"Save this editor value and close the panel.\",\"operationId\":\"panel.saveBehavior.set\",\"params\":{\"requireDirty\":true,\"requireValid\":true,\"blockWhileBusy\":true,\"useProviderHook\":true,\"closeAfterSave\":true},\"isPositive\":true}],\"negativeExamples\":[]}",
1279
1279
  "sourcePointer": "projects/praxis-settings-panel/src/lib/ai/praxis-settings-panel-authoring-manifest.ts",
1280
- "contentHash": "2f27aa3b25dcf4709e5000cb26ee7c77ea0f1319ee101e7bf7c60485ba1f916a",
1280
+ "contentHash": "af12cde9658310e8357ea8b93a7a59109f620a985f32898c17949f9d918b8799",
1281
1281
  "sourceKind": "component_definition",
1282
1282
  "sourceId": "praxis-settings-panel",
1283
1283
  "corpusVersion": "1.0.0"
@@ -1345,9 +1345,9 @@
1345
1345
  {
1346
1346
  "chunkIndex": 13,
1347
1347
  "chunkKind": "authoring_manifest",
1348
- "content": "{\"schemaVersion\":\"1.0.0\",\"manifestVersion\":\"1.0.0\",\"componentId\":\"praxis-settings-panel\",\"ownerPackage\":\"@praxisui/settings-panel\",\"configSchemaId\":\"SettingsPanelConfig\",\"chunkSection\":\"operations\",\"operations\":[{\"operationId\":\"panel.shell.configure\",\"title\":\"Configure panel shell identity\",\"scope\":\"global\",\"targetKind\":\"panelShell\",\"target\":{\"kind\":\"panelShell\",\"resolver\":\"settings-panel-config-root\",\"ambiguityPolicy\":\"fail\",\"required\":true},\"inputSchema\":{\"type\":\"object\",\"minProperties\":1,\"properties\":{\"id\":{\"type\":\"string\"},\"title\":{\"type\":\"string\"},\"titleIcon\":{\"type\":\"string\"}}},\"effects\":[{\"kind\":\"merge-object\",\"path\":\"config\"}],\"validators\":[\"panel-id-stable\",\"title-i18n-compatible\",\"settings-panel-round-trip\"],\"affectedPaths\":[\"config.id\",\"config.title\",\"config.titleIcon\"],\"submissionImpact\":\"config-only\",\"destructive\":false,\"requiresConfirmation\":false,\"preconditions\":[\"config-initialized\"]},{\"operationId\":\"panel.openMode.set\",\"title\":\"Set panel open mode\",\"scope\":\"global\",\"targetKind\":\"openMode\",\"target\":{\"kind\":\"openMode\",\"resolver\":\"settings-panel-open-mode\",\"ambiguityPolicy\":\"fail\",\"required\":false},\"inputSchema\":{\"type\":\"object\",\"minProperties\":1,\"properties\":{\"expanded\":{\"type\":\"boolean\"},\"replacementPolicy\":{\"enum\":[\"consult-current-editor\",\"reject-when-dirty\",\"force-close-disallowed\"]}}},\"effects\":[{\"kind\":\"merge-object\",\"path\":\"config\"}],\"validators\":[\"replacement-mediates-before-close\",\"settings-panel-round-trip\"],\"affectedPaths\":[\"config.expanded\"],\"submissionImpact\":\"config-only\",\"destructive\":false,\"requiresConfirmation\":false,\"preconditions\":[\"config-initialized\"]},{\"operationId\":\"panel.size.set\",\"title\":\"Set panel size and resize policy\",\"scope\":\"layout\",\"targetKind\":\"panelSize\",\"target\":{\"kind\":\"panelSize\",\"resolver\":\"settings-panel-size-and-resize\",\"ambiguityPolicy\":\"fail\",\"required\":false},\"inputSchema\":{\"type\":\"object\",\"minProperties\":1,\"properties\":{\"width\":{\"oneOf\":[{\"type\":\"string\"},{\"type\":\"number\"}]},\"minWidth\":{\"type\":\"string\"},\"maxWidth\":{\"type\":\"string\"},\"resizable\":{\"type\":\"boolean\"},\"persistSizeKey\":{\"type\":\"string\"},\"expanded\":{\"type\":\"boolean\"}}},\"effects\":[{\"kind\":\"compile-domain-patch\",\"handler\":\"settings-panel-size-set\",\"handlerContract\":{\"reads\":[\"SettingsPanelConfig\",\"SettingsPanelRef.sizeChanged$\",\"persistSizeKey\"],\"writes\":[\"config.minWidth\",\"config.maxWidth\",\"config.resizable\",\"config.persistSizeKey\",\"runtime.size\"],\"identityKeys\":[\"config.id\",\"persistSizeKey\"],\"inputSchema\":{\"type\":\"object\",\"minProperties\":1,\"properties\":{\"width\":{\"oneOf\":[{\"type\":\"string\"},{\"type\":\"number\"}]},\"minWidth\":{\"type\":\"string\"},\"maxWidth\":{\"type\":\"string\"},\"resizable\":{\"type\":\"boolean\"},\"persistSizeKey\":{\"type\":\"string\"},\"expanded\":{\"type\":\"boolean\"}}},\"failureModes\":[\"invalid-css-size\",\"min-width-greater-than-max-width\",\"persist-size-key-missing-for-persistence\"],\"description\":\"Applies shell size configuration and open-panel width changes through SettingsPanelRef.updateSize without changing hosted editor config semantics.\"}}],\"validators\":[\"panel-size-safe\",\"panel-min-max-consistent\",\"resize-persistence-explicit\",\"settings-panel-round-trip\"],\"affectedPaths\":[\"config.minWidth\",\"config.maxWidth\",\"config.resizable\",\"config.persistSizeKey\",\"runtime.width\"],\"submissionImpact\":\"visual-only\",\"destructive\":false,\"requiresConfirmation\":false,\"preconditions\":[\"config-initialized\"]},{\"operationId\":\"panel.applyBehavior.set\",\"title\":\"Set apply behavior\",\"scope\":\"interaction\",\"targetKind\":\"applyBehavior\",\"target\":{\"kind\":\"applyBehavior\",\"resolver\":\"settings-value-provider-apply-contract\",\"ambiguityPolicy\":\"fail\",\"required\":false},\"inputSchema\":{\"type\":\"object\",\"minProperties\":1,\"properties\":{\"requireDirty\":{\"type\":\"boolean\"},\"requireValid\":{\"type\":\"boolean\"},\"blockWhileBusy\":{\"type\":\"boolean\"},\"useProviderHook\":{\"type\":\"boolean\"},\"closeAfterSave\":{\"type\":\"boolean\"}}},\"effects\":[{\"kind\":\"compile-domain-patch\",\"handler\":\"settings-panel-apply-behavior-set\",\"handlerContract\":{\"reads\":[\"SettingsValueProvider.isDirty$\",\"SettingsValueProvider.isValid$\",\"SettingsValueProvider.isBusy$\",\"SettingsValueProvider.getSettingsValue\"],\"writes\":[\"SettingsPanelRef.applied$\"],\"identityKeys\":[\"config.id\",\"provider.getSettingsValue\"],\"inputSchema\":{\"type\":\"object\",\"minProperties\":1,\"properties\":{\"requireDirty\":{\"type\":\"boolean\"},\"requireValid\":{\"type\":\"boolean\"},\"blockWhileBusy\":{\"type\":\"boolean\"},\"useProviderHook\":{\"type\":\"boolean\"},\"closeAfterSave\":{\"type\":\"boolean\"}}},\"failureModes\":[\"provider-missing-get-settings-value\",\"apply-while-invalid\",\"apply-while-busy\",\"apply-without-dirty-state\"],\"description\":\"Keeps Apply gated by dirty, valid and busy state and emits the provider value through SettingsPanelRef.applied$.\"}}],\"validators\":[\"apply-requires-provider-value\",\"dirty-valid-busy-gates-preserved\",\"apply-does-not-close-panel\",\"settings-panel-round-trip\"],\"affectedPaths\":[\"provider.isDirty$\",\"provider.isValid$\",\"provider.isBusy$\",\"ref.applied$\"],\"submissionImpact\":\"none\",\"destructive\":false,\"requiresConfirmation\":false,\"preconditions\":[\"settings-value-provider-attached\"]},{\"operationId\":\"panel.saveBehavior.set\",\"title\":\"Set save behavior\",\"scope\":\"interaction\",\"targetKind\":\"saveBehavior\",\"target\":{\"kind\":\"saveBehavior\",\"resolver\":\"settings-value-provider-save-contract\",\"ambiguityPolicy\":\"fail\",\"required\":false},\"inputSchema\":{\"type\":\"object\",\"minProperties\":1,\"properties\":{\"requireDirty\":{\"type\":\"boolean\"},\"requireValid\":{\"type\":\"boolean\"},\"blockWhileBusy\":{\"type\":\"boolean\"},\"useProviderHook\":{\"type\":\"boolean\"},\"closeAfterSave\":{\"type\":\"boolean\"}}},\"effects\":[{\"kind\":\"compile-domain-patch\",\"handler\":\"settings-panel-save-behavior-set\",\"handlerContract\":{\"reads\":[\"SettingsValueProvider.onSave\",\"SettingsValueProvider.getSettingsValue\",\"SettingsValueProvider.isDirty$\",\"SettingsValueProvider.isValid$\",\"SettingsValueProvider.isBusy$\"],\"writes\":[\"SettingsPanelRef.saved$\",\"SettingsPanelRef.closed$\"],\"identityKeys\":[\"config.id\",\"provider.onSave\"],\"inputSchema\":{\"type\":\"object\",\"minProperties\":1,\"properties\":{\"requireDirty\":{\"type\":\"boolean\"},\"requireValid\":{\"type\":\"boolean\"},\"blockWhileBusy\":{\"type\":\"boolean\"},\"useProviderHook\":{\"type\":\"boolean\"},\"closeAfterSave\":{\"type\":\"boolean\"}}},\"failureModes\":[\"save-while-invalid\",\"save-while-busy\",\"save-result-undefined\",\"provider-save-rejected\"],\"description\":\"Keeps Save gated by dirty, valid and busy state, prefers onSave when present, falls back to getSettingsValue and closes with reason save.\"}}],\"validators\":[\"save-prefers-provider-hook\",\"save-fallback-value-preserved\",\"save-closes-with-save-reason\",\"dirty-valid-busy-gates-preserved\"],\"affectedPaths\":[\"provider.onSave\",\"provider.getSettingsValue\",\"ref.saved$\",\"ref.closed$\"],\"submissionImpact\":\"config-only\",\"destructive\":false,\"requiresConfirmation\":false,\"preconditions\":[\"settings-value-provider-attached\"]}]}",
1348
+ "content": "{\"schemaVersion\":\"1.0.0\",\"manifestVersion\":\"1.0.0\",\"componentId\":\"praxis-settings-panel\",\"ownerPackage\":\"@praxisui/settings-panel\",\"configSchemaId\":\"SettingsPanelConfig\",\"chunkSection\":\"operations\",\"operations\":[{\"operationId\":\"panel.shell.configure\",\"title\":\"Configure panel shell identity\",\"scope\":\"global\",\"targetKind\":\"panelShell\",\"target\":{\"kind\":\"panelShell\",\"resolver\":\"settings-panel-config-root\",\"ambiguityPolicy\":\"fail\",\"required\":true},\"inputSchema\":{\"type\":\"object\",\"minProperties\":1,\"properties\":{\"id\":{\"type\":\"string\"},\"title\":{\"type\":\"string\"},\"titleIcon\":{\"type\":\"string\"}}},\"effects\":[{\"kind\":\"merge-object\",\"path\":\"config\"}],\"validators\":[\"panel-id-stable\",\"title-i18n-compatible\",\"settings-panel-round-trip\"],\"affectedPaths\":[\"config.id\",\"config.title\",\"config.titleIcon\"],\"submissionImpact\":\"config-only\",\"destructive\":false,\"requiresConfirmation\":false,\"preconditions\":[\"config-initialized\"]},{\"operationId\":\"panel.openMode.set\",\"title\":\"Set panel open mode\",\"scope\":\"global\",\"targetKind\":\"openMode\",\"target\":{\"kind\":\"openMode\",\"resolver\":\"settings-panel-open-mode\",\"ambiguityPolicy\":\"fail\",\"required\":false},\"inputSchema\":{\"type\":\"object\",\"minProperties\":1,\"properties\":{\"expanded\":{\"type\":\"boolean\"},\"replacementPolicy\":{\"enum\":[\"consult-current-editor\",\"reject-when-dirty\",\"force-close-disallowed\"]}}},\"effects\":[{\"kind\":\"merge-object\",\"path\":\"config\"}],\"validators\":[\"replacement-mediates-before-close\",\"settings-panel-round-trip\"],\"affectedPaths\":[\"config.expanded\"],\"submissionImpact\":\"config-only\",\"destructive\":false,\"requiresConfirmation\":false,\"preconditions\":[\"config-initialized\"]},{\"operationId\":\"panel.size.set\",\"title\":\"Set panel size and resize policy\",\"scope\":\"layout\",\"targetKind\":\"panelSize\",\"target\":{\"kind\":\"panelSize\",\"resolver\":\"settings-panel-size-and-resize\",\"ambiguityPolicy\":\"fail\",\"required\":false},\"inputSchema\":{\"type\":\"object\",\"minProperties\":1,\"properties\":{\"width\":{\"oneOf\":[{\"type\":\"string\"},{\"type\":\"number\"}]},\"minWidth\":{\"type\":\"string\"},\"maxWidth\":{\"type\":\"string\"},\"resizable\":{\"type\":\"boolean\"},\"persistSizeKey\":{\"type\":\"string\"},\"expanded\":{\"type\":\"boolean\"}}},\"effects\":[{\"kind\":\"compile-domain-patch\",\"handler\":\"settings-panel-size-set\",\"handlerContract\":{\"reads\":[\"SettingsPanelConfig\",\"SettingsPanelRef.sizeChanged$\",\"persistSizeKey\"],\"writes\":[\"config.minWidth\",\"config.maxWidth\",\"config.resizable\",\"config.persistSizeKey\",\"runtime.size\"],\"identityKeys\":[\"config.id\",\"persistSizeKey\"],\"inputSchema\":{\"type\":\"object\",\"minProperties\":1,\"properties\":{\"width\":{\"oneOf\":[{\"type\":\"string\"},{\"type\":\"number\"}]},\"minWidth\":{\"type\":\"string\"},\"maxWidth\":{\"type\":\"string\"},\"resizable\":{\"type\":\"boolean\"},\"persistSizeKey\":{\"type\":\"string\"},\"expanded\":{\"type\":\"boolean\"}}},\"failureModes\":[\"invalid-css-size\",\"min-width-greater-than-max-width\",\"persist-size-key-missing-for-persistence\"],\"description\":\"Applies shell size configuration and open-panel width changes through SettingsPanelRef.updateSize without changing hosted editor config semantics.\"}}],\"validators\":[\"panel-size-safe\",\"panel-min-max-consistent\",\"resize-persistence-explicit\",\"settings-panel-round-trip\"],\"affectedPaths\":[\"config.minWidth\",\"config.maxWidth\",\"config.resizable\",\"config.persistSizeKey\",\"runtime.width\"],\"submissionImpact\":\"visual-only\",\"destructive\":false,\"requiresConfirmation\":false,\"preconditions\":[\"config-initialized\"]},{\"operationId\":\"panel.applyBehavior.set\",\"title\":\"Set apply behavior\",\"scope\":\"interaction\",\"targetKind\":\"applyBehavior\",\"target\":{\"kind\":\"applyBehavior\",\"resolver\":\"settings-value-provider-apply-contract\",\"ambiguityPolicy\":\"fail\",\"required\":false},\"inputSchema\":{\"type\":\"object\",\"minProperties\":1,\"properties\":{\"requireDirty\":{\"type\":\"boolean\"},\"requireValid\":{\"type\":\"boolean\"},\"blockWhileBusy\":{\"type\":\"boolean\"},\"useProviderHook\":{\"type\":\"boolean\"},\"closeAfterSave\":{\"type\":\"boolean\"}}},\"effects\":[{\"kind\":\"compile-domain-patch\",\"handler\":\"settings-panel-apply-behavior-set\",\"handlerContract\":{\"reads\":[\"SettingsValueProvider.isDirty$\",\"SettingsValueProvider.isValid$\",\"SettingsValueProvider.isBusy$\",\"SettingsValueProvider.getSettingsValue\"],\"writes\":[\"SettingsPanelRef.applied$\"],\"identityKeys\":[\"config.id\",\"provider.getSettingsValue\"],\"inputSchema\":{\"type\":\"object\",\"minProperties\":1,\"properties\":{\"requireDirty\":{\"type\":\"boolean\"},\"requireValid\":{\"type\":\"boolean\"},\"blockWhileBusy\":{\"type\":\"boolean\"},\"useProviderHook\":{\"type\":\"boolean\"},\"closeAfterSave\":{\"type\":\"boolean\"}}},\"failureModes\":[\"provider-missing-get-settings-value\",\"apply-while-invalid\",\"apply-while-busy\",\"apply-without-dirty-state\"],\"description\":\"Keeps Apply gated by dirty, valid and busy state and emits the provider value through SettingsPanelRef.applied$.\"}}],\"validators\":[\"apply-requires-provider-value\",\"dirty-valid-busy-gates-preserved\",\"apply-does-not-close-panel\",\"settings-panel-round-trip\"],\"affectedPaths\":[\"provider.isDirty$\",\"provider.isValid$\",\"provider.isBusy$\",\"ref.applied$\"],\"submissionImpact\":\"none\",\"destructive\":false,\"requiresConfirmation\":false,\"preconditions\":[\"settings-value-provider-attached\"]},{\"operationId\":\"panel.saveBehavior.set\",\"title\":\"Set save behavior\",\"scope\":\"interaction\",\"targetKind\":\"saveBehavior\",\"target\":{\"kind\":\"saveBehavior\",\"resolver\":\"settings-value-provider-save-contract\",\"ambiguityPolicy\":\"fail\",\"required\":false},\"inputSchema\":{\"type\":\"object\",\"minProperties\":1,\"properties\":{\"requireDirty\":{\"type\":\"boolean\"},\"requireValid\":{\"type\":\"boolean\"},\"blockWhileBusy\":{\"type\":\"boolean\"},\"useProviderHook\":{\"type\":\"boolean\"},\"closeAfterSave\":{\"type\":\"boolean\"}}},\"effects\":[{\"kind\":\"compile-domain-patch\",\"handler\":\"settings-panel-save-behavior-set\",\"handlerContract\":{\"reads\":[\"SettingsValueProvider.onSave\",\"SettingsValueProvider.getSettingsValue\",\"SettingsValueProvider.isDirty$\",\"SettingsValueProvider.isValid$\",\"SettingsValueProvider.isBusy$\"],\"writes\":[\"SettingsPanelRef.saved$\",\"SettingsPanelRef.closed$\"],\"identityKeys\":[\"config.id\",\"provider.onSave\"],\"inputSchema\":{\"type\":\"object\",\"minProperties\":1,\"properties\":{\"requireDirty\":{\"type\":\"boolean\"},\"requireValid\":{\"type\":\"boolean\"},\"blockWhileBusy\":{\"type\":\"boolean\"},\"useProviderHook\":{\"type\":\"boolean\"},\"closeAfterSave\":{\"type\":\"boolean\"}}},\"failureModes\":[\"save-while-invalid\",\"save-while-busy\",\"save-result-undefined\",\"provider-save-rejected\"],\"description\":\"Save requires a dirty draft or changes already applied in the open panel, plus valid and non-busy state. It obtains a fresh value through onSave or getSettingsValue and closes with reason save; it never replays a cached Apply payload.\"}}],\"validators\":[\"save-prefers-provider-hook\",\"save-fallback-value-preserved\",\"save-closes-with-save-reason\",\"dirty-valid-busy-gates-preserved\"],\"affectedPaths\":[\"provider.onSave\",\"provider.getSettingsValue\",\"ref.saved$\",\"ref.closed$\"],\"submissionImpact\":\"config-only\",\"destructive\":false,\"requiresConfirmation\":false,\"preconditions\":[\"settings-value-provider-attached\"]}]}",
1349
1349
  "sourcePointer": "projects/praxis-settings-panel/src/lib/ai/praxis-settings-panel-authoring-manifest.ts",
1350
- "contentHash": "b16d2abba10705e7236125187ec34c513cd21e375a06c94464c2cbb689f4a25b",
1350
+ "contentHash": "f03c56a9ee676d8120a4903552d00899ad5b2b59d3fdd755cba2d4aec492969d",
1351
1351
  "sourceKind": "component_definition",
1352
1352
  "sourceId": "praxis-settings-panel",
1353
1353
  "corpusVersion": "1.0.0"
@@ -1365,9 +1365,9 @@
1365
1365
  {
1366
1366
  "chunkIndex": 15,
1367
1367
  "chunkKind": "authoring_manifest",
1368
- "content": "{\"schemaVersion\":\"1.0.0\",\"manifestVersion\":\"1.0.0\",\"componentId\":\"praxis-settings-panel\",\"ownerPackage\":\"@praxisui/settings-panel\",\"configSchemaId\":\"SettingsPanelConfig\",\"chunkSection\":\"validators\",\"validators\":[{\"validatorId\":\"panel-id-stable\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_ID_STABLE\",\"description\":\"Panel id must remain stable for replacement, persistence and diagnostics.\"},{\"validatorId\":\"replacement-mediates-before-close\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_REPLACEMENT_MEDIATES_CLOSE\",\"description\":\"Opening a replacement panel must consult the current editor onBeforeClose before closing.\"},{\"validatorId\":\"child-panel-isolates-parent-interaction\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_CHILD_ISOLATES_PARENT\",\"description\":\"A subordinate authoring panel must preserve the parent draft while making the parent inert and preventing parent keyboard shortcuts until the child closes.\"},{\"validatorId\":\"title-i18n-compatible\",\"level\":\"warning\",\"code\":\"SETTINGS_PANEL_TITLE_I18N_COMPATIBLE\",\"description\":\"Authoring chrome text must remain compatible with the settings panel i18n namespace.\"},{\"validatorId\":\"panel-size-safe\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_SIZE_SAFE\",\"description\":\"Panel sizes must be finite numbers or safe CSS size strings.\"},{\"validatorId\":\"panel-min-max-consistent\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_MIN_MAX_CONSISTENT\",\"description\":\"Minimum width must not exceed maximum width.\"},{\"validatorId\":\"resize-persistence-explicit\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_RESIZE_PERSISTENCE_EXPLICIT\",\"description\":\"Persisted resize must use a stable persistSizeKey or be explicitly transient.\"},{\"validatorId\":\"apply-requires-provider-value\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_APPLY_REQUIRES_PROVIDER_VALUE\",\"description\":\"Apply must obtain payloads from SettingsValueProvider.getSettingsValue().\"},{\"validatorId\":\"apply-does-not-close-panel\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_APPLY_DOES_NOT_CLOSE\",\"description\":\"Apply emits preview payloads without closing the panel.\"},{\"validatorId\":\"dirty-valid-busy-gates-preserved\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_STATE_GATES_PRESERVED\",\"description\":\"Apply and Save remain gated by dirty, valid and busy state.\"},{\"validatorId\":\"save-prefers-provider-hook\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_SAVE_PREFERS_PROVIDER_HOOK\",\"description\":\"Save must call onSave when provided before falling back to getSettingsValue().\"},{\"validatorId\":\"save-fallback-value-preserved\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_SAVE_FALLBACK_PRESERVED\",\"description\":\"Save fallback must preserve getSettingsValue payload semantics.\"},{\"validatorId\":\"save-closes-with-save-reason\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_SAVE_CLOSE_REASON\",\"description\":\"Successful save must emit saved$ and close with reason save.\"},{\"validatorId\":\"reset-requires-confirmation\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_RESET_REQUIRES_CONFIRMATION\",\"description\":\"Reset is destructive and must remain confirmed before provider reset is called.\"},{\"validatorId\":\"reset-calls-provider-reset\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_RESET_CALLS_PROVIDER\",\"description\":\"Reset must call the hosted provider reset hook when present.\"},{\"validatorId\":\"reset-event-emitted\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_RESET_EVENT_EMITTED\",\"description\":\"Reset must emit SettingsPanelRef.reset$ so hosts can coordinate state.\"},{\"validatorId\":\"editor-component-registered\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_EDITOR_REGISTERED\",\"description\":\"Hosted editor component must resolve from governed component metadata or host registration.\"},{\"validatorId\":\"settings-value-provider-contract-present\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_PROVIDER_CONTRACT_PRESENT\",\"description\":\"Hosted authoring editors must implement SettingsValueProvider state and value contract.\"},{\"validatorId\":\"consumer-config-delegated\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_CONSUMER_CONFIG_DELEGATED\",\"description\":\"Consumer-specific config operations must delegate to the owning component manifest.\"},{\"validatorId\":\"editor-inputs-serializable\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_EDITOR_INPUTS_SERIALIZABLE\",\"description\":\"Persisted editor host inputs must be serializable safe values.\"},{\"validatorId\":\"diagnostics-follow-provider-state\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_DIAGNOSTICS_PROVIDER_STATE\",\"description\":\"Diagnostics must reflect provider dirty, valid and busy state.\"},{\"validatorId\":\"diagnostics-i18n-compatible\",\"level\":\"warning\",\"code\":\"SETTINGS_PANEL_DIAGNOSTICS_I18N_COMPATIBLE\",\"description\":\"Diagnostics copy must use the settings panel i18n namespace.\"},{\"validatorId\":\"busy-valid-dirty-visible-when-needed\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_STATE_VISIBLE\",\"description\":\"Busy, invalid and dirty states must remain visible or explain disabled actions.\"},{\"validatorId\":\"settings-panel-round-trip\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_ROUND_TRIP\",\"description\":\"Open, edit, apply, save, reset and reopen must preserve the shell protocol without mutating consumer config semantics.\"}]}",
1368
+ "content": "{\"schemaVersion\":\"1.0.0\",\"manifestVersion\":\"1.0.0\",\"componentId\":\"praxis-settings-panel\",\"ownerPackage\":\"@praxisui/settings-panel\",\"configSchemaId\":\"SettingsPanelConfig\",\"chunkSection\":\"validators\",\"validators\":[{\"validatorId\":\"panel-id-stable\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_ID_STABLE\",\"description\":\"Panel id must remain stable for replacement, persistence and diagnostics.\"},{\"validatorId\":\"replacement-mediates-before-close\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_REPLACEMENT_MEDIATES_CLOSE\",\"description\":\"Opening a replacement panel must consult the current editor onBeforeClose before closing.\"},{\"validatorId\":\"child-panel-isolates-parent-interaction\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_CHILD_ISOLATES_PARENT\",\"description\":\"A subordinate authoring panel must preserve the parent draft while making the parent inert and preventing parent keyboard shortcuts until the child closes.\"},{\"validatorId\":\"title-i18n-compatible\",\"level\":\"warning\",\"code\":\"SETTINGS_PANEL_TITLE_I18N_COMPATIBLE\",\"description\":\"Authoring chrome text must remain compatible with the settings panel i18n namespace.\"},{\"validatorId\":\"panel-size-safe\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_SIZE_SAFE\",\"description\":\"Panel sizes must be finite numbers or safe CSS size strings.\"},{\"validatorId\":\"panel-min-max-consistent\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_MIN_MAX_CONSISTENT\",\"description\":\"Minimum width must not exceed maximum width.\"},{\"validatorId\":\"resize-persistence-explicit\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_RESIZE_PERSISTENCE_EXPLICIT\",\"description\":\"Persisted resize must use a stable persistSizeKey or be explicitly transient.\"},{\"validatorId\":\"apply-requires-provider-value\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_APPLY_REQUIRES_PROVIDER_VALUE\",\"description\":\"Apply must obtain payloads from SettingsValueProvider.getSettingsValue().\"},{\"validatorId\":\"apply-does-not-close-panel\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_APPLY_DOES_NOT_CLOSE\",\"description\":\"Apply emits preview payloads without closing the panel.\"},{\"validatorId\":\"dirty-valid-busy-gates-preserved\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_STATE_GATES_PRESERVED\",\"description\":\"Apply requires dirty, valid and non-busy state. Save also accepts changes already applied in the open panel when the draft is clean; validity and non-busy state remain mandatory.\"},{\"validatorId\":\"save-prefers-provider-hook\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_SAVE_PREFERS_PROVIDER_HOOK\",\"description\":\"Save must call onSave when provided before falling back to getSettingsValue().\"},{\"validatorId\":\"save-fallback-value-preserved\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_SAVE_FALLBACK_PRESERVED\",\"description\":\"Save fallback must preserve getSettingsValue payload semantics.\"},{\"validatorId\":\"save-closes-with-save-reason\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_SAVE_CLOSE_REASON\",\"description\":\"Successful save must emit saved$ and close with reason save.\"},{\"validatorId\":\"reset-requires-confirmation\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_RESET_REQUIRES_CONFIRMATION\",\"description\":\"Reset is destructive and must remain confirmed before provider reset is called.\"},{\"validatorId\":\"reset-calls-provider-reset\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_RESET_CALLS_PROVIDER\",\"description\":\"Reset must call the hosted provider reset hook when present.\"},{\"validatorId\":\"reset-event-emitted\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_RESET_EVENT_EMITTED\",\"description\":\"Reset must emit SettingsPanelRef.reset$ so hosts can coordinate state.\"},{\"validatorId\":\"editor-component-registered\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_EDITOR_REGISTERED\",\"description\":\"Hosted editor component must resolve from governed component metadata or host registration.\"},{\"validatorId\":\"settings-value-provider-contract-present\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_PROVIDER_CONTRACT_PRESENT\",\"description\":\"Hosted authoring editors must implement SettingsValueProvider state and value contract.\"},{\"validatorId\":\"consumer-config-delegated\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_CONSUMER_CONFIG_DELEGATED\",\"description\":\"Consumer-specific config operations must delegate to the owning component manifest.\"},{\"validatorId\":\"editor-inputs-serializable\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_EDITOR_INPUTS_SERIALIZABLE\",\"description\":\"Persisted editor host inputs must be serializable safe values.\"},{\"validatorId\":\"diagnostics-follow-provider-state\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_DIAGNOSTICS_PROVIDER_STATE\",\"description\":\"Diagnostics must reflect provider dirty, valid and busy state.\"},{\"validatorId\":\"diagnostics-i18n-compatible\",\"level\":\"warning\",\"code\":\"SETTINGS_PANEL_DIAGNOSTICS_I18N_COMPATIBLE\",\"description\":\"Diagnostics copy must use the settings panel i18n namespace.\"},{\"validatorId\":\"busy-valid-dirty-visible-when-needed\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_STATE_VISIBLE\",\"description\":\"Busy, invalid and dirty states must remain visible or explain disabled actions.\"},{\"validatorId\":\"settings-panel-round-trip\",\"level\":\"error\",\"code\":\"SETTINGS_PANEL_ROUND_TRIP\",\"description\":\"Open, edit, apply, save, reset and reopen must preserve the shell protocol without mutating consumer config semantics.\"}]}",
1369
1369
  "sourcePointer": "projects/praxis-settings-panel/src/lib/ai/praxis-settings-panel-authoring-manifest.ts",
1370
- "contentHash": "113367420fed3529b93de6f8f978657063d01fb96686feb8ee276c047bd1fe64",
1370
+ "contentHash": "69ea78398d404e7076c8afcb4bae5e72560fde07069d672442072da951e8a78a",
1371
1371
  "sourceKind": "component_definition",
1372
1372
  "sourceId": "praxis-settings-panel",
1373
1373
  "corpusVersion": "1.0.0"