@ai-matrx/records-ui 0.38.0 → 0.41.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,136 @@
1
1
  # Changelog — @ai-matrx/records-ui
2
2
 
3
+ ## 0.41.0
4
+
5
+ **The last two product screens that could not work at all, rewritten against the
6
+ doors the store actually has. PRODUCTS rows 13 and 14 (lane SCREENS-2).**
7
+
8
+ Both components shipped, were exported, and were mounted NOWHERE — and neither
9
+ could have worked if it had been.
10
+
11
+ **`ChecklistRunner` kept its own store.** It was written before the store had
12
+ checklists, so it built one out of the generic work-template doors and kept the
13
+ run in a package-owned Table (`records_ui_checklist_run`) whose columns were
14
+ `step_ids` as a JSON string that `JSON.parse` decided the steps from. That is the
15
+ same defect `ActionInbox` had — a second store beside the store — and it meant the
16
+ screen could do none of the things a checklist is FOR: no roles, so no step
17
+ belonged to anybody by their part in the process; no due dates, so "day one" and
18
+ "by Friday" had nowhere to live; no dependencies, so a step could be ticked before
19
+ the one it waits for and nothing had told the store to refuse it; no requirements,
20
+ so "done" was a person clicking a word; no trigger, so a run started by hand every
21
+ time.
22
+
23
+ It is now three mounts of one component over the store's own nine checklist doors:
24
+ the **record page** (the checklists running on this record, and the templates that
25
+ could be started on it), the **table's own Checklists rail** (`ChecklistsPanel` —
26
+ the templates, the runs, the progress, and a plain-rows editor that asks
27
+ `custom.checklist_refusal` on every change so the store's sentence arrives before
28
+ the save), and the **inbox** (`MyChecklistSteps` — a checklist step is a work item,
29
+ so it reaches its owner where her approvals already are, asked through the door
30
+ that also knows what the step asks for and whether it may be finished).
31
+
32
+ Nothing is decided on the screen. `may_complete` and `refusal` are the store's
33
+ answers per step and per seat, and `blocked_by` is what tells the door's two kinds
34
+ of "no" apart: *waiting on another step*, which has no control at all, and *asks
35
+ you to say what you did*, which is the box beside the button. A screen that read
36
+ the sentence's wording would be a second opinion, and it would be the comfortable
37
+ one — the one nobody can be refused by.
38
+
39
+ **`BookingSlots` was a slot picker for a person who has no account.** It called
40
+ `tableList`, `personKernelId`, `recordWrite`, `workSlotsDeclare`, `workSlotHolds`,
41
+ `workSlotHold` and `workSlotRelease` — seven doors granted to `authenticated` —
42
+ for a VISITOR, who can reach none of them. It also built its own grid of times in
43
+ the browser from an `availability` prop, which is a second idea of what is on
44
+ offer, and declared a THIRD slots Table under its own slug beside the one
45
+ `custom.booking_declare` finds-or-makes, so a page opened through the component and
46
+ a page opened through the link protected different indexes.
47
+
48
+ It is now the owner's panel, the way `FormsPanel` is for forms: `custom.bookings`
49
+ for the pages, their four counts and the next appointment in words in the
50
+ ORGANIZATION's own zone, the visitor's link, and open/close through
51
+ `custom.anon_publish` — offered only where `custom.my_levels` answered `admin`, and
52
+ never while that door is still in flight. It mounts on the Records home (absent
53
+ when the organization has none) and on the bookings table's own rail. The picker is
54
+ the public `/b/<id>` route's, server-fed and server-lane; a suite clause fails if
55
+ any of those nine doors is ever called from here again.
56
+
57
+ **Consumer action:** `CHECKLIST_TABLE` is gone, and so is the run store it
58
+ described — a run is `custom.checklist_runs`' and its steps are work items.
59
+ `ChecklistSpec` / `ChecklistStepSpec` are no longer re-declared here; import them
60
+ from `@ai-matrx/records`, which is where the store's own judge
61
+ (`custom.checklist_refusal`) reads them from. `BookingSlots` no longer takes
62
+ `form` or `availability`; it takes an optional `tableId` and nothing else.
63
+ `ChecklistRunner`'s `seed` prop is gone — a checklist is declared through
64
+ `checklistDeclare`, whole, and judged before a single step is written.
65
+
66
+ **The proof.** `demo/checklists.test.tsx` and `demo/bookings.test.tsx` are in the
67
+ blocking gate against RECORDED REAL answers taken from the one database by
68
+ `demo/fixtures/*.record.sql`, from the `authenticated` seat, through the doors
69
+ alone, rolled back. The checklist recording is a two-seat run — an admin describes
70
+ onboarding once, a new hire record arrives, a run starts by itself, four steps land
71
+ on two real people, and the same run answers differently from each of their seats.
72
+ The booking recording is a whole lifecycle in five snapshots: open, held, booked,
73
+ rescheduled, cancelled. `src/checklists.red.tsx` and `src/bookings.red.tsx` are the
74
+ red twins; all six clauses fail on these bytes.
75
+
76
+ ## 0.40.0
77
+
78
+ **Pressing "Settings" on a table crashed the whole page, and had since the
79
+ enrichment panel was added.**
80
+
81
+ Lane LAND-SCREENS pressed it in a production build of the app, signed in as the
82
+ admin who owns the table, and the route went to the application's global error
83
+ boundary with React #310 — *"Rendered more hooks than during the previous render."*
84
+ Everything on that panel went with it: rename the table, add a column, take one
85
+ off, reorder, delete the table, and the enrichment panel itself, which lives behind
86
+ a column's own row and was therefore unreachable in the shipped build.
87
+
88
+ **The cause, and why no suite saw it.** `TableSettings` declared `useState` for the
89
+ enrichment panel BELOW three early returns, one of which fires on the FIRST render
90
+ of every real mount: a host that lets the store decide rights binds no `rights`
91
+ port, so `useTableRights(table.data)` answers `NO_RIGHTS` until `useTable` and
92
+ `custom.my_level` come back. Render one ran eight hooks and returned the "you may
93
+ not change the structure" line; render two, a moment later, ran nine. Every test in
94
+ this package binds `rights: () => tableRightsAt("admin")`, which never takes that
95
+ return — so the panel was only ever rendered with nine hooks and the order never
96
+ changed.
97
+
98
+ `src/TableSettings.hooks.test.tsx` mounts the panel with NO rights port, which is
99
+ the seat the product actually uses, and fails with that exact error on the previous
100
+ hook order.
101
+
102
+ Also: `src/form-publish.test.tsx` had two TS7006 implicit-`any` parameters that had
103
+ `tsc --noEmit` red on this package on `main`. Typed; the package typechecks clean.
104
+
105
+ ## 0.39.0
106
+
107
+ **The kanban view becomes the board, with the store judging every drag.**
108
+
109
+ `PipelineBoard` renders THROUGH the view that already exists — `ViewSwitcher`'s
110
+ kanban layout — rather than beside it. It draws the very same rows the view holds;
111
+ what it adds is the store's judgement.
112
+
113
+ * **Drag between columns.** A drop asks `custom.pipeline_transition_refusal` first
114
+ and either writes the move or leaves the card exactly where it was, carrying the
115
+ store's own sentence, verbatim. Nothing is written on a refusal, so there is no
116
+ snap-back to animate — the card never moved.
117
+ * **A stage's demands, prompted on the way in.** When the refusal names the columns
118
+ a stage needs, they appear on the card with a field each and one button, so the
119
+ person finishes the move instead of being sent away from it. Until every demand is
120
+ answered there is no button to press, rather than one that looks live.
121
+ * **Column headings carry the store's numbers** — the count, the chosen measure's
122
+ total, and the column's limit — over every record this person may see, not over
123
+ the page the screen happened to load. Which column is totalled is a fact about the
124
+ VIEW, saved on it like its colours.
125
+ * **A work-in-progress limit shows on the column it belongs to**, and a column over
126
+ its limit says so in a sentence rather than only turning red.
127
+ * **A viewer's card has no drag handle at all.** Absent rather than dead.
128
+
129
+ A table that is not a pipeline draws the plain kanban exactly as before; the
130
+ decision is the Table's own `stage_field`, asked once, never guessed from the shape
131
+ of a Choice column.
132
+
133
+
3
134
 
4
135
 
5
136
  ## 0.38.0 — 2026-09-20