@ai-matrx/records 0.17.0 → 0.21.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,154 @@
1
1
  # Changelog — @ai-matrx/records
2
2
 
3
+
4
+ ## 0.21.0 — 2026-09-20
5
+
6
+ **The store moved and this package's census caught it — twice.** The release
7
+ gate runs the live-door suite against the real record store, and it went red on
8
+ main:
9
+
10
+ - `src/store.generated.ts` regenerated from the live store. The value envelope
11
+ gained `pinned`, the door census gained `conversation_scope` and its bind /
12
+ unbind / context siblings (478 doors, up from 428), and the knob list grew to
13
+ 43. Nothing in that file is typed by a person.
14
+ - **SQLSTATE `22003` is mapped.** `custom.context_resolve` raises it — a number
15
+ the store could not hold at the size it was handed — and this package did not
16
+ know the class, so it would have read as `internal` in somebody's console. It
17
+ is `invalid_argument`, the same class `22P02`, `42703` and `22007` already
18
+ are: the call named a value the shape does not accept, and the store's own
19
+ sentence names the number and the range.
20
+
21
+ > **About 0.20.0 on npm.** This lane tagged `0.20.0` from a commit that carried
22
+ > the census fixes above but NOT the checklist doors below — the tag was pushed
23
+ > while a merge of main was still open, and a tag is never moved. `0.21.0` is
24
+ > the first version that carries both. Nobody should sit on 0.20.0.
25
+
26
+
27
+ ## 0.20.0
28
+
29
+ **"Every new hire gets these twelve steps." — the checklist doors, PRODUCTS row 13.**
30
+
31
+ A checklist template is a record of the store: ordered steps, each with the role
32
+ that owns it, how many days in it is due, what it waits for and what it asks for
33
+ before it counts as done, plus the thing that starts a run. Starting one makes
34
+ ONE work item per step in the one work layer — assigned by role to real people,
35
+ dated from the offsets, dependencies carried across — so a step appears in the
36
+ person's ordinary inbox beside everything else and there is no
37
+ checklist-shaped queue anywhere.
38
+
39
+ Nine doors, all of them live on the main database:
40
+ `checklistRefusal` (pure — a screen may ask it on every keystroke, and the
41
+ refusal arrives before the save), `checklistDeclare`, `checklistTemplates`,
42
+ `checklistTemplateShape`, `checklistStart`, `checklistRun`, `checklistRuns`,
43
+ `checklistStepComplete`, `checklistStepRefusal`.
44
+
45
+ `ChecklistRunStep` carries `blocked_by`, `refusal`, `may_complete` and
46
+ `requires_key`, so a screen can say why a step cannot be finished yet — in the
47
+ words a person would use — before anybody clicks, file the evidence under the
48
+ key the checklist itself named, and show no control at all where a control would
49
+ fail.
50
+
51
+ THE DEPENDENCY RULE LIVES IN THE STORE, not in these methods: a BEFORE trigger
52
+ on `custom.record` refuses a step reaching Done while a step it waits for is
53
+ open, so `workSetState` meets the same sentence `checklistStepComplete` does.
54
+
55
+
56
+ ## 0.19.0
57
+
58
+ **"Pull my spreadsheet in" — the import doors, and the address a Table can own.**
59
+
60
+ `core/io.ts` has parsed CSV and XLSX bytes since W4-IO, and `ImportWizard` then
61
+ wrote the rows one at a time through `recordWrite` — one HTTP round trip per
62
+ row, no duplicate check, no provenance, and a refusal that carried a row NUMBER
63
+ into a file the screen no longer had. Every one of those is a way to lose data
64
+ quietly at 5,000 rows.
65
+
66
+ Eleven client methods arrive. The BYTES are still parsed here, because Postgres
67
+ cannot unzip a workbook; **everything after the parse is the store's**, so a file
68
+ imported from a screen, from an agent and from a script land identically and
69
+ there is no second importer in this package to drift.
70
+
71
+ - **`importPlan({ table_id, columns })`** — what the store makes of a file's
72
+ columns before anything is written, reading the parity map AND this
73
+ organization: an address that belongs to a member is a `member` column, a few
74
+ repeating words are a `select` with its options, `$1,250.00` is `currency` with
75
+ its unit, a column of names that are all records of another Table is a
76
+ `relation` at it. Every answer carries one sentence saying why, and two columns
77
+ that would make the same key say so.
78
+ - **`importBegin(...)`** — opens a run with the file's sha-256 as its IDENTITY.
79
+ The same bytes into the same table a second time answer the FIRST run with
80
+ `already: true` and write nothing, so **a re-import doubles nothing**. Carries
81
+ the duplicate key and the policy the whole run obeys.
82
+ - **`importRows({ import_id, rows, mapping })`** — a BATCH. Every row goes
83
+ through the one write door inside its own subtransaction and comes back with
84
+ one of exactly three outcomes: `landed` with the record id, `duplicate` with
85
+ the id of the record already there, or `refused` with the store's own sentence
86
+ **and the source row**, so an outcome table is clickable. Every value that
87
+ lands carries `{"kind":"import", …}` as its source (VAL-1).
88
+ - **`importFinish({ import_id, unmapped })`** — closes the run and sends every
89
+ column the file had and the table did not to the **ONE approvals inbox**
90
+ (`propose`, the default and the only choice a non-admin has), or adds them
91
+ outright (`create`, an admin's), or leaves them out. Never a junk bag.
92
+ - **`importReport`**, **`imports`**, **`importForget`** — the refused and
93
+ already-here rows with their source, this organization's runs, and forgetting
94
+ a receipt so the same bytes can be imported again deliberately.
95
+ - **`inboundDeclare` / `inboundAddresses` / `inboundSet`** (DOOR-19) — the
96
+ address a Table owns. `inboundDeclare` answers with **`mail_route`**: the one
97
+ sentence saying what has to exist in DNS before anything arrives. Show it
98
+ wherever the address is shown. The gateway's own landing door is deliberately
99
+ absent from this client — it is `service_role`'s alone.
100
+
101
+ New types in `@ai-matrx/records`: `ImportPlan`, `ImportColumnPlan`,
102
+ `ImportPolicy`, `ImportOpened`, `ImportOutcome`, `ImportProposal`,
103
+ `ImportBatchResult`, `ImportFinished`, `ImportReport`, `ImportRun`,
104
+ `InboundAddress`, `InboundDeclared`.
105
+
106
+ `store.generated.ts` regenerated against the live store: **428 doors**.
107
+
108
+ ## 0.18.0
109
+
110
+ **"Who changed this price, and can I put it back?" — the doors for PRODUCTS row 4.**
111
+
112
+ The store has kept every version of every record since W3-HIST: one append-only
113
+ chain covering Values AND structure, with the compound verb that wrote each
114
+ version stamped on it since MERGE-HISTORY. None of it reached a screen. The only
115
+ thing a client could ask for was `revisions()` (`custom.io_revisions`), which
116
+ answers a version number, a moment, a RAW UUID for the author and a list of
117
+ KEYS — so a timeline could say "something changed" and could not say who, what
118
+ it was before, or which Rule produced a derived value.
119
+
120
+ Seven client methods arrive:
121
+
122
+ - **`recordHistory({ record_id })`** — one record's versions, newest first, each
123
+ naming the author as `user` / `agent` / `system` **and, for an agent, the
124
+ person it acted for**, the operation in the word somebody used, and every
125
+ field that moved with its `before`, its `after`, the Rule VERSION that
126
+ produced a derived value and its interned source pointer. Viewer.
127
+ - **`fieldHistory({ table_id, field_key })`** — one column's history across a
128
+ whole Table ("who changed the price on ANY record"), narrowed to the records
129
+ this person may see by a predicate in the same statement. A column that names
130
+ no Field is refused BY NAME.
131
+ - **`restorePreview({ record_id, version, field_key? })`** — what a restore
132
+ would change, BEFORE it does, computed by the body that computes the write.
133
+ Editor: the first half of an act is not shown to somebody who may not do it.
134
+ - **`restoreVersion`** and **`valueRestore`** — put the whole record, or ONE
135
+ column (HIS-N-2), back to what it said at a version. Both write a NEW version
136
+ through the record's own write path; no stored version is ever altered.
137
+ - **`commentThread`**, **`commentWrite`**, **`commentResolve`** — SCR-18, at the
138
+ store's own `commenter` rung, with everybody NAMED, a comment anchored to one
139
+ Field, and a mention that notifies the person named.
140
+
141
+ **Consumer action:** none required. `revisions()` is unchanged and every
142
+ existing caller keeps working. A screen showing a record's past should move to
143
+ `recordHistory` — `revisions()` cannot answer who, and was never able to.
144
+
145
+ **And two defects in the store this came with**, both fixed in the same session
146
+ and both reaching every existing caller: `custom.io_restore` did not restore (it
147
+ patched the old document through a merging write, so a key added after the
148
+ target version survived its own restore in silence), and it returned NULL to
149
+ every caller it has ever had (it read the version out of the read door, which
150
+ answers a document, and `version` is a column).
151
+
3
152
  ## 0.17.0
4
153
 
5
154
  **A list is a door, never a grant on the thing behind it.**