datanotes 2.0.1 → 3.0.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.
Files changed (181) hide show
  1. package/NOTICE +9 -0
  2. package/README.md +207 -28
  3. package/SECURITY.md +92 -45
  4. package/dist/THIRD-PARTY-NOTICES.txt +682 -0
  5. package/dist/api/catalog.d.cts +69 -0
  6. package/dist/api/catalog.d.ts +50 -2
  7. package/dist/api/cli-options.d.cts +39 -0
  8. package/dist/api/cli-options.d.ts +39 -0
  9. package/dist/api/client.d.cts +89 -0
  10. package/dist/api/client.d.ts +19 -30
  11. package/dist/api/docs.d.cts +211 -0
  12. package/dist/api/docs.d.ts +211 -0
  13. package/dist/api/guidance.d.cts +81 -0
  14. package/dist/api/guidance.d.ts +81 -0
  15. package/dist/api/index.cjs +6610 -2247
  16. package/dist/api/index.d.cts +13 -0
  17. package/dist/api/index.d.ts +10 -7
  18. package/dist/api/index.js +6610 -2247
  19. package/dist/api/local.cjs +118 -6
  20. package/dist/api/local.d.cts +95 -0
  21. package/dist/api/local.d.ts +70 -6
  22. package/dist/api/local.js +104 -6
  23. package/dist/api/mcp.cjs +17384 -0
  24. package/dist/api/mcp.d.cts +108 -0
  25. package/dist/api/mcp.d.ts +108 -0
  26. package/dist/api/mcp.js +17334 -0
  27. package/dist/api/otlp.d.cts +65 -0
  28. package/dist/api/redact.d.cts +17 -0
  29. package/dist/api/redact.d.ts +17 -0
  30. package/dist/api/requests.d.cts +26 -0
  31. package/dist/api/requests.d.ts +14 -16
  32. package/dist/api/results.d.cts +16 -0
  33. package/dist/api/results.d.ts +2 -1
  34. package/dist/api/tokens.d.cts +7 -0
  35. package/dist/datanotes.cjs +62511 -28069
  36. package/dist/docs/administration/configuration.md +59 -0
  37. package/dist/docs/administration/docker.md +80 -0
  38. package/dist/docs/administration/git-sync.md +71 -0
  39. package/dist/docs/administration/limits.md +69 -0
  40. package/dist/docs/administration/run-the-service.md +219 -0
  41. package/dist/docs/administration/status.md +61 -0
  42. package/dist/docs/administration/use-with-obsidian.md +75 -0
  43. package/dist/docs/api/operations/add_column.md +49 -0
  44. package/dist/docs/api/operations/add_constraint.md +55 -0
  45. package/dist/docs/api/operations/adopt_rows.md +50 -0
  46. package/dist/docs/api/operations/align_relations.md +41 -0
  47. package/dist/docs/api/operations/alter_column.md +46 -0
  48. package/dist/docs/api/operations/alter_table.md +67 -0
  49. package/dist/docs/api/operations/batch.md +48 -0
  50. package/dist/docs/api/operations/changes_stream.md +28 -0
  51. package/dist/docs/api/operations/check_table.md +29 -0
  52. package/dist/docs/api/operations/clone_table.md +48 -0
  53. package/dist/docs/api/operations/comment_on.md +42 -0
  54. package/dist/docs/api/operations/configure_database.md +52 -0
  55. package/dist/docs/api/operations/create_table.md +78 -0
  56. package/dist/docs/api/operations/create_view.md +54 -0
  57. package/dist/docs/api/operations/create_webhook.md +37 -0
  58. package/dist/docs/api/operations/define_base.md +52 -0
  59. package/dist/docs/api/operations/delete_rows.md +43 -0
  60. package/dist/docs/api/operations/delete_webhook.md +31 -0
  61. package/dist/docs/api/operations/describe_database.md +30 -0
  62. package/dist/docs/api/operations/describe_history.md +40 -0
  63. package/dist/docs/api/operations/describe_semantic_index.md +24 -0
  64. package/dist/docs/api/operations/describe_table.md +38 -0
  65. package/dist/docs/api/operations/docs.md +13 -0
  66. package/dist/docs/api/operations/drop_column.md +41 -0
  67. package/dist/docs/api/operations/drop_constraint.md +39 -0
  68. package/dist/docs/api/operations/drop_table.md +43 -0
  69. package/dist/docs/api/operations/drop_view.md +38 -0
  70. package/dist/docs/api/operations/engine_status.md +23 -0
  71. package/dist/docs/api/operations/graph_neighbors.md +32 -0
  72. package/dist/docs/api/operations/graph_path.md +32 -0
  73. package/dist/docs/api/operations/graph_traverse.md +43 -0
  74. package/dist/docs/api/operations/identify_session.md +24 -0
  75. package/dist/docs/api/operations/infer_table.md +43 -0
  76. package/dist/docs/api/operations/insert_row.md +48 -0
  77. package/dist/docs/api/operations/list_changes.md +35 -0
  78. package/dist/docs/api/operations/list_folder.md +28 -0
  79. package/dist/docs/api/operations/list_link_targets.md +44 -0
  80. package/dist/docs/api/operations/list_migrations.md +35 -0
  81. package/dist/docs/api/operations/list_tables.md +32 -0
  82. package/dist/docs/api/operations/list_webhooks.md +23 -0
  83. package/dist/docs/api/operations/manual_index.md +14 -0
  84. package/dist/docs/api/operations/manual_page.md +22 -0
  85. package/dist/docs/api/operations/merge_rows.md +44 -0
  86. package/dist/docs/api/operations/move_rows.md +52 -0
  87. package/dist/docs/api/operations/openapi.md +13 -0
  88. package/dist/docs/api/operations/openapi_post.md +20 -0
  89. package/dist/docs/api/operations/read_note.md +29 -0
  90. package/dist/docs/api/operations/recompute_columns.md +44 -0
  91. package/dist/docs/api/operations/record_tool_call.md +36 -0
  92. package/dist/docs/api/operations/rename_column.md +44 -0
  93. package/dist/docs/api/operations/rename_value.md +45 -0
  94. package/dist/docs/api/operations/restore_database.md +51 -0
  95. package/dist/docs/api/operations/restore_table.md +46 -0
  96. package/dist/docs/api/operations/search_notes.md +28 -0
  97. package/dist/docs/api/operations/select_rows.md +61 -0
  98. package/dist/docs/api/operations/semantic_search.md +34 -0
  99. package/dist/docs/api/operations/semantic_search_docs.md +26 -0
  100. package/dist/docs/api/operations/set_table_bases.md +44 -0
  101. package/dist/docs/api/operations/status.md +13 -0
  102. package/dist/docs/api/operations/stop_engine.md +23 -0
  103. package/dist/docs/api/operations/sync_semantic_index.md +33 -0
  104. package/dist/docs/api/operations/table_changes.md +31 -0
  105. package/dist/docs/api/operations/tags/auxiliary.md +14 -0
  106. package/dist/docs/api/operations/tags/change-feed.md +8 -0
  107. package/dist/docs/api/operations/tags/history.md +17 -0
  108. package/dist/docs/api/operations/tags/queries.md +15 -0
  109. package/dist/docs/api/operations/tags/rows-dml.md +16 -0
  110. package/dist/docs/api/operations/tags/schema-ddl.md +22 -0
  111. package/dist/docs/api/operations/tags/service.md +15 -0
  112. package/dist/docs/api/operations/tags/tokens.md +13 -0
  113. package/dist/docs/api/operations/tokens_create.md +34 -0
  114. package/dist/docs/api/operations/tokens_delete.md +29 -0
  115. package/dist/docs/api/operations/tokens_list.md +21 -0
  116. package/dist/docs/api/operations/tokens_me.md +20 -0
  117. package/dist/docs/api/operations/tokens_rotate.md +29 -0
  118. package/dist/docs/api/operations/tokens_update.md +34 -0
  119. package/dist/docs/api/operations/undo_migration.md +46 -0
  120. package/dist/docs/api/operations/update_row.md +60 -0
  121. package/dist/docs/api/operations/update_rows.md +46 -0
  122. package/dist/docs/api/operations/vacuum_table.md +37 -0
  123. package/dist/docs/api.md +135 -0
  124. package/dist/docs/develop/build-an-app.md +320 -0
  125. package/dist/docs/develop/build-on-datanotes.md +138 -0
  126. package/dist/docs/develop/change-feed-and-webhooks.md +70 -0
  127. package/dist/docs/develop/client.md +116 -0
  128. package/dist/docs/develop/concurrency.md +153 -0
  129. package/dist/docs/develop/http-api.md +79 -0
  130. package/dist/docs/develop/telemetry.md +86 -0
  131. package/dist/docs/guides/agents/docs-offline.md +99 -0
  132. package/dist/docs/guides/agents/how-agents-use-datanotes.md +124 -0
  133. package/dist/docs/guides/agents/prompts.md +495 -0
  134. package/dist/docs/guides/agents/reading-errors.md +112 -0
  135. package/dist/docs/guides/data-quality/check-constraints.md +379 -0
  136. package/dist/docs/guides/data-quality/check-table.md +63 -0
  137. package/dist/docs/guides/data-quality/hand-edits.md +507 -0
  138. package/dist/docs/guides/data-quality/sync-between-devices.md +51 -0
  139. package/dist/docs/guides/data-quality/validation.md +90 -0
  140. package/dist/docs/guides/database-objects/bases.md +480 -0
  141. package/dist/docs/guides/database-objects/catalogs-and-schemas.md +897 -0
  142. package/dist/docs/guides/database-objects/columns.md +1332 -0
  143. package/dist/docs/guides/database-objects/relations.md +1454 -0
  144. package/dist/docs/guides/database-objects/tables.md +1404 -0
  145. package/dist/docs/guides/database-objects/views.md +1003 -0
  146. package/dist/docs/guides/history/back-up.md +195 -0
  147. package/dist/docs/guides/history/change-data-feed.md +247 -0
  148. package/dist/docs/guides/history/journal-and-undo.md +262 -0
  149. package/dist/docs/guides/history/restore.md +341 -0
  150. package/dist/docs/guides/history/table-history.md +657 -0
  151. package/dist/docs/guides/history/vacuum.md +35 -0
  152. package/dist/docs/guides/read-and-write/automatic-links.md +768 -0
  153. package/dist/docs/guides/read-and-write/batch.md +139 -0
  154. package/dist/docs/guides/read-and-write/import-notes.md +896 -0
  155. package/dist/docs/guides/read-and-write/joins-and-aggregates.md +251 -0
  156. package/dist/docs/guides/read-and-write/read-and-filter.md +536 -0
  157. package/dist/docs/guides/read-and-write/write-rows.md +573 -0
  158. package/dist/docs/guides/search/link-graph.md +146 -0
  159. package/dist/docs/guides/search/semantic.md +133 -0
  160. package/dist/docs/guides/search/text.md +142 -0
  161. package/dist/docs/guides/security/security-model.md +110 -0
  162. package/dist/docs/guides/security/tokens.md +60 -0
  163. package/dist/docs/guides/security/who-did-what.md +42 -0
  164. package/dist/docs/index.md +113 -0
  165. package/dist/docs/llms.txt +33 -0
  166. package/dist/docs/reference/cli.md +136 -0
  167. package/dist/docs/reference/compatibility.md +63 -0
  168. package/dist/docs/reference/errors.md +72 -0
  169. package/dist/docs/reference/glossary.md +161 -0
  170. package/dist/docs/reference/operations/auxiliary.md +116 -0
  171. package/dist/docs/reference/operations/history.md +168 -0
  172. package/dist/docs/reference/operations/queries.md +169 -0
  173. package/dist/docs/reference/operations/rows.md +185 -0
  174. package/dist/docs/reference/operations/schema.md +316 -0
  175. package/dist/docs/reference/operations.md +96 -0
  176. package/dist/docs/reference/settings.md +31 -0
  177. package/dist/docs/release-notes.md +67 -0
  178. package/dist/docs/start/connect-agents.md +204 -0
  179. package/dist/docs/start/how-it-works.md +317 -0
  180. package/dist/docs/start/quick-start.md +126 -0
  181. package/package.json +58 -14
