@ai-matrx/records 0.93.2 → 0.93.4

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 (72) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/dist/{client-BKhJ6Ezn.d.ts → client-DM3dRewB.d.ts} +8 -8
  3. package/dist/{client-DJFcYJ8I.d.cts → client-icpxhaRE.d.cts} +8 -8
  4. package/dist/core/index.d.cts +50 -17
  5. package/dist/core/index.d.ts +50 -17
  6. package/dist/data/index.d.cts +11 -11
  7. package/dist/data/index.d.ts +11 -11
  8. package/dist/{declareTable-y5e-Qasq.d.cts → declareTable-BtpsSJCr.d.cts} +4 -4
  9. package/dist/{declareTable-BVvld0W6.d.ts → declareTable-MN4WuhWK.d.ts} +4 -4
  10. package/dist/entity/index.d.cts +7 -7
  11. package/dist/entity/index.d.ts +7 -7
  12. package/dist/{field-GR--cya9.d.ts → field-D-1OKy5r.d.ts} +1 -1
  13. package/dist/{field-F9BK-aUO.d.cts → field-DjS7iId2.d.cts} +1 -1
  14. package/dist/first-page/index.cjs +10 -6659
  15. package/dist/first-page/index.cjs.map +1 -1
  16. package/dist/first-page/index.d.cts +1097 -12
  17. package/dist/first-page/index.d.ts +1097 -12
  18. package/dist/first-page/index.js +4 -6646
  19. package/dist/first-page/index.js.map +1 -1
  20. package/dist/forms/index.d.cts +3 -3
  21. package/dist/forms/index.d.ts +3 -3
  22. package/dist/index.d.cts +12 -12
  23. package/dist/index.d.ts +12 -12
  24. package/dist/memory/index.d.cts +7 -7
  25. package/dist/memory/index.d.ts +7 -7
  26. package/dist/{objectOrganization-Cec0G7mm.d.cts → objectOrganization-CDAoE7Ft.d.cts} +1 -1
  27. package/dist/{objectOrganization-C2RtRmci.d.ts → objectOrganization-IBxZqFZQ.d.ts} +1 -1
  28. package/dist/{port-CiDvXxG7.d.cts → port-B3UeC536.d.cts} +3 -3
  29. package/dist/{port-Bhl_rn5k.d.ts → port-DyZ0GfxE.d.ts} +3 -3
  30. package/dist/{portal-CL2Qtc-G.d.cts → portal-CUwIsXsx.d.cts} +1 -1
  31. package/dist/{portal-o9FhryoU.d.ts → portal-DDOmQR1f.d.ts} +1 -1
  32. package/dist/{ports-BTDZ9ydi.d.cts → ports-DEkN-WfA.d.cts} +3 -3
  33. package/dist/{ports-CCPhsr-V.d.ts → ports-YOhD5T7h.d.ts} +3 -3
  34. package/dist/questions/index.d.cts +9 -9
  35. package/dist/questions/index.d.ts +9 -9
  36. package/dist/realtime/index.d.cts +3 -3
  37. package/dist/realtime/index.d.ts +3 -3
  38. package/dist/{record-Bo1ahH3_.d.cts → record-zwSBU5PQ.d.cts} +1 -1
  39. package/dist/{record-Bo1ahH3_.d.ts → record-zwSBU5PQ.d.ts} +1 -1
  40. package/dist/{relation-BTww_Cby.d.cts → relation-BbPDcXp5.d.cts} +2 -2
  41. package/dist/{relation-D8UmOxPh.d.ts → relation-Dk9-VzY0.d.ts} +2 -2
  42. package/dist/{rule-BojwTDvi.d.ts → rule-BVX1C83I.d.ts} +1 -1
  43. package/dist/{rule-G4UQndi-.d.cts → rule-CbBXN-FW.d.cts} +1 -1
  44. package/dist/search/index.d.cts +1 -1
  45. package/dist/search/index.d.ts +1 -1
  46. package/dist/setup/index.d.cts +12 -12
  47. package/dist/setup/index.d.ts +12 -12
  48. package/dist/{subscription-1ik9orQK.d.ts → subscription-DucBLG-Y.d.ts} +3 -3
  49. package/dist/{subscription-x61fFv_7.d.cts → subscription-ycCVo9e2.d.cts} +3 -3
  50. package/dist/{table-kind-C2bMlOaV.d.ts → table-kind-BGokuDJj.d.ts} +4 -4
  51. package/dist/{table-kind-C3PlCE9_.d.cts → table-kind-C5ZLyOxE.d.cts} +4 -4
  52. package/dist/templates/index.d.cts +10 -10
  53. package/dist/templates/index.d.ts +10 -10
  54. package/dist/typed-table/index.d.cts +10 -10
  55. package/dist/typed-table/index.d.ts +10 -10
  56. package/dist/{types-C433sVT-.d.cts → types-Bg1q6qwq.d.cts} +2 -2
  57. package/dist/{types-Gur64NY0.d.ts → types-Cl0b_Hy8.d.ts} +2 -2
  58. package/dist/{types-DYXymeSx.d.ts → types-D31PewA2.d.ts} +2 -2
  59. package/dist/{types-BBwIxf_z.d.ts → types-DB4J-zIt.d.ts} +2 -2
  60. package/dist/{types-_D768Jzt.d.cts → types-DtEP7XLv.d.cts} +2 -2
  61. package/dist/{types-BTydwrlW.d.cts → types-SezYoQ5_.d.cts} +2 -2
  62. package/dist/use-cases/index.d.cts +5 -5
  63. package/dist/use-cases/index.d.ts +5 -5
  64. package/dist/{validate-BRfOuXKD.d.ts → validate-BWqeG2sK.d.ts} +1 -1
  65. package/dist/{validate-CmZ93paU.d.cts → validate-QdnFP97_.d.cts} +1 -1
  66. package/dist/views/index.d.cts +400 -12
  67. package/dist/views/index.d.ts +400 -12
  68. package/package.json +2 -2
  69. package/dist/seed-CQkIf8UR.d.cts +0 -37
  70. package/dist/seed-Dz8Hi2LZ.d.ts +0 -37
  71. package/dist/views-B156FsIH.d.cts +0 -396
  72. package/dist/views-Bny6SBX0.d.ts +0 -396
