@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.
Files changed (38) hide show
  1. package/README.md +150 -8
  2. package/docs/DSL-Extensions-Guide.md +23 -0
  3. package/docs/adr/2026-03-dynamic-filter-cross-lib-coupling.md +107 -0
  4. package/docs/adr/2026-03-filter-drawer-adapter-light-entrypoint.md +105 -0
  5. package/docs/adr/2026-03-table-editor-idfield-decision.md +85 -0
  6. package/docs/column-resize-reorder-implementation-plan.md +338 -0
  7. package/docs/column-resize-reorder-review-prompt.md +34 -0
  8. package/docs/dynamic-filter-architecture-overview.md +207 -0
  9. package/docs/dynamic-filter-backend-contract-cheatsheet.md +167 -0
  10. package/docs/dynamic-filter-editor-settings-guide.md +229 -0
  11. package/docs/dynamic-filter-host-integration-guide.md +217 -0
  12. package/docs/dynamic-filter-payload-contract.md +331 -0
  13. package/docs/dynamic-filter-range-filters-guide.md +289 -0
  14. package/docs/dynamic-filter-troubleshooting-guide.md +220 -0
  15. package/docs/dynamic-inline-filter-catalog.md +147 -0
  16. package/docs/e2e-column-drag-playwright.md +62 -0
  17. package/docs/expandable-rows-enterprise-big-leagues-plan.md +1080 -0
  18. package/docs/json-logic-operators-and-helpers.md +57 -0
  19. package/docs/local-data-mode-precedence.md +12 -0
  20. package/docs/local-data-pre-implementation-baseline.md +22 -0
  21. package/docs/local-data-preimplementation-go-no-go.md +39 -0
  22. package/docs/local-data-support-implementation-plan.md +524 -0
  23. package/docs/local-data-support-pr-package.md +66 -0
  24. package/docs/localization-persistence-merge.md +22 -0
  25. package/docs/performance-hardening-v2-implementation-plan.md +479 -0
  26. package/docs/playground-scenario-curation-plan.md +482 -0
  27. package/docs/playground-scenario-second-opinion-prompt.md +121 -0
  28. package/docs/playground-scenario-second-opinion-review.md +234 -0
  29. package/docs/release-notes-p1-hardening.md +76 -0
  30. package/docs/table-authoring-document-completeness-checklist.md +120 -0
  31. package/docs/table-editor-capability-review-prompt.md +349 -0
  32. package/docs/visual-rules-editor-transition.md +29 -0
  33. package/fesm2022/{praxisui-table-table-agentic-authoring-turn-flow-tu7jtTwV.mjs → praxisui-table-table-agentic-authoring-turn-flow-DRuE55Mi.mjs} +100 -0
  34. package/fesm2022/{praxisui-table-table-ai.adapter-DxjDaQqy.mjs → praxisui-table-table-ai.adapter-fS74fZ7o.mjs} +14 -5
  35. package/fesm2022/praxisui-table.mjs +5317 -736
  36. package/index.d.ts +325 -106
  37. package/package.json +15 -9
  38. package/src/lib/praxis-table.json-api.md +1325 -0
