@ai-matrx/records 0.57.2 → 0.58.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,131 @@
1
1
  # Changelog — @ai-matrx/records
2
2
 
3
+ ## 0.58.0 (2026-09-24 — published by PUBLISH-SWEEP-5; folds every section below down to 0.57.3)
4
+
5
+ * **`src/store.generated.ts` is regenerated from the LIVE main database at publish time** (608 doors).
6
+ The integrator sweep `79b505cfa5` had committed a catalogue generated against a rehearsal copy,
7
+ claiming 30 doors production does not have (`form_preview_asks`, `table_row_counts`,
8
+ `agg_*`, `pipeline_move_many`, `work_decide_many` …); `real-doors` refused it. Those doors answer
9
+ `door_absent` naming their file until the chair's production window applies them and
10
+ `pnpm records:generate` runs again. Some sections below reached main through integrator sweeps
11
+ (`79b505cfa5`, `4bf803c452`) rather than their lanes' own commits.
12
+ * S2-PRIME's `StoreFilter` (`isRuleFilter`, `stableFilterKey`; `e7e53d3269`) and S6's client/door
13
+ hunks (`4bf803c452`) ride in this release.
14
+
15
+ ### Lane S3 PERIODS (2026-09-24)
16
+
17
+ * **A target read from a goal column.** `DashboardTarget` is a fixed `value` OR a `field` (a Field
18
+ key of the block's Table) with `op` `sum | avg | min | max` (default `sum`): the store adds that
19
+ column up over exactly the records the block's own number read — same filter, same current window,
20
+ same reader. `DashboardTargetResult.value` is now `number | null` and carries `field`, `op` and
21
+ `refused` (the store's sentence when this reader may not read the goal column; the block still
22
+ answers its number). Store side: matrx-frontend
23
+ `uichamp_s3_a_target_can_be_read_from_a_goal_column.sql` (chair applies after the S3 files).
24
+
25
+ ### Lane S4 BATCH-DOORS (2026-09-24)
26
+
27
+ * **Two batch doors, one transaction each, one answer per item.**
28
+ `pipelineMoveMany({moves: [{record_id, stage, expected_version, also?}]})` over
29
+ `custom.pipeline_move_many`, and `workDecideMany({decisions: [{item, decision: "approve" | "decline",
30
+ note?}]})` over `custom.work_decide_many`. Every item is judged exactly as the single door judges it
31
+ (`pipeline_move` / `work_approval_decide`), in its own savepoint, so a refused item writes nothing and
32
+ the rest still land. `expected_version` is required per card: a card somebody changed after the board
33
+ loaded answers `changed_since_loaded` and is never overwritten. Verdicts: moves
34
+ `moved | needs_approval | needs_fields | changed_since_loaded | no_right | refused`; decisions
35
+ `approved | declined | already_decided | no_right | refused`. Cap: knob `custom/batch_items_max` (500).
36
+ Types `PipelineMoveMany*`, `WorkDecideMany*`. Until the chair's production apply and
37
+ `records:generate`, both answer `door_absent` naming lane S4.
38
+
39
+ ### Lane DEFAULT-GRID-PARITY (2026-09-24)
40
+
41
+ * `NewFieldDeclaration.formula_text` and `FieldPatch.formula_text`: a formula in the language a
42
+ person types (GRID-PRIMITIVES G3). The store parses it and keeps both the text and the expression.
43
+ * `FieldTypeWord` gains `autonumber`, `created_time` and `modified_time`, the words
44
+ `custom.field_declare` takes for the store's own stamps (G5).
45
+ * For lane SC-R: `NewFieldDeclaration.allowed_types` and the `entity_reference` word on `FieldTypeWord`.
46
+
47
+ ### Lane SC-R (2026-09-24)
48
+
49
+ * **A new field kind, `entity_reference`** — a column that points at a PLATFORM thing (a note, a web
50
+ site, an agent, a workbook, a dataset, a conversation …) rather than at a record of one of your
51
+ Tables. In the store it is a relation whose `config.target_mode` is `any`, restricted by
52
+ `config.allowed_types` (entity tokens); each value is `{token, id}`, and every read door answers
53
+ `{token, id, label}` with the label withheld from a reader who may not open the thing. Declare it
54
+ with `fieldDeclare({ type: "entity_reference", allowed_types: ["note"] })`. `FIELD_KINDS` and
55
+ `fieldKindFor` know it; `coerceTypedAnswer` takes `note:<id>` (or a bare id when the column allows one
56
+ kind) and refuses words. File and Person stay `attachment` / `member`.
57
+ * **Helpers**: `isEntityReferenceConfig`, `entityReferenceKindsOf`, `entityRefsOf` (read a cell in any
58
+ shape), `entityRefsToWrite` (what to send — `{token, id}` only, each thing once, the label dropped),
59
+ and the two doors `entityReferenceKinds(source)` (`custom.entity_reference_kinds`, for the kind
60
+ picker) and `entityReferenceWords(source, organizationId, refs)` (`custom.entity_reference_words`,
61
+ the words of a chip before it is saved). Types `EntityRef`, `EntityRefWithWords`,
62
+ `EntityReferenceKind`. Both doors are on the dev clone and the rehearsal branch;
63
+ `pnpm records:generate` after the chair's production apply.
64
+
65
+ ### Lane S3 (2026-09-24)
66
+
67
+ * **`recordAggregate({ …, compare })`** — `custom.record_aggregate(…, p_compare)`: the same question
68
+ over a prior window (`previous_period`, `same_period_last_year`, or a fixed `range` baseline),
69
+ answered under the same principal. Each row carries `prior_groups`, `prior_measures`,
70
+ `prior_row_count`, `delta` ({current, prior, change, change_pct} per measure), `position` and the
71
+ two `compare` windows as local ISO moments. Buckets are cut in the organization's calendar (knobs
72
+ `custom/time_zone`, `custom/week_start`) and answer ISO 8601 with the organization's offset.
73
+ * **`dashboardRun({ …, compare, grain })`** — `custom.dashboard_run(…, p_compare, p_grain)`; blocks
74
+ carry `compare` and `target` (`DashboardTarget`), and each block's answer adds `compare` (the
75
+ windows), `totals`, `target` (current, progress, pace) and `compare_refused`.
76
+ * New types: `AggregateCompare`, `AggregateCompareKind`, `AggregateDelta`, `AggregateCompareWindows`,
77
+ `DashboardTarget`, `DashboardTotals`, `DashboardTargetResult`. Both doors are on the dev clone and
78
+ the rehearsal branch; `pnpm records:generate` after the chair's production apply.
79
+
80
+ ### Lane FORMS-FIX-1 (2026-09-24)
81
+
82
+ * **`client.formPreviewAsks({ table_id, questions, values })`** — `custom.form_preview_asks`, the
83
+ owner's form-preview door: which questions of a draft form are asked given the answers so far,
84
+ answered by the same store loop as the public form (`custom._form_questions_asked` →
85
+ `custom.rule_eval`), behind the organization wall and the caller's own viewer rung on the Table.
86
+ It replaces `records-ui`'s direct `ruleEval` call from the browser, which every real database
87
+ refuses. On the rehearsal branch; listed in `OWED_BY` until the chair's production apply and
88
+ `pnpm records:generate`.
89
+
90
+ ### Lane GRID-PRIMITIVES G9–G11 (2026-09-23)
91
+
92
+ * **Three cutover doors** (CUTOVER-PLAN.md F1, A3, F11/D5), on the rehearsal branch and waiting for
93
+ the chair's production apply; until `pnpm records:generate` lists them each call answers
94
+ `door_absent` naming its file. `tableListEverywhere()` — every table a picker may offer, from BOTH
95
+ stores, in `get_user_tables`' shape plus `store` (`TableListEntry`). `tableSync({home_id, spec})`
96
+ — refresh a sheet tab into ONE Table: new rows added, changed rows updated, dropped rows archived,
97
+ columns the person added kept (`TableSyncSpec`, `TableSyncResult`). Pure `sheetSyncSpec()` turns a
98
+ tab's cells into that spec and refuses repeated column names or row ids.
99
+ `scopeTableProvision({home_id, item_id, scope_id})` — a context scope's template-bound Table in
100
+ the store, one per item and scope. Tests: `grid.test.ts` (sheetSyncSpec).
101
+ * **G12** `tableRowCounts({table_ids})` (`TableRowCount`) and pure `withRowCounts(tables, counts)` —
102
+ one call counts the rows each Table's reader may see, so a list never shows `row_count: null`;
103
+ `recordHeaders({ids})` (`RecordHeader`) — created / updated / version of live rows the read door
104
+ does not answer, `created_by` only as the caller's own id. Tests: `grid.test.ts` (withRowCounts).
105
+ * **G13** `viewRecordOrderSet({view_id, record_ids})` (`ViewOrderSet`) keeps a hand-set row order
106
+ on a saved view; `readInViewOrder({view_id, limit, offset})` reads it back (placed rows by
107
+ position, then the rest by created time); pure `moveInOrder(order, moved, toIndex)` builds the
108
+ order a drag sends. Tests: `grid.test.ts` (moveInOrder).
109
+ * **Headless `declareTable`** (asked by INTEG-CLIENTS): `declareTable`, `addFields`,
110
+ `fieldDeclarationFor`, `tokenFor`, `DEFAULT_FIELDS` and their types now live in
111
+ `@ai-matrx/records/core` — no React, no host — so the extension's service worker and server-side
112
+ births walk the one birth. `@ai-matrx/records-ui` re-exports them from here, unchanged for its
113
+ callers. Tests: `declare-table.test.ts`.
114
+ * **G11 amended**: `scopeTableProvision({item_id, scope_id, home_id?})` — the Home is optional (the
115
+ organization's own), and a scope provisioned before the move answers with its moved Table.
116
+ * **G14** `tableShareOutsideGrant({table_id, person, level})` (`OutsideShareAnswer`): an existing
117
+ account outside the organization is granted at once and notified; no account → the invitation.
118
+
119
+ ## 0.57.3 (unpublished — lane HUB-FIX)
120
+
121
+ * **The lane facts are their own call.** 0.57.2 folded `custom.table_facts` into every
122
+ `tableList()`, so every screen that only LISTS tables paid a second round trip, and every
123
+ test double that answers a table list had to answer it too (records-ui 0.84.5's publish gate:
124
+ 47 tests in 15 files red). `tableList()` is back to one door; new `tableFacts()` (door-presence:
125
+ `null` when the catalogue has no such door) and pure `withTableFacts(tables, facts, me)`, which
126
+ sets `visibility` and — only on the caller's own Tables — `created_by`. Exported from `/core`
127
+ with `TableFact`. Tests: `table-list-facts.test.ts` (tableList never asks for the facts).
128
+
3
129
  ## 0.57.2 (unpublished — lane HUB-FIX, 2026-09-23; `custom.table_facts` is live on the main database, ledger 2026-09-23 11:51Z, and `STORE_DOORS` is regenerated to carry it)
4
130
 
5
131
  * `tableList()` folds `custom.table_facts` onto every Table: `visibility` (a record column the