@praxisui/dynamic-form 10.0.0-rc.4 → 10.0.0-rc.41

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.
@@ -0,0 +1,229 @@
1
+ ---
2
+ title: "Custom fields: revisão de adoção corporativa"
3
+ slug: "dynamic-form-custom-fields-enterprise-review"
4
+ description: "Registro de achados, fontes, provas e pendências da adoção de custom fields no Core e Dynamic Form."
5
+ doc_type: "reference"
6
+ document_kind: "governance-reference"
7
+ component: "dynamic-form"
8
+ category: "architecture"
9
+ audience:
10
+ - "frontend"
11
+ - "host"
12
+ - "architect"
13
+ - "platform-team"
14
+ level: "advanced"
15
+ status: "active"
16
+ owner: "praxis-ui"
17
+ last_updated: "2026-10-27"
18
+ toc: true
19
+ sidebar: false
20
+ source_of_truth:
21
+ - "projects/praxis-core/src/lib/services/schema-normalization-kernel.ts"
22
+ - "projects/praxis-core/src/lib/models/form/materialize-custom-fields-layout.ts"
23
+ - "projects/praxis-core/src/lib/services/dynamic-form.service.ts"
24
+ - "projects/praxis-core/src/lib/schema/schema-metadata-client.ts"
25
+ - "projects/praxis-core/src/lib/services/generic-crud.service.ts"
26
+ - "projects/praxis-dynamic-form/src/lib/praxis-dynamic-form.ts"
27
+ - "projects/praxis-dynamic-form/src/lib/utils/prepare-submit-payload.ts"
28
+ - "projects/praxis-dynamic-form/src/lib/services/form-rules.service.ts"
29
+ ---
30
+
31
+ # Custom fields: revisão de adoção corporativa
32
+
33
+ ## Escopo e baseline
34
+
35
+ A [Issue 657](https://github.com/codexrodrigues/praxis-ui-angular/issues/657) e o
36
+ [PR 658](https://github.com/codexrodrigues/praxis-ui-angular/pull/658) materializam
37
+ custom fields no runtime oficial. A revisão atual parte de Angular `48b004c9e` e
38
+ Metadata `368d96266b`. Os PRs 658/304 permanecem sem merge. A revisão da fonte e os gates focais desta rodada estão concluídos, com as
39
+ exceções preexistentes e pendências downstream registradas abaixo. Fonte candidata e provas
40
+ não certificam publicação, deploy, release ou adoção corporativa irrestrita.
41
+
42
+ A revisão anterior partiu de Angular `6598ef221f0708c6628b02380c0e27110fa4a1ae`
43
+ e skills `59c64169fe062de69c83b886c75b681d4e7ee967`; seus achados motivaram esta
44
+ rodada. O backend é dono da definição, autorização e validação. Core projeta,
45
+ reconcilia e transporta; Form/Table materializam controles e payloads. A landing
46
+ publica essa fonte, e não uma semântica alternativa.
47
+
48
+ Classificação: `contrato-publico`, com correções de semântica já suportada e mal
49
+ materializada em Core/Form/Table e alinhamento canônico backend. Consumidores:
50
+ Form schema-driven/salvo, Filter standalone/integrado/avançado, discovery e
51
+ GenericCrud. Derivados: READMEs, JSON API, dois guias Table, vendor docs da landing
52
+ e skills existentes. Não há nova rota pública para este relatório, nem alteração
53
+ de endpoint, corpus HTTP ou recipe pela documentação.
54
+
55
+ ## Achados, tratamento e fontes
56
+
57
+ | Cenário / origem | Correção na fonte candidata | Gate / limite |
58
+ | --- | --- | --- |
59
+ | Container salvo ou local colidente substituía filhos e podia perder a subárvore no payload. | `materialize-custom-fields-layout`, reconciliadores e sync migram pai direto para filhos schema-backed, preservando posições, rich content e locais não colidentes; diagnostics persistem a correção. | Integração normalizer/reconcile/FormGroup/submit nos três caminhos; não transferir omit/defaults/validadores escalares do pai. |
60
+ | Restrições e identidade eram relaxadas por metadata antiga. | Pisos disabled/readOnly/formHidden do container; identidade customField/key/scope e constraints items/enum server-owned. FieldAccess ausente é herdado; policies equivalentes por sets são aceitas, conflito exige policy leaf efetiva do backend. | Conflito de normalização bloqueia inicialização, incluindo configuração salva; listas OR não implementam AND arbitrário. |
61
+ | Cache/deduplicação/replay e getters podiam cruzar tenant, autenticação ou recurso por chamada. | `schema-request-key`, `schema-request-context`, `schema-fetch`, SchemaMetadataClient, GenericCrud e Discovery capturam contexto/headers, isolam representação e deduplicam só trabalho em andamento. GenericCrud só publica derivados do recurso configurado; callbacks obsoletos não publicam. | Snapshot antes de await/subscription e retry304 igual; provider/hook/aliases inválidos falham antes do request. Getters singleton não são mapa de resultados por chamada. |
62
+ | L1, cache status0 ou configuração salva podiam parecer schema autorizado atual. | Novo ciclo HTTP revalida e normaliza; L1 compilado não estabelece readiness. Corpo cacheado só após 304 correspondente; status0/401/403/normalização inválida não recuperam silenciosamente o form. | Sem modo offline. Discovery não usa resumo do catálogo ou schema response para substituir request vazio/negado. Fallback de indisponibilidade conhecido só nas trilhas equivalentes já suportadas. |
63
+ | Remover o último campo gerava defs=[] ignorado; sync/filter conservavam órfãos aplicáveis/required. | Schema vazio bem-sucedido é autoritativo. Reconcile Form/Filter e sync manual marcam órfãos não locais hidden+disabled+omit; reaparecimento usa required/type/items/enum atuais. | Hidden legítimo e `source: local` explícito conservam sua semântica; raw draft pode manter diagnóstico, mas não é payload aplicável. |
64
+ | Request publicava read-only que o backend recusava; nomes admitidos colidiam com controles. | Metadata PR304 exclui read-only de comando properties/required e mantém leitura/filtro apropriados; política de chaves rejeita nomes reservados exatos. | Consumir schema da operação; não mesclar response em comando nem inventar x-ui.submitPolicy local. Definições antigas exigem migração explícita. |
65
+ | Arrays IN/enum perdiam tipo e diferentes fronteiras emitiam valores incompatíveis. | FieldDefinition/Metadata `items: FieldScalarItemsSchema`; parser Core único `normalizeScalarArrayValue`, validators e projeção Form/Table. Modal Apply/Save usa payload do child; merge de shortcut reprojeta omit. | Rejeição inteira de item inválido/null, sem descarte parcial; bloqueio pending/invalid inclui debounce anterior. Zero filtros ativos DISABLED permite limpar. |
66
+ | Regras computed liam alias pontuado antigo. | Contexto JSON Logic aninhado via helper interno; `fieldValues` continua mapa plano de target IDs. | Cadeia em ordem inversa, condições true/false e imutabilidade. Arrays intermediários não são record paths suportados. |
67
+ | Heurística temporal alterava strings e arrays numéricos; rebuild perdia estado aninhado. | Normalização metadata-aware de datas e item schemas, DateInput date-only e snapshot dirty/touched por leaf/FormArray. Campos planos escrevem draft privado, sem clone raiz por campo. | Arrays numéricos/unknown e strings não temporais preservados; não é autosave entre contextos/resets. |
68
+ | Erro de acesso parecia conexão/retry e submit podia usar estado não pronto. | Form distingue acesso, contexto não confirmado, projeção inválida e transporte. Loading/erro/known nonready bloqueiam submit; preview scalar inválido emite formData:null/isValid:false com raw intacto. | 401/403 não oferecem retry genérico. Troca confirmada invalida seed anterior e revalida; não restaura draft de outro tenant. |
69
+
70
+ ## Contratos e limites ainda exigidos do host
71
+
72
+ A fonte backend inspecionada é o candidato PR304, docs em `99b75a2dde`:
73
+ [spec canônica](https://github.com/codexrodrigues/praxis-metadata-starter/blob/99b75a2dde/docs/spec/custom-fields-and-resource-facts.md).
74
+ A política rejeita exatamente `constructor`, `prototype`, `hasOwnProperty`,
75
+ `isPrototypeOf`, `propertyIsEnumerable`, `toLocaleString`, `toString` e `valueOf`,
76
+ com comparação sensível a maiúsculas. `__proto__` já é inválido pelo formato da
77
+ chave. Não corrigir dados antigos com aliases silenciosos de frontend.
78
+
79
+ Read-only/disabled/hidden não significam omissão universal. Na escrita, a projeção
80
+ canônica exclui custom fields read-only; filtros podem mantê-los como operandos de
81
+ busca e respostas como leitura. Campos contextuais legítimos continuam sujeitos
82
+ ao contrato da operação. `rawFormData`/`getRawValue()` são diagnósticos, não uma
83
+ instrução para ignorar o payload projetado.
84
+
85
+ A chave de representação usa URL real, identidade semântica e tenant/locale
86
+ capturados; headers adicionais selecionam um token opaco por sessão/página.
87
+ O lookup de headers é limitado e fica só em memória: credenciais/fingerprints não
88
+ são persistidos em chaves ou metadata. Isso não redige corpos arbitrários do
89
+ servidor. Contexto enterprise confirmado fornece tenant/locale/version; GenericCrud,
90
+ Discovery e Form bloqueiam um snapshot conhecido não pronto. O cliente standalone
91
+ SchemaMetadataClient captura o hook e não descobre o serviço DI por conta própria. Parâmetros explícitos conflitantes falham.
92
+
93
+ Cookies/interceptors que alterem identidade depois do snapshot não são observáveis
94
+ pelo cache. O host precisa materializar a versão confirmada nos headers capturados
95
+ ou invalidar todo o escopo de cache/sessão; recriar somente um cliente sobre o
96
+ mesmo armazenamento não basta. Tenant nunca substitui autorização por principal.
97
+ GenericCrud mantém getters do recurso configurado: overrides por chamada devolvem
98
+ seus resultados, sem transformar esses getters em uma API multiscope.
99
+
100
+ Scalar `items` cobre string/integer/number/boolean e formatos date/date-time
101
+ suportados. Inteiros precisam ser seguros no JavaScript; números finitos seguem
102
+ sintaxe JSON e booleans são exatos. Enum é aplicado depois da conversão. `null`
103
+ container/ausente e `[]` não equivalem a item null; required continua independente.
104
+ Não anunciar arbitrary JSON Schema items, editor object-array, precisão int64 ou
105
+ record paths de regras através de arrays intermediários.
106
+
107
+ ## UX e progresso
108
+
109
+ | Situação | Comportamento / limite comunicável |
110
+ | --- | --- |
111
+ | Schema loading, timeout e transporte | SchemaMetadataClient aplica deadline; leituras supersedidas são canceladas. Falha recuperável oferece retry. Não é modo offline ou promessa de recuperar todo rascunho. |
112
+ | Acesso negado ou contexto não confirmado | Form não monta controles cacheados como prontos nem permite submit; acesso tem feedback próprio sem retry genérico. Recuperação depende de contexto/autorização do host. |
113
+ | Config salva, defs vazias ou projeção inválida | Vazio bem-sucedido reconcilia; erro não mantém configuração antiga pronta. FieldAccess conflitante é erro de metadata, não autorização alternativa de host. |
114
+ | Troca de tenant/registro | Cancela geração antiga, invalida seed anterior e revalida. Não comunica continuidade de dados entre identidades. |
115
+ | Campo removido/reaparecido | Órfão server-backed pode manter metadata/layout/raw diagnóstico, mas fica disabled/omit. Ao voltar usa constraints do schema atual. |
116
+ | Rebuild do filtro | Valores suportados do mesmo contexto podem ser restaurados; default explícito pode resetar. Hidden/local legítimo não é removido por uma política genérica. |
117
+ | Valor scalar inválido | Permanece corrigível no raw/control com feedback; nenhuma emissão aplicável/submit/shortcut ou preview com formData utilizável. |
118
+ | Narrow viewport | Ações/labels devem permanecer acessíveis por scroll sem overflow horizontal. Densidade da toolbar não prova campo acima da dobra ou conformidade de teclado/AXE. |
119
+
120
+ ## Evidências da rodada atual
121
+
122
+ - Core: 471 casos distintos na campanha atual. Quatro falhas de fixture/guard foram
123
+ corrigidas; rerun focal de contexto/discovery 61/61 aprovado. Não somar 471+61.
124
+ - Comandos de build Core e Form com closure de 13 libs aprovados. Core precedeu
125
+ o último guard; a closure final Form recompilou Core/Form/Table e cobre a fonte
126
+ final de produção. Pureza e MatSelect zero-debt também passaram.
127
+ - Form: 406 casos distintos aprovados, com rerun focal das três fixtures
128
+ corrigidas. Deltas posteriores ao build são apenas testes.
129
+ - Browser: seis casos distintos aprovados (quatro Form e dois Table). Os quatro
130
+ Form cobrem editor desktop/resize, abertura narrow inicial, warm-cache seguido
131
+ de403 e formulário público scalar/enum. O último caso passou em rerun após
132
+ corrigir uma corrida do teste ao observar a ação ficar disabled. Table cobre
133
+ toolbar/gerenciador de campos/avançado/modal, sem prova de query IN por browser.
134
+ - Table: **224/224 aprovados** após o alinhamento das quatro fixtures year/month
135
+ ao contrato introduzido em `6de618805`. O runtime e o registry preservam
136
+ inlineYearRange/inlineMonthRange como wrappers numéricos; não são aliases de
137
+ inlinePeriodRange. Os testes agora verificam IDs, modo range, imutabilidade,
138
+ hidratação em controle real e payload numérico no submit. O resultado anterior
139
+ 220/224 é histórico e foi substituído pela execução focal completa aprovada.
140
+ - Dynamic Fields: **10/10 aprovados** nos componentes inline-year-range,
141
+ inline-month-range e inline-period-range. A prova distingue limites numéricos
142
+ de identificadores de períodos, sem alterar a semântica de produção.
143
+ - Quickstart: revisão cruzada confirmou 25 casos distintos sem falha no candidato
144
+ backend e a prova HTTP Neon coordenada no trabalho backend. Três pilotos
145
+ históricos (EventosFolha, MetadataMigration e OpenApiGroupResolution), além do
146
+ verify integral e do pin de artefato público, permanecem pendentes no Draft482;
147
+ não inferir adoção completa a partir do piloto. Fontes brutas e fingerprint estão no registro
148
+ backend `docs/technical/ISSUE-303-EXECUTION.md` e no PR304.
149
+ - Frontmatter incremental dos documentos desta rodada validado. Skills867
150
+ publicado em `d351c44`; landing docs no PR270 em `cfc0212`. Validação canônica
151
+ de skills e gates documentais aprovados. O fechamento documental corrigiu também as
152
+ cinco cópias vendor antigas: List, Metadata Editor, Page Builder, Table API e
153
+ Visual Builder. Os dois guias Dynamic Fields foram alinhados ao contrato de
154
+ ranges; o link prospectivo do Page Builder aponta à fonte GitHub existente.
155
+ Full vendor freshness passou para os 75 documentos, assim como docs25,
156
+ published-guides146 e sitemap. Nenhuma sincronização instalada ou merge.
157
+
158
+ A E2E ampliada `surface-open-form-demo.playwright.spec.ts` cobre o editor,
159
+ abertura narrow inicial, leitura autorizada seguida de403 sem reaproveitar
160
+ campos prontos, e formulário público com items/enum, bloqueio de token inválido e
161
+ submit nested tipado. Esses casos passaram na execução final e usam
162
+ schema/HTTP mockado; não substituem prova backend Neon. Não há prova AXE,
163
+ teclado completo, tema claro, filtro IN por browser ou persistência real pelo E2E.
164
+
165
+ A coordenação inspecionou screenshots desktop e narrow estabilizados: labels e
166
+ quadros acessíveis, sem overflow horizontal; a toolbar estreita continua densa e
167
+ o campo pode exigir scroll. O rerun Playwright pode limpar `test-results`, então
168
+ este registro não publica links para screenshots transitórios. Logs em
169
+ `/tmp/praxis-658-e2e-form-final.log`, `praxis-658-e2e-scalar-rerun.log` e
170
+ `praxis-658-e2e-table-final.log` pertencem à campanha local coordenada.
171
+
172
+ O receipt `/tmp/praxis-658-source-freeze.json` vincula as provas à árvore de
173
+ 44 arquivos fonte/teste alterados contra48b004, fingerprint SHA256
174
+ `f99a2bdde6f3fa9f05cd56025e1d375c24c6bcffa2fef5e541e155d6c2650bda`.
175
+ O lockfile não mudou. O commit Angular final é registrado no PR658 após o freeze
176
+ documental; o fingerprint distingue a fonte validada das edições de relatório.
177
+
178
+ ## Evidência histórica anterior
179
+
180
+ A rodada anterior passou 313 casos Core distintos (311+duas novas em rerun70),
181
+ 324 Form e build closure13. Um E2E mockado passou em1280×720 e após resize390×844,
182
+ com screenshots finais inspecionados pela coordenação: sem overflow, tabs para
183
+ select, ações sticky e campo narrow atingível por scroll, abaixo da dobra. Essa
184
+ execução não cobria abertura narrow inicial nem submit real. Capturas ignoradas
185
+ pelo Git em `test-results/surface-open-form-demo.pla-6e87b-the-employee-drawer-surface-chromium/`.
186
+ Esses resultados não são somados aos gates da árvore atual.
187
+
188
+ ## Publicação e guidance
189
+
190
+ O [PR skills867](https://github.com/codexrodrigues/praxis-codex-skills/pull/867)
191
+ pertence ao incremento Angular Core/Form/Table; o
192
+ [PR skills868](https://github.com/codexrodrigues/praxis-codex-skills/pull/868)
193
+ pertence ao backend e tem escritor próprio. Integração canônica e sincronização
194
+ instalada são estados separados e permanecem pendentes enquanto os PRs não forem
195
+ integrados. O [PR270 da landing](https://github.com/codexrodrigues/praxis-ui-landing-page/pull/270)
196
+ usa o fluxo vendor oficial em worktree isolado. Este registro
197
+ não cria nova rota, manifesto, endpoint, corpus ou assets públicos.
198
+
199
+
200
+ ## Fechamento Table e documentação — 27/10/2026
201
+
202
+ Escopo autorizado: corrigir as quatro falhas preexistentes da Table e as cinco
203
+ cópias documentais divergentes enquanto a campanha financeira Quickstart segue
204
+ em outro chat. Classificação transversal: testes e documentação, sem modificação
205
+ de runtime, API, dependências, rotas ou configuração de build. Inventário
206
+ `ja-suportado-mal-nomeado-ou-mal-materializado`: contrato e implementação já
207
+ concordavam; expectativas e guias ainda ensinavam a conversão antiga.
208
+
209
+ A auditoria das cinco cópias vendor encontrou versões históricas exatas das fontes
210
+ Angular, sem conteúdo exclusivo novo a preservar. A correção usa o sync oficial
211
+ com `PRAXIS_UI_ANGULAR_ROOT` apontando ao worktree revisado. O ajuste dos dois guias
212
+ Dynamic Fields é derivado do mesmo diagnóstico; não cria controles ou DTOs.
213
+
214
+ A revisão independente confrontou o patch dos quatro testes, os wrappers e
215
+ registry, o contrato runtime e o histórico. O coordenador revisou os guias e a
216
+ projeção vendor. Evidências locais: `/tmp/praxis-658-table-alignment.log` (224),
217
+ `/tmp/praxis-658-range-contracts.log` (10) e
218
+ `/tmp/praxis-658-alignment-docs.log`. A bateria Table inclui componente, host e projeção; Dynamic Fields cobre os três
219
+ componentes de range, com `tools/karma/karma.headless.conf.cjs`. Não foi repetido build
220
+ ou E2E porque este incremento altera somente specs/documentação. Os builds e E2E
221
+ da fonte de produção `f5880172f` continuam válidos.
222
+
223
+ Skills: `atualizar-existente` para `praxis-fields-inline-overlay-runtime`, com a
224
+ distinção de valores numéricos/períodos e provas de promoção; `existente-adequada`
225
+ para publicação na landing, que já determina owner-first, sync oficial e gates
226
+ completos. A atualização canônica segue no PR867; integração e sync instalado
227
+ aguardam a revisão sem merge. Os commits finais deste fechamento estão nos PRs
228
+ 658/270/867. Pilotos financeiros, verify integral e pin público do Quickstart
229
+ continuam sob coordenação exclusiva do outro chat; este incremento não os aprova.
@@ -4,7 +4,7 @@ doc_type: "adr"
4
4
  component: "praxis-dynamic-form"
5
5
  status: "accepted"
6
6
  owner: "praxis-ui"
7
- last_updated: "2026-09-10"
7
+ last_updated: "2026-10-23"
8
8
  ---
9
9
 
10
10
  # Dynamic Form Authoring Document Semantics
@@ -23,6 +23,63 @@ Ao aplicar um documento canônico:
23
23
 
24
24
  Payloads legados ou parciais recebidos por APIs de compatibilidade, como `applyConfigFromAdapter(...)`, permanecem com semântica `merge-compat`: campos não informados devem ser preservados até migração completa para o contrato canônico.
25
25
 
26
+ ## Rule conversion and recovery
27
+
28
+ `config.formRules` owns the canonical rule expression and both effect branches.
29
+ `formRulesState` is derived visual authoring state. Wizard inline JSON Logic must
30
+ survive Apply, Save and reopen unchanged. Conditions outside the visual graph
31
+ vocabulary remain intact inline and are diagnosed as `runtime-only`; a valid
32
+ root-data reference (`var: ''`) is not an invalid field reference.
33
+
34
+ A partial graph must never weaken an AND/OR expression by dropping children.
35
+ Missing rule roots, rules without a serializable target, and missing, cyclic or
36
+ unsupported explicit condition graph nodes block Apply/Save while
37
+ retaining the draft and last accepted configuration. Repairing through the
38
+ properties panel revalidates a supplied replacement. A nonserializable visual
39
+ draft is repaired in the wizard or JSON; the effects panel and accepted-rule diagnostics are withheld until
40
+ conversion succeeds, so it cannot present the last accepted rule as the current
41
+ draft. Deleting the last rule removes both
42
+ `formRules` and `formRulesState`, including after a validation failure.
43
+
44
+ Editor validation that gates Apply/Save uses the injected `PraxisJsonLogicService`
45
+ and the same host operator registry as runtime evaluation. A registered host
46
+ operator can remain runtime-only in the visual builder and must still save and
47
+ reopen. Unknown operators and invalid arity remain blocked.
48
+
49
+ ### Reviewing conditional presentation rules
50
+
51
+ The rule wizard and list describe the condition, target labels, and every effect
52
+ in both branches. Boolean condition choices use Yes/No (Sim/Não). Grouping and
53
+ order remain visible for AND/OR; expressions outside the readable vocabulary
54
+ retain an explicit advanced/JSON review path and their original expression.
55
+
56
+ Indicators have separate scopes: the Visual Builder checks structure; the
57
+ structured effects panel reports whether a property can be edited; form
58
+ analysis validates the condition against the injected runtime registry and
59
+ reports unavailable targets or unsupported properties. A successful sample-data
60
+ preview proves only the selected branch for those data. None of these labels
61
+ replaces target access policies or a governed business decision.
62
+
63
+ Replacing JSON rules, clearing the list, and Reset refresh the same visual draft
64
+ and effects panel. A valid stale `formRulesState` is rebuilt from canonical
65
+ `formRules`; malformed explicit graphs remain repairable and block Apply/Save.
66
+ Removing or emptying `formRules` in a JSON replacement clears residual visual
67
+ state. Input echoes do not freeze subsequent edits or reset builder history.
68
+ Each canonical form rule reopens as one `propertyRule` with its complete target
69
+ list, both effect branches and authoring metadata. The bridge does not recreate
70
+ legacy conditional-validator nodes or duplicate a rule per target.
71
+
72
+ Presentation (`formRules`) and conditional actions (`formCommandRules`) retain
73
+ separate channels and validation policies. Hidden or inaccessible targets are
74
+ reported as unavailable; authoring does not grant access to those fields.
75
+
76
+ Identified standalone forms with host-provided fields use the same persisted
77
+ configuration initializer as schema-backed forms. Local-first restores saved
78
+ rules and field customizations after reload; input-first, volatile configuration
79
+ and transient layout persistence retain their existing policies. Standalone initialization does not
80
+ request a server schema. New host inputs received while storage or hooks are
81
+ pending remain authoritative when the form is built.
82
+
26
83
  ## Filter Form projection
27
84
 
28
85
  `praxis-filter-form` compartilha o mesmo documento canônico, parser e serializer,
@@ -161,7 +218,8 @@ that the resource schema could not be loaded.
161
218
 
162
219
  The wrapper also exposes the existing `configPersistenceStrategy` as **Fonte da configuração**.
163
220
  **Definida nesta página** selects `input-first`; **Preferências salvas** selects `local-first`.
164
- The runtime default remains `local-first`. When the goal is a page-owned layout, select `input-first`
221
+ **Configuração temporária** selects `volatile`, which never reads, saves or clears independent child preferences.
222
+ The runtime default remains `local-first`. For ordinary page layouts, select `input-first`
165
223
  so an older saved form preference does not replace the correctly persisted page sections on reload.
166
224
  Changing only the source preserves the authored page config even if the currently displayed effective
167
225
  layout came from older local preferences. This is an existing runtime input, not a new persistence
@@ -213,3 +271,11 @@ Conflicting preference regression: the external config hydration suite passed al
213
271
  and placeholder (log `/private/tmp/praxis-form-preference-conflict-tests.log`). This
214
272
  is an isolated storage-service test and serialized widget round-trip; actual
215
273
  backend persistence and visual editor interaction are validated separately.
274
+
275
+ ## Governed page child adapter
276
+
277
+ For published page authorship, use [the native page adapter](governed-page-widget-adapter.md), not the
278
+ common wrapper output directly. It preserves exact presence and only explicit editor deltas, locks
279
+ bindings/context to the admitted seed, and derives volatile execution inputs from page/widget identity.
280
+ Native `presentation` and `dossier` modes survive open/save/reopen; new visual flows still prefer
281
+ `view` with a separate display preference. Filter Form keeps its three-mode runtime subset.
@@ -0,0 +1,46 @@
1
+ ---
2
+ title: "PR 645 — final review and regression evidence"
3
+ doc_type: "guide"
4
+ component: "praxis-dynamic-form"
5
+ status: "validated"
6
+ owner: "praxis-ui"
7
+ last_updated: "2026-10-23"
8
+ ---
9
+
10
+ # Final review of PR 645
11
+
12
+ Review started at PR head `9ad3c8221b1de2bdba6b62adec778c185553bcd5`, against main `51075de81704596606bb578ab681124df5ae8493`. The follow-up source is identified by the refreshed 32-file `source-hashes.json`; earlier screenshots and logs remain historical evidence at the original head, not new executions against the follow-up. The original shared checkout and its server were preserved.
13
+
14
+ ## Findings resolved before integration
15
+
16
+ 1. **Shared graph ownership.** A and B could reference G/L, but clearing A retained `parentId=A`; clearing/removing B then left invalid orphan conditions. The existing graph owner now transfers retained parent references when the old edge is removed. Removal follows both child and condition references, including nested property rules, while preserving external sharing, immutable history and undo/redo. Incoming draft references are remapped together with IDs. The original red lane had two failures; the final service/component lane passed 74 tests.
17
+ 2. **Angular input assignment and cold storage.** Angular assigns `config` before `ngOnChanges`, so comparing against that property missed already-normalized replacements. The previous host document now determines whether the input changed. Genuine standalone replacements, including empty documents, rebuild without resuming an obsolete persisted initializer. A cold adapter that returns the old saved value on every subscription reproduced the failure; the final test asserts one config read and the latest field metadata.
18
+ 3. **Equivalent host echoes.** A local-first form can have a saved effective document different from its opening host document. An equivalent echo must retain the effective document and both rule branches, dirty controls and pending initialization. The public input retains the same type; an accessor observes only the transient pre-assignment references around the existing single effective document. Internal writes use that backing document directly. Only a config echo is excluded from the ownership epoch; other owner/mode/resource fences remain. Tests cover settled and pending-hook echoes, manual lifecycle calls without assignment, and two host assignments before one change-detection pass, ending either in an echo or a genuine update. Echo and batched-echo red lanes each reproduced one failure before correction.
19
+
20
+ Inventory classification: `suportado-parcialmente`, corrected at the existing Visual Builder graph and Dynamic Form runtime owners. No additional model, persistence adapter, endpoint, feature flag, exported type or parallel authoring document was introduced by the review fixes.
21
+
22
+ ## Final applicable gates
23
+
24
+ | Gate | Final result |
25
+ | --- | --- |
26
+ | Visual Builder service, Rule Editor, Rule Definition and Field Condition Editor | 74 passed |
27
+ | Form field metadata, first-config and external-config hydration | 74 passed |
28
+ | Official `build-libs.js --prod --only praxis-dynamic-form` dependency closure, including VB, Form and Page Builder | Passed |
29
+ | Library purity | Passed, 2320 files |
30
+ | Published documentation assets | Passed, 5 packages |
31
+ | Material select content model | Passed, zero debt |
32
+ | Catalog | Passed, zero errors/warnings |
33
+ | Authoring contract acceptance | Passed, 20/20 |
34
+ | Final component-doc extraction versus tracked source, excluding generation timestamp | Equal |
35
+
36
+ These are focal lane counts, not a combined unique-test total. The unchanged editor/converter/diagnostic and visual presentation evidence is recorded in `validation.md`. Tests use Chrome Headless and real Angular `componentRef.setInput`; mocked storage/hooks and schema reconciliation do not constitute live HTTP proof. The final review did not rerun the desktop/narrow live authoring journey or a database lane. It does not certify settled form/component identity switching, full-suite behavior, screen readers, concurrency or release publication.
37
+
38
+ The catalog initially lacked an ignored generated ingestion artifact. Official workspace generation resolved that environmental failure without editing tracked registry data. Authoring acceptance initially lacked the backend sibling path in the isolated worktree; the final gate used only an immutable source snapshot of canonical config-starter main `deebc69187f2aebcb23ebe259a6913947fc10b27`, not the unrelated dirty backend checkout. No backend runtime or database was started for this source-contract check.
39
+
40
+ The graph fix author was different from the runtime fix author. Root independently reviewed both final diffs; the graph author also independently reviewed the final runtime accessor, internal writes, batching and ownership fences. No blocking finding remained in the reviewed final source. Test/configuration strictness was not weakened.
41
+
42
+ ## Derived artifacts and skills
43
+
44
+ The existing documentation already describes graph ownership, host authority and persistence; the review enforces those invariants. No new public semantics require a README, HTTP corpus, AI manifest or landing delta. Final metadata extraction confirms no derived catalog change. Landing PR 268 from the original implementation remains outside this merge.
45
+
46
+ Visual Builder graph skill: `existente-adequada`, because its canonical graph-runtime guidance already requires shared ownership, graph integrity and undo proofs. Form schema/runtime skill: `atualizar-existente`, adding real Angular/cold adapter and effective-echo proofs in canonical skills PRs 838 and 839. Both were independently reviewed and integrated; final canonical merge is `3ca2d184ba803dac1e560697142475e5ee8336fa`. Validation used the repository's focal validator, Python preflight and both family audits. The optional quick validator lacked `yaml`; the official fallback passed. Official selective synchronization of this one skill passed: canonical, manifest and installed hashes match, and all 796 files outside the target remained unchanged. Five unrelated existing Praxis drifts were preserved. The raw selective receipt is `review-skill-sync-receipt.json`.
@@ -0,0 +1,50 @@
1
+ # Revisão independente — Form Authoring #635
2
+
3
+ Revisor: `rules_audit`; atualizado em 2026-10-23T21:18:03+00:00.
4
+ Checkout: `/Users/rodrigo/Dev/pessoal/praxis-plataform/.worktrees/form-p1-631-633`; branch `fix/form-authoring-635`; HEAD `51075de81704596606bb578ab681124df5ae8493` **mais alterações locais**. Os hashes abaixo identificam os bytes revisados, não um futuro commit.
5
+
6
+ ## Resultado e limites
7
+
8
+ Sem bloqueantes nos recortes revisados abaixo. Esta nota é revisão de código e evidência; não declara browser final, validação integral, contagem de testes únicos nem autorização de merge.
9
+
10
+ - **Autoria VB:** este agente implementou o trabalho em `praxis-visual-builder/src` e seus testes. A revisão independente desses trechos foi feita pelo coordenador `root`; a presente nota não substitui essa revisão por autorrevisão. A última rodada própria foi `88 SUCCESS` em sete includes (`/tmp/praxis-635-vb-final88.log`); as contagens intermediárias são execuções sobrepostas, não suítes somáveis.
11
+ - **Revisão independente feita por este agente:** ConfigEditor, painel de propriedades, textos/i18n, documentação e o follow-up runtime de `initialValue`. Não escrevi esses trechos. Não reexecutei suas suítes nem os builds finais nesta revisão. A ponte Form/propertyRule e sua preservação de metadados também têm revisão própria de `audit_environment`; aqui apenas confrontei seu contrato com o consumidor VB.
12
+
13
+ ## Escopos confrontados
14
+
15
+ - **ConfigEditor:** hidratação centralizada; `formRules` prevalece sobre projeção válida obsoleta; drafts inválidos continuam disponíveis e bloqueiam Apply/Save; JSON vazio e Reset não ressuscitam estado residual. O eco descartado é somente uma assinatura obsoleta conhecida; seleção de nó não substitui o documento. O teste de assinatura distingue `selected` de uma mudança real no valor da condição.
16
+ - **Painel e pureza:** o painel de efeitos obsoleto fica oculto durante falha de conversão; a mensagem esclarece qual configuração foi preservada. O painel usa o `PraxisJsonLogicService` injetado para validar/simular; prévia de ramo, edição de propriedade e validade runtime têm escopos explícitos. A guarda não oculta nem une o canal separado de comandos. Sem autorização extra de acesso ou decisão de negócio pela UX.
17
+ - **i18n/docs:** mensagem do draft presente uma vez em pt/en; documentação coerente com os canais separados, limitações da prévia, alvos indisponíveis e edição de JSON avançado. README descreve a assinatura aditiva `updateNode(..., conditionState?)`, atomicidade, histórico e preservação de draft. Nenhum novo manifest/modelo foi exigido para esse ajuste visual.
18
+ - **Runtime, revisão adicional:** a atualização local autoritativa de `initialValue` agora atualiza o cache mesmo antes dos controles. O build posterior usa o snapshot mais recente; se os controles já existem, o mesmo ramo faz reset/patch sem emitir mudanças de valor e restaura pristine/untouched. A condição existente `usesInitialValueAsAuthoritativeSnapshot()` continua excluindo edit/view com `readUrl` ou `resourcePath`; não encontrei ampliação da autoridade local sobre dados remotos. Confrontei os quatro casos storage/afterInit × atualização/limpeza e suas asserções sem HTTP. A revisão principal do guard de `loadEntity` pertence a `audit_environment`/root.
19
+
20
+ A atestação runtime existente registra `67/67` por seu executor (`standalone-runtime-final-attestation.json`); correspondência dos três hashes de fonte/testes com esta árvore: **True**. Isso não transforma essa execução em uma prova nova executada por este revisor.
21
+
22
+ Follow-up VB após a rodada de 86: a assinatura de eco normaliza somente dados de transporte (`selected`, `parentId`, `children` omitido/`[]` e ordem de chaves), preservando conteúdo e ordem semântica. Os dois novos casos cobrem o passo Condição montado no MatStepper ao ativar Visual, o eco atômico equivalente e a hidratação de mudança externa real. O coordenador revisou esse delta; a prova browser final permanece sob sua responsabilidade. `git diff --check` passou.
23
+
24
+ Follow-up independente final do escopo dos diagnósticos: aprovados os guards em HTML que também ocultam o diagnóstico aceito e seu placeholder vazio enquanto `ruleConversionFailed` estiver ativo. O alerta de conversão, o editor visual e o canal separado de comandos continuam disponíveis; estado aceito, persistência e gates não mudam. As três novas asserções do teste montado cobrem ambos os estados ausentes no draft inválido e o retorno do diagnóstico após reparo. A frase atualizada em `dynamic-form-authoring-document-semantics.md` corresponde ao comportamento. O executor root registrou `69 SUCCESS` em `/tmp/praxis-635-editor-diagnostic-scope-final.log` e build Form de produção verde; conferi o resultado bruto do log, sem executar outra suíte. Sem novos bloqueantes nesta revisão.
25
+
26
+ ## Identidade das fontes
27
+
28
+ SHA-256 agregado dos 12 arquivos revistos: `93fbacf7a416827699ef172877caeb82e1207c42dd8db8c180398a26158d0adb`.
29
+ Snapshot agregado de 17 arquivos VB de código/testes modificados ou novos: `fe60920e81205607fe87096add54791f0ca9492d35862cdf2f8df15ea1f739e5`. Esse segundo conjunto é de autoria, cuja aprovação independente pertence ao root.
30
+ Algoritmo: ordenar os paths relativos; concatenar para cada arquivo `path UTF-8`, NUL, bytes do arquivo, NUL; calcular SHA-256.
31
+
32
+ <details>
33
+ <summary>SHA-256 por fonte revista</summary>
34
+
35
+ | Fonte relativa ao checkout acima | SHA-256 |
36
+ | --- | --- |
37
+ | `projects/praxis-dynamic-form/src/lib/config-editor/praxis-dynamic-form-config-editor.ts` | `472441a47e45788961bdb1debe5618dd3f035fa9f588d16395a6e2debf713eaa` |
38
+ | `projects/praxis-dynamic-form/src/lib/config-editor/praxis-dynamic-form-config-editor.html` | `89ca1a449d24bacaa2ac051fa152623524f70d843bab2e834375014874dddd94` |
39
+ | `projects/praxis-dynamic-form/src/lib/config-editor/praxis-dynamic-form-config-editor.spec.ts` | `e1f6418631923aed67479168f534e2a7193dffce3efe682e3adf5371d0b7888e` |
40
+ | `projects/praxis-dynamic-form/src/lib/config-editor/rule-properties-panel.component.ts` | `42a0e7ed41ab822ed82e6dcb455671be0fc3546a4676bc09e4f2daffde71f241` |
41
+ | `projects/praxis-dynamic-form/src/lib/config-editor/rule-properties-panel.component.spec.ts` | `7428843281cfdd408064677bc531437843cea23f0e19ab32d1c376b749b46987` |
42
+ | `projects/praxis-dynamic-form/src/lib/praxis-dynamic-form.i18n.ts` | `2aadec19c29908e76faf3cb3a6620bc905f7088322f7cc3b92bed3069d82e011` |
43
+ | `projects/praxis-dynamic-form/src/lib/praxis-dynamic-form.ts` | `76d419643fc77da32c30b8fba1c7d65e955552adb84f0576f7f8b4eb9c2a7c1e` |
44
+ | `projects/praxis-dynamic-form/src/lib/praxis-dynamic-form.field-metadata-roundtrip.spec.ts` | `e8e967d0dccec403d2dff1c7691a5f609bf6d1c8bfd4f48a57139a3f9f78a403` |
45
+ | `projects/praxis-dynamic-form/src/lib/praxis-dynamic-form.first-config-hydration.spec.ts` | `da5d24f06e2fb5c72acc74a65dde090a2d5a0c9e14621236e9c6d1eb1c4df706` |
46
+ | `projects/praxis-dynamic-form/docs/dynamic-form-authoring-document-semantics.md` | `98235e6fae395e2f51a32ace72d9369d7b7f0e2097f689bf15b4f419bcb39d40` |
47
+ | `projects/praxis-dynamic-form/src/lib/config-editor/praxis-dynamic-form-config-editor.json-api.md` | `3a2e2c2e78c6286dbd34396ee21e468244321fda7c2c4bc6112252990d81bc58` |
48
+ | `projects/praxis-visual-builder/README.md` | `6250604032792b0f23f4b33d5a1596e51325b27911aba7f0268b801a571dbe6d` |
49
+
50
+ </details>
@@ -0,0 +1,76 @@
1
+ ---
2
+ title: "Conditional form authoring — issue 635 validation"
3
+ doc_type: "guide"
4
+ component: "praxis-dynamic-form"
5
+ status: "validated"
6
+ owner: "praxis-ui"
7
+ last_updated: "2026-10-23"
8
+ ---
9
+
10
+ # Conditional form authoring — issue 635
11
+
12
+ The subsequent [final PR review](final-review.md) records additional ownership and Angular input regressions found and corrected before integration, final source hashes and fresh focal/build gates. Browser screenshots below belong to the original PR head; they were not rerun during that final review.
13
+
14
+ The change was implemented in an isolated checkout on main `51075de81704596606bb578ab681124df5ae8493`. Unrelated changes in the original checkout were preserved. Classification: cross-library public behavior, with an additive optional `conditionState` argument on the existing `RuleBuilderService.updateNode` API. No new rule model, endpoint, AI contract, workspace configuration, dependency or public-api export was introduced.
15
+
16
+ ## Canonical inventory and impact
17
+
18
+ Existing canonical property effects, graph drafts, host operator registry, diagnostics and persistence already cover the requested behavior. Summaries/status scopes are `ja-suportado-so-ux`; replacement, graph transfer and standalone hydration were `suportado-parcialmente`. An atomic node plus complete owned condition-graph update was missing from the existing service operation: the optional existing RuleBuilderState argument supplies that operation without a parallel contract. Complete conditions derive from fresh graph fields; incomplete descendants must not become an unconditional or partial condition.
19
+
20
+ Owners: Visual Builder for authoring/history and Dynamic Form for the canonical document, diagnostics and persistence. Direct consumers are the Form config editor, authoring diagnostics and the All Fields showcase. Form→builder now produces one propertyRule per rule, retaining every target, both branches, identity and authoring/semantic metadata. Existing legacy ingestion remains; new authoring does not generate legacy conditional-validator nodes.
21
+
22
+ Presentation formRules and formCommandRules retain separate channels. Core access policy remains authoritative; formHidden/access filters were preserved. Source builds include a direct consumer and the official dependency closure. No backend schema, business rule or HTTP corpus changed.
23
+
24
+ ## Automated gates
25
+
26
+ | Gate | Result |
27
+ | --- | --- |
28
+ | Visual Builder: field condition, wizard, rule editor/list, target selector, service and summary | 88 passed |
29
+ | Form config editor, converters and diagnostics | 121 passed |
30
+ | Final mounted ConfigEditor diagnostic-scope guard | 69 passed (overlaps the preceding lane) |
31
+ | Standalone field metadata roundtrip, first/external config hydration | 67 passed |
32
+ | Official production dependency closure through Dynamic Form and Page Builder consumer | Passed |
33
+ | Final Visual Builder and Dynamic Form production builds | Passed |
34
+ | Purity and changed-document frontmatter | Passed |
35
+
36
+ These are focal unit/component lanes, not unique-test totals or a full release certification. The mounted Material stepper tests cover backward/forward navigation and linear blocking; real FieldConditionEditor debounce and canonical own echoes are exercised. Atomic graph tests cover incomplete descendants, cycles, shared nodes, removal, selection and undo. Host initialValue updates/clears during storage/hooks preserve the latest local authority without schema/entity HTTP. Existing remote-authority guards remain intact.
37
+
38
+ Logs in this folder contain the raw focal outcomes with terminal control sequences and trailing display padding removed. Historical failures were diagnosed before rerun; no test configuration or TypeScript strictness was weakened. The full test suite and screen-reader/assistive-technology certification were not run.
39
+
40
+ ## Browser validation
41
+
42
+ Chrome via visible UI on official UI4003/API8088, frozen task checkout. No DOM state injection, fetch, mocks or JSON were used to author the simple rule. The real library All Fields example was used: Toggle and URL were renamed to Ativo and Foto (URL) through the visible Metadata Editor. This is a local form example using real remote config persistence; it is not certification of the Quickstart Foto upload or its backend field-access policy.
43
+
44
+ The analyst task used target selection, Visual condition Ativo = Sim, visible/required true and false branches, readable review and Save. The review and list describe all four effects. The runtime false branch hides Foto; the true branch exposes a required input with aria-required=true. Sample-data preview evaluates the two branches separately and explicitly states its limits.
45
+
46
+ Verified scenarios include incomplete draft/disabled saving with stale accepted effects and diagnostics withheld, repaired draft, keyboard target/Boolean choices and Next/Anterior, JSON replacement and advanced runtime-only if condition, exact advanced Save/reload with both branches, and subsequent restoration of the simple rule. Merely selecting a rule and navigating leaves Sem alterações. Closing returns focus to Configurar formulário.
47
+
48
+ Reset was confirmed through its visible dialog: it restores the opened document in the editor and this host also clears persisted keys. A read-only GET returned404 afterward. Reload consequently returned to the host example, as intended; the rule was then authored and saved again. Final persisted receipt returned200/version5 with one rule, toggle===true and both visible/required branches intact. This does not certify ETag conflict handling or concurrent saves.
49
+
50
+ At390×844 the section selector, footer actions and effect controls fit; review content is readable by vertical scrolling. This is an agent simulation, not a human usability study: no human task-time or comprehension score is claimed. Multiple internal scroll areas remain a usability limit for small screens.
51
+
52
+ ## Independent review and derived guidance
53
+
54
+ Each implementation area was reviewed by a different agent. Root reviewed Visual Builder, runtime and converter changes; the VB author independently reviewed root ConfigEditor, panel, docs/i18n and the latest initialValue fix; the runtime author independently reviewed VB metadata preservation and root selection signature. Review covered canonical authority, replacement, both branches, ownership/history, consumers, source/test evidence and docs.
55
+
56
+ Owner documentation was updated. The Visual Builder README is synchronized by the official vendor helper in praxis-ui-landing-page PR268; vendor75/docs25/guides145/sitemap gates passed, with the existing Cron Mermaid warning. No AI manifest/catalog, exported model or HTTP semantic surface changed, so registry/corpus generation was unnecessary.
57
+
58
+ Skills: atualizar-existente for five existing skills in canonical praxis-codex-skills PR836, including document roundtrip, Form authoring settings and Visual Builder rules/graph/JSON Logic. No new skill was introduced. Standalone runtime guidance was already adequate in the canonical schema/runtime skill. Canonical skills PR836 was integrated at e13f4b4d1a0ed1bc127f15105cefc5f2eeb9524f. Official selective sync validated5/5 affected skills and preserved all783 files outside scope and unrelated local drifts. Landing PR268 remains open for review, without deployment.
59
+
60
+ ## Final visual receipts
61
+
62
+ The last PT retest confirmed Condition stayed selected after fresh Visual activation, saving was disabled, and both accepted diagnostics (including the empty placeholder) and stale effects were absent. Repair restored current diagnostics and effects. Immediate Boolean edit→Next and Anterior both worked. JSON formRules=[] with residual formRulesState produced zero rows and the empty diagnostic; replacing it with the complete document restored one editable rule. The test draft was discarded and focus returned to Configure form. No additional configuration was saved during this last retest.
63
+
64
+ English was exercised using the official providePraxisI18nConfig provider on the same UI origin. New summaries/status/preview copy and Yes were localized. The temporary host file was restored exactly: app.config.ts SHA256 bdf1dbc425b4d9babfa76b78a2f913ce36095d3e500d74d344ea5dd8bb251718. Host business labels and some existing metadata/control labels remain Portuguese; a whole-platform translation audit is not claimed. The final display-only diagnostic guard was then retested in PT and the mounted component lane.
65
+
66
+ ![Complete review](desktop-review-accepted.png)
67
+
68
+ ![Incomplete condition blocks saving without stale diagnostics](desktop-incomplete-accepted.png)
69
+
70
+ ![Narrow effect editor](narrow-effects-final-main.png)
71
+
72
+ ![Narrow review, lower effects after scrolling](narrow-review-effects-final-main.png)
73
+
74
+ ![English summary](english-summary-final.png)
75
+
76
+ ![Advanced expression preserved](advanced-reopen-final-main.png)