@@ -0,0 +1,66 @@
1
+ # Pacote de PR - Local Data Support + Gate Karma
2
+
3
+ ## Objetivo do pacote
4
+ Consolidar o estado pronto para PR da trilha de suporte local/remote da `praxis-table`, com evidencias de validacao e operacao de testes no WSL/Windows.
5
+
6
+ ## Escopo consolidado
7
+ 1. `praxis-crud` com suporte a `metadata.data` sem `resource.path`, preservando precedencia remoto > local.
8
+ 2. Hardening da lane isolada da `praxis-table` no WSL (wrapper/probe Chromium).
9
+ 3. Runner de gate seguro (`tools/karma/run-safe-gate.sh`) com modo estrito WSL e opcao de suite full da `praxis-table`.
10
+ 4. Revalidacao final do gate com trilha primaria WSL e suites completas verdes.
11
+
12
+ ## Commits da etapa
13
+ 1. `7855fb9` feat(praxis-crud): suportar modo local via metadata.data sem resource.path
14
+ 2. `cc17ef8` test(praxis-crud): garantir precedencia resourcePath sobre metadata.data
15
+ 3. `99f5be9` docs(praxis-crud): alinhar contrato local/remote em metadata e hints
16
+ 4. `accf85b` test(praxis-crud): estabiliza specs para injeção e contrato de metadata
17
+ 5. `f9eac2c` docs(praxis-table): atualizar status do gate seguro de validacao
18
+ 6. `93d59dc` chore(karma): add safe gate runner for table+crud
19
+ 7. `0086e4c` test(praxis-table): estabiliza specs pendentes e fecha suíte
20
+ 8. `4e95076` test(praxis-table): expand shared TestBed provider coverage
21
+ 9. `e545355` docs(praxis-table): atualizar status de validacao pos-hardening
22
+ 10. `186e367` chore(karma): add WSL chromium probe wrapper for preimpl lane
23
+ 11. `3951fab` docs(praxis-table): registrar revalidacao do safe gate
24
+ 12. `73e7160` chore(karma): auto-configure WSL chromium wrapper in safe gate
25
+ 13. `7a8e0d4` test(praxis-crud): cobrir precedencia de resourcePath fallback
26
+ 14. `d84c49d` docs(praxis-table): registrar safe-gate com crud 32 success
27
+ 15. `5d0a335` docs(praxis-table): registrar full suite 372 success apos safe-gate
28
+ 16. `0c0f55a` chore(karma): auto-fallback to chromium wrapper in preimpl lane
29
+ 17. `f7fe073` chore(karma): log resolved real chromium in preimpl lane
30
+ 18. `1857a87` docs(praxis-table): registrar gate estrito com full suite verde
31
+ 19. `b7d6782` docs(karma): document strict WSL safe-gate modes
32
+
33
+ ## Validacoes executadas (gate operacional)
34
+ 1. `bash ./scripts/test-table-preimpl-lane.sh`
35
+ - Resultado: `TOTAL: 48 SUCCESS`.
36
+ 2. `bash tools/karma/run-safe-gate.sh`
37
+ - Resultado: `praxis-table lane PASS (48 SUCCESS)` e `praxis-crud full PASS (32 SUCCESS)`.
38
+ 3. `SAFE_GATE_STRICT_WSL_PRIMARY=true SAFE_GATE_INCLUDE_TABLE_FULL=true bash tools/karma/run-safe-gate.sh`
39
+ - Resultado: `praxis-table lane PASS (48 SUCCESS)`, `praxis-table lane path: wsl-primary`, `praxis-crud full PASS (32 SUCCESS)`, `praxis-table full PASS (372 SUCCESS)`.
40
+
41
+ ## Cobertura critica confirmada
42
+ 1. Preservacao de `pageSize` local (override do usuario)
43
+ - Spec: `projects/praxis-table/src/lib/praxis-table.local-runtime.spec.ts` (`preserves user-selected pageSize in local mode during data source sync`).
44
+ 2. Estabilidade de `fieldMetadata` em modo local
45
+ - Spec: `projects/praxis-table/src/lib/praxis-table.local-runtime.spec.ts` (`keeps local fieldMetadata reference stable when config is unchanged`).
46
+
47
+ ## Risco residual atual
48
+ 1. Sem bloqueador funcional imediato identificado no gate atual.
49
+ 2. Aviso nao bloqueante em build de testes: `baseline-browser-mapping` desatualizado.
50
+
51
+ ## Evidencia MCP (Angular CLI MCP)
52
+ 1. Ferramentas listadas via MCP smoke inline:
53
+ - `get_best_practices`
54
+ - `search_documentation`
55
+ - `list_projects`
56
+ 2. Recomendacoes aplicadas ao pacote:
57
+ - manter validacao focada e reproduzivel via `ng test` com `--include` por suite/arquivo;
58
+ - preferir setup de testes centralizado e reutilizavel (consolidacao de providers compartilhados no hardening dos integration tests);
59
+ - manter contratos e comportamento com regressao protegida por specs dedicadas (precedencia `resourcePath > data`, transicoes local/remote/empty);
60
+ - executar gate com comandos explicitos e deterministicos (modo estrito WSL + suite full opcional).
61
+ 3. Referencias oficiais retornadas por `search_documentation`:
62
+ - https://angular.dev/cli/test#options
63
+ - https://angular.dev/guide/testing/utility-apis
64
+
65
+ ## Nota operacional
66
+ O workspace atual usa `npm run mcp:smoke` e `npm run mcp:tools` via `scripts/mcp-smoke.js` para validar o Angular CLI MCP. A trilha Chrome DevTools continua separada em `npm run mcp:devtools:*`. A validacao MCP tambem pode ser executada por cliente inline (`@modelcontextprotocol/sdk`) conectando em `npx -y @angular/cli mcp`.
@@ -0,0 +1,22 @@
1
+ # Localization and Persistence Merge
2
+
3
+ `PraxisTable` hydrates persisted `table-config:*` snapshots by merging them on top of the current host `config`.
4
+
5
+ This preserves newer host-provided fields that may not exist in older persisted snapshots, including:
6
+
7
+ - `localization.locale`
8
+ - `localization.dateTime`
9
+ - `localization.currency`
10
+ - `localization.number`
11
+
12
+ Practical consequence:
13
+
14
+ - a consumer can add localization settings in a newer release
15
+ - older persisted table snapshots keep their saved preferences
16
+ - missing localization fields are inherited from the current host input instead of being erased by the persisted snapshot
17
+
18
+ This behavior is especially important for cross-host scenarios such as:
19
+
20
+ - `praxis-crud` forwarding `metadata.table` into `praxis-table`
21
+ - published playgrounds and examples that reuse older persisted table state
22
+ - enterprise hosts with locale-specific number and currency conventions
@@ -0,0 +1,479 @@
1
+ # Praxis Table Performance Hardening V2 Implementation Plan
2
+
3
+ ## Objective
4
+
5
+ Execute the first two cuts of the `praxis-table` performance hardening plan without changing workspace configuration and without introducing public compatibility knobs too early.
6
+
7
+ The immediate goal is to make the runtime safe for enterprise grids by:
8
+
9
+ 1. making the render path side-effect free;
10
+ 2. creating instrumentation that proves the current and improved behavior;
11
+ 3. preparing the table for on-demand contextual discovery without visual instability;
12
+ 4. keeping the correction in the canonical table runtime, not in host apps.
13
+
14
+ This plan covers only:
15
+
16
+ - `Cut 0`: observability and performance budgets
17
+ - `Cut 1`: removing discovery side effects from the render path
18
+
19
+ It intentionally does **not** yet implement:
20
+
21
+ - a new public performance API;
22
+ - scheduler/concurrency orchestration;
23
+ - backend contract changes;
24
+ - broad UX redesign of row actions.
25
+
26
+ For clarity, this is an implementation-ready internal plan for the canonical table runtime.
27
+ It is not yet a public consumer contract change.
28
+
29
+ ---
30
+
31
+ ## Executive Decision
32
+
33
+ The canonical default direction for enterprise is:
34
+
35
+ - collection-level capabilities remain eager;
36
+ - item-level capabilities/actions move toward on-demand;
37
+ - row/render code must not trigger network discovery;
38
+ - layout stability and accessibility are first-class acceptance criteria, not follow-up polish.
39
+
40
+ ---
41
+
42
+ ## Current Runtime Problems
43
+
44
+ The current table still mixes rendering and discovery:
45
+
46
+ - `fetchData()` triggers `prefetchRowDiscovery(page.content)` in [praxis-table.ts](/D:/Developer/praxis-plataform/praxis-ui-angular/projects/praxis-table/src/lib/praxis-table.ts)
47
+ - `prefetchRowDiscovery()` loops through visible rows and calls `ensureRowDiscovery(row)`
48
+ - `ensureRowDiscovery()` triggers item-level `capabilities` and `actions`
49
+ - `getResolvedRowActions(row)` also calls `ensureRowDiscovery(row)` in the render path
50
+
51
+ That creates three categories of cost:
52
+
53
+ 1. network fan-out for each visible row;
54
+ 2. change-detection churn because each completion calls `markForCheck()`;
55
+ 3. unstable runtime semantics because template reads can mutate runtime state.
56
+
57
+ In enterprise scenarios this gets worse under:
58
+
59
+ - pagination, filtering and sorting;
60
+ - multiple grids on the same screen;
61
+ - remote multi-tenant hosts;
62
+ - slower networks and session-scoped permissions.
63
+
64
+ ---
65
+
66
+ ## Guiding Principles
67
+
68
+ - Render-time getters must be pure.
69
+ - Discovery must be event-driven or policy-driven, never template-driven.
70
+ - Instrumentation comes before optimization guesses.
71
+ - Layout must stay stable while contextual affordances are unresolved.
72
+ - Accessibility states must distinguish `loading`, `blocked`, `error`, and `ready`.
73
+ - Session cache and visual runtime state must be modeled separately.
74
+ - No premature public flags. Stabilize canonical internal behavior first.
75
+
76
+ ---
77
+
78
+ ## Scope and Impact Map
79
+
80
+ ### Canonical subproject affected
81
+
82
+ - [praxis-table](/D:/Developer/praxis-plataform/praxis-ui-angular/projects/praxis-table)
83
+
84
+ ### Consumers impacted
85
+
86
+ - [praxis-crud](/D:/Developer/praxis-plataform/praxis-ui-angular/projects/praxis-crud)
87
+ - the remote host lab in [quickstart-remote-metadata-lab.page.ts](/D:/Developer/praxis-plataform/praxis-ui-angular/src/app/features/quickstart-remote-metadata-lab/quickstart-remote-metadata-lab.page.ts)
88
+
89
+ ### Public docs potentially affected
90
+
91
+ - [README.md](/D:/Developer/praxis-plataform/praxis-ui-angular/projects/praxis-table/README.md)
92
+ - [praxis-table.json-api.md](/D:/Developer/praxis-plataform/praxis-ui-angular/projects/praxis-table/src/lib/praxis-table.json-api.md)
93
+
94
+ For Cuts 0 and 1, documentation updates are expected to stay in internal planning/test notes unless implementation changes observable runtime behavior.
95
+
96
+ ### Tests and validations minimally required
97
+
98
+ - focused specs in `praxis-table`
99
+ - focused regression in `praxis-crud` only if row action integration changes
100
+ - `npm run build:praxis-table`
101
+ - remote/browser proof only after the code cuts, not during planning
102
+
103
+ ### Breaking-change risk
104
+
105
+ - low if changes remain internal and preserve current row actions behavior
106
+ - medium if a hidden reliance on render-triggered discovery exists in current templates/integration tests
107
+
108
+ ---
109
+
110
+ ## Cut 0: Observability and Budgets
111
+
112
+ ## Goal
113
+
114
+ Add instrumentation that makes current row discovery cost measurable before behavior is changed.
115
+
116
+ ## Required outcomes
117
+
118
+ 1. We can count item-level discovery requests per table session.
119
+ 2. We can distinguish:
120
+ - discovery requested
121
+ - discovery served from cache
122
+ - discovery completed
123
+ - discovery failed
124
+ 3. We can inspect row contextual runtime state without relying on network logs.
125
+ 4. We can define initial budgets and assert against them in tests.
126
+
127
+ ## Canonical budgets for Cut 0
128
+
129
+ These are initial engineering budgets, not final SLAs:
130
+
131
+ - no more than `1` discovery trigger per row/rel while an identical request is in flight
132
+ - no more than `1` item-level discovery request per rel/href inside the freshness window
133
+ - no implicit discovery from render-time getters
134
+ - remote load of a page with 10 rows must not enqueue more discovery work than the current explicit policy allows
135
+
136
+ These cuts must also define initial perception budgets for enterprise validation:
137
+
138
+ - contextual row affordance must expose a visible `loading-context` state immediately when user-triggered discovery starts
139
+ - row action area must remain layout-stable while contextual discovery is pending
140
+ - row expansion/detail entry must distinguish `loading-context`, `blocked-semantic`, and `error-transient`
141
+ - no focusable control may disappear from under keyboard focus during contextual resolution
142
+
143
+ Budgets to measure and expose internally:
144
+
145
+ - `rowDiscoveryRequestedCount`
146
+ - `rowDiscoveryNetworkCount`
147
+ - `rowDiscoveryCacheHitCount`
148
+ - `rowDiscoveryFailureCount`
149
+ - `rowDiscoveryInFlightCount`
150
+ - `rowDiscoveryLastResolvedAt`
151
+ - `rowDiscoveryPendingRowCount`
152
+ - `rowDiscoveryUserTriggeredCount`
153
+ - `rowDiscoveryPrefetchCount`
154
+
155
+ Initial measurable thresholds to freeze for Cuts 0 and 1:
156
+
157
+ - repeated evaluation of row-action getters for the same row must add `0` new network requests
158
+ - a single explicit row interaction must start at most `1` capability request and `1` action-catalog request for that row/interaction cycle
159
+
160
+ ## Planned write set
161
+
162
+ Primary files:
163
+
164
+ - [praxis-table.ts](/D:/Developer/praxis-plataform/praxis-ui-angular/projects/praxis-table/src/lib/praxis-table.ts)
165
+ - [praxis-table.html](/D:/Developer/praxis-plataform/praxis-ui-angular/projects/praxis-table/src/lib/praxis-table.html) if instrumentation is surfaced through loading-state affordances used in focused tests
166
+ - [praxis-table.remote-regression.spec.ts](/D:/Developer/praxis-plataform/praxis-ui-angular/projects/praxis-table/src/lib/praxis-table.remote-regression.spec.ts)
167
+ - potentially one new focused spec file near the table runtime if it improves isolation
168
+
169
+ Optional if needed for test support:
170
+
171
+ - [README.md](/D:/Developer/praxis-plataform/praxis-ui-angular/projects/praxis-table/README.md)
172
+
173
+ ## Implementation tasks
174
+
175
+ ### 0.1 Introduce internal row discovery metrics state
176
+
177
+ Add an internal structure in `PraxisTable` dedicated to diagnostics/observability for row discovery.
178
+
179
+ It should capture at least:
180
+
181
+ - total requested by rel
182
+ - total served from cache by rel
183
+ - total completed by rel
184
+ - total failed by rel
185
+ - current in-flight href count
186
+
187
+ This must remain internal runtime state for now.
188
+
189
+ ### 0.2 Add explicit instrumentation points
190
+
191
+ Instrument the following events:
192
+
193
+ - prefetch scheduled
194
+ - on-demand discovery scheduled
195
+ - cache hit
196
+ - request started
197
+ - request resolved
198
+ - request failed
199
+
200
+ Instrumentation should attach enough context to debug:
201
+
202
+ - `tableId`
203
+ - `resourcePath`
204
+ - `rel`
205
+ - `href`
206
+ - source:
207
+ - `prefetch`
208
+ - `row-action`
209
+ - `expansion`
210
+ - future sources can be added later
211
+
212
+ ### 0.3 Add a debug snapshot accessor
213
+
214
+ Expose an internal/debug-friendly snapshot method or readonly getter on the component that tests can inspect.
215
+
216
+ This is not a new public API for consumers. It is a runtime diagnostic surface for focused specs.
217
+
218
+ Recommended contents:
219
+
220
+ - metrics counters
221
+ - current policy decisions
222
+ - number of cached hrefs
223
+ - number of pending hrefs
224
+
225
+ Implementation constraint:
226
+
227
+ - prefer a clearly internal debug accessor/helper used only by focused specs
228
+ - do not export a new public symbol from `public-api.ts`
229
+ - do not document this accessor as a supported consumer contract
230
+
231
+ ### 0.4 Encode the initial budgets in tests
232
+
233
+ Focused specs should prove:
234
+
235
+ - dedupe works while requests are in flight
236
+ - repeated reads inside TTL count as cache hits rather than network hits
237
+ - current explicit prefetch policy is visible in diagnostics
238
+ - user-triggered discovery transitions the runtime into a distinct `loading-context` state
239
+ - loading/blocked/error states are distinguishable in runtime diagnostics
240
+
241
+ ## Focused tests for Cut 0
242
+
243
+ Primary:
244
+
245
+ - add/update a focused spec around row discovery metrics in `praxis-table`
246
+ - keep or extend [praxis-table.remote-regression.spec.ts](/D:/Developer/praxis-plataform/praxis-ui-angular/projects/praxis-table/src/lib/praxis-table.remote-regression.spec.ts)
247
+
248
+ Suggested test cases:
249
+
250
+ 1. `records a single network discovery for repeated same-href capability requests`
251
+ 2. `records cache hit for repeated row capability read inside TTL`
252
+ 3. `distinguishes prefetch and on-demand discovery sources`
253
+ 4. `does not increment network count when href is already in flight`
254
+ 5. `records pending contextual rows and loading-context transitions for user-triggered discovery`
255
+
256
+ ## Acceptance criteria for Cut 0
257
+
258
+ - row discovery metrics are available in focused tests
259
+ - dedupe and cache hit behavior are asserted by tests
260
+ - runtime diagnostics distinguish `idle`, `loading-context`, `ready`, `blocked-semantic`, and `error-transient`
261
+ - no workspace config changes
262
+ - no public API contract is introduced yet
263
+
264
+ ---
265
+
266
+ ## Cut 1: Remove Side Effects From the Render Path
267
+
268
+ ## Goal
269
+
270
+ Make render-time reads pure by removing discovery-triggering side effects from row action resolution.
271
+
272
+ ## Required outcomes
273
+
274
+ 1. Template-driven calls must no longer trigger network work.
275
+ 2. Row discovery must be triggered only from explicit runtime entrypoints.
276
+ 3. Existing visual affordances should continue to work, using already-resolved state.
277
+ 4. This cut should not yet force the final on-demand UX policy; it only removes the structural flaw.
278
+
279
+ ## Planned write set
280
+
281
+ Primary files:
282
+
283
+ - [praxis-table.ts](/D:/Developer/praxis-plataform/praxis-ui-angular/projects/praxis-table/src/lib/praxis-table.ts)
284
+ - [praxis-table.html](/D:/Developer/praxis-plataform/praxis-ui-angular/projects/praxis-table/src/lib/praxis-table.html)
285
+ - [praxis-table.scss](/D:/Developer/praxis-plataform/praxis-ui-angular/projects/praxis-table/src/lib/praxis-table.scss) when needed to keep row affordance layout stable during unresolved contextual discovery
286
+ - [praxis-table.remote-regression.spec.ts](/D:/Developer/praxis-plataform/praxis-ui-angular/projects/praxis-table/src/lib/praxis-table.remote-regression.spec.ts)
287
+ - [praxis-crud.component.spec.ts](/D:/Developer/praxis-plataform/praxis-ui-angular/projects/praxis-crud/src/lib/praxis-crud.component.spec.ts) only if host interaction assumptions change
288
+
289
+ Potential supporting docs after implementation:
290
+
291
+ - [README.md](/D:/Developer/praxis-plataform/praxis-ui-angular/projects/praxis-table/README.md)
292
+
293
+ ## Implementation tasks
294
+
295
+ ### 1.1 Remove `ensureRowDiscovery(row)` from render-time action resolution
296
+
297
+ Target the current call path rooted in `getResolvedRowActions(row)`.
298
+
299
+ After this cut:
300
+
301
+ - `getResolvedRowActions(row)` must only derive from current row runtime state
302
+ - `getVisibleRowActions(row)`, `getInlineRowActions(row)`, `getOverflowRowActions(row)` must stay pure
303
+
304
+ ### 1.2 Introduce explicit runtime trigger points
305
+
306
+ Create explicit discovery trigger methods with named intent, for example:
307
+
308
+ - trigger discovery for row overflow-menu open intent
309
+ - trigger discovery for explicit row workflow interaction only when the action is already surfaced by resolved runtime state
310
+ - keep expansion-triggered discovery in expansion flow only
311
+
312
+ These methods should become the only legal entrypoints for row item discovery until the scheduler cut.
313
+
314
+ For avoidance of ambiguity, the expected concrete UI/runtime anchor points are:
315
+
316
+ - row expansion trigger from the expander control rendered in [praxis-table.html](/D:/Developer/praxis-plataform/praxis-ui-angular/projects/praxis-table/src/lib/praxis-table.html) around the `_expander` column and its `aria-expanded` toggle
317
+ - row overflow contextual actions from the overflow menu trigger rendered in the row actions cell in [praxis-table.html](/D:/Developer/praxis-plataform/praxis-ui-angular/projects/praxis-table/src/lib/praxis-table.html), currently using `matMenuTriggerFor` and the `more_vert` icon
318
+ - runtime handlers must live in [praxis-table.ts](/D:/Developer/praxis-plataform/praxis-ui-angular/projects/praxis-table/src/lib/praxis-table.ts) rather than in template-side incidental calls
319
+
320
+ For Cut 1, freeze the trigger policy explicitly:
321
+
322
+ - allowed:
323
+ - expansion toggle in `hypermedia` mode
324
+ - row overflow menu open
325
+ - explicit workflow interaction when the row runtime already exposed that affordance
326
+ - not allowed:
327
+ - plain row render
328
+ - repeated getter evaluation
329
+ - hover-only discovery
330
+ - passive focus traversal that is not an explicit user intent to inspect contextual actions
331
+
332
+ These entrypoints must also set explicit runtime states that future UX can rely on:
333
+
334
+ - `loading-context`
335
+ - `ready`
336
+ - `blocked-semantic`
337
+ - `error-transient`
338
+
339
+ ### 1.3 Preserve current behavior using already-known state
340
+
341
+ If row discovery has not run yet:
342
+
343
+ - configured CRUD actions should still render according to existing fallback behavior
344
+ - discovered workflow actions should only appear after explicit resolution
345
+ - unresolved contextual affordances must keep a stable reserved area in the row action layout
346
+ - unresolved contextual affordances must not masquerade as `no actions available`
347
+
348
+ This prevents the cut from accidentally breaking baseline CRUD affordances while removing the side effect.
349
+
350
+ ### 1.4 Add temporary guardrails for accidental regressions
351
+
352
+ Add a diagnostic assertion pattern in tests that proves repeated rendering/getter access does not change discovery counters.
353
+
354
+ This is the key regression guard for the cut.
355
+
356
+ Also add guardrails for UX/accessibility regressions:
357
+
358
+ - keyboard focus remains on a stable trigger while discovery is pending
359
+ - loading state is represented distinctly from semantic unavailability
360
+ - row action area does not collapse/reflow when contextual state changes
361
+
362
+ ## Focused tests for Cut 1
363
+
364
+ Suggested cases:
365
+
366
+ 1. `render-time row action getters do not trigger discovery`
367
+ 2. `opening contextual row affordance triggers discovery exactly once`
368
+ 3. `expansion hypermedia still resolves capabilities on demand when expanded`
369
+ 4. `configured CRUD row actions remain visible without implicit discovery`
370
+ 5. `discovered workflow row actions appear only after explicit contextual resolution`
371
+ 6. `row action area stays layout-stable while contextual discovery is pending`
372
+ 7. `contextual loading state is distinguishable from blocked or transient error states`
373
+
374
+ If needed, split tests into:
375
+
376
+ - pure table runtime spec
377
+ - remote regression spec
378
+
379
+ ## Acceptance criteria for Cut 1
380
+
381
+ - template/read getters are side-effect free
382
+ - no discovery is triggered during plain render
383
+ - explicit interaction still triggers discovery
384
+ - expansion hypermedia behavior remains on-demand
385
+ - focused tests prove the difference between render and interaction paths
386
+ - row affordance area stays visually stable while contextual discovery is unresolved
387
+ - contextual interaction exposes an explicit `loading-context` state
388
+ - contextual failure does not silently degrade into `no actions`
389
+ - no focusable affordance disappears from under keyboard focus during contextual resolution
390
+ - render/getter re-evaluation alone adds `0` new discovery requests for the same row
391
+ - a single overflow-menu open or expansion toggle does not fan out into repeated duplicate requests for the same row/rel while one is already in flight
392
+
393
+ ---
394
+
395
+ ## Design Constraints for Cuts 0 and 1
396
+
397
+ These constraints must be respected now even if some of them are fully exercised only in later cuts.
398
+
399
+ ### Layout stability
400
+
401
+ - do not make row action width depend on late-arriving discovery in a way that causes visible reflow
402
+ - prefer existing configured actions plus later enrichment over inserting/removing controls unpredictably
403
+
404
+ ### Accessibility
405
+
406
+ - do not make focusable controls disappear from under focus
407
+ - if interaction-triggered loading is introduced in templates, it must be announced in the same implementation slice
408
+ - do not conflate `loading` with `blocked`
409
+ - degraded discovery states must remain perceivable for keyboard and assistive-tech users
410
+
411
+ ### Degraded UX contract
412
+
413
+ - `loading-context`: user-triggered contextual resolution is pending
414
+ - `blocked-semantic`: backend resolved the context and denied the affordance semantically
415
+ - `error-transient`: contextual discovery failed or timed out and can be retried
416
+ - `ready`: contextual discovery completed and affordances are stable
417
+
418
+ These states must be explicit in runtime/test diagnostics even if the final UX chrome evolves later.
419
+
420
+ ### Cache semantics
421
+
422
+ - do not redesign the full cache in Cut 1
423
+ - but do not add new logic that further mixes:
424
+ - session cache
425
+ - current-page visual state
426
+ - in-flight requests
427
+
428
+ ### Future compatibility
429
+
430
+ - Cut 1 must make it easier, not harder, to add:
431
+ - row runtime state materialization
432
+ - concurrency scheduler
433
+ - context-aware cache keys
434
+ - viewport-aware discovery
435
+
436
+ ---
437
+
438
+ ## Validation Strategy
439
+
440
+ Minimal validation for implementation of these cuts:
441
+
442
+ 1. focused specs in `praxis-table`
443
+ 2. `npm run build:praxis-table`
444
+ 3. only if host integration changes are affected, focused specs in `praxis-crud`
445
+
446
+ Not required for these cuts by default:
447
+
448
+ - full workspace suite
449
+ - remote browser proof
450
+ - backend changes
451
+
452
+ If validation is partial, the implementation handoff must state exactly which focused specs were run.
453
+
454
+ Recommended escalation only if a focused regression becomes ambiguous:
455
+
456
+ - one browser-level proof in the remote lab after Cut 1 to confirm row action/menu behavior did not drift visually
457
+
458
+ ---
459
+
460
+ ## Not In Scope Yet
461
+
462
+ - scheduler with concurrency limit
463
+ - visual skeleton redesign for row menus
464
+ - context-aware cache key including tenant/principal/locale
465
+ - backend aggregation of row affordances
466
+ - new public config flags for prefetch policies
467
+
468
+ These belong to later cuts after Cuts 0 and 1 are stable.
469
+
470
+ ---
471
+
472
+ ## Exit Condition
473
+
474
+ This plan is ready to execute when:
475
+
476
+ 1. focused implementation starts in `praxis-table`;
477
+ 2. Cut 0 metrics are in place;
478
+ 3. Cut 1 removes render-path side effects without breaking baseline CRUD row affordances;
479
+ 4. the Cut 1 write set and tests explicitly cover runtime states, layout stability, and non-silent degraded UX.