db-mcp 1.1.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitleaks.toml +9 -0
- package/.trivyignore +8 -0
- package/README.md +193 -120
- package/dist/{chunk-DWJXQEFA.js → chunk-5Y42NPBP.js} +4168 -2411
- package/dist/{chunk-AOUL5SHS.js → chunk-645ZEFLA.js} +70 -20
- package/dist/chunk-OKOVZ5QE.js +28 -0
- package/dist/chunk-SFJQCNG7.js +131 -0
- package/dist/{chunk-S5IDDSSB.js → chunk-VIDSICEL.js} +12 -1
- package/dist/chunk-WBER5YY4.js +2053 -0
- package/dist/{chunk-4IA3DB5C.js → chunk-X3MUUOWM.js} +19 -2
- package/dist/{chunk-Z2GFQU3G.js → chunk-Z7C2TM4L.js} +114 -21
- package/dist/cli.js +79 -5
- package/dist/{http-VSB7DBJR.js → http-6KF4ULDI.js} +199 -77
- package/dist/index.d.ts +231 -8
- package/dist/index.js +6 -5
- package/dist/{sqlite-VHBA4ABV.js → sqlite-U5KSYQXK.js} +63 -140
- package/dist/{sqlite-native-D2LH5ZT7.js → sqlite-native-JXMCFQBA.js} +576 -114
- package/dist/worker-script.js +34 -10
- package/logs/.gitkeep +1 -0
- package/mcp-config-example.json +83 -0
- package/package.json +9 -8
- package/playwright.config.ts +1 -1
- package/scripts/update-badges.ts +99 -0
- package/server.json +7 -5
- package/test-server/README.md +20 -23
- package/test-server/code-map.md +45 -33
- package/test-server/reset-database.ps1 +59 -17
- package/test-server/scripts/README.md +27 -0
- package/test-server/{test-help-resources.mjs → scripts/test-help-resources.mjs} +12 -5
- package/test-server/scripts/test-prompts.mjs +251 -0
- package/test-server/{test-tool-annotations.mjs → scripts/test-tool-annotations.mjs} +9 -4
- package/test-server/test-advanced/README.md +70 -0
- package/test-server/test-advanced/test-codemode-advanced-admin.md +174 -0
- package/test-server/test-advanced/test-codemode-advanced-core.md +193 -0
- package/test-server/test-advanced/test-codemode-advanced-geo.md +157 -0
- package/test-server/test-advanced/test-codemode-advanced-introspection.md +171 -0
- package/test-server/test-advanced/test-codemode-advanced-json.md +169 -0
- package/test-server/test-advanced/test-codemode-advanced-migration.md +160 -0
- package/test-server/test-advanced/test-codemode-advanced-stats.md +185 -0
- package/test-server/test-advanced/test-codemode-advanced-text.md +183 -0
- package/test-server/test-advanced/test-codemode-advanced-transactions.md +136 -0
- package/test-server/test-advanced/test-codemode-advanced-vector.md +141 -0
- package/test-server/test-codemode/README.md +121 -0
- package/test-server/test-codemode/test-codemode-admin.md +223 -0
- package/test-server/test-codemode/test-codemode-core.md +286 -0
- package/test-server/test-codemode/test-codemode-geo.md +177 -0
- package/test-server/test-codemode/test-codemode-introspection.md +190 -0
- package/test-server/test-codemode/test-codemode-json.md +237 -0
- package/test-server/test-codemode/test-codemode-migration.md +278 -0
- package/test-server/test-codemode/test-codemode-sandbox.md +413 -0
- package/test-server/test-codemode/test-codemode-stats.md +232 -0
- package/test-server/test-codemode/test-codemode-text.md +237 -0
- package/test-server/test-codemode/test-codemode-transactions.md +236 -0
- package/test-server/test-codemode/test-codemode-vector.md +244 -0
- package/test-server/test-codemode/test-codemode-wasm-degradation.md +394 -0
- package/test-server/test-database.sql +37 -1
- package/test-server/test-resources.md +43 -16
- package/test-server/test-tool-groups/README.md +100 -0
- package/test-server/test-tool-groups/test-admin-core.md +165 -0
- package/test-server/test-tool-groups/test-admin-extensions.md +133 -0
- package/test-server/{test-tools.md → test-tool-groups/test-core-data.md} +103 -17
- package/test-server/test-tool-groups/test-core-schema.md +240 -0
- package/test-server/test-tool-groups/test-geo-haversine.md +130 -0
- package/test-server/test-tool-groups/test-geo-spatialite.md +110 -0
- package/test-server/test-tool-groups/test-introspection-diagnostics.md +123 -0
- package/test-server/test-tool-groups/test-introspection-schema.md +133 -0
- package/test-server/test-tool-groups/test-json-read.md +219 -0
- package/test-server/test-tool-groups/test-json-write.md +157 -0
- package/test-server/test-tool-groups/test-migration.md +193 -0
- package/test-server/test-tool-groups/test-stats-advanced.md +118 -0
- package/test-server/test-tool-groups/test-stats-basic.md +156 -0
- package/test-server/test-tool-groups/test-text-advanced.md +169 -0
- package/test-server/test-tool-groups/test-text-basic.md +177 -0
- package/test-server/test-tool-groups/test-transactions.md +179 -0
- package/test-server/test-tool-groups/test-vector-read.md +130 -0
- package/test-server/test-tool-groups/test-vector-write.md +115 -0
- package/test-server/tool-reference.md +79 -58
- package/tsconfig.build.json +6 -0
- package/dist/chunk-DZQLDEQS.js +0 -879
- package/test-server/test-agent-experience.md +0 -243
- package/test-server/test-group-tools.md +0 -861
- package/test-server/test-tools-advanced-1.md +0 -517
- package/test-server/test-tools-advanced-2.md +0 -487
- package/test-server/test-tools-codemode.md +0 -629
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# db-mcp Code Mode Testing Suite
|
|
2
|
+
|
|
3
|
+
**Directory Purpose**: This folder contains 12 self-contained, modular test prompts covering every tool group in `db-mcp`. These prompts are strictly designed for **Code Mode (`sqlite_execute_code`) validation only**.
|
|
4
|
+
|
|
5
|
+
## Agent Instructions
|
|
6
|
+
|
|
7
|
+
When tasked with running tests from this folder, adhere to the following optimized protocol:
|
|
8
|
+
|
|
9
|
+
### 1. Execution Strictness
|
|
10
|
+
|
|
11
|
+
- **Code Mode Exclusive**: Test tools ONLY using `sqlite_execute_code`. Do not use direct tool calls or the terminal unless specifically comparing behavior.
|
|
12
|
+
- **Batching**: Group multiple method calls into a single JavaScript code execution script to save context window tokens and improve speed.
|
|
13
|
+
- **Failures Array Format**: Design your JS script to capture both expected outputs and caught errors, appending assertions to a `failures` array, and returning `{ failures, success: failures.length === 0 }`.
|
|
14
|
+
|
|
15
|
+
### 2. Validation Targets
|
|
16
|
+
|
|
17
|
+
- **Happy Path Parity**: Validate that Code Mode handler execution matches expected database behavior.
|
|
18
|
+
- **Structured Error Path**: Ensure domain errors (e.g., nonexistent table) return an object `{"success": false, "error": "..."}` instead of crashing or leaking raw MCP errors.
|
|
19
|
+
- **Zod Resilience**: Pass `{}` with missing required parameters or invalid types. Verify that Zod errors are properly caught and formatted.
|
|
20
|
+
- **Payload Limits**: If a response payload is excessively large, report it as a 📦 Payload issue.
|
|
21
|
+
- **Code Over Docs (When Standards Violated)**: If the code deviates from established standards (e.g., throwing raw MCP errors instead of Structured Errors, or failing Zod validation), **fix the handler code**. Do not modify documentation, prompts, or `gotchas.md` to accommodate buggy code.
|
|
22
|
+
- **Documentation Parity & Test Prompt Integrity**: Only update files in `src/constants/server-instructions` (or test prompts) if the code's behavior is mathematically/logically correct and intended, but the documentation is inaccurate, outdated, or lacking specificity. You SHOULD directly edit the markdown test files in this directory to fix factual errors, broken code blocks, or incorrect test assertions.
|
|
23
|
+
|
|
24
|
+
### 3. Tracking Progress
|
|
25
|
+
|
|
26
|
+
You must maintain a **Strict Coverage Matrix** in `tmp/task.md` logging completion for:
|
|
27
|
+
`| Tool | Code Mode (Happy Path) | Code Mode (Domain Error/Zod Error) |`
|
|
28
|
+
Never proceed to the final step until every tool in a given group has both columns marked as ✅.
|
|
29
|
+
|
|
30
|
+
### 4. Token Tracking
|
|
31
|
+
|
|
32
|
+
Monitor `metrics.tokenEstimate` on every Code Mode response. Report the single most expensive execution block in your final summary.
|
|
33
|
+
|
|
34
|
+
### 5. Cleanup
|
|
35
|
+
|
|
36
|
+
- Any write tests should operate on temporary tables or objects prefixed with `temp_`.
|
|
37
|
+
- **Active Connection Lock**: The MCP server holds a lock on the SQLite database, preventing the reset script from replacing the file outright. The reset script only seeds default tables, it does not drop unknown `temp_` tables.
|
|
38
|
+
- **Mandatory Code Mode Cleanup**: Your final step MUST be a Code Mode script that explicitly drops ALL `temp_*` tables (e.g., `sqlite.core.dropTable({tableName: '...', force: true})`) BEFORE you run the reset script.
|
|
39
|
+
|
|
40
|
+
### 6. Testing Limits
|
|
41
|
+
|
|
42
|
+
- **No Automated Execution**: Do not run build or tests automatically (`npm run lint`, `npm run typecheck`, `npm run test:e2e`, `vitest`, or `playwright`). The user will execute them manually. When you reach the validate step, explicitly instruct the user to run the validations.
|
|
43
|
+
|
|
44
|
+
### 7. WASM Mode Execution
|
|
45
|
+
|
|
46
|
+
When testing against a **WASM backend** (`--sqlite` flag, sql.js adapter), follow these additional rules:
|
|
47
|
+
|
|
48
|
+
#### Skip Rules
|
|
49
|
+
|
|
50
|
+
- **`[NATIVE ONLY]` items**: Skip all phases and individual test items annotated with `[NATIVE ONLY]`. This annotation already exists in each prompt.
|
|
51
|
+
- **Transactions prompt**: Skip entirely — the transactions group has 0 WASM tools. `sqlite.transactions.help()` returns an empty methods list.
|
|
52
|
+
- **Window function items** (stats prompt Phases 3, 6): Skip — 6 window tools are Native-only.
|
|
53
|
+
- **SpatiaLite items** (geo prompt Phase 2): Skip — 7 SpatiaLite tools are Native-only.
|
|
54
|
+
- **FTS5 items** (text prompt Phase 2): Skip — 5 FTS5 tools are Native-only.
|
|
55
|
+
|
|
56
|
+
#### Graceful Degradation (Don't Skip — Validate Errors)
|
|
57
|
+
|
|
58
|
+
Several admin tools are **registered in WASM mode but return structured errors** instead of succeeding. Test these as **negative validation** — verify the structured error response, don't skip them:
|
|
59
|
+
|
|
60
|
+
| Tool | Expected WASM Behavior |
|
|
61
|
+
| ------------------------------------ | ---------------------------------------------- |
|
|
62
|
+
| `sqlite.admin.backup(...)` | `{success: false, error: "...WASM mode"}` |
|
|
63
|
+
| `sqlite.admin.restore(...)` | `{success: false, error: "...WASM mode"}` |
|
|
64
|
+
| `sqlite.admin.verifyBackup(...)` | `{success: false, error: "...WASM mode"}` |
|
|
65
|
+
| `sqlite.admin.createCsvTable(...)` | `{success: false}` — CSV extension unavailable |
|
|
66
|
+
| `sqlite.admin.analyzeCsvSchema(...)` | `{success: false}` — CSV extension unavailable |
|
|
67
|
+
| `sqlite.admin.createRtreeTable(...)` | `{success: false}` — R-Tree module unavailable |
|
|
68
|
+
|
|
69
|
+
#### Adjusted Expectations
|
|
70
|
+
|
|
71
|
+
| Item | Native Behavior | WASM Behavior |
|
|
72
|
+
| --------------------------------------------------------------- | ----------------------------------------- | --------------------------------------------------------------------- |
|
|
73
|
+
| `sqlite.admin.dbstat({summarize: true})` | Per-table storage breakdown | Counts-only (JS fallback) |
|
|
74
|
+
| `sqlite.admin.pragmaCompileOptions()` | Includes `ENABLE_FTS5` | Shows `ENABLE_FTS3` instead |
|
|
75
|
+
| `sqlite.admin.pragmaCompileOptions({filter: "FTS"})` | Matches FTS5 | Matches FTS3 |
|
|
76
|
+
| `sqlite.core.listTables()` / `sqlite.admin.listVirtualTables()` | `test_articles_fts` present and queryable | `test_articles_fts` may appear in sqlite_master but FTS5 queries fail |
|
|
77
|
+
| `sqlite.help()` | `totalMethods` reflects 151 tools | `totalMethods` reflects 125 tools |
|
|
78
|
+
| Phase 2.1 (sandbox prompt) top-level help | 10 groups listed | `transactions` group shows 0 methods |
|
|
79
|
+
|
|
80
|
+
#### WASM-Specific Degradation Prompt
|
|
81
|
+
|
|
82
|
+
After completing the applicable prompts above, run `test-codemode-wasm-degradation.md` — a dedicated prompt that validates graceful degradation patterns unique to WASM mode. This prompt should **only** be run against a WASM backend.
|
|
83
|
+
|
|
84
|
+
## File Inventory
|
|
85
|
+
|
|
86
|
+
| File | Group | Tools |
|
|
87
|
+
| ----------------------------------- | ------------- | ------------------------------------------------------------------------ |
|
|
88
|
+
| `test-codemode-sandbox.md` | sandbox | Sandbox basics, API discoverability, security, readonly, state isolation |
|
|
89
|
+
| `test-codemode-core.md` | core | 14 |
|
|
90
|
+
| `test-codemode-json.md` | json | 24 |
|
|
91
|
+
| `test-codemode-text.md` | text | 19N/14W |
|
|
92
|
+
| `test-codemode-stats.md` | stats | 22N/16W |
|
|
93
|
+
| `test-codemode-vector.md` | vector | 11 |
|
|
94
|
+
| `test-codemode-admin.md` | admin | 26 |
|
|
95
|
+
| `test-codemode-transactions.md` | transactions | 8 `[NATIVE ONLY]` |
|
|
96
|
+
| `test-codemode-geo.md` | geo | 11N/4W |
|
|
97
|
+
| `test-codemode-introspection.md` | introspection | 9 |
|
|
98
|
+
| `test-codemode-migration.md` | migration | 6 |
|
|
99
|
+
| `test-codemode-wasm-degradation.md` | cross-group | WASM-only graceful degradation |
|
|
100
|
+
|
|
101
|
+
**Total**: 151 Native / 125 WASM tools across 10 groups + 1 sandbox prompt + 1 WASM degradation prompt.
|
|
102
|
+
|
|
103
|
+
## Recommended Execution Order
|
|
104
|
+
|
|
105
|
+
1. **`test-codemode-sandbox.md`** — Run first. Validates the sandbox execution environment (return values, API discoverability, security blocks, readonly mode, state isolation). If this fails, subsequent prompts will not work correctly.
|
|
106
|
+
2. **`test-codemode-core.md`** — Run second. Tests the core tool group (read/write queries, tables, indexes, parameter binding).
|
|
107
|
+
3. **Remaining group prompts** — Run in any order: `json`, `text`, `stats`, `vector`, `admin`, `transactions`, `geo`, `introspection`, `migration`.
|
|
108
|
+
4. **`test-codemode-wasm-degradation.md`** — Run last, WASM only. Validates graceful degradation patterns.
|
|
109
|
+
|
|
110
|
+
## Tool Groups Available
|
|
111
|
+
|
|
112
|
+
1. `core`
|
|
113
|
+
2. `json`
|
|
114
|
+
3. `text`
|
|
115
|
+
4. `stats`
|
|
116
|
+
5. `vector`
|
|
117
|
+
6. `admin`
|
|
118
|
+
7. `transactions`
|
|
119
|
+
8. `geo`
|
|
120
|
+
9. `introspection`
|
|
121
|
+
10. `migration`
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
# db-mcp Code Mode Testing: [admin]
|
|
2
|
+
|
|
3
|
+
> [!IMPORTANT]
|
|
4
|
+
> **Do not track progress in this file.** Track your test progress, coverage matrix, and findings in your internal task tracking system (artifact). However, you SHOULD edit this file to fix any factual errors, broken code, or incorrect assertions in the test prompts.
|
|
5
|
+
> If there is nothing to fix, don't update UNRELEASED.md.
|
|
6
|
+
> We're currently testing Native mode.
|
|
7
|
+
|
|
8
|
+
**Step 1:** Read `C:\Users\chris\Desktop\db-mcp\src\constants\server-instructions\gotchas.md` using `view_file`.
|
|
9
|
+
|
|
10
|
+
**Step 2:** Conduct an exhaustive test of the **admin** tool group using ONLY `sqlite_execute_code`. Do not use direct tool calls or terminal.
|
|
11
|
+
|
|
12
|
+
**Step 3:** The agent should update C:\Users\chris\Desktop\db-mcp\UNRELEASED.md with any/all changes/fixes.
|
|
13
|
+
|
|
14
|
+
## WASM Mode
|
|
15
|
+
|
|
16
|
+
> When testing against a **WASM backend** (`--sqlite` / sql.js), apply these adjustments:
|
|
17
|
+
|
|
18
|
+
- **Phase 1**: Item 2 (`pragmaCompileOptions`) — WASM shows `FTS3` instead of `FTS5`. Item 3 (filter `"FTS"`) — matches FTS3. Item 9 (`dbstat`) — WASM returns counts-only (no per-table storage).
|
|
19
|
+
- **Phase 3**: Item 13 (`listVirtualTables`) — `test_articles_fts` may appear but is not queryable. Item 16 (`createRtreeTable`) — returns `{success: false}` (R-Tree unavailable in WASM). Treat as **negative validation**.
|
|
20
|
+
- **Phase 4** (Backup/Restore): All 3 items (19-21) return `{success: false, error: "...WASM mode"}`. Treat as **negative validation** — verify the structured error, do not skip.
|
|
21
|
+
- **Phase 6** (CSV): Both items (25-26) return `{success: false}` (CSV extension unavailable in WASM). Treat as **negative validation**.
|
|
22
|
+
- All other phases are WASM-compatible.
|
|
23
|
+
|
|
24
|
+
## Reporting Format
|
|
25
|
+
|
|
26
|
+
- ❌ Fail: Tool errors or produces incorrect results
|
|
27
|
+
- ⚠️ Issue: Unexpected behavior or improvement opportunity
|
|
28
|
+
- 📦 Payload: Unnecessarily large response — monitor `metrics.tokenEstimate`.
|
|
29
|
+
|
|
30
|
+
## Test Database Schema
|
|
31
|
+
|
|
32
|
+
| Table | Rows | Key Columns |
|
|
33
|
+
| ----------------- | ---- | ------------------------------------------------------ |
|
|
34
|
+
| test_products | 16 | id, name, price, category, created_at |
|
|
35
|
+
| test_orders | 20 | id, product_id (FK→test_products), total_price, status |
|
|
36
|
+
| test_articles | 8 | id, title, body, author, category |
|
|
37
|
+
| test_articles_fts | — | FTS5 virtual table (title, body columns) |
|
|
38
|
+
|
|
39
|
+
> **CSV testing**: Use `C:\Users\chris\Desktop\db-mcp\test-server\sample.csv` (columns: id, name, category, price, quantity, created_at). **Absolute paths only** — relative paths resolve from IDE CWD.
|
|
40
|
+
|
|
41
|
+
## Testing Requirements
|
|
42
|
+
|
|
43
|
+
> [!CAUTION]
|
|
44
|
+
> **Zero tolerance for raw MCP errors.** Report as ❌.
|
|
45
|
+
|
|
46
|
+
1. **Batched scripting**: Bundle checks with `failures` array.
|
|
47
|
+
2. **Error path testing**: Every tool with `{}` (Zod) and domain error.
|
|
48
|
+
3. **Token tracking**: Monitor `metrics.tokenEstimate`.
|
|
49
|
+
4. **Coverage Matrix**: `| Tool | Happy Path | Domain Error | Zod Error |`
|
|
50
|
+
5. **Deterministic checklist first**.
|
|
51
|
+
6. **Code Over Docs**: Fix the handler code if standards (Structured Errors/Zod) are violated. Do NOT change docs/prompts to accommodate broken code.
|
|
52
|
+
|
|
53
|
+
## Structured Error Response Pattern
|
|
54
|
+
|
|
55
|
+
Handler error ✅ = JSON with `success` + `error`. MCP error ❌ = raw text, `isError: true`.
|
|
56
|
+
|
|
57
|
+
## Cleanup
|
|
58
|
+
|
|
59
|
+
- Temporary tables: `temp_*` prefix. Views: `temp_view_*` prefix. Drop at end of script.
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Phase 1: Pragma & Inspection — Happy Paths (batched)
|
|
64
|
+
|
|
65
|
+
1. `sqlite.admin.pragmaDatabaseList()` → verify database path matches `test.db`
|
|
66
|
+
2. `sqlite.admin.pragmaCompileOptions()` → list of compile options
|
|
67
|
+
3. `sqlite.admin.pragmaCompileOptions({filter: "FTS"})` → filtered to FTS options
|
|
68
|
+
4. `sqlite.admin.pragmaSettings({pragma: "journal_mode"})` → `{value: "wal"}`
|
|
69
|
+
5. `sqlite.admin.pragmaTableInfo({table: "test_products"})` → columns: id, name, description, price, category, created_at
|
|
70
|
+
6. `sqlite.admin.indexStats()` → index statistics
|
|
71
|
+
7. `sqlite.admin.integrityCheck()` → `ok`
|
|
72
|
+
8. `sqlite.admin.analyze()` → success
|
|
73
|
+
9. `sqlite.admin.dbstat({summarize: true})` → per-table storage
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Phase 2: View Management (batched)
|
|
78
|
+
|
|
79
|
+
10. `sqlite.admin.createView({viewName: "temp_view_orders", selectQuery: "SELECT product_id, COUNT(*) as order_count, SUM(total_price) as revenue FROM test_orders GROUP BY product_id"})` → success
|
|
80
|
+
11. `sqlite.admin.listViews()` → `temp_view_orders` present
|
|
81
|
+
12. `sqlite.admin.dropView({viewName: "temp_view_orders"})` → success
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Phase 3: Virtual Tables (batched)
|
|
86
|
+
|
|
87
|
+
13. `sqlite.admin.listVirtualTables()` → `test_articles_fts` present
|
|
88
|
+
14. `sqlite.admin.virtualTableInfo({tableName: "test_articles_fts"})` → module and column info
|
|
89
|
+
15. `sqlite.admin.generateSeries({start: 1, stop: 5, step: 1})` → 5 values
|
|
90
|
+
16. `sqlite.admin.createRtreeTable({tableName: "temp_cm_rtree", dimensions: 2})` → R-Tree created
|
|
91
|
+
17. `sqlite.admin.createSeriesTable({tableName: "temp_cm_series", start: 1, stop: 10})` → regular table with 10 rows
|
|
92
|
+
18. Cleanup: drop `temp_cm_rtree` (virtual) and `temp_cm_series` (regular)
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Phase 4: Backup/Restore (batched)
|
|
97
|
+
|
|
98
|
+
> Use absolute path for backup: `C:\Users\chris\Desktop\db-mcp\test-server\test-backup.db`
|
|
99
|
+
|
|
100
|
+
19. `sqlite.admin.backup({targetPath: "C:\\Users\\chris\\Desktop\\db-mcp\\test-server\\test-backup.db"})` → success
|
|
101
|
+
20. `sqlite.admin.verifyBackup({backupPath: "C:\\Users\\chris\\Desktop\\db-mcp\\test-server\\test-backup.db"})` → integrity verified
|
|
102
|
+
21. `sqlite.admin.restore({sourcePath: "C:\\Users\\chris\\Desktop\\db-mcp\\test-server\\test-backup.db"})` → restore success
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Phase 5: Optimization (batched)
|
|
107
|
+
|
|
108
|
+
22. `sqlite.admin.vacuum()` → success
|
|
109
|
+
23. `sqlite.admin.optimize()` → optimization details
|
|
110
|
+
24. `sqlite.admin.pragmaOptimize()` → distinct from `optimize` — runs `PRAGMA optimize`
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Phase 6: CSV (batched)
|
|
115
|
+
|
|
116
|
+
> Use absolute path: `C:\Users\chris\Desktop\db-mcp\test-server\sample.csv`
|
|
117
|
+
|
|
118
|
+
25. `sqlite.admin.analyzeCsvSchema({filePath: "C:\\Users\\chris\\Desktop\\db-mcp\\test-server\\sample.csv"})` → inferred column types
|
|
119
|
+
26. `sqlite.admin.createCsvTable({tableName: "temp_cm_csv", filePath: "C:\\Users\\chris\\Desktop\\db-mcp\\test-server\\sample.csv"})` → virtual table
|
|
120
|
+
27. Cleanup: drop `temp_cm_csv` (virtual)
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Phase 7: Insights
|
|
125
|
+
|
|
126
|
+
28. `sqlite.admin.appendInsight({insight: "Test insight from codemode"})` → success
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Phase 8: Admin Domain Errors (batched)
|
|
131
|
+
|
|
132
|
+
🔴 29. `sqlite.admin.pragmaTableInfo({table: "nonexistent_xyz"})` → report behavior
|
|
133
|
+
🔴 30. `sqlite.admin.virtualTableInfo({tableName: "nonexistent_xyz"})` → `{success: false}`
|
|
134
|
+
🔴 31. `sqlite.admin.verifyBackup({backupPath: "nonexistent_file.db"})` → `{success: false}`
|
|
135
|
+
🔴 32. `sqlite.admin.dropView({viewName: "nonexistent_xyz", ifExists: false})` → `{success: false}`
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Phase 9: Admin Zod Validation (batched)
|
|
140
|
+
|
|
141
|
+
🔴 33. `sqlite.admin.backup({})` → `{success: false}`
|
|
142
|
+
🔴 34. `sqlite.admin.restore({})` → `{success: false}`
|
|
143
|
+
🔴 35. `sqlite.admin.verifyBackup({})` → `{success: false}`
|
|
144
|
+
🔴 36. `sqlite.admin.pragmaTableInfo({})` → `{success: false}`
|
|
145
|
+
🔴 37. `sqlite.admin.pragmaSettings({})` → `{success: false}`
|
|
146
|
+
🔴 38. `sqlite.admin.appendInsight({})` → `{success: false}`
|
|
147
|
+
🔴 39. `sqlite.admin.createView({})` → `{success: false}`
|
|
148
|
+
🔴 40. `sqlite.admin.dropView({})` → `{success: false}`
|
|
149
|
+
🔴 41. `sqlite.admin.virtualTableInfo({})` → `{success: false}`
|
|
150
|
+
🔴 42. `sqlite.admin.dropVirtualTable({})` → `{success: false}`
|
|
151
|
+
🔴 43. `sqlite.admin.createCsvTable({})` → `{success: false}`
|
|
152
|
+
🔴 44. `sqlite.admin.analyzeCsvSchema({})` → `{success: false}`
|
|
153
|
+
🔴 45. `sqlite.admin.createRtreeTable({})` → `{success: false}`
|
|
154
|
+
🔴 46. `sqlite.admin.createSeriesTable({})` → `{success: false}`
|
|
155
|
+
🔴 47. `sqlite.admin.generateSeries({})` → `{success: false}`
|
|
156
|
+
🔴 48. `sqlite.admin.dbstat({})` → `{success: false}` or success (no required params)
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Phase 9.5: Gotcha Edge Cases (batched)
|
|
161
|
+
|
|
162
|
+
49. `sqlite.admin.generateSeries({start: 1, stop: 10, step: 2})` → 5 values: 1, 3, 5, 7, 9 (non-default step value)
|
|
163
|
+
50. `sqlite.admin.pragmaSettings({pragma: "cache_size", value: "2000"})` → set cache_size, then `sqlite.admin.pragmaSettings({pragma: "cache_size"})` → verify read-back returns the set value
|
|
164
|
+
51. `sqlite.admin.createSeriesTable({tableName: "temp_cm_series_regular", start: 1, stop: 5})` → creates a REGULAR table (not virtual). Verify with `sqlite.core.describeTable({table: "temp_cm_series_regular"})` → success, then `sqlite.core.dropTable({table: "temp_cm_series_regular"})` → success (gotcha #15: use `dropTable`, not `dropVirtualTable`)
|
|
165
|
+
52. `sqlite.admin.dropVirtualTable({tableName: "test_products"})` → `{success: false}` — test_products is a regular table, not a virtual table (domain error)
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## Phase 10: Multi-Step Workflow
|
|
170
|
+
|
|
171
|
+
### 10.1 — Database health check pipeline
|
|
172
|
+
|
|
173
|
+
```javascript
|
|
174
|
+
const failures = [];
|
|
175
|
+
const integrity = await sqlite.admin.integrityCheck();
|
|
176
|
+
if (integrity.integrity !== "ok") failures.push("integrity check failed");
|
|
177
|
+
|
|
178
|
+
const journal = await sqlite.admin.pragmaSettings({ pragma: "journal_mode" });
|
|
179
|
+
if (journal.value !== "wal")
|
|
180
|
+
failures.push(`expected WAL, got ${journal.value}`);
|
|
181
|
+
|
|
182
|
+
const storage = await sqlite.admin.dbstat({ summarize: true });
|
|
183
|
+
const views = await sqlite.admin.listViews();
|
|
184
|
+
const vtables = await sqlite.admin.listVirtualTables();
|
|
185
|
+
|
|
186
|
+
return {
|
|
187
|
+
failures,
|
|
188
|
+
success: failures.length === 0,
|
|
189
|
+
summary: {
|
|
190
|
+
integrity: "ok",
|
|
191
|
+
journalMode: journal.value,
|
|
192
|
+
viewCount: views?.views?.length,
|
|
193
|
+
virtualTableCount: vtables?.virtualTables?.length,
|
|
194
|
+
},
|
|
195
|
+
};
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### 10.2 — View lifecycle
|
|
199
|
+
|
|
200
|
+
```javascript
|
|
201
|
+
const failures = [];
|
|
202
|
+
await sqlite.admin.createView({
|
|
203
|
+
viewName: "temp_view_cm_test",
|
|
204
|
+
selectQuery: "SELECT COUNT(*) as n FROM test_products",
|
|
205
|
+
});
|
|
206
|
+
const views = await sqlite.admin.listViews();
|
|
207
|
+
const found = views.views?.some((v) => v.name === "temp_view_cm_test");
|
|
208
|
+
if (!found) failures.push("view not found after creation");
|
|
209
|
+
await sqlite.admin.dropView({ viewName: "temp_view_cm_test" });
|
|
210
|
+
return { failures, success: failures.length === 0 };
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## Post-Test Procedures
|
|
216
|
+
|
|
217
|
+
1. **Cleanup**: Drop `temp_*` tables, views, and virtual tables
|
|
218
|
+
2. **Triage findings**: Create implementation plan if issues found
|
|
219
|
+
3. **Scope of fixes**: Handler code, server-instructions, this prompt
|
|
220
|
+
4. **Validate**: Instruct the user to run the test suite (Vitest/Playwright), lint, and typecheck. Do NOT run them yourself.
|
|
221
|
+
5. **Commit**: Stage and commit — do NOT push
|
|
222
|
+
6. **Token audit**: Report most expensive block
|
|
223
|
+
7. **Final summary**: After testing/re-testing
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
# db-mcp Code Mode Testing: [core]
|
|
2
|
+
|
|
3
|
+
> [!IMPORTANT]
|
|
4
|
+
> **Do not track progress in this file.** Track your test progress, coverage matrix, and findings in your internal task tracking system (artifact). However, you SHOULD edit this file to fix any factual errors, broken code, or incorrect assertions in the test prompts.
|
|
5
|
+
> If there is nothing to fix, don't update UNRELEASED.md.
|
|
6
|
+
> We're currently testing Native mode.
|
|
7
|
+
|
|
8
|
+
**Step 1:** Read `C:\Users\chris\Desktop\db-mcp\src\constants\server-instructions\gotchas.md` using `view_file`.
|
|
9
|
+
|
|
10
|
+
**Step 2:** Conduct an exhaustive test of the **core** tool group using ONLY `sqlite_execute_code`. Do not use direct tool calls or terminal.
|
|
11
|
+
|
|
12
|
+
**Step 3:** The agent should update C:\Users\chris\Desktop\db-mcp\UNRELEASED.md with any/all changes/fixes.
|
|
13
|
+
|
|
14
|
+
## WASM Mode
|
|
15
|
+
|
|
16
|
+
> When testing against a **WASM backend** (`--sqlite` / sql.js): All 14 core tools are fully WASM-compatible. No phases to skip or adjust.
|
|
17
|
+
|
|
18
|
+
## Reporting Format
|
|
19
|
+
|
|
20
|
+
- ❌ Fail: Tool errors or produces incorrect results (include error message)
|
|
21
|
+
- ⚠️ Issue: Unexpected behavior or improvement opportunity
|
|
22
|
+
- 📦 Payload: Unnecessarily large response — **blocking, equally important as ❌ bugs**. You **MUST** monitor `metrics.tokenEstimate` for every operation. Report the response size in tokens/KB and suggest optimization.
|
|
23
|
+
|
|
24
|
+
## Test Database Schema
|
|
25
|
+
|
|
26
|
+
| Table | Rows | Key Columns |
|
|
27
|
+
| ----------------- | ---- | ------------------------------------------------------------------------------------------- |
|
|
28
|
+
| test_products | 16 | id, name, description, price (REAL), category (TEXT lowercase), created_at |
|
|
29
|
+
| test_orders | 20 | id, product_id (FK→test_products), customer_name, quantity, total_price, order_date, status |
|
|
30
|
+
| test_jsonb_docs | 6 | id, doc (JSON), metadata (JSON), tags (JSON array), created_at |
|
|
31
|
+
| test_articles | 8 | id, title, body, author, category, published_at |
|
|
32
|
+
| test_users | 9 | id, username, email, phone, bio, created_at |
|
|
33
|
+
| test_measurements | 200 | id, sensor_id (INT 1-5), temperature, humidity, pressure, measured_at |
|
|
34
|
+
| test_embeddings | 20 | id, content, category, embedding (8-dim JSON array) |
|
|
35
|
+
| test_locations | 15 | id, name, city, latitude, longitude, type |
|
|
36
|
+
| test_categories | 17 | id, name, path, level |
|
|
37
|
+
| test_events | 100 | id, event_type, user_id (INT), payload (JSON), event_date |
|
|
38
|
+
|
|
39
|
+
> **Note:** `sensor_id` is INTEGER (1-5). String values use **lowercase**. Do **not** pass `readonly: true` unless specifically testing readonly filtering.
|
|
40
|
+
|
|
41
|
+
## Testing Requirements
|
|
42
|
+
|
|
43
|
+
> [!CAUTION]
|
|
44
|
+
> **Zero tolerance for raw MCP errors.** Any response that is a raw MCP error (no `success` field) is a bug — report as ❌.
|
|
45
|
+
|
|
46
|
+
1. **Batched scripting**: Bundle multiple checks into single `sqlite_execute_code` calls. Use a `failures` array pattern.
|
|
47
|
+
2. **Error path testing**: For **every** tool, test with `{}` (Zod) and a domain error. Both must return `{success: false, error: "..."}`.
|
|
48
|
+
3. **Token tracking**: Monitor `metrics.tokenEstimate` on every response. Report the most expensive block.
|
|
49
|
+
4. **Strict Coverage Matrix**: Maintain in `tmp/task.md`: `| Tool | Happy Path | Domain Error | Zod Error |`
|
|
50
|
+
5. **Deterministic checklist first**: Complete ALL numbered items before freeform exploration.
|
|
51
|
+
6. **Code Over Docs**: Fix the handler code if standards (Structured Errors/Zod) are violated. Do NOT change docs/prompts to accommodate broken code.
|
|
52
|
+
|
|
53
|
+
## Structured Error Response Pattern
|
|
54
|
+
|
|
55
|
+
```json
|
|
56
|
+
{ "success": false, "error": "Human-readable error message" }
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
| Type | What you see | Verdict |
|
|
60
|
+
| -------------------- | --------------------------------------------- | ------- |
|
|
61
|
+
| **Handler error** ✅ | JSON object with `success` and `error` fields | Correct |
|
|
62
|
+
| **MCP error** ❌ | Raw text, `isError: true`, no `success` field | Bug |
|
|
63
|
+
|
|
64
|
+
### Zod Refinement Leak Pattern
|
|
65
|
+
|
|
66
|
+
`.partial()` does NOT strip `.min(N)` / `.max(N)` refinements. If `{}` or invalid values trigger raw MCP `-32602` instead of handler error, report as ❌.
|
|
67
|
+
|
|
68
|
+
### Output Schema Validation Errors
|
|
69
|
+
|
|
70
|
+
If valid inputs return raw MCP `-32602` mentioning "output schema", report as ❌.
|
|
71
|
+
|
|
72
|
+
## Batched Script Pattern
|
|
73
|
+
|
|
74
|
+
```javascript
|
|
75
|
+
const failures = [];
|
|
76
|
+
|
|
77
|
+
// Happy path
|
|
78
|
+
const count = await sqlite.core.readQuery({
|
|
79
|
+
query: "SELECT COUNT(*) AS n FROM test_products",
|
|
80
|
+
});
|
|
81
|
+
if (!count.rows || count.rows[0].n !== 16)
|
|
82
|
+
failures.push("readQuery: expected 16 products");
|
|
83
|
+
|
|
84
|
+
// Domain error
|
|
85
|
+
const err = await sqlite.core.describeTable("nonexistent_xyz");
|
|
86
|
+
if (err.success !== false)
|
|
87
|
+
failures.push("describeTable(nonexistent): expected {success: false}");
|
|
88
|
+
|
|
89
|
+
// Zod empty params
|
|
90
|
+
const zod = await sqlite.core.createTable({});
|
|
91
|
+
if (zod.success !== false)
|
|
92
|
+
failures.push("createTable({}): expected validation error");
|
|
93
|
+
|
|
94
|
+
return { failures, success: failures.length === 0 };
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Cleanup Conventions
|
|
98
|
+
|
|
99
|
+
- Temporary tables: `temp_*` prefix. Drop at end of each script.
|
|
100
|
+
- If DROP fails due to lock, note and move on.
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Phase 1: Core Group — Happy Paths (batched)
|
|
105
|
+
|
|
106
|
+
> **Instructions**: Construct a single `sqlite_execute_code` script to execute the numbered items below. Use the `sqlite.*` namespace. Compare responses against expected results and push deviations to a `failures` array.
|
|
107
|
+
|
|
108
|
+
**Read/Query tools:**
|
|
109
|
+
|
|
110
|
+
1. `sqlite.core.readQuery({query: "SELECT COUNT(*) AS n FROM test_products"})` → `{rows: [{n: 16}]}`
|
|
111
|
+
2. `sqlite.core.readQuery("SELECT name, price FROM test_products WHERE price > 500")` → 1 result: `Laptop Pro 15` (1299.99)
|
|
112
|
+
3. `sqlite.core.readQuery({query: "SELECT COUNT(*) AS n FROM test_orders WHERE status = 'completed'"})` → `{rows: [{n: 8}]}`
|
|
113
|
+
4. `sqlite.core.listTables()` → tables array includes `test_products`, `test_orders`, etc.
|
|
114
|
+
5. `sqlite.core.describeTable("test_products")` → columns include `id` (INTEGER), `name` (TEXT), `price` (REAL)
|
|
115
|
+
6. `sqlite.core.getIndexes({table: "test_orders"})` → includes `idx_orders_status`
|
|
116
|
+
|
|
117
|
+
**Convenience tools:**
|
|
118
|
+
|
|
119
|
+
7. `sqlite.core.count({table: "test_products"})` → `{count: 16}`
|
|
120
|
+
8. `sqlite.core.count({table: "test_products", column: "category", distinct: true})` → distinct category count
|
|
121
|
+
9. `sqlite.core.exists({table: "test_products", whereClause: "price > 1000"})` → `{exists: true}`
|
|
122
|
+
10. `sqlite.core.exists({table: "test_products", whereClause: "price > 99999"})` → `{exists: false}`
|
|
123
|
+
|
|
124
|
+
**Write tools (use temp tables):**
|
|
125
|
+
|
|
126
|
+
11. `sqlite.core.createTable({table: "temp_cm_core", columns: [{name: "id", type: "INTEGER", primaryKey: true}, {name: "name", type: "TEXT"}, {name: "value", type: "REAL"}]})` → success
|
|
127
|
+
12. `sqlite.core.writeQuery("INSERT INTO temp_cm_core (id, name, value) VALUES (1, 'alpha', 10.5), (2, 'beta', 20.0)")` → `{rowsAffected: 2}`
|
|
128
|
+
13. `sqlite.core.upsert({table: "temp_cm_core", data: {id: 1, name: "alpha_updated", value: 15.0}, conflictColumn: "id"})` → success, row 1 updated
|
|
129
|
+
14. `sqlite.core.batchInsert({table: "temp_cm_core", rows: [{id: 3, name: "gamma", value: 30.0}, {id: 4, name: "delta", value: 40.0}]})` → 2 rows inserted
|
|
130
|
+
15. `sqlite.core.count({table: "temp_cm_core"})` → `{count: 4}`
|
|
131
|
+
16. `sqlite.core.truncate({table: "temp_cm_core"})` → success
|
|
132
|
+
17. `sqlite.core.count({table: "temp_cm_core"})` → `{count: 0}`
|
|
133
|
+
|
|
134
|
+
**Index lifecycle:**
|
|
135
|
+
|
|
136
|
+
18. `sqlite.core.writeQuery("INSERT INTO temp_cm_core (id, name) VALUES (1, 'test')")` → re-populate
|
|
137
|
+
19. `sqlite.core.createIndex({table: "temp_cm_core", columns: ["name"], indexName: "idx_temp_cm_name"})` → success
|
|
138
|
+
20. `sqlite.core.getIndexes({table: "temp_cm_core"})` → includes `idx_temp_cm_name`
|
|
139
|
+
21. `sqlite.core.dropIndex({indexName: "idx_temp_cm_name"})` → success
|
|
140
|
+
22. `sqlite.core.dropTable({table: "temp_cm_core"})` → success
|
|
141
|
+
|
|
142
|
+
**Parameter binding:**
|
|
143
|
+
|
|
144
|
+
23. `sqlite.core.readQuery({query: "SELECT name, price FROM test_products WHERE price > ?", params: [500]})` → 1 result: `Laptop Pro 15` (1299.99)
|
|
145
|
+
24. `sqlite.core.readQuery({query: "SELECT name FROM test_products WHERE category = ? AND price < ?", params: ["electronics", 100]})` → verify multi-parameter binding returns correct subset
|
|
146
|
+
|
|
147
|
+
**Boundary tests:**
|
|
148
|
+
|
|
149
|
+
25. `sqlite.core.dropTable({table: "nonexistent_drop_test", ifExists: true})` → succeeds silently (ifExists prevents error on nonexistent table)
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Phase 2: Core Group — Domain & Separation Errors (batched)
|
|
154
|
+
|
|
155
|
+
🔴 26. `sqlite.core.readQuery({query: "SELECT * FROM nonexistent_xyz"})` → `{success: false}`
|
|
156
|
+
🔴 27. `sqlite.core.writeQuery("INSERT INTO nonexistent_xyz VALUES (1)")` → `{success: false}`
|
|
157
|
+
🔴 28. `sqlite.core.describeTable("nonexistent_xyz")` → `{success: false}` mentioning table
|
|
158
|
+
🔴 29. `sqlite.core.getIndexes({table: "nonexistent_xyz"})` → report behavior
|
|
159
|
+
🔴 30. `sqlite.core.dropTable({table: "nonexistent_xyz", ifExists: false})` → `{success: false}`
|
|
160
|
+
🔴 31. `sqlite.core.count({table: "nonexistent_xyz"})` → `{success: false}`
|
|
161
|
+
🔴 32. `sqlite.core.exists({table: "nonexistent_xyz"})` → `{success: false}`
|
|
162
|
+
🔴 33. `sqlite.core.upsert({table: "nonexistent_xyz", data: {id: 1}})` → `{success: false}`
|
|
163
|
+
🔴 34. `sqlite.core.batchInsert({table: "nonexistent_xyz", rows: [{id: 1}]})` → `{success: false}`
|
|
164
|
+
🔴 35. `sqlite.core.truncate({table: "nonexistent_xyz"})` → `{success: false}`
|
|
165
|
+
|
|
166
|
+
**Write/read separation (gotcha #1):**
|
|
167
|
+
|
|
168
|
+
🔴 36. `sqlite.core.writeQuery("SELECT * FROM test_products")` → `{success: false}` — writeQuery rejects SELECT statements
|
|
169
|
+
🔴 37. `sqlite.core.readQuery("INSERT INTO test_products (name) VALUES ('bad')")` → `{success: false}` — readQuery rejects INSERT/UPDATE/DELETE
|
|
170
|
+
|
|
171
|
+
**Boundary conditions:**
|
|
172
|
+
|
|
173
|
+
🔴 38. `sqlite.core.batchInsert({table: "test_products", rows: []})` → report behavior (empty rows array)
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## Phase 3: Core Group — Zod Validation (batched)
|
|
178
|
+
|
|
179
|
+
🔴 39. `sqlite.core.readQuery({})` → `{success: false}` handler error
|
|
180
|
+
🔴 40. `sqlite.core.writeQuery({})` → `{success: false}` handler error
|
|
181
|
+
🔴 41. `sqlite.core.createTable({})` → `{success: false}` handler error
|
|
182
|
+
🔴 42. `sqlite.core.describeTable({})` → `{success: false}` handler error
|
|
183
|
+
🔴 43. `sqlite.core.dropTable({})` → `{success: false}` handler error
|
|
184
|
+
🔴 44. `sqlite.core.createIndex({})` → `{success: false}` handler error
|
|
185
|
+
🔴 45. `sqlite.core.dropIndex({})` → `{success: false}` handler error
|
|
186
|
+
🔴 46. `sqlite.core.upsert({})` → `{success: false}` handler error
|
|
187
|
+
🔴 47. `sqlite.core.batchInsert({})` → `{success: false}` handler error
|
|
188
|
+
🔴 48. `sqlite.core.count({})` → `{success: false}` handler error
|
|
189
|
+
🔴 49. `sqlite.core.exists({})` → `{success: false}` handler error
|
|
190
|
+
🔴 50. `sqlite.core.truncate({})` → `{success: false}` handler error
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## Phase 4: Multi-Step Workflow (4 tests)
|
|
195
|
+
|
|
196
|
+
### 4.1 — ETL pipeline
|
|
197
|
+
|
|
198
|
+
```javascript
|
|
199
|
+
await sqlite.core.createTable({
|
|
200
|
+
table: "temp_cm_etl",
|
|
201
|
+
columns: [
|
|
202
|
+
{ name: "id", type: "INTEGER", primaryKey: true },
|
|
203
|
+
{ name: "raw", type: "TEXT" },
|
|
204
|
+
{ name: "processed", type: "TEXT" },
|
|
205
|
+
],
|
|
206
|
+
});
|
|
207
|
+
for (let i = 1; i <= 5; i++) {
|
|
208
|
+
await sqlite.core.writeQuery({
|
|
209
|
+
query: `INSERT INTO temp_cm_etl (raw) VALUES ('item_${i}')`,
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
await sqlite.core.writeQuery("UPDATE temp_cm_etl SET processed = UPPER(raw)");
|
|
213
|
+
const result = await sqlite.core.readQuery("SELECT * FROM temp_cm_etl");
|
|
214
|
+
await sqlite.core.dropTable({ table: "temp_cm_etl", ifExists: true });
|
|
215
|
+
return result;
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### 4.2 — Schema introspection + query
|
|
219
|
+
|
|
220
|
+
```javascript
|
|
221
|
+
const tables = await sqlite.core.listTables();
|
|
222
|
+
const first = tables.tables[0].name;
|
|
223
|
+
const schema = await sqlite.core.describeTable(first);
|
|
224
|
+
const sample = await sqlite.core.readQuery({
|
|
225
|
+
query: `SELECT * FROM ${first} LIMIT 3`,
|
|
226
|
+
});
|
|
227
|
+
return {
|
|
228
|
+
table: first,
|
|
229
|
+
columnCount: schema.columns?.length,
|
|
230
|
+
sampleRows: sample.rows?.length,
|
|
231
|
+
};
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### 4.3 — Loop with accumulator
|
|
235
|
+
|
|
236
|
+
```javascript
|
|
237
|
+
const tables = await sqlite.core.listTables();
|
|
238
|
+
const counts = {};
|
|
239
|
+
for (const t of tables.tables.slice(0, 5)) {
|
|
240
|
+
const r = await sqlite.core.count({ table: t.name });
|
|
241
|
+
counts[t.name] = r.count;
|
|
242
|
+
}
|
|
243
|
+
return counts;
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### 4.4 — Schema mutation + introspection verification
|
|
247
|
+
|
|
248
|
+
```javascript
|
|
249
|
+
const failures = [];
|
|
250
|
+
// Create table and verify it appears in introspection
|
|
251
|
+
await sqlite.core.createTable({
|
|
252
|
+
table: "temp_cm_intro_check",
|
|
253
|
+
columns: [
|
|
254
|
+
{ name: "id", type: "INTEGER", primaryKey: true },
|
|
255
|
+
{ name: "data", type: "TEXT" },
|
|
256
|
+
],
|
|
257
|
+
});
|
|
258
|
+
const snapshot = await sqlite.introspection.schemaSnapshot({ compact: true });
|
|
259
|
+
const found = snapshot.snapshot?.tables?.some(
|
|
260
|
+
(t) => t.name === "temp_cm_intro_check",
|
|
261
|
+
);
|
|
262
|
+
if (!found) failures.push("temp table not in schema snapshot after creation");
|
|
263
|
+
|
|
264
|
+
// Drop table and verify it's gone
|
|
265
|
+
await sqlite.core.dropTable({ table: "temp_cm_intro_check" });
|
|
266
|
+
const after = await sqlite.introspection.schemaSnapshot({ compact: true });
|
|
267
|
+
const stillThere = after.snapshot?.tables?.some(
|
|
268
|
+
(t) => t.name === "temp_cm_intro_check",
|
|
269
|
+
);
|
|
270
|
+
if (stillThere) failures.push("temp table still in snapshot after drop");
|
|
271
|
+
|
|
272
|
+
return { failures, success: failures.length === 0 };
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
## Post-Test Procedures
|
|
278
|
+
|
|
279
|
+
1. **Cleanup**: Confirm all `temp_*` tables are removed
|
|
280
|
+
2. **Triage findings**: Create implementation plan if issues found
|
|
281
|
+
3. **Scope of fixes**: Handler code, server-instructions, test database, this prompt
|
|
282
|
+
4. **Validate**: Instruct the user to run the test suite (Vitest/Playwright), lint, and typecheck. Do NOT run them yourself.
|
|
283
|
+
5. **Commit**: Stage and commit — do NOT push
|
|
284
|
+
6. **Live re-test**: After server rebuild
|
|
285
|
+
7. **Token audit**: Report `metrics.tokenEstimate` for the most expensive block
|
|
286
|
+
8. **Final summary**: After testing/re-testing
|