@carllee1983/dbcli 1.52.0 → 1.53.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.
@@ -4,6 +4,69 @@ Companion to [SKILL.md](SKILL.md). Exhaustive flags, copy-paste examples, `shell
4
4
 
5
5
  For cross-engine support status, see `docs/feature-matrix.md` in the repository.
6
6
 
7
+ ## Index
8
+
9
+ Jump straight to what you need — this file is long, and reading it end to end is
10
+ never the right move.
11
+
12
+ | Section | What is in it |
13
+ |---|---|
14
+ | [Global options and placement](#global-options-and-placement) | Flags that must precede the command (`--use`, `--config`), and [redirecting output](#redirecting-output). |
15
+ | [Commands](#commands) | Every command, one `###` each — see the command list below. |
16
+ | [Recovery Cookbook](#recovery-cookbook-agent-walkthroughs) | Failure-to-fix walkthroughs S1–S6, the [scenario index](#scenario-index), [risk gate cheat sheet](#risk-gate-cheat-sheet), and [common pitfalls](#common-pitfalls). |
17
+ | [Interactive HTML dashboard](#interactive-html-dashboard) | `--ui` / `--format html`: [entry points](#entry-points), [data injection contract](#data-injection-contract), [`meta` shape](#meta-shape). |
18
+ | [MongoDB Support](#mongodb-support) | Connection shapes, JSON query bodies, write-stage guard. |
19
+ | [Redis Support](#redis-support) | Command permission tiers, size guards, key masking. |
20
+ | [Elasticsearch Support](#elasticsearch-support) | DSL and Lucene queries, scroll export, mapping flattening. |
21
+
22
+ **Commands** —
23
+ [init](#init) ·
24
+ [use](#use) ·
25
+ [list](#list) ·
26
+ [schema](#schema) ·
27
+ [query](#query) ·
28
+ [explain](#explain) ·
29
+ [lint](#lint) ·
30
+ [plan](#plan) ·
31
+ [q](#q) ·
32
+ [queries](#queries) ·
33
+ [insert](#insert) ·
34
+ [update](#update) ·
35
+ [delete](#delete) ·
36
+ [export](#export) ·
37
+ [blacklist](#blacklist) ·
38
+ [check](#check) ·
39
+ [diff](#diff) ·
40
+ [design](#design) ·
41
+ [impact assess](#impact-assess) ·
42
+ [snapshot](#snapshot) ·
43
+ [assert](#assert) ·
44
+ [proxy](#proxy) ·
45
+ [status](#status) ·
46
+ [inspect](#inspect) ·
47
+ [report](#report) ·
48
+ [guide](#guide) ·
49
+ [recovery](#recovery) ·
50
+ [recover](#recover) ·
51
+ [audit](#audit) ·
52
+ [verify](#verify) ·
53
+ [verification](#verification) ·
54
+ [backfill](#backfill) ·
55
+ [evidence](#evidence) ·
56
+ [doctor](#doctor) ·
57
+ [completion](#completion) ·
58
+ [upgrade](#upgrade) ·
59
+ [shell](#dbcli-shell) ·
60
+ [migrate](#migrate) ·
61
+ [semantic](#semantic) ·
62
+ [contract](#contract) ·
63
+ [skill](#skill) ·
64
+ [skill context](#skill-context) ·
65
+ [skill tasks](#skill-tasks-agent-task-packs)
66
+
67
+ Also worth knowing before you connect:
68
+ [Agent configuration trust boundary](#agent-configuration-trust-boundary).
69
+
7
70
  ## Global options and placement
8
71
 
9
72
  These options are available on the root `dbcli` command. Root-level options must
@@ -561,13 +624,15 @@ dbcli q @analytics/revenue --param days=30 --format html > report.html
561
624
  - `--ui` — open the rendered HTML dashboard in the system browser (implies `--format html`; writes to a temp file then invokes `open` / `xdg-open` / `start`)
562
625
  - `--param <key=value>` — pass a parameter (repeatable)
563
626
  - `--param-file <path>` — JSON object whose keys are param names
564
- - `--no-limit` — skip the `SELECT * FROM (…) AS _dbcli_guard LIMIT 1000` wrap
627
+ - `--no-limit` — skip the `SELECT * FROM (…) AS _dbcli_guard LIMIT 1001` wrap (the effective cap is 1000; one extra row is fetched to detect truncation)
565
628
  - `--dry-run` — print the bound SQL + values without executing
566
- - `--use <name>` — pick a v2 named connection
567
629
  - `--slow-ms <number>` — passive slow-query hint threshold (default `1000`; `0` disables). Same contract as `query` — see "Passive slow-query hint" there
568
630
  - `--recovery` — emit a `RecoveryEnvelope` on failure (see `recover`)
569
631
  - `--verify` — run the snippet's verification assertions after execution (only if the snippet defines them)
570
632
 
633
+ `q` has no command-level `--use`. To run a snippet against a v2 named connection,
634
+ use the global form: `dbcli --use <name> q @<snippet>`.
635
+
571
636
  **Permission:** query-only+
572
637
 
573
638
  #### Snippet file format
@@ -691,8 +756,9 @@ Size guard: `LRANGE` / `ZRANGE` stop overridden when `< 0` or `> 1000`; `SCAN` /
691
756
  ##### MongoDB snippets
692
757
 
693
758
  File extension: `.mongodb.sql`. Frontmatter must declare `engine: mongodb` and
694
- `operation: find` or `operation: aggregate`. `target: <collection>` provides a default
695
- collection that `dbcli q --collection <name>` can override. The body is JSON: an object
759
+ `operation: find` or `operation: aggregate`. `target: <collection>` declares the
760
+ collection the snippet runs against; the CLI has no flag to override it, so a different
761
+ collection means a different snippet. The body is JSON: an object
696
762
  for `find` and an array for `aggregate`. Each `{{param}}` placeholder is JSON-encoded
697
763
  at substitution time — strings are quoted and escaped, so an attacker-supplied string
698
764
  cannot escape into operator position.
@@ -1126,6 +1192,7 @@ dbcli design validate [--file <path>] [--format <format>]
1126
1192
  dbcli design render [--file <path>] [--format <format>]
1127
1193
  dbcli design diff (--against-cache | --against-orm <paths>) [options]
1128
1194
  dbcli design propose (--against-cache | --against-orm <paths>) [options]
1195
+ dbcli impact assess --design <path> (--against-cache | --against-orm <paths>) --output <path> [options]
1129
1196
  ```
1130
1197
 
1131
1198
  ```bash
@@ -1137,6 +1204,7 @@ dbcli design render --format mermaid
1137
1204
  dbcli design diff --against-cache --format markdown
1138
1205
  dbcli design diff --against-orm ./prisma/schema.prisma --format markdown
1139
1206
  dbcli design propose --against-orm ./prisma/schema.prisma --format markdown
1207
+ dbcli impact assess --design ./dbcli.design.json --against-cache --output ./impact.json --fail-on warn
1140
1208
  ```
1141
1209
 
1142
1210
  | Option | Applies to | Default | Meaning |
@@ -1153,8 +1221,14 @@ dbcli design propose --against-orm ./prisma/schema.prisma --format markdown
1153
1221
  `diff` and `propose` require **exactly one** comparison target; passing both or
1154
1222
  neither is an error.
1155
1223
 
1224
+ ### impact assess
1225
+
1226
+ Writes an offline JSON or Markdown report for the known declared impact of a design change. It requires `--design`, exactly one baseline (`--against-cache` or `--against-orm`), and an explicit workspace-contained `--output`. `--format` is `json` (default) or `markdown`; `--fail-on` is `error`, `warn`, or `never` (default). The threshold changes only the successful command exit code after the report is written. The report is limited to declared/partial coverage and never claims complete coverage. It may join the optional reviewed `dbcli.data-access.json` manifest only after validating its canonical semantic references and existing workspace-relative source paths; it never reads those sources. An optional explicit `--events <path>` is bounded and streamed through a redaction-first projection that retains recent safe table metadata only. It never starts a proxy, reads a rotated log, renders SQL/literals/errors/sessions/paths, or makes the command fail solely because workload evidence is absent or advisory. It reads no database, executes no SQL, and never reads saved-query bodies.
1227
+
1156
1228
  #### Artifact shape
1157
1229
 
1230
+ This example validates clean (0 errors, 0 warnings):
1231
+
1158
1232
  ```json
1159
1233
  {
1160
1234
  "version": 1,
@@ -1166,14 +1240,24 @@ neither is an error.
1166
1240
  "description": "Completed purchases.",
1167
1241
  "fields": [
1168
1242
  { "name": "id", "type": "bigint", "nullable": false, "primaryKey": true, "unique": true },
1169
- { "name": "customer_id", "type": "bigint", "nullable": false, "primaryKey": false, "unique": false }
1243
+ { "name": "customer_id", "type": "bigint", "nullable": false },
1244
+ { "name": "created_at", "type": "timestamptz", "nullable": false }
1170
1245
  ],
1171
- "indexes": [{ "name": "orders_customer_idx", "columns": ["customer_id"], "unique": false }]
1246
+ "indexes": [
1247
+ { "name": "orders_customer_idx", "columns": ["customer_id", "created_at"], "unique": false }
1248
+ ]
1249
+ },
1250
+ {
1251
+ "name": "customers",
1252
+ "table": "customers",
1253
+ "fields": [
1254
+ { "name": "id", "type": "bigint", "nullable": false, "primaryKey": true, "unique": true }
1255
+ ]
1172
1256
  }
1173
1257
  ],
1174
1258
  "relationships": [
1175
1259
  {
1176
- "name": "orders_customer",
1260
+ "name": "orders-customer",
1177
1261
  "from": { "model": "orders", "field": "customer_id" },
1178
1262
  "to": { "model": "customers", "field": "id" },
1179
1263
  "cardinality": "many-to-one"
@@ -1188,11 +1272,38 @@ It holds no SQL, credentials, rows, or provider configuration. `design init`
1188
1272
  emits this envelope with empty `models`, `relationships`, `accessPatterns`, and
1189
1273
  `decisions`.
1190
1274
 
1275
+ #### Naming and limits
1276
+
1277
+ Two different naming rules apply, and mixing them up is the most common way an
1278
+ artifact fails before any review rule runs.
1279
+
1280
+ | Applies to | Rule |
1281
+ |---|---|
1282
+ | `models[].name`, `relationships[].name`, `relationships[].from/to.model`, `accessPatterns[].model`, `decisions[].name` | lowercase kebab-case, `^[a-z][a-z0-9-]*$` — underscores are rejected |
1283
+ | `models[].table`, `fields[].name`, `indexes[].name`, `indexes[].columns[]`, `filters[]`, `sort[]` | SQL identifier, `^[A-Za-z_][A-Za-z0-9_]*$` |
1284
+
1285
+ Relationship endpoints reference a **model name**, not a table name. Every object
1286
+ is strict: an unknown key is an error, not ignored. `description` and `rationale`
1287
+ are 1–1000 characters and must not contain SQL keywords or a connection string —
1288
+ "rows we delete after 30 days" is rejected for the word `delete`. `fields[].type`
1289
+ is at most 100 characters with no `;` or newline. `primaryKey`, `unique`,
1290
+ `indexes`, `filters`, `sort`, `relationships`, `accessPatterns`, and `decisions`
1291
+ may all be omitted.
1292
+
1293
+ Limits: file 256 KiB, 100 models, 100 fields per model, 200 relationships,
1294
+ 200 access patterns, 100 decisions, 1–16 columns per index, ≤16 entries in
1295
+ `filters` and `sort`.
1296
+
1191
1297
  #### Review findings
1192
1298
 
1193
1299
  `validate` is fail-closed: any `error` finding exits `1`, and `render`, `diff`,
1194
1300
  and `propose` refuse to do their work while errors remain.
1195
1301
 
1302
+ Structural problems — malformed JSON, an unknown key, a naming or type violation,
1303
+ a missing file, or a file over 256 KiB — are rejected before review runs and are
1304
+ reported as a single `INVALID_ARTIFACT` finding (`error`) whose `path` points at
1305
+ the offending JSON location. None of the codes below appear in that case.
1306
+
1196
1307
  | Severity | Codes |
1197
1308
  |---|---|
1198
1309
  | `error` | `NO_MODELS`, `DUPLICATE_MODEL`, `DUPLICATE_TABLE`, `DUPLICATE_FIELD`, `PRIMARY_KEY_COUNT`, `NULLABLE_PRIMARY_KEY`, `UNKNOWN_INDEX_FIELD`, `DUPLICATE_RELATIONSHIP`, `REVERSE_RELATIONSHIP`, `UNKNOWN_RELATIONSHIP_MODEL`, `UNKNOWN_RELATIONSHIP_FIELD`, `RELATIONSHIP_TYPE_MISMATCH`, `MANY_TO_MANY_REQUIRES_BRIDGE`, `ONE_TO_ONE_REQUIRES_UNIQUE_FK`, `UNKNOWN_ACCESS_MODEL`, `UNKNOWN_ACCESS_FIELD` |
@@ -1297,7 +1408,7 @@ Opt-in flag trio that persists a **VerificationArtifact JSON** (schema v1) under
1297
1408
  | Flag | Required | Description |
1298
1409
  | :--- | :--- | :--- |
1299
1410
  | `--write-verification-artifact` | opt-in | Trigger artifact write. No-op when no verdict has been produced. |
1300
- | `--verification-subject <kind:name>` | yes (when flag is set) | Subject identifier. Format: `<kind>:<name>`. Allowed kinds: `recovery`, `task-pack`, `assertion`, `migration`, `backfill`, `manual`. |
1411
+ | `--verification-subject <kind:name>` | yes (when flag is set) | Subject identifier. Format: `<kind>:<name>`. Allowed kinds: `recovery`, `task-pack`, `assertion`, `migration`, `backfill`, `table`, `manual`. |
1301
1412
  | `--verification-summary <text>` | no | Free-text summary line stored in the artifact. Default when pass: "Assertion verified the expected state." Default when fail: "Assertion did not verify the expected state." |
1302
1413
 
1303
1414
  **Output contract:**
@@ -1559,7 +1670,7 @@ Examples:
1559
1670
 
1560
1671
  Boundaries:
1561
1672
  - Recovery only **suggests** commands; agents (or humans) execute them. No automatic remediation in v1.15.0.
1562
- - As of v1.16.0, `--recovery` is honored on `query`, `q`, `insert`, `update`, `delete`, `export`, `schema`, and `inspect`. Other commands (`report`, `guide`, `doctor`, `migrate`, `init`, `use`, `status`, `list`, `check`, `diff`, `plan`, `shell`, `blacklist`, `completion`, `upgrade`, `skill`) keep their existing error behavior.
1673
+ - `--recovery` is honored on `query`, `q`, `insert`, `update`, `delete`, `export`, `schema`, `inspect`, `lint`, and `diff`. Other commands (`report`, `guide`, `doctor`, `migrate`, `init`, `use`, `status`, `list`, `check`, `plan`, `shell`, `blacklist`, `completion`, `upgrade`, `skill`) keep their existing error behavior.
1563
1674
  - `dbcli inspect --require-schema-cache` throws `SCHEMA_CACHE_MISSING` when the active SQL connection has no usable schema cache. Combine with `--recovery` for the structured envelope.
1564
1675
  - `BLACKLIST_COLUMN_WRITE` and `PERMISSION_DENIED` envelopes prepend a `risk: 'dry-run'` step (e.g. `dbcli insert <table> --dry-run`) when the failing operation was an INSERT / UPDATE / DELETE.
1565
1676
  - Recovery steps reuse the v1.14.0 `GuideStep` shape, including the full `risk` enum (`readonly` / `dry-run` / `write` / `unknown`).
@@ -1593,7 +1704,7 @@ Boundaries:
1593
1704
  |---|---|---|
1594
1705
  | `readonly` | local read-only | `dbcli inspect`, `dbcli doctor`, `dbcli blacklist list`, `dbcli schema <table>` |
1595
1706
  | `dry-run` | write subcommand invoked with `--dry-run` | `dbcli update orders --where id=1 --dry-run`, `dbcli q @x --dry-run` |
1596
- | `local-write` | writes local config / cache / blacklist | `dbcli blacklist remove <table>`, `dbcli use <name>`, `dbcli schema --refresh` |
1707
+ | `local-write` | writes local config / cache / blacklist | `dbcli blacklist table remove <table>`, `dbcli use <name>`, `dbcli schema --refresh` |
1597
1708
  | `db-write` | mutates the connected database | `dbcli update orders --where id=1 --set …` (no `--dry-run`), `dbcli q @x` (no `--dry-run`) |
1598
1709
  | `interactive` | requires TTY | `dbcli init`, `dbcli init --force` |
1599
1710
 
@@ -1746,7 +1857,7 @@ dbcli recover --next --after-step 1 --result '{"status":"ok"}' --format markdown
1746
1857
 
1747
1858
  (v1.20.0+) Inspect, query, and manage the per-connection audit log written to `.dbcli/audit/<connection>.jsonl`.
1748
1859
 
1749
- Audit entries are metadata-only by design — never raw SQL bodies, `--param` values, or result cell contents (D3 lock). Redaction is sourced from `tests/helpers/sensitive-output.ts` (same source as `inspect` / `guide` / `recover` agent contracts).
1860
+ Audit entries are metadata-only by design — never raw SQL bodies, `--param` values, or result cell contents (D3 lock). Redaction is sourced from `src/utils/redaction.ts` (same source as `inspect` / `guide` / `recover` agent contracts).
1750
1861
 
1751
1862
  #### Subcommands
1752
1863
 
@@ -1783,7 +1894,9 @@ Examples:
1783
1894
  | `<id-prefix>` | Positional. UUID or prefix ≥ 4 characters; ambiguous prefix exits 1 with disambiguation hint; prefix < 4 chars exits 1. | — |
1784
1895
  | `--recovery-ref <id>` | Find the audit entry whose `recovery_ref` field matches this id (exact, not prefix). Mutually exclusive with positional `<id-prefix>` (D-38). | — |
1785
1896
  | `--all` | Search across all connections. Output is an envelope `{ connection, entry }` (single-hit also envelope, for shape stability — D-36). | off |
1786
- | `--no-brief` | Disable brief mode when a higher-level default enables it. | off |
1897
+ | `--brief` | Trim `metadata` and `redacted_query` from the entry. | off |
1898
+ | `--for-agent` | Shortcut for `--format json --brief`. | off |
1899
+ | `--no-brief` | Disable brief mode when a higher-level default enables it (e.g. `--for-agent`). | off |
1787
1900
  | `--format <fmt>` | `table` \| `json`. | `table` |
1788
1901
 
1789
1902
  Examples:
@@ -1817,7 +1930,7 @@ Output reports: writer enabled/disabled, last write result, file-lock state, rot
1817
1930
  #### Boundaries
1818
1931
 
1819
1932
  - Entries are append-only JSONL; rotation triggers at `~10 MB` or `~1000` entries (whichever first). Previous segment is preserved as `.jsonl.1`.
1820
- - Bi-directional `recovery_ref` / `audit_ref` linkage is wired on every command that accepts `--recovery`: `query`, `inspect`, `insert`, `update`, `delete`, `export`, `q`, and `schema`. Use `audit tail --recovery-ref <id>` to find the audit entry an envelope was emitted alongside.
1933
+ - Bi-directional `recovery_ref` / `audit_ref` linkage is wired on every command that accepts `--recovery`: `query`, `inspect`, `insert`, `update`, `delete`, `export`, `q`, and `schema`. Use `audit show --recovery-ref <id>` to find the audit entry an envelope was emitted alongside.
1821
1934
  - Audit writer failures are non-fatal (D6): main command result and exit code are preserved; a stderr warning is emitted. `audit health` surfaces the failure reason.
1822
1935
  - Reader truncation tolerance: a crash-truncated last line is skipped with a stderr warn `[dbcli audit] skipping truncated last line in <file>`; a mid-file non-JSON line is treated as corruption, exits 1, and points at `dbcli audit clear`.
1823
1936
 
@@ -1835,7 +1948,7 @@ Output reports: writer enabled/disabled, last write result, file-lock state, rot
1835
1948
  ### verify
1836
1949
 
1837
1950
  Run a verification scenario. `verify` **runs** verification scenarios (safe-backfill,
1838
- migration, rollback) and never executes writes/DDL. `verification` **inspects and manages**
1951
+ migration, rollback, constraint) and never executes writes/DDL. `verification` **inspects and manages**
1839
1952
  the local result artifacts those scenarios produce under `.dbcli/verification/`.
1840
1953
 
1841
1954
  ```bash
@@ -1847,7 +1960,8 @@ dbcli verify safe-backfill \
1847
1960
  --expect "value == 0"
1848
1961
 
1849
1962
  # After-write: re-run guards, run the read-back assertion, write a v1 artifact.
1850
- dbcli verify safe-backfill ... --after-write
1963
+ # An optional receipt is provenance only, never approval to execute a write.
1964
+ dbcli verify safe-backfill ... --after-write --evidence-receipt .dbcli/evidence/verify-receipt.json
1851
1965
 
1852
1966
  # JSON for agents.
1853
1967
  dbcli verify safe-backfill ... --format json
@@ -1855,7 +1969,11 @@ dbcli verify safe-backfill ... --format json
1855
1969
 
1856
1970
  Options: `--table` (req), `--query` (req, analyzed not executed), `--verify-query`
1857
1971
  (req, **plain SELECT only**), `--expect` (req), `--after-write`, `--format <table|json>`,
1858
- `--subject-name <name>`, `--summary <text>`.
1972
+ `--subject-name <name>`, `--summary <text>`, `--evidence-receipt <workspace-relative-path>`
1973
+ (after-write only). A receipt is safe provenance for the already-executed verification,
1974
+ not approval to execute a write. Its `succeeded`/`failed` outcome remains distinct from
1975
+ the artifact status (`verified`, `not_verified`, `indeterminate`, or `blocked`); task-pack
1976
+ `planned` evidence stays plan-only.
1859
1977
 
1860
1978
  Guard constraints (fail closed): `--verify-query` must be a **plain `SELECT`** —
1861
1979
  `EXPLAIN`/`EXPLAIN ANALYZE`, `SHOW`, `DESCRIBE`, and data-modifying CTEs are rejected
@@ -2078,7 +2196,7 @@ dbcli verification list --include-invalid --format json
2078
2196
  | `--format <json\|table>` | Output format. | `json` |
2079
2197
  | `--limit <n>` | Maximum number of entries to return. | `20` |
2080
2198
  | `--status <status>` | Filter by status. One of: `verified`, `not_verified`, `indeterminate`, `blocked`. | all |
2081
- | `--subject <kind[:name]>` | Filter by subject kind or exact `kind:name`. Allowed kinds: `recovery`, `task-pack`, `assertion`, `migration`, `backfill`, `manual`. | all |
2199
+ | `--subject <kind[:name]>` | Filter by subject kind or exact `kind:name`. Allowed kinds: `recovery`, `task-pack`, `assertion`, `migration`, `backfill`, `table`, `manual`. | all |
2082
2200
  | `--include-invalid` | Surface malformed artifact files (normally skipped silently). Invalid files are returned as a separate top-level `invalid` array in JSON output, each entry shaped `{ "path": "...", "filename": "...", "error": "..." }`. When off, `invalid` is `[]`. | off |
2083
2201
 
2084
2202
  **Missing directory:** if `.dbcli/verification/` does not exist, exits `0` with an
@@ -2192,6 +2310,7 @@ includes `storageDir`, `dryRun`, `cutoff`, `criteria`, `protected`, `candidates`
2192
2310
  | `assertion` | General-purpose inline assertions. |
2193
2311
  | `migration` | Schema migration pre/post checks. |
2194
2312
  | `backfill` | Data backfill verification assertions. |
2313
+ | `table` | `verify constraint` artifacts — the subject name is the table checked. |
2195
2314
  | `manual` | Manually triggered or ad-hoc verification runs. |
2196
2315
 
2197
2316
  **Storage root:** `<cwd>/.dbcli/verification/` (cwd-relative; independent of `--config`).
@@ -2359,6 +2478,66 @@ dbcli migrate drop-enum status --execute --force
2359
2478
 
2360
2479
  **AI agent note:** Always use dry-run first (no `--execute`) to preview generated SQL. Only add `--execute` after confirming the SQL is correct. For DROP operations, both `--execute` and `--force` are required.
2361
2480
 
2481
+ ### evidence
2482
+
2483
+ Compose a canonical, offline **Evidence Pack** from existing verification artifacts
2484
+ and audit entries. This command never opens a database connection. A pack retains only
2485
+ safe pointers and outcome fields: it excludes SQL, targets, audit metadata, verification
2486
+ summaries, result data, and credentials. Claims are external statements, never dbcli
2487
+ verification verdicts.
2488
+
2489
+ #### `evidence compose`
2490
+
2491
+ ```bash
2492
+ dbcli evidence compose --claims ./claims.json --verification ver_abcd --audit 1a2b \
2493
+ --receipt .dbcli/evidence/verify-receipt.json \
2494
+ --output .dbcli/evidence/review.json --format json
2495
+ ```
2496
+
2497
+ | Flag | Purpose | Default |
2498
+ |---|---|---|
2499
+ | `--claims <file>` | Required JSON file with exactly `subject` and `claims`; every claim has an `id` and plain-language `text`. SQL-shaped text, credentials, error content, and blacklisted identifiers are rejected. | — |
2500
+ | `--verification <selector...>` | One or more verification artifact ids, unique prefixes, filenames, or in-bounds paths. | none |
2501
+ | `--audit <selector...>` | One or more audit ids or unique prefixes (minimum four characters) from the active connection. | none |
2502
+ | `--receipt <path...>` | Explicit workspace-relative receipt path(s). Receipts contribute safe provenance only; they are not execution approval. | none |
2503
+ | `--output <path>` | Required new JSON path under the current workspace. Existing files and paths outside the workspace are refused. | — |
2504
+ | `--format <json\|markdown>` | Compose receipt format printed to stdout. | `json` |
2505
+
2506
+ At least one `--verification`, `--audit`, or `--receipt` reference is required. The resulting pack
2507
+ contains a canonical SHA-256 integrity digest and `coverage.completeForDeclaredEvidence:
2508
+ true` for its explicitly selected references.
2509
+
2510
+ #### `evidence validate`
2511
+
2512
+ ```bash
2513
+ dbcli evidence validate --file .dbcli/evidence/review.json --format json
2514
+ ```
2515
+
2516
+ | Flag | Purpose | Default |
2517
+ |---|---|---|
2518
+ | `--file <path>` | Required evidence-pack JSON file. | — |
2519
+ | `--format <json\|markdown>` | Validation report format. | `json` |
2520
+
2521
+ Exit `0` when digest and all selected sources are valid. If a referenced audit or
2522
+ verification artifact later rotates, is cleared, disappears, or belongs to a different
2523
+ active connection, output stays parseable with `integrity: "valid"` and
2524
+ `references: "source-expired"`, then exits `1`.
2525
+
2526
+ #### `evidence render`
2527
+
2528
+ ```bash
2529
+ dbcli evidence render --file .dbcli/evidence/review.json --format markdown
2530
+ ```
2531
+
2532
+ | Flag | Purpose | Default |
2533
+ |---|---|---|
2534
+ | `--file <path>` | Required evidence-pack JSON file. | — |
2535
+ | `--format <json\|markdown>` | Render format. | `markdown` |
2536
+
2537
+ `render` validates the pack digest and active blacklist policy but does not resolve its
2538
+ original references. It is therefore available for historical review after `validate`
2539
+ reports `source-expired`, unless an exposed pack field is now blacklisted.
2540
+
2362
2541
  ### semantic
2363
2542
 
2364
2543
  Validate or print the optional, version-controlled `dbcli.semantic.json` in the
@@ -2485,6 +2664,39 @@ limits, audit, and recovery safeguards remain in force.
2485
2664
 
2486
2665
  **Permission:** n/a (local files only; no database connection).
2487
2666
 
2667
+ ### contract
2668
+
2669
+ Inspect the optional, version-controlled `dbcli.contracts.json` without opening a
2670
+ database connection. A contract adds a reviewed owner and descriptive evidence policy
2671
+ to canonical semantic references; it is not an executable data contract, assertion,
2672
+ query, or verification scenario.
2673
+
2674
+ ```bash
2675
+ dbcli contract validate --format json
2676
+ dbcli contract context --format json
2677
+ dbcli contract context --format markdown
2678
+ dbcli contract search customer --format json
2679
+ dbcli contract drift --format json
2680
+ ```
2681
+
2682
+ The strict v1 artifact contains `version` and `contracts`. Each contract has a unique
2683
+ canonical `name`, `status` (`draft`, `approved`, or `deprecated`), bounded plain-text
2684
+ `description` and `owner`, one or more canonical semantic `subjects`, optional aliases,
2685
+ and an `evidencePolicy` of `none`, `receipt-required`, or `verification-required`.
2686
+ Subjects must remain in the existing visible semantic registry; protected identifiers,
2687
+ unknown keys, duplicate names or subjects, SQL-like text, credentials, and stale
2688
+ references fail closed without exposing protected names.
2689
+
2690
+ `contract validate` requires an explicit valid artifact. `contract context` and
2691
+ `contract search` return only valid approved contracts; draft and deprecated contracts
2692
+ remain local review artifacts. `contract drift` reports `valid`, `stale`, `invalid`, or
2693
+ `unavailable` evidence offline and exits non-zero except for `valid`. A missing default
2694
+ file is allowed by `skill context` and leaves ordinary semantic context unchanged; a
2695
+ present invalid file fails closed. No contract command writes a file, opens a database
2696
+ connection, widens a `QueryDraft`, or changes permission/blacklist behavior.
2697
+
2698
+ **Permission:** n/a (local files only; no database connection).
2699
+
2488
2700
  ### skill
2489
2701
 
2490
2702
  Emit `SKILL.md` (and the companion `reference.md`) to stdout, a file, or an
@@ -3024,9 +3236,9 @@ Permission is derived from the command's first token (case-insensitive). Unknown
3024
3236
 
3025
3237
  | Tier | Commands |
3026
3238
  |------|----------|
3027
- | `query-only` | `GET`, `MGET`, `STRLEN`, `EXISTS`, `TTL`, `PTTL`, `TYPE`, `SCAN`, `HGET`, `HGETALL`, `HKEYS`, `HVALS`, `HLEN`, `HEXISTS`, `HMGET`, `LRANGE`, `LLEN`, `LINDEX`, `SMEMBERS`, `SCARD`, `SISMEMBER`, `ZRANGE`, `ZREVRANGE`, `ZRANGEBYSCORE`, `ZCARD`, `ZSCORE`, `PING`, `ECHO` |
3028
- | `read-write` | `SET`, `SETEX`, `SETNX`, `PSETEX`, `MSET`, `MSETNX`, `APPEND`, `INCR`/`INCRBY`, `DECR`/`DECRBY`, `HSET`/`HSETNX`/`HMSET`/`HINCRBY`, `LPUSH`/`RPUSH`/`LPOP`/`RPOP`/`LSET`, `SADD`/`SREM`, `ZADD`/`ZREM`, `EXPIRE`/`EXPIREAT`/`PEXPIRE`/`PERSIST`, `RENAME` |
3029
- | `data-admin` | `DEL`, `UNLINK`, `HDEL` |
3239
+ | `query-only` | `GET`, `MGET`, `STRLEN`, `EXISTS`, `TTL`, `PTTL`, `TYPE`, `SCAN`, `HGET`, `HGETALL`, `HKEYS`, `HVALS`, `HLEN`, `HEXISTS`, `HMGET`, `LRANGE`, `LLEN`, `LINDEX`, `SMEMBERS`, `SCARD`, `SISMEMBER`, `ZRANGE`, `ZREVRANGE`, `ZRANGEBYSCORE`, `ZCARD`, `ZSCORE`, `XLEN`, `XREAD`, `XRANGE`, `XREVRANGE`, `PING`, `ECHO` |
3240
+ | `read-write` | `SET`, `SETEX`, `SETNX`, `PSETEX`, `MSET`, `MSETNX`, `APPEND`, `INCR`/`INCRBY`, `DECR`/`DECRBY`, `HSET`/`HSETNX`/`HMSET`/`HINCRBY`, `LPUSH`/`RPUSH`/`LPOP`/`RPOP`/`LSET`/`LREM`, `SADD`/`SREM`, `ZADD`/`ZREM`, `XADD`, `EXPIRE`/`EXPIREAT`/`PEXPIRE`/`PERSIST`, `RENAME` |
3241
+ | `data-admin` | `DEL`, `UNLINK`, `HDEL`, `XDEL` |
3030
3242
  | `admin` | `FLUSHDB`, `FLUSHALL`, `CONFIG`, `INFO`, `CLIENT`, `DEBUG`, `SHUTDOWN`, `KEYS`, `MONITOR`, `SAVE`, `BGSAVE`, `BGREWRITEAOF`, `REPLICAOF`, `SLAVEOF`, `ACL` |
3031
3243
 
3032
3244
  ### Schema inspection
@@ -3237,5 +3449,5 @@ GET /orders/_search
3237
3449
 
3238
3450
  - Writes (`insert`/`update`/`delete`) are not exposed yet — the adapter implements them, but the CLI currently only routes them for SQL and MongoDB. Read-only `export` (v1.22) and the interactive `shell` (v1.22) are available.
3239
3451
  - No `_search/scroll` or PIT pagination at the CLI layer; large pulls need a saved external script.
3240
- - `check`, `diff`, `migrate`, and `q` are SQL-only and exit with errors (or fall through to a generic "unsupported" path).
3452
+ - `check`, `diff`, and `migrate` are SQL-only and exit with errors (or fall through to a generic "unsupported" path). `q` **is** supported — Elasticsearch snippets use the `.elasticsearch.sql` extension (see `@diag/es-cluster-health`).
3241
3453
  - Blacklist column rules are applied to flattened hit rows on `query`; table-level blacklist rejects an index up front.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,44 @@ All notable changes to dbcli are documented here.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.53.0] - 2026-08-09 - Offline evidence, semantic contracts, and impact assessment
9
+
10
+ ### Added
11
+
12
+ - **Offline evidence packs.** `dbcli evidence compose`, `validate`, and `render` create, verify, and render workspace-contained evidence packs from safe claim text plus existing verification artifacts, audit entries, and optional assert receipts. Packs omit SQL, rows, targets, credentials, audit metadata, and verification summaries; source retention loss remains visible without preventing historical rendering.
13
+ - **Evidence receipts for post-write assertions.** `assert --evidence-receipt <path>` atomically records safe provenance only after the verdict, audit attempt, and optional verification artifact are authoritative. Receipts are workspace-contained, contain no SQL or returned data, cannot be used as execution approval, and may be composed into an evidence pack.
14
+ - **Reviewable semantic contracts.** `dbcli contract validate|context|search|drift` governs optional `dbcli.contracts.json` evidence expectations for canonical semantic terms. The commands are offline and read-only; only valid approved contracts enter ordinary agent context.
15
+ - **Offline impact assessment.** `dbcli impact assess` creates a declared-coverage report for a design change against exactly one local schema-cache or ORM baseline, optionally incorporating reviewed data-access metadata and redaction-first proxy workload evidence. It never connects, executes SQL, or claims complete coverage.
16
+
17
+ ### Changed
18
+
19
+ - **Shared execution and adapter boundaries.** Query execution now uses an injectable command runtime, SQL adapters share readiness and driver-error handling, and doctor accepts a non-SQL collector runtime. These internal changes keep the CLI behavior stable while making offline evidence and impact workflows testable.
20
+ - **Documentation and agent skills cover the new surfaces.** English and Traditional Chinese Markdown and HTML guides, installed skill copies, and reference material document evidence packs, assert receipts, semantic contracts, and impact assessment.
21
+
22
+ ### Fixed
23
+
24
+ - **Release audit no longer resolves a vulnerable `nanoid`.** The build-only PostCSS and Tailwind dependencies now resolve `nanoid@3.3.18`, satisfying the security advisory without adding a runtime dependency.
25
+
26
+ ## [1.52.1] - 2026-08-08 - Skill audit: correct claims, per-platform install, drift gate
27
+
28
+ ### Fixed
29
+
30
+ - **The skill documented three flags that do not exist.** `q --use` (the global `dbcli --use <name> q` form is the real one), `q --collection` (a MongoDB snippet's `target:` is the only collection source), and `audit tail --recovery-ref` (it lives on `audit show`). The same wrong `audit tail --recovery-ref` is corrected in `docs/user` (en/zh, Markdown and HTML).
31
+ - **The `design` artifact example failed its own validator.** It is replaced with one that validates clean, and the naming rules it has to satisfy are now documented: lowercase kebab-case for design names versus SQL identifiers for tables and columns, endpoints referencing a model rather than a table, strict objects, descriptions that must not contain SQL keywords, and the size limits. Structural violations report `INVALID_ARTIFACT`, a code the severity table did not list.
32
+ - **Stale lists corrected against the CLI.** `--recovery` covers `lint` and `diff`; verification subject kinds include `table` (what `verify constraint` writes); the Redis permission table includes `XLEN` / `XREAD` / `XRANGE` / `XREVRANGE` / `XADD` / `XDEL` / `LREM`; `audit show` lists `--brief` and `--for-agent`; the snippet guard emits `LIMIT 1001`, fetching one extra row to detect truncation. Elasticsearch supports `q`, and the 10 000 bound belongs to `query` — `export --no-limit` streams via the scroll API. `schema --help` claimed `--sample-size` defaults to 50; it is 100.
33
+ - **`design` was unreachable from the skill entry point.** `SKILL.md` did not mention it at all, so an agent asked to design or review a schema would hand-write DDL and bypass the review-only `propose` contract. It now has a command row, both workflows, and a guardrail that a proposed plan is never executed.
34
+ - **Six drifts between the English and Traditional Chinese skills.** The most serious dropped the permission-tier semantics (multi-statement SQL rejected below `admin`, snippets free of write and DDL keywords, `$out` / `$merge` requiring `data-admin`). The MongoDB connection guidance also disagreed between languages — field-by-field is the recommendation, full URI the escape hatch — and the zh-TW side was missing the env-refs MongoDB exception, the `uri`-wins-silently gotcha, `--slow-ms` on `query` and `q`, and the `proxy analyze` action guidance.
35
+ - **Cursor and Windsurf installs were the Claude skill verbatim.** Windsurf does not parse frontmatter, so roughly 900 characters of `description:` were read as rule text; Cursor reads `description` / `globs` / `alwaysApply` and received none of them. Both platforms keep `reference.md` outside the primary file's directory, so every mention of it resolved to nothing. `dbcli skill --install` now shapes the file per platform — Cursor as an Agent Requested rule, Windsurf with the frontmatter stripped and the description kept as prose — and repoints the reference path. Recognizing an existing dbcli install no longer depends on the frontmatter, so a Windsurf reinstall stops backing up dbcli's own file. See ADR 0006.
36
+
37
+ ### Added
38
+
39
+ - **`reference.md` has an index.** 3300 lines previously offered no way in but a full read or a guessed grep, and the skill pointed at it in prose ("reference.md Redis section"). Those pointers are real anchors now, and a test derives the anchors from the headings so a renamed heading cannot break them silently.
40
+
41
+ ### Changed
42
+
43
+ - **The bilingual parity gate compares content, not just shape.** It checked heading levels, fence counts, table rows, and a curated token list for mere presence — every drift above kept that structure intact. It now compares per-section counts of every code token and list item; run against 1.52.0 it reports 48 problems it used to pass. Its success message no longer reads as "the docs are aligned" when it only checked the skeleton.
44
+ - **The skill entry point carries less that an agent cannot act on.** The always-loaded `description` drops from 990 to 626 characters with every trigger branch intact, release markers such as `(v1.23)` and an internal ticket id are gone (an agent has exactly one installed version), and the `proxy` row's flag wall becomes an anchor.
45
+
8
46
  ## [1.52.0] - 2026-08-07 - Offline database design assistant and slow-query hints
9
47
 
10
48
  ### Added