@@ -0,0 +1,657 @@
1
+ # Table history and time travel
2
+
3
+ > Turn history on, list a table’s versions, read a table as it was, compare two versions and find hand edits.
4
+
5
+ With history on, every write to a table becomes a numbered version in a transaction log, including edits made by hand. The engine keeps the log in its store, outside the vault.
6
+
7
+ History is on in a database the engine creates: its `metastore.yaml` says `history: true` under `config`. A database whose `metastore.yaml` lacks the key, such as one from a version before 3.0.0, has it off. Turn it on for the whole database with `configure_database`, or per table with `alter_table` or `create_table` (`history: true`).
8
+
9
+ History costs disk space. Each version keeps the full text of every note it writes, so a note saved ten times is stored about ten times. Trim old versions with [`vacuum_table`](https://datanotes.dev/guides/history/vacuum/), and turn history off with `history: false` for a table that doesn’t need it.
10
+
11
+ ## Turn history on for a table
12
+
13
+ A table’s own `history` wins over the database’s setting. With `history: true`, the engine records every write to the table, even in a database with history off.
14
+
15
+ **`alter_table`**
16
+
17
+ ```json
18
+ { "table": "film", "history": true }
19
+ ```
20
+
21
+ Answer:
22
+
23
+ ```json
24
+ {
25
+ "ok": true,
26
+ "op": "alter_table",
27
+ "planned_texts": ["datanotes/metastore.yaml"],
28
+ "commits": [{ "table": "main.public.film", "version": 1, "operation": "ALTER TABLE" }],
29
+ "migration_id": "20261012T072004-alter_table-alter-table-main-public-film"
30
+ }
31
+ ```
32
+
33
+ **`insert_row`**
34
+
35
+ ```json
36
+ { "table": "film", "values": { "title": "Nosferatu" } }
37
+ ```
38
+
39
+ **`insert_row`**
40
+
41
+ ```json
42
+ { "table": "film", "values": { "title": "Metropolis" } }
43
+ ```
44
+
45
+ **`update_row`**
46
+
47
+ ```json
48
+ {
49
+ "table": "film",
50
+ "path": "datanotes/main/public/film/Nosferatu.md",
51
+ "set": { "status": "watched", "rating": 4, "watched_on": "2026-10-03" }
52
+ }
53
+ ```
54
+
55
+ **`update_row`**
56
+
57
+ ```json
58
+ {
59
+ "table": "film",
60
+ "path": "datanotes/main/public/film/Metropolis.md",
61
+ "set": { "status": "watched" }
62
+ }
63
+ ```
64
+
65
+ **`delete_rows`**
66
+
67
+ ```json
68
+ { "table": "film", "where": { "title": "Metropolis" } }
69
+ ```
70
+
71
+ The calls after `alter_table` add two films, rate Nosferatu, mark Metropolis watched by mistake and then remove it.
72
+
73
+ ## List the versions of a table
74
+
75
+ `describe_history` lists the versions, newest first, each with its operation and metrics. Each version has the `migration_id` that `undo_migration` takes.
76
+
77
+ **`describe_history`**
78
+
79
+ ```json
80
+ { "table": "film" }
81
+ ```
82
+
83
+ Answer (110 lines)
84
+
85
+ ```json
86
+ {
87
+ "table": "main.public.film",
88
+ "history": [
89
+ {
90
+ "version": 6,
91
+ "timestamp": "2026-10-12T07:20:04.648Z",
92
+ "operation": "DELETE",
93
+ "operation_parameters": { "summary": "archive 1 rows of film" },
94
+ "migration_id": "20261012T072004-delete_rows-archive-1-rows-of-film",
95
+ "operation_metrics": {
96
+ "num_added_files": 0,
97
+ "num_removed_files": 1,
98
+ "metadata_changed": false
99
+ },
100
+ "engine_info": "datanotes",
101
+ "user_name": "docs-example",
102
+ "actor": { "session": "history", "harness": "docs-example", "auth": "owner" }
103
+ },
104
+ {
105
+ "version": 5,
106
+ "timestamp": "2026-10-12T07:20:04.642Z",
107
+ "operation": "UPDATE",
108
+ "operation_parameters": { "summary": "update film" },
109
+ "migration_id": "20261012T072004-update_row-update-film-2",
110
+ "operation_metrics": {
111
+ "num_added_files": 1,
112
+ "num_removed_files": 1,
113
+ "metadata_changed": false
114
+ },
115
+ "engine_info": "datanotes",
116
+ "user_name": "docs-example",
117
+ "actor": { "session": "history", "harness": "docs-example", "auth": "owner" }
118
+ },
119
+ {
120
+ "version": 4,
121
+ "timestamp": "2026-10-12T07:20:04.636Z",
122
+ "operation": "UPDATE",
123
+ "operation_parameters": { "summary": "update film" },
124
+ "migration_id": "20261012T072004-update_row-update-film",
125
+ "operation_metrics": {
126
+ "num_added_files": 1,
127
+ "num_removed_files": 1,
128
+ "metadata_changed": false
129
+ },
130
+ "engine_info": "datanotes",
131
+ "user_name": "docs-example",
132
+ "actor": { "session": "history", "harness": "docs-example", "auth": "owner" }
133
+ },
134
+ {
135
+ "version": 3,
136
+ "timestamp": "2026-10-12T07:20:04.630Z",
137
+ "operation": "WRITE",
138
+ "operation_parameters": { "summary": "insert into film" },
139
+ "migration_id": "20261012T072004-insert_row-insert-into-film-2",
140
+ "operation_metrics": {
141
+ "num_added_files": 1,
142
+ "num_removed_files": 0,
143
+ "metadata_changed": false
144
+ },
145
+ "engine_info": "datanotes",
146
+ "user_name": "docs-example",
147
+ "actor": { "session": "history", "harness": "docs-example", "auth": "owner" }
148
+ },
149
+ {
150
+ "version": 2,
151
+ "timestamp": "2026-10-12T07:20:04.624Z",
152
+ "operation": "WRITE",
153
+ "operation_parameters": { "summary": "insert into film" },
154
+ "migration_id": "20261012T072004-insert_row-insert-into-film",
155
+ "operation_metrics": {
156
+ "num_added_files": 1,
157
+ "num_removed_files": 0,
158
+ "metadata_changed": false
159
+ },
160
+ "engine_info": "datanotes",
161
+ "user_name": "docs-example",
162
+ "actor": { "session": "history", "harness": "docs-example", "auth": "owner" }
163
+ },
164
+ {
165
+ "version": 1,
166
+ "timestamp": "2026-10-12T07:20:04.617Z",
167
+ "operation": "ALTER TABLE",
168
+ "operation_parameters": { "summary": "alter table main.public.film" },
169
+ "migration_id": "20261012T072004-alter_table-alter-table-main-public-film",
170
+ "operation_metrics": {
171
+ "num_added_files": 0,
172
+ "num_removed_files": 0,
173
+ "metadata_changed": true
174
+ },
175
+ "engine_info": "datanotes",
176
+ "user_name": "docs-example",
177
+ "actor": { "session": "history", "harness": "docs-example", "auth": "owner" }
178
+ },
179
+ {
180
+ "version": 0,
181
+ "timestamp": "2026-10-12T07:20:04.609Z",
182
+ "operation": "CREATE TABLE",
183
+ "operation_parameters": { "summary": "create table main.public.film" },
184
+ "migration_id": "20261012T072004-create_table-create-table-main-public-film",
185
+ "operation_metrics": {
186
+ "num_added_files": 0,
187
+ "num_removed_files": 0,
188
+ "metadata_changed": true
189
+ },
190
+ "engine_info": "datanotes",
191
+ "user_name": "docs-example",
192
+ "actor": { "session": "history", "harness": "docs-example", "auth": "owner" }
193
+ }
194
+ ]
195
+ }
196
+ ```
197
+
198
+ ## Read a table as it was
199
+
200
+ `select_rows` with `version` or `timestamp` reads the table as it was at that point, a technique called time travel. Metropolis, which you removed since, is still there.
201
+
202
+ **`select_rows`**
203
+
204
+ ```json
205
+ { "table": "film", "columns": ["title", "status", "rating"], "version": 5 }
206
+ ```
207
+
208
+ Answer:
209
+
210
+ ```json
211
+ {
212
+ "table": "main.public.film",
213
+ "total": 2,
214
+ "rows": [
215
+ {
216
+ "path": "datanotes/main/public/film/Metropolis.md",
217
+ "title": "Metropolis",
218
+ "status": "watched",
219
+ "rating": null
220
+ },
221
+ {
222
+ "path": "datanotes/main/public/film/Nosferatu.md",
223
+ "title": "Nosferatu",
224
+ "status": "watched",
225
+ "rating": 4
226
+ }
227
+ ],
228
+ "version": 5,
229
+ "timestamp": "2026-10-12T07:20:04.642Z"
230
+ }
231
+ ```
232
+
233
+ ## Copy a table as it was
234
+
235
+ `clone_table` with `version`, or with `timestamp` as a date-time, copies the table as it was then into a new table. The copy gets the definition and the rows as independent notes, and the source stays untouched.
236
+
237
+ **`clone_table`**
238
+
239
+ ```json
240
+ { "source": "film", "target": "film_before", "version": 5 }
241
+ ```
242
+
243
+ Answer:
244
+
245
+ ```json
246
+ {
247
+ "ok": true,
248
+ "op": "clone_table",
249
+ "files_created": 2,
250
+ "planned_creates": [
251
+ "datanotes/main/public/film_before/Metropolis.md",
252
+ "datanotes/main/public/film_before/Nosferatu.md"
253
+ ],
254
+ "planned_texts": ["datanotes/metastore.yaml"],
255
+ "commits": [{ "table": "main.public.film_before", "version": 0, "operation": "CLONE" }],
256
+ "migration_id": "20261012T072004-clone_table-clone-main-public-film-to-main"
257
+ }
258
+ ```
259
+
260
+ **`select_rows`**
261
+
262
+ ```json
263
+ { "table": "film_before", "columns": ["title", "status", "rating"] }
264
+ ```
265
+
266
+ Answer:
267
+
268
+ ```json
269
+ {
270
+ "table": "main.public.film_before",
271
+ "total": 2,
272
+ "rows": [
273
+ {
274
+ "path": "datanotes/main/public/film_before/Metropolis.md",
275
+ "title": "Metropolis",
276
+ "status": "watched",
277
+ "rating": null
278
+ },
279
+ {
280
+ "path": "datanotes/main/public/film_before/Nosferatu.md",
281
+ "title": "Nosferatu",
282
+ "status": "watched",
283
+ "rating": 4
284
+ }
285
+ ]
286
+ }
287
+ ```
288
+
289
+ This call names the same moment by its time, taken from the history read above:
290
+
291
+ **`clone_table`**
292
+
293
+ ```json
294
+ {
295
+ "source": "film",
296
+ "target": "film_at",
297
+ "timestamp": "2026-10-12T07:20:04.642Z",
298
+ "copy_rows": false
299
+ }
300
+ ```
301
+
302
+ ## See what changed between two versions
303
+
304
+ `table_changes` returns one entry per row change between two versions. It lists inserts, deletes, and updates, each update as a pre-image and a post-image of the row.
305
+
306
+ **`table_changes`**
307
+
308
+ ```json
309
+ { "table": "film", "start_version": 5 }
310
+ ```
311
+
312
+ Answer:
313
+
314
+ ```json
315
+ {
316
+ "table": "main.public.film",
317
+ "changes": [
318
+ {
319
+ "id": "01a12efb-9f12-7afd-8545-4fec074ff1fb",
320
+ "title": "Metropolis",
321
+ "status": "to watch",
322
+ "path": "datanotes/main/public/film/Metropolis.md",
323
+ "_change_type": "update_preimage",
324
+ "_commit_version": 5,
325
+ "_commit_timestamp": "2026-10-12T07:20:04.642Z",
326
+ "_operation": "UPDATE"
327
+ },
328
+ {
329
+ "id": "01a12efb-9f12-7afd-8545-4fec074ff1fb",
330
+ "title": "Metropolis",
331
+ "status": "watched",
332
+ "path": "datanotes/main/public/film/Metropolis.md",
333
+ "_change_type": "update_postimage",
334
+ "_commit_version": 5,
335
+ "_commit_timestamp": "2026-10-12T07:20:04.642Z",
336
+ "_operation": "UPDATE"
337
+ },
338
+ {
339
+ "id": "01a12efb-9f12-7afd-8545-4fec074ff1fb",
340
+ "title": "Metropolis",
341
+ "status": "watched",
342
+ "path": "datanotes/main/public/film/Metropolis.md",
343
+ "_change_type": "delete",
344
+ "_commit_version": 6,
345
+ "_commit_timestamp": "2026-10-12T07:20:04.648Z",
346
+ "_operation": "DELETE"
347
+ }
348
+ ]
349
+ }
350
+ ```
351
+
352
+ ## Find hand edits in the history
353
+
354
+ When a note changes outside the engine, in an editor, through git or through a sync, the engine records an `EXTERNAL_EDIT` version a moment later.
355
+
356
+ You edit `datanotes/main/public/film/Nosferatu.md` by hand, outside the engine. The note now reads:
357
+
358
+ ```markdown
359
+ ---
360
+ table: main.public.film
361
+ id: 01a12efb-9f0c-7795-aacb-6e9601757026
362
+ title: Nosferatu
363
+ status: watched
364
+ rating: 5
365
+ watched_on: 2026-10-03
366
+ ---
367
+ ```
368
+
369
+ **`describe_history`**
370
+
371
+ ```json
372
+ { "table": "film", "limit": 2 }
373
+ ```
374
+
375
+ Answer:
376
+
377
+ ```json
378
+ {
379
+ "table": "main.public.film",
380
+ "history": [
381
+ {
382
+ "version": 8,
383
+ "timestamp": "2026-10-12T07:20:07.804Z",
384
+ "operation": "EXTERNAL_EDIT",
385
+ "operation_metrics": {
386
+ "num_added_files": 1,
387
+ "num_removed_files": 1,
388
+ "metadata_changed": false,
389
+ "violations": 0
390
+ },
391
+ "engine_info": "datanotes"
392
+ },
393
+ {
394
+ "version": 7,
395
+ "timestamp": "2026-10-12T07:20:04.709Z",
396
+ "operation": "RESTORE",
397
+ "operation_parameters": { "summary": "restore main.public.film to version 5" },
398
+ "migration_id": "20261012T072004-restore_table-restore-main-public-film-to-ve",
399
+ "operation_metrics": {
400
+ "num_added_files": 1,
401
+ "num_removed_files": 0,
402
+ "metadata_changed": false
403
+ },
404
+ "engine_info": "datanotes",
405
+ "user_name": "docs-example",
406
+ "actor": { "session": "history", "harness": "docs-example", "auth": "owner" }
407
+ }
408
+ ]
409
+ }
410
+ ```
411
+
412
+ ## Turn history on for every table
413
+
414
+ `configure_database` with `history: true` turns history on for every table that doesn’t say otherwise. A database the engine creates has it on already. One whose `metastore.yaml` lacks the setting, such as one from a version before 3.0.0, has it off. A table’s own `history`, `true` or `false` with `alter_table`, wins, and `"default"` makes it follow the database again. The journal doesn’t record settings, so an agent changes it only when you ask.
415
+
416
+ **`configure_database`**
417
+
418
+ ```json
419
+ { "history": true }
420
+ ```
421
+
422
+ Answer:
423
+
424
+ ```json
425
+ {
426
+ "default_catalog": "main",
427
+ "default_schema": "public",
428
+ "default_partition": "",
429
+ "default_filename": "YYYY-MM-DD[T]HHmm",
430
+ "archive_folder": "_archive",
431
+ "timezone": "",
432
+ "history": true,
433
+ "autolink": true
434
+ }
435
+ ```
436
+
437
+ **`create_table`**
438
+
439
+ ```json
440
+ {
441
+ "name": "actor",
442
+ "description": "Actors of the films I watch",
443
+ "columns": [
444
+ {
445
+ "name": "name",
446
+ "type": "string",
447
+ "required": true,
448
+ "description": "The actor's name, as credited"
449
+ },
450
+ { "name": "born", "type": "date", "description": "The actor's date of birth" }
451
+ ],
452
+ "filename": "{name}"
453
+ }
454
+ ```
455
+
456
+ **`insert_row`**
457
+
458
+ ```json
459
+ { "table": "actor", "values": { "name": "Rosalind Russell", "born": "1907-06-04" } }
460
+ ```
461
+
462
+ The new table has versions from its creation:
463
+
464
+ **`describe_history`**
465
+
466
+ ```json
467
+ { "table": "actor" }
468
+ ```
469
+
470
+ Answer:
471
+
472
+ ```json
473
+ [{ "version": 1, "operation": "WRITE" }, { "version": 0, "operation": "CREATE TABLE" }]
474
+ ```
475
+
476
+ A table’s own setting wins: `false` keeps the copy `film_before` without history, and `"default"` makes `film_at` follow the database again:
477
+
478
+ **`alter_table`**
479
+
480
+ ```json
481
+ { "table": "film_before", "history": false }
482
+ ```
483
+
484
+ Answer:
485
+
486
+ ```json
487
+ {
488
+ "ok": true,
489
+ "op": "alter_table",
490
+ "planned_texts": ["datanotes/metastore.yaml"],
491
+ "migration_id": "20261012T072013-alter_table-alter-table-main-public-film_b"
492
+ }
493
+ ```
494
+
495
+ **`alter_table`**
496
+
497
+ ```json
498
+ { "table": "film_at", "history": "default" }
499
+ ```
500
+
501
+ Answer:
502
+
503
+ ```json
504
+ {
505
+ "ok": true,
506
+ "op": "alter_table",
507
+ "planned_texts": ["datanotes/metastore.yaml"],
508
+ "commits": [
509
+ { "table": "main.public.film_at", "version": 1, "operation": "ALTER TABLE" }
510
+ ],
511
+ "migration_id": "20261012T072013-alter_table-alter-table-main-public-film_a"
512
+ }
513
+ ```
514
+
515
+ ## See the history settings in `metastore.yaml`
516
+
517
+ History is a setting of the definition. `alter_table` writes `history: true` under the table’s `options`, `false` writes `false`, and `"default"` removes the key. For the whole database, the setting is under `config`. The copies made on this page are tables of their own.
518
+
519
+ `datanotes/metastore.yaml` now reads:
520
+
521
+ ```yaml
522
+ # Metastore (Datanotes): catalogs, schemas, tables, columns, views.
523
+ id: 01a12efb-9ef8-7ceb-9b54-14318eb9becb
524
+ config:
525
+ history: true
526
+
527
+
528
+ catalogs:
529
+ main:
530
+ schemas:
531
+ public:
532
+ tables:
533
+ film:
534
+ description: Classic films I watched or want to watch
535
+ options:
536
+ filename: "{title}"
537
+ archive: _archive
538
+ history: true
539
+ columns:
540
+ - name: id
541
+ type: string
542
+ unique: true
543
+ identity: uuid
544
+ required: true
545
+ dense: true
546
+ description: "Unique id of the row (UUIDv7): set when the row is created, never changes"
547
+ - name: title
548
+ type: string
549
+ required: true
550
+ description: The film's title, as on its poster
551
+ unique: true
552
+ - name: status
553
+ type: enum
554
+ default: to watch
555
+ values:
556
+ - to watch
557
+ - watched
558
+ description: Where the film is on my list
559
+ ordered: true
560
+ - name: rating
561
+ type: integer
562
+ min: 1
563
+ max: 5
564
+ description: My rating, from 1 (poor) to 5 (a masterpiece)
565
+ - name: watched_on
566
+ type: date
567
+ description: The day I last watched it
568
+ film_before:
569
+ description: Classic films I watched or want to watch
570
+ options:
571
+ filename: "{title}"
572
+ archive: _archive
573
+ history: false
574
+ columns:
575
+ - name: id
576
+ type: string
577
+ unique: true
578
+ identity: uuid
579
+ required: true
580
+ dense: true
581
+ description: "Unique id of the row (UUIDv7): set when the row is created, never changes"
582
+ - name: title
583
+ type: string
584
+ required: true
585
+ description: The film's title, as on its poster
586
+ unique: true
587
+ - name: status
588
+ type: enum
589
+ default: to watch
590
+ values:
591
+ - to watch
592
+ - watched
593
+ description: Where the film is on my list
594
+ ordered: true
595
+ - name: rating
596
+ type: integer
597
+ min: 1
598
+ max: 5
599
+ description: My rating, from 1 (poor) to 5 (a masterpiece)
600
+ - name: watched_on
601
+ type: date
602
+ description: The day I last watched it
603
+ film_at:
604
+ description: Classic films I watched or want to watch
605
+ options:
606
+ filename: "{title}"
607
+ archive: _archive
608
+ columns:
609
+ - name: id
610
+ type: string
611
+ unique: true
612
+ identity: uuid
613
+ required: true
614
+ dense: true
615
+ description: "Unique id of the row (UUIDv7): set when the row is created, never changes"
616
+ - name: title
617
+ type: string
618
+ required: true
619
+ description: The film's title, as on its poster
620
+ unique: true
621
+ - name: status
622
+ type: enum
623
+ default: to watch
624
+ values:
625
+ - to watch
626
+ - watched
627
+ description: Where the film is on my list
628
+ ordered: true
629
+ - name: rating
630
+ type: integer
631
+ min: 1
632
+ max: 5
633
+ description: My rating, from 1 (poor) to 5 (a masterpiece)
634
+ - name: watched_on
635
+ type: date
636
+ description: The day I last watched it
637
+ actor:
638
+ description: Actors of the films I watch
639
+ options:
640
+ filename: "{name}"
641
+ archive: _archive
642
+ columns:
643
+ - name: id
644
+ type: string
645
+ required: true
646
+ description: "Unique id of the row (UUIDv7): set when the row is created, never changes"
647
+ unique: true
648
+ identity: uuid
649
+ dense: true
650
+ - name: name
651
+ type: string
652
+ required: true
653
+ description: The actor's name, as credited
654
+ - name: born
655
+ type: date
656
+ description: The actor's date of birth
657
+ ```
@@ -0,0 +1,35 @@
1
+ # Vacuum old history
2
+
3
+ > Trim a table’s old versions with vacuum_table to keep its transaction log small.
4
+
5
+ A table’s transaction log grows with what you write. `vacuum_table` deletes the history older than `retain_from_version`, by default every version but the latest, so time travel and restores reach back only that far. The rows stay as they are. It isn’t journaled and can’t be undone, so its `dry_run` is on by default: it lists the log files that would go.
6
+
7
+ ## Trim old history with `vacuum_table`
8
+
9
+ `vacuum_table` deletes log history older than a version. You can no longer time travel to an earlier version, and the rows stay untouched. It’s a dry run unless you pass `dry_run: false`, and an agent runs it only when you ask.
10
+
11
+ **`vacuum_table`**
12
+
13
+ ```json
14
+ { "table": "film" }
15
+ ```
16
+
17
+ Answer:
18
+
19
+ ```json
20
+ {
21
+ "table": "main.public.film",
22
+ "retained_from": 8,
23
+ "deleted": [
24
+ "store:transaction_log/main.public.film/00000000000000000000.json",
25
+ "store:transaction_log/main.public.film/00000000000000000001.json",
26
+ "store:transaction_log/main.public.film/00000000000000000002.json",
27
+ "store:transaction_log/main.public.film/00000000000000000003.json",
28
+ "store:transaction_log/main.public.film/00000000000000000004.json",
29
+ "store:transaction_log/main.public.film/00000000000000000005.json",
30
+ "store:transaction_log/main.public.film/00000000000000000006.json",
31
+ "store:transaction_log/main.public.film/00000000000000000007.json"
32
+ ],
33
+ "dry_run": true
34
+ }
35
+ ```