@omgbase/core 0.23.0 → 0.27.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 (45) hide show
  1. package/dist/src/core/edit-script.d.ts +15 -0
  2. package/dist/src/core/edit-script.js +72 -0
  3. package/dist/src/core/ingest.js +42 -12
  4. package/dist/src/core/read/document.d.ts +7 -0
  5. package/dist/src/core/read/document.js +38 -17
  6. package/dist/src/core/store/archive.d.ts +28 -0
  7. package/dist/src/core/store/archive.js +106 -17
  8. package/dist/src/core/store/delta.d.ts +131 -0
  9. package/dist/src/core/store/delta.js +470 -0
  10. package/dist/src/core/store/gc.d.ts +10 -0
  11. package/dist/src/core/store/gc.js +23 -7
  12. package/dist/src/core/store/retention.d.ts +1 -1
  13. package/dist/src/core/store/retention.js +3 -17
  14. package/dist/src/core/store/schema.d.ts +1 -1
  15. package/dist/src/core/store/schema.js +2 -1
  16. package/dist/src/core/store/store.js +7 -0
  17. package/dist/src/core/store/writers.d.ts +42 -6
  18. package/dist/src/core/store/writers.js +67 -25
  19. package/dist/src/format/json.js +5 -0
  20. package/dist/src/format/yaml.js +15 -3
  21. package/dist/src/graph/history.d.ts +1 -15
  22. package/dist/src/graph/history.js +14 -74
  23. package/dist/src/mcp/arguments.d.ts +11 -0
  24. package/dist/src/mcp/arguments.js +47 -4
  25. package/dist/src/mcp/errors.js +1 -1
  26. package/dist/src/mcp/reference.d.ts +1 -1
  27. package/dist/src/mcp/reference.js +29 -9
  28. package/dist/src/mcp/server.js +4 -2
  29. package/dist/src/mutate/effects.js +87 -13
  30. package/dist/src/mutate/frontmatter-parts.d.ts +71 -0
  31. package/dist/src/mutate/frontmatter-parts.js +237 -0
  32. package/dist/src/mutate/load.js +9 -9
  33. package/dist/src/mutate/select.js +14 -4
  34. package/dist/src/oqx-js/context.js +32 -3
  35. package/dist/src/oqx-js/names.js +1 -1
  36. package/dist/src/oqx-js/planner.js +11 -7
  37. package/dist/src/oqx-js/run.d.ts +8 -0
  38. package/dist/src/oqx-js/run.js +103 -2
  39. package/dist/src/oqx-js/sql/translate.js +33 -6
  40. package/dist/src/oqx-js/store-index.js +1 -1
  41. package/dist/src/search/cel/parser.d.ts +3 -1
  42. package/dist/src/search/cel/parser.js +4 -1
  43. package/dist/src/spec-versions.d.ts +5 -5
  44. package/dist/src/spec-versions.js +4 -4
  45. package/package.json +2 -2
@@ -56,18 +56,20 @@ export const NON_PROPERTY_NAMES = {
56
56
  docs: new Set(["doc", "nodes", "blocks", "out_links", "in_links", "revisions", "data", "frontmatter", "inline"]),
57
57
  blocks: new Set(["block", "doc", "children", "nodes", "out_links", "section", "attrs"]),
58
58
  nodes: new Set(["section", "doc", "block", "blocks", "subsections", "children", "attrs"]),
59
- links: new Set(["doc", "dst"]),
59
+ links: new Set(["doc", "dst", "block"]),
60
60
  };
61
61
  // ---- engine attributes ------------------------------------------------------
62
62
  // The engine attributes (spec/surface §1.2, 3.0: bare, snake_case, winning on
63
- // collision — `id`, `path`, `raw`, `hash`, `updated_at` on docs and blocks,
64
- // `title`/`tags` on docs, `id`/`path` on nodes and edges) → a param-free SQL
63
+ // collision — `id`, `path`, `raw`, `hash`, `updated_at`, `created_at` on docs
64
+ // and blocks, `title`/`tags` on docs, `id`/`path` on nodes and edges) → a param-free SQL
65
65
  // scalar, per target, with its kind. The structural columns and foreign keys are
66
66
  // translated in `translateOperand`. Anything not mapped (`raw`, reconstructed or
67
67
  // a blob; `title`, computed; `tags`, the union of the authored list and the
68
68
  // computed hashtags) returns null → residual, and the caller must NOT fall
69
69
  // through to a property read of the same name (the attribute wins in memory).
