@cavelang/cli 0.27.14 → 0.29.1
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/Authors.md +5 -0
- package/License.md +6 -0
- package/README.md +122 -24
- package/dist/internal/act/action.d.ts +69 -0
- package/dist/internal/act/action.d.ts.map +1 -0
- package/dist/internal/act/action.js +201 -0
- package/dist/internal/act/action.js.map +1 -0
- package/dist/internal/act/declare.d.ts +102 -0
- package/dist/internal/act/declare.d.ts.map +1 -0
- package/dist/internal/act/declare.js +270 -0
- package/dist/internal/act/declare.js.map +1 -0
- package/dist/internal/act/engine.d.ts +103 -0
- package/dist/internal/act/engine.d.ts.map +1 -0
- package/dist/internal/act/engine.js +298 -0
- package/dist/internal/act/engine.js.map +1 -0
- package/dist/internal/act/index.d.ts +27 -0
- package/dist/internal/act/index.d.ts.map +1 -0
- package/dist/internal/act/index.js +25 -0
- package/dist/internal/act/index.js.map +1 -0
- package/dist/internal/automate/automation.d.ts +78 -0
- package/dist/internal/automate/automation.d.ts.map +1 -0
- package/dist/internal/automate/automation.js +135 -0
- package/dist/internal/automate/automation.js.map +1 -0
- package/dist/internal/automate/declare.d.ts +84 -0
- package/dist/internal/automate/declare.d.ts.map +1 -0
- package/dist/internal/automate/declare.js +233 -0
- package/dist/internal/automate/declare.js.map +1 -0
- package/dist/internal/automate/engine.d.ts +125 -0
- package/dist/internal/automate/engine.d.ts.map +1 -0
- package/dist/internal/automate/engine.js +388 -0
- package/dist/internal/automate/engine.js.map +1 -0
- package/dist/internal/automate/index.d.ts +28 -0
- package/dist/internal/automate/index.d.ts.map +1 -0
- package/dist/internal/automate/index.js +26 -0
- package/dist/internal/automate/index.js.map +1 -0
- package/dist/internal/automate/main.d.ts +26 -0
- package/dist/internal/automate/main.d.ts.map +1 -0
- package/dist/internal/automate/main.js +298 -0
- package/dist/internal/automate/main.js.map +1 -0
- package/dist/internal/connect/index.d.ts +26 -0
- package/dist/internal/connect/index.d.ts.map +1 -0
- package/dist/internal/connect/index.js +24 -0
- package/dist/internal/connect/index.js.map +1 -0
- package/dist/internal/connect/main.d.ts +23 -0
- package/dist/internal/connect/main.d.ts.map +1 -0
- package/dist/internal/connect/main.js +330 -0
- package/dist/internal/connect/main.js.map +1 -0
- package/dist/internal/connect/run.d.ts +85 -0
- package/dist/internal/connect/run.d.ts.map +1 -0
- package/dist/internal/connect/run.js +242 -0
- package/dist/internal/connect/run.js.map +1 -0
- package/dist/internal/connect/source.d.ts +44 -0
- package/dist/internal/connect/source.d.ts.map +1 -0
- package/dist/internal/connect/source.js +215 -0
- package/dist/internal/connect/source.js.map +1 -0
- package/dist/internal/connect/template.d.ts +69 -0
- package/dist/internal/connect/template.d.ts.map +1 -0
- package/dist/internal/connect/template.js +221 -0
- package/dist/internal/connect/template.js.map +1 -0
- package/dist/internal/eval/index.d.ts +28 -0
- package/dist/internal/eval/index.d.ts.map +1 -0
- package/dist/internal/eval/index.js +27 -0
- package/dist/internal/eval/index.js.map +1 -0
- package/dist/internal/eval/judge.d.ts +30 -0
- package/dist/internal/eval/judge.d.ts.map +1 -0
- package/dist/internal/eval/judge.js +101 -0
- package/dist/internal/eval/judge.js.map +1 -0
- package/dist/internal/eval/loop.d.ts +64 -0
- package/dist/internal/eval/loop.d.ts.map +1 -0
- package/dist/internal/eval/loop.js +123 -0
- package/dist/internal/eval/loop.js.map +1 -0
- package/dist/internal/eval/main.d.ts +17 -0
- package/dist/internal/eval/main.d.ts.map +1 -0
- package/dist/internal/eval/main.js +236 -0
- package/dist/internal/eval/main.js.map +1 -0
- package/dist/internal/eval/queries.d.ts +74 -0
- package/dist/internal/eval/queries.d.ts.map +1 -0
- package/dist/internal/eval/queries.js +161 -0
- package/dist/internal/eval/queries.js.map +1 -0
- package/dist/internal/eval/run.d.ts +143 -0
- package/dist/internal/eval/run.d.ts.map +1 -0
- package/dist/internal/eval/run.js +376 -0
- package/dist/internal/eval/run.js.map +1 -0
- package/dist/internal/eval/score.d.ts +81 -0
- package/dist/internal/eval/score.d.ts.map +1 -0
- package/dist/internal/eval/score.js +126 -0
- package/dist/internal/eval/score.js.map +1 -0
- package/dist/internal/eval/suite.d.ts +66 -0
- package/dist/internal/eval/suite.d.ts.map +1 -0
- package/dist/internal/eval/suite.js +130 -0
- package/dist/internal/eval/suite.js.map +1 -0
- package/dist/internal/ingest/context.d.ts +20 -0
- package/dist/internal/ingest/context.d.ts.map +1 -0
- package/dist/internal/ingest/context.js +59 -0
- package/dist/internal/ingest/context.js.map +1 -0
- package/dist/internal/ingest/files.d.ts +46 -0
- package/dist/internal/ingest/files.d.ts.map +1 -0
- package/dist/internal/ingest/files.js +115 -0
- package/dist/internal/ingest/files.js.map +1 -0
- package/dist/internal/ingest/index.d.ts +31 -0
- package/dist/internal/ingest/index.d.ts.map +1 -0
- package/dist/internal/ingest/index.js +29 -0
- package/dist/internal/ingest/index.js.map +1 -0
- package/dist/internal/ingest/main.d.ts +12 -0
- package/dist/internal/ingest/main.d.ts.map +1 -0
- package/dist/internal/ingest/main.js +180 -0
- package/dist/internal/ingest/main.js.map +1 -0
- package/dist/internal/ingest/prompt.d.ts +32 -0
- package/dist/internal/ingest/prompt.d.ts.map +1 -0
- package/dist/internal/ingest/prompt.js +75 -0
- package/dist/internal/ingest/prompt.js.map +1 -0
- package/dist/internal/ingest/run.d.ts +142 -0
- package/dist/internal/ingest/run.d.ts.map +1 -0
- package/dist/internal/ingest/run.js +350 -0
- package/dist/internal/ingest/run.js.map +1 -0
- package/dist/internal/ingest/web.d.ts +48 -0
- package/dist/internal/ingest/web.d.ts.map +1 -0
- package/dist/internal/ingest/web.js +140 -0
- package/dist/internal/ingest/web.js.map +1 -0
- package/dist/internal/loop/demo.d.ts +22 -0
- package/dist/internal/loop/demo.d.ts.map +1 -0
- package/dist/internal/loop/demo.js +67 -0
- package/dist/internal/loop/demo.js.map +1 -0
- package/dist/internal/loop/index.d.ts +20 -0
- package/dist/internal/loop/index.d.ts.map +1 -0
- package/dist/internal/loop/index.js +17 -0
- package/dist/internal/loop/index.js.map +1 -0
- package/dist/internal/loop/llm.d.ts +99 -0
- package/dist/internal/loop/llm.d.ts.map +1 -0
- package/dist/internal/loop/llm.js +231 -0
- package/dist/internal/loop/llm.js.map +1 -0
- package/dist/internal/loop/reconstruct.d.ts +87 -0
- package/dist/internal/loop/reconstruct.d.ts.map +1 -0
- package/dist/internal/loop/reconstruct.js +157 -0
- package/dist/internal/loop/reconstruct.js.map +1 -0
- package/dist/internal/loop/sqlite.d.ts +13 -0
- package/dist/internal/loop/sqlite.d.ts.map +1 -0
- package/dist/internal/loop/sqlite.js +33 -0
- package/dist/internal/loop/sqlite.js.map +1 -0
- package/dist/internal/loop/store.d.ts +50 -0
- package/dist/internal/loop/store.d.ts.map +1 -0
- package/dist/internal/loop/store.js +100 -0
- package/dist/internal/loop/store.js.map +1 -0
- package/dist/internal/mcp/bin.d.ts +7 -0
- package/dist/internal/mcp/bin.d.ts.map +1 -0
- package/dist/internal/mcp/bin.js +8 -0
- package/dist/internal/mcp/bin.js.map +1 -0
- package/dist/internal/mcp/index.d.ts +25 -0
- package/dist/internal/mcp/index.d.ts.map +1 -0
- package/dist/internal/mcp/index.js +23 -0
- package/dist/internal/mcp/index.js.map +1 -0
- package/dist/internal/mcp/main.d.ts +23 -0
- package/dist/internal/mcp/main.d.ts.map +1 -0
- package/dist/internal/mcp/main.js +156 -0
- package/dist/internal/mcp/main.js.map +1 -0
- package/dist/internal/mcp/server.d.ts +92 -0
- package/dist/internal/mcp/server.d.ts.map +1 -0
- package/dist/internal/mcp/server.js +251 -0
- package/dist/internal/mcp/server.js.map +1 -0
- package/dist/internal/mcp/tools.d.ts +91 -0
- package/dist/internal/mcp/tools.d.ts.map +1 -0
- package/dist/internal/mcp/tools.js +584 -0
- package/dist/internal/mcp/tools.js.map +1 -0
- package/dist/internal/rules/declare.d.ts +58 -0
- package/dist/internal/rules/declare.d.ts.map +1 -0
- package/dist/internal/rules/declare.js +152 -0
- package/dist/internal/rules/declare.js.map +1 -0
- package/dist/internal/rules/engine.d.ts +125 -0
- package/dist/internal/rules/engine.d.ts.map +1 -0
- package/dist/internal/rules/engine.js +575 -0
- package/dist/internal/rules/engine.js.map +1 -0
- package/dist/internal/rules/index.d.ts +23 -0
- package/dist/internal/rules/index.d.ts.map +1 -0
- package/dist/internal/rules/index.js +21 -0
- package/dist/internal/rules/index.js.map +1 -0
- package/dist/internal/rules/rule.d.ts +88 -0
- package/dist/internal/rules/rule.d.ts.map +1 -0
- package/dist/internal/rules/rule.js +221 -0
- package/dist/internal/rules/rule.js.map +1 -0
- package/dist/internal/shape/check.d.ts +118 -0
- package/dist/internal/shape/check.d.ts.map +1 -0
- package/dist/internal/shape/check.js +331 -0
- package/dist/internal/shape/check.js.map +1 -0
- package/dist/internal/shape/client.d.ts +31 -0
- package/dist/internal/shape/client.d.ts.map +1 -0
- package/dist/internal/shape/client.js +170 -0
- package/dist/internal/shape/client.js.map +1 -0
- package/dist/internal/shape/gate.d.ts +33 -0
- package/dist/internal/shape/gate.d.ts.map +1 -0
- package/dist/internal/shape/gate.js +0 -0
- package/dist/internal/shape/gate.js.map +1 -0
- package/dist/internal/shape/index.d.ts +27 -0
- package/dist/internal/shape/index.d.ts.map +1 -0
- package/dist/internal/shape/index.js +23 -0
- package/dist/internal/shape/index.js.map +1 -0
- package/dist/internal/shape/suggest.d.ts +82 -0
- package/dist/internal/shape/suggest.d.ts.map +1 -0
- package/dist/internal/shape/suggest.js +374 -0
- package/dist/internal/shape/suggest.js.map +1 -0
- package/dist/internal/sync/index.d.ts +22 -0
- package/dist/internal/sync/index.d.ts.map +1 -0
- package/dist/internal/sync/index.js +21 -0
- package/dist/internal/sync/index.js.map +1 -0
- package/dist/internal/sync/sync.d.ts +95 -0
- package/dist/internal/sync/sync.d.ts.map +1 -0
- package/dist/internal/sync/sync.js +342 -0
- package/dist/internal/sync/sync.js.map +1 -0
- package/dist/internal/view/api.d.ts +196 -0
- package/dist/internal/view/api.d.ts.map +1 -0
- package/dist/internal/view/api.js +189 -0
- package/dist/internal/view/api.js.map +1 -0
- package/dist/internal/view/index.d.ts +33 -0
- package/dist/internal/view/index.d.ts.map +1 -0
- package/dist/internal/view/index.js +30 -0
- package/dist/internal/view/index.js.map +1 -0
- package/dist/internal/view/main.d.ts +11 -0
- package/dist/internal/view/main.d.ts.map +1 -0
- package/dist/internal/view/main.js +98 -0
- package/dist/internal/view/main.js.map +1 -0
- package/dist/internal/view/page.d.ts +14 -0
- package/dist/internal/view/page.d.ts.map +1 -0
- package/dist/internal/view/page.js +370 -0
- package/dist/internal/view/page.js.map +1 -0
- package/dist/internal/view/report.d.ts +52 -0
- package/dist/internal/view/report.d.ts.map +1 -0
- package/dist/internal/view/report.js +367 -0
- package/dist/internal/view/report.js.map +1 -0
- package/dist/internal/view/scope.d.ts +11 -0
- package/dist/internal/view/scope.d.ts.map +1 -0
- package/dist/internal/view/scope.js +41 -0
- package/dist/internal/view/scope.js.map +1 -0
- package/dist/internal/view/server.d.ts +35 -0
- package/dist/internal/view/server.d.ts.map +1 -0
- package/dist/internal/view/server.js +141 -0
- package/dist/internal/view/server.js.map +1 -0
- package/dist/src/act.d.ts +3 -0
- package/dist/src/act.d.ts.map +1 -0
- package/dist/src/act.js +3 -0
- package/dist/src/act.js.map +1 -0
- package/dist/src/automate.d.ts +3 -0
- package/dist/src/automate.d.ts.map +1 -0
- package/dist/src/automate.js +3 -0
- package/dist/src/automate.js.map +1 -0
- package/dist/src/cli.d.ts +24 -17
- package/dist/src/cli.d.ts.map +1 -1
- package/dist/src/cli.js +408 -107
- package/dist/src/cli.js.map +1 -1
- package/dist/src/commands.d.ts +104 -0
- package/dist/src/commands.d.ts.map +1 -0
- package/dist/src/commands.js +33 -0
- package/dist/src/commands.js.map +1 -0
- package/dist/src/connect.d.ts +3 -0
- package/dist/src/connect.d.ts.map +1 -0
- package/dist/src/connect.js +3 -0
- package/dist/src/connect.js.map +1 -0
- package/dist/src/dispatch.d.ts +14 -0
- package/dist/src/dispatch.d.ts.map +1 -0
- package/dist/src/dispatch.js +116 -0
- package/dist/src/dispatch.js.map +1 -0
- package/dist/src/doctor.d.ts +45 -0
- package/dist/src/doctor.d.ts.map +1 -0
- package/dist/src/doctor.js +284 -0
- package/dist/src/doctor.js.map +1 -0
- package/dist/src/eval.d.ts +3 -0
- package/dist/src/eval.d.ts.map +1 -0
- package/dist/src/eval.js +3 -0
- package/dist/src/eval.js.map +1 -0
- package/dist/src/index.d.ts +9 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +6 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/ingest.d.ts +3 -0
- package/dist/src/ingest.d.ts.map +1 -0
- package/dist/src/ingest.js +3 -0
- package/dist/src/ingest.js.map +1 -0
- package/dist/src/loop.d.ts +3 -0
- package/dist/src/loop.d.ts.map +1 -0
- package/dist/src/loop.js +3 -0
- package/dist/src/loop.js.map +1 -0
- package/dist/src/main.d.ts +1 -1
- package/dist/src/main.d.ts.map +1 -1
- package/dist/src/main.js +3 -75
- package/dist/src/main.js.map +1 -1
- package/dist/src/mcp.d.ts +3 -0
- package/dist/src/mcp.d.ts.map +1 -0
- package/dist/src/mcp.js +3 -0
- package/dist/src/mcp.js.map +1 -0
- package/dist/src/rules.d.ts +3 -0
- package/dist/src/rules.d.ts.map +1 -0
- package/dist/src/rules.js +3 -0
- package/dist/src/rules.js.map +1 -0
- package/dist/src/shape.d.ts +3 -0
- package/dist/src/shape.d.ts.map +1 -0
- package/dist/src/shape.js +3 -0
- package/dist/src/shape.js.map +1 -0
- package/dist/src/sync.d.ts +3 -0
- package/dist/src/sync.d.ts.map +1 -0
- package/dist/src/sync.js +3 -0
- package/dist/src/sync.js.map +1 -0
- package/dist/src/view.d.ts +3 -0
- package/dist/src/view.d.ts.map +1 -0
- package/dist/src/view.js +3 -0
- package/dist/src/view.js.map +1 -0
- package/package.json +81 -21
- package/src/act.ts +2 -0
- package/src/automate.ts +2 -0
- package/src/cli.ts +416 -102
- package/src/commands.ts +48 -0
- package/src/connect.ts +2 -0
- package/src/dispatch.ts +141 -0
- package/src/doctor.ts +370 -0
- package/src/eval.ts +2 -0
- package/src/index.ts +9 -2
- package/src/ingest.ts +2 -0
- package/src/loop.ts +2 -0
- package/src/main.ts +3 -66
- package/src/mcp.ts +2 -0
- package/src/rules.ts +2 -0
- package/src/shape.ts +2 -0
- package/src/sync.ts +2 -0
- package/src/view.ts +2 -0
package/dist/src/cli.js
CHANGED
|
@@ -1,27 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `cave` command implementation — pure functions from parsed arguments to
|
|
3
|
-
* `{ code, out, err }`, so tests can call commands directly
|
|
4
|
-
*
|
|
3
|
+
* `{ code, out, err }`, so tests can call commands directly while
|
|
4
|
+
* `dispatch.ts` gives every command one awaited process lifecycle.
|
|
5
5
|
*
|
|
6
6
|
* Commands:
|
|
7
7
|
*
|
|
8
8
|
* - `cave parse [file]` — lint / dump the AST (`--json`)
|
|
9
|
-
* - `cave highlight [file]` — ANSI syntax colors (async
|
|
9
|
+
* - `cave highlight [file]` — ANSI syntax colors (async)
|
|
10
10
|
* - `cave add [--db <path>] [file…]` — ingest into a store (`--strict`, `--check`)
|
|
11
11
|
* - `cave query [--db <path>] '<pattern>'` — CAVE-Q (`--json`, `--all`, `--aliases`, `--as-of`, `--resolve`)
|
|
12
12
|
* - `cave resolve [--db <path>]` — contested facts under the §26 policy (`--aliases`, `--policy`, `--json`)
|
|
13
13
|
* - `cave derive [--db <path>] [rules.cave…]` — fire rules (`--dry-run`, `--full`, `--list`, `--retract`)
|
|
14
14
|
* - `cave act [--db <path>] <name> [param=value…]` — execute an action (spec §25; `--declare`, `--list`, `--retract`)
|
|
15
|
-
* - `cave automate [--db <path>]` — the event-driven loop (spec §29; async
|
|
15
|
+
* - `cave automate [--db <path>]` — the event-driven loop (spec §29; async)
|
|
16
16
|
* - `cave check [--db <path>]` — knowledge health report (`--stale`, `--json`)
|
|
17
|
-
* - `cave
|
|
17
|
+
* - `cave backup [--db <path>] --out <path>` — exact verified SQLite snapshot
|
|
18
|
+
* - `cave restore <snapshot> --db <path>` — verify and atomically restore a snapshot
|
|
19
|
+
* - `cave generate [--db <path>]` — versioned TypeScript client from EXPECTS declarations
|
|
20
|
+
* - `cave suggest-alias [--db <path>]` — same-entity candidates (spec §27; async)
|
|
18
21
|
* - `cave sync [--db <path>] <source>` — merge another store by row identity (spec §28; `--dry-run`, `--as`, `--into`)
|
|
19
22
|
* - `cave export [--db <path>]` — canonical text out (`--current`, `--tx`)
|
|
20
|
-
* - `cave serve [--db <path>]` — the human read surface in a browser (spec §30; async
|
|
23
|
+
* - `cave serve [--db <path>]` — the human read surface in a browser (spec §30; async)
|
|
21
24
|
* - `cave report [--db <path>] [template.md…]` — cited markdown from CAVE-Q template blocks (spec §31)
|
|
22
|
-
* - `cave connect [--db <path>] <source>` — deterministic structured ingestion (async
|
|
23
|
-
* - `cave eval <suite...>` — golden-fixture extraction/query/reconstruction evals (async
|
|
24
|
-
* - `cave reconstruct [--db <path>] <seed...>` — §18 reconstruction from seed cues (async
|
|
25
|
+
* - `cave connect [--db <path>] <source>` — deterministic structured ingestion (async)
|
|
26
|
+
* - `cave eval <suite...>` — golden-fixture extraction/query/reconstruction evals (async)
|
|
27
|
+
* - `cave reconstruct [--db <path>] <seed...>` — §18 reconstruction from seed cues (async)
|
|
28
|
+
* - `cave doctor [--db <path>]` — read-only runtime, installation, and store diagnostics
|
|
25
29
|
* - `cave demo` — the cave-loop multi-hop recovery demo
|
|
26
30
|
* - `cave version` — print the cave version
|
|
27
31
|
* - `cave help [command]` — overview, or one command's help
|
|
@@ -29,21 +33,51 @@
|
|
|
29
33
|
* `file` defaults to stdin (`-`); `--db` defaults to `$CAVE_DB`, then
|
|
30
34
|
* `cave.db`. Every command answers `--help` with options and examples.
|
|
31
35
|
*/
|
|
32
|
-
import { readFileSync, statSync, writeFileSync } from 'node:fs';
|
|
36
|
+
import { readFileSync, readSync, statSync, writeFileSync } from 'node:fs';
|
|
33
37
|
import { resolve } from 'node:path';
|
|
34
38
|
import { parseArgs } from 'node:util';
|
|
35
39
|
import { Version } from '@cavelang/core';
|
|
36
40
|
import { parseDocument } from '@cavelang/parser';
|
|
37
41
|
import { Registry, standardRegistry } from '@cavelang/canonical';
|
|
38
|
-
import { defaultDbPath, open } from '@cavelang/store';
|
|
39
|
-
import {
|
|
40
|
-
import { check as caveCheck, defaultMinScore, defaultStaleDays, gatedIngest, judgePrompt, parseJudgeReply, suggestAliases, writeSuggestions } from '@cavelang/shape';
|
|
41
|
-
import { declareRules, defaultMaxPasses, defaultMinConf, derive, listRules, retractRule } from '@cavelang/rules';
|
|
42
|
-
import { act, declareActions, listActions, retractAction } from '@cavelang/act';
|
|
43
|
-
import { Demo, heuristicPolicy, llmPolicy, reconstruct, reconstructAsync, shellComplete, sqliteStore } from '@cavelang/loop';
|
|
44
|
-
import { labelOf, sanitizeLabel, syncFile, syncText } from '@cavelang/sync';
|
|
45
|
-
import { report as caveReport } from '@cavelang/view';
|
|
42
|
+
import { Sensitivity, backup as backupStore, defaultDbPath, open, restoreBackup, verifyBackup } from '@cavelang/store';
|
|
43
|
+
import { defaultLimit as defaultQueryLimit, page as caveQueryPage } from '@cavelang/query';
|
|
44
|
+
import { check as caveCheck, defaultMinScore, defaultStaleDays, gatedIngest, judgePrompt, parseJudgeReply, generateClient, suggestAliases, writeSuggestions } from '@cavelang/cli/shape';
|
|
45
|
+
import { declareRules, defaultMaxPasses, defaultMinConf, derive, listRules, retractRule } from '@cavelang/cli/rules';
|
|
46
|
+
import { act, declareActions, listActions, retractAction } from '@cavelang/cli/act';
|
|
47
|
+
import { Demo, heuristicPolicy, llmPolicy, reconstruct, reconstructAsync, shellComplete, sqliteStore } from '@cavelang/cli/loop';
|
|
48
|
+
import { labelOf, sanitizeLabel, syncFile, syncText } from '@cavelang/cli/sync';
|
|
49
|
+
import { report as caveReport } from '@cavelang/cli/view';
|
|
46
50
|
import { emitClaim } from '@cavelang/canonical';
|
|
51
|
+
import { doctorCommand } from "./doctor.js";
|
|
52
|
+
import { delegatedCommandNames } from "./commands.js";
|
|
53
|
+
const storageRow = (value) => typeof value === 'object' && value !== null &&
|
|
54
|
+
typeof value['id'] === 'string' &&
|
|
55
|
+
typeof value['tx'] === 'string' &&
|
|
56
|
+
typeof value['claim_key'] === 'string' &&
|
|
57
|
+
typeof value['raw_line'] === 'string';
|
|
58
|
+
/** Recursively replace storage rows in JSON reports with cave.claim/v1 records. */
|
|
59
|
+
const stableJsonValue = (store, value) => {
|
|
60
|
+
if (storageRow(value)) {
|
|
61
|
+
const record = store.recordOf(value);
|
|
62
|
+
const ranked = value;
|
|
63
|
+
return typeof ranked['res_rank'] === 'number' ? {
|
|
64
|
+
...record,
|
|
65
|
+
resolution: {
|
|
66
|
+
group: ranked['res_group'],
|
|
67
|
+
class: ranked['res_class'],
|
|
68
|
+
effectiveConfidence: ranked['res_conf'],
|
|
69
|
+
rank: ranked['res_rank'],
|
|
70
|
+
},
|
|
71
|
+
} : record;
|
|
72
|
+
}
|
|
73
|
+
if (Array.isArray(value))
|
|
74
|
+
return value.map(entry => stableJsonValue(store, entry));
|
|
75
|
+
if (typeof value === 'object' && value !== null) {
|
|
76
|
+
return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, stableJsonValue(store, entry)]));
|
|
77
|
+
}
|
|
78
|
+
return value;
|
|
79
|
+
};
|
|
80
|
+
const stableJson = (store, value) => JSON.stringify(stableJsonValue(store, value), undefined, 2);
|
|
47
81
|
const ok = (out) => ({ code: 0, out, err: '' });
|
|
48
82
|
const fail = (err, code = 1) => ({ code, out: '', err });
|
|
49
83
|
export const usage = `cave — Compressed Atomic Verb Expressions
|
|
@@ -53,23 +87,27 @@ Usage:
|
|
|
53
87
|
cave highlight [file...] print CAVE text with ANSI syntax colors
|
|
54
88
|
cave add [--db <path>] [file...] ingest into a store [--strict] [--check] [--no-prelude] [--no-src]
|
|
55
89
|
cave import [--db <path>] [file...] restore/merge from CAVE text (add without @src: stamping)
|
|
56
|
-
cave query [--db <path>] <pattern> run a CAVE-Q
|
|
90
|
+
cave query [--db <path>] <pattern> run a bounded CAVE-Q page [--limit <n>] [--cursor <token>] [--json]
|
|
57
91
|
cave resolve [--db <path>] contested facts + winners (spec §26) [--aliases] [--policy] [--json]
|
|
58
92
|
cave derive [--db <path>] [rules.cave..] declare + fire rules (spec §24) [--dry-run] [--full] [--list] [--retract <rule>]
|
|
59
93
|
cave act [--db <path>] <name> [p=v...] execute an action (spec §25) [--dry-run] [--no-check] [--hooks <file>]
|
|
60
94
|
cave act --declare [file...] declare actions from a CAVE document; --list / --retract <name> manage them
|
|
61
95
|
cave automate [--db <path>] event-driven loop (spec §29): new claims fire rules/actions/hooks/agent prompts [--once]
|
|
62
96
|
cave check [--db <path>] knowledge health report (spec §20) [--stale <days>] [--json]
|
|
97
|
+
cave backup [--db <path>] --out <file> exact verified SQLite snapshot [--force]
|
|
98
|
+
cave restore <snapshot> --db <path> verify and atomically restore an exact snapshot [--force]
|
|
99
|
+
cave generate [--db <path>] generate a typed client from EXPECTS [--out <file>] [--version <n>]
|
|
63
100
|
cave suggest-alias [--db <path>] propose same-entity ALIAS candidates (spec §27) [--min <s>] [--agent] [--write]
|
|
64
101
|
cave sync [--db <path>] <source> merge another store by row identity (spec §28) [--dry-run] [--as] [--into]
|
|
65
|
-
cave export [--db <path>] [--out <file>] emit canonical CAVE text [--
|
|
66
|
-
cave serve [--db <path>] browse
|
|
67
|
-
cave report [--db <path>] [template...] render cited markdown
|
|
102
|
+
cave export [--db <path>] [--out <file>] emit filtered canonical CAVE text [--max-sensitivity <level>]
|
|
103
|
+
cave serve [--db <path>] browse a filtered store (spec §30) [--max-sensitivity <level>]
|
|
104
|
+
cave report [--db <path>] [template...] render filtered cited markdown (spec §31) [--max-sensitivity <level>]
|
|
68
105
|
cave mcp [--db <path>] serve the engine as an MCP server on stdio [--no-prelude]
|
|
69
106
|
cave ingest [--db <path>] <globs/urls..> LLM-driven ingestion of files and web pages
|
|
70
|
-
cave eval <suite..> --agent '<command>' golden-fixture extraction/query/reconstruction evals
|
|
107
|
+
cave eval <suite..> --agent '<command>' golden-fixture extraction/query/reconstruction evals
|
|
71
108
|
cave connect <source> --map <file> deterministic structured ingestion (CSV/JSON/SQLite/URL, spec §23)
|
|
72
109
|
cave reconstruct [--db <path>] <seed..> reconstruct memory from seed cues (spec §18) [--agent] [--query] [--trace]
|
|
110
|
+
cave doctor [--db <path>] diagnose runtime, installation, and store health [--hooks <file>] [--json]
|
|
73
111
|
cave demo run the cave-loop reconstruction demo
|
|
74
112
|
cave version print the cave version
|
|
75
113
|
cave help [command] this text, or one command's options and examples
|
|
@@ -80,6 +118,25 @@ the repository root (section index in README.md).`;
|
|
|
80
118
|
const dbHelp = `--db <path> database file (default: $CAVE_DB, or cave.db)`;
|
|
81
119
|
/** Per-command help, printed for \`cave <command> --help\` and \`cave help <command>\`. */
|
|
82
120
|
export const commandHelp = {
|
|
121
|
+
doctor: `cave doctor — diagnose runtime, installation, and store health
|
|
122
|
+
|
|
123
|
+
Usage:
|
|
124
|
+
cave doctor [--db <path>] [--hooks <file>] [--json]
|
|
125
|
+
|
|
126
|
+
Options:
|
|
127
|
+
${dbHelp}
|
|
128
|
+
--hooks <file> validate an optional hooks JSON file
|
|
129
|
+
--json emit the versioned cave.doctor/v1 report
|
|
130
|
+
|
|
131
|
+
The command is read-only: it never creates or migrates a database and never
|
|
132
|
+
runs hooks. Its output is safe to share — database and hooks paths, hook names
|
|
133
|
+
and commands, URLs, and environment values are not included. Warnings such as
|
|
134
|
+
a not-yet-created database exit 0; failed required checks exit 1.
|
|
135
|
+
|
|
136
|
+
Examples:
|
|
137
|
+
cave doctor
|
|
138
|
+
cave doctor --db knowledge.db
|
|
139
|
+
cave doctor --hooks hooks.json --json`,
|
|
83
140
|
parse: `cave parse — lint CAVE text, or dump the parsed document
|
|
84
141
|
|
|
85
142
|
Usage:
|
|
@@ -152,23 +209,27 @@ file read as ordinary comments; to merge under the recorded row
|
|
|
152
209
|
identity, use \`cave sync\` (spec §28.4).
|
|
153
210
|
|
|
154
211
|
Examples:
|
|
155
|
-
cave export --db old.db --out backup.cave
|
|
212
|
+
cave export --db old.db --max-sensitivity restricted --out backup.cave
|
|
156
213
|
cave import --db new.db backup.cave`,
|
|
157
214
|
query: `cave query — run a CAVE-Q pattern against a store
|
|
158
215
|
|
|
159
216
|
Usage:
|
|
160
|
-
cave query [--db <path>] <pattern> [WHERE <filter>] [--json] [--all] [--aliases] [--as-of <t>] [--at <t>] [--resolve] [--no-prelude]
|
|
217
|
+
cave query [--db <path>] <pattern> [WHERE <filter>] [--limit <n>] [--cursor <token>] [--json] [--all] [--aliases] [--as-of <t>] [--at <t>] [--resolve] [--no-prelude]
|
|
161
218
|
|
|
162
219
|
Options:
|
|
163
220
|
${dbHelp}
|
|
164
|
-
--json emit
|
|
221
|
+
--json emit a versioned cave.query-page/v1 JSON object
|
|
222
|
+
--limit <n> matches per page (default ${defaultQueryLimit}, maximum 1000)
|
|
223
|
+
--cursor <t> continue the same frozen query snapshot
|
|
165
224
|
--all match all beliefs, not just current ones
|
|
166
225
|
--aliases resolve entities through current ALIAS claims (spec §13.6)
|
|
167
226
|
--as-of <t> resolve beliefs as of a past moment (spec §12.3): a date
|
|
168
227
|
(whole day included), a timestamp (whole second), or a
|
|
169
|
-
transaction id — rows recorded later are invisible
|
|
228
|
+
transaction id — rows recorded later are invisible;
|
|
229
|
+
timestamps without an offset mean UTC
|
|
170
230
|
--at <t> anchor in valid time (spec §32.4): a date-like period
|
|
171
|
-
(read as its start instant) or a timestamp
|
|
231
|
+
(read as its start instant) or a timestamp (offset-less
|
|
232
|
+
means UTC). Claims whose
|
|
172
233
|
time contexts — @2026-Q1 points, @2025..2028 ranges — do
|
|
173
234
|
not cover the instant are invisible; timeless claims
|
|
174
235
|
always match; trajectory values (20B -> 40B USD/yr)
|
|
@@ -324,7 +385,8 @@ Options:
|
|
|
324
385
|
--no-prelude open the store without the standard verb registry
|
|
325
386
|
|
|
326
387
|
Reads the store against its own in-band EXPECTS declarations (spec §20.1)
|
|
327
|
-
and reports
|
|
388
|
+
and reports actionable presence, #cardinality:one, and #unit:<unit>
|
|
389
|
+
violations, stale current beliefs, review candidates
|
|
328
390
|
(conf 0.3–0.7), alias disagreements (spec §13.6) and coverage stats.
|
|
329
391
|
Exits 1 when violations exist; everything else is advisory.
|
|
330
392
|
|
|
@@ -332,6 +394,66 @@ Examples:
|
|
|
332
394
|
cave check --db k.db
|
|
333
395
|
cave check --db k.db --stale 30
|
|
334
396
|
cave check --db k.db --json | jq '.violations'`,
|
|
397
|
+
backup: `cave backup — exact, verified SQLite snapshot (spec §13.2.2)
|
|
398
|
+
|
|
399
|
+
Usage:
|
|
400
|
+
cave backup [--db <path>] --out <file> [--force]
|
|
401
|
+
cave backup --verify <file> [--sha256 <hex>]
|
|
402
|
+
|
|
403
|
+
Options:
|
|
404
|
+
${dbHelp}
|
|
405
|
+
--out <file> destination snapshot (required when creating)
|
|
406
|
+
--force atomically replace an existing snapshot
|
|
407
|
+
--verify <file> verify integrity, foreign keys, schema and SHA-256 only
|
|
408
|
+
--sha256 <hex> expected digest for --verify
|
|
409
|
+
|
|
410
|
+
The source remains online. SQLite VACUUM INTO takes one consistent committed
|
|
411
|
+
snapshot, including WAL-visible rows; CAVE writes to a temporary file,
|
|
412
|
+
validates it, fsyncs it, then publishes it atomically. The summary SHA-256 is
|
|
413
|
+
the restore verification token.
|
|
414
|
+
|
|
415
|
+
Examples:
|
|
416
|
+
cave backup --db k.db --out backups/k.db
|
|
417
|
+
cave backup --verify backups/k.db --sha256 <hex>`,
|
|
418
|
+
restore: `cave restore — verify and atomically restore an exact SQLite snapshot (spec §13.2.2)
|
|
419
|
+
|
|
420
|
+
Usage:
|
|
421
|
+
cave restore <snapshot> --db <path> [--force] [--sha256 <hex>]
|
|
422
|
+
|
|
423
|
+
Options:
|
|
424
|
+
--db <path> destination database (required)
|
|
425
|
+
--force atomically replace an existing destination
|
|
426
|
+
--sha256 <hex> require the recorded backup digest
|
|
427
|
+
|
|
428
|
+
Stop every process using the destination first. Restore refuses WAL/SHM
|
|
429
|
+
sidecars, verifies the input and copied temporary database, then publishes one
|
|
430
|
+
atomic file. WAL, SHM, or rollback-journal sidecars cause a refusal. On
|
|
431
|
+
failure the prior destination remains untouched.
|
|
432
|
+
|
|
433
|
+
Example:
|
|
434
|
+
cave restore backups/k.db --db restored.db --sha256 <hex>`,
|
|
435
|
+
generate: `cave generate — deterministic TypeScript client from EXPECTS declarations (spec §20.4)
|
|
436
|
+
|
|
437
|
+
Usage:
|
|
438
|
+
cave generate [--db <path>] [--out <file>] [--version <n>] [--no-prelude]
|
|
439
|
+
|
|
440
|
+
Options:
|
|
441
|
+
${dbHelp}
|
|
442
|
+
--out <file> write the generated module instead of stdout
|
|
443
|
+
--version <n> generated-client format version (default and currently
|
|
444
|
+
supported: 1)
|
|
445
|
+
--no-prelude open the store without the standard verb registry
|
|
446
|
+
|
|
447
|
+
Current positive EXPECTS claims become TypeScript interfaces plus store-backed
|
|
448
|
+
reader functions. #cardinality:one emits a scalar checked at runtime;
|
|
449
|
+
attributes preserve text, number and unit; relation readers honor declared
|
|
450
|
+
inverse verbs. The file embeds its format version and deterministic schema
|
|
451
|
+
SHA-256. Conflicting declarations, invalid cardinality/unit tags, unsupported
|
|
452
|
+
versions and generated type-name collisions fail without writing output.
|
|
453
|
+
|
|
454
|
+
Examples:
|
|
455
|
+
cave generate --db k.db > cave-client.ts
|
|
456
|
+
cave generate --db k.db --out src/generated/cave-client.ts`,
|
|
335
457
|
'suggest-alias': `cave suggest-alias — propose same-entity ALIAS candidates for review (spec §27)
|
|
336
458
|
|
|
337
459
|
Usage:
|
|
@@ -414,38 +536,49 @@ a merge driver on *.cave files.
|
|
|
414
536
|
Examples:
|
|
415
537
|
cave sync --db main.db laptop.db
|
|
416
538
|
cave sync --db main.db laptop.db --dry-run --json
|
|
417
|
-
cave export --db laptop.db --tx | cave sync --db main.db -
|
|
539
|
+
cave export --db laptop.db --tx --max-sensitivity restricted | cave sync --db main.db -
|
|
418
540
|
cave sync --db a.db b.db && cave sync --db b.db a.db # converge both
|
|
419
541
|
cave sync --db work.db knowledge.cave --no-record # checkout (§28.6)
|
|
420
542
|
cave sync --db main.db knowledge.cave --as reorg-auth # land the branch`,
|
|
421
543
|
export: `cave export — emit canonical CAVE text from a store
|
|
422
544
|
|
|
423
545
|
Usage:
|
|
424
|
-
cave export [--db <path>] [--out <file>] [--current] [--tx]
|
|
546
|
+
cave export [--db <path>] [--out <file>] [--current] [--tx]
|
|
547
|
+
[--max-sensitivity <level>] [--no-prelude]
|
|
425
548
|
|
|
426
549
|
Options:
|
|
427
550
|
${dbHelp}
|
|
428
551
|
--out <file> write to a file instead of stdout — refused when it
|
|
429
552
|
names the store's own database file
|
|
430
|
-
--current current beliefs only (skip superseded rows)
|
|
553
|
+
--current current beliefs only (skip superseded rows); compacting
|
|
554
|
+
view, not sanitization or selective erasure (spec §9.6)
|
|
555
|
+
--max-sensitivity <level>
|
|
556
|
+
public, internal, confidential, or restricted (default
|
|
557
|
+
internal; restricted includes complete portable history)
|
|
431
558
|
--tx precede every claim line with its ;@ transaction
|
|
432
559
|
annotation (spec §28.4) — the text carries row identity,
|
|
433
560
|
so cave sync replays it idempotently; other readers see
|
|
434
561
|
ordinary comments
|
|
435
562
|
--no-prelude open the store without the standard verb registry
|
|
436
563
|
|
|
564
|
+
Retention: claim history is permanent. Retraction and --current do not
|
|
565
|
+
guarantee erasure from the store, exports, peers, or backups (spec §9.6).
|
|
566
|
+
|
|
437
567
|
Examples:
|
|
438
568
|
cave export --db k.db
|
|
439
|
-
cave export --db k.db --out
|
|
569
|
+
cave export --db k.db --out internal-export.cave
|
|
570
|
+
cave export --db k.db --max-sensitivity restricted --out complete-history.cave
|
|
440
571
|
cave export --db k.db --current --out snapshot.cave
|
|
441
|
-
cave export --db k.db --tx | cave sync --db other.db -
|
|
442
|
-
cave export --db work.db --tx --out knowledge.cave
|
|
572
|
+
cave export --db k.db --tx --max-sensitivity restricted | cave sync --db other.db -
|
|
573
|
+
cave export --db work.db --tx --max-sensitivity restricted --out knowledge.cave
|
|
574
|
+
# the committed,
|
|
443
575
|
# reviewable store text (spec §28.6)`,
|
|
444
576
|
report: `cave report — render cited markdown from a CAVE-Q template (spec §31)
|
|
445
577
|
|
|
446
578
|
Usage:
|
|
447
579
|
cave report [--db <path>] [template.md...] [--out <file>]
|
|
448
|
-
[--aliases] [--resolve] [--as-of <t>] [--at <t>]
|
|
580
|
+
[--aliases] [--resolve] [--as-of <t>] [--at <t>]
|
|
581
|
+
[--max-sensitivity <level>] [--no-prelude]
|
|
449
582
|
|
|
450
583
|
Options:
|
|
451
584
|
${dbHelp}
|
|
@@ -458,6 +591,9 @@ Options:
|
|
|
458
591
|
--at <t> anchor every query in valid time (spec §32.4): claims
|
|
459
592
|
whose time contexts don't cover the instant drop out,
|
|
460
593
|
trajectory values render interpolated
|
|
594
|
+
--max-sensitivity <level>
|
|
595
|
+
public, internal, confidential, or restricted (default
|
|
596
|
+
internal; malformed/unknown claim labels fail closed)
|
|
461
597
|
--no-prelude open the store without the standard verb registry
|
|
462
598
|
|
|
463
599
|
Reads stdin when no file (or \`-\`) is given. A template is ordinary
|
|
@@ -529,8 +665,28 @@ topic → fix over a small in-memory store.`,
|
|
|
529
665
|
Usage:
|
|
530
666
|
cave version`
|
|
531
667
|
};
|
|
668
|
+
const readStdin = () => {
|
|
669
|
+
const chunks = [];
|
|
670
|
+
const buffer = Buffer.allocUnsafe(64 * 1024);
|
|
671
|
+
const pause = new Int32Array(new SharedArrayBuffer(4));
|
|
672
|
+
for (;;) {
|
|
673
|
+
try {
|
|
674
|
+
const size = readSync(0, buffer, 0, buffer.length, null);
|
|
675
|
+
if (size === 0)
|
|
676
|
+
return Buffer.concat(chunks).toString('utf8');
|
|
677
|
+
chunks.push(Buffer.from(buffer.subarray(0, size)));
|
|
678
|
+
}
|
|
679
|
+
catch (error) {
|
|
680
|
+
if (error.code !== 'EAGAIN')
|
|
681
|
+
throw error;
|
|
682
|
+
// A pipe may be non-blocking on macOS. The producer is another process,
|
|
683
|
+
// so a short synchronous retry does not prevent it from making progress.
|
|
684
|
+
Atomics.wait(pause, 0, 0, 5);
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
};
|
|
532
688
|
const readInput = (files) => files.length === 0 || (files.length === 1 && files[0] === '-') ?
|
|
533
|
-
|
|
689
|
+
readStdin() :
|
|
534
690
|
files.map(file => readFileSync(file, 'utf8')).join('\n');
|
|
535
691
|
export const parseCommand = (argv) => {
|
|
536
692
|
const { values, positionals } = parseArgs({
|
|
@@ -560,8 +716,7 @@ export const parseCommand = (argv) => {
|
|
|
560
716
|
};
|
|
561
717
|
/**
|
|
562
718
|
* `cave highlight` — ANSI syntax colors from the tree-sitter grammar's own
|
|
563
|
-
* highlight query. Async
|
|
564
|
-
* routes it separately, like `mcp` and `ingest`.
|
|
719
|
+
* highlight query. Async because the grammar WASM loads on first use.
|
|
565
720
|
*/
|
|
566
721
|
export const highlightCommand = async (argv) => {
|
|
567
722
|
const { positionals } = parseArgs({ args: [...argv], options: {}, allowPositionals: true });
|
|
@@ -577,8 +732,23 @@ export const highlightCommand = async (argv) => {
|
|
|
577
732
|
* replays interchange text, which must preserve claim keys as exported,
|
|
578
733
|
* so it never stamps.
|
|
579
734
|
*/
|
|
580
|
-
const
|
|
581
|
-
|
|
735
|
+
const formatViolationProblem = (violation) => {
|
|
736
|
+
const { entity, expectation, actualCount, actualUnits } = violation;
|
|
737
|
+
if (actualCount === 0) {
|
|
738
|
+
return `${entity} missing ${expectation.kind} ${expectation.name}`;
|
|
739
|
+
}
|
|
740
|
+
const problems = [];
|
|
741
|
+
if (expectation.cardinality === 'one' && actualCount !== 1) {
|
|
742
|
+
problems.push(`${entity} has ${actualCount} ${expectation.kind}s ${expectation.name}; expected exactly one`);
|
|
743
|
+
}
|
|
744
|
+
if (expectation.unit !== undefined && actualUnits.some(unit => unit !== expectation.unit)) {
|
|
745
|
+
const units = actualUnits.map(unit => unit ?? '(none)').join(', ');
|
|
746
|
+
problems.push(`${entity} attribute ${expectation.name} has unit${actualUnits.length === 1 ? '' : 's'} ${units}; expected ${expectation.unit}`);
|
|
747
|
+
}
|
|
748
|
+
return problems.join('; ');
|
|
749
|
+
};
|
|
750
|
+
const formatViolation = (violation) => `${formatViolationProblem(violation)} ` +
|
|
751
|
+
`(${violation.entity} IS ${violation.via}; ${violation.expectation.row.raw_line})`;
|
|
582
752
|
const ingestCommand = (name) => (argv) => {
|
|
583
753
|
const { values, positionals } = parseArgs({
|
|
584
754
|
args: [...argv],
|
|
@@ -647,6 +817,8 @@ export const queryCommand = (argv) => {
|
|
|
647
817
|
'as-of': { type: 'string' },
|
|
648
818
|
at: { type: 'string' },
|
|
649
819
|
resolve: { type: 'boolean' },
|
|
820
|
+
limit: { type: 'string' },
|
|
821
|
+
cursor: { type: 'string' },
|
|
650
822
|
'no-prelude': { type: 'boolean' }
|
|
651
823
|
},
|
|
652
824
|
allowPositionals: true
|
|
@@ -657,18 +829,22 @@ export const queryCommand = (argv) => {
|
|
|
657
829
|
const pattern = positionals.join('\n');
|
|
658
830
|
const store = open(values.db ?? defaultDbPath(), values['no-prelude'] === true ? { registry: Registry.empty } : {});
|
|
659
831
|
try {
|
|
660
|
-
const
|
|
832
|
+
const limit = values.limit === undefined ? defaultQueryLimit : Number(values.limit);
|
|
833
|
+
const result = caveQueryPage(store, pattern, {
|
|
661
834
|
all: values.all === true,
|
|
662
835
|
aliases: values.aliases === true,
|
|
663
836
|
resolve: values.resolve === true,
|
|
837
|
+
limit,
|
|
838
|
+
...values.cursor === undefined ? {} : { cursor: values.cursor },
|
|
664
839
|
...values['as-of'] === undefined ? {} : { asOf: values['as-of'] },
|
|
665
840
|
...values.at === undefined ? {} : { at: values.at }
|
|
666
841
|
});
|
|
667
842
|
if (values.json === true) {
|
|
668
|
-
return ok(`${JSON.stringify(
|
|
843
|
+
return ok(`${JSON.stringify(result, undefined, 2)}\n`);
|
|
669
844
|
}
|
|
845
|
+
const matches = result.matches;
|
|
670
846
|
if (matches.length === 0) {
|
|
671
|
-
return ok(
|
|
847
|
+
return ok(`no matches\n${result.next === undefined ? '' : `next: ${result.next}\n`}`);
|
|
672
848
|
}
|
|
673
849
|
const lines = matches.map(match => {
|
|
674
850
|
const bindings = Object.entries(match.bindings)
|
|
@@ -676,14 +852,14 @@ export const queryCommand = (argv) => {
|
|
|
676
852
|
.join(' ');
|
|
677
853
|
// A fully bound pattern has no bindings to print; transitive matches
|
|
678
854
|
// additionally carry no row — confirm with the pattern itself.
|
|
679
|
-
const line = bindings !== '' ? bindings : match.
|
|
855
|
+
const line = bindings !== '' ? bindings : match.claim?.claim.raw ?? pattern.split('\n')[0];
|
|
680
856
|
// An interpolated trajectory shows its value at the anchor
|
|
681
857
|
// (spec §32.4) — bindings already carry it in the value slot.
|
|
682
858
|
return match.at !== undefined && bindings === '' ?
|
|
683
859
|
`${line} ; at ${values.at}: ${match.at.text}` :
|
|
684
860
|
line;
|
|
685
861
|
});
|
|
686
|
-
return ok(`${lines.join('\n')}\n`);
|
|
862
|
+
return ok(`${lines.join('\n')}\n${result.next === undefined ? '' : `next: ${result.next}\n`}`);
|
|
687
863
|
}
|
|
688
864
|
catch (error) {
|
|
689
865
|
return fail(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
@@ -730,7 +906,7 @@ export const resolveCommand = (argv) => {
|
|
|
730
906
|
}
|
|
731
907
|
const contested = store.contested({ aliases: values.aliases === true });
|
|
732
908
|
if (values.json === true) {
|
|
733
|
-
return ok(`${
|
|
909
|
+
return ok(`${stableJson(store, contested)}\n`);
|
|
734
910
|
}
|
|
735
911
|
if (contested.length === 0) {
|
|
736
912
|
return ok('no contested facts\n');
|
|
@@ -777,7 +953,7 @@ export const deriveCommand = (argv) => {
|
|
|
777
953
|
if (values.list === true) {
|
|
778
954
|
const rules = listRules(store);
|
|
779
955
|
if (values.json === true) {
|
|
780
|
-
return ok(`${
|
|
956
|
+
return ok(`${stableJson(store, rules)}\n`);
|
|
781
957
|
}
|
|
782
958
|
if (rules.length === 0) {
|
|
783
959
|
return ok('no rules\n');
|
|
@@ -839,7 +1015,7 @@ export const deriveCommand = (argv) => {
|
|
|
839
1015
|
(declaration.prelude > 0 ? `, +${declaration.prelude} prelude claim(s)` : ''));
|
|
840
1016
|
}
|
|
841
1017
|
if (values.json === true) {
|
|
842
|
-
return { code: report.problems.length > 0 ? 1 : 0, out: `${
|
|
1018
|
+
return { code: report.problems.length > 0 || !report.complete ? 1 : 0, out: `${stableJson(store, report)}\n`, err: err.join('\n') + (err.length > 0 ? '\n' : '') };
|
|
843
1019
|
}
|
|
844
1020
|
for (const problem of report.problems) {
|
|
845
1021
|
err.push(`${problem.subject}: ${problem.problems.join('; ')}`);
|
|
@@ -855,7 +1031,7 @@ export const deriveCommand = (argv) => {
|
|
|
855
1031
|
out.push(`derived${values['dry-run'] === true ? ' (dry run)' : ''}: ` +
|
|
856
1032
|
`+${report.appended} appended, ${report.updated} updated, ${report.retracted} retracted, ` +
|
|
857
1033
|
`${report.unchanged} unchanged (${report.passes} pass(es))`);
|
|
858
|
-
const hasProblems = report.problems.length > 0 || report.rules.some(rule => rule.problems.length > 0);
|
|
1034
|
+
const hasProblems = !report.complete || report.problems.length > 0 || report.rules.some(rule => rule.problems.length > 0);
|
|
859
1035
|
return { code: hasProblems ? 1 : 0, out: `${out.join('\n')}\n`, err: err.length === 0 ? '' : `${err.join('\n')}\n` };
|
|
860
1036
|
}
|
|
861
1037
|
catch (error) {
|
|
@@ -943,7 +1119,7 @@ export const actCommand = (argv) => {
|
|
|
943
1119
|
if (values.list === true) {
|
|
944
1120
|
const actions = listActions(store);
|
|
945
1121
|
if (values.json === true) {
|
|
946
|
-
return ok(`${
|
|
1122
|
+
return ok(`${stableJson(store, actions)}\n`);
|
|
947
1123
|
}
|
|
948
1124
|
if (actions.length === 0) {
|
|
949
1125
|
return ok('no actions\n');
|
|
@@ -983,7 +1159,7 @@ export const actCommand = (argv) => {
|
|
|
983
1159
|
...hooksPath === undefined ? {} : { hooks: readHooks(hooksPath) }
|
|
984
1160
|
});
|
|
985
1161
|
if (values.json === true) {
|
|
986
|
-
return { code: report.ok && report.hook?.error === undefined ? 0 : 1, out: `${
|
|
1162
|
+
return { code: report.ok && report.hook?.error === undefined ? 0 : 1, out: `${stableJson(store, report)}\n`, err: '' };
|
|
987
1163
|
}
|
|
988
1164
|
const { lines, code } = renderActReport(report);
|
|
989
1165
|
return report.ok ?
|
|
@@ -1048,7 +1224,7 @@ export const checkCommand = (argv) => {
|
|
|
1048
1224
|
try {
|
|
1049
1225
|
const report = caveCheck(store, { staleDays });
|
|
1050
1226
|
const out = values.json === true ?
|
|
1051
|
-
`${
|
|
1227
|
+
`${stableJson(store, report)}\n` :
|
|
1052
1228
|
renderReport(report, staleDays);
|
|
1053
1229
|
// Violations fail the check (spec §20.2); the other sections are advisory.
|
|
1054
1230
|
return { code: report.violations.length > 0 ? 1 : 0, out, err: '' };
|
|
@@ -1057,11 +1233,83 @@ export const checkCommand = (argv) => {
|
|
|
1057
1233
|
store.close();
|
|
1058
1234
|
}
|
|
1059
1235
|
};
|
|
1236
|
+
const snapshotLine = (action, snapshot) => `${action} exact backup (${snapshot.rows} row(s), schema v${snapshot.schemaVersion}, ` +
|
|
1237
|
+
`${snapshot.bytes} bytes, sha256:${snapshot.sha256}) at ${snapshot.path}\n`;
|
|
1238
|
+
/** `cave backup` — create or verify an exact SQLite snapshot (§13.2.2). */
|
|
1239
|
+
export const backupCommand = (argv) => {
|
|
1240
|
+
const { values } = parseArgs({
|
|
1241
|
+
args: [...argv],
|
|
1242
|
+
options: {
|
|
1243
|
+
db: { type: 'string' },
|
|
1244
|
+
out: { type: 'string' },
|
|
1245
|
+
force: { type: 'boolean' },
|
|
1246
|
+
verify: { type: 'string' },
|
|
1247
|
+
sha256: { type: 'string' }
|
|
1248
|
+
},
|
|
1249
|
+
allowPositionals: false
|
|
1250
|
+
});
|
|
1251
|
+
if (values.sha256 !== undefined && !/^[0-9a-f]{64}$/i.test(values.sha256)) {
|
|
1252
|
+
return fail('cave backup: --sha256 must be 64 hexadecimal characters\n');
|
|
1253
|
+
}
|
|
1254
|
+
try {
|
|
1255
|
+
if (values.verify !== undefined) {
|
|
1256
|
+
if (values.out !== undefined || values.force === true || values.db !== undefined) {
|
|
1257
|
+
return fail('cave backup: --verify excludes --db, --out, and --force\n');
|
|
1258
|
+
}
|
|
1259
|
+
return ok(snapshotLine('verified', verifyBackup(values.verify, values.sha256)));
|
|
1260
|
+
}
|
|
1261
|
+
if (values.sha256 !== undefined) {
|
|
1262
|
+
return fail('cave backup: --sha256 requires --verify\n');
|
|
1263
|
+
}
|
|
1264
|
+
if (values.out === undefined) {
|
|
1265
|
+
return fail('cave backup: --out <file> is required\n');
|
|
1266
|
+
}
|
|
1267
|
+
const store = open(values.db ?? defaultDbPath());
|
|
1268
|
+
try {
|
|
1269
|
+
return ok(snapshotLine('created', backupStore(store, values.out, { force: values.force === true })));
|
|
1270
|
+
}
|
|
1271
|
+
finally {
|
|
1272
|
+
store.close();
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
catch (error) {
|
|
1276
|
+
return fail(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
1277
|
+
}
|
|
1278
|
+
};
|
|
1279
|
+
/** `cave restore` — verify and atomically restore an exact snapshot (§13.2.2). */
|
|
1280
|
+
export const restoreCommand = (argv) => {
|
|
1281
|
+
const { values, positionals } = parseArgs({
|
|
1282
|
+
args: [...argv],
|
|
1283
|
+
options: {
|
|
1284
|
+
db: { type: 'string' },
|
|
1285
|
+
force: { type: 'boolean' },
|
|
1286
|
+
sha256: { type: 'string' }
|
|
1287
|
+
},
|
|
1288
|
+
allowPositionals: true
|
|
1289
|
+
});
|
|
1290
|
+
if (positionals.length !== 1) {
|
|
1291
|
+
return fail('cave restore: exactly one snapshot file is required\n');
|
|
1292
|
+
}
|
|
1293
|
+
if (values.db === undefined) {
|
|
1294
|
+
return fail('cave restore: --db <path> destination is required\n');
|
|
1295
|
+
}
|
|
1296
|
+
if (values.sha256 !== undefined && !/^[0-9a-f]{64}$/i.test(values.sha256)) {
|
|
1297
|
+
return fail('cave restore: --sha256 must be 64 hexadecimal characters\n');
|
|
1298
|
+
}
|
|
1299
|
+
try {
|
|
1300
|
+
return ok(snapshotLine('restored', restoreBackup(positionals[0], values.db, {
|
|
1301
|
+
force: values.force === true,
|
|
1302
|
+
...values.sha256 === undefined ? {} : { expectedSha256: values.sha256 }
|
|
1303
|
+
})));
|
|
1304
|
+
}
|
|
1305
|
+
catch (error) {
|
|
1306
|
+
return fail(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
1307
|
+
}
|
|
1308
|
+
};
|
|
1060
1309
|
/**
|
|
1061
1310
|
* `cave suggest-alias` — alias discovery (spec §27): same-entity
|
|
1062
|
-
* candidates as suggested `ALIAS` claims for review. Async
|
|
1063
|
-
* judge runs a shell agent
|
|
1064
|
-
* `reconstruct`.
|
|
1311
|
+
* candidates as suggested `ALIAS` claims for review. Async when the optional
|
|
1312
|
+
* judge runs a shell agent.
|
|
1065
1313
|
*/
|
|
1066
1314
|
export const suggestAliasCommand = async (argv) => {
|
|
1067
1315
|
try {
|
|
@@ -1159,7 +1407,7 @@ export const syncCommand = (argv) => {
|
|
|
1159
1407
|
...values.as === undefined ? {} : { from: sanitizeLabel(values.as) }
|
|
1160
1408
|
};
|
|
1161
1409
|
const report = source === '-' ?
|
|
1162
|
-
syncText(store,
|
|
1410
|
+
syncText(store, readStdin(), { from: 'stdin', ...options }) :
|
|
1163
1411
|
syncFile(store, source, options);
|
|
1164
1412
|
if (values.json === true) {
|
|
1165
1413
|
return { code: report.problems.length > 0 ? 1 : 0, out: `${JSON.stringify(report, undefined, 2)}\n`, err: '' };
|
|
@@ -1202,16 +1450,22 @@ export const reportCommand = (argv) => {
|
|
|
1202
1450
|
resolve: { type: 'boolean' },
|
|
1203
1451
|
'as-of': { type: 'string' },
|
|
1204
1452
|
at: { type: 'string' },
|
|
1453
|
+
'max-sensitivity': { type: 'string' },
|
|
1205
1454
|
'no-prelude': { type: 'boolean' }
|
|
1206
1455
|
},
|
|
1207
1456
|
allowPositionals: true
|
|
1208
1457
|
});
|
|
1209
1458
|
const template = readInput(positionals);
|
|
1459
|
+
const maximum = Sensitivity.parse(values['max-sensitivity'] ?? Sensitivity.defaultMaximum);
|
|
1460
|
+
if (maximum === undefined) {
|
|
1461
|
+
return fail(`cave report: --max-sensitivity expects ${Sensitivity.levels.join(', ')}, got ${JSON.stringify(values['max-sensitivity'])}\n`);
|
|
1462
|
+
}
|
|
1210
1463
|
const store = open(values.db ?? defaultDbPath(), values['no-prelude'] === true ? { registry: Registry.empty } : {});
|
|
1211
1464
|
try {
|
|
1212
1465
|
const rendered = caveReport(store, template, {
|
|
1213
1466
|
aliases: values.aliases === true,
|
|
1214
1467
|
resolve: values.resolve === true,
|
|
1468
|
+
maxSensitivity: maximum,
|
|
1215
1469
|
...values['as-of'] === undefined ? {} : { asOf: values['as-of'] },
|
|
1216
1470
|
...values.at === undefined ? {} : { at: values.at }
|
|
1217
1471
|
});
|
|
@@ -1262,17 +1516,22 @@ export const exportCommand = (argv) => {
|
|
|
1262
1516
|
current: { type: 'boolean' },
|
|
1263
1517
|
tx: { type: 'boolean' },
|
|
1264
1518
|
out: { type: 'string' },
|
|
1519
|
+
'max-sensitivity': { type: 'string' },
|
|
1265
1520
|
'no-prelude': { type: 'boolean' }
|
|
1266
1521
|
},
|
|
1267
1522
|
allowPositionals: false
|
|
1268
1523
|
});
|
|
1269
1524
|
const db = values.db ?? defaultDbPath();
|
|
1525
|
+
const maximum = Sensitivity.parse(values['max-sensitivity'] ?? Sensitivity.defaultMaximum);
|
|
1526
|
+
if (maximum === undefined) {
|
|
1527
|
+
return fail(`cave export: --max-sensitivity expects ${Sensitivity.levels.join(', ')}, got ${JSON.stringify(values['max-sensitivity'])}\n`);
|
|
1528
|
+
}
|
|
1270
1529
|
if (values.out !== undefined && sameFile(db, values.out)) {
|
|
1271
1530
|
return fail(`cave export: --out '${values.out}' is the source database — refusing to overwrite it\n`);
|
|
1272
1531
|
}
|
|
1273
1532
|
const store = open(db, values['no-prelude'] === true ? { registry: Registry.empty } : {});
|
|
1274
1533
|
try {
|
|
1275
|
-
const text = store.exportText({ current: values.current === true, tx: values.tx === true });
|
|
1534
|
+
const text = store.exportText({ current: values.current === true, tx: values.tx === true, maxSensitivity: maximum });
|
|
1276
1535
|
if (values.out === undefined) {
|
|
1277
1536
|
return ok(text);
|
|
1278
1537
|
}
|
|
@@ -1290,11 +1549,50 @@ export const exportCommand = (argv) => {
|
|
|
1290
1549
|
store.close();
|
|
1291
1550
|
}
|
|
1292
1551
|
};
|
|
1552
|
+
/** `cave generate` — spec §20.4's versioned TypeScript client artifact. */
|
|
1553
|
+
export const generateCommand = (argv) => {
|
|
1554
|
+
const { values } = parseArgs({
|
|
1555
|
+
args: [...argv],
|
|
1556
|
+
options: {
|
|
1557
|
+
db: { type: 'string' },
|
|
1558
|
+
out: { type: 'string' },
|
|
1559
|
+
version: { type: 'string' },
|
|
1560
|
+
'no-prelude': { type: 'boolean' }
|
|
1561
|
+
},
|
|
1562
|
+
allowPositionals: false
|
|
1563
|
+
});
|
|
1564
|
+
const version = values.version === undefined ? undefined : Number(values.version);
|
|
1565
|
+
if (version !== undefined && (!Number.isInteger(version) || version < 1)) {
|
|
1566
|
+
return fail(`cave generate: --version expects a positive integer, got ${JSON.stringify(values.version)}\n`);
|
|
1567
|
+
}
|
|
1568
|
+
const db = values.db ?? defaultDbPath();
|
|
1569
|
+
if (values.out !== undefined && sameFile(db, values.out)) {
|
|
1570
|
+
return fail(`cave generate: --out '${values.out}' is the source database — refusing to overwrite it\n`);
|
|
1571
|
+
}
|
|
1572
|
+
const store = open(db, values['no-prelude'] === true ? { registry: Registry.empty } : {});
|
|
1573
|
+
try {
|
|
1574
|
+
const generated = generateClient(store, version === undefined ? {} : { version });
|
|
1575
|
+
if (!generated.ok) {
|
|
1576
|
+
return fail(`cave generate: schema cannot be generated:\n${generated.problems.map(problem => ` ${problem}`).join('\n')}\n`);
|
|
1577
|
+
}
|
|
1578
|
+
if (values.out === undefined) {
|
|
1579
|
+
return ok(generated.code);
|
|
1580
|
+
}
|
|
1581
|
+
writeFileSync(values.out, generated.code);
|
|
1582
|
+
return ok(`generated typed client v${generated.version} (${generated.fields.length} field(s), ` +
|
|
1583
|
+
`sha256:${generated.digest}) to ${values.out}\n`);
|
|
1584
|
+
}
|
|
1585
|
+
catch (error) {
|
|
1586
|
+
return fail(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
1587
|
+
}
|
|
1588
|
+
finally {
|
|
1589
|
+
store.close();
|
|
1590
|
+
}
|
|
1591
|
+
};
|
|
1293
1592
|
/**
|
|
1294
1593
|
* `cave reconstruct` — the §18 loop over the store: heuristic policy by
|
|
1295
1594
|
* default (the eval baseline), the LLM policy over a shell-agent template
|
|
1296
|
-
* with `--agent`. Async
|
|
1297
|
-
* routes it separately, like `connect`.
|
|
1595
|
+
* with `--agent`. Async because the agent runs once per step.
|
|
1298
1596
|
*/
|
|
1299
1597
|
export const reconstructCommand = async (argv) => {
|
|
1300
1598
|
try {
|
|
@@ -1368,8 +1666,8 @@ export const helpCommand = (argv) => {
|
|
|
1368
1666
|
if (text !== undefined) {
|
|
1369
1667
|
return ok(`${text}\n`);
|
|
1370
1668
|
}
|
|
1371
|
-
//
|
|
1372
|
-
if (topic
|
|
1669
|
+
// Delegated commands own their help; dispatch.ts forwards `help X` to `X --help`.
|
|
1670
|
+
if (delegatedCommandNames.includes(topic)) {
|
|
1373
1671
|
return ok(`see: cave ${topic} --help\n`);
|
|
1374
1672
|
}
|
|
1375
1673
|
return fail(`cave help: unknown command ${JSON.stringify(topic)}\n\n${usage}\n`, 2);
|
|
@@ -1378,52 +1676,55 @@ export const helpCommand = (argv) => {
|
|
|
1378
1676
|
export const cave = (argv) => {
|
|
1379
1677
|
const [command, ...rest] = argv;
|
|
1380
1678
|
const canonical = command === 'q' ? 'query' : command;
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
return ok(`${commandHelp[canonical]}\n`);
|
|
1385
|
-
}
|
|
1386
|
-
switch (canonical) {
|
|
1387
|
-
case 'parse':
|
|
1388
|
-
return parseCommand(rest);
|
|
1389
|
-
case 'add':
|
|
1390
|
-
return addCommand(rest);
|
|
1391
|
-
case 'import':
|
|
1392
|
-
return importCommand(rest);
|
|
1393
|
-
case 'query':
|
|
1394
|
-
return queryCommand(rest);
|
|
1395
|
-
case 'resolve':
|
|
1396
|
-
return resolveCommand(rest);
|
|
1397
|
-
case 'derive':
|
|
1398
|
-
return deriveCommand(rest);
|
|
1399
|
-
case 'act':
|
|
1400
|
-
return actCommand(rest);
|
|
1401
|
-
case 'check':
|
|
1402
|
-
return checkCommand(rest);
|
|
1403
|
-
case 'sync':
|
|
1404
|
-
return syncCommand(rest);
|
|
1405
|
-
case 'export':
|
|
1406
|
-
return exportCommand(rest);
|
|
1407
|
-
case 'report':
|
|
1408
|
-
return reportCommand(rest);
|
|
1409
|
-
case 'demo':
|
|
1410
|
-
return demoCommand();
|
|
1411
|
-
case 'version':
|
|
1412
|
-
case '--version':
|
|
1413
|
-
case '-v':
|
|
1414
|
-
return versionCommand();
|
|
1415
|
-
case 'help':
|
|
1416
|
-
return helpCommand(rest);
|
|
1417
|
-
case undefined:
|
|
1418
|
-
case '--help':
|
|
1419
|
-
case '-h':
|
|
1420
|
-
return ok(`${usage}\n`);
|
|
1421
|
-
default:
|
|
1422
|
-
return fail(`cave: unknown command ${JSON.stringify(command)}\n\n${usage}\n`, 2);
|
|
1423
|
-
}
|
|
1679
|
+
if (canonical !== undefined && canonical in commandHelp &&
|
|
1680
|
+
(rest.includes('--help') || rest.includes('-h'))) {
|
|
1681
|
+
return ok(`${commandHelp[canonical]}\n`);
|
|
1424
1682
|
}
|
|
1425
|
-
|
|
1426
|
-
|
|
1683
|
+
switch (canonical) {
|
|
1684
|
+
case 'parse':
|
|
1685
|
+
return parseCommand(rest);
|
|
1686
|
+
case 'add':
|
|
1687
|
+
return addCommand(rest);
|
|
1688
|
+
case 'import':
|
|
1689
|
+
return importCommand(rest);
|
|
1690
|
+
case 'query':
|
|
1691
|
+
return queryCommand(rest);
|
|
1692
|
+
case 'resolve':
|
|
1693
|
+
return resolveCommand(rest);
|
|
1694
|
+
case 'derive':
|
|
1695
|
+
return deriveCommand(rest);
|
|
1696
|
+
case 'act':
|
|
1697
|
+
return actCommand(rest);
|
|
1698
|
+
case 'check':
|
|
1699
|
+
return checkCommand(rest);
|
|
1700
|
+
case 'backup':
|
|
1701
|
+
return backupCommand(rest);
|
|
1702
|
+
case 'restore':
|
|
1703
|
+
return restoreCommand(rest);
|
|
1704
|
+
case 'generate':
|
|
1705
|
+
return generateCommand(rest);
|
|
1706
|
+
case 'sync':
|
|
1707
|
+
return syncCommand(rest);
|
|
1708
|
+
case 'export':
|
|
1709
|
+
return exportCommand(rest);
|
|
1710
|
+
case 'report':
|
|
1711
|
+
return reportCommand(rest);
|
|
1712
|
+
case 'doctor':
|
|
1713
|
+
return doctorCommand(rest);
|
|
1714
|
+
case 'demo':
|
|
1715
|
+
return demoCommand();
|
|
1716
|
+
case 'version':
|
|
1717
|
+
case '--version':
|
|
1718
|
+
case '-v':
|
|
1719
|
+
return versionCommand();
|
|
1720
|
+
case 'help':
|
|
1721
|
+
return helpCommand(rest);
|
|
1722
|
+
case undefined:
|
|
1723
|
+
case '--help':
|
|
1724
|
+
case '-h':
|
|
1725
|
+
return ok(`${usage}\n`);
|
|
1726
|
+
default:
|
|
1727
|
+
return fail(`cave: unknown command ${JSON.stringify(command)}\n\n${usage}\n`, 2);
|
|
1427
1728
|
}
|
|
1428
1729
|
};
|
|
1429
1730
|
//# sourceMappingURL=cli.js.map
|