@cavelang/cli 0.15.0 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -31,15 +31,19 @@ Every command answers `--help` with its options and examples (also
31
31
  | `highlight [file…]` | | ANSI syntax colors from the tree-sitter grammar's own highlight query (see [`@cavelang/highlight`](../highlight)); `cave export` colors the same way on a terminal. |
32
32
  | `add [--db p] [file…]` | `--strict`, `--check`, `--no-prelude`, `--no-src` | Ingest. Lenient by default (problems on stderr, valid lines land); `--strict` rolls back on any problem; `--check` is the shape gate (spec §20.3) — the append rolls back if it introduces new expectation violations; `--no-prelude` starts from an empty registry instead of the standard §5.5 pairs. Claims without a `@src:` context are stamped `@src:cli` (spec §9.5); `--no-src` opts out. |
33
33
  | `import [--db p] [file…]` | `--strict`, `--no-prelude` | Restore/merge a database from CAVE text — `add` minus provenance stamping, because canonical text *is* the interchange format and replayed claims must keep their exported claim keys (spec §9.5). |
34
- | `query [--db p] <pattern…>` | `--json`, `--all`, `--no-prelude` | CAVE-Q. Extra positionals join as lines, so `WHERE` filters ride as separate arguments. Bindings print as `?x = value`; fully bound patterns print the matched raw line (or the pattern itself for transitive matches, which carry no row). `--no-prelude` aligns the read-time registry with a store written via `add --no-prelude`. |
34
+ | `query [--db p] <pattern…>` | `--json`, `--all`, `--aliases`, `--as-of <t>`, `--resolve`, `--no-prelude` | CAVE-Q. Extra positionals join as lines, so `WHERE` filters ride as separate arguments. Bindings print as `?x = value`; fully bound patterns print the matched raw line (or the pattern itself for transitive matches, which carry no row). `--aliases` widens matching through the §13.6 closure; `--as-of <t>` reconstructs belief at a past date/timestamp/tx (spec §12.3); `--resolve` matches only the winners the §26 resolution policy picks among contested facts (incompatible with `--all`). `--no-prelude` aligns the read-time registry with a store written via `add --no-prelude`. |
35
+ | `resolve [--db p]` | `--aliases`, `--policy`, `--json`, `--no-prelude` | Contested facts under the §26 resolution policy: every fact more than one belief series speaks about, candidates ranked (precedence class, reliability-weighted confidence, tx) with the winner first — what `query --resolve` would match. `--policy` prints the effective policy instead: the built-in precedence ladder merged with in-band `source/<name> HAS precedence:` / `HAS reliability:` declarations. |
35
36
  | `derive [--db p] [rules.cave…]` | `--dry-run`, `--full`, `--aliases`, `--min-conf <p>`, `--max-passes <n>`, `--list`, `--retract <r>`, `--json`, `--no-prelude` | Declare and fire rules (spec §24, see [`@cavelang/rules`](../rules)): `premises => conclusion` forward chaining over current beliefs, `BECAUSE`/`VIA` lineage, watermark-incremental and idempotent; retracts conclusions whose premises no longer hold. |
36
37
  | `act [--db p] <name> [p=v…]` | `--declare`, `--list`, `--retract <n>`, `--dry-run`, `--no-check`, `--aliases`, `--hooks <file>`, `--json`, `--no-prelude` | Execute an action template (spec §25, see [`@cavelang/act`](../act)): validate parameters, check CAVE-Q preconditions against current belief, append effects atomically with lineage inside the §20.3 shape gate; out-of-band hooks fire after commit. |
37
38
  | `check [--db p]` | `--stale <days>`, `--json`, `--no-prelude` | Knowledge health report (spec §20, see [`@cavelang/shape`](../shape)): shape violations against in-band `EXPECTS` declarations, stale current beliefs (default horizon 90 days), review candidates (conf 0.3–0.7), alias disagreements, coverage stats. Exit 1 on violations; everything else is advisory. |
38
- | `export [--db p]` | `--out <file>`, `--current`, `--no-prelude` | Canonical CAVE text — all rows in tx order, or current beliefs only. Stdout by default; `--out` writes a file and reports the claim count. |
39
- | `mcp [--db p]` | `--read-only`, `--tools <list>`, `--no-prelude`, `--src <ctx>`, `--no-src` | Serve the engine as an MCP server on stdio (see [`@cavelang/mcp`](../mcp)) — tools for add/query/search/about/neighbors/reconstruct/export/lint, with the §22 spec card as server instructions. `--read-only` / `--tools <list>` narrow the served tool surface (the agent permission boundary), composing by intersection. Appends are stamped `@src:agent/<client-name>` (spec §9.5); `--src` replaces the stamp, `--no-src` disables it. |
39
+ | `suggest-alias [--db p]` | `--min <s>`, `--limit <n>`, `--agent <template>`, `--timeout <s>`, `--write`, `--json`, `--no-prelude` | Alias discovery (spec §27, see [`@cavelang/shape`](../shape)): same-entity candidates from string/graph similarity as suggested `ALIAS` claims at review-band confidence (0.3–0.5). Prints pipeable CAVE text; `--write` appends stamped `@src:suggest/alias`; `--agent` runs an LLM judge over the candidates (the ingest/eval shell contract). Pairs with any recorded `ALIAS` history are never re-suggested. |
40
+ | `sync [--db p] <source>` | `--as <label>`, `--into <label>`, `--dry-run`, `--no-record`, `--json`, `--no-prelude` | Store merge (spec §28, see [`@cavelang/sync`](../sync)): another CAVE store file — or `;@`-annotated canonical text, `-` for stdin — merges by row identity; present rows skip, re-runs merge nothing, effective merges append a `SYNCED-INTO` record (`--no-record` for checkouts, spec §28.6). |
41
+ | `export [--db p]` | `--out <file>`, `--current`, `--tx`, `--no-prelude` | Canonical CAVE text — all rows in tx order, or current beliefs only. `--tx` precedes every claim line with its `;@` transaction annotation (spec §28.4), so the text carries row identity: the committed, reviewable store text of the §28.6 branching convention. Stdout by default; `--out` writes a file and reports the claim count. |
42
+ | `mcp [--db p]` | `--read-only`, `--tools <list>`, `--no-prelude`, `--src <ctx>`, `--no-src` | Serve the engine as an MCP server on stdio (see [`@cavelang/mcp`](../mcp)) — tools for add/query/fuse/search/about/neighbors/reconstruct/derive/export/lint, with the §22 spec card as server instructions. `--read-only` / `--tools <list>` narrow the served tool surface (the agent permission boundary), composing by intersection. Appends are stamped `@src:agent/<client-name>` (spec §9.5); `--src` replaces the stamp, `--no-src` disables it. |
40
43
  | `ingest [--db p] <globs/urls…>` | see `cave ingest --help` | LLM-driven ingestion of files and web pages (fetched and readability-extracted) through any headless agent (see [`@cavelang/ingest`](../ingest)): batching, instructions markdown, hybrid knowledge context, MCP or stdout agents, incremental digests, `--plan` NDJSON for SDK drivers. |
41
44
  | `eval <suite…>` | see `cave eval --help` | Golden-fixture extraction/query evals (ROADMAP item 9, see [`@cavelang/eval`](../eval)): N fresh-store runs against any agent, claim-key + value scoring with §9.5 actor-stamp normalization, CAVE-Q expectations, optional LLM judge, `--min` CI gate. |
42
45
  | `connect <source>` | see `cave connect --help` | Deterministic structured ingestion (spec §23, see [`@cavelang/connect`](../connect)): CSV/TSV/JSON/JSONL/SQLite/URL records through `?field` mapping templates, per-record digests, `--watch`, `--prune`, query-time `--query` overlay. |
46
+ | `reconstruct [--db p] <seed…>` | `--query <text>`, `--agent <template>`, `--steps <n>`, `--claims <n>`, `--timeout <s>`, `--trace`, `--no-prelude` | Active memory reconstruction from seed cues (spec §18, see [`@cavelang/loop`](../loop)): best-first traversal collecting related claims as canonical CAVE text; the heuristic policy by default, an LLM select/stop policy with `--agent` (ROADMAP item 10). |
43
47
  | `demo` | | The cave-loop multi-hop recovery demo (§18). |
44
48
  | `version` | | Print the cave version. |
45
49
  | `help [command]` | | The overview, or one command's options and examples. |
package/dist/src/cli.d.ts CHANGED
@@ -8,11 +8,14 @@
8
8
  * - `cave parse [file]` — lint / dump the AST (`--json`)
9
9
  * - `cave highlight [file]` — ANSI syntax colors (async, routed in `main.ts`)
10
10
  * - `cave add [--db <path>] [file…]` — ingest into a store (`--strict`, `--check`)
11
- * - `cave query [--db <path>] '<pattern>'` — CAVE-Q (`--json`, `--all`, `--aliases`, `--as-of`)
11
+ * - `cave query [--db <path>] '<pattern>'` — CAVE-Q (`--json`, `--all`, `--aliases`, `--as-of`, `--resolve`)
12
+ * - `cave resolve [--db <path>]` — contested facts under the §26 policy (`--aliases`, `--policy`, `--json`)
12
13
  * - `cave derive [--db <path>] [rules.cave…]` — fire rules (`--dry-run`, `--full`, `--list`, `--retract`)
13
14
  * - `cave act [--db <path>] <name> [param=value…]` — execute an action (spec §25; `--declare`, `--list`, `--retract`)
14
15
  * - `cave check [--db <path>]` — knowledge health report (`--stale`, `--json`)
15
- * - `cave export [--db <path>]` — canonical text out (`--current`)
16
+ * - `cave suggest-alias [--db <path>]` — same-entity candidates (spec §27; async, routed in `main.ts`)
17
+ * - `cave sync [--db <path>] <source>` — merge another store by row identity (spec §28; `--dry-run`, `--as`, `--into`)
18
+ * - `cave export [--db <path>]` — canonical text out (`--current`, `--tx`)
16
19
  * - `cave connect [--db <path>] <source>` — deterministic structured ingestion (async, routed in `main.ts`)
17
20
  * - `cave eval <suite...>` — golden-fixture extraction/query/reconstruction evals (async, routed in `main.ts`)
18
21
  * - `cave reconstruct [--db <path>] <seed...>` — §18 reconstruction from seed cues (async, routed in `main.ts`)
@@ -28,7 +31,7 @@ export type Output = {
28
31
  readonly out: string;
29
32
  readonly err: string;
30
33
  };
31
- export declare const usage = "cave \u2014 Compressed Atomic Verb Expressions\n\nUsage:\n cave parse [file...] [--json] lint CAVE text (stdin when no file)\n cave highlight [file...] print CAVE text with ANSI syntax colors\n cave add [--db <path>] [file...] ingest into a store [--strict] [--check] [--no-prelude] [--no-src]\n cave import [--db <path>] [file...] restore/merge from CAVE text (add without @src: stamping)\n cave query [--db <path>] <pattern> run a CAVE-Q pattern [--json] [--all] [--aliases] [--as-of <t>] [--no-prelude]\n cave derive [--db <path>] [rules.cave..] declare + fire rules (spec \u00A724) [--dry-run] [--full] [--list] [--retract <rule>]\n cave act [--db <path>] <name> [p=v...] execute an action (spec \u00A725) [--dry-run] [--no-check] [--hooks <file>]\n cave act --declare [file...] declare actions from a CAVE document; --list / --retract <name> manage them\n cave check [--db <path>] knowledge health report (spec \u00A720) [--stale <days>] [--json]\n cave export [--db <path>] [--out <file>] emit canonical CAVE text [--current] [--no-prelude]\n cave mcp [--db <path>] serve the engine as an MCP server on stdio [--no-prelude]\n cave ingest [--db <path>] <globs/urls..> LLM-driven ingestion of files and web pages\n cave eval <suite..> --agent '<command>' golden-fixture extraction/query/reconstruction evals (items 9, 10)\n cave connect <source> --map <file> deterministic structured ingestion (CSV/JSON/SQLite/URL, spec \u00A723)\n cave reconstruct [--db <path>] <seed..> reconstruct memory from seed cues (spec \u00A718) [--agent] [--query] [--trace]\n cave demo run the cave-loop reconstruction demo\n cave version print the cave version\n cave help [command] this text, or one command's options and examples\n\nEvery command answers --help. --db defaults to $CAVE_DB, or cave.db in\nthe current directory. The spec lives in the .claude/skills/ directory at\nthe repository root (section index in README.md).";
34
+ export declare const usage = "cave \u2014 Compressed Atomic Verb Expressions\n\nUsage:\n cave parse [file...] [--json] lint CAVE text (stdin when no file)\n cave highlight [file...] print CAVE text with ANSI syntax colors\n cave add [--db <path>] [file...] ingest into a store [--strict] [--check] [--no-prelude] [--no-src]\n cave import [--db <path>] [file...] restore/merge from CAVE text (add without @src: stamping)\n cave query [--db <path>] <pattern> run a CAVE-Q pattern [--json] [--all] [--aliases] [--as-of <t>] [--resolve] [--no-prelude]\n cave resolve [--db <path>] contested facts + winners (spec \u00A726) [--aliases] [--policy] [--json]\n cave derive [--db <path>] [rules.cave..] declare + fire rules (spec \u00A724) [--dry-run] [--full] [--list] [--retract <rule>]\n cave act [--db <path>] <name> [p=v...] execute an action (spec \u00A725) [--dry-run] [--no-check] [--hooks <file>]\n cave act --declare [file...] declare actions from a CAVE document; --list / --retract <name> manage them\n cave check [--db <path>] knowledge health report (spec \u00A720) [--stale <days>] [--json]\n cave suggest-alias [--db <path>] propose same-entity ALIAS candidates (spec \u00A727) [--min <s>] [--agent] [--write]\n cave sync [--db <path>] <source> merge another store by row identity (spec \u00A728) [--dry-run] [--as] [--into]\n cave export [--db <path>] [--out <file>] emit canonical CAVE text [--current] [--tx] [--no-prelude]\n cave mcp [--db <path>] serve the engine as an MCP server on stdio [--no-prelude]\n cave ingest [--db <path>] <globs/urls..> LLM-driven ingestion of files and web pages\n cave eval <suite..> --agent '<command>' golden-fixture extraction/query/reconstruction evals (items 9, 10)\n cave connect <source> --map <file> deterministic structured ingestion (CSV/JSON/SQLite/URL, spec \u00A723)\n cave reconstruct [--db <path>] <seed..> reconstruct memory from seed cues (spec \u00A718) [--agent] [--query] [--trace]\n cave demo run the cave-loop reconstruction demo\n cave version print the cave version\n cave help [command] this text, or one command's options and examples\n\nEvery command answers --help. --db defaults to $CAVE_DB, or cave.db in\nthe current directory. The spec lives in the .claude/skills/ directory at\nthe repository root (section index in README.md).";
32
35
  /** Per-command help, printed for \`cave <command> --help\` and \`cave help <command>\`. */
33
36
  export declare const commandHelp: Record<string, string>;
34
37
  export declare const parseCommand: (argv: readonly string[]) => Output;
@@ -53,9 +56,29 @@ export declare const addCommand: (argv: readonly string[]) => Output;
53
56
  */
54
57
  export declare const importCommand: (argv: readonly string[]) => Output;
55
58
  export declare const queryCommand: (argv: readonly string[]) => Output;
59
+ /**
60
+ * `cave resolve` — the human view of contradiction resolution (spec §26.4):
61
+ * contested facts with their candidates ranked as the policy sees them,
62
+ * or the effective policy itself under `--policy`.
63
+ */
64
+ export declare const resolveCommand: (argv: readonly string[]) => Output;
56
65
  export declare const deriveCommand: (argv: readonly string[]) => Output;
57
66
  export declare const actCommand: (argv: readonly string[]) => Output;
58
67
  export declare const checkCommand: (argv: readonly string[]) => Output;
68
+ /**
69
+ * `cave suggest-alias` — alias discovery (spec §27): same-entity
70
+ * candidates as suggested `ALIAS` claims for review. Async (the optional
71
+ * judge runs a shell agent), so `main.ts` routes it separately, like
72
+ * `reconstruct`.
73
+ */
74
+ export declare const suggestAliasCommand: (argv: readonly string[]) => Promise<Output>;
75
+ /**
76
+ * `cave sync` — store merge (spec §28): another store's rows arrive by
77
+ * identity — a store file merges through SQL, `;@`-annotated canonical
78
+ * text (`cave export --tx`, or `-` for stdin) replays under its recorded
79
+ * ids. Idempotent: re-runs merge nothing and append no record.
80
+ */
81
+ export declare const syncCommand: (argv: readonly string[]) => Output;
59
82
  export declare const exportCommand: (argv: readonly string[]) => Output;
60
83
  /**
61
84
  * `cave reconstruct` — the §18 loop over the store: heuristic policy by
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAoBH,MAAM,MAAM,MAAM,GAAG;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CACrB,CAAA;AAQD,eAAO,MAAM,KAAK,wkEAwBgC,CAAA;AAIlD,2FAA2F;AAC3F,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CA+Q9C,CAAA;AAOD,eAAO,MAAM,YAAY,GAAI,MAAM,SAAS,MAAM,EAAE,KAAG,MAyBtD,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,GAAU,MAAM,SAAS,MAAM,EAAE,KAAG,OAAO,CAAC,MAAM,CAM9E,CAAA;AAuDD,eAAO,MAAM,UAAU,SA1CkC,SAAS,MAAM,EAAE,KAAG,MA0C/B,CAAA;AAE9C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,aAAa,SAxD+B,SAAS,MAAM,EAAE,KAAG,MAwDzB,CAAA;AAEpD,eAAO,MAAM,YAAY,GAAI,MAAM,SAAS,MAAM,EAAE,KAAG,MA4CtD,CAAA;AAED,eAAO,MAAM,aAAa,GAAI,MAAM,SAAS,MAAM,EAAE,KAAG,MAsHvD,CAAA;AA8CD,eAAO,MAAM,UAAU,GAAI,MAAM,SAAS,MAAM,EAAE,KAAG,MAsFpD,CAAA;AAqCD,eAAO,MAAM,YAAY,GAAI,MAAM,SAAS,MAAM,EAAE,KAAG,MA0BtD,CAAA;AAED,eAAO,MAAM,aAAa,GAAI,MAAM,SAAS,MAAM,EAAE,KAAG,MAuBvD,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,GAAU,MAAM,SAAS,MAAM,EAAE,KAAG,OAAO,CAAC,MAAM,CAgEhF,CAAA;AAED,eAAO,MAAM,WAAW,QAAO,MACS,CAAA;AAExC,eAAO,MAAM,cAAc,QAAO,MACJ,CAAA;AAE9B,wEAAwE;AACxE,eAAO,MAAM,WAAW,GAAI,MAAM,SAAS,MAAM,EAAE,KAAG,MAcrD,CAAA;AAED,iCAAiC;AACjC,eAAO,MAAM,IAAI,GAAI,MAAM,SAAS,MAAM,EAAE,KAAG,MA2C9C,CAAA"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAyBH,MAAM,MAAM,MAAM,GAAG;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CACrB,CAAA;AAQD,eAAO,MAAM,KAAK,88EA2BgC,CAAA;AAIlD,2FAA2F;AAC3F,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAqZ9C,CAAA;AAOD,eAAO,MAAM,YAAY,GAAI,MAAM,SAAS,MAAM,EAAE,KAAG,MAyBtD,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,GAAU,MAAM,SAAS,MAAM,EAAE,KAAG,OAAO,CAAC,MAAM,CAM9E,CAAA;AAuDD,eAAO,MAAM,UAAU,SA1CkC,SAAS,MAAM,EAAE,KAAG,MA0C/B,CAAA;AAE9C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,aAAa,SAxD+B,SAAS,MAAM,EAAE,KAAG,MAwDzB,CAAA;AAEpD,eAAO,MAAM,YAAY,GAAI,MAAM,SAAS,MAAM,EAAE,KAAG,MA8CtD,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,cAAc,GAAI,MAAM,SAAS,MAAM,EAAE,KAAG,MA+CxD,CAAA;AAED,eAAO,MAAM,aAAa,GAAI,MAAM,SAAS,MAAM,EAAE,KAAG,MAsHvD,CAAA;AA8CD,eAAO,MAAM,UAAU,GAAI,MAAM,SAAS,MAAM,EAAE,KAAG,MAsFpD,CAAA;AAqCD,eAAO,MAAM,YAAY,GAAI,MAAM,SAAS,MAAM,EAAE,KAAG,MA0BtD,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,GAAU,MAAM,SAAS,MAAM,EAAE,KAAG,OAAO,CAAC,MAAM,CA6DjF,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,WAAW,GAAI,MAAM,SAAS,MAAM,EAAE,KAAG,MAmDrD,CAAA;AAED,eAAO,MAAM,aAAa,GAAI,MAAM,SAAS,MAAM,EAAE,KAAG,MAwBvD,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,GAAU,MAAM,SAAS,MAAM,EAAE,KAAG,OAAO,CAAC,MAAM,CAgEhF,CAAA;AAED,eAAO,MAAM,WAAW,QAAO,MACS,CAAA;AAExC,eAAO,MAAM,cAAc,QAAO,MACJ,CAAA;AAE9B,wEAAwE;AACxE,eAAO,MAAM,WAAW,GAAI,MAAM,SAAS,MAAM,EAAE,KAAG,MAcrD,CAAA;AAED,iCAAiC;AACjC,eAAO,MAAM,IAAI,GAAI,MAAM,SAAS,MAAM,EAAE,KAAG,MA+C9C,CAAA"}
package/dist/src/cli.js CHANGED
@@ -8,11 +8,14 @@
8
8
  * - `cave parse [file]` — lint / dump the AST (`--json`)
9
9
  * - `cave highlight [file]` — ANSI syntax colors (async, routed in `main.ts`)
10
10
  * - `cave add [--db <path>] [file…]` — ingest into a store (`--strict`, `--check`)
11
- * - `cave query [--db <path>] '<pattern>'` — CAVE-Q (`--json`, `--all`, `--aliases`, `--as-of`)
11
+ * - `cave query [--db <path>] '<pattern>'` — CAVE-Q (`--json`, `--all`, `--aliases`, `--as-of`, `--resolve`)
12
+ * - `cave resolve [--db <path>]` — contested facts under the §26 policy (`--aliases`, `--policy`, `--json`)
12
13
  * - `cave derive [--db <path>] [rules.cave…]` — fire rules (`--dry-run`, `--full`, `--list`, `--retract`)
13
14
  * - `cave act [--db <path>] <name> [param=value…]` — execute an action (spec §25; `--declare`, `--list`, `--retract`)
14
15
  * - `cave check [--db <path>]` — knowledge health report (`--stale`, `--json`)
15
- * - `cave export [--db <path>]` — canonical text out (`--current`)
16
+ * - `cave suggest-alias [--db <path>]` — same-entity candidates (spec §27; async, routed in `main.ts`)
17
+ * - `cave sync [--db <path>] <source>` — merge another store by row identity (spec §28; `--dry-run`, `--as`, `--into`)
18
+ * - `cave export [--db <path>]` — canonical text out (`--current`, `--tx`)
16
19
  * - `cave connect [--db <path>] <source>` — deterministic structured ingestion (async, routed in `main.ts`)
17
20
  * - `cave eval <suite...>` — golden-fixture extraction/query/reconstruction evals (async, routed in `main.ts`)
18
21
  * - `cave reconstruct [--db <path>] <seed...>` — §18 reconstruction from seed cues (async, routed in `main.ts`)
@@ -30,11 +33,12 @@ import { parseDocument } from '@cavelang/parser';
30
33
  import { Registry, standardRegistry } from '@cavelang/canonical';
31
34
  import { defaultDbPath, open } from '@cavelang/store';
32
35
  import { query as caveQuery } from '@cavelang/query';
33
- import { check as caveCheck, defaultStaleDays, gatedIngest } from '@cavelang/shape';
36
+ import { check as caveCheck, defaultMinScore, defaultStaleDays, gatedIngest, judgePrompt, parseJudgeReply, suggestAliases, writeSuggestions } from '@cavelang/shape';
34
37
  import { declareRules, defaultMaxPasses, defaultMinConf, derive, listRules, retractRule } from '@cavelang/rules';
35
38
  import { act, declareActions, listActions, retractAction } from '@cavelang/act';
36
39
  import { Demo, heuristicPolicy, llmPolicy, reconstruct, reconstructAsync, shellComplete, sqliteStore } from '@cavelang/loop';
37
- import { emitClaim } from '@cavelang/canonical';
40
+ import { labelOf, sanitizeLabel, syncFile, syncText } from '@cavelang/sync';
41
+ import { emitClaim, txOfLine } from '@cavelang/canonical';
38
42
  const ok = (out) => ({ code: 0, out, err: '' });
39
43
  const fail = (err, code = 1) => ({ code, out: '', err });
40
44
  export const usage = `cave — Compressed Atomic Verb Expressions
@@ -44,12 +48,15 @@ Usage:
44
48
  cave highlight [file...] print CAVE text with ANSI syntax colors
45
49
  cave add [--db <path>] [file...] ingest into a store [--strict] [--check] [--no-prelude] [--no-src]
46
50
  cave import [--db <path>] [file...] restore/merge from CAVE text (add without @src: stamping)
47
- cave query [--db <path>] <pattern> run a CAVE-Q pattern [--json] [--all] [--aliases] [--as-of <t>] [--no-prelude]
51
+ cave query [--db <path>] <pattern> run a CAVE-Q pattern [--json] [--all] [--aliases] [--as-of <t>] [--resolve] [--no-prelude]
52
+ cave resolve [--db <path>] contested facts + winners (spec §26) [--aliases] [--policy] [--json]
48
53
  cave derive [--db <path>] [rules.cave..] declare + fire rules (spec §24) [--dry-run] [--full] [--list] [--retract <rule>]
49
54
  cave act [--db <path>] <name> [p=v...] execute an action (spec §25) [--dry-run] [--no-check] [--hooks <file>]
50
55
  cave act --declare [file...] declare actions from a CAVE document; --list / --retract <name> manage them
51
56
  cave check [--db <path>] knowledge health report (spec §20) [--stale <days>] [--json]
52
- cave export [--db <path>] [--out <file>] emit canonical CAVE text [--current] [--no-prelude]
57
+ cave suggest-alias [--db <path>] propose same-entity ALIAS candidates (spec §27) [--min <s>] [--agent] [--write]
58
+ cave sync [--db <path>] <source> merge another store by row identity (spec §28) [--dry-run] [--as] [--into]
59
+ cave export [--db <path>] [--out <file>] emit canonical CAVE text [--current] [--tx] [--no-prelude]
53
60
  cave mcp [--db <path>] serve the engine as an MCP server on stdio [--no-prelude]
54
61
  cave ingest [--db <path>] <globs/urls..> LLM-driven ingestion of files and web pages
55
62
  cave eval <suite..> --agent '<command>' golden-fixture extraction/query/reconstruction evals (items 9, 10)
@@ -131,7 +138,10 @@ Canonical CAVE text is the interchange format (spec §2.2): importing a
131
138
  file written by \`cave export\` replays its claims append-only, preserving
132
139
  the belief series, qualifier edges and in-band declarations. Unlike
133
140
  \`cave add\`, import never stamps actor provenance — replayed claims must
134
- keep the claim keys they were exported with (spec §9.5).
141
+ keep the claim keys they were exported with (spec §9.5). Import always
142
+ mints fresh transaction ids — ;@ annotations in a \`cave export --tx\`
143
+ file read as ordinary comments; to merge under the recorded row
144
+ identity, use \`cave sync\` (spec §28.4).
135
145
 
136
146
  Examples:
137
147
  cave export --db old.db --out backup.cave
@@ -139,7 +149,7 @@ Examples:
139
149
  query: `cave query — run a CAVE-Q pattern against a store
140
150
 
141
151
  Usage:
142
- cave query [--db <path>] <pattern> [WHERE <filter>] [--json] [--all] [--aliases] [--as-of <t>] [--no-prelude]
152
+ cave query [--db <path>] <pattern> [WHERE <filter>] [--json] [--all] [--aliases] [--as-of <t>] [--resolve] [--no-prelude]
143
153
 
144
154
  Options:
145
155
  ${dbHelp}
@@ -149,6 +159,11 @@ Options:
149
159
  --as-of <t> resolve beliefs as of a past moment (spec §12.3): a date
150
160
  (whole day included), a timestamp (whole second), or a
151
161
  transaction id — rows recorded later are invisible
162
+ --resolve match resolved winners only (spec §26): contested facts —
163
+ same fact from several sources, or opposite polarity —
164
+ collapse to the row the resolution policy picks
165
+ (precedence class, reliability-weighted confidence, tx);
166
+ incompatible with --all
152
167
  --no-prelude open the store without the standard verb registry
153
168
 
154
169
  Patterns are claim triples with ?variables and optional metadata filters
@@ -162,7 +177,38 @@ Examples:
162
177
  cave query --db k.db 'terrier EXTENDS+ animal'
163
178
  cave query --db k.db '?x USES postgres' --aliases
164
179
  cave query --db k.db 'server IS compromised' --as-of 2026-01-15
180
+ cave query --db k.db 'service HAS owner: ?who' --resolve
165
181
  cave query --db k.db '?x ?verb ?y @production' --json`,
182
+ resolve: `cave resolve — contested facts and their winners (spec §26)
183
+
184
+ Usage:
185
+ cave resolve [--db <path>] [--aliases] [--policy] [--json] [--no-prelude]
186
+
187
+ Options:
188
+ ${dbHelp}
189
+ --aliases widen resolution groups through current ALIAS claims
190
+ (spec §13.6) — aliased names contest one fact
191
+ --policy print the effective resolution policy instead: the
192
+ built-in precedence ladder merged with in-band
193
+ source/<name> HAS precedence: / HAS reliability: claims
194
+ --json emit the report as JSON
195
+ --no-prelude open the store without the standard verb registry
196
+
197
+ Lists every fact more than one belief series currently speaks about —
198
+ same fact from different sources (§9.5 actor stamps, content sources)
199
+ or opposite polarity — with the candidates ranked as the resolution
200
+ policy sees them: precedence class first, reliability-weighted
201
+ confidence second, latest transaction last. The winner is what
202
+ \`cave query --resolve\` matches; the rest are invisible there. Declare
203
+ policy overrides in-band, e.g.:
204
+
205
+ source/scanner-a HAS reliability: 60%
206
+ source/ingest HAS precedence: 1
207
+
208
+ Examples:
209
+ cave resolve --db k.db
210
+ cave resolve --db k.db --aliases
211
+ cave resolve --db k.db --policy`,
166
212
  derive: `cave derive — declare and fire rules (spec §24)
167
213
 
168
214
  Usage:
@@ -269,21 +315,113 @@ Examples:
269
315
  cave check --db k.db
270
316
  cave check --db k.db --stale 30
271
317
  cave check --db k.db --json | jq '.violations'`,
318
+ 'suggest-alias': `cave suggest-alias — propose same-entity ALIAS candidates for review (spec §27)
319
+
320
+ Usage:
321
+ cave suggest-alias [--db <path>] [options]
322
+
323
+ Options:
324
+ ${dbHelp}
325
+ --min <s> minimum evidence score, 0..1 or N% (default 60%)
326
+ --limit <n> at most n suggestions, strongest first
327
+ --agent <template> LLM judge filtering the candidates — the cave
328
+ ingest/eval shell contract: the prompt (each pair
329
+ with both sides' current claims) is piped to stdin
330
+ and {prompt-file} is substituted; stdout replies
331
+ with a JSON array of confirmed suggestion numbers
332
+ --timeout <seconds> judge timeout (default 120)
333
+ --write append the suggestions, stamped @src:suggest/alias,
334
+ instead of only printing them
335
+ --json print suggestions with scores and signals as JSON
336
+ --no-prelude open the store without the standard verb registry
337
+
338
+ Candidates come from string similarity (case/separator drift, segment
339
+ containment, prefixes, typos) and shared rare attribute values; shared
340
+ relations strengthen a candidate but never create one. Suggested claims
341
+ are questions, not merges: confidence 30–50% puts them in cave check's
342
+ review band, and a pair with any recorded ALIAS history — merged,
343
+ rejected or unmerged — is never suggested again.
344
+
345
+ Output is CAVE text: review it, edit it, pipe it into cave add — or
346
+ --write it and review afterwards. A written suggestion is a positive
347
+ claim, so the opt-in §13.6 closure links it until reviewed:
348
+
349
+ confirm echo 'dupe ALIAS canonical' | cave add --db k.db
350
+ reject echo 'dupe ALIAS canonical @src:suggest/alias @ 0%' | cave add --db k.db
351
+
352
+ (rejection retracts the suggestion's own series — contexts are part of
353
+ claim identity, §9.2, so a plain @ 0% append would start a new series
354
+ and leave the suggested link standing).
355
+
356
+ Examples:
357
+ cave suggest-alias --db k.db
358
+ cave suggest-alias --db k.db --min 80% --limit 10
359
+ cave suggest-alias --db k.db | cave add --db k.db
360
+ cave suggest-alias --db k.db --agent 'claude -p' --write`,
361
+ sync: `cave sync — merge another store into this one by row identity (spec §28)
362
+
363
+ Usage:
364
+ cave sync [--db <path>] <source> [--as <label>] [--into <label>]
365
+ [--dry-run] [--no-record] [--json] [--no-prelude]
366
+
367
+ Options:
368
+ ${dbHelp}
369
+ --as <label> origin label in the merge record (default: the source
370
+ file's basename stem; stdin defaults to "stdin")
371
+ --into <label> target label in the merge record (default: the database
372
+ file's basename stem)
373
+ --dry-run compute the full report inside a rolled-back transaction
374
+ --no-record do not append the store/<from> SYNCED-INTO store/<into>
375
+ merge record
376
+ --json emit the report as JSON
377
+ --no-prelude open the store without the standard verb registry
378
+
379
+ The source is a CAVE store file (recognized by the SQLite header),
380
+ canonical text with ;@ transaction annotations (cave export --tx), or -
381
+ for annotated text on stdin. Rows merge by identity: a row's UUIDv7 is
382
+ its id everywhere, so present rows skip, re-runs merge nothing, and two
383
+ stores syncing each other converge. Contradictions coexist (spec §9.4)
384
+ and resolve at read time (cave resolve, --resolve); everything appended
385
+ after a merge outsorts everything merged, whatever the origin machine's
386
+ clock read (spec §28.2). An effective merge appends one record claim,
387
+ stamped @src:sync — the sync log is its belief series.
388
+
389
+ Branching (spec §28.6): commit the full annotated export — the text is
390
+ the store — and rebuild working stores from it. A checkout is plumbing
391
+ (--no-record); landing reviewed text into a live store is a real merge
392
+ event (let it record). Never hand-merge exports: sync both sides into
393
+ a fresh store and re-export — the union — which git can run for you as
394
+ a merge driver on *.cave files.
395
+
396
+ Examples:
397
+ cave sync --db main.db laptop.db
398
+ cave sync --db main.db laptop.db --dry-run --json
399
+ cave export --db laptop.db --tx | cave sync --db main.db -
400
+ cave sync --db a.db b.db && cave sync --db b.db a.db # converge both
401
+ cave sync --db work.db knowledge.cave --no-record # checkout (§28.6)
402
+ cave sync --db main.db knowledge.cave --as reorg-auth # land the branch`,
272
403
  export: `cave export — emit canonical CAVE text from a store
273
404
 
274
405
  Usage:
275
- cave export [--db <path>] [--out <file>] [--current] [--no-prelude]
406
+ cave export [--db <path>] [--out <file>] [--current] [--tx] [--no-prelude]
276
407
 
277
408
  Options:
278
409
  ${dbHelp}
279
410
  --out <file> write to a file instead of stdout
280
411
  --current current beliefs only (skip superseded rows)
412
+ --tx precede every claim line with its ;@ transaction
413
+ annotation (spec §28.4) — the text carries row identity,
414
+ so cave sync replays it idempotently; other readers see
415
+ ordinary comments
281
416
  --no-prelude open the store without the standard verb registry
282
417
 
283
418
  Examples:
284
419
  cave export --db k.db
285
420
  cave export --db k.db --out backup.cave
286
- cave export --db k.db --current --out snapshot.cave`,
421
+ cave export --db k.db --current --out snapshot.cave
422
+ cave export --db k.db --tx | cave sync --db other.db -
423
+ cave export --db work.db --tx --out knowledge.cave # the committed,
424
+ # reviewable store text (spec §28.6)`,
287
425
  reconstruct: `cave reconstruct — active memory reconstruction from seed cues (spec §18)
288
426
 
289
427
  Usage:
@@ -441,6 +579,7 @@ export const queryCommand = (argv) => {
441
579
  all: { type: 'boolean' },
442
580
  aliases: { type: 'boolean' },
443
581
  'as-of': { type: 'string' },
582
+ resolve: { type: 'boolean' },
444
583
  'no-prelude': { type: 'boolean' }
445
584
  },
446
585
  allowPositionals: true
@@ -454,6 +593,7 @@ export const queryCommand = (argv) => {
454
593
  const matches = caveQuery(store, pattern, {
455
594
  all: values.all === true,
456
595
  aliases: values.aliases === true,
596
+ resolve: values.resolve === true,
457
597
  ...values['as-of'] === undefined ? {} : { asOf: values['as-of'] }
458
598
  });
459
599
  if (values.json === true) {
@@ -479,6 +619,59 @@ export const queryCommand = (argv) => {
479
619
  store.close();
480
620
  }
481
621
  };
622
+ /**
623
+ * `cave resolve` — the human view of contradiction resolution (spec §26.4):
624
+ * contested facts with their candidates ranked as the policy sees them,
625
+ * or the effective policy itself under `--policy`.
626
+ */
627
+ export const resolveCommand = (argv) => {
628
+ const { values } = parseArgs({
629
+ args: [...argv],
630
+ options: {
631
+ db: { type: 'string' },
632
+ aliases: { type: 'boolean' },
633
+ policy: { type: 'boolean' },
634
+ json: { type: 'boolean' },
635
+ 'no-prelude': { type: 'boolean' }
636
+ },
637
+ allowPositionals: false
638
+ });
639
+ const percent = (value) => `${Math.round(value * 1000) / 10}%`;
640
+ const store = open(values.db ?? defaultDbPath(), values['no-prelude'] === true ? { registry: Registry.empty } : {});
641
+ try {
642
+ if (values.policy === true) {
643
+ const policy = store.resolutionPolicy();
644
+ if (values.json === true) {
645
+ return ok(`${JSON.stringify(policy, undefined, 2)}\n`);
646
+ }
647
+ const width = Math.max(...policy.map(entry => entry.prefix.length + 7));
648
+ const lines = policy.map(entry => {
649
+ const subject = entry.prefix === '' ? 'source' : `source/${entry.prefix}`;
650
+ const dimensions = [
651
+ ...entry.precedence === undefined ? [] : [`precedence ${entry.precedence}`],
652
+ ...entry.reliability === undefined ? [] : [`reliability ${percent(entry.reliability)}`]
653
+ ];
654
+ return `${subject.padEnd(width)} ${dimensions.join(', ')}`;
655
+ });
656
+ return ok(`${lines.join('\n')}\n`);
657
+ }
658
+ const contested = store.contested({ aliases: values.aliases === true });
659
+ if (values.json === true) {
660
+ return ok(`${JSON.stringify(contested, undefined, 2)}\n`);
661
+ }
662
+ if (contested.length === 0) {
663
+ return ok('no contested facts\n');
664
+ }
665
+ const lines = contested.flatMap(group => group.rows.map((row, at) => `${at === 0 ? '' : ' over '}${row.raw_line} ; class ${row.res_class}, effective ${percent(row.res_conf)}`));
666
+ return ok(`${lines.join('\n')}\n`);
667
+ }
668
+ catch (error) {
669
+ return fail(`${error instanceof Error ? error.message : String(error)}\n`);
670
+ }
671
+ finally {
672
+ store.close();
673
+ }
674
+ };
482
675
  export const deriveCommand = (argv) => {
483
676
  const { values, positionals } = parseArgs({
484
677
  args: [...argv],
@@ -791,12 +984,141 @@ export const checkCommand = (argv) => {
791
984
  store.close();
792
985
  }
793
986
  };
987
+ /**
988
+ * `cave suggest-alias` — alias discovery (spec §27): same-entity
989
+ * candidates as suggested `ALIAS` claims for review. Async (the optional
990
+ * judge runs a shell agent), so `main.ts` routes it separately, like
991
+ * `reconstruct`.
992
+ */
993
+ export const suggestAliasCommand = async (argv) => {
994
+ try {
995
+ const { values } = parseArgs({
996
+ args: [...argv],
997
+ options: {
998
+ db: { type: 'string' },
999
+ min: { type: 'string' },
1000
+ limit: { type: 'string' },
1001
+ agent: { type: 'string' },
1002
+ timeout: { type: 'string' },
1003
+ write: { type: 'boolean' },
1004
+ json: { type: 'boolean' },
1005
+ 'no-prelude': { type: 'boolean' },
1006
+ help: { type: 'boolean', short: 'h' }
1007
+ },
1008
+ allowPositionals: false
1009
+ });
1010
+ if (values.help === true) {
1011
+ return ok(`${commandHelp['suggest-alias']}\n`);
1012
+ }
1013
+ const minScore = values.min === undefined ?
1014
+ defaultMinScore :
1015
+ values.min.endsWith('%') ? Number(values.min.slice(0, -1)) / 100 : Number(values.min);
1016
+ if (!Number.isFinite(minScore) || minScore < 0 || minScore > 1) {
1017
+ return fail(`cave suggest-alias: --min expects a score in 0..1 or N%, got ${JSON.stringify(values.min)}\n`);
1018
+ }
1019
+ const limit = values.limit === undefined ? undefined : Number(values.limit);
1020
+ if (limit !== undefined && (!Number.isInteger(limit) || limit < 1)) {
1021
+ return fail(`cave suggest-alias: --limit expects a positive integer, got ${JSON.stringify(values.limit)}\n`);
1022
+ }
1023
+ const timeoutSeconds = values.timeout === undefined ? undefined : Number(values.timeout);
1024
+ if (timeoutSeconds !== undefined && (!Number.isFinite(timeoutSeconds) || timeoutSeconds <= 0)) {
1025
+ return fail(`cave suggest-alias: --timeout must be a positive number of seconds, got '${values.timeout}'\n`);
1026
+ }
1027
+ const store = open(values.db ?? defaultDbPath(), values['no-prelude'] === true ? { registry: Registry.empty } : {});
1028
+ try {
1029
+ let suggestions = suggestAliases(store, { minScore, ...limit === undefined ? {} : { limit } });
1030
+ if (values.agent !== undefined && suggestions.length > 0) {
1031
+ const reply = await shellComplete(values.agent, timeoutSeconds === undefined ? {} : { timeoutSeconds })(judgePrompt(store, suggestions));
1032
+ suggestions = parseJudgeReply(reply, suggestions.length).map(index => suggestions[index]);
1033
+ }
1034
+ if (values.json === true) {
1035
+ return ok(`${JSON.stringify(suggestions, undefined, 2)}\n`);
1036
+ }
1037
+ if (suggestions.length === 0) {
1038
+ return ok('no alias suggestions\n');
1039
+ }
1040
+ const lines = suggestions.map(suggestion => suggestion.line);
1041
+ if (values.write === true) {
1042
+ const { appended } = writeSuggestions(store, suggestions);
1043
+ return ok(`${lines.join('\n')}\nappended ${appended} suggested alias claim(s)\n`);
1044
+ }
1045
+ return ok(`${lines.join('\n')}\n`);
1046
+ }
1047
+ finally {
1048
+ store.close();
1049
+ }
1050
+ }
1051
+ catch (error) {
1052
+ return fail(`${error instanceof Error ? error.message : String(error)}\n`);
1053
+ }
1054
+ };
1055
+ /**
1056
+ * `cave sync` — store merge (spec §28): another store's rows arrive by
1057
+ * identity — a store file merges through SQL, `;@`-annotated canonical
1058
+ * text (`cave export --tx`, or `-` for stdin) replays under its recorded
1059
+ * ids. Idempotent: re-runs merge nothing and append no record.
1060
+ */
1061
+ export const syncCommand = (argv) => {
1062
+ const { values, positionals } = parseArgs({
1063
+ args: [...argv],
1064
+ options: {
1065
+ db: { type: 'string' },
1066
+ as: { type: 'string' },
1067
+ into: { type: 'string' },
1068
+ 'dry-run': { type: 'boolean' },
1069
+ 'no-record': { type: 'boolean' },
1070
+ json: { type: 'boolean' },
1071
+ 'no-prelude': { type: 'boolean' }
1072
+ },
1073
+ allowPositionals: true
1074
+ });
1075
+ const [source, ...extra] = positionals;
1076
+ if (source === undefined || extra.length > 0) {
1077
+ return fail('cave sync: exactly one source is required — a CAVE store file, ;@-annotated text, or - for stdin (spec §28.5)\n');
1078
+ }
1079
+ const dbPath = values.db ?? defaultDbPath();
1080
+ const store = open(dbPath, values['no-prelude'] === true ? { registry: Registry.empty } : {});
1081
+ try {
1082
+ const options = {
1083
+ into: values.into === undefined ? labelOf(dbPath) : sanitizeLabel(values.into),
1084
+ record: values['no-record'] !== true,
1085
+ dryRun: values['dry-run'] === true,
1086
+ ...values.as === undefined ? {} : { from: sanitizeLabel(values.as) }
1087
+ };
1088
+ const report = source === '-' ?
1089
+ syncText(store, readFileSync(0, 'utf8'), { from: 'stdin', ...options }) :
1090
+ syncFile(store, source, options);
1091
+ if (values.json === true) {
1092
+ return { code: report.problems.length > 0 ? 1 : 0, out: `${JSON.stringify(report, undefined, 2)}\n`, err: '' };
1093
+ }
1094
+ if (report.problems.length > 0) {
1095
+ const detail = report.problems.map(problem => ` line ${problem.line}: ${problem.message}`).join('\n');
1096
+ return fail(`cave sync: ${source}: ${report.problems.length} problem(s), nothing merged\n${detail}\n`);
1097
+ }
1098
+ const lines = [
1099
+ `merged ${report.merged} claim(s), ${report.edges} edge(s)` +
1100
+ (report.skipped > 0 ? `, ${report.skipped} already present` : '') +
1101
+ (report.dryRun ? ' (dry run)' : '')
1102
+ ];
1103
+ if (report.record !== undefined) {
1104
+ lines.push(`record: ${report.record}`);
1105
+ }
1106
+ return ok(`${lines.join('\n')}\n`);
1107
+ }
1108
+ catch (error) {
1109
+ return fail(`${error instanceof Error ? error.message : String(error)}\n`);
1110
+ }
1111
+ finally {
1112
+ store.close();
1113
+ }
1114
+ };
794
1115
  export const exportCommand = (argv) => {
795
1116
  const { values } = parseArgs({
796
1117
  args: [...argv],
797
1118
  options: {
798
1119
  db: { type: 'string' },
799
1120
  current: { type: 'boolean' },
1121
+ tx: { type: 'boolean' },
800
1122
  out: { type: 'string' },
801
1123
  'no-prelude': { type: 'boolean' }
802
1124
  },
@@ -804,12 +1126,12 @@ export const exportCommand = (argv) => {
804
1126
  });
805
1127
  const store = open(values.db ?? defaultDbPath(), values['no-prelude'] === true ? { registry: Registry.empty } : {});
806
1128
  try {
807
- const text = store.exportText({ current: values.current === true });
1129
+ const text = store.exportText({ current: values.current === true, tx: values.tx === true });
808
1130
  if (values.out === undefined) {
809
1131
  return ok(text);
810
1132
  }
811
1133
  writeFileSync(values.out, text);
812
- const claims = text === '' ? 0 : text.trimEnd().split('\n').length;
1134
+ const claims = text === '' ? 0 : text.trimEnd().split('\n').filter(line => txOfLine(line) === undefined).length;
813
1135
  return ok(`exported ${claims} claim(s) to ${values.out}\n`);
814
1136
  }
815
1137
  finally {
@@ -918,12 +1240,16 @@ export const cave = (argv) => {
918
1240
  return importCommand(rest);
919
1241
  case 'query':
920
1242
  return queryCommand(rest);
1243
+ case 'resolve':
1244
+ return resolveCommand(rest);
921
1245
  case 'derive':
922
1246
  return deriveCommand(rest);
923
1247
  case 'act':
924
1248
  return actCommand(rest);
925
1249
  case 'check':
926
1250
  return checkCommand(rest);
1251
+ case 'sync':
1252
+ return syncCommand(rest);
927
1253
  case 'export':
928
1254
  return exportCommand(rest);
929
1255
  case 'demo':