@@ -1,14 +1,402 @@
1
- import { V as ViewPresentationDocument, S as SavedViewSpec, b as SavedView, a as ViewPresentationCodec, c as ViewSettings, d as ViewSettingsPatch } from '../views-Bny6SBX0.js';
2
- export { L as LAYOUT_FIELD_KIND, e as LAYOUT_LABEL, P as PAGE_VIEWS, f as PAGE_VIEW_LABEL, g as PageView, h as STORE_KEEPS_TIMELINE, i as STORE_KEPT_LAYOUTS, j as VIEW_KEYS, k as VIEW_LAYOUTS, l as VIEW_NEEDS, m as ViewKeyDeclaration, n as ViewKeyLayout, o as ViewKeyWriter, p as ViewLayout, q as ViewNeed, r as ViewNeedKind, s as ViewOrder, t as ViewSort, u as ViewSortKey, v as declareView, w as defaultViewOf, x as designateView, y as freeColumnName, z as makeDefaultLabel, A as pageViewFromParam, B as plainPresentation, C as saveViewPatch, D as storeKeepsLayout, E as unknownViewLine, F as viewDocument, G as viewFromRow, H as viewKeysFor, I as viewOrderOf, J as viewPatchDocument, K as viewPatchFor, M as viewSettings, N as viewSettingsFor, O as viewSettingsPatch, Q as wordsList } from '../views-Bny6SBX0.js';
3
- import { R as RecordsClient } from '../client-BKhJ6Ezn.js';
4
- import { U as Uuid, R as RecordsResult } from '../record-Bo1ahH3_.js';
5
- import { R as RecordFilter, e as SavedViewRow } from '../subscription-1ik9orQK.js';
6
- import '../rule-BojwTDvi.js';
7
- import '../table-kind-C2bMlOaV.js';
8
- import '../field-GR--cya9.js';
9
- import '../ports-CCPhsr-V.js';
10
- import '../relation-D8UmOxPh.js';
11
- import '../portal-o9FhryoU.js';
1
+ import { R as RuleExpression } from '../rule-BVX1C83I.js';
2
+ import { R as RecordFilter, n as SavedViewRow } from '../subscription-DucBLG-Y.js';
3
+ import { R as RecordsClient } from '../client-DM3dRewB.js';
4
+ import { U as Uuid, R as RecordsResult } from '../record-zwSBU5PQ.js';
5
+ import '../table-kind-BGokuDJj.js';
6
+ import '../field-D-1OKy5r.js';
7
+ import '../ports-YOhD5T7h.js';
8
+ import '../relation-Dk9-VzY0.js';
9
+ import '../portal-DDOmQR1f.js';
10
+
11
+ /** A view's look as the store keeps it: one JSON object under `definition.presentation`. */
12
+ type ViewPresentationDocument = Record<string, unknown>;
13
+ /**
14
+ * HOW A VIEW'S LOOK IS READ AND WRITTEN — a PORT. The store keeps the look as one JSON object; what it
15
+ * means (colors, formats, frozen columns) belongs to the screens that draw it, so the screens hand their
16
+ * codec in (`@ai-matrx/records-ui` binds its grid presentation). Left out, the look stays the plain
17
+ * document the store keeps — a headless host reads and writes it untouched.
18
+ */
19
+ interface ViewPresentationCodec<P> {
20
+ parse(raw: unknown): P;
21
+ isEmpty(presentation: P): boolean;
22
+ /** The look as the JSON object the store keeps. */
23
+ toDocument(presentation: P): Record<string, unknown>;
24
+ }
25
+ /** The look as the plain JSON document the store keeps (no screen's meaning applied). */
26
+ declare const plainPresentation: ViewPresentationCodec<ViewPresentationDocument>;
27
+ /** Every surface a saved view is drawn by. */
28
+ type ViewKeyLayout = "grid" | "kanban" | "calendar" | "gallery" | "timeline" | "list";
29
+ /**
30
+ * 🚩 THE ONE SWITCH FOR THE TIMELINE'S STORE KEYS (lane VIEWS-AND-FIELDS, sublane TL).
31
+ *
32
+ * `vk_a_calendar_keeps_where_a_record_ends_and_a_timeline_is_a_view.sql` (sublane VK) teaches
33
+ * `custom.view_keys()` the layout `timeline`, the keys `start_field` and `end_field` (calendar +
34
+ * timeline), and `group_field` for the timeline. Until that migration is on production this stays
35
+ * `false`, and:
36
+ * · `timeline` is not a layout the store keeps (`STORE_KEPT_LAYOUTS`), so it is drawn for the visit;
37
+ * · `start_field` / `end_field` are held for the visit, never sent (`viewSettingsPatch`), and the
38
+ * Start also rides `date_field`, which the store already keeps;
39
+ * · the timeline's toolbar says "Kept for this visit only".
40
+ * Flipped to `true`, VIEW_KEYS below mirrors the migrated registry row for row (the live walk
41
+ * compares them) and every one of those is kept on the view.
42
+ */
43
+ declare const STORE_KEEPS_TIMELINE = true;
44
+ /** Who may write a key: anyone who may save the view, an input the door rewrites, or the server only. */
45
+ type ViewKeyWriter = "caller" | "input" | "server";
46
+ interface ViewKeyDeclaration {
47
+ /** Where it lives in `platform.saved_view.definition` (dotted under `presentation`). */
48
+ path: string;
49
+ /** What the store's guard checks (`custom._view_key_value`). */
50
+ shape: string;
51
+ /** The layouts that read it. */
52
+ layouts: readonly ViewKeyLayout[];
53
+ writer: ViewKeyWriter;
54
+ }
55
+ /**
56
+ * THE REGISTRY, as `custom.view_keys()` declares it (uichamp_s1_a_view_keeps_every_setting_it_is_given.sql).
57
+ * Order and content are compared with the store by the live walk.
58
+ */
59
+ declare const VIEW_KEYS: readonly ViewKeyDeclaration[];
60
+ /**
61
+ * THE LAYOUTS THE STORE KEEPS ON A VIEW. `custom.view_keys()` judges a view's `layout` against its
62
+ * own list (grid, kanban, calendar, gallery) and refuses any other word by name. A layout this
63
+ * package draws before the store keeps it — the timeline, 2026-10-02 — is never sent as a view's or a
64
+ * look's layout (`viewSettingsPatch`, `viewDocument`): it is drawn for this visit and says so. When the
65
+ * store's registry admits it, add it here and nothing else changes.
66
+ */
67
+ declare const STORE_KEPT_LAYOUTS: readonly string[];
68
+ /** Whether the store keeps this layout on a saved view. */
69
+ declare function storeKeepsLayout(layout: string): boolean;
70
+ /** The keys one layout reads, by path. */
71
+ declare function viewKeysFor(layout: ViewKeyLayout): string[];
72
+ /** One sort clause: a Field key and a direction. */
73
+ interface ViewSortKey {
74
+ field: string;
75
+ direction: "asc" | "desc";
76
+ }
77
+ /**
78
+ * EVERY DECLARED KEY OF A VIEW, TYPED. Absent keys are `null` / empty, never guessed.
79
+ * `presentation` is the parsed look (colour field, pinned fields, row height, grouping with its
80
+ * sub-groups and shut sections, hidden fields, gallery size, summaries).
81
+ */
82
+ interface ViewSettings<P = ViewPresentationDocument> {
83
+ layout: "grid" | "kanban" | "calendar" | "gallery" | "timeline" | "list";
84
+ filters: RecordFilter | null;
85
+ where: RuleExpression | null;
86
+ groupField: string | null;
87
+ swimlaneField: string | null;
88
+ collapsedColumns: string[];
89
+ measure: string | null;
90
+ dateField: string | null;
91
+ /** Timeline: where a record's bar starts (`start_field`). */
92
+ startField: string | null;
93
+ /** Calendar and timeline: where a record ends (`end_field`). */
94
+ endField: string | null;
95
+ imageField: string | null;
96
+ sorts: ViewSortKey[];
97
+ ruleId: string | null;
98
+ isDefault: boolean;
99
+ presentation: P;
100
+ movedFrom: Record<string, unknown> | null;
101
+ }
102
+ /** THE READER. A stored `definition` (and the row's flat `filters`) in, every declared key out. */
103
+ declare function viewSettings<P = ViewPresentationDocument>(definition: Record<string, unknown> | null | undefined, rowFilters?: RecordFilter | null, codec?: ViewPresentationCodec<P>): ViewSettings<P>;
104
+ /** The settings as the spec names them — what `viewSettingsPatch` takes. */
105
+ type ViewSettingsPatch<P = ViewPresentationDocument> = Partial<Omit<ViewSettings<P>, "movedFrom" | "layout">> & {
106
+ /** Any layout the package draws; one the store does not keep is not sent. */
107
+ layout?: string;
108
+ };
109
+ /**
110
+ * THE KEYS ONE LAYOUT READS, and nothing else. A layout that does not use a key never sees it:
111
+ * a calendar is not told the board's swimlanes, a board is not told the grid's pinned fields.
112
+ */
113
+ declare function viewSettingsFor<P extends object = ViewPresentationDocument>(settings: ViewSettings<P>, layout: ViewKeyLayout): Partial<ViewSettings<P>>;
114
+ /**
115
+ * THE WRITER'S SHAPE. Only the keys a press changed; a cleared Field is `null` (the door removes
116
+ * it); lists are sent whole. `presentation` is sent whole because the door judges it as one key.
117
+ */
118
+ declare function viewSettingsPatch<P = ViewPresentationDocument>(patch: ViewSettingsPatch<P>, codec?: ViewPresentationCodec<P>): Record<string, unknown>;
119
+
120
+ /** The ways one saved view can be looked at (SCR-6; the timeline, lane VIEWS-AND-FIELDS TL). */
121
+ declare const VIEW_LAYOUTS: readonly ["grid", "kanban", "calendar", "gallery", "timeline", "list"];
122
+ type ViewLayout = (typeof VIEW_LAYOUTS)[number];
123
+ declare const LAYOUT_LABEL: Record<ViewLayout, string>;
124
+ /**
125
+ * ─────────────────────────────────────────────────────────────────────────────
126
+ * WHAT EACH LAYOUT NEEDS FROM THE TABLE, AND HOW THE SCREEN SUPPLIES IT
127
+ * (lane DATA-V2-VIEWS-1, Arman 2026-09-28).
128
+ *
129
+ * THE DEFECT. A plain table opened as a Kanban said "A kanban board needs a Field to make its
130
+ * columns from … Add column, then Select — and it appears here." It told the person what to do
131
+ * instead of doing it, and on an AI platform it offered no AI. The ruling: ONE primitive, used by
132
+ * every view (`ViewNeeds`) — the empty state says in one plain sentence what is missing and what
133
+ * pressing will do, offers "Make it work" (the column is declared through the store's
134
+ * `custom.field_declare`, its key minted by the store, its name and choices editable before the
135
+ * press) and "Ask AI" (the agent does it through the same door, held for the person's approval by
136
+ * the organization's "Agent changes to this organization's data" setting).
137
+ *
138
+ * THE CENSUS — every layout this package draws, and what it reads:
139
+ * · grid nothing.
140
+ * · kanban a CHOICE column (its options become the board's columns). Blocking.
141
+ * · calendar a DATE column (it places each record on a day). Blocking.
142
+ * · gallery a FILE column for the card's picture. NOT blocking: the cards draw without one,
143
+ * so the offer sits above them instead of in place of them.
144
+ * · timeline a DATE column each bar starts on (the calendar's `dateField`). Blocking.
145
+ * `PAGE_VIEWS`' two extra values (dashboards, archived) read
146
+ * nothing a table can lack. This package ships no map layout; the day it does,
147
+ * `Record<ViewLayout, …>` below refuses to compile until the new layout names what it needs.
148
+ */
149
+ type ViewNeedKind = "choice" | "date" | "file";
150
+ interface ViewNeed {
151
+ /** What the layout reads, as a kind a column declares (`offerableFields`). */
152
+ kind: ViewNeedKind;
153
+ /** The view key the made column is written onto, so the layout opens drawn by it. */
154
+ viewKey: "groupField" | "dateField" | "imageField";
155
+ /** True when the layout cannot draw at all without it (kanban, calendar). */
156
+ blocking: boolean;
157
+ /** The column the press makes, before the person edits it: its name, the store's word, its choices. */
158
+ starter: {
159
+ label: string;
160
+ type: "select" | "datetime" | "attachment";
161
+ options?: readonly string[];
162
+ };
163
+ /** The table HAS columns this layout can use and none is chosen: the sentence over the picker. */
164
+ pick: string;
165
+ /** One plain sentence: what the table is missing (all a person who may not change it is told). */
166
+ missing: string;
167
+ /** One plain sentence: what pressing Make it work will do, with the column's name. */
168
+ does: (label: string) => string;
169
+ /** The sentence an agent is asked with — the same act, said in words. */
170
+ ask: (label: string, options: readonly string[]) => string;
171
+ }
172
+ /** A list of words as a person says it: "To do, In progress and Done". */
173
+ declare function wordsList(words: readonly string[]): string;
174
+ declare const VIEW_NEEDS: Record<ViewLayout, ViewNeed | null>;
175
+ /**
176
+ * A NAME NO COLUMN OF THIS TABLE ALREADY HAS: the starter's own, else "Status 2", "Status 3"…
177
+ * A table that already holds a text column called Status must not be refused the board.
178
+ */
179
+ declare function freeColumnName(wanted: string, taken: readonly string[]): string;
180
+ /** One sort clause. The Field's key and a direction; nothing else is a sort. */
181
+ interface ViewSort {
182
+ field: string;
183
+ direction: "asc" | "desc";
184
+ }
185
+ /** How a saved view is ordered: by hand, by its sort, or it never said (the same as sorted). */
186
+ type ViewOrder = "manual" | "sorted" | null;
187
+ /** The order word a stored definition carries. Only the two words the store writes are read. */
188
+ declare function viewOrderOf(definition: Record<string, unknown> | null | undefined): ViewOrder;
189
+ /**
190
+ * THE DECLARATIVE SPEC. An agent writes this whole object; a person tweaks it.
191
+ * Every builder component in this package takes one of these as a prop.
192
+ */
193
+ interface SavedViewSpec<P = ViewPresentationDocument> {
194
+ name: string;
195
+ /** The Table this view looks at. */
196
+ subject: Uuid;
197
+ layout: ViewLayout;
198
+ /** Kanban: the Field whose value becomes a column. */
199
+ groupField?: string | null;
200
+ /**
201
+ * Kanban: a number Field to TOTAL under each column heading. It lives on the VIEW for
202
+ * the same reason the colours do — two people read one board two ways and neither
203
+ * reading is a fact about the records.
204
+ */
205
+ measure?: string | null;
206
+ /**
207
+ * Kanban: the Field whose values cut the board into SWIMLANES across the columns — a
208
+ * dispatcher's board by Status, one lane per Technician (S1-PRIME VIEW-KEYS). Never the
209
+ * column Field itself; the store refuses that.
210
+ */
211
+ swimlaneField?: string | null;
212
+ /** Kanban: the columns this view keeps shut to a strip, by the column's stored value. */
213
+ collapsedColumns?: string[];
214
+ /** Calendar: the Field that places a record in the month. */
215
+ dateField?: string | null;
216
+ /** Timeline: the Field a record's bar starts on (`start_field`). */
217
+ startField?: string | null;
218
+ /** Calendar and timeline: the Field a record ends on (`end_field`). */
219
+ endField?: string | null;
220
+ /** Gallery: the Field shown large on the card. */
221
+ imageField?: string | null;
222
+ sorts?: ViewSort[];
223
+ /**
224
+ * HOW THE VIEW IS ORDERED (ORDER-FIX): `"manual"` — the positions a person set by hand ARE the
225
+ * view's sort, and it carries no `sorts`; `"sorted"` or null — by `sorts`. READ ONLY: the store
226
+ * writes "manual" only when the rows are placed (`custom.view_record_order_set`) and turns it
227
+ * off itself when a sort is saved, so no patch ever sends it (`viewSettingsPatch` does not).
228
+ */
229
+ order?: ViewOrder;
230
+ /**
231
+ * The membership Rule. The STORE decides who is in this view; this is a
232
+ * reference to its Rule record, never a predicate this package evaluates.
233
+ */
234
+ ruleId?: Uuid | null;
235
+ /**
236
+ * THE FLAT FILTER a digest or a notify rule wrote the view with — the one shape
237
+ * `custom.record_filter_sql` compiles, by Field KEY. A view saved in the bar has
238
+ * none; a view saved by `DigestScheduler` ("where Status is Open") does, and the
239
+ * grid and the board show exactly the records it names.
240
+ */
241
+ filters?: RecordFilter;
242
+ /**
243
+ * S2-PRIME — THE VIEW'S OWN QUESTION, as the condition builder writes it: the store's Rule
244
+ * shape `{op, args}`, ALL / ANY / NOT groups nested to any depth, Fields by id. Kept in the
245
+ * definition as `where` and asked of the store unchanged — the grid's list door, the board's
246
+ * headings and the dashboard's numbers compile it into the one WHERE clause
247
+ * (`custom.record_filter_sql`). Never stored under `filters`: that key is the flat map the
248
+ * digests and the notifier read, and they would refuse it by name.
249
+ */
250
+ where?: RuleExpression | null;
251
+ isDefault?: boolean;
252
+ /**
253
+ * HOW THIS VIEW LOOKS — its colors, its per-column formats and its frozen
254
+ * column (`presentation.ts`).
255
+ *
256
+ * It lives on the VIEW and not on the Fields because two people read one
257
+ * table two ways and neither reading is a fact about the records; it lives on
258
+ * a RECORD, not a new column, because that is what makes it something an
259
+ * agent writes with the same `records` tool as everything else.
260
+ */
261
+ presentation?: P;
262
+ }
263
+ /**
264
+ * A saved view as it comes back out of the store, with its row's own id.
265
+ *
266
+ * It carries no version: `custom.view_declare` MERGES one key at a time, so two
267
+ * tabs pressing two different controls on one view both stand, and one control
268
+ * pressed in both keeps the latest — how Airtable and Notion keep a view change.
269
+ */
270
+ interface SavedView<P = ViewPresentationDocument> extends SavedViewSpec<P> {
271
+ id: Uuid;
272
+ /** Where the view came from when it was moved in (the mover, the S0 repair), else null. */
273
+ movedFrom: Record<string, unknown> | null;
274
+ }
275
+ /** THE TABLE'S DEFAULT VIEW: the first view that says it is. */
276
+ declare function defaultViewOf<V extends Pick<SavedView, "isDefault">>(views: readonly V[]): V | undefined;
277
+ /**
278
+ * WHICH FIELD EACH LAYOUT CAN BE DRAWN FROM, decided from the FIELD'S OWN
279
+ * DECLARATION and never from the values it happens to hold.
280
+ *
281
+ * A kanban makes columns from a choice: the Field whose value is one of a
282
+ * closed set (FLD-5 / FLD-6 — a pick-list is a Table, and a select stores the
283
+ * id of one of its records). Grouping by a free-text Field produces one column
284
+ * per record, which is not a board. A calendar places a record in time, so it
285
+ * needs a Field that holds a date.
286
+ *
287
+ * These two answers are here, beside the layouts, because the picker on the
288
+ * screen and any agent writing a view spec must agree about what is offerable.
289
+ */
290
+ declare const LAYOUT_FIELD_KIND: Record<ViewLayout, ViewNeedKind | null>;
291
+ /**
292
+ * ─────────────────────────────────────────────────────────────────────────────
293
+ * WHICH VIEW A LINK NAMES — the address bar as a first-class control.
294
+ *
295
+ * 🚨 THE DEFECT THIS CLOSES (lane FRONT-DOOR, 2026-09-21; VERIFIER-8 HIGH-2).
296
+ * `/data/<table>?view=kanban` returned 200 and rendered THE GRID. The
297
+ * switcher was there, the four buttons worked, and the parameter was read by
298
+ * nobody — so a person who bookmarked a board, or sent one to a colleague, got
299
+ * a grid, and nothing on the screen said the view had been dropped. A link that
300
+ * does not land is the inbox-link defect (`activeRecordId`) and the dashboard
301
+ * defect (`activeDashboardId`) for the third time, so this is the same shape of
302
+ * fix: the URL names it, the page opens on it, and the URL FOLLOWS the person
303
+ * when they pick another.
304
+ *
305
+ * The dashboards are a fifth value and not a special case: to the person, "the
306
+ * dashboard" is one of the ways to look at this table, and a link to it has to
307
+ * work like a link to the board.
308
+ */
309
+ /**
310
+ * 🚨 `archived` IS THE SIXTH VALUE, AND IT IS NOT A SPECIAL CASE EITHER (lane
311
+ * FIX-10A-ARCHIVE, 2026-09-22; VERIFIER-10 F4).
312
+ *
313
+ * Archiving a record used to be a ONE-WAY DOOR: the grid's row action soft-
314
+ * deletes correctly — `deleted_at` set, version bumped, nothing removed — and
315
+ * then no screen anywhere in the platform could bring it back. The store's
316
+ * `custom.record_restore` was there the whole time and did exactly the right
317
+ * thing; nothing reached it, because every read door answers live rows only.
318
+ *
319
+ * So the archive is a WAY OF LOOKING AT THIS TABLE, like the board and the
320
+ * dashboards, reached by the same row of buttons and named by the same
321
+ * `?view=` parameter — never a Trash area of the app somebody has to know
322
+ * exists, and never a per-table screen. Every Table inherits it the moment it
323
+ * is in this list.
324
+ */
325
+ declare const PAGE_VIEWS: readonly ["grid", "kanban", "calendar", "gallery", "timeline", "list", "dashboards", "archived"];
326
+ type PageView = (typeof PAGE_VIEWS)[number];
327
+ declare const PAGE_VIEW_LABEL: Record<PageView, string>;
328
+ /**
329
+ * What a `?view=` value means, or `null` when it means nothing here.
330
+ *
331
+ * `null` is NOT "show the grid": the caller is expected to say that the link
332
+ * named something this table has no view for, because silently substituting a
333
+ * different view is exactly the defect above wearing a parser.
334
+ */
335
+ declare function pageViewFromParam(raw: string | null | undefined): PageView | null;
336
+ /** The sentence a link that named a view nobody has says. Never silent. */
337
+ declare function unknownViewLine(raw: string): string;
338
+ /**
339
+ * THE SPEC AS THE ONE DEFINITION `platform.saved_view` HOLDS — the keys
340
+ * `custom.view_declare` documents, by Field KEY. `subject` is not in it: the door
341
+ * takes the Table as its own argument and writes `table_id` itself.
342
+ */
343
+ declare function viewDocument<P = ViewPresentationDocument>(spec: SavedViewSpec<P>, codec?: ViewPresentationCodec<P>): Record<string, unknown>;
344
+ /**
345
+ * One row of `custom.views` back into the spec a screen and an agent both read — THROUGH THE ONE
346
+ * ACCESSOR (`viewSettings`, viewKeys.ts), so every layout sees every declared key the same way.
347
+ */
348
+ declare function viewFromRow<P = ViewPresentationDocument>(row: SavedViewRow, codec?: ViewPresentationCodec<P>): SavedView<P>;
349
+ /**
350
+ * SAVE ONE NEW VIEW of a Table — the bar's "New view" and an agent's seed spec.
351
+ * One `view_declare` with no `view_id`; the answer is the new view's id.
352
+ */
353
+ declare function declareView<P = ViewPresentationDocument>(client: Pick<RecordsClient, "viewDeclare">, spec: SavedViewSpec<P>, codec?: ViewPresentationCodec<P>): Promise<RecordsResult<Uuid>>;
354
+ /**
355
+ * WRITE A CHANGE ONTO A SAVED VIEW, AND KEEP IT.
356
+ *
357
+ * `custom.view_declare` with the view's id MERGES: only the keys in `patch` are
358
+ * written, a key cleared to null is removed, and everything the patch did not
359
+ * name — the grid's own choices, a hand-set order, where the view was moved from,
360
+ * a colour set in another tab — stays exactly as it was (S0, 2026-09-23: the door
361
+ * used to rebuild the whole definition from what one press sent).
362
+ *
363
+ * There is no version to be stale against (VERIFIER-15 M4 is closed by the shape,
364
+ * not by a retry): a saved view is a person's own arrangement of a table, and
365
+ * their latest press on a control is the one that stands. A refusal — the view
366
+ * was removed, or belongs to a table this person cannot open — is handed back for
367
+ * the page to say through the one notice.
368
+ */
369
+ declare function saveViewPatch<P = ViewPresentationDocument>(client: Pick<RecordsClient, "viewDeclare">, tableId: Uuid, viewId: Uuid, patch: Partial<SavedViewSpec<P>>, codec?: ViewPresentationCodec<P>): Promise<RecordsResult<Uuid>>;
370
+ /**
371
+ * A PARTIAL change to a saved view, as the definition keys the door merges. Only
372
+ * the keys the caller actually changed are sent; a Field cleared (a board with no
373
+ * "Group by") is sent as `null`, which the door removes.
374
+ */
375
+ declare function viewPatchDocument<P = ViewPresentationDocument>(patch: Partial<SavedViewSpec<P>>, codec?: ViewPresentationCodec<P>): Record<string, unknown>;
376
+ /**
377
+ * A LOOK AT A TABLE NEVER CHANGES HOW IT OPENS (lane VIEW-SWITCH-NOT-DESIGNATION, VERIFIER-21).
378
+ *
379
+ * On production the owner pressed Kanban, then Calendar, and the office member's table opened in
380
+ * the Calendar: every layout press was saved onto the DEFAULT view, which is how the table opens
381
+ * for everyone. The table's default view's `layout` and `isDefault` are its DESIGNATION, changed
382
+ * only by an editor's deliberate "Make this the default" (`designateView`); the store refuses them
383
+ * through `view_declare` by name. So a press on the default view carries every other key it
384
+ * changed — a board's grouping, a calendar's date, a colour — and never those two.
385
+ */
386
+ declare function viewPatchFor<S extends {
387
+ layout?: unknown;
388
+ isDefault?: boolean;
389
+ }>(view: {
390
+ isDefault?: boolean;
391
+ }, patch: Partial<S>): Partial<S>;
392
+ /** The one words for the explicit designation, with the layout it would make the default. */
393
+ declare function makeDefaultLabel(layoutLabel: string): string;
394
+ /**
395
+ * MAKE THIS THE DEFAULT — the ONE designation door (`custom.view_designate`, editor on the table).
396
+ * `layout` is the layout this table should open in for everyone: one of the layouts the store keeps. The view
397
+ * becomes the table's only default.
398
+ */
399
+ declare function designateView(client: Pick<RecordsClient, "viewDesignate">, tableId: Uuid, viewId: Uuid, layout: string | null): Promise<RecordsResult<Uuid>>;
12
400
 
