datanotes 3.0.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.
Files changed (73) hide show
  1. package/README.md +1 -5
  2. package/dist/api/client.d.cts +37 -4
  3. package/dist/api/client.d.ts +37 -4
  4. package/dist/api/index.cjs +563 -60
  5. package/dist/api/index.d.cts +3 -2
  6. package/dist/api/index.d.ts +3 -2
  7. package/dist/api/index.js +563 -60
  8. package/dist/api/mcp.cjs +181 -11
  9. package/dist/api/mcp.js +181 -11
  10. package/dist/api/otlp.d.cts +63 -15
  11. package/dist/api/otlp.d.ts +63 -15
  12. package/dist/api/redact.d.cts +25 -0
  13. package/dist/api/redact.d.ts +25 -0
  14. package/dist/api/tokens.d.cts +5 -0
  15. package/dist/api/tokens.d.ts +5 -0
  16. package/dist/api/tracing.d.cts +107 -0
  17. package/dist/api/tracing.d.ts +107 -0
  18. package/dist/datanotes.cjs +9934 -2656
  19. package/dist/docs/administration/limits.md +96 -12
  20. package/dist/docs/administration/run-the-service.md +18 -0
  21. package/dist/docs/api/operations/add_column.md +1 -0
  22. package/dist/docs/api/operations/add_constraint.md +2 -0
  23. package/dist/docs/api/operations/alter_column.md +1 -1
  24. package/dist/docs/api/operations/alter_table.md +3 -2
  25. package/dist/docs/api/operations/check_table.md +1 -1
  26. package/dist/docs/api/operations/create_table.md +3 -1
  27. package/dist/docs/api/operations/describe_table.md +1 -1
  28. package/dist/docs/api/operations/graph_neighbors.md +4 -2
  29. package/dist/docs/api/operations/graph_path.md +3 -3
  30. package/dist/docs/api/operations/graph_traverse.md +2 -2
  31. package/dist/docs/api/operations/insert_row.md +2 -2
  32. package/dist/docs/api/operations/record_tool_call.md +1 -0
  33. package/dist/docs/api/operations/tags/queries.md +2 -2
  34. package/dist/docs/api/operations/tags/rows-dml.md +1 -1
  35. package/dist/docs/api.md +4 -4
  36. package/dist/docs/develop/concurrency.md +36 -1
  37. package/dist/docs/develop/http-api.md +11 -1
  38. package/dist/docs/develop/telemetry.md +224 -25
  39. package/dist/docs/guides/data-quality/check-constraints.md +14 -13
  40. package/dist/docs/guides/data-quality/hand-edits.md +10 -10
  41. package/dist/docs/guides/database-objects/bases.md +11 -11
  42. package/dist/docs/guides/database-objects/catalogs-and-schemas.md +16 -10
  43. package/dist/docs/guides/database-objects/columns.md +38 -38
  44. package/dist/docs/guides/database-objects/relations.md +173 -36
  45. package/dist/docs/guides/database-objects/tables.md +90 -109
  46. package/dist/docs/guides/database-objects/views.md +44 -44
  47. package/dist/docs/guides/history/back-up.md +12 -4
  48. package/dist/docs/guides/history/change-data-feed.md +34 -34
  49. package/dist/docs/guides/history/journal-and-undo.md +12 -12
  50. package/dist/docs/guides/history/restore.md +20 -20
  51. package/dist/docs/guides/history/table-history.md +31 -31
  52. package/dist/docs/guides/history/vacuum.md +1 -10
  53. package/dist/docs/guides/read-and-write/automatic-links.md +15 -15
  54. package/dist/docs/guides/read-and-write/import-notes.md +21 -21
  55. package/dist/docs/guides/read-and-write/joins-and-aggregates.md +7 -7
  56. package/dist/docs/guides/read-and-write/read-and-filter.md +10 -10
  57. package/dist/docs/guides/read-and-write/write-rows.md +10 -10
  58. package/dist/docs/guides/search/link-graph.md +95 -0
  59. package/dist/docs/guides/search/text.md +1 -1
  60. package/dist/docs/guides/security/who-did-what.md +2 -0
  61. package/dist/docs/reference/cli.md +10 -3
  62. package/dist/docs/reference/compatibility.md +33 -13
  63. package/dist/docs/reference/errors.md +1 -1
  64. package/dist/docs/reference/operations/auxiliary.md +2 -2
  65. package/dist/docs/reference/operations/queries.md +3 -3
  66. package/dist/docs/reference/operations/rows.md +1 -1
  67. package/dist/docs/reference/operations/schema.md +15 -11
  68. package/dist/docs/reference/operations.md +39 -39
  69. package/dist/docs/reference/settings.md +37 -25
  70. package/dist/docs/release-notes.md +145 -0
  71. package/dist/docs/start/how-it-works.md +35 -3
  72. package/dist/docs/start/quick-start.md +2 -0
  73. package/package.json +3 -2
