datanotes 3.1.0 → 3.2.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/dist/api/index.cjs +175 -8
- package/dist/api/index.js +175 -8
- package/dist/api/mcp.cjs +175 -8
- package/dist/api/mcp.js +175 -8
- package/dist/datanotes.cjs +591 -139
- package/dist/docs/api/operations/add_column.md +1 -0
- package/dist/docs/api/operations/add_constraint.md +2 -0
- package/dist/docs/api/operations/alter_column.md +1 -1
- package/dist/docs/api/operations/alter_table.md +3 -2
- package/dist/docs/api/operations/check_table.md +1 -1
- package/dist/docs/api/operations/create_table.md +3 -1
- package/dist/docs/api/operations/describe_table.md +1 -1
- package/dist/docs/api/operations/insert_row.md +2 -2
- package/dist/docs/api/operations/tags/rows-dml.md +1 -1
- package/dist/docs/api.md +2 -2
- package/dist/docs/guides/data-quality/check-constraints.md +14 -13
- package/dist/docs/guides/data-quality/hand-edits.md +10 -10
- package/dist/docs/guides/database-objects/bases.md +11 -11
- package/dist/docs/guides/database-objects/catalogs-and-schemas.md +16 -10
- package/dist/docs/guides/database-objects/columns.md +38 -38
- package/dist/docs/guides/database-objects/relations.md +173 -36
- package/dist/docs/guides/database-objects/tables.md +80 -35
- package/dist/docs/guides/database-objects/views.md +44 -44
- package/dist/docs/guides/history/change-data-feed.md +34 -34
- package/dist/docs/guides/history/journal-and-undo.md +12 -12
- package/dist/docs/guides/history/restore.md +20 -20
- package/dist/docs/guides/history/table-history.md +31 -31
- package/dist/docs/guides/read-and-write/automatic-links.md +15 -15
- package/dist/docs/guides/read-and-write/import-notes.md +21 -21
- package/dist/docs/guides/read-and-write/joins-and-aggregates.md +7 -7
- package/dist/docs/guides/read-and-write/read-and-filter.md +10 -10
- package/dist/docs/guides/read-and-write/write-rows.md +10 -10
- package/dist/docs/guides/search/text.md +1 -1
- package/dist/docs/reference/cli.md +1 -1
- package/dist/docs/reference/errors.md +1 -1
- package/dist/docs/reference/operations/auxiliary.md +2 -2
- package/dist/docs/reference/operations/rows.md +1 -1
- package/dist/docs/reference/operations/schema.md +15 -11
- package/dist/docs/reference/operations.md +28 -28
- package/dist/docs/release-notes.md +24 -0
- package/package.json +1 -1
|
@@ -13,6 +13,7 @@ Column names are permanent identifiers; only `rename_column` changes them.
|
|
|
13
13
|
Enum columns: `values` and, for each, its meaning in `value_descriptions` (`{"stated": "the user said it", …}`): describe_table shows them and a refused value lists them.
|
|
14
14
|
Generated link columns: `generated: "link({occurred_at:YYYY-MM-DD})"` with `ref` = the days table links each row to the row of `ref` named by the template (its folder read from the schema; the target may not exist yet).
|
|
15
15
|
Filtered link targets (link columns): `ref_where` (a `where` every target must match) and `ref_by` (a column of the row picks the target level: `{"column": "kind", "levels": ["area", "project", "workstream"]}` or `{"column": "kind", "map": {"area": null, "project": ["area"]}}`; null = top level, no link; `target_column` when the target names it differently: an enum target column must have every value the map allows, a string one takes any value). A link to no row of the table, or to the row itself, is refused too. Existing rows that break them refuse the change; `list_link_targets` lists the valid targets of a row.
|
|
16
|
+
Acyclic links: `acyclic: true` on a link (or list of links) to the table itself refuses every write that closes a cycle, on either side of an `inverse`; refused while existing rows form one (they are listed).
|
|
16
17
|
|
|
17
18
|
The schema changes only through operations like this one: never edit metastore.yaml by hand (no validation, no undo).
|
|
18
19
|
|
|
@@ -18,6 +18,7 @@ A write that changes a linked row re-checks the rows that link to it and is refu
|
|
|
18
18
|
it breaks them, naming the changed row (in a batch, re-link them first: each step is checked on the vault
|
|
19
19
|
the earlier ones left); the inverse links a write adds, undo_migration and restore_table are checked too.
|
|
20
20
|
rename_column / rename_value follow into CHECKs; drop_column of a column a CHECK reads is refused.
|
|
21
|
+
`hint`: what to do when a row breaks the rule, in your words; a refused write puts it first in its hint, and each violation of the CHECK carries it.
|
|
21
22
|
|
|
22
23
|
The schema changes only through operations like this one: never edit metastore.yaml by hand (no validation, no undo).
|
|
23
24
|
|
|
@@ -36,6 +37,7 @@ The schema changes only through operations like this one: never edit metastore.y
|
|
|
36
37
|
| `table` | `string` | yes | | |
|
|
37
38
|
| `name` | `string` | yes | | |
|
|
38
39
|
| `check` | `object` | yes | | |
|
|
40
|
+
| `hint` | `string \| null` | no | `null` | What a refused write tells the agent when a row breaks this CHECK: how to fix the row. It comes first in the refusal's hint; describe_table lists it in constraint_hints. |
|
|
39
41
|
| `dry_run` | `boolean` | no | `false` | |
|
|
40
42
|
|
|
41
43
|
## Responses
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
`POST /datanotes/operations/alter_column/` (operation `alter_column`)
|
|
4
4
|
|
|
5
5
|
Change a column's attributes (type, min/max/step, values, required, default, label,
|
|
6
|
-
aliases, description, note, `ref_where`, `ref_by` (see list_link_targets); `null` removes an attribute, except
|
|
6
|
+
aliases, description, note, `ref_where`, `ref_by` (see list_link_targets), `acyclic` (refused while the rows already form a cycle: they are listed); `null` removes an attribute, except
|
|
7
7
|
`description`, which changes but never goes (null or "" is refused); `dense` true/false). Refused with
|
|
8
8
|
the list of violating rows when existing values do not satisfy the new definition. A
|
|
9
9
|
different scale means a different column: add a new one instead of rescaling. To rename one
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
Alter a table: move it (`catalog`, `schema`), rename it (`name`), change
|
|
6
6
|
`partition` / `filename` patterns, `description` (changes, never goes: "" is refused), `aliases`,
|
|
7
7
|
`exclude` folders, `row_template`
|
|
8
|
-
("" removes it), `history` (true | false | "default"), `autolink_target`
|
|
8
|
+
("" removes it), `instructions` (how to fill a row, for agents; "" removes them), `history` (true | false | "default"), `autolink_target`
|
|
9
9
|
(true | false | "default": may automatic links link its rows? default: yes, unless its rows are named by
|
|
10
10
|
a date or a time) or `tags` (key/value
|
|
11
11
|
labels merged into the table's, e.g. `{"domain": "health"}`; a `null` value removes that tag;
|
|
@@ -13,7 +13,7 @@ labels merged into the table's, e.g. `{"domain": "health"}`; a `null` value remo
|
|
|
13
13
|
`archive` (folder name inside the table folder) or `fields` (untyped fields, name → default; a
|
|
14
14
|
`null` value removes one). Rows, archive and transaction log follow; links are updated; renamed
|
|
15
15
|
rows keep their old name in `aliases`. A change of metadata only (tags, description, aliases,
|
|
16
|
-
history, autolink_target, row_template, fields) rewrites the table entry alone: no row is moved or rewritten. Refused
|
|
16
|
+
history, autolink_target, row_template, instructions, fields) rewrites the table entry alone: no row is moved or rewritten. Refused
|
|
17
17
|
when a row cannot fill a pattern. Renaming or moving the table is refused while a CHECK that follows
|
|
18
18
|
links, or a `ref_where` / `ref_by`, of another table reads it through a link (link targets are not
|
|
19
19
|
rewritten): the conflicts name them. Use `dry_run` to see `planned_moves`; undo with undo_migration.
|
|
@@ -44,6 +44,7 @@ The schema changes only through operations like this one: never edit metastore.y
|
|
|
44
44
|
| `autolink_target` | `boolean \| "default" \| null` | no | `null` | May automatic links link the table's rows? true, false, or "default" (yes, unless its rows are named by a date or a time). |
|
|
45
45
|
| `exclude` | `string[] \| null` | no | `null` | |
|
|
46
46
|
| `row_template` | `string \| null` | no | `null` | Markdown body of new rows; "" removes it. |
|
|
47
|
+
| `instructions` | `string \| null` | no | `null` | How to fill a row, for agents (Markdown); "" removes them. |
|
|
47
48
|
| `tags` | `object \| null` | no | `null` | Tags to add or change (strings); a null value removes that tag. The other tags are kept. |
|
|
48
49
|
| `clear_tags` | `boolean` | no | `false` | Remove every tag first (with `tags`: the table keeps exactly those). |
|
|
49
50
|
| `archive` | `string \| null` | no | `null` | Archive folder: a folder name inside the table folder (e.g. "_archive"); "" = the database default (`archive_folder`). Archived rows follow. |
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
`POST /datanotes/operations/check_table/` (operation `check_table`)
|
|
4
4
|
|
|
5
5
|
Validate every row against the table (required, types, ranges, enums, links, unknown
|
|
6
|
-
columns, CHECK constraints, those that follow links included, filtered link targets (ref_where / ref_by), stale generated/identity values, missing inverse links, front matter that cannot be read: code `unreadable`, with no column, for a note whose `table` line names the table but whose YAML is broken, which every other read leaves out). A CHECK violation has code `check` and the CHECK's name as `constraint` (every other code names its `column`), as in the `violations` of list_changes. Use it to find rows edited by hand that break the schema. Without `table`, every table is checked: each row then names its `table`, `tables_checked` counts the tables checked, and a table that cannot be checked is listed in `errors` ({table, error}) while the others are. The rows with violations are paged: `limit` (default 500, at most 5000) from `offset`; `total` counts them all. (Hand edits are also checked as they happen: see `violations` in list_changes.)
|
|
6
|
+
columns, CHECK constraints, those that follow links included, filtered link targets (ref_where / ref_by), stale generated/identity values, missing inverse links, cycles of hierarchy and acyclic columns, front matter that cannot be read: code `unreadable`, with no column, for a note whose `table` line names the table but whose YAML is broken, which every other read leaves out). A CHECK violation has code `check` and the CHECK's name as `constraint` (every other code names its `column`), as in the `violations` of list_changes. Use it to find rows edited by hand that break the schema. Without `table`, every table is checked: each row then names its `table`, `tables_checked` counts the tables checked, and a table that cannot be checked is listed in `errors` ({table, error}) while the others are. The rows with violations are paged: `limit` (default 500, at most 5000) from `offset`; `total` counts them all. (Hand edits are also checked as they happen: see `violations` in list_changes.)
|
|
7
7
|
|
|
8
8
|
## Request body
|
|
9
9
|
|
|
@@ -16,7 +16,7 @@ digits, `_` (no dots: pass the catalog and the schema as their own arguments).
|
|
|
16
16
|
order: filters/avg use the position), ref (link target, full `catalog.schema.table` or "self"),
|
|
17
17
|
unique, label, description, aliases, `generated` (e.g. `"date(occurred_at)"`, `"{name} {surname}"`),
|
|
18
18
|
`identity` ("filename" | "created"), `vocabulary` (allowed values = names of another table's rows),
|
|
19
|
-
`hierarchy: true` (one parent link to its own table), `dense` (written on every row),
|
|
19
|
+
`hierarchy: true` (one parent link to its own table), `acyclic: true` (links to rows of its own table that never loop back, such as tasks blocked by tasks; with `inverse`, the rule holds on both sides), `dense` (written on every row),
|
|
20
20
|
`inverse` on a link column: the column of the `ref` table that links back (`friends` ↔
|
|
21
21
|
`friends`, `children` ↔ `parents`, `partner` ↔ `partner`); writes keep both sides in step.
|
|
22
22
|
- `time_column`: rows named by that date/datetime; otherwise `filename` (e.g. `"{name}"`).
|
|
@@ -25,6 +25,7 @@ digits, `_` (no dots: pass the catalog and the schema as their own arguments).
|
|
|
25
25
|
database's setting), `autolink_target` (true / false: may automatic links link its rows? default:
|
|
26
26
|
yes, unless its rows are named by a date or a time, as with `time_column`).
|
|
27
27
|
- `row_template`: markdown body of new rows. Shared columns come from bases: `set_table_bases`.
|
|
28
|
+
- `instructions`: how to fill a row, for agents (Markdown); describe_table returns them.
|
|
28
29
|
- `tags`: key/value labels of the table, strings (`{"domain": "health"}`); list_tables and
|
|
29
30
|
describe_table return them, alter_table changes them.
|
|
30
31
|
Enum columns: `values` and, for each, its meaning in `value_descriptions` (`{"stated": "the user said it", …}`): describe_table shows them and a refused value lists them.
|
|
@@ -59,6 +60,7 @@ The schema changes only through operations like this one: never edit metastore.y
|
|
|
59
60
|
| `history` | `boolean \| null` | no | `null` | Keep the table's versions (time travel, restore); default: the database's setting. |
|
|
60
61
|
| `autolink_target` | `boolean \| null` | no | `null` | May automatic links link the table's rows? Default: yes, unless its rows are named by a date or a time. |
|
|
61
62
|
| `row_template` | `string \| null` | no | `null` | Markdown body of new rows; {column} placeholders are filled from the row. |
|
|
63
|
+
| `instructions` | `string \| null` | no | `null` | How to fill a row, for agents (Markdown): which columns first, what to ask the user. describe_table returns them. |
|
|
62
64
|
| `fields` | `object \| null` | no | `null` | Untyped fields of the table (name → default), kept on every row; a field cannot share a name with a column. |
|
|
63
65
|
| `tags` | `object \| null` | no | `null` | Key/value labels of the table (strings), e.g. {"domain": "health"}. |
|
|
64
66
|
| `dry_run` | `boolean` | no | `false` | |
|
|
@@ -6,7 +6,7 @@ Describe a table (`catalog.schema.table` or a shorter unambiguous name): `qualif
|
|
|
6
6
|
`catalog`, `schema`, `description`, `aliases`, `layout` (`folder`, `row_folder`: the folder pattern
|
|
7
7
|
of new rows, `archive`), `options` (`partition`, `filename`, `archive`, `exclude`), typed `columns`
|
|
8
8
|
with label/aliases/description and the dense flag, `untyped_fields`, `row_count`, and when set:
|
|
9
|
-
`tags`, `bases` (the bases it inherits from, in order), `constraints` (its CHECKs, name → where), `row_template`, `history`,
|
|
9
|
+
`tags`, `bases` (the bases it inherits from, in order), `constraints` (its CHECKs, name → where), `constraint_hints` (their own hints, name → hint), `instructions` (how to fill a row: follow them before you write one), `row_template`, `history`,
|
|
10
10
|
`autolink_target`, `fields` (their values).
|
|
11
11
|
|
|
12
12
|
Before adding a column (e.g. a new metric), read `columns` and match your concept against
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
# Insert a row (new note). Values are validated against the columns; the note path comes from
|
|
1
|
+
# Insert a row (new note). When describe_table gives the table's `instructions`, fill the row as they say. Values are validated against the columns; the note path comes from
|
|
2
2
|
|
|
3
3
|
`POST /datanotes/operations/insert_row/` (operation `insert_row`)
|
|
4
4
|
|
|
5
|
-
Insert a row (new note). Values are validated against the columns; the note path comes from
|
|
5
|
+
Insert a row (new note). When describe_table gives the table's `instructions`, fill the row as they say. Values are validated against the columns; the note path comes from
|
|
6
6
|
the table's `path`/`filename` patterns (e.g. an event logged today about last night lands in
|
|
7
7
|
last night's day folder when you set `occurred_at` to last night). `body` is the note text.
|
|
8
8
|
Generated / identity columns are computed (do not pass them); CHECK constraints are enforced.
|
|
@@ -4,7 +4,7 @@ Operations that write rows: insert, update, merge, delete, move, adopt and batch
|
|
|
4
4
|
|
|
5
5
|
## Operations
|
|
6
6
|
|
|
7
|
-
- [Insert a row (new note). Values are validated against the columns; the note path comes from](https://datanotes.dev/api/operations/insert_row/): `POST /datanotes/operations/insert_row/`
|
|
7
|
+
- [Insert a row (new note). When describe_table gives the table's `instructions`, fill the row as they say. Values are validated against the columns; the note path comes from](https://datanotes.dev/api/operations/insert_row/): `POST /datanotes/operations/insert_row/`
|
|
8
8
|
- [Update every row matching `where` (required: `{}` is every row). `where`: keys AND-ed; values are equality or operators](https://datanotes.dev/api/operations/update_rows/): `POST /datanotes/operations/update_rows/`
|
|
9
9
|
- [Update exactly ONE row, addressed by its `id` (the system UUID) or its `path`; refused when](https://datanotes.dev/api/operations/update_row/): `POST /datanotes/operations/update_row/`
|
|
10
10
|
- [Delete rows matching `where`. `mode`: "archive" (default, move to the table's archive](https://datanotes.dev/api/operations/delete_rows/): `POST /datanotes/operations/delete_rows/`
|
package/dist/docs/api.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Datanotes HTTP API
|
|
2
2
|
|
|
3
|
-
> OpenAPI 3.1.0 description of the Datanotes 3.
|
|
3
|
+
> OpenAPI 3.1.0 description of the Datanotes 3.2.0 HTTP API: https://datanotes.dev/openapi.json
|
|
4
4
|
|
|
5
5
|
Database of Markdown notes: tables of notes, rows, queries, history, a change feed and the vault's notes.
|
|
6
6
|
|
|
@@ -47,7 +47,7 @@ Operations that define the database: tables, columns, constraints, bases and vie
|
|
|
47
47
|
|
|
48
48
|
Operations that write rows: insert, update, merge, delete, move, adopt and batch.
|
|
49
49
|
|
|
50
|
-
- [Insert a row (new note). Values are validated against the columns; the note path comes from](https://datanotes.dev/api/operations/insert_row/): `POST /datanotes/operations/insert_row/`
|
|
50
|
+
- [Insert a row (new note). When describe_table gives the table's `instructions`, fill the row as they say. Values are validated against the columns; the note path comes from](https://datanotes.dev/api/operations/insert_row/): `POST /datanotes/operations/insert_row/`
|
|
51
51
|
- [Update every row matching `where` (required: `{}` is every row). `where`: keys AND-ed; values are equality or operators](https://datanotes.dev/api/operations/update_rows/): `POST /datanotes/operations/update_rows/`
|
|
52
52
|
- [Update exactly ONE row, addressed by its `id` (the system UUID) or its `path`; refused when](https://datanotes.dev/api/operations/update_row/): `POST /datanotes/operations/update_row/`
|
|
53
53
|
- [Delete rows matching `where`. `mode`: "archive" (default, move to the table's archive](https://datanotes.dev/api/operations/delete_rows/): `POST /datanotes/operations/delete_rows/`
|
|
@@ -6,7 +6,7 @@ A CHECK constraint is a rule written as a `where` filter, such as “a watched f
|
|
|
6
6
|
|
|
7
7
|
## Enforce rules with CHECK constraints
|
|
8
8
|
|
|
9
|
-
`add_constraint` adds a CHECK constraint, a rule every row must satisfy, written as a `where` filter. The engine refuses it while existing rows break the rule and lists them; after that, it enforces the rule on every write. A condition on a column the row leaves empty passes, as in Structured Query Language (SQL). Inside `or`, `and` and `not`, the engine tests an empty value as it is, so a watched film without a `rating` breaks `rated_when_watched`.
|
|
9
|
+
`add_constraint` adds a CHECK constraint, a rule every row must satisfy, written as a `where` filter. The engine refuses it while existing rows break the rule and lists them; after that, it enforces the rule on every write. A condition on a column the row leaves empty passes, as in Structured Query Language (SQL). Inside `or`, `and` and `not`, the engine tests an empty value as it is, so a watched film without a `rating` breaks `rated_when_watched`. `hint` says what to do when a row breaks the rule. The refusal puts it first, and `describe_table` lists it in `constraint_hints`.
|
|
10
10
|
|
|
11
11
|
**`add_constraint`**
|
|
12
12
|
|
|
@@ -14,7 +14,8 @@ A CHECK constraint is a rule written as a `where` filter, such as “a watched f
|
|
|
14
14
|
{
|
|
15
15
|
"table": "film",
|
|
16
16
|
"name": "rated_when_watched",
|
|
17
|
-
"check": { "or": [{ "status": { "ne": "watched" } }, { "rating": { "exists": true } }] }
|
|
17
|
+
"check": { "or": [{ "status": { "ne": "watched" } }, { "rating": { "exists": true } }] },
|
|
18
|
+
"hint": "A watched film needs a rating from 1 to 5: ask me for it."
|
|
18
19
|
}
|
|
19
20
|
```
|
|
20
21
|
|
|
@@ -28,7 +29,7 @@ Answer:
|
|
|
28
29
|
"commits": [
|
|
29
30
|
{ "table": "diary.classics.film", "version": 8, "operation": "ADD CONSTRAINT" }
|
|
30
31
|
],
|
|
31
|
-
"migration_id": "
|
|
32
|
+
"migration_id": "20261019T040655-add_constraint-add-constraint-rated_when_watc"
|
|
32
33
|
}
|
|
33
34
|
```
|
|
34
35
|
|
|
@@ -57,7 +58,7 @@ Refused:
|
|
|
57
58
|
```text
|
|
58
59
|
insert_row refused — nothing was written:
|
|
59
60
|
invalid datanotes/diary/classics/film/His Girl Friday.md: rated_when_watched violates CHECK rated_when_watched: {"or":[{"status":{"ne":"watched"}},{"rating":{"exists":true}}]}
|
|
60
|
-
Hint: The row breaks a CHECK constraint of the table (named in the message, with its rule): change the values so the rule holds. describe_table lists the table's constraints. Then call insert_row again (dry_run: true checks without writing).
|
|
61
|
+
Hint: A watched film needs a rating from 1 to 5: ask me for it. The row breaks a CHECK constraint of the table (named in the message, with its rule): change the values so the rule holds. describe_table lists the table's constraints. Then call insert_row again (dry_run: true checks without writing).
|
|
61
62
|
Docs: https://datanotes.dev/guides/data-quality/check-constraints.md#enforce-rules-with-check-constraints (offline: read_docs("guides/data-quality/check-constraints#enforce-rules-with-check-constraints"))
|
|
62
63
|
```
|
|
63
64
|
|
|
@@ -85,7 +86,7 @@ Answer:
|
|
|
85
86
|
"files_created": 1,
|
|
86
87
|
"planned_creates": ["datanotes/diary/classics/film/His Girl Friday.md"],
|
|
87
88
|
"commits": [{ "table": "diary.classics.film", "version": 10, "operation": "WRITE" }],
|
|
88
|
-
"migration_id": "
|
|
89
|
+
"migration_id": "20261019T040655-insert_row-insert-into-film-2"
|
|
89
90
|
}
|
|
90
91
|
```
|
|
91
92
|
|
|
@@ -107,7 +108,7 @@ Answer:
|
|
|
107
108
|
"commits": [
|
|
108
109
|
{ "table": "diary.classics.film", "version": 11, "operation": "DROP CONSTRAINT" }
|
|
109
110
|
],
|
|
110
|
-
"migration_id": "
|
|
111
|
+
"migration_id": "20261019T040655-drop_constraint-drop-constraint-at_most_three_"
|
|
111
112
|
}
|
|
112
113
|
```
|
|
113
114
|
|
|
@@ -148,7 +149,7 @@ Answer:
|
|
|
148
149
|
"commits": [
|
|
149
150
|
{ "table": "main.public.genre", "version": 4, "operation": "ADD CONSTRAINT" }
|
|
150
151
|
],
|
|
151
|
-
"migration_id": "
|
|
152
|
+
"migration_id": "20261019T040641-add_constraint-add-constraint-parent_by_level"
|
|
152
153
|
}
|
|
153
154
|
```
|
|
154
155
|
|
|
@@ -227,34 +228,34 @@ Answer:
|
|
|
227
228
|
"ok": true,
|
|
228
229
|
"op": "batch",
|
|
229
230
|
"dry_run": false,
|
|
230
|
-
"migration_id": "
|
|
231
|
+
"migration_id": "20261019T040641-batch-add-the-silent-era-and-slapsti",
|
|
231
232
|
"steps": [
|
|
232
233
|
{
|
|
233
234
|
"index": 0,
|
|
234
235
|
"op": "insert_row",
|
|
235
236
|
"ok": true,
|
|
236
|
-
"migration_id": "
|
|
237
|
+
"migration_id": "20261019T040641-insert_row-insert-into-genre",
|
|
237
238
|
"result": {
|
|
238
239
|
"ok": true,
|
|
239
240
|
"op": "insert_row",
|
|
240
241
|
"files_created": 1,
|
|
241
242
|
"planned_creates": ["datanotes/main/public/genre/Silent cinema.md"],
|
|
242
243
|
"commits": [{ "table": "main.public.genre", "version": 5, "operation": "WRITE" }],
|
|
243
|
-
"migration_id": "
|
|
244
|
+
"migration_id": "20261019T040641-insert_row-insert-into-genre"
|
|
244
245
|
}
|
|
245
246
|
},
|
|
246
247
|
{
|
|
247
248
|
"index": 1,
|
|
248
249
|
"op": "insert_row",
|
|
249
250
|
"ok": true,
|
|
250
|
-
"migration_id": "
|
|
251
|
+
"migration_id": "20261019T040641-insert_row-insert-into-genre-2",
|
|
251
252
|
"result": {
|
|
252
253
|
"ok": true,
|
|
253
254
|
"op": "insert_row",
|
|
254
255
|
"files_created": 1,
|
|
255
256
|
"planned_creates": ["datanotes/main/public/genre/Slapstick comedy.md"],
|
|
256
257
|
"commits": [{ "table": "main.public.genre", "version": 6, "operation": "WRITE" }],
|
|
257
|
-
"migration_id": "
|
|
258
|
+
"migration_id": "20261019T040641-insert_row-insert-into-genre-2"
|
|
258
259
|
}
|
|
259
260
|
}
|
|
260
261
|
]
|
|
@@ -342,7 +343,7 @@ Answer:
|
|
|
342
343
|
}
|
|
343
344
|
],
|
|
344
345
|
"commits": [{ "table": "main.public.genre", "version": 7, "operation": "UPDATE" }],
|
|
345
|
-
"migration_id": "
|
|
346
|
+
"migration_id": "20261019T040641-update_row-update-genre"
|
|
346
347
|
}
|
|
347
348
|
```
|
|
348
349
|
|
|
@@ -35,7 +35,7 @@ You edit `datanotes/main/public/genre/Silent film.md` by hand, outside the engin
|
|
|
35
35
|
```markdown
|
|
36
36
|
---
|
|
37
37
|
table: main.public.genre
|
|
38
|
-
id:
|
|
38
|
+
id: 01a15257-1485-7217-8806-89c6ca196427
|
|
39
39
|
name: Silent film
|
|
40
40
|
kind: cinema
|
|
41
41
|
parent: "[[Cinema]]"
|
|
@@ -47,7 +47,7 @@ Read the hand edit’s event. `list_changes` long-polls with `wait_ms` until the
|
|
|
47
47
|
**`list_changes`**
|
|
48
48
|
|
|
49
49
|
```json
|
|
50
|
-
{ "since":
|
|
50
|
+
{ "since": 45, "tables": ["genre"], "wait_ms": 10000 }
|
|
51
51
|
```
|
|
52
52
|
|
|
53
53
|
Answer:
|
|
@@ -55,7 +55,7 @@ Answer:
|
|
|
55
55
|
```json
|
|
56
56
|
[
|
|
57
57
|
{
|
|
58
|
-
"seq":
|
|
58
|
+
"seq": 46,
|
|
59
59
|
"kind": "update",
|
|
60
60
|
"path": "datanotes/main/public/genre/Silent film.md",
|
|
61
61
|
"source": "external",
|
|
@@ -152,7 +152,7 @@ Answer:
|
|
|
152
152
|
}
|
|
153
153
|
],
|
|
154
154
|
"commits": [{ "table": "main.public.genre", "version": 9, "operation": "UPDATE" }],
|
|
155
|
-
"migration_id": "
|
|
155
|
+
"migration_id": "20261019T040642-update_row-update-genre"
|
|
156
156
|
}
|
|
157
157
|
```
|
|
158
158
|
|
|
@@ -167,7 +167,7 @@ You edit `datanotes/main/public/watch/2026-10-03T2130.md` by hand, outside the e
|
|
|
167
167
|
```markdown
|
|
168
168
|
---
|
|
169
169
|
table: main.public.watch
|
|
170
|
-
id:
|
|
170
|
+
id: 01a15257-0c9b-7856-9c12-bebb7eaf82e5
|
|
171
171
|
film: His Girl Friday
|
|
172
172
|
occurred_at: 2026-10-03T21:30
|
|
173
173
|
where: cinema
|
|
@@ -226,7 +226,7 @@ Answer:
|
|
|
226
226
|
}
|
|
227
227
|
],
|
|
228
228
|
"commits": [{ "table": "main.public.watch", "version": 3, "operation": "RECOMPUTE" }],
|
|
229
|
-
"migration_id": "
|
|
229
|
+
"migration_id": "20261019T040640-recompute_columns-recompute-id-day-label-of-watc"
|
|
230
230
|
}
|
|
231
231
|
```
|
|
232
232
|
|
|
@@ -292,7 +292,7 @@ Answer:
|
|
|
292
292
|
```markdown
|
|
293
293
|
---
|
|
294
294
|
table: main.public.watch
|
|
295
|
-
id:
|
|
295
|
+
id: 01a15257-70f0-7ede-9186-f790fe037b07
|
|
296
296
|
occurred_at: 2026-09-25T21:00
|
|
297
297
|
film: "[[Charade]]"
|
|
298
298
|
where: home
|
|
@@ -311,7 +311,7 @@ You edit `datanotes/main/public/film/Metropolis.md` by hand, outside the engine.
|
|
|
311
311
|
```markdown
|
|
312
312
|
---
|
|
313
313
|
table: main.public.film
|
|
314
|
-
id:
|
|
314
|
+
id: 01a15257-31bb-7113-b86a-5d6fdca79420
|
|
315
315
|
year: 1927
|
|
316
316
|
minutes: 153
|
|
317
317
|
status: to watch
|
|
@@ -384,7 +384,7 @@ You edit `datanotes/main/public/film/Sherlock Jr..md` by hand, outside the engin
|
|
|
384
384
|
```markdown
|
|
385
385
|
---
|
|
386
386
|
table: main.public.film
|
|
387
|
-
id:
|
|
387
|
+
id: 01a15257-1cbb-7591-97e2-5b880ad79d39
|
|
388
388
|
title: Sherlock Jr.: the projectionist
|
|
389
389
|
year: 1924
|
|
390
390
|
status: watched
|
|
@@ -471,7 +471,7 @@ You edit `datanotes/main/public/film/Sherlock Jr..md` by hand, outside the engin
|
|
|
471
471
|
```markdown
|
|
472
472
|
---
|
|
473
473
|
table: main.public.film
|
|
474
|
-
id:
|
|
474
|
+
id: 01a15257-1cbb-7591-97e2-5b880ad79d39
|
|
475
475
|
title: "Sherlock Jr.: the projectionist"
|
|
476
476
|
year: 1924
|
|
477
477
|
status: watched
|
|
@@ -30,7 +30,7 @@ Answer:
|
|
|
30
30
|
"ok": true,
|
|
31
31
|
"op": "define_base",
|
|
32
32
|
"planned_texts": ["datanotes/metastore.yaml"],
|
|
33
|
-
"migration_id": "
|
|
33
|
+
"migration_id": "20261019T040655-define_base-create-base-entry"
|
|
34
34
|
}
|
|
35
35
|
```
|
|
36
36
|
|
|
@@ -50,7 +50,7 @@ Answer:
|
|
|
50
50
|
"commits": [
|
|
51
51
|
{ "table": "diary.classics.film", "version": 6, "operation": "SET TABLE BASES" }
|
|
52
52
|
],
|
|
53
|
-
"migration_id": "
|
|
53
|
+
"migration_id": "20261019T040655-set_table_bases-diary-classics-film-extends-en"
|
|
54
54
|
}
|
|
55
55
|
```
|
|
56
56
|
|
|
@@ -118,14 +118,14 @@ Answer:
|
|
|
118
118
|
"rows": [
|
|
119
119
|
{
|
|
120
120
|
"path": "datanotes/diary/classics/actors/Max Schreck.md",
|
|
121
|
-
"id": "
|
|
121
|
+
"id": "01a15257-4be9-775a-9d44-7c12bf38b0ed",
|
|
122
122
|
"added_on": "2026-10-05",
|
|
123
123
|
"note": "The face of Nosferatu",
|
|
124
124
|
"_source": "diary.classics.actors"
|
|
125
125
|
},
|
|
126
126
|
{
|
|
127
127
|
"path": "datanotes/diary/classics/film/Nosferatu.md",
|
|
128
|
-
"id": "
|
|
128
|
+
"id": "01a15257-4b79-7e2f-83db-94f0aef0d4ae",
|
|
129
129
|
"added_on": "2026-10-05",
|
|
130
130
|
"note": null,
|
|
131
131
|
"_source": "diary.classics.film"
|
|
@@ -169,7 +169,7 @@ Answer:
|
|
|
169
169
|
"commits": [
|
|
170
170
|
{ "table": "diary.classics.actors", "version": 3, "operation": "DEFINE BASE" }
|
|
171
171
|
],
|
|
172
|
-
"migration_id": "
|
|
172
|
+
"migration_id": "20261019T040655-define_base-alter-base-entry"
|
|
173
173
|
}
|
|
174
174
|
```
|
|
175
175
|
|
|
@@ -246,7 +246,7 @@ Answer:
|
|
|
246
246
|
"commits": [
|
|
247
247
|
{ "table": "diary.classics.actors", "version": 4, "operation": "DEFINE BASE" }
|
|
248
248
|
],
|
|
249
|
-
"migration_id": "
|
|
249
|
+
"migration_id": "20261019T040655-define_base-alter-base-entry-2"
|
|
250
250
|
}
|
|
251
251
|
```
|
|
252
252
|
|
|
@@ -280,7 +280,7 @@ Answer:
|
|
|
280
280
|
"ok": true,
|
|
281
281
|
"op": "define_base",
|
|
282
282
|
"planned_texts": ["datanotes/metastore.yaml"],
|
|
283
|
-
"migration_id": "
|
|
283
|
+
"migration_id": "20261019T040655-define_base-create-base-credited"
|
|
284
284
|
}
|
|
285
285
|
```
|
|
286
286
|
|
|
@@ -300,7 +300,7 @@ Answer:
|
|
|
300
300
|
"commits": [
|
|
301
301
|
{ "table": "diary.classics.actors", "version": 5, "operation": "SET TABLE BASES" }
|
|
302
302
|
],
|
|
303
|
-
"migration_id": "
|
|
303
|
+
"migration_id": "20261019T040655-set_table_bases-diary-classics-actors-extends--2"
|
|
304
304
|
}
|
|
305
305
|
```
|
|
306
306
|
|
|
@@ -329,7 +329,7 @@ Answer:
|
|
|
329
329
|
"ok": true,
|
|
330
330
|
"op": "define_base",
|
|
331
331
|
"planned_texts": ["datanotes/metastore.yaml"],
|
|
332
|
-
"migration_id": "
|
|
332
|
+
"migration_id": "20261019T040655-define_base-create-base-tree"
|
|
333
333
|
}
|
|
334
334
|
```
|
|
335
335
|
|
|
@@ -369,7 +369,7 @@ Answer:
|
|
|
369
369
|
"commits": [
|
|
370
370
|
{ "table": "diary.classics.genre", "version": 1, "operation": "SET TABLE BASES" }
|
|
371
371
|
],
|
|
372
|
-
"migration_id": "
|
|
372
|
+
"migration_id": "20261019T040655-set_table_bases-diary-classics-genre-extends-t"
|
|
373
373
|
}
|
|
374
374
|
```
|
|
375
375
|
|
|
@@ -475,6 +475,6 @@ Answer:
|
|
|
475
475
|
"operation": "SET TABLE BASES"
|
|
476
476
|
}
|
|
477
477
|
],
|
|
478
|
-
"migration_id": "
|
|
478
|
+
"migration_id": "20261019T040655-set_table_bases-diary-classics-genre_draft-ext"
|
|
479
479
|
}
|
|
480
480
|
```
|
|
@@ -63,7 +63,7 @@ Answer:
|
|
|
63
63
|
"commits": [
|
|
64
64
|
{ "table": "diary.classics.film", "version": 0, "operation": "CREATE TABLE" }
|
|
65
65
|
],
|
|
66
|
-
"migration_id": "
|
|
66
|
+
"migration_id": "20261019T040655-create_table-create-table-diary-classics-fi"
|
|
67
67
|
}
|
|
68
68
|
```
|
|
69
69
|
|
|
@@ -91,7 +91,7 @@ Answer:
|
|
|
91
91
|
"files_created": 1,
|
|
92
92
|
"planned_creates": ["datanotes/diary/classics/film/Nosferatu.md"],
|
|
93
93
|
"commits": [{ "table": "diary.classics.film", "version": 1, "operation": "WRITE" }],
|
|
94
|
-
"migration_id": "
|
|
94
|
+
"migration_id": "20261019T040655-insert_row-insert-into-film"
|
|
95
95
|
}
|
|
96
96
|
```
|
|
97
97
|
|
|
@@ -127,7 +127,7 @@ Answer:
|
|
|
127
127
|
"commits": [
|
|
128
128
|
{ "table": "diary.classics.film", "version": 3, "operation": "ALTER TABLE" }
|
|
129
129
|
],
|
|
130
|
-
"migration_id": "
|
|
130
|
+
"migration_id": "20261019T040655-alter_table-alter-table-diary-classics-fil-2"
|
|
131
131
|
}
|
|
132
132
|
```
|
|
133
133
|
|
|
@@ -144,7 +144,7 @@ Answer:
|
|
|
144
144
|
"ok": true,
|
|
145
145
|
"op": "comment_on",
|
|
146
146
|
"planned_texts": ["datanotes/metastore.yaml"],
|
|
147
|
-
"migration_id": "
|
|
147
|
+
"migration_id": "20261019T040655-comment_on-comment-on-catalog-diary"
|
|
148
148
|
}
|
|
149
149
|
```
|
|
150
150
|
|
|
@@ -165,7 +165,7 @@ Answer:
|
|
|
165
165
|
"ok": true,
|
|
166
166
|
"op": "comment_on",
|
|
167
167
|
"planned_texts": ["datanotes/metastore.yaml"],
|
|
168
|
-
"migration_id": "
|
|
168
|
+
"migration_id": "20261019T040655-comment_on-comment-on-schema-diary-classi"
|
|
169
169
|
}
|
|
170
170
|
```
|
|
171
171
|
|
|
@@ -173,7 +173,7 @@ Answer:
|
|
|
173
173
|
|
|
174
174
|
```yaml
|
|
175
175
|
# Metastore (Datanotes): catalogs, schemas, tables, columns, views.
|
|
176
|
-
id:
|
|
176
|
+
id: 01a15257-4b68-7b8b-bf1b-44c297b63995
|
|
177
177
|
config:
|
|
178
178
|
history: true
|
|
179
179
|
|
|
@@ -270,7 +270,7 @@ Answer:
|
|
|
270
270
|
"commits": [
|
|
271
271
|
{ "table": "diary.classics.film", "version": 4, "operation": "ALTER TABLE" }
|
|
272
272
|
],
|
|
273
|
-
"migration_id": "
|
|
273
|
+
"migration_id": "20261019T040655-alter_table-alter-table-diary-classics-fil-3"
|
|
274
274
|
}
|
|
275
275
|
```
|
|
276
276
|
|
|
@@ -287,7 +287,7 @@ Answer:
|
|
|
287
287
|
"ok": true,
|
|
288
288
|
"op": "comment_on",
|
|
289
289
|
"planned_texts": ["datanotes/metastore.yaml"],
|
|
290
|
-
"migration_id": "
|
|
290
|
+
"migration_id": "20261019T040655-comment_on-remove-the-comment-on-schema-d"
|
|
291
291
|
}
|
|
292
292
|
```
|
|
293
293
|
|
|
@@ -309,7 +309,7 @@ Answer:
|
|
|
309
309
|
"commits": [
|
|
310
310
|
{ "table": "diary.classics.film", "version": 5, "operation": "ALTER TABLE" }
|
|
311
311
|
],
|
|
312
|
-
"migration_id": "
|
|
312
|
+
"migration_id": "20261019T040655-alter_table-alter-table-diary-classics-fil-4"
|
|
313
313
|
}
|
|
314
314
|
```
|
|
315
315
|
|
|
@@ -593,7 +593,7 @@ This is the database of this page as the engine wrote it. `metastore.yaml` holds
|
|
|
593
593
|
|
|
594
594
|
```yaml
|
|
595
595
|
# Metastore (Datanotes): catalogs, schemas, tables, columns, views.
|
|
596
|
-
id:
|
|
596
|
+
id: 01a15257-4b68-7b8b-bf1b-44c297b63995
|
|
597
597
|
config:
|
|
598
598
|
history: true
|
|
599
599
|
default_catalog: diary
|
|
@@ -626,6 +626,8 @@ catalogs:
|
|
|
626
626
|
ne: watched
|
|
627
627
|
- rating:
|
|
628
628
|
exists: true
|
|
629
|
+
constraint_hints:
|
|
630
|
+
rated_when_watched: "A watched film needs a rating from 1 to 5: ask me for it."
|
|
629
631
|
options:
|
|
630
632
|
partition: "{year}"
|
|
631
633
|
filename: "{title} ({year})"
|
|
@@ -777,6 +779,8 @@ catalogs:
|
|
|
777
779
|
ne: watched
|
|
778
780
|
- rating:
|
|
779
781
|
exists: true
|
|
782
|
+
constraint_hints:
|
|
783
|
+
rated_when_watched: "A watched film needs a rating from 1 to 5: ask me for it."
|
|
780
784
|
options:
|
|
781
785
|
partition: "{year}"
|
|
782
786
|
filename: "{title} ({year})"
|
|
@@ -831,6 +835,8 @@ catalogs:
|
|
|
831
835
|
ne: watched
|
|
832
836
|
- rating:
|
|
833
837
|
exists: true
|
|
838
|
+
constraint_hints:
|
|
839
|
+
rated_when_watched: "A watched film needs a rating from 1 to 5: ask me for it."
|
|
834
840
|
options:
|
|
835
841
|
partition: "{year}"
|
|
836
842
|
filename: "{title} ({year})"
|