13
401
  /**
14
402
  * WHAT A LOOK MAY HOLD — how a person looks, never what the view is: not its name, not whether it is the default,
@@ -53,4 +441,4 @@ declare function bindViewCodec<P>(codec: ViewPresentationCodec<P>): {
53
441
  keepLook: (client: Pick<RecordsClient, "viewLookSet">, tableId: Uuid, viewId: Uuid, look: ViewLook<P> | null) => Promise<RecordsResult<Record<string, unknown> | null>>;
54
442
  };
55
443
 
56
- export { SavedView, SavedViewSpec, type ViewLook, ViewPresentationCodec, ViewPresentationDocument, ViewSettings, ViewSettingsPatch, applyLook, bindViewCodec, keepLook, lookDiffers, lookDocument, lookFromDocument, lookPart, readLooks, saveToViewPlan };
444
+ export { LAYOUT_FIELD_KIND, LAYOUT_LABEL, PAGE_VIEWS, PAGE_VIEW_LABEL, type PageView, STORE_KEEPS_TIMELINE, STORE_KEPT_LAYOUTS, type SavedView, type SavedViewSpec, VIEW_KEYS, VIEW_LAYOUTS, VIEW_NEEDS, type ViewKeyDeclaration, type ViewKeyLayout, type ViewKeyWriter, type ViewLayout, type ViewLook, type ViewNeed, type ViewNeedKind, type ViewOrder, type ViewPresentationCodec, type ViewPresentationDocument, type ViewSettings, type ViewSettingsPatch, type ViewSort, type ViewSortKey, applyLook, bindViewCodec, declareView, defaultViewOf, designateView, freeColumnName, keepLook, lookDiffers, lookDocument, lookFromDocument, lookPart, makeDefaultLabel, pageViewFromParam, plainPresentation, readLooks, saveToViewPlan, saveViewPatch, storeKeepsLayout, unknownViewLine, viewDocument, viewFromRow, viewKeysFor, viewOrderOf, viewPatchDocument, viewPatchFor, viewSettings, viewSettingsFor, viewSettingsPatch, wordsList };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-matrx/records",
3
- "version": "0.93.2",
3
+ "version": "0.93.4",
4
4
  "description": "The headless client of the AI Matrx record store: the Table / Field / Rule / Record / Relation / Home types, the closed vocabularies and refusal codes read from the store itself, the typed calls over the store's doors and nothing else, the merge-field declaration, a validation mirror that predicts only what the store's own triggers refuse, and the never-throw result envelope. Zero React, zero DOM in the root and /core.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -320,5 +320,5 @@
320
320
  "describe-bench:run": "../../../.venv/bin/python scripts/describe-bench/score-env.py run",
321
321
  "describe-bench:arms": "../../../.venv/bin/python scripts/describe-bench/score-env.py arms"
322
322
  },
323
- "gitHead": "f0c9d2820cbe5bef9bcd8e136dcce9358371c49e"
323
+ "gitHead": "58cf6cf4b39debf76a01dc2f2cbd5ab7ad8cbbfe"
324
324
  }
@@ -1,37 +0,0 @@
1
- import { R as RecordsDataSource } from './ports-BTDZ9ydi.cjs';
2
-
3
- /** One door's answer, under its exact arguments. Plain JSON: it crosses from server to browser. */
4
- interface RecordsSeedAnswer {
5
- door: string;
6
- args: Record<string, unknown>;
7
- data: unknown;
8
- }
9
- /** What a server asked for a page, as the person, and when. */
10
- interface RecordsSeed {
11
- /** Epoch ms when the server asked. */
12
- at: number;
13
- answers: RecordsSeedAnswer[];
14
- }
15
- /** The match key: a door and every argument, keys sorted at every depth. */
16
- declare function seedKey(door: string, args: Record<string, unknown>): string;
17
- /**
18
- * A data source that asks `source` and keeps every answer a door GAVE (errors are not kept). For a
19
- * server render: create a records client over it, ask what the page will ask, then `seed()`.
20
- */
21
- declare function recordingDataSource(source: RecordsDataSource): {
22
- source: RecordsDataSource;
23
- seed: () => RecordsSeed;
24
- };
25
- /** The seed as a lookup, built once per seed. */
26
- declare function seedIndex(seed: RecordsSeed): Map<string, unknown>;
27
- /**
28
- * ONE RUN AGAINST THE SEED: a data source answering from `index` only, and whether the run asked a
29
- * door the seed does not hold. It never opens a bundle itself (`opensInOneCall` off): the bundle's
30
- * parts are already answers in the index.
31
- */
32
- declare function seededDataSource(index: Map<string, unknown>): {
33
- source: RecordsDataSource;
34
- missed: () => boolean;
35
- };
36
-
37
- export { type RecordsSeed as R, type RecordsSeedAnswer as a, seedKey as b, seededDataSource as c, recordingDataSource as r, seedIndex as s };
@@ -1,37 +0,0 @@
1
- import { R as RecordsDataSource } from './ports-CCPhsr-V.js';
2
-
3
- /** One door's answer, under its exact arguments. Plain JSON: it crosses from server to browser. */
4
- interface RecordsSeedAnswer {
5
- door: string;
6
- args: Record<string, unknown>;
7
- data: unknown;
8
- }
9
- /** What a server asked for a page, as the person, and when. */
10
- interface RecordsSeed {
11
- /** Epoch ms when the server asked. */
12
- at: number;
13
- answers: RecordsSeedAnswer[];
14
- }
15
- /** The match key: a door and every argument, keys sorted at every depth. */
16
- declare function seedKey(door: string, args: Record<string, unknown>): string;
17
- /**
18
- * A data source that asks `source` and keeps every answer a door GAVE (errors are not kept). For a
19
- * server render: create a records client over it, ask what the page will ask, then `seed()`.
20
- */
21
- declare function recordingDataSource(source: RecordsDataSource): {
22
- source: RecordsDataSource;
23
- seed: () => RecordsSeed;
24
- };
25
- /** The seed as a lookup, built once per seed. */
26
- declare function seedIndex(seed: RecordsSeed): Map<string, unknown>;
27
- /**
28
- * ONE RUN AGAINST THE SEED: a data source answering from `index` only, and whether the run asked a
29
- * door the seed does not hold. It never opens a bundle itself (`opensInOneCall` off): the bundle's
30
- * parts are already answers in the index.
31
- */
32
- declare function seededDataSource(index: Map<string, unknown>): {
33
- source: RecordsDataSource;
34
- missed: () => boolean;
35
- };
36
-
37
- export { type RecordsSeed as R, type RecordsSeedAnswer as a, seedKey as b, seededDataSource as c, recordingDataSource as r, seedIndex as s };