@praxisui/table 8.0.0-beta.2 → 8.0.0-beta.21
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 +150 -8
- package/docs/DSL-Extensions-Guide.md +23 -0
- package/docs/adr/2026-03-dynamic-filter-cross-lib-coupling.md +107 -0
- package/docs/adr/2026-03-filter-drawer-adapter-light-entrypoint.md +105 -0
- package/docs/adr/2026-03-table-editor-idfield-decision.md +85 -0
- package/docs/column-resize-reorder-implementation-plan.md +338 -0
- package/docs/column-resize-reorder-review-prompt.md +34 -0
- package/docs/dynamic-filter-architecture-overview.md +207 -0
- package/docs/dynamic-filter-backend-contract-cheatsheet.md +167 -0
- package/docs/dynamic-filter-editor-settings-guide.md +229 -0
- package/docs/dynamic-filter-host-integration-guide.md +217 -0
- package/docs/dynamic-filter-payload-contract.md +331 -0
- package/docs/dynamic-filter-range-filters-guide.md +289 -0
- package/docs/dynamic-filter-troubleshooting-guide.md +220 -0
- package/docs/dynamic-inline-filter-catalog.md +147 -0
- package/docs/e2e-column-drag-playwright.md +62 -0
- package/docs/expandable-rows-enterprise-big-leagues-plan.md +1080 -0
- package/docs/json-logic-operators-and-helpers.md +57 -0
- package/docs/local-data-mode-precedence.md +12 -0
- package/docs/local-data-pre-implementation-baseline.md +22 -0
- package/docs/local-data-preimplementation-go-no-go.md +39 -0
- package/docs/local-data-support-implementation-plan.md +524 -0
- package/docs/local-data-support-pr-package.md +66 -0
- package/docs/localization-persistence-merge.md +22 -0
- package/docs/performance-hardening-v2-implementation-plan.md +479 -0
- package/docs/playground-scenario-curation-plan.md +482 -0
- package/docs/playground-scenario-second-opinion-prompt.md +121 -0
- package/docs/playground-scenario-second-opinion-review.md +234 -0
- package/docs/release-notes-p1-hardening.md +76 -0
- package/docs/table-authoring-document-completeness-checklist.md +120 -0
- package/docs/table-editor-capability-review-prompt.md +349 -0
- package/docs/visual-rules-editor-transition.md +29 -0
- package/fesm2022/{praxisui-table-table-agentic-authoring-turn-flow-tu7jtTwV.mjs → praxisui-table-table-agentic-authoring-turn-flow-DRuE55Mi.mjs} +100 -0
- package/fesm2022/{praxisui-table-table-ai.adapter-DxjDaQqy.mjs → praxisui-table-table-ai.adapter-fS74fZ7o.mjs} +14 -5
- package/fesm2022/praxisui-table.mjs +5317 -736
- package/index.d.ts +325 -106
- package/package.json +15 -9
- package/src/lib/praxis-table.json-api.md +1325 -0
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
# Prompt Para Revisão Especializada: `tableEditorCapability`
|
|
2
|
+
|
|
3
|
+
## Contexto
|
|
4
|
+
|
|
5
|
+
Estamos evoluindo a arquitetura de edição de configuração dos componentes do ecossistema Praxis UI, com foco inicial em `praxis-table`, mas com intenção clara de estabelecer um padrão reaproveitável por `praxis-list`, `praxis-dynamic-form` e futuros componentes editáveis do playground.
|
|
6
|
+
|
|
7
|
+
O problema atual não é falta de editor JSON nem falta de editor visual. O problema é ausência de um protocolo canônico único entre as diferentes superfícies de autoria e o runtime real.
|
|
8
|
+
|
|
9
|
+
Hoje convivem, de forma parcialmente desconectada:
|
|
10
|
+
|
|
11
|
+
- editor visual embutido no componente
|
|
12
|
+
- editor JSON embutido no componente
|
|
13
|
+
- playground com apply simplificado
|
|
14
|
+
- apply por `@Input()`
|
|
15
|
+
- alguns fluxos com métodos públicos como `applyConfigFromAdapter(...)`
|
|
16
|
+
|
|
17
|
+
No caso de `praxis-table`, a situação é especialmente instrutiva:
|
|
18
|
+
|
|
19
|
+
- a tabela já possui um editor robusto
|
|
20
|
+
- o editor não trata o JSON como `TableConfig` cru
|
|
21
|
+
- ele usa `editedConfig`, dirty state, normalização, coerção por modo efetivo e reconciliação de campos auxiliares
|
|
22
|
+
- `resourcePath`, `idField` e `horizontalScroll` vivem fora do `TableConfig` puro
|
|
23
|
+
- o host/runtime reinterpreta campos internos como `__resourcePath__`, `__resourcePathIntent__`, `__idField__`, `__horizontalScroll__`
|
|
24
|
+
|
|
25
|
+
Ou seja: o componente já demonstra, na prática, que o modelo correto não é "editar JSON e repassar por input". O modelo correto é "editar um documento canônico de autoria e aplicar por um protocolo oficial".
|
|
26
|
+
|
|
27
|
+
## Motivação
|
|
28
|
+
|
|
29
|
+
Queremos transformar edição de configuração em uma capability formal do componente.
|
|
30
|
+
|
|
31
|
+
Objetivos centrais:
|
|
32
|
+
|
|
33
|
+
- round-trip confiável entre editor visual, editor JSON, playground e runtime
|
|
34
|
+
- separação clara entre `config` do componente e `hostInputs/contexto`
|
|
35
|
+
- normalização e validação centralizadas
|
|
36
|
+
- remoção de hacks específicos do playground
|
|
37
|
+
- remoção gradual de marcadores mágicos públicos como `__resourcePath__`
|
|
38
|
+
- base uniforme para consumo futuro por IA
|
|
39
|
+
|
|
40
|
+
O `praxis-table` será o blueprint inicial.
|
|
41
|
+
|
|
42
|
+
## Diagnóstico resumido do estado atual em `praxis-table`
|
|
43
|
+
|
|
44
|
+
### Editor
|
|
45
|
+
|
|
46
|
+
O editor atual concentra lógica relevante em:
|
|
47
|
+
|
|
48
|
+
- normalização de `TableConfig`
|
|
49
|
+
- dirty state comparando config normalizada + host inputs paralelos
|
|
50
|
+
- coerção de `pagination.strategy` e `sorting.strategy` para `client` em modo local
|
|
51
|
+
- reconciliação/preservação de `advancedFilters.settings`
|
|
52
|
+
- reconciliação visual de divergência com `serverIdField` e `serverSchemaHash`
|
|
53
|
+
|
|
54
|
+
### Runtime
|
|
55
|
+
|
|
56
|
+
O host (`PraxisTable`) hoje:
|
|
57
|
+
|
|
58
|
+
- abre o editor com `tableConfig`, `resourcePath`, `idField`, `horizontalScroll`, contexto CRUD e metadados de servidor
|
|
59
|
+
- recebe payload de volta
|
|
60
|
+
- lê marcadores internos
|
|
61
|
+
- reconcilia `resourcePath`, `idField`, `horizontalScroll`
|
|
62
|
+
- injeta metadados em `config.meta`
|
|
63
|
+
- remove marcadores internos
|
|
64
|
+
- finalmente chama `applyTableConfig(...)`
|
|
65
|
+
|
|
66
|
+
Esse fluxo funciona, mas o contrato entre editor e runtime é implícito, frágil e difícil de reutilizar no playground.
|
|
67
|
+
|
|
68
|
+
## Proposta arquitetural
|
|
69
|
+
|
|
70
|
+
Introduzir uma capability formal por componente, começando por `praxis-table`.
|
|
71
|
+
|
|
72
|
+
### Contrato base esperado
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
export interface EditorDiagnostic {
|
|
76
|
+
level: 'error' | 'warning' | 'info';
|
|
77
|
+
code: string;
|
|
78
|
+
message: string;
|
|
79
|
+
path?: string;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export interface ComponentEditorCapability<TDocument, TConfig, TTarget = unknown> {
|
|
83
|
+
kind: string;
|
|
84
|
+
version: 1;
|
|
85
|
+
|
|
86
|
+
createDocument(source: {
|
|
87
|
+
config?: unknown;
|
|
88
|
+
hostInputs?: Record<string, unknown>;
|
|
89
|
+
hostContext?: Record<string, unknown>;
|
|
90
|
+
}): TDocument;
|
|
91
|
+
|
|
92
|
+
normalizeDocument(raw: unknown): TDocument;
|
|
93
|
+
validateDocument(doc: TDocument): EditorDiagnostic[];
|
|
94
|
+
|
|
95
|
+
parseDocument(json: unknown): TDocument;
|
|
96
|
+
serializeDocument(doc: TDocument): unknown;
|
|
97
|
+
|
|
98
|
+
toCanonicalConfig(doc: TDocument): TConfig;
|
|
99
|
+
|
|
100
|
+
applyDocument(
|
|
101
|
+
target: TTarget,
|
|
102
|
+
doc: TDocument,
|
|
103
|
+
context?: unknown,
|
|
104
|
+
): void | Promise<void>;
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Documento canônico proposto para tabela
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
export type TableHorizontalScroll = 'auto' | 'wrap' | 'none';
|
|
112
|
+
export type ResourcePathIntent = 'set' | 'clear' | 'unchanged';
|
|
113
|
+
export type EffectiveDataMode = 'remote' | 'local' | 'empty';
|
|
114
|
+
|
|
115
|
+
export interface TableEditorHostInputs {
|
|
116
|
+
resourcePath?: string;
|
|
117
|
+
idField?: string;
|
|
118
|
+
horizontalScroll?: TableHorizontalScroll;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export interface TableEditorHostContext {
|
|
122
|
+
hasLocalDataInput?: boolean;
|
|
123
|
+
localDataModeFlagEnabled?: boolean;
|
|
124
|
+
serverIdField?: string;
|
|
125
|
+
serverSchemaHash?: string;
|
|
126
|
+
crudContext?: {
|
|
127
|
+
tableId: string;
|
|
128
|
+
componentKeyId?: string;
|
|
129
|
+
resourcePath?: string;
|
|
130
|
+
idField?: string;
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export interface TableEditorMeta {
|
|
135
|
+
effectiveDataMode?: EffectiveDataMode;
|
|
136
|
+
resourcePathIntent?: ResourcePathIntent;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export interface TableEditorDocument {
|
|
140
|
+
config: TableConfig;
|
|
141
|
+
hostInputs?: TableEditorHostInputs;
|
|
142
|
+
hostContext?: TableEditorHostContext;
|
|
143
|
+
editorMeta?: TableEditorMeta;
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Plano proposto para `tableEditorCapability`
|
|
148
|
+
|
|
149
|
+
### 1. `createDocument(source)`
|
|
150
|
+
|
|
151
|
+
Responsabilidade:
|
|
152
|
+
|
|
153
|
+
- criar o documento inicial a partir do estado real do host/editor
|
|
154
|
+
- derivar `resourcePath`, `idField`, `horizontalScroll`
|
|
155
|
+
- normalizar config de entrada
|
|
156
|
+
- preencher `editorMeta.effectiveDataMode`
|
|
157
|
+
|
|
158
|
+
Origem da lógica:
|
|
159
|
+
|
|
160
|
+
- `PraxisTable.openConfigEditor(...)`
|
|
161
|
+
- inicialização de `PraxisTableConfigEditor.ngOnInit()`
|
|
162
|
+
|
|
163
|
+
### 2. `normalizeDocument(raw)`
|
|
164
|
+
|
|
165
|
+
Responsabilidade:
|
|
166
|
+
|
|
167
|
+
- aceitar payload novo ou legado
|
|
168
|
+
- migrar `__resourcePath__`, `__idField__`, `__horizontalScroll__`, `__resourcePathIntent__`
|
|
169
|
+
- normalizar `config`
|
|
170
|
+
- normalizar `hostInputs`
|
|
171
|
+
- derivar `effectiveDataMode`
|
|
172
|
+
- aplicar coerções de estratégia em modo local
|
|
173
|
+
- estabilizar settings de filtros avançados
|
|
174
|
+
|
|
175
|
+
Essa é a peça principal da capability.
|
|
176
|
+
|
|
177
|
+
### 3. `validateDocument(doc)`
|
|
178
|
+
|
|
179
|
+
Responsabilidade:
|
|
180
|
+
|
|
181
|
+
- centralizar erros bloqueantes e warnings
|
|
182
|
+
- impedir apply inválido
|
|
183
|
+
- expor diagnósticos para editor visual, JSON editor e playground
|
|
184
|
+
|
|
185
|
+
Validações esperadas:
|
|
186
|
+
|
|
187
|
+
- `config.columns` deve ser array
|
|
188
|
+
- colunas devem ter `field`
|
|
189
|
+
- `horizontalScroll` deve estar no enum
|
|
190
|
+
- `resourcePathIntent=set` exige `resourcePath`
|
|
191
|
+
- `server pagination/sorting` não podem permanecer em modo local
|
|
192
|
+
- warning de divergência entre `hostInputs.idField` e `serverIdField`
|
|
193
|
+
- warning de divergência entre `config.meta.serverHash` e `serverSchemaHash`
|
|
194
|
+
|
|
195
|
+
### 4. `toCanonicalConfig(doc)`
|
|
196
|
+
|
|
197
|
+
Responsabilidade:
|
|
198
|
+
|
|
199
|
+
- projetar somente o `TableConfig` persistível/consumível pelo runtime
|
|
200
|
+
- não embutir `resourcePath` nem `horizontalScroll`
|
|
201
|
+
- opcionalmente persistir `meta.idField`
|
|
202
|
+
- nunca vazar marcadores internos
|
|
203
|
+
|
|
204
|
+
### 5. `serializeDocument(doc)` / `parseDocument(json)`
|
|
205
|
+
|
|
206
|
+
Responsabilidade:
|
|
207
|
+
|
|
208
|
+
- fazer do `TableEditorDocument` o JSON oficial de autoria
|
|
209
|
+
- permitir round-trip confiável entre editor visual e editor JSON
|
|
210
|
+
- aceitar payload legado na leitura, mas serializar só no formato novo
|
|
211
|
+
|
|
212
|
+
### 6. `applyDocument(target, doc, context?)`
|
|
213
|
+
|
|
214
|
+
Responsabilidade:
|
|
215
|
+
|
|
216
|
+
- encapsular o fluxo hoje espalhado no `PraxisTable`
|
|
217
|
+
- aplicar `resourcePath`, `idField`, `horizontalScroll`
|
|
218
|
+
- persistir inputs quando necessário
|
|
219
|
+
- compor `config.meta`
|
|
220
|
+
- persistir config quando necessário
|
|
221
|
+
- chamar o apply final do runtime
|
|
222
|
+
|
|
223
|
+
Contexto sugerido:
|
|
224
|
+
|
|
225
|
+
```ts
|
|
226
|
+
export interface TableApplyContext {
|
|
227
|
+
trigger: 'applied' | 'saved' | 'adapter' | 'playground';
|
|
228
|
+
persistConfig?: boolean;
|
|
229
|
+
persistInputs?: boolean;
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
## Como isso substituiria o fluxo atual
|
|
234
|
+
|
|
235
|
+
### Hoje
|
|
236
|
+
|
|
237
|
+
O editor devolve algo próximo de `TableConfig`, mas injeta campos internos:
|
|
238
|
+
|
|
239
|
+
- `__resourcePath__`
|
|
240
|
+
- `__resourcePathIntent__`
|
|
241
|
+
- `__idField__`
|
|
242
|
+
- `__horizontalScroll__`
|
|
243
|
+
|
|
244
|
+
O host reinterpreta isso manualmente.
|
|
245
|
+
|
|
246
|
+
### Proposto
|
|
247
|
+
|
|
248
|
+
O editor devolve `TableEditorDocument`.
|
|
249
|
+
|
|
250
|
+
O host faz:
|
|
251
|
+
|
|
252
|
+
```ts
|
|
253
|
+
const doc = tableEditorCapability.parseDocument(value);
|
|
254
|
+
tableEditorCapability.applyDocument(this, doc, {
|
|
255
|
+
trigger: 'saved',
|
|
256
|
+
persistConfig: true,
|
|
257
|
+
persistInputs: true,
|
|
258
|
+
});
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
## Compatibilidade
|
|
262
|
+
|
|
263
|
+
Queremos migração incremental, sem quebra abrupta.
|
|
264
|
+
|
|
265
|
+
Estratégia:
|
|
266
|
+
|
|
267
|
+
1. capability nova aceita payload legado
|
|
268
|
+
2. editor passa a produzir `TableEditorDocument`
|
|
269
|
+
3. runtime passa a preferir capability
|
|
270
|
+
4. fallback legado de `__...__` permanece temporariamente
|
|
271
|
+
5. playground passa a consumir capability
|
|
272
|
+
6. só depois removemos o protocolo mágico
|
|
273
|
+
|
|
274
|
+
## O que eu quero da revisão especializada
|
|
275
|
+
|
|
276
|
+
Quero uma revisão técnica rigorosa do desenho do `tableEditorCapability`, com foco em:
|
|
277
|
+
|
|
278
|
+
### 1. Contrato
|
|
279
|
+
|
|
280
|
+
- o `TableEditorDocument` está bem delimitado?
|
|
281
|
+
- `hostInputs`, `hostContext` e `editorMeta` estão bem separados?
|
|
282
|
+
- há campos demais ou de menos no documento?
|
|
283
|
+
|
|
284
|
+
### 2. Normalização
|
|
285
|
+
|
|
286
|
+
- a responsabilidade de `normalizeDocument()` está correta?
|
|
287
|
+
- alguma parte importante do comportamento atual da tabela ficaria fora?
|
|
288
|
+
- há risco de normalização com efeitos colaterais excessivos?
|
|
289
|
+
|
|
290
|
+
### 3. Apply
|
|
291
|
+
|
|
292
|
+
- `applyDocument()` deve chamar diretamente `applyTableConfig(...)`?
|
|
293
|
+
- a composição de `meta.idField`, `meta.version`, `meta.updatedAt`, `schemaId`, `serverHash` está no lugar certo?
|
|
294
|
+
- a persistência de `horizontalScroll` e `resourcePath` deveria ficar no capability ou no host?
|
|
295
|
+
|
|
296
|
+
### 4. Boundary público
|
|
297
|
+
|
|
298
|
+
- faz sentido expor `applyDocument()` como API oficial do componente?
|
|
299
|
+
- `toCanonicalConfig()` deve persistir `meta.idField` ou isso deve ser decisão só do host?
|
|
300
|
+
- `serverIdField` e `serverSchemaHash` devem existir no documento serializado ou apenas no contexto de sessão?
|
|
301
|
+
|
|
302
|
+
### 5. Migração
|
|
303
|
+
|
|
304
|
+
- a estratégia de compatibilidade com `__resourcePath__` etc. está adequada?
|
|
305
|
+
- existe uma abordagem melhor para migrar sem quebrar playground/editor atual?
|
|
306
|
+
|
|
307
|
+
### 6. Riscos
|
|
308
|
+
|
|
309
|
+
- riscos de drift que ainda permaneceriam
|
|
310
|
+
- riscos de acoplamento excessivo entre capability e classe Angular do componente
|
|
311
|
+
- riscos de versionamento do documento
|
|
312
|
+
|
|
313
|
+
## Critério de qualidade da revisão
|
|
314
|
+
|
|
315
|
+
Prefiro uma revisão em modo crítico, não superficial.
|
|
316
|
+
|
|
317
|
+
Se você enxergar fragilidade conceitual, ponto cego arquitetural, boundary errado ou risco de manutenção, aponte diretamente.
|
|
318
|
+
|
|
319
|
+
Quero principalmente saber:
|
|
320
|
+
|
|
321
|
+
- onde esse design ainda está fraco
|
|
322
|
+
- o que deveria ser movido de lugar
|
|
323
|
+
- o que ainda está dependente demais do estado atual do componente
|
|
324
|
+
- como deixar isso forte o suficiente para virar padrão do ecossistema
|
|
325
|
+
|
|
326
|
+
## Referências úteis no código atual
|
|
327
|
+
|
|
328
|
+
- `projects/praxis-table/src/lib/praxis-table-config-editor.ts`
|
|
329
|
+
- `projects/praxis-table/src/lib/praxis-table.ts`
|
|
330
|
+
- `projects/praxis-table/src/lib/json-config-editor/json-config-editor.component.ts`
|
|
331
|
+
|
|
332
|
+
Pontos mais relevantes observados no código atual:
|
|
333
|
+
|
|
334
|
+
- normalização/editor state no `PraxisTableConfigEditor`
|
|
335
|
+
- dirty state com `resourcePath`, `idField`, `horizontalScroll`
|
|
336
|
+
- coerção em modo local
|
|
337
|
+
- markers `__resourcePath__`, `__resourcePathIntent__`, `__idField__`, `__horizontalScroll__`
|
|
338
|
+
- apply final no runtime via `applyTableConfig(...)`
|
|
339
|
+
|
|
340
|
+
## Resultado esperado da revisão
|
|
341
|
+
|
|
342
|
+
Quero uma devolutiva estruturada contendo:
|
|
343
|
+
|
|
344
|
+
1. avaliação geral do desenho
|
|
345
|
+
2. falhas ou riscos mais importantes
|
|
346
|
+
3. mudanças recomendadas no contrato
|
|
347
|
+
4. mudanças recomendadas na estratégia de apply
|
|
348
|
+
5. recomendações de rollout/migração
|
|
349
|
+
6. se possível, uma proposta refinada do shape final da capability
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Transição: Editor de Regras da Tabela (especializado)
|
|
2
|
+
|
|
3
|
+
Status: concluído (novo editor disponível)
|
|
4
|
+
|
|
5
|
+
Resumo
|
|
6
|
+
- A aba "Regras Visuais" foi removida do editor de configuração da Tabela (`PraxisTableConfigEditor`).
|
|
7
|
+
- O wrapper anterior baseado no construtor genérico visual foi descontinuado nesta biblioteca.
|
|
8
|
+
- Um editor especializado de regras da Tabela foi introduzido e substitui o fluxo anterior.
|
|
9
|
+
|
|
10
|
+
Motivação
|
|
11
|
+
- Reduzir complexidade e dependências desnecessárias do builder genérico.
|
|
12
|
+
- Focar o domínio de Tabela (alvos linha/célula, efeitos dedicados e integração direta com `TableConfig`).
|
|
13
|
+
|
|
14
|
+
Impacto
|
|
15
|
+
- A aba "Regras" agora utiliza o novo editor especializado, com fluxo column‑first, operadores por tipo, editores de valor dinâmicos e construtor de grupos (AND/OR/NOT).
|
|
16
|
+
- As regras continuam salvas como DSL em `rowConditionalStyles` e `columns[].conditionalStyles` (runtime inalterado).
|
|
17
|
+
- O runtime DSL da tabela foi ampliado com helpers corporativos embutidos (`jsonType`, `eqIgnoreCase`, `between`, `dateBetween`, `containsAny`, `containsAll`, `coalesce`), sem necessidade de registro manual no host.
|
|
18
|
+
|
|
19
|
+
Alternativas
|
|
20
|
+
- A aba JSON permanece disponível para ajustes diretos quando necessário.
|
|
21
|
+
|
|
22
|
+
Notas técnicas
|
|
23
|
+
- Componentes e conversores removidos (nomes antigos omitidos por política):
|
|
24
|
+
- Editor visual anterior e seu wrapper
|
|
25
|
+
- Conversores de regras do editor visual e seus testes
|
|
26
|
+
- Remoções de export na API pública: `src/public-api.ts`.
|
|
27
|
+
|
|
28
|
+
Próximos passos
|
|
29
|
+
- Evoluir efeitos dedicados (classe/estilo/ícone/imagem/badge/valor/tooltip) preservando compatibilidade de runtime.
|
|
@@ -26,6 +26,9 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
26
26
|
?.map((field) => this.toAiJsonObject(field))
|
|
27
27
|
.filter((field) => Object.keys(field).length > 0);
|
|
28
28
|
const contextHints = this.optionalJsonObject(this.adapter.getAuthoringContext?.());
|
|
29
|
+
if (this.shouldRouteToGovernedDecision(prompt, contextHints)) {
|
|
30
|
+
return this.toGovernedDecisionHandoff(prompt, request);
|
|
31
|
+
}
|
|
29
32
|
const response = await firstValueFrom(this.aiApi.getPatch({
|
|
30
33
|
componentId,
|
|
31
34
|
componentType,
|
|
@@ -173,9 +176,26 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
173
176
|
}
|
|
174
177
|
compileAdapterResponse(response) {
|
|
175
178
|
const compiled = this.adapter.compileAiResponse?.(response);
|
|
179
|
+
if (!compiled && response.patch && Object.keys(response.patch).length > 0) {
|
|
180
|
+
return {
|
|
181
|
+
type: 'error',
|
|
182
|
+
message: 'A tabela exige componentEditPlan validado pelo manifesto antes de gerar patch local.',
|
|
183
|
+
warnings: [
|
|
184
|
+
'free-table-patch-rejected',
|
|
185
|
+
'Use componentEditPlan validado contra PRAXIS_TABLE_AUTHORING_MANIFEST.',
|
|
186
|
+
],
|
|
187
|
+
};
|
|
188
|
+
}
|
|
176
189
|
if (!compiled) {
|
|
177
190
|
return response;
|
|
178
191
|
}
|
|
192
|
+
if (compiled.type === 'error') {
|
|
193
|
+
return {
|
|
194
|
+
type: 'error',
|
|
195
|
+
message: compiled.message || 'O componentEditPlan da tabela nao passou na validacao de capacidades.',
|
|
196
|
+
warnings: compiled.warnings,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
179
199
|
const warnings = [
|
|
180
200
|
...(response.warnings ?? []),
|
|
181
201
|
...(compiled.warnings ?? []),
|
|
@@ -183,6 +203,7 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
183
203
|
return {
|
|
184
204
|
...response,
|
|
185
205
|
...compiled,
|
|
206
|
+
patch: compiled.patch,
|
|
186
207
|
warnings: warnings.length ? warnings : undefined,
|
|
187
208
|
};
|
|
188
209
|
}
|
|
@@ -251,6 +272,85 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
251
272
|
...(rowCount !== undefined ? { rowCount } : {}),
|
|
252
273
|
};
|
|
253
274
|
}
|
|
275
|
+
shouldRouteToGovernedDecision(prompt, contextHints) {
|
|
276
|
+
const normalized = prompt.normalize('NFD').replace(/[\u0300-\u036f]/g, '').toLowerCase();
|
|
277
|
+
const recommendedFlow = this.toRecord(contextHints?.['domainCatalog'])?.['recommendedAuthoringFlow'];
|
|
278
|
+
if (recommendedFlow === 'shared_rule_authoring')
|
|
279
|
+
return true;
|
|
280
|
+
return [
|
|
281
|
+
'regra',
|
|
282
|
+
'politica',
|
|
283
|
+
'policy',
|
|
284
|
+
'compliance',
|
|
285
|
+
'lgpd',
|
|
286
|
+
'privacidade',
|
|
287
|
+
'aprovacao',
|
|
288
|
+
'aprovar',
|
|
289
|
+
'publicar',
|
|
290
|
+
'materializar',
|
|
291
|
+
'enforcement',
|
|
292
|
+
'validacao de negocio',
|
|
293
|
+
'validar negocio',
|
|
294
|
+
'elegibilidade',
|
|
295
|
+
'permissao',
|
|
296
|
+
'acesso',
|
|
297
|
+
].some((term) => normalized.includes(term));
|
|
298
|
+
}
|
|
299
|
+
toGovernedDecisionHandoff(prompt, request) {
|
|
300
|
+
const message = 'Esse pedido parece alterar uma decisao de negocio compartilhada. A tabela pode ajudar a descrever o alvo, mas a regra deve seguir pelo fluxo governado de domain-rules antes de qualquer materializacao runtime.';
|
|
301
|
+
return {
|
|
302
|
+
state: 'clarification',
|
|
303
|
+
phase: 'clarify',
|
|
304
|
+
sessionId: request.sessionId,
|
|
305
|
+
assistantMessage: message,
|
|
306
|
+
statusText: 'Handoff governado necessario.',
|
|
307
|
+
canApply: false,
|
|
308
|
+
quickReplies: [
|
|
309
|
+
{
|
|
310
|
+
id: 'shared-rule-handoff',
|
|
311
|
+
label: 'Continuar como regra governada',
|
|
312
|
+
prompt,
|
|
313
|
+
kind: 'shared-rule-handoff',
|
|
314
|
+
description: 'Criar intake de domain-rules em vez de aplicar patch local na tabela.',
|
|
315
|
+
icon: 'rule',
|
|
316
|
+
tone: 'warning',
|
|
317
|
+
contextHints: {
|
|
318
|
+
flowId: 'shared_rule_authoring',
|
|
319
|
+
source: 'praxis-table',
|
|
320
|
+
recommendedAction: 'domain-rules/intake',
|
|
321
|
+
},
|
|
322
|
+
},
|
|
323
|
+
],
|
|
324
|
+
clarificationQuestions: [
|
|
325
|
+
{
|
|
326
|
+
id: 'table-governed-rule-confirmation',
|
|
327
|
+
type: 'confirm',
|
|
328
|
+
label: 'Deseja continuar pelo fluxo governado de regras compartilhadas?',
|
|
329
|
+
description: 'Esse caminho permite intake, simulacao, aprovacao/publicacao, materializacao e validacao de enforcement.',
|
|
330
|
+
required: true,
|
|
331
|
+
options: [
|
|
332
|
+
{
|
|
333
|
+
id: 'shared-rule-handoff',
|
|
334
|
+
label: 'Sim, continuar governado',
|
|
335
|
+
value: prompt,
|
|
336
|
+
description: 'Nao aplicar como patch local da tabela.',
|
|
337
|
+
contextHints: {
|
|
338
|
+
flowId: 'shared_rule_authoring',
|
|
339
|
+
source: 'praxis-table',
|
|
340
|
+
},
|
|
341
|
+
},
|
|
342
|
+
],
|
|
343
|
+
},
|
|
344
|
+
],
|
|
345
|
+
diagnostics: {
|
|
346
|
+
governedDecisionHandoff: {
|
|
347
|
+
flowId: 'shared_rule_authoring',
|
|
348
|
+
sourcePrompt: prompt,
|
|
349
|
+
sourceComponent: 'praxis-table',
|
|
350
|
+
},
|
|
351
|
+
},
|
|
352
|
+
};
|
|
353
|
+
}
|
|
254
354
|
optionalJsonObject(value) {
|
|
255
355
|
if (value === undefined || value === null) {
|
|
256
356
|
return undefined;
|
|
@@ -198,11 +198,12 @@ class TableAiAdapter extends BaseAiAdapter {
|
|
|
198
198
|
const actions = config.actions || {};
|
|
199
199
|
const availableFeatures = [];
|
|
200
200
|
const missingCapabilities = [];
|
|
201
|
+
const effectiveIdField = this.normalizeString(this.table.getIdField?.());
|
|
201
202
|
if (!this.table.resourcePath) {
|
|
202
203
|
availableFeatures.push('data-connection');
|
|
203
204
|
}
|
|
204
|
-
if (!
|
|
205
|
-
availableFeatures.push('
|
|
205
|
+
if (!effectiveIdField) {
|
|
206
|
+
availableFeatures.push('meta.idField');
|
|
206
207
|
}
|
|
207
208
|
if (!behavior.filtering?.enabled) {
|
|
208
209
|
availableFeatures.push('behavior.filtering');
|
|
@@ -264,14 +265,15 @@ class TableAiAdapter extends BaseAiAdapter {
|
|
|
264
265
|
authoringContract: {
|
|
265
266
|
kind: 'praxis.table.editor',
|
|
266
267
|
usesBindings: true,
|
|
267
|
-
bindingsPaths: ['bindings.resourcePath', 'bindings.
|
|
268
|
+
bindingsPaths: ['bindings.resourcePath', 'bindings.horizontalScroll'],
|
|
269
|
+
configPaths: ['meta.idField'],
|
|
268
270
|
runtimeConfigProjection: 'TableConfig',
|
|
269
271
|
},
|
|
270
272
|
availableFeatures,
|
|
271
273
|
missingCapabilities: Array.from(new Set(missingCapabilities)),
|
|
272
274
|
inputs: {
|
|
273
275
|
resourcePath: this.table.resourcePath || null,
|
|
274
|
-
idField:
|
|
276
|
+
idField: effectiveIdField || null,
|
|
275
277
|
horizontalScroll: this.table.horizontalScroll || null,
|
|
276
278
|
},
|
|
277
279
|
};
|
|
@@ -303,6 +305,13 @@ class TableAiAdapter extends BaseAiAdapter {
|
|
|
303
305
|
this.applyConfig(nextConfig);
|
|
304
306
|
return { success: true };
|
|
305
307
|
}
|
|
308
|
+
normalizeString(value) {
|
|
309
|
+
if (typeof value !== 'string') {
|
|
310
|
+
return null;
|
|
311
|
+
}
|
|
312
|
+
const normalized = value.trim();
|
|
313
|
+
return normalized ? normalized : null;
|
|
314
|
+
}
|
|
306
315
|
// -------- Context & suggestions --------
|
|
307
316
|
/**
|
|
308
317
|
* Human-friendly summary for prompt/context (columns + feature flags + data stats).
|
|
@@ -564,7 +573,7 @@ Columns Analysis:
|
|
|
564
573
|
const id = this.table.tableId || 'default';
|
|
565
574
|
const rp = this.table.resourcePath || 'default';
|
|
566
575
|
// bump version to invalidate old cached suggestions
|
|
567
|
-
return `ai-suggestions:
|
|
576
|
+
return `ai-suggestions:v4:${id}:${rp}`;
|
|
568
577
|
}
|
|
569
578
|
getColumnNames() {
|
|
570
579
|
return (this.table.config?.columns || [])
|