@carllee1983/dbcli 1.48.0 → 1.50.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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dbcli-agent",
3
- "version": "1.48.0",
3
+ "version": "1.50.0",
4
4
  "description": "Database CLI skill and command reference for AI agents.",
5
5
  "author": {
6
6
  "name": "Carl Lee",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dbcli-agent",
3
- "version": "1.48.0",
3
+ "version": "1.50.0",
4
4
  "description": "Database CLI skill and command reference for AI agents",
5
5
  "author": {
6
6
  "name": "Carl Lee",
@@ -26,11 +26,7 @@
26
26
  "longDescription": "Installs the dbcli agent skill and reference guide so Codex can inspect schemas, query databases, respect blacklist boundaries, and recover from database errors through the dbcli command workflow.",
27
27
  "developerName": "Carl Lee",
28
28
  "category": "Productivity",
29
- "capabilities": [
30
- "Database",
31
- "Local CLI",
32
- "Agent Skill"
33
- ],
29
+ "capabilities": ["Database", "Local CLI", "Agent Skill"],
34
30
  "websiteURL": "https://github.com/CarlLee1983/dbcli",
35
31
  "defaultPrompt": [
36
32
  "Inspect my database with dbcli.",
@@ -363,7 +363,7 @@ Full flags and edge cases: see [reference.md](reference.md) `init` section.
363
363
  | `assert` | query-only+ | **(v1.25)** SQL only. Verify an invariant; exit 1 on failure unless `--no-fail`. `--expect "rows>0\|value==X\|col:c not null\|unique\|between a and b\|>= n"`, `--vs <query> --compare rows\|value` (reconcile), `--against <snapshot> --tolerance <pct>`. |
364
364
  | `verification` | n/a | Inspect and manage local verification artifacts. `list` / `show <id-or-path>` / `summary` are read-only; `prune` is dry-run by default and deletes only with `--execute --force`. Reads `<cwd>/.dbcli/verification/`; no DB connection, no audit writes. |
365
365
  | `backfill artifact` | n/a | Build a bounded, reviewable source-to-SQL backfill artifact from JSON. Includes source/target identity, blacklist/schema preflight, read-back verification, and rollback hints; dry-run only and never executes writes. |
366
- | `proxy` | n/a | **(v1.26)** MySQL/MariaDB/PostgreSQL only. Local-dev observability proxy — relays app traffic to the real DB and appends query/latency/byte/error events to `.dbcli/proxy/events.jsonl`. Subcommands: `mysql` \| `mariadb` \| `postgresql`. `--listen`, `--target`, `--events`, `--slow-ms` (default `1000`), `--redact none\|literals`. Observe-only. **(v1.27)** `proxy analyze` aggregates the event log offline into a JSON/text report (summary, byFingerprint with suggestedCommands, slowest, errors, hotTables, N+1) — errors out if no events exist yet. |
366
+ | `proxy` | n/a | **(v1.26)** MySQL/MariaDB/PostgreSQL only. Local-dev observability proxy — relays app traffic to the real DB and appends query/latency/byte/error events to `.dbcli/proxy/events.jsonl`. Subcommands: `mysql` \| `mariadb` \| `postgresql`. `--listen`, `--target`, `--events` (default `.dbcli/proxy/events.jsonl`), `--slow-ms` (default `1000`), `--redact none\|literals` (default `none`). Observe-only. **(v1.27)** `proxy analyze` aggregates the event log offline into a JSON/text report (summary, byFingerprint, slowest, errors, hotTables, N+1) — `--format`, `--top`, `--slow-ms`, `--n-plus-one`; errors out if no events exist yet. **(v1.50)** `proxy analyze --format markdown` produces the QueryLens report and redacts SQL/error literals in-memory before analysis; use `proxy <engine> --redact literals` to protect the log itself. Actionable blocks carry `suggestedCommands` + `hints` so an agent can act: SELECT hotspots/N+1 → `explain` / `guide missing-index-for`, errors → `schema <table>` (verify names, never guess), N+1 → batch (JOIN / `IN (...)`). After analyzing, run each finding's `suggestedCommands`, read its `hints`, then propose the fix. |
367
367
  | `status` | query-only+ | Safe JSON/text summary (no credentials). |
368
368
  | `inspect` | query-only+ | Read-only context snapshot (connection, permission, blacklist, objects, snippets, context-aware `suggestedCommands`, and **(v1.23)** human-readable `hints`). `--for-agent` / `--brief` / `--no-connect` / `--require-schema-cache`. Supports `--recovery`. |
369
369
  | `report` | query-only+ | Diagnostic report built from `@diag/*` snippets. `--section <health\|capacity\|perf>` (comma-separated to combine), `--brief`, `--for-agent`, `--no-connect`. |
@@ -1180,6 +1180,7 @@ dbcli --use prod proxy postgresql # infer target from na
1180
1180
 
1181
1181
  dbcli proxy analyze # analyze .dbcli/proxy/events.jsonl (JSON)
1182
1182
  dbcli proxy analyze --format text --top 10 # human-readable top-10 view
1183
+ dbcli proxy analyze --format markdown # QueryLens shareable, redacted Markdown report
1183
1184
  dbcli proxy analyze --slow-ms 200 --n-plus-one 5 # custom thresholds
1184
1185
  ```
1185
1186
 
@@ -1200,7 +1201,16 @@ dbcli proxy analyze --slow-ms 200 --n-plus-one 5 # custom thresholds
1200
1201
 
1201
1202
  **Log rotation:** all writes are serialized through one in-process chain (concurrent sessions never interleave partial lines). The event log auto-rotates to keep one rolling segment — when the next line would reach ~50 MiB or 200,000 entries, the current file is renamed to `<events>.1` (overwriting any prior segment) and a fresh file starts. Worst-case on-disk footprint is ~2× the byte cap.
1202
1203
 
1203
- **`proxy analyze`** — offline aggregation of the event log (no DB). Flags: `--events <path>` (default `.dbcli/proxy/events.jsonl`), `--format json|text` (default `json`), `--top <n>` (default 20; text rows + suggestedCommands depth), `--slow-ms <ms>` (default 1000; recomputes slowCount), `--n-plus-one <n>` (default 10), `--no-include-rotated`. JSON report blocks: `summary`, `byFingerprint` (sorted by total time; SELECT entries in the top-N carry `suggestedCommands` for `explain` / `guide missing-index-for`), `slowest`, `errors`, `hotTables`, `repetition` (N+1 suspects). Reads the current log plus the rotated `.1` segment by default.
1204
+ **`proxy analyze`** — offline aggregation of the event log (no DB). Flags: `--events <path>` (default `.dbcli/proxy/events.jsonl`), `--format json|text|markdown` (default `json`), `--top <n>` (default 20; text rows + suggestedCommands depth), `--slow-ms <ms>` (default 1000; recomputes slowCount), `--n-plus-one <n>` (default 10), `--no-include-rotated`. JSON report blocks: `summary`, `byFingerprint` (sorted by total time; SELECT entries in the top-N carry `suggestedCommands` for `explain` / `guide missing-index-for`), `slowest`, `errors`, `hotTables`, `repetition` (N+1 suspects). Reads the current log plus the rotated `.1` segment by default. `markdown` is the QueryLens report: it redacts SQL and error-message literals in an in-memory copy before analysis, while leaving the source log untouched.
1205
+
1206
+ Every actionable block carries machine-readable next steps so an agent can move from "what is wrong" to "what to run":
1207
+ - `byFingerprint[]` — top-N SELECT entries get `suggestedCommands`: `dbcli explain "<sql>"` and `dbcli guide missing-index-for "<sql>"`.
1208
+ - `errors[]` — carries `tables`; emits `suggestedCommands` of `dbcli schema <table>` (capped at the first 3 tables) plus a `hints` note to verify table/column names before fixing (never guess column names). No tables known (e.g. a syntax error) → no `suggestedCommands`, but the hint still appears.
1209
+ - `repetition[]` — carries `statement` and a runnable `exampleSql` (the slowest occurrence). SELECT N+1 groups get `explain` / `guide missing-index-for` `suggestedCommands`; every group carries a `hints` note suggesting batching (JOIN / `IN (...)`) or caching.
1210
+
1211
+ `suggestedCommands` are emitted as strings only — `proxy analyze` never executes them. When the proxy ran with `--redact literals`, `exampleSql` (and therefore the suggested commands) contains `?` placeholders; fill in real values before running them.
1212
+
1213
+ **Acting on the report (agent loop):** after `proxy analyze`, for each block read `hints` for the diagnosis, run the entry's `suggestedCommands` to gather schema/plan/index evidence, then propose a concrete fix — add an index (`guide missing-index-for`), rewrite a slow SELECT (`explain`), batch an N+1 (`repetition`), or correct a column/table name (`errors` → `schema`). The text format mirrors this with aggregated `SUGGESTED COMMANDS` and `HINTS` sections; JSON keeps the suggestions attached per-finding.
1204
1214
 
1205
1215
  **Engines:** MySQL / MariaDB / PostgreSQL
1206
1216
  **Permission:** n/a (acts as a TCP relay; does not use dbcli's SQL permission model)
@@ -2,7 +2,7 @@
2
2
  "name": "dbcli-agent",
3
3
  "displayName": "dbcli Agent",
4
4
  "description": "Database CLI skill and command reference for AI agents.",
5
- "version": "1.48.0",
5
+ "version": "1.50.0",
6
6
  "author": {
7
7
  "name": "Carl Lee",
8
8
  "url": "https://github.com/CarlLee1983"
@@ -363,7 +363,7 @@ Full flags and edge cases: see [reference.md](reference.md) `init` section.
363
363
  | `assert` | query-only+ | **(v1.25)** SQL only. Verify an invariant; exit 1 on failure unless `--no-fail`. `--expect "rows>0\|value==X\|col:c not null\|unique\|between a and b\|>= n"`, `--vs <query> --compare rows\|value` (reconcile), `--against <snapshot> --tolerance <pct>`. |
364
364
  | `verification` | n/a | Inspect and manage local verification artifacts. `list` / `show <id-or-path>` / `summary` are read-only; `prune` is dry-run by default and deletes only with `--execute --force`. Reads `<cwd>/.dbcli/verification/`; no DB connection, no audit writes. |
365
365
  | `backfill artifact` | n/a | Build a bounded, reviewable source-to-SQL backfill artifact from JSON. Includes source/target identity, blacklist/schema preflight, read-back verification, and rollback hints; dry-run only and never executes writes. |
366
- | `proxy` | n/a | **(v1.26)** MySQL/MariaDB/PostgreSQL only. Local-dev observability proxy — relays app traffic to the real DB and appends query/latency/byte/error events to `.dbcli/proxy/events.jsonl`. Subcommands: `mysql` \| `mariadb` \| `postgresql`. `--listen`, `--target`, `--events`, `--slow-ms` (default `1000`), `--redact none\|literals`. Observe-only. **(v1.27)** `proxy analyze` aggregates the event log offline into a JSON/text report (summary, byFingerprint with suggestedCommands, slowest, errors, hotTables, N+1) — errors out if no events exist yet. |
366
+ | `proxy` | n/a | **(v1.26)** MySQL/MariaDB/PostgreSQL only. Local-dev observability proxy — relays app traffic to the real DB and appends query/latency/byte/error events to `.dbcli/proxy/events.jsonl`. Subcommands: `mysql` \| `mariadb` \| `postgresql`. `--listen`, `--target`, `--events` (default `.dbcli/proxy/events.jsonl`), `--slow-ms` (default `1000`), `--redact none\|literals` (default `none`). Observe-only. **(v1.27)** `proxy analyze` aggregates the event log offline into a JSON/text report (summary, byFingerprint, slowest, errors, hotTables, N+1) — `--format`, `--top`, `--slow-ms`, `--n-plus-one`; errors out if no events exist yet. **(v1.50)** `proxy analyze --format markdown` produces the QueryLens report and redacts SQL/error literals in-memory before analysis; use `proxy <engine> --redact literals` to protect the log itself. Actionable blocks carry `suggestedCommands` + `hints` so an agent can act: SELECT hotspots/N+1 → `explain` / `guide missing-index-for`, errors → `schema <table>` (verify names, never guess), N+1 → batch (JOIN / `IN (...)`). After analyzing, run each finding's `suggestedCommands`, read its `hints`, then propose the fix. |
367
367
  | `status` | query-only+ | Safe JSON/text summary (no credentials). |
368
368
  | `inspect` | query-only+ | Read-only context snapshot (connection, permission, blacklist, objects, snippets, context-aware `suggestedCommands`, and **(v1.23)** human-readable `hints`). `--for-agent` / `--brief` / `--no-connect` / `--require-schema-cache`. Supports `--recovery`. |
369
369
  | `report` | query-only+ | Diagnostic report built from `@diag/*` snippets. `--section <health\|capacity\|perf>` (comma-separated to combine), `--brief`, `--for-agent`, `--no-connect`. |
@@ -1180,6 +1180,7 @@ dbcli --use prod proxy postgresql # infer target from na
1180
1180
 
1181
1181
  dbcli proxy analyze # analyze .dbcli/proxy/events.jsonl (JSON)
1182
1182
  dbcli proxy analyze --format text --top 10 # human-readable top-10 view
1183
+ dbcli proxy analyze --format markdown # QueryLens shareable, redacted Markdown report
1183
1184
  dbcli proxy analyze --slow-ms 200 --n-plus-one 5 # custom thresholds
1184
1185
  ```
1185
1186
 
@@ -1200,7 +1201,16 @@ dbcli proxy analyze --slow-ms 200 --n-plus-one 5 # custom thresholds
1200
1201
 
1201
1202
  **Log rotation:** all writes are serialized through one in-process chain (concurrent sessions never interleave partial lines). The event log auto-rotates to keep one rolling segment — when the next line would reach ~50 MiB or 200,000 entries, the current file is renamed to `<events>.1` (overwriting any prior segment) and a fresh file starts. Worst-case on-disk footprint is ~2× the byte cap.
1202
1203
 
1203
- **`proxy analyze`** — offline aggregation of the event log (no DB). Flags: `--events <path>` (default `.dbcli/proxy/events.jsonl`), `--format json|text` (default `json`), `--top <n>` (default 20; text rows + suggestedCommands depth), `--slow-ms <ms>` (default 1000; recomputes slowCount), `--n-plus-one <n>` (default 10), `--no-include-rotated`. JSON report blocks: `summary`, `byFingerprint` (sorted by total time; SELECT entries in the top-N carry `suggestedCommands` for `explain` / `guide missing-index-for`), `slowest`, `errors`, `hotTables`, `repetition` (N+1 suspects). Reads the current log plus the rotated `.1` segment by default.
1204
+ **`proxy analyze`** — offline aggregation of the event log (no DB). Flags: `--events <path>` (default `.dbcli/proxy/events.jsonl`), `--format json|text|markdown` (default `json`), `--top <n>` (default 20; text rows + suggestedCommands depth), `--slow-ms <ms>` (default 1000; recomputes slowCount), `--n-plus-one <n>` (default 10), `--no-include-rotated`. JSON report blocks: `summary`, `byFingerprint` (sorted by total time; SELECT entries in the top-N carry `suggestedCommands` for `explain` / `guide missing-index-for`), `slowest`, `errors`, `hotTables`, `repetition` (N+1 suspects). Reads the current log plus the rotated `.1` segment by default. `markdown` is the QueryLens report: it redacts SQL and error-message literals in an in-memory copy before analysis, while leaving the source log untouched.
1205
+
1206
+ Every actionable block carries machine-readable next steps so an agent can move from "what is wrong" to "what to run":
1207
+ - `byFingerprint[]` — top-N SELECT entries get `suggestedCommands`: `dbcli explain "<sql>"` and `dbcli guide missing-index-for "<sql>"`.
1208
+ - `errors[]` — carries `tables`; emits `suggestedCommands` of `dbcli schema <table>` (capped at the first 3 tables) plus a `hints` note to verify table/column names before fixing (never guess column names). No tables known (e.g. a syntax error) → no `suggestedCommands`, but the hint still appears.
1209
+ - `repetition[]` — carries `statement` and a runnable `exampleSql` (the slowest occurrence). SELECT N+1 groups get `explain` / `guide missing-index-for` `suggestedCommands`; every group carries a `hints` note suggesting batching (JOIN / `IN (...)`) or caching.
1210
+
1211
+ `suggestedCommands` are emitted as strings only — `proxy analyze` never executes them. When the proxy ran with `--redact literals`, `exampleSql` (and therefore the suggested commands) contains `?` placeholders; fill in real values before running them.
1212
+
1213
+ **Acting on the report (agent loop):** after `proxy analyze`, for each block read `hints` for the diagnosis, run the entry's `suggestedCommands` to gather schema/plan/index evidence, then propose a concrete fix — add an index (`guide missing-index-for`), rewrite a slow SELECT (`explain`), batch an N+1 (`repetition`), or correct a column/table name (`errors` → `schema`). The text format mirrors this with aggregated `SUGGESTED COMMANDS` and `HINTS` sections; JSON keeps the suggestions attached per-finding.
1204
1214
 
1205
1215
  **Engines:** MySQL / MariaDB / PostgreSQL
1206
1216
  **Permission:** n/a (acts as a TCP relay; does not use dbcli's SQL permission model)
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.50.0] - 2026-08-06 - QueryLens proxy query analysis
9
+
10
+ ### Added
11
+
12
+ - **QueryLens Markdown report for `dbcli proxy analyze`.** `dbcli proxy analyze --format markdown` now produces a shareable report covering query volume, latency percentiles, expensive fingerprints, slowest queries, errors, and N+1 suspects. It reads the proxy JSONL log offline and includes its rotated segment unless `--no-include-rotated` is supplied.
13
+
14
+ ### Security
15
+
16
+ - **QueryLens redacts report literals independently of capture configuration.** The Markdown path analyzes an in-memory redacted copy of SQL-bearing events, including error messages, so a legacy log captured without `--redact literals` does not expose those values in the report. Use `dbcli proxy <engine> --redact literals` as well to protect the event log itself.
17
+
18
+ ## [1.49.0] - 2026-08-06 - 欄位遮罩涵蓋攤平與陣列列,且不再為每條規則掃過整個結果集
19
+
20
+ 延續 1.48.0 的 blacklist 主題:那一版修的是「哪些物件受保護」,這一版修的是「受保護的欄位到底有沒有真的被遮掉」,以及遮罩本身的成本。兩條安全性修復都屬於 fail-open —— 資料原樣回傳,其中一條連安全通知都不會發。
21
+
22
+ ### Added
23
+
24
+ - **`dbcli proxy analyze` — 各區塊行動化(commands + hints),銜接 AI agent 介入。** `errors[]` 新增 `tables`,並附 `suggestedCommands`(`dbcli schema <table>`,最多前 3 表)+ `hints`(先核對表名/欄名再修正,勿臆測欄名);`repetition[]` 新增 `statement` 與可執行的 `exampleSql`(取最慢一筆),SELECT 群組附 `explain` / `guide missing-index-for` 的 `suggestedCommands`,每組附 N+1 批次化/快取的 `hints`。text 輸出彙整為 `SUGGESTED COMMANDS` 與 `HINTS` 區段;JSON 將建議附在各發現上。沿用 inspect 的 `suggestedCommands` + `hints` 雙軌慣例。skill 與使用者文件同步說明「analyze 後的 agent 行動流程」。
25
+
26
+ ### Security
27
+
28
+ - **黑名單指定父欄位時,攤平後的子欄位未被遮蔽,而且不發通知。** Elasticsearch adapter 會把 `_source` 遞迴攤平成帶點的頂層鍵(`{profile:{ssn}}` → 鍵 `profile.ssn`,文件裡根本沒有 `profile`),而遮蔽判斷是以欄位名等值比對,因此把 `profile` 列入欄位黑名單完全沒有作用:資料原樣回傳,且因為「已遮蔽欄位」清單是空的,連安全通知都不會發出 —— 使用者不會知道有東西本來該被藏起來。影響 `query` / `q` / `export` 三條 Elasticsearch 路徑。現在任何位於黑名單祖先之下的欄位都會被遮蔽(`profiles`、`profile_name` 這類僅前綴相似的欄位不受影響)。已知天花板(規則指定葉節點名、或祖先不從路徑開頭起算)記於 `docs/security-threat-model.md`。
29
+
30
+ - **欄位遮罩把「列本身是陣列」當成 record,遮蔽通知發了但資料沒被拿掉。** 判斷「這個欄位在不在」的 `readPath` 把陣列當透明容器往裡面找,但實際執行遮蔽的 `cloneRecord` 把它當 record,於是索引變成鍵、元素裡的敏感欄位原封不動 —— 一列被回報為已遮蔽,卻是完整回傳的。兩邊現在都看穿陣列(含巢狀陣列)。目前沒有任何 adapter 會回傳陣列列,所以這是把「偵測」與「移除」兩半釘在同一個答案上,而不是修一個可觸發的洩漏。
31
+
32
+ ### Performance
33
+
34
+ - **欄位遮罩對每一列的每一個欄位各複製一次整列。** `omitFieldPaths` 逐一路徑呼叫 `omitPath`,而後者每次都重建整個 record,因此成本是 O(列數 × 遮罩欄位數) 次完整複製 —— 100 列對上 50 個遮罩欄位就是 5000 次。沒有點的路徑只會刪掉一個頂層鍵,而欄位黑名單絕大多數就是這種名稱,現在合併成一趟處理,只有真正的巢狀路徑才遞迴。輸出完全相同,實測 30.37ms → 1.73ms。任何回傳大量資料又設有欄位黑名單的查詢或匯出都會受益。
35
+
36
+ - **黑名單規則多、命中少時,遮罩層對每條規則掃過整個結果集。** 判斷一條規則有沒有東西要遮,會對每一列呼叫一次 `hasFieldPath`,而它每次都重跑一遍 `path.split('.')`。掃不到表名的 fail-safe 分支會把設定裡的**每一條**規則都套上來,所以「規則多、命中少」正是它的常態形狀:60 條帶點且完全不命中的規則對上 1000 列,實測 12.10ms,而真正遮掉的只有一個欄位。現在沒有點的規則直接由既有的欄位集合精確回答,帶點的規則只在「開頭那一段在某列真的是物件或陣列」時才走訪列 —— 這與 `readPath` 本來就會判斷的條件相同,只是每條規則判一次而不是每列判一次;而讀取欄位值(比只列出名稱貴約 4 倍,也會觸發列物件上的 getter)只在黑名單裡真的有帶點規則時才做,所以常見的純欄位名黑名單反而比修改前更快。輸出完全相同,實測 12.10ms → 0.70ms,一般查詢的遮罩 0.69ms → 0.53ms。
37
+
38
+ ### Changed
39
+
40
+ - **效能基準改為阻擋 CI。** `ci.yml` 的 `continue-on-error: true` 是那兩條基準能失敗四個月沒人發現的原因,已移除。同時每條基準都改為取多次量測的中位數並印出實測值,預算也依**實際 runner** 的數字重訂(最慢的 windows-latest 1.3.3 量到 3.25ms,原本 5ms 的預算只剩 35% 餘裕,放寬到 8ms)。一個會被強制執行的寬預算,勝過一個被忽略的嚴預算。
41
+
42
+ ### Fixed
43
+
44
+ - **兩條效能基準自 2026-03-26 加入起就沒通過過。** 它們被 `ci.yml` 的 `continue-on-error: true` 蓋住,所以 CI 從未因此變紅,超標 6 倍也沒人看見。門檻本身是合理的(修正後餘裕 3 倍),問題在上面那條實作。基準也改為取多次量測的中位數並印出實測值:單次 `performance.now()` 加硬門檻約每三次就會誤報一次,當不了 gate。
45
+
8
46
  ## [1.48.0] - 2026-08-05 - blacklist 涵蓋語句中的每一張表,以及所有執行路徑(安全性修復)
9
47
 
10
48
  對應 issue [#23](https://github.com/CarlLee1983/dbcli/issues/23)。與 1.47.1 修掉的六個繞過不同,這一批洩漏的是**讀取內容**,不是寫入能力。
package/README.md CHANGED
@@ -880,6 +880,7 @@ dbcli proxy mysql --listen 127.0.0.1:3307 --target 127.0.0.1:3306
880
880
  dbcli proxy postgresql --listen 127.0.0.1:5434 --target 127.0.0.1:5432
881
881
  dbcli proxy mysql --slow-ms 500 --redact literals
882
882
  dbcli proxy mariadb --events ./logs/proxy.jsonl
883
+ dbcli proxy analyze --events ./logs/proxy.jsonl --format markdown # QueryLens report
883
884
  ```
884
885
 
885
886
  **Options:**
@@ -890,6 +891,8 @@ dbcli proxy mariadb --events ./logs/proxy.jsonl
890
891
  - `--redact none|literals` — Strip SQL literal values from event records (default: `none`)
891
892
  - `--format text|json` — Startup output format (default: `text`)
892
893
 
894
+ **QueryLens:** `dbcli proxy analyze --format markdown` reads the event log offline and produces a shareable Markdown report. It redacts SQL and error-message literals in memory before analysis; use `--redact literals` while capturing as well to protect the log on disk.
895
+
893
896
  ---
894
897
 
895
898
  #### `dbcli status`
package/assets/SKILL.md CHANGED
@@ -363,7 +363,7 @@ Full flags and edge cases: see [reference.md](reference.md) `init` section.
363
363
  | `assert` | query-only+ | **(v1.25)** SQL only. Verify an invariant; exit 1 on failure unless `--no-fail`. `--expect "rows>0\|value==X\|col:c not null\|unique\|between a and b\|>= n"`, `--vs <query> --compare rows\|value` (reconcile), `--against <snapshot> --tolerance <pct>`. |
364
364
  | `verification` | n/a | Inspect and manage local verification artifacts. `list` / `show <id-or-path>` / `summary` are read-only; `prune` is dry-run by default and deletes only with `--execute --force`. Reads `<cwd>/.dbcli/verification/`; no DB connection, no audit writes. |
365
365
  | `backfill artifact` | n/a | Build a bounded, reviewable source-to-SQL backfill artifact from JSON. Includes source/target identity, blacklist/schema preflight, read-back verification, and rollback hints; dry-run only and never executes writes. |
366
- | `proxy` | n/a | **(v1.26)** MySQL/MariaDB/PostgreSQL only. Local-dev observability proxy — relays app traffic to the real DB and appends query/latency/byte/error events to `.dbcli/proxy/events.jsonl`. Subcommands: `mysql` \| `mariadb` \| `postgresql`. `--listen`, `--target`, `--events`, `--slow-ms` (default `1000`), `--redact none\|literals`. Observe-only. **(v1.27)** `proxy analyze` aggregates the event log offline into a JSON/text report (summary, byFingerprint with suggestedCommands, slowest, errors, hotTables, N+1) — errors out if no events exist yet. |
366
+ | `proxy` | n/a | **(v1.26)** MySQL/MariaDB/PostgreSQL only. Local-dev observability proxy — relays app traffic to the real DB and appends query/latency/byte/error events to `.dbcli/proxy/events.jsonl`. Subcommands: `mysql` \| `mariadb` \| `postgresql`. `--listen`, `--target`, `--events` (default `.dbcli/proxy/events.jsonl`), `--slow-ms` (default `1000`), `--redact none\|literals` (default `none`). Observe-only. **(v1.27)** `proxy analyze` aggregates the event log offline into a JSON/text report (summary, byFingerprint, slowest, errors, hotTables, N+1) — `--format`, `--top`, `--slow-ms`, `--n-plus-one`; errors out if no events exist yet. **(v1.50)** `proxy analyze --format markdown` produces the QueryLens report and redacts SQL/error literals in-memory before analysis; use `proxy <engine> --redact literals` to protect the log itself. Actionable blocks carry `suggestedCommands` + `hints` so an agent can act: SELECT hotspots/N+1 → `explain` / `guide missing-index-for`, errors → `schema <table>` (verify names, never guess), N+1 → batch (JOIN / `IN (...)`). After analyzing, run each finding's `suggestedCommands`, read its `hints`, then propose the fix. |
367
367
  | `status` | query-only+ | Safe JSON/text summary (no credentials). |
368
368
  | `inspect` | query-only+ | Read-only context snapshot (connection, permission, blacklist, objects, snippets, context-aware `suggestedCommands`, and **(v1.23)** human-readable `hints`). `--for-agent` / `--brief` / `--no-connect` / `--require-schema-cache`. Supports `--recovery`. |
369
369
  | `report` | query-only+ | Diagnostic report built from `@diag/*` snippets. `--section <health\|capacity\|perf>` (comma-separated to combine), `--brief`, `--for-agent`, `--no-connect`. |
@@ -276,7 +276,7 @@ dbcli init --conn-name prod --env-file .env.production --use-env-refs --skip-tes
276
276
  | `assert` | query-only+ | **(v1.25)** 僅 SQL。驗證不變量;失敗時 exit 1,除非 `--no-fail`。`--expect "rows>0\|value==X\|col:c not null\|unique\|between a and b\|>= n"`、`--vs <query> --compare rows\|value`(對帳)、`--against <snapshot> --tolerance <pct>`。 |
277
277
  | `verification` | n/a | 檢視與管理本機驗證 artifact。`list` / `show <id-or-path>` / `summary` 為唯讀;`prune` 預設 dry-run,僅在 `--execute --force` 時刪除。讀取 `<cwd>/.dbcli/verification/`;不需 DB 連線,不寫入 audit log。 |
278
278
  | `backfill artifact` | n/a | 將受限 JSON source catalog 產生可檢閱的 source-to-SQL 回填 artifact,包含 source/target identity、blacklist/schema preflight、read-back 驗證與 rollback hint;只產生 dry-run,絕不執行寫入。 |
279
- | `proxy` | n/a | **(v1.26)** 僅 MySQL/MariaDB/PostgreSQL。本地端開發觀測代理 — 中繼應用程式流量至真實資料庫,並將查詢 / 延遲 / 位元組 / 錯誤事件附加到 `.dbcli/proxy/events.jsonl`。子指令:`mysql` \| `mariadb` \| `postgresql`。`--listen`、`--target`、`--events`、`--slow-ms`(預設 `1000`)、`--redact none\|literals`。僅作觀測。**(v1.27)** `proxy analyze` 離線彙整事件 log 為 JSON / 文字報表(summary、byFingerprint 含 suggestedCommands、slowest、errors、hotTables、N+1)— 若無事件則報錯。 |
279
+ | `proxy` | n/a | **(v1.26)** 僅 MySQL/MariaDB/PostgreSQL。本地端開發觀測代理 — 中繼應用程式流量至真實資料庫,並將查詢 / 延遲 / 位元組 / 錯誤事件附加到 `.dbcli/proxy/events.jsonl`。子指令:`mysql` \| `mariadb` \| `postgresql`。`--listen`、`--target`、`--events`、`--slow-ms`(預設 `1000`)、`--redact none\|literals`。僅作觀測。**(v1.27)** `proxy analyze` 離線彙整事件 log 為 JSON / 文字報表(summary、byFingerprint 含 suggestedCommands、slowest、errors、hotTables、N+1)— 若無事件則報錯。**(v1.50)** `proxy analyze --format markdown` 產生 QueryLens 報告,分析前會在記憶體中遮罩 SQL/錯誤 literal;仍應以 `proxy <engine> --redact literals` 保護事件日誌本身。 |
280
280
  | `status` | query-only+ | 安全 JSON / 文字摘要(不含憑證)。 |
281
281
  | `inspect` | query-only+ | 唯讀脈絡快照(連線、權限、blacklist、物件、snippets、建議指令,以及 **(v1.23)** 人類可讀 `hints`)。`--for-agent` / `--brief` / `--no-connect` / `--require-schema-cache`。支援 `--recovery`。 |
282
282
  | `report` | query-only+ | 以 `@diag/*` snippet 組成的診斷報告。`--section <health\|capacity\|perf>`(可用逗號組合)、`--brief`、`--for-agent`、`--no-connect`。 |
@@ -1180,6 +1180,7 @@ dbcli --use prod proxy postgresql # infer target from na
1180
1180
 
1181
1181
  dbcli proxy analyze # analyze .dbcli/proxy/events.jsonl (JSON)
1182
1182
  dbcli proxy analyze --format text --top 10 # human-readable top-10 view
1183
+ dbcli proxy analyze --format markdown # QueryLens shareable, redacted Markdown report
1183
1184
  dbcli proxy analyze --slow-ms 200 --n-plus-one 5 # custom thresholds
1184
1185
  ```
1185
1186
 
@@ -1200,7 +1201,16 @@ dbcli proxy analyze --slow-ms 200 --n-plus-one 5 # custom thresholds
1200
1201
 
1201
1202
  **Log rotation:** all writes are serialized through one in-process chain (concurrent sessions never interleave partial lines). The event log auto-rotates to keep one rolling segment — when the next line would reach ~50 MiB or 200,000 entries, the current file is renamed to `<events>.1` (overwriting any prior segment) and a fresh file starts. Worst-case on-disk footprint is ~2× the byte cap.
1202
1203
 
1203
- **`proxy analyze`** — offline aggregation of the event log (no DB). Flags: `--events <path>` (default `.dbcli/proxy/events.jsonl`), `--format json|text` (default `json`), `--top <n>` (default 20; text rows + suggestedCommands depth), `--slow-ms <ms>` (default 1000; recomputes slowCount), `--n-plus-one <n>` (default 10), `--no-include-rotated`. JSON report blocks: `summary`, `byFingerprint` (sorted by total time; SELECT entries in the top-N carry `suggestedCommands` for `explain` / `guide missing-index-for`), `slowest`, `errors`, `hotTables`, `repetition` (N+1 suspects). Reads the current log plus the rotated `.1` segment by default.
1204
+ **`proxy analyze`** — offline aggregation of the event log (no DB). Flags: `--events <path>` (default `.dbcli/proxy/events.jsonl`), `--format json|text|markdown` (default `json`), `--top <n>` (default 20; text rows + suggestedCommands depth), `--slow-ms <ms>` (default 1000; recomputes slowCount), `--n-plus-one <n>` (default 10), `--no-include-rotated`. JSON report blocks: `summary`, `byFingerprint` (sorted by total time; SELECT entries in the top-N carry `suggestedCommands` for `explain` / `guide missing-index-for`), `slowest`, `errors`, `hotTables`, `repetition` (N+1 suspects). Reads the current log plus the rotated `.1` segment by default. `markdown` is the QueryLens report: it redacts SQL and error-message literals in an in-memory copy before analysis, while leaving the source log untouched.
1205
+
1206
+ Every actionable block carries machine-readable next steps so an agent can move from "what is wrong" to "what to run":
1207
+ - `byFingerprint[]` — top-N SELECT entries get `suggestedCommands`: `dbcli explain "<sql>"` and `dbcli guide missing-index-for "<sql>"`.
1208
+ - `errors[]` — carries `tables`; emits `suggestedCommands` of `dbcli schema <table>` (capped at the first 3 tables) plus a `hints` note to verify table/column names before fixing (never guess column names). No tables known (e.g. a syntax error) → no `suggestedCommands`, but the hint still appears.
1209
+ - `repetition[]` — carries `statement` and a runnable `exampleSql` (the slowest occurrence). SELECT N+1 groups get `explain` / `guide missing-index-for` `suggestedCommands`; every group carries a `hints` note suggesting batching (JOIN / `IN (...)`) or caching.
1210
+
1211
+ `suggestedCommands` are emitted as strings only — `proxy analyze` never executes them. When the proxy ran with `--redact literals`, `exampleSql` (and therefore the suggested commands) contains `?` placeholders; fill in real values before running them.
1212
+
1213
+ **Acting on the report (agent loop):** after `proxy analyze`, for each block read `hints` for the diagnosis, run the entry's `suggestedCommands` to gather schema/plan/index evidence, then propose a concrete fix — add an index (`guide missing-index-for`), rewrite a slow SELECT (`explain`), batch an N+1 (`repetition`), or correct a column/table name (`errors` → `schema`). The text format mirrors this with aggregated `SUGGESTED COMMANDS` and `HINTS` sections; JSON keeps the suggestions attached per-finding.
1204
1214
 
1205
1215
  **Engines:** MySQL / MariaDB / PostgreSQL
1206
1216
  **Permission:** n/a (acts as a TCP relay; does not use dbcli's SQL permission model)