70
- // `updated_at` is a correlated subquery. `path` (and the edge field `dst_path`)
70
+ // `updated_at` and `created_at` (4.10) are correlated subqueries over the
71
+ // document's revisions (`current_rev` / `seq = 1`); a block's are residual, as
72
+ // before. `path` (and the edge field `dst_path`)
71
73
  // is the REFERENCE form on the surface (spec/surface §1 "Paths", 2.0) — `'/' ||
72
74
  // <storage column>` in SQL — so every comparison, `startsWith`, `contains`,
73
75
  // `lower()`… sees exactly the string the in-memory attribute yields;
@@ -79,8 +81,8 @@ export function pathColumn(col) {
79
81
  /** The identity/bytes/time attributes per kind — the names `attributeSql` owns
80
82
  * (the structural columns are handled per target in `translateOperand`). */
81
83
  export const ROW_ATTRIBUTES = {
82
- docs: new Set(["id", "path", "raw", "hash", "updated_at", "title", "tags"]),
83
- blocks: new Set(["id", "path", "raw", "hash", "updated_at"]),
84
+ docs: new Set(["id", "path", "raw", "hash", "updated_at", "created_at", "title", "tags"]),
85
+ blocks: new Set(["id", "path", "raw", "hash", "updated_at", "created_at"]),
84
86
  nodes: new Set(["id", "path"]),
85
87
  links: new Set(["id", "path"]),
86
88
  };
@@ -93,6 +95,7 @@ function attributeSql(name, ctx) {
93
95
  case "path": return pathColumn(`${doc}.path`);
94
96
  case "hash": return text(`lower(hex(${self}.file_hash))`);
95
97
  case "updated_at": return text(`(SELECT c.ts FROM revisions r JOIN commits c ON c.commit_id = r.commit_id WHERE r.rev_id = ${self}.current_rev)`);
98
+ case "created_at": return text(`(SELECT c.ts FROM revisions r JOIN commits c ON c.commit_id = r.commit_id WHERE r.doc_id = ${self}.doc_id AND r.seq = 1)`);
96
99
  }
97
100
  else if (target === "blocks")
98
101
  switch (name) {
@@ -300,6 +303,8 @@ export function translateOperand(e, ctx) {
300
303
  return text(`lower(hex(${doc}.file_hash))`);
301
304
  if (k === "updated_at")
302
305
  return text(`(SELECT c.ts FROM revisions r JOIN commits c ON c.commit_id = r.commit_id WHERE r.rev_id = ${doc}.current_rev)`);
306
+ if (k === "created_at")
307
+ return text(`(SELECT c.ts FROM revisions r JOIN commits c ON c.commit_id = r.commit_id WHERE r.doc_id = ${doc}.doc_id AND r.seq = 1)`);
303
308
  if (k === "format")
304
309
  return text(`${doc}.format`);
305
310
  if (k.startsWith("$"))
@@ -334,6 +339,8 @@ export function translateOperand(e, ctx) {
334
339
  return probe("lower(hex(dd.file_hash))");
335
340
  if (k === "updated_at")
336
341
  return probe("(SELECT c.ts FROM revisions r JOIN commits c ON c.commit_id = r.commit_id WHERE r.rev_id = dd.current_rev)");
342
+ if (k === "created_at")
343
+ return probe("(SELECT c.ts FROM revisions r JOIN commits c ON c.commit_id = r.commit_id WHERE r.doc_id = dd.doc_id AND r.seq = 1)");
337
344
  if (k === "format")
338
345
  return probe("dd.format");
339
346
  if (k.startsWith("$"))
@@ -358,6 +365,26 @@ export function translateOperand(e, ctx) {
358
365
  return text(`(SELECT bb.${k} FROM blocks bb WHERE bb.block_id = ${self}.block_id)`);
359
366
  return null;
360
367
  }
368
+ // block.<x> reach-through from a link (spec/surface §1.2, 4.11): the SOURCE
369
+ // block, keyed by the row's own `src_block` — `block.id` is that FK column
370
+ // (NULL for a frontmatter link, exactly where `block` is absent in memory);
371
+ // everything else is a primary-key probe of the block row, NULL for the
372
+ // same rows (`block.path` reads the scan's joined source document inside
373
+ // the probe, so it too is NULL when there is no block). `raw`, `hash`,
374
+ // `updated_at`, `attrs` and the relations stay residual.
375
+ if (head === "block" && target === "links" && rest.length === 1) {
376
+ const k = rest[0];
377
+ const probe = (col) => text(`(SELECT ${col} FROM blocks bb WHERE bb.block_id = ${self}.src_block)`);
378
+ if (k === "id")
379
+ return text(`${self}.src_block`);
380
+ if (k === "path")
381
+ return probe(`'/' || ${doc}.path`);
382
+ if (k === "doc_id")
383
+ return probe("bb.doc_id");
384
+ if (k === "type" || k === "text")
385
+ return probe(`bb.${k}`);
386
+ return null;
387
+ }
361
388
  return null;
362
389
  }
363
390
  case "call": {
@@ -79,7 +79,7 @@ function probeFor(target, path) {
79
79
  // relation / handle (`out_links`, `data`, `frontmatter`, …), not the `format` column
80
80
  // (not indexed), not an OQX `$` name, and of the engine attributes only
81
81
  // `title` (the computed `$title` row, a scalar property the author's `title:`
82
- // never reaches — `data.title` does): `raw`, `hash`, `updated_at` and `tags`
82
+ // never reaches — `data.title` does): `raw`, `hash`, `updated_at`, `created_at` and `tags`
83
83
  // (authored ∪ hashtags) have no index and are never property probes.
84
84
  if (key === "title")
85
85
  return { kind: "property", key: "$title", source: "computed" };
@@ -2,6 +2,8 @@ import type { Node } from "./ast.js";
2
2
  export declare class FilterInvalid extends Error {
3
3
  reason: string;
4
4
  hint: string;
5
- constructor(reason: string, hint?: string);
5
+ /** (spec/surface 4.11) a literal corrected call, canonical JSON, when the surface can spell one (`data.fix`). */
6
+ fix: string | undefined;
7
+ constructor(reason: string, hint?: string, fix?: string);
6
8
  }
7
9
  export declare function parseFilter(src: string): Node;
@@ -4,10 +4,13 @@ import { lex, LexError } from "./lexer.js";
4
4
  export class FilterInvalid extends Error {
5
5
  reason;
6
6
  hint;
7
- constructor(reason, hint = "see query-language.md §3") {
7
+ /** (spec/surface 4.11) a literal corrected call, canonical JSON, when the surface can spell one (`data.fix`). */
8
+ fix;
9
+ constructor(reason, hint = "see query-language.md §3", fix) {
8
10
  super(reason);
9
11
  this.reason = reason;
10
12
  this.hint = hint;
13
+ this.fix = fix;
11
14
  }
12
15
  }
13
16
  const RELOPS = new Set(["==", "!=", "<", "<=", ">", ">="]);
@@ -1,14 +1,14 @@
1
1
  export declare const SPEC_VERSIONS: {
2
- readonly oqx: "0.24";
2
+ readonly oqx: "0.25";
3
3
  readonly format: "0.2";
4
4
  readonly reconcile: "2.3";
5
- readonly store: "15.0";
6
- readonly properties: "1.1";
5
+ readonly store: "16.0";
6
+ readonly properties: "1.2";
7
7
  readonly graph: "1.1";
8
8
  readonly search: "2.0";
9
- readonly mutate: "3.5";
9
+ readonly mutate: "3.6";
10
10
  readonly sync: "2.2";
11
- readonly surface: "4.9";
11
+ readonly surface: "4.11";
12
12
  readonly cli: "4.6";
13
13
  };
14
14
  export type SpecName = keyof typeof SPEC_VERSIONS;
@@ -13,13 +13,13 @@ export const SPEC_VERSIONS = {
13
13
  oqx: LANGUAGE_VERSION,
14
14
  format: "0.2",
15
15
  reconcile: "2.3",
16
- store: "15.0",
17
- properties: "1.1",
16
+ store: "16.0",
17
+ properties: "1.2",
18
18
  graph: "1.1",
19
19
  search: "2.0",
20
- mutate: "3.5",
20
+ mutate: "3.6",
21
21
  sync: "2.2",
22
- surface: "4.9",
22
+ surface: "4.11",
23
23
  cli: "4.6",
24
24
  };
25
25
  //# sourceMappingURL=spec-versions.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omgbase/core",
3
- "version": "0.23.0",
3
+ "version": "0.27.0",
4
4
  "description": "Open Markdown Graph Base — embedded engine",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -55,7 +55,7 @@
55
55
  },
56
56
  "dependencies": {
57
57
  "@modelcontextprotocol/sdk": "^1.30.0",
58
- "@omgbase/oqx": "^0.24.0",
58
+ "@omgbase/oqx": "^0.25.0",
59
59
  "better-sqlite3": "^13.0.3",
60
60
  "mdast-util-from-markdown": "^2.0.2",
61
61
  "mdast-util-frontmatter": "^2.0.1",