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.
Files changed (41) hide show
  1. package/dist/api/index.cjs +175 -8
  2. package/dist/api/index.js +175 -8
  3. package/dist/api/mcp.cjs +175 -8
  4. package/dist/api/mcp.js +175 -8
  5. package/dist/datanotes.cjs +591 -139
  6. package/dist/docs/api/operations/add_column.md +1 -0
  7. package/dist/docs/api/operations/add_constraint.md +2 -0
  8. package/dist/docs/api/operations/alter_column.md +1 -1
  9. package/dist/docs/api/operations/alter_table.md +3 -2
  10. package/dist/docs/api/operations/check_table.md +1 -1
  11. package/dist/docs/api/operations/create_table.md +3 -1
  12. package/dist/docs/api/operations/describe_table.md +1 -1
  13. package/dist/docs/api/operations/insert_row.md +2 -2
  14. package/dist/docs/api/operations/tags/rows-dml.md +1 -1
  15. package/dist/docs/api.md +2 -2
  16. package/dist/docs/guides/data-quality/check-constraints.md +14 -13
  17. package/dist/docs/guides/data-quality/hand-edits.md +10 -10
  18. package/dist/docs/guides/database-objects/bases.md +11 -11
  19. package/dist/docs/guides/database-objects/catalogs-and-schemas.md +16 -10
  20. package/dist/docs/guides/database-objects/columns.md +38 -38
  21. package/dist/docs/guides/database-objects/relations.md +173 -36
  22. package/dist/docs/guides/database-objects/tables.md +80 -35
  23. package/dist/docs/guides/database-objects/views.md +44 -44
  24. package/dist/docs/guides/history/change-data-feed.md +34 -34
  25. package/dist/docs/guides/history/journal-and-undo.md +12 -12
  26. package/dist/docs/guides/history/restore.md +20 -20
  27. package/dist/docs/guides/history/table-history.md +31 -31
  28. package/dist/docs/guides/read-and-write/automatic-links.md +15 -15
  29. package/dist/docs/guides/read-and-write/import-notes.md +21 -21
  30. package/dist/docs/guides/read-and-write/joins-and-aggregates.md +7 -7
  31. package/dist/docs/guides/read-and-write/read-and-filter.md +10 -10
  32. package/dist/docs/guides/read-and-write/write-rows.md +10 -10
  33. package/dist/docs/guides/search/text.md +1 -1
  34. package/dist/docs/reference/cli.md +1 -1
  35. package/dist/docs/reference/errors.md +1 -1
  36. package/dist/docs/reference/operations/auxiliary.md +2 -2
  37. package/dist/docs/reference/operations/rows.md +1 -1
  38. package/dist/docs/reference/operations/schema.md +15 -11
  39. package/dist/docs/reference/operations.md +28 -28
  40. package/dist/docs/release-notes.md +24 -0
  41. package/package.json +1 -1
@@ -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
 
@@ -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,6 +4,30 @@
4
4
 
5
5
  This page lists each version of Datanotes, newest first. Datanotes follows [semantic versioning](https://semver.org): a major version can break what you rely on, and its notes list those changes first. The package is on [npm](https://www.npmjs.com/package/datanotes), and each version has a [GitHub release](https://github.com/davidefornelli/datanotes/releases).
6
6
 
7
+ ## 3.2.0
8
+
9
+ Datanotes 3.2.0 keeps the links between rows of one table free of cycles. It also lets a table tell agents how to fill its rows. It only adds to 3.1: no operation, argument or setting goes away.
10
+
11
+ ### Links without cycles
12
+
13
+ A link column, or a list of links, to its own table takes `acyclic: true`. The engine then refuses a write that makes a row depend on itself through that column. An example is a task blocked by a task it blocks. [Keep dependencies free of cycles with `acyclic`](https://datanotes.dev/guides/database-objects/relations/#keep-dependencies-free-of-cycles-with-acyclic) shows it.
14
+
15
+ * **Both sides**: with `inverse`, a write to either column is checked. The links the engine adds on the other side count too.
16
+ * **Existing rows**: `add_column` and `alter_column` refuse `acyclic: true` while rows already form a cycle, and list them.
17
+ * **Hand edits**: `check_table` and the change feed report a cycle made outside the engine.
18
+ * **The refusal**: it shows the cycle, such as `would close a cycle in "blocked_by" (A → B → A)`. It has its own hint and docs.
19
+ * **`system.information_schema.columns`**: a new column, `is_acyclic`.
20
+
21
+ ### Tell agents how to fill a table
22
+
23
+ * **`instructions`**: `create_table` and `alter_table` take Markdown text that says how to fill a row. It can list which columns come first and what to ask the user. `describe_table` returns it, and `instructions: ""` removes it. [Tell agents how to fill a row with `instructions`](https://datanotes.dev/guides/database-objects/tables/#tell-agents-how-to-fill-a-row-with-instructions) shows it.
24
+ * **A hint for each CHECK**: `add_constraint` takes `hint`, what to do when a row breaks the rule. A refused write puts it first in its `hint`, and each violation of that CHECK carries it as `hint`. `describe_table` lists the hints in `constraint_hints`, next to `constraints`.
25
+ * **`system.information_schema`**: `tables` has a new column, `instructions`, and `check_constraints` a new column, `hint`.
26
+
27
+ ### Fixes
28
+
29
+ * `alter_column` with `ref: "self"` no longer refuses the links a column already holds.
30
+
7
31
  ## 3.1.0
8
32
 
9
33
  Datanotes 3.1.0 makes the engine fast at scale and adds OpenTelemetry traces. It only adds to 3.0: no operation, argument or setting goes away. One default changes: the transaction log now writes segments. Read [Before you downgrade to 3.0](#before-you-downgrade-to-30) if you may go back.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "datanotes",
3
- "version": "3.1.0",
3
+ "version": "3.2.0",
4
4
  "mcpName": "io.github.davidefornelli/datanotes",
5
5
  "description": "The engine of your second brain: Markdown notes as database tables, for you and your agents.",
6
6
  "keywords": [