@@ -116,7 +116,7 @@ Examples: [Find notes by meaning](https://datanotes.dev/guides/search/semantic/)
116
116
 
117
117
  Direct neighbours of notes: what they link to (`out`) and what links to them (`in`, backlinks), with counts per edge label. `direction`: out, in or both (default).
118
118
 
119
- `from_nodes` selects the notes: `{"paths": [...]}` and/or `{"table": ..., "where": {...}}`. Edges are labelled with their link column (`people`, `event`, …) or `link` for other links.
119
+ `from_nodes` selects the notes: `{"paths": [...]}`, `{"table": ..., "where": {...}}` and/or `{"tables": [...]}`: the rows of several tables, by name or pattern (`["*"]` every table, `["personal.*"]` a catalog’s). The whole vault’s graph in one call: `{"tables": ["*"]}` with direction `out` (at most 5000 start notes). Edges are labelled with their link column (`people`, `event`, …) or `link` for other links.
120
120
 
121
121
  Examples: [Walk the link graph](https://datanotes.dev/guides/search/link-graph/).
122
122
 
@@ -130,7 +130,7 @@ Examples: [Walk the link graph](https://datanotes.dev/guides/search/link-graph/)
130
130
 
131
131
  **Graph Traverse** · read-only
132
132
 
133
- Breadth-first walk over links from `from_nodes` (`{"paths": [...]}` and/or `{"table", "where"}`).
133
+ Breadth-first walk over links from `from_nodes` (`{"paths": [...]}`, `{"table", "where"}` and/or `{"tables": [...]}`).
134
134
 
135
135
  * `direction`: out (default, follow links), in (follow backlinks) or both.
136
136
  * `edges`: edge labels to follow (link columns such as `people`, `event`, or `link`).
@@ -156,7 +156,7 @@ Examples: [Walk the link graph](https://datanotes.dev/guides/search/link-graph/)
156
156
 
157
157
  **Graph Path** · read-only
158
158
 
159
- Shortest chain of links between two sets of notes (each `{"paths": [...]}` and/or `{"table", "where"}`): `found`, `length` and `path`: the steps (`from`, `label`, `direction`, `to`). `direction` both by default; `max_depth` default 6 (max 10).
159
+ Shortest chain of links between two sets of notes (each `{"paths": [...]}`, `{"table", "where"}` and/or `{"tables": [...]}`): `found`, `length` and `path`: the steps (`from`, `label`, `direction`, `to`). `direction` both by default; `max_depth` default 6 (max 10).
160
160
 
161
161
  Examples: [Walk the link graph](https://datanotes.dev/guides/search/link-graph/).
162
162
 
@@ -10,7 +10,7 @@ Every write is validated. Writes to rows and to the schema are journaled and und
10
10
 
11
11
  **Insert Row** · write
12
12
 
13
- Insert a row (new note). Values are validated against the columns; the note path comes from the table’s `path`/`filename` patterns (e.g. an event logged today about last night lands in last night’s day folder when you set `occurred_at` to last night). `body` is the note text. Generated / identity columns are computed (do not pass them); CHECK constraints are enforced. Returns `migration_id` (undo) and the created path in `planned_creates`. `body` links the notes it mentions by name, at their first mention (automatic links; off with `autolink: false` or the database’s `autolink` setting). `links_added` lists the links made; `ambiguous_mentions` lists the mentions left as text with the notes they may name: read those, then link the right one with update_row and `autolink: false`, or leave the text.
13
+ 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 the table’s `path`/`filename` patterns (e.g. an event logged today about last night lands in last night’s day folder when you set `occurred_at` to last night). `body` is the note text. Generated / identity columns are computed (do not pass them); CHECK constraints are enforced. Returns `migration_id` (undo) and the created path in `planned_creates`. `body` links the notes it mentions by name, at their first mention (automatic links; off with `autolink: false` or the database’s `autolink` setting). `links_added` lists the links made; `ambiguous_mentions` lists the mentions left as text with the notes they may name: read those, then link the right one with update_row and `autolink: false`, or leave the text.
14
14
 
15
15
  Examples: [Catalogs, schemas and the database](https://datanotes.dev/guides/database-objects/catalogs-and-schemas/), [Tables](https://datanotes.dev/guides/database-objects/tables/), [Columns and types](https://datanotes.dev/guides/database-objects/columns/), [Bases](https://datanotes.dev/guides/database-objects/bases/), [Relations and hierarchies](https://datanotes.dev/guides/database-objects/relations/), [Validation](https://datanotes.dev/guides/data-quality/validation/), [CHECK constraints](https://datanotes.dev/guides/data-quality/check-constraints/), [Write and move rows](https://datanotes.dev/guides/read-and-write/write-rows/), [Automatic links](https://datanotes.dev/guides/read-and-write/automatic-links/), [Batch writes](https://datanotes.dev/guides/read-and-write/batch/), [Import existing notes](https://datanotes.dev/guides/read-and-write/import-notes/), [Journal and undo](https://datanotes.dev/guides/history/journal-and-undo/), [Table history and time travel](https://datanotes.dev/guides/history/table-history/), [Change data feed](https://datanotes.dev/guides/history/change-data-feed/), [Restore a table or the database](https://datanotes.dev/guides/history/restore/).
16
16
 
@@ -13,10 +13,11 @@ Every write is validated. Writes to rows and to the schema are journaled and und
13
13
  Create a table: `name`, in `catalog` and `schema` (default: the database’s defaults); the definition goes in metastore.yaml, the rows in `<root>/<catalog>/<schema>/<name>/`. Names: lowercase letters, digits, `_` (no dots: pass the catalog and the schema as their own arguments).
14
14
 
15
15
  * `description` (required): what a row of the table records. Every column needs its own `description` too, what it holds: the table is refused otherwise, with every missing one listed. Descriptions are how agents and people understand the schema, so write them for a reader who never saw the notes. The engine writes those of `id` and of `identity` “uuid” / “created” columns.
16
- * `columns`: specs like `{"name": "kind", "type": "enum", "values": ["a","b"], "required": true, "description": "What kind of entry the row is"}`. Types: string, integer, number, boolean, date, datetime, enum, link, list (+ `items`), json. Attributes: required, default (`"{now}"`/`"{today}"`), min, max, step, values, `ordered` (enum in order: filters/avg use the position), ref (link target, full `catalog.schema.table` or “self”), unique, label, description, aliases, `generated` (e.g. `"date(occurred_at)"`, `"{name} {surname}"`), `identity` (“filename” | “created”), `vocabulary` (allowed values = names of another table’s rows), `hierarchy: true` (one parent link to its own table), `dense` (written on every row), `inverse` on a link column: the column of the `ref` table that links back (`friends` ↔ `friends`, `children` ↔ `parents`, `partner` ↔ `partner`); writes keep both sides in step.
16
+ * `columns`: specs like `{"name": "kind", "type": "enum", "values": ["a","b"], "required": true, "description": "What kind of entry the row is"}`. Types: string, integer, number, boolean, date, datetime, enum, link, list (+ `items`), json. Attributes: required, default (`"{now}"`/`"{today}"`), min, max, step, values, `ordered` (enum in order: filters/avg use the position), ref (link target, full `catalog.schema.table` or “self”), unique, label, description, aliases, `generated` (e.g. `"date(occurred_at)"`, `"{name} {surname}"`), `identity` (“filename” | “created”), `vocabulary` (allowed values = names of another table’s rows), `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), `inverse` on a link column: the column of the `ref` table that links back (`friends` ↔ `friends`, `children` ↔ `parents`, `partner` ↔ `partner`); writes keep both sides in step.
17
17
  * `time_column`: rows named by that date/datetime; otherwise `filename` (e.g. `"{name}"`).
18
18
  * The table’s options, as alter_table names them: `aliases` (how agents find it, with the description), `partition`, `exclude`, `archive`, `history` (keep its versions; default: the database’s setting), `autolink_target` (true / false: may automatic links link its rows? default: yes, unless its rows are named by a date or a time, as with `time_column`).
19
19
  * `row_template`: markdown body of new rows. Shared columns come from bases: `set_table_bases`.
20
+ * `instructions`: how to fill a row, for agents (Markdown); describe_table returns them.
20
21
  * `tags`: key/value labels of the table, strings (`{"domain": "health"}`); list_tables and describe_table return them, alter_table changes them. 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. 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). 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.
21
22
 
22
23
  The schema changes only through operations like this one: never edit metastore.yaml by hand (no validation, no undo).
@@ -39,6 +40,7 @@ Examples: [Catalogs, schemas and the database](https://datanotes.dev/guides/data
39
40
  | `history` | boolean \\ | null | | `null` |
40
41
  | `autolink_target` | boolean \\ | null | | `null` |
41
42
  | `row_template` | string \\ | null | | `null` |
43
+ | `instructions` | string \\ | null | | `null` |
42
44
  | `fields` | object \\ | null | | `null` |
43
45
  | `tags` | object \\ | null | | `null` |
44
46
  | `dry_run` | boolean | | `false` | |
@@ -63,7 +65,7 @@ Examples: [Tables](https://datanotes.dev/guides/database-objects/tables/).
63
65
 
64
66
  **Alter Table** · destructive write
65
67
 
66
- Alter a table: move it (`catalog`, `schema`), rename it (`name`), change `partition` / `filename` patterns, `description` (changes, never goes: “” is refused), `aliases`, `exclude` folders, `row_template` (“” removes it), `history` (true | false | “default”), `autolink_target` (true | false | “default”: may automatic links link its rows? default: yes, unless its rows are named by a date or a time) or `tags` (key/value labels merged into the table’s, e.g. `{"domain": "health"}`; a `null` value removes that tag; `clear_tags: true` removes every tag first, so with `tags` the table keeps exactly those), `archive` (folder name inside the table folder) or `fields` (untyped fields, name → default; a `null` value removes one). Rows, archive and transaction log follow; links are updated; renamed rows keep their old name in `aliases`. A change of metadata only (tags, description, aliases, history, autolink_target, row_template, fields) rewrites the table entry alone: no row is moved or rewritten. Refused when a row cannot fill a pattern. Renaming or moving the table is refused while a CHECK that follows links, or a `ref_where` / `ref_by`, of another table reads it through a link (link targets are not rewritten): the conflicts name them. Use `dry_run` to see `planned_moves`; undo with undo_migration.
68
+ Alter a table: move it (`catalog`, `schema`), rename it (`name`), change `partition` / `filename` patterns, `description` (changes, never goes: “” is refused), `aliases`, `exclude` folders, `row_template` (“” removes it), `instructions` (how to fill a row, for agents; “” removes them), `history` (true | false | “default”), `autolink_target` (true | false | “default”: may automatic links link its rows? default: yes, unless its rows are named by a date or a time) or `tags` (key/value labels merged into the table’s, e.g. `{"domain": "health"}`; a `null` value removes that tag; `clear_tags: true` removes every tag first, so with `tags` the table keeps exactly those), `archive` (folder name inside the table folder) or `fields` (untyped fields, name → default; a `null` value removes one). Rows, archive and transaction log follow; links are updated; renamed rows keep their old name in `aliases`. A change of metadata only (tags, description, aliases, history, autolink_target, row_template, instructions, fields) rewrites the table entry alone: no row is moved or rewritten. Refused when a row cannot fill a pattern. Renaming or moving the table is refused while a CHECK that follows links, or a `ref_where` / `ref_by`, of another table reads it through a link (link targets are not rewritten): the conflicts name them. Use `dry_run` to see `planned_moves`; undo with undo_migration.
67
69
 
68
70
  The schema changes only through operations like this one: never edit metastore.yaml by hand (no validation, no undo).
69
71
 
@@ -83,6 +85,7 @@ Examples: [Catalogs, schemas and the database](https://datanotes.dev/guides/data
83
85
  | `autolink_target` | boolean \\ | `"default"` \\ | null | |
84
86
  | `exclude` | string\[] \\ | null | | `null` |
85
87
  | `row_template` | string \\ | null | | `null` |
88
+ | `instructions` | string \\ | null | | `null` |
86
89
  | `tags` | object \\ | null | | `null` |
87
90
  | `clear_tags` | boolean | | `false` | Remove every tag first (with `tags`: the table keeps exactly those). |
88
91
  | `archive` | string \\ | null | | `null` |
@@ -112,7 +115,7 @@ Examples: [Tables](https://datanotes.dev/guides/database-objects/tables/), [Base
112
115
 
113
116
  **Add Column** · write
114
117
 
115
- Add a typed column. Sparse by default (written only on rows that have a value — use for metrics, e.g. `{"name": "metric_mood", "type": "integer", "min": 1, "max": 5, "label": "Mood", "aliases": ["mood"], "description": "Mood of the day, 1 = bad, 5 = great"}`). `description` is required: what the column holds, for the agents and people who read the schema (the engine writes it for `identity` “uuid” / “created” columns). `dense: true` in the spec adds it to every row with its `default`. Call `describe_table` first: never add a column whose meaning an existing column (name/label/aliases/description) already covers. Column names are permanent identifiers; only `rename_column` changes them. 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. 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). 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.
118
+ Add a typed column. Sparse by default (written only on rows that have a value — use for metrics, e.g. `{"name": "metric_mood", "type": "integer", "min": 1, "max": 5, "label": "Mood", "aliases": ["mood"], "description": "Mood of the day, 1 = bad, 5 = great"}`). `description` is required: what the column holds, for the agents and people who read the schema (the engine writes it for `identity` “uuid” / “created” columns). `dense: true` in the spec adds it to every row with its `default`. Call `describe_table` first: never add a column whose meaning an existing column (name/label/aliases/description) already covers. Column names are permanent identifiers; only `rename_column` changes them. 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. 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). 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. 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).
116
119
 
117
120
  The schema changes only through operations like this one: never edit metastore.yaml by hand (no validation, no undo).
118
121
 
@@ -161,7 +164,7 @@ Examples: [Columns and types](https://datanotes.dev/guides/database-objects/colu
161
164
 
162
165
  **Alter Column** · destructive write
163
166
 
164
- Change a column’s attributes (type, min/max/step, values, required, default, label, aliases, description, note, `ref_where`, `ref_by` (see list_link_targets); `null` removes an attribute, except `description`, which changes but never goes (null or “” is refused); `dense` true/false). Refused with the list of violating rows when existing values do not satisfy the new definition. A different scale means a different column: add a new one instead of rescaling. To rename one enum value use `rename_value`. Dropping an enum value that a `ref_by` (of any table) allows as a target level is refused, naming it.
167
+ Change a column’s attributes (type, min/max/step, values, required, default, label, 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 `description`, which changes but never goes (null or “” is refused); `dense` true/false). Refused with the list of violating rows when existing values do not satisfy the new definition. A different scale means a different column: add a new one instead of rescaling. To rename one enum value use `rename_value`. Dropping an enum value that a `ref_by` (of any table) allows as a target level is refused, naming it.
165
168
 
166
169
  The schema changes only through operations like this one: never edit metastore.yaml by hand (no validation, no undo).
167
170
 
@@ -249,18 +252,19 @@ Examples: [Bases](https://datanotes.dev/guides/database-objects/bases/).
249
252
 
250
253
  **Add Constraint** · write
251
254
 
252
- ALTER TABLE ADD CONSTRAINT `name` CHECK: `check` is a where filter every row must match, e.g. `{"value": {"gte": 1, "lte": 5}}`. A condition on a column the row leaves empty passes, like SQL; inside `or` / `and` / `not` an empty value is tested as it is (`{"exists": true}` there fails). A key may follow a link column to the row it names, as in queries: `{"parent.kind": "project"}` (further dots follow further links). An empty link passes at the top level and fails inside `or` / `and` / `not`; only the first link of a longer path is skipped when empty (`parent.parent.kind` fails for a row whose parent has no parent). A link to a row that does not exist fails; on a list of links every linked row must match. `not` turns that into a pass: `{"not": {"parent.kind": "area"}}` passes a link to a missing row, so add `"parent.kind": {"exists": true}` to require a real one. Links resolve as in the vault (by path, from the row’s note: same-named rows in two folders stay apart); renaming or moving a linked row keeps them (they follow it). Refused while existing rows violate it (they are listed); then enforced on every write, by the same rule. A write that changes a linked row re-checks the rows that link to it and is refused, listing them, when it breaks them, naming the changed row (in a batch, re-link them first: each step is checked on the vault the earlier ones left); the inverse links a write adds, undo_migration and restore_table are checked too. rename_column / rename_value follow into CHECKs; drop_column of a column a CHECK reads is refused.
255
+ ALTER TABLE ADD CONSTRAINT `name` CHECK: `check` is a where filter every row must match, e.g. `{"value": {"gte": 1, "lte": 5}}`. A condition on a column the row leaves empty passes, like SQL; inside `or` / `and` / `not` an empty value is tested as it is (`{"exists": true}` there fails). A key may follow a link column to the row it names, as in queries: `{"parent.kind": "project"}` (further dots follow further links). An empty link passes at the top level and fails inside `or` / `and` / `not`; only the first link of a longer path is skipped when empty (`parent.parent.kind` fails for a row whose parent has no parent). A link to a row that does not exist fails; on a list of links every linked row must match. `not` turns that into a pass: `{"not": {"parent.kind": "area"}}` passes a link to a missing row, so add `"parent.kind": {"exists": true}` to require a real one. Links resolve as in the vault (by path, from the row’s note: same-named rows in two folders stay apart); renaming or moving a linked row keeps them (they follow it). Refused while existing rows violate it (they are listed); then enforced on every write, by the same rule. A write that changes a linked row re-checks the rows that link to it and is refused, listing them, when it breaks them, naming the changed row (in a batch, re-link them first: each step is checked on the vault the earlier ones left); the inverse links a write adds, undo_migration and restore_table are checked too. rename_column / rename_value follow into CHECKs; drop_column of a column a CHECK reads is refused. `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.
253
256
 
254
257
  The schema changes only through operations like this one: never edit metastore.yaml by hand (no validation, no undo).
255
258
 
256
259
  Examples: [CHECK constraints](https://datanotes.dev/guides/data-quality/check-constraints/).
257
260
 
258
- | Parameter | Type | Required | Default | Description |
259
- | --------- | ------- | -------- | ------- | ----------- |
260
- | `table` | string | yes | | |
261
- | `name` | string | yes | | |
262
- | `check` | object | yes | | |
263
- | `dry_run` | boolean | | `false` | |
261
+ | Parameter | Type | Required | Default | Description |
262
+ | --------- | --------- | -------- | ------- | ----------- |
263
+ | `table` | string | yes | | |
264
+ | `name` | string | yes | | |
265
+ | `check` | object | yes | | |
266
+ | `hint` | string \\ | null | | `null` |
267
+ | `dry_run` | boolean | | `false` | |
264
268
 
265
269
  ## `drop_constraint`
266
270
 
@@ -10,24 +10,24 @@ Next to them, `datanotes mcp` offers three tools that read these docs offline, `
10
10
 
11
11
  Operations that define the database: tables, columns, constraints, bases and views. [Schema operations (DDL)](https://datanotes.dev/reference/operations/schema/) lists their parameters.
12
12
 
13
- | Operation | What it does | Examples |
14
- | ------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
15
- | [`create_table`](https://datanotes.dev/reference/operations/schema/#create_table) | Create a table: `name`, in `catalog` and `schema` (default: the database’s defaults); the definition goes in metastore.yaml, the rows in `<root>/<catalog>/<schema>/<name>/`. | [Catalogs, schemas and the database](https://datanotes.dev/guides/database-objects/catalogs-and-schemas/), [Tables](https://datanotes.dev/guides/database-objects/tables/), [Columns and types](https://datanotes.dev/guides/database-objects/columns/), [Bases](https://datanotes.dev/guides/database-objects/bases/), [Relations and hierarchies](https://datanotes.dev/guides/database-objects/relations/), [Write and move rows](https://datanotes.dev/guides/read-and-write/write-rows/), [Automatic links](https://datanotes.dev/guides/read-and-write/automatic-links/), [Import existing notes](https://datanotes.dev/guides/read-and-write/import-notes/), [Table history and time travel](https://datanotes.dev/guides/history/table-history/) |
16
- | [`drop_table`](https://datanotes.dev/reference/operations/schema/#drop_table) | Drop a table. | [Tables](https://datanotes.dev/guides/database-objects/tables/) |
17
- | [`alter_table`](https://datanotes.dev/reference/operations/schema/#alter_table) | Alter a table: move it (`catalog`, `schema`), rename it (`name`), change `partition` / `filename` patterns, `description` (changes, never goes: “” is refused), `aliases`, `exclude` folders, `row_template` (“” removes it), `history` (true \| false \| “default”), `autolink_target` (true \| false \| “default”: may automatic links link its rows? default: yes, unless its rows are named by a date or a time) or `tags` (key/value labels merged into the table’s, e.g. | [Catalogs, schemas and the database](https://datanotes.dev/guides/database-objects/catalogs-and-schemas/), [Tables](https://datanotes.dev/guides/database-objects/tables/), [Automatic links](https://datanotes.dev/guides/read-and-write/automatic-links/), [Import existing notes](https://datanotes.dev/guides/read-and-write/import-notes/), [Table history and time travel](https://datanotes.dev/guides/history/table-history/) |
18
- | [`clone_table`](https://datanotes.dev/reference/operations/schema/#clone_table) | CREATE TABLE `target` CLONE `source`: same definition plus independent copies of its rows (deep clone), optionally as of a `version` / `timestamp`. | [Tables](https://datanotes.dev/guides/database-objects/tables/), [Bases](https://datanotes.dev/guides/database-objects/bases/), [Table history and time travel](https://datanotes.dev/guides/history/table-history/) |
19
- | [`add_column`](https://datanotes.dev/reference/operations/schema/#add_column) | Add a typed column. | [Columns and types](https://datanotes.dev/guides/database-objects/columns/), [Relations and hierarchies](https://datanotes.dev/guides/database-objects/relations/), [Import existing notes](https://datanotes.dev/guides/read-and-write/import-notes/) |
20
- | [`rename_column`](https://datanotes.dev/reference/operations/schema/#rename_column) | Rename a column in metastore.yaml and on every row. | [Columns and types](https://datanotes.dev/guides/database-objects/columns/) |
21
- | [`drop_column`](https://datanotes.dev/reference/operations/schema/#drop_column) | Remove a column from the schema and every row. | [Columns and types](https://datanotes.dev/guides/database-objects/columns/) |
22
- | [`alter_column`](https://datanotes.dev/reference/operations/schema/#alter_column) | Change a column’s attributes (type, min/max/step, values, required, default, label, aliases, description, note, `ref_where`, `ref_by` (see list_link_targets); `null` removes an attribute, except `description`, which changes but never goes (null or “” is refused); `dense` true/false). | [Tables](https://datanotes.dev/guides/database-objects/tables/), [Columns and types](https://datanotes.dev/guides/database-objects/columns/), [Relations and hierarchies](https://datanotes.dev/guides/database-objects/relations/) |
23
- | [`rename_value`](https://datanotes.dev/reference/operations/schema/#rename_value) | Rename one value of an enum column (e.g. | [Columns and types](https://datanotes.dev/guides/database-objects/columns/) |
24
- | [`comment_on`](https://datanotes.dev/reference/operations/schema/#comment_on) | COMMENT ON CATALOG / SCHEMA: set the `description` of a catalog (`catalog` alone) or of one of its schemas (`catalog` and `schema`) in metastore.yaml: what it holds, so agents pick the right place. | [Catalogs, schemas and the database](https://datanotes.dev/guides/database-objects/catalogs-and-schemas/) |
25
- | [`define_base`](https://datanotes.dev/reference/operations/schema/#define_base) | Create or replace a base: a named set of columns (same spec as `create_table`) that tables inherit, like a parent class (`bases` in `metastore.yaml`). | [Bases](https://datanotes.dev/guides/database-objects/bases/) |
26
- | [`set_table_bases`](https://datanotes.dev/reference/operations/schema/#set_table_bases) | Set the bases a table inherits from (`bases`, in order; `[]` removes them). | [Bases](https://datanotes.dev/guides/database-objects/bases/) |
27
- | [`add_constraint`](https://datanotes.dev/reference/operations/schema/#add_constraint) | ALTER TABLE ADD CONSTRAINT `name` CHECK: `check` is a where filter every row must match, e.g. | [CHECK constraints](https://datanotes.dev/guides/data-quality/check-constraints/) |
28
- | [`drop_constraint`](https://datanotes.dev/reference/operations/schema/#drop_constraint) | Remove the CHECK constraint `name` from `table`. | [CHECK constraints](https://datanotes.dev/guides/data-quality/check-constraints/) |
29
- | [`create_view`](https://datanotes.dev/reference/operations/schema/#create_view) | Create (or `replace`) a view: a named select stored in metastore.yaml. | [Views](https://datanotes.dev/guides/database-objects/views/) |
30
- | [`drop_view`](https://datanotes.dev/reference/operations/schema/#drop_view) | Remove a view from `metastore.yaml` (undo with `undo_migration`). | [Views](https://datanotes.dev/guides/database-objects/views/) |
13
+ | Operation | What it does | Examples |
14
+ | ------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
15
+ | [`create_table`](https://datanotes.dev/reference/operations/schema/#create_table) | Create a table: `name`, in `catalog` and `schema` (default: the database’s defaults); the definition goes in metastore.yaml, the rows in `<root>/<catalog>/<schema>/<name>/`. | [Catalogs, schemas and the database](https://datanotes.dev/guides/database-objects/catalogs-and-schemas/), [Tables](https://datanotes.dev/guides/database-objects/tables/), [Columns and types](https://datanotes.dev/guides/database-objects/columns/), [Bases](https://datanotes.dev/guides/database-objects/bases/), [Relations and hierarchies](https://datanotes.dev/guides/database-objects/relations/), [Write and move rows](https://datanotes.dev/guides/read-and-write/write-rows/), [Automatic links](https://datanotes.dev/guides/read-and-write/automatic-links/), [Import existing notes](https://datanotes.dev/guides/read-and-write/import-notes/), [Table history and time travel](https://datanotes.dev/guides/history/table-history/) |
16
+ | [`drop_table`](https://datanotes.dev/reference/operations/schema/#drop_table) | Drop a table. | [Tables](https://datanotes.dev/guides/database-objects/tables/) |
17
+ | [`alter_table`](https://datanotes.dev/reference/operations/schema/#alter_table) | Alter a table: move it (`catalog`, `schema`), rename it (`name`), change `partition` / `filename` patterns, `description` (changes, never goes: “” is refused), `aliases`, `exclude` folders, `row_template` (“” removes it), `instructions` (how to fill a row, for agents; “” removes them), `history` (true \| false \| “default”), `autolink_target` (true \| false \| “default”: may automatic links link its rows? default: yes, unless its rows are named by a date or a time) or `tags` (key/value labels merged into the table’s, e.g. | [Catalogs, schemas and the database](https://datanotes.dev/guides/database-objects/catalogs-and-schemas/), [Tables](https://datanotes.dev/guides/database-objects/tables/), [Automatic links](https://datanotes.dev/guides/read-and-write/automatic-links/), [Import existing notes](https://datanotes.dev/guides/read-and-write/import-notes/), [Table history and time travel](https://datanotes.dev/guides/history/table-history/) |
18
+ | [`clone_table`](https://datanotes.dev/reference/operations/schema/#clone_table) | CREATE TABLE `target` CLONE `source`: same definition plus independent copies of its rows (deep clone), optionally as of a `version` / `timestamp`. | [Tables](https://datanotes.dev/guides/database-objects/tables/), [Bases](https://datanotes.dev/guides/database-objects/bases/), [Table history and time travel](https://datanotes.dev/guides/history/table-history/) |
19
+ | [`add_column`](https://datanotes.dev/reference/operations/schema/#add_column) | Add a typed column. | [Columns and types](https://datanotes.dev/guides/database-objects/columns/), [Relations and hierarchies](https://datanotes.dev/guides/database-objects/relations/), [Import existing notes](https://datanotes.dev/guides/read-and-write/import-notes/) |
20
+ | [`rename_column`](https://datanotes.dev/reference/operations/schema/#rename_column) | Rename a column in metastore.yaml and on every row. | [Columns and types](https://datanotes.dev/guides/database-objects/columns/) |
21
+ | [`drop_column`](https://datanotes.dev/reference/operations/schema/#drop_column) | Remove a column from the schema and every row. | [Columns and types](https://datanotes.dev/guides/database-objects/columns/) |
22
+ | [`alter_column`](https://datanotes.dev/reference/operations/schema/#alter_column) | Change a column’s attributes (type, min/max/step, values, required, default, label, 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 `description`, which changes but never goes (null or “” is refused); `dense` true/false). | [Tables](https://datanotes.dev/guides/database-objects/tables/), [Columns and types](https://datanotes.dev/guides/database-objects/columns/), [Relations and hierarchies](https://datanotes.dev/guides/database-objects/relations/) |
23
+ | [`rename_value`](https://datanotes.dev/reference/operations/schema/#rename_value) | Rename one value of an enum column (e.g. | [Columns and types](https://datanotes.dev/guides/database-objects/columns/) |
24
+ | [`comment_on`](https://datanotes.dev/reference/operations/schema/#comment_on) | COMMENT ON CATALOG / SCHEMA: set the `description` of a catalog (`catalog` alone) or of one of its schemas (`catalog` and `schema`) in metastore.yaml: what it holds, so agents pick the right place. | [Catalogs, schemas and the database](https://datanotes.dev/guides/database-objects/catalogs-and-schemas/) |
25
+ | [`define_base`](https://datanotes.dev/reference/operations/schema/#define_base) | Create or replace a base: a named set of columns (same spec as `create_table`) that tables inherit, like a parent class (`bases` in `metastore.yaml`). | [Bases](https://datanotes.dev/guides/database-objects/bases/) |
26
+ | [`set_table_bases`](https://datanotes.dev/reference/operations/schema/#set_table_bases) | Set the bases a table inherits from (`bases`, in order; `[]` removes them). | [Bases](https://datanotes.dev/guides/database-objects/bases/) |
27
+ | [`add_constraint`](https://datanotes.dev/reference/operations/schema/#add_constraint) | ALTER TABLE ADD CONSTRAINT `name` CHECK: `check` is a where filter every row must match, e.g. | [CHECK constraints](https://datanotes.dev/guides/data-quality/check-constraints/) |
28
+ | [`drop_constraint`](https://datanotes.dev/reference/operations/schema/#drop_constraint) | Remove the CHECK constraint `name` from `table`. | [CHECK constraints](https://datanotes.dev/guides/data-quality/check-constraints/) |
29
+ | [`create_view`](https://datanotes.dev/reference/operations/schema/#create_view) | Create (or `replace`) a view: a named select stored in metastore.yaml. | [Views](https://datanotes.dev/guides/database-objects/views/) |
30
+ | [`drop_view`](https://datanotes.dev/reference/operations/schema/#drop_view) | Remove a view from `metastore.yaml` (undo with `undo_migration`). | [Views](https://datanotes.dev/guides/database-objects/views/) |
31
31
 
32
32
  ## Rows (DML)
33
33
 
@@ -50,17 +50,17 @@ Operations that write rows: insert, update, merge, delete, move, adopt and batch
50
50
 
51
51
  Operations that read rows and notes: select_rows, link targets, text and semantic search, the link graph. [Query operations](https://datanotes.dev/reference/operations/queries/) lists their parameters.
52
52
 
53
- | Operation | What it does | Examples |
54
- | ----------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
55
- | [`select_rows`](https://datanotes.dev/reference/operations/queries/#select_rows) | Query rows: `{table, total, rows: [{path, ...}]}`. | [Catalogs, schemas and the database](https://datanotes.dev/guides/database-objects/catalogs-and-schemas/), [Tables](https://datanotes.dev/guides/database-objects/tables/), [Columns and types](https://datanotes.dev/guides/database-objects/columns/), [Views](https://datanotes.dev/guides/database-objects/views/), [Bases](https://datanotes.dev/guides/database-objects/bases/), [Relations and hierarchies](https://datanotes.dev/guides/database-objects/relations/), [Validation](https://datanotes.dev/guides/data-quality/validation/), [CHECK constraints](https://datanotes.dev/guides/data-quality/check-constraints/), [Hand edits](https://datanotes.dev/guides/data-quality/hand-edits/), [Read and filter rows](https://datanotes.dev/guides/read-and-write/read-and-filter/), [Joins and aggregates](https://datanotes.dev/guides/read-and-write/joins-and-aggregates/), [Write and move rows](https://datanotes.dev/guides/read-and-write/write-rows/), [Batch writes](https://datanotes.dev/guides/read-and-write/batch/), [Import existing notes](https://datanotes.dev/guides/read-and-write/import-notes/), [Journal and undo](https://datanotes.dev/guides/history/journal-and-undo/), [Table history and time travel](https://datanotes.dev/guides/history/table-history/), [Restore a table or the database](https://datanotes.dev/guides/history/restore/) |
56
- | [`list_link_targets`](https://datanotes.dev/reference/operations/queries/#list_link_targets) | The rows a link column may point to, for one row: what an agent or a picker offers before writing the link. | [Relations and hierarchies](https://datanotes.dev/guides/database-objects/relations/) |
57
- | [`read_note`](https://datanotes.dev/reference/operations/queries/#read_note) | Read a note or another file of the vault: `{path, content, front_matter, tags, modified_at, created_at, size}`. | [Relations and hierarchies](https://datanotes.dev/guides/database-objects/relations/), [Hand edits](https://datanotes.dev/guides/data-quality/hand-edits/), [Import existing notes](https://datanotes.dev/guides/read-and-write/import-notes/), [Read and search notes](https://datanotes.dev/guides/search/text/) |
58
- | [`list_folder`](https://datanotes.dev/reference/operations/queries/#list_folder) | The direct children of a vault folder: `{folder, folders, files}`, each a vault path, sorted; dot-files and dot-folders are left out. | [Catalogs, schemas and the database](https://datanotes.dev/guides/database-objects/catalogs-and-schemas/), [Tables](https://datanotes.dev/guides/database-objects/tables/), [Columns and types](https://datanotes.dev/guides/database-objects/columns/), [Write and move rows](https://datanotes.dev/guides/read-and-write/write-rows/), [Read and search notes](https://datanotes.dev/guides/search/text/) |
59
- | [`search_notes`](https://datanotes.dev/reference/operations/queries/#search_notes) | Plain-text search: every word of `query` must occur, case- and accent-insensitive, in the note’s path or text; there are no operators. | [Read and search notes](https://datanotes.dev/guides/search/text/) |
60
- | [`semantic_search`](https://datanotes.dev/reference/operations/queries/#semantic_search) | Find notes by meaning, not exact words: `{query, results: [{path, score, heading, snippet, table?}]}`, one result per note (its best passage), best first. | [Find notes by meaning](https://datanotes.dev/guides/search/semantic/) |
61
- | [`graph_neighbors`](https://datanotes.dev/reference/operations/queries/#graph_neighbors) | Direct neighbours of notes: what they link to (`out`) and what links to them (`in`, backlinks), with counts per edge label. | [Walk the link graph](https://datanotes.dev/guides/search/link-graph/) |
62
- | [`graph_traverse`](https://datanotes.dev/reference/operations/queries/#graph_traverse) | Breadth-first walk over links from `from_nodes` (`{"paths": [...]}` and/or `{"table", "where"}`). | [Walk the link graph](https://datanotes.dev/guides/search/link-graph/) |
63
- | [`graph_path`](https://datanotes.dev/reference/operations/queries/#graph_path) | Shortest chain of links between two sets of notes (each `{"paths": [...]}` and/or `{"table", "where"}`): `found`, `length` and `path`: the steps (`from`, `label`, `direction`, `to`). | [Walk the link graph](https://datanotes.dev/guides/search/link-graph/) |
53
+ | Operation | What it does | Examples |
54
+ | ----------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
55
+ | [`select_rows`](https://datanotes.dev/reference/operations/queries/#select_rows) | Query rows: `{table, total, rows: [{path, ...}]}`. | [Catalogs, schemas and the database](https://datanotes.dev/guides/database-objects/catalogs-and-schemas/), [Tables](https://datanotes.dev/guides/database-objects/tables/), [Columns and types](https://datanotes.dev/guides/database-objects/columns/), [Views](https://datanotes.dev/guides/database-objects/views/), [Bases](https://datanotes.dev/guides/database-objects/bases/), [Relations and hierarchies](https://datanotes.dev/guides/database-objects/relations/), [Validation](https://datanotes.dev/guides/data-quality/validation/), [CHECK constraints](https://datanotes.dev/guides/data-quality/check-constraints/), [Hand edits](https://datanotes.dev/guides/data-quality/hand-edits/), [Read and filter rows](https://datanotes.dev/guides/read-and-write/read-and-filter/), [Joins and aggregates](https://datanotes.dev/guides/read-and-write/joins-and-aggregates/), [Write and move rows](https://datanotes.dev/guides/read-and-write/write-rows/), [Batch writes](https://datanotes.dev/guides/read-and-write/batch/), [Import existing notes](https://datanotes.dev/guides/read-and-write/import-notes/), [Journal and undo](https://datanotes.dev/guides/history/journal-and-undo/), [Table history and time travel](https://datanotes.dev/guides/history/table-history/), [Restore a table or the database](https://datanotes.dev/guides/history/restore/) |
56
+ | [`list_link_targets`](https://datanotes.dev/reference/operations/queries/#list_link_targets) | The rows a link column may point to, for one row: what an agent or a picker offers before writing the link. | [Relations and hierarchies](https://datanotes.dev/guides/database-objects/relations/) |
57
+ | [`read_note`](https://datanotes.dev/reference/operations/queries/#read_note) | Read a note or another file of the vault: `{path, content, front_matter, tags, modified_at, created_at, size}`. | [Relations and hierarchies](https://datanotes.dev/guides/database-objects/relations/), [Hand edits](https://datanotes.dev/guides/data-quality/hand-edits/), [Import existing notes](https://datanotes.dev/guides/read-and-write/import-notes/), [Read and search notes](https://datanotes.dev/guides/search/text/) |
58
+ | [`list_folder`](https://datanotes.dev/reference/operations/queries/#list_folder) | The direct children of a vault folder: `{folder, folders, files}`, each a vault path, sorted; dot-files and dot-folders are left out. | [Catalogs, schemas and the database](https://datanotes.dev/guides/database-objects/catalogs-and-schemas/), [Tables](https://datanotes.dev/guides/database-objects/tables/), [Columns and types](https://datanotes.dev/guides/database-objects/columns/), [Write and move rows](https://datanotes.dev/guides/read-and-write/write-rows/), [Read and search notes](https://datanotes.dev/guides/search/text/) |
59
+ | [`search_notes`](https://datanotes.dev/reference/operations/queries/#search_notes) | Plain-text search: every word of `query` must occur, case- and accent-insensitive, in the note’s path or text; there are no operators. | [Read and search notes](https://datanotes.dev/guides/search/text/) |
60
+ | [`semantic_search`](https://datanotes.dev/reference/operations/queries/#semantic_search) | Find notes by meaning, not exact words: `{query, results: [{path, score, heading, snippet, table?}]}`, one result per note (its best passage), best first. | [Find notes by meaning](https://datanotes.dev/guides/search/semantic/) |
61
+ | [`graph_neighbors`](https://datanotes.dev/reference/operations/queries/#graph_neighbors) | Direct neighbours of notes: what they link to (`out`) and what links to them (`in`, backlinks), with counts per edge label. | [Walk the link graph](https://datanotes.dev/guides/search/link-graph/) |
62
+ | [`graph_traverse`](https://datanotes.dev/reference/operations/queries/#graph_traverse) | Breadth-first walk over links from `from_nodes` (`{"paths": [...]}`, `{"table", "where"}` and/or `{"tables": [...]}`). | [Walk the link graph](https://datanotes.dev/guides/search/link-graph/) |
63
+ | [`graph_path`](https://datanotes.dev/reference/operations/queries/#graph_path) | Shortest chain of links between two sets of notes (each `{"paths": [...]}`, `{"table", "where"}` and/or `{"tables": [...]}`): `found`, `length` and `path`: the steps (`from`, `label`, `direction`, `to`). | [Walk the link graph](https://datanotes.dev/guides/search/link-graph/) |
64
64
 
65
65
  ## History
66
66
 
@@ -84,13 +84,13 @@ Operations on the journal, a table’s versions, the change feed and webhooks: u
84
84
 
85
85
  Operations that describe and check the database, configure it and maintain its indexes. [Auxiliary operations](https://datanotes.dev/reference/operations/auxiliary/) lists their parameters.
86
86
 
87
- | Operation | What it does | Examples |
88
- | ------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
89
- | [`list_tables`](https://datanotes.dev/reference/operations/auxiliary/#list_tables) | List every table: `name`, `catalog`, `schema`, `qualified` (`personal.metrics.mood` — use it wherever a table is expected; `metrics.mood` or `mood` also work when unambiguous), `path` and, when declared, `description`, `aliases` (other words for what it records) and `tags`. | [Tables](https://datanotes.dev/guides/database-objects/tables/), [Views](https://datanotes.dev/guides/database-objects/views/) |
90
- | [`describe_table`](https://datanotes.dev/reference/operations/auxiliary/#describe_table) | Describe a table (`catalog.schema.table` or a shorter unambiguous name): `qualified`, `name`, `catalog`, `schema`, `description`, `aliases`, `layout` (`folder`, `row_folder`: the folder pattern of new rows, `archive`), `options` (`partition`, `filename`, `archive`, `exclude`), typed `columns` with label/aliases/description and the dense flag, `untyped_fields`, `row_count`, and when set: `tags`, `bases` (the bases it inherits from, in order), `constraints` (its CHECKs, name → where), `row_template`, `history`, `autolink_target`, `fields` (their values). | [Catalogs, schemas and the database](https://datanotes.dev/guides/database-objects/catalogs-and-schemas/), [Tables](https://datanotes.dev/guides/database-objects/tables/), [Bases](https://datanotes.dev/guides/database-objects/bases/), [Relations and hierarchies](https://datanotes.dev/guides/database-objects/relations/) |
91
- | [`describe_database`](https://datanotes.dev/reference/operations/auxiliary/#describe_database) | Describe the database: its folder (`root`), `metastore` (`metastore.yaml`: read it freely, but it is read-only for agents and changes only through the schema operations), configuration (default catalog and schema, row partition and file-name formats, archive folder, time zone, history, automatic links), journal folder, `bases` (shared column sets and the tables using them), `catalogs` → `schemas` → `tables` (with `row_count`, `tags`, and `unreadable_count` when some rows’ front matter cannot be read) and `views`; catalogs and schemas show their `comment` (set with `comment_on`). | [Catalogs, schemas and the database](https://datanotes.dev/guides/database-objects/catalogs-and-schemas/), [Hand edits](https://datanotes.dev/guides/data-quality/hand-edits/) |
92
- | [`configure_database`](https://datanotes.dev/reference/operations/auxiliary/#configure_database) | Configure the database (persisted in metastore.yaml `config:`): `root` (rename the database folder; links follow; revert by renaming back), `default_catalog`, `default_schema`, `default_partition` (“” = flat) and `default_filename` (date formats for new time-based tables), `archive_folder`, `timezone` (IANA; completes date-times written without offset), `history` (transaction log for every table: true in a database the engine creates, false when `config` lacks it, as in a metastore from before 3.0.0; change it only on the user’s request), `autolink` (the text a write puts in a body links the notes it mentions; on by default). | [Catalogs, schemas and the database](https://datanotes.dev/guides/database-objects/catalogs-and-schemas/), [Tables](https://datanotes.dev/guides/database-objects/tables/), [Automatic links](https://datanotes.dev/guides/read-and-write/automatic-links/), [Table history and time travel](https://datanotes.dev/guides/history/table-history/) |
93
- | [`check_table`](https://datanotes.dev/reference/operations/auxiliary/#check_table) | Validate every row against the table (required, types, ranges, enums, links, unknown 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). | [Relations and hierarchies](https://datanotes.dev/guides/database-objects/relations/), [Hand edits](https://datanotes.dev/guides/data-quality/hand-edits/), [Find rows that break the schema](https://datanotes.dev/guides/data-quality/check-table/) |
94
- | [`infer_table`](https://datanotes.dev/reference/operations/auxiliary/#infer_table) | Read-only schema inference from notes’ front matter. | [Hand edits](https://datanotes.dev/guides/data-quality/hand-edits/), [Import existing notes](https://datanotes.dev/guides/read-and-write/import-notes/) |
95
- | [`describe_semantic_index`](https://datanotes.dev/reference/operations/auxiliary/#describe_semantic_index) | The semantic search index: `enabled`, `provider`, `model`, `files`, `passages`, `pending`, `running`, `last_sync`, `last_error`. | [Find notes by meaning](https://datanotes.dev/guides/search/semantic/) |
96
- | [`sync_semantic_index`](https://datanotes.dev/reference/operations/auxiliary/#sync_semantic_index) | Bring the semantic search index up to date: embed the notes changed since the last run (the engine also does it on its own about ten seconds after edits). | [Find notes by meaning](https://datanotes.dev/guides/search/semantic/) |
87
+ | Operation | What it does | Examples |
88
+ | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
89
+ | [`list_tables`](https://datanotes.dev/reference/operations/auxiliary/#list_tables) | List every table: `name`, `catalog`, `schema`, `qualified` (`personal.metrics.mood` — use it wherever a table is expected; `metrics.mood` or `mood` also work when unambiguous), `path` and, when declared, `description`, `aliases` (other words for what it records) and `tags`. | [Tables](https://datanotes.dev/guides/database-objects/tables/), [Views](https://datanotes.dev/guides/database-objects/views/) |
90
+ | [`describe_table`](https://datanotes.dev/reference/operations/auxiliary/#describe_table) | Describe a table (`catalog.schema.table` or a shorter unambiguous name): `qualified`, `name`, `catalog`, `schema`, `description`, `aliases`, `layout` (`folder`, `row_folder`: the folder pattern of new rows, `archive`), `options` (`partition`, `filename`, `archive`, `exclude`), typed `columns` with label/aliases/description and the dense flag, `untyped_fields`, `row_count`, and when set: `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`, `autolink_target`, `fields` (their values). | [Catalogs, schemas and the database](https://datanotes.dev/guides/database-objects/catalogs-and-schemas/), [Tables](https://datanotes.dev/guides/database-objects/tables/), [Bases](https://datanotes.dev/guides/database-objects/bases/), [Relations and hierarchies](https://datanotes.dev/guides/database-objects/relations/) |
91
+ | [`describe_database`](https://datanotes.dev/reference/operations/auxiliary/#describe_database) | Describe the database: its folder (`root`), `metastore` (`metastore.yaml`: read it freely, but it is read-only for agents and changes only through the schema operations), configuration (default catalog and schema, row partition and file-name formats, archive folder, time zone, history, automatic links), journal folder, `bases` (shared column sets and the tables using them), `catalogs` → `schemas` → `tables` (with `row_count`, `tags`, and `unreadable_count` when some rows’ front matter cannot be read) and `views`; catalogs and schemas show their `comment` (set with `comment_on`). | [Catalogs, schemas and the database](https://datanotes.dev/guides/database-objects/catalogs-and-schemas/), [Hand edits](https://datanotes.dev/guides/data-quality/hand-edits/) |
92
+ | [`configure_database`](https://datanotes.dev/reference/operations/auxiliary/#configure_database) | Configure the database (persisted in metastore.yaml `config:`): `root` (rename the database folder; links follow; revert by renaming back), `default_catalog`, `default_schema`, `default_partition` (“” = flat) and `default_filename` (date formats for new time-based tables), `archive_folder`, `timezone` (IANA; completes date-times written without offset), `history` (transaction log for every table: true in a database the engine creates, false when `config` lacks it, as in a metastore from before 3.0.0; change it only on the user’s request), `autolink` (the text a write puts in a body links the notes it mentions; on by default). | [Catalogs, schemas and the database](https://datanotes.dev/guides/database-objects/catalogs-and-schemas/), [Tables](https://datanotes.dev/guides/database-objects/tables/), [Automatic links](https://datanotes.dev/guides/read-and-write/automatic-links/), [Table history and time travel](https://datanotes.dev/guides/history/table-history/) |
93
+ | [`check_table`](https://datanotes.dev/reference/operations/auxiliary/#check_table) | Validate every row against the table (required, types, ranges, enums, links, unknown 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). | [Relations and hierarchies](https://datanotes.dev/guides/database-objects/relations/), [Hand edits](https://datanotes.dev/guides/data-quality/hand-edits/), [Find rows that break the schema](https://datanotes.dev/guides/data-quality/check-table/) |
94
+ | [`infer_table`](https://datanotes.dev/reference/operations/auxiliary/#infer_table) | Read-only schema inference from notes’ front matter. | [Hand edits](https://datanotes.dev/guides/data-quality/hand-edits/), [Import existing notes](https://datanotes.dev/guides/read-and-write/import-notes/) |
95
+ | [`describe_semantic_index`](https://datanotes.dev/reference/operations/auxiliary/#describe_semantic_index) | The semantic search index: `enabled`, `provider`, `model`, `files`, `passages`, `pending`, `running`, `last_sync`, `last_error`. | [Find notes by meaning](https://datanotes.dev/guides/search/semantic/) |
96
+ | [`sync_semantic_index`](https://datanotes.dev/reference/operations/auxiliary/#sync_semantic_index) | Bring the semantic search index up to date: embed the notes changed since the last run (the engine also does it on its own about ten seconds after edits). | [Find notes by meaning](https://datanotes.dev/guides/search/semantic/) |
@@ -4,28 +4,40 @@
4
4
 
5
5
  The headless engine reads `settings.json` in its store, outside the vault (`datanotes store path` shows where), or the file given with `--settings`. Missing keys take their default.
6
6
 
7
- | Key | Default | Meaning |
8
- | ---------------------------- | ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
9
- | `journalRetentionDays` | `90` | Journal entries older than this many days are dropped (undo is no longer possible for them). |
10
- | `fileLogEnabled` | `true` | Write log records to `logs/<day>.<source>.jsonl` in the engine’s store. |
11
- | `logRetentionDays` | `30` | Log files older than this many days are deleted. |
12
- | `tableKey` | `"table"` | Row property naming the catalog table a note belongs to (`table: personal.metrics.mood`). |
13
- | `telemetryEnabled` | `false` | Send the engine’s logs to an OpenTelemetry collector or OTLP backend (OTLP/HTTP). |
14
- | `telemetryEndpoint` | `"http://127.0.0.1:4318"` | OTLP/HTTP base URL; logs are POSTed to `<endpoint>/v1/logs`. |
15
- | `telemetryServiceName` | `"datanotes"` | `service.name` resource attribute. |
16
- | `telemetryHeaders` | `{}` | HTTP headers sent with every export: the API key or `Authorization` the backend asks for. Kept in the settings file; `OTEL_EXPORTER_OTLP_HEADERS` adds to them. |
17
- | `telemetryProtocol` | `"http/protobuf"` | OTLP encoding: `http/protobuf` (the OpenTelemetry default) or `http/json`. |
18
- | `autoRecompute` | `true` | After a row is edited by hand, recompute its generated / identity columns (a few seconds after the last change, as a journaled `recompute_columns` operation). |
19
- | `repairLinksOnHandMove` | `true` | Rewrite the links to a note renamed or moved by hand (in a file manager, with git or a sync tool), across the vault, once the vault has been quiet for 4 s and not while git pulls, rebases or merges. The repair is one journaled `repair_links` operation that undo takes back. Links an editor already rewrote stay as they are. |
20
- | `semanticEnabled` | `false` | Semantic search: embed notes with `semanticProvider` (off by default: content is sent to it). |
21
- | `semanticProvider` | `"ollama"` | Embedding provider: `ollama`, `lmstudio`, `openrouter`, `openai` or `custom` (any OpenAI-compatible API). |
22
- | `semanticBaseUrl` | `""` | Empty: the provider’s default URL. |
23
- | `semanticModel` | `""` | Embedding model, e.g. `nomic-embed-text` (Ollama) or `openai/text-embedding-3-small` (OpenRouter). |
24
- | `semanticScope` | `"vault"` | “vault”: every note; “tables”: only table rows. |
25
- | `semanticExclude` | `[]` | Folders left out of the index. |
26
- | `semanticBatchSize` | `32` | Passages per embedding request. |
27
- | `httpServerPort` | `27150` | Port of the HTTP API (on 127.0.0.1 unless the service is told otherwise): 1024 to 65535, or 0 for any free port. Any other value stops the engine from starting. |
28
- | `httpServerToken` | `""` | The owner’s bearer token (generated at the first start). |
29
- | `storeBackupEnabled` | `false` | Back up the engine’s store to a git repository: commits as `storeBackupIntervalSeconds` says, each pushed to `storeBackupRemote` (headless engine; `datanotes store backup` sets it). |
30
- | `storeBackupRemote` | `""` | The git remote the store backup pushes to, such as a private GitHub repository. Empty: commits in the store only, nothing pushed. |
31
- | `storeBackupIntervalSeconds` | `60` | How often the store backup looks for changes, in seconds (at least 10): when something changed, it commits between two operations (a consistent snapshot), then pushes. |
7
+ | Key | Default | Meaning |
8
+ | ---------------------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
9
+ | `journalRetentionDays` | `90` | Journal entries older than this many days are dropped (undo is no longer possible for them). |
10
+ | `fileLogEnabled` | `true` | Write log records to `logs/<day>.<source>.jsonl` in the engine’s store. |
11
+ | `logRetentionDays` | `30` | Log files older than this many days are deleted. |
12
+ | `tableKey` | `"table"` | Row property naming the catalog table a note belongs to (`table: personal.metrics.mood`). |
13
+ | `telemetryEnabled` | `false` | Send the engine’s logs and traces to an OpenTelemetry collector or OTLP backend (OTLP/HTTP). |
14
+ | `telemetryEndpoint` | `"http://127.0.0.1:4318"` | OTLP/HTTP base URL; logs are POSTed to `<endpoint>/v1/logs`, traces to `<endpoint>/v1/traces`. |
15
+ | `telemetryServiceName` | `"datanotes"` | `service.name` resource attribute. |
16
+ | `telemetryHeaders` | `{}` | HTTP headers sent with every export: the API key or `Authorization` the backend asks for. Kept in the settings file; `OTEL_EXPORTER_OTLP_HEADERS` adds to them. |
17
+ | `telemetryProtocol` | `"http/protobuf"` | OTLP encoding: `http/protobuf` (the OpenTelemetry default) or `http/json`. |
18
+ | `telemetryTraces` | `true` | Send traces too while telemetry is on: a span for every HTTP request, operation and phase of an operation (lock, query, checks, journal, vault calls), with its duration and parent. `OTEL_TRACES_EXPORTER=none` turns them off. |
19
+ | `telemetryTraceSampleRatio` | `1` | Share of new traces kept, from 0 to 1 (1: every one). A trace continued from a caller (`traceparent`) follows the caller’s choice. `OTEL_TRACES_SAMPLER` overrides it. |
20
+ | `telemetryMaxSpansPerTrace` | `1000` | Most spans one trace may hold (1 to 100000); the others are dropped and counted in `datanotes.spans_dropped`. |
21
+ | `telemetrySlowSpanMs` | `0` | A request, operation or background job lasting at least this many milliseconds is also logged as a WARN (0: never). |
22
+ | `telemetryEnvironment` | `""` | `deployment.environment.name` of the logs and traces, such as `dev` or `home` (empty: none). |
23
+ | `autoRecompute` | `true` | After a row is edited by hand, recompute its generated / identity columns (a few seconds after the last change, as a journaled `recompute_columns` operation). |
24
+ | `repairLinksOnHandMove` | `true` | Rewrite the links to a note renamed or moved by hand (in a file manager, with git or a sync tool), across the vault, once the vault has been quiet for 4 s and not while git pulls, rebases or merges. The repair is one journaled `repair_links` operation that undo takes back. Links an editor already rewrote stay as they are. |
25
+ | `semanticEnabled` | `false` | Semantic search: embed notes with `semanticProvider` (off by default: content is sent to it). |
26
+ | `semanticProvider` | `"ollama"` | Embedding provider: `ollama`, `lmstudio`, `openrouter`, `openai` or `custom` (any OpenAI-compatible API). |
27
+ | `semanticBaseUrl` | `""` | Empty: the provider’s default URL. |
28
+ | `semanticModel` | `""` | Embedding model, e.g. `nomic-embed-text` (Ollama) or `openai/text-embedding-3-small` (OpenRouter). |
29
+ | `semanticScope` | `"vault"` | “vault”: every note; “tables”: only table rows. |
30
+ | `semanticExclude` | `[]` | Folders left out of the index. |
31
+ | `semanticBatchSize` | `32` | Passages per embedding request. |
32
+ | `writePriority` | `true` | Write priority: while a write runs or waits, new reads wait for it (reads under way finish), so a stream of reads does not slow a write down. Writes start one at a time, in order. |
33
+ | `writePriorityMaxWaitMs` | `100` | The longest a read waits for writes under `writePriority`, in milliseconds (0 to 60000). |
34
+ | `readCacheMaxBytes` | `33554432` | Memory for the answers of repeated reads, in bytes (0: no cache). A read asked again with the same arguments is answered from it while nothing it depends on has changed. |
35
+ | `vaultIndexEnabled` | `true` | Keep an index of the vault’s notes in the engine’s store (`index/vault.sqlite`), so that a start reads only the notes changed since the last one, and `search_notes` only the notes that can match (headless engine, Node 22.13 or later). The index is a cache: deleting it is safe, the next start builds it again. Off: every start and every search reads every note, and the index is deleted. |
36
+ | `httpServerPort` | `27150` | Port of the HTTP API (on 127.0.0.1 unless the service is told otherwise): 1024 to 65535, or 0 for any free port. Any other value stops the engine from starting. |
37
+ | `httpServerToken` | `""` | The owner’s bearer token (generated at the first start). |
38
+ | `httpCompression` | `"remote"` | Which clients of the HTTP API get answers of 16 KB or more compressed with gzip, when their request says `Accept-Encoding: gzip`: `remote` (default) those on other machines, `always` this machine’s too, `off` none. Compressing costs the engine time that a client on the same machine does not win back. |
39
+ | `storeBackupEnabled` | `false` | Back up the engine’s store to a git repository: commits as `storeBackupIntervalSeconds` says, each pushed to `storeBackupRemote` (headless engine; `datanotes store backup` sets it). |
40
+ | `storeBackupRemote` | `""` | The git remote the store backup pushes to, such as a private GitHub repository. Empty: commits in the store only, nothing pushed. |
41
+ | `storeBackupIntervalSeconds` | `60` | How often the store backup looks for changes, in seconds (at least 10): when something changed, it commits between two operations (a consistent snapshot), then pushes. |
42
+ | `storeSync` | `"operation"` | How the engine makes its store files durable: `operation` syncs (fsync) every store file an operation wrote once, when the operation ends (the journal line, the transaction log, the blobs; the change feed after each of its appends); `off` leaves it to the operating system, which is faster but lets a power loss take the last operations’ undo data and history. Notes are never synced (they are written atomically, as Obsidian writes them). Headless engine. |
43
+ | `transactionLogFormat` | `"segments"` | How the transaction log writes new versions: `segments` (default since 3.1) appends them to a few large files (far fewer files for the antivirus, git and the store backup), which Datanotes 3.0 cannot read: run `datanotes store convert-log --to files` before you go back to it; `files` writes one file per version, which every Datanotes 3 reads. The engine reads both, also mixed in one folder: a log of 3.0 keeps its files and grows in segments. |