07 — Task Breakdown
Format: P<phase>-T<n> · size S ≤ 1 d · M 2–3 d · L 4–5 d. Deps in brackets.
Phase 0 — Foundations
- [x] P0-T1 (M) pnpm workspace + TS strict + package skeletons (
core,driver-pg,protocol,extension,webview-ui) - [x] P0-T2 (M) esbuild extension bundle · Vite webview build · watch tasks ·
.vscode/launch.json - [x] P0-T3 (S)
package.jsoncontributes stub: activation events, one command, view container, icon placeholder - [x] P0-T4 (S) eslint +
dependency-cruiserboundary rules (core⊬vscode/pg;webview-ui⊬extension) - [x] P0-T5 (S) Vitest config + first unit test;
@vscode/test-electronharness stub - [x] P0-T6 (M) GitHub Actions: lint · typecheck · unit · VSIX artifact upload
- [x] P0-T7 (S)
docker-compose.test.yml— PG 13/15/17 + seeded fixture schema - [x] P0-T8 (S) Logger + output channel + secret redaction pass [S1.4]
Phase 1 — Connections + Explorer
- [x] P1-T1 (L)
DriverAdapter/Session/QueryHandle/DriverCapabilitiestypes +defineDriverregistry [P0-T1] - [x] P1-T2 (L)
driver-pgconnect: node-postgres pool, TLS modes, server-version probe,application_name,search_path,TimeZone - [x] P1-T3 (M) Out-of-band CancelRequest implementation + test against
pg_stat_activity - [x] P1-T4 (M) SSH tunnel via
ssh2: password / key+passphrase / agent, jump host,known_hostsverification [S2.3] - [x] P1-T5 (M) SecretStorage service +
SecretRefresolvers: keychain, env,.pgpass,pg_service.conf, prompt - [x] P1-T6 (M)
ConnectionProfilemodel + global store + workspace file store + JSON Schema (rejects secret literals) [S1.2] - [x] P1-T7 (L) Connection form webview, rendered from
connectionSchema; Test Connection; URI paste parser - [x] P1-T8 (S) Environment tag + color + read-only flag; status-bar and tree decoration
- [x] P1-T9 (M)
protocolpackage: zod-validated RPC envelope + typed client/host helpers [S5.2] - [x] P1-T10 (L)
IntrospectionPlanfor PG: databases, schemas, tables, views, matviews, foreign tables, functions, types, sequences, extensions — version-gated 13→17 - [x] P1-T11 (L) TreeDataProvider: lazy children, filter box, refresh, context menu, drag-reorder groups
- [x] P1-T12 (M) Metadata cache: TTL, eager DDL invalidation, disk persistence
- [x] P1-T13 (M) Integration tests vs docker PG 13/15/17 in CI
- [x] P1-T14 (S) Security test: grep entire storage dir for any credential after a full connect flow [S1.1]
Phase 2 — Query mode MVP → M1
Complete. The grid, wire encoding, and panel shell are shared components - query results mount the same
Gridas the data view. P2-T12 is covered by the integration suite rather than@vscode/test-electron; a real E2E harness is still outstanding.
- [x] P2-T1 (M) Editor↔connection binding: status bar picker, per-file persistence,
-- @pitta connection:directive - [x] P2-T2 (M) Statement splitter: dollar-quoting,
E'', nested comments,\meta-command subset - [x] P2-T3 (S) CodeLens
▶ Run · Explain · Explain Analyze+ keybindings + cancel command - [x] P2-T4 (L) Execution engine: multi-statement queue, per-statement result, timing,
commandTag, abort wiring - [x] P2-T5 (L) Results webview shell: tabbed panels, state restore across reload, theme tokens
- [x] P2-T6 (L) Grid v1: TanStack Virtual rows+cols, columnar store, type renderers,
NULLtoken, exactnumeric[04 §4] - [x] P2-T7 (M) Type handler table for PG: arrays, json/jsonb, ranges, enums, domains, composites, uuid, bytea, interval, timestamptz, bigint, numeric
- [x] P2-T8 (S) Messages tab — live
NOTICE/WARNING/RAISEstreaming - [x] P2-T9 (M) Statement analyzer v1 (heuristic) + guards: destructive confirm, unqualified-DML block, read-only enforcement [S4]
- [x] P2-T10 (S) Error surfacing:
SQLSTATE, message, hint, character position → editor squiggle - [x] P2-T11 (S) Copy-as TSV / CSV / JSON / Markdown /
INSERT - [x] P2-T12 (M) E2E test: open file, bind connection, run, assert grid contents
Phase 3 — UI mode: data view & editing
Remaining in this phase: P3-T9 (Structure panel tabs). DDL generation (P3-T10) ships as a read-only virtual
sqldocument rather than a webview tab, so it gets syntax highlighting, find, and Save As for free. Paging is still offset-based; keyset is implemented and tested inbuildSelectbut not yet wired into the data view.
- [x] P3-T1 (L)
buildSelect: filters + sorts + keyset paging,LIMIT/OFFSETfallback, params only [S3.1] - [x] P3-T2 (L) Table Data panel: grid reuse, generated-SQL bar, page controls, refresh
- [x] P3-T3 (M) Filter row UI: per-type operators and value editors
- [x] P3-T4 (M) Column state: show/hide/pin/reorder/resize, persisted per table
- [x] P3-T5 (L) Cell editors: text · exact-decimal · tri-state bool · date/time+tz · enum · JSON · array chips · bytea · FK picker
- [x] P3-T6 (L) Staged-edit store, dirty highlighting, DML preview diff, single-transaction apply, rollback, affected-row verification [04 §6]
- [x] P3-T7 (M) Insert / duplicate / delete row
- [x] P3-T8 (M) Updatability detection from
tableOid+columnAttr×pg_index;ctidopt-in; disabled-reason UI - [x] P3-T9 (L) Structure panel tabs: Columns · Indexes · Constraints · Triggers · Policies · Partitions · Statistics
- [x] P3-T10 (L)
generateDdlfor table/view/matview/function/type/sequence; round-trip test vspg_dump - [x] P3-T11 (M) Cell detail pane (long text / JSON tree / image / hex)
- [x] P3-T12 (M) Integration tests: edit-apply-verify against real PG, incl. rollback path
Phase 4 — SQL intelligence
- [x] P4-T1 (L)
@pgsql/parserWASM integration + parse cache (the maintained WASM build of libpg-query; ADR-026) - [x] P4-T2 (M) Replace heuristic analyzer with AST-based classification (destructive detection, statement kind, referenced objects)
- [x] P4-T3 (L) Completion provider: alias-aware columns, FROM-scope, functions w/ signatures, enum values, keyword ranking
- [x] P4-T4 (M) Hover provider: type, default, nullability, comment, size/row estimate
- [x] P4-T5 (M) Go-to-definition → DDL virtual doc; find-references across open
.sql - [x] P4-T6 (M) Semantic diagnostics: syntax errors, unknown relation, unknown qualified column (type mismatch not attempted - ADR-027)
- [x] P4-T7 (S) Formatter + format-on-save + snippets + user templates
- [x] P4-T8 (S) Completion latency benchmark: p95 1.1 ms on a 2 000-relation / 40 000-column fixture, budget 50 ms
Phase 5 — Productivity → M2 beta
P5-T3 landed early: streaming CSV/JSON/JSONL export from the results panel, written through a generator into a write stream. Not started: history, saved queries, CSV import, notebooks.
- [x] P5-T1 (M) Query history store (JSONL, rotation) + search UI + re-run + prod exclusion
- [x] P5-T2 (M) Saved queries tree over a workspace folder; parameter prompts → bind params
- [x] P5-T3 (L) Streaming exporters: CSV · JSON · JSONL · XLSX · SQL inserts, with progress + cancel
- [x] P5-T4 (L) CSV import: column mapping, type-coercion preview,
COPYfast path, error report - [x] P5-T5 (L) SQL Notebooks: serializer, controller, per-notebook connection (ADR-029), HTML/JSON/markdown outputs, export to
.sql - [x] P5-T6 (M) Onboarding walkthrough + README + docs skeleton
- [x] P5-T7 (S) Pre-release publish pipeline → Marketplace + Open VSX
Phase 6 — Postgres power
Plan visualizer, red-flag rules, plan diff, session monitor with blocking chains, and the health advisor are done. The lock inspector (P6-T5) is folded into the session monitor:
pg_blocking_pidsanswers the question a separatepg_locksview would, without a second panel. Remaining: LISTEN/NOTIFY panel, extensions and roles browser, publications/subscriptions, pgvector and PostGIS cell renderers.
- [x] P6-T1 (L) EXPLAIN JSON →
PlanNodemodel + interactive tree visualizer - [x] P6-T2 (M) Plan red-flag rules (estimate skew, seq scan on large table, external sort, lossy bitmap, nested-loop blowup)
- [x] P6-T3 (M) Plan diff between two runs
- [x] P6-T4 (M) Session monitor:
pg_stat_activitylive, blocking chain, cancel/terminate (guarded) - [x] P6-T5 (S) Lock inspector over
pg_locks - [x] P6-T6 (M) LISTEN/NOTIFY subscriber panel
- [x] P6-T7 (L) Health advisor queries + report UI + suggested DDL
- [x] P6-T8 (M) Extensions panel; roles/privileges browser
- [x] P6-T9 (S) Publications / subscriptions / replication slots listing
- [x] P6-T10 (M) pgvector + PostGIS cell renderers and snippets
Phase 7 — ERD + schema tooling
Complete. The generated migration opens as an ordinary SQL document and is applied through query mode, which already carries the guards (ADR-019), so there is no separate review panel or apply path.
- [x] P7-T1 (L) ERD canvas: dagre layout, FK edges, pan/zoom, drag, persist
- [x] P7-T2 (M) Neighbor filter, search, click-through to Structure
- [x] P7-T3 (M) PNG / SVG export
- [x] P7-T4 (L) Schema snapshot model + differ
- [x] P7-T5 (L) Migration SQL generation + review UI + apply flow (guarded)
- [x] P7-T6 (M) Migration file export (plain SQL / Flyway naming)
Phase 8 — Performance (v1.0 gate)
- [~] P8-T1 (L)
Forked— not needed, see ADR-023. Streaming 1M rows peaks at +10MB.QueryHostchild process - [~] P8-T2 (M)
Columnar store— not needed, see ADR-023. Encoding runs at 48M cells/s and the panel holds one page. - [x] P8-T3 (M) End-to-end cursor streaming + webview backpressure
- [x] P8-T4 (M) Benchmark suite in CI with hard budgets (Roadmap P8)
- [x] P8-T5 (M) Memory-leak soak test (200 panels, 1 000 queries, flat heap assertion)
- [x] P8-T6 (S) Cold-start audit: lazy activation, deferred driver import, activation < 200 ms
Phase 9 — Second driver
Complete, with one finding. The SQLite driver needed no core change. The capability audit did find three places where the host had leaked Postgres assumptions - row estimation, an exact-count cast, and the blank connection form's defaults - and fixing the first required one addition to the driver contract. See ADR-021.
- [x] P9-T1 (M) Driver conformance kit in
core/test - [x] P9-T2 (L)
driver-sqlitefull implementation - [x] P9-T3 (S) Capability-gating audit: every PG-only affordance hidden, not broken
- [x] P9-T4 (S) CI assertion — the driver PR's diff touches no core file
Phase 10 — Release
Everything that is code is done. What is left needs an account. The listing, the docs site and the community files landed; the publish itself needs a publisher on both marketplaces and two tokens, which is a decision rather than a task.
docs/13-RELEASE.mdis the runbook.
- [x] P10-T1 (M) Marketplace + Open VSX listing: categories and keywords tuned to what the Marketplace actually ranks,
pricing,qnapointed at Discussions rather than the Q&A tab nobody watches, andcapabilitiesdeclaring both untrusted-workspace and virtual-workspace support honestly — the guard settings are listed asrestrictedConfigurations, so VS Code itself ignores a workspace value for them in a workspace you have not trusted and a cloned repository cannot turn the confirmations off. The demo clips are specified rather than recorded (docs/13-RELEASE.mdsection 4) and their<img>block sits commented in the extension README: they are committed for the listing and excluded from the VSIX, becausevscerewrites relative links to raw GitHub URLs and a set of GIFs would otherwise be most of the download - [x] P10-T2 (L) VitePress docs site under
docs/, published to Pages by.github/workflows/docs.yml. Eight guide pages, ten connection recipes, the driver-authoring guide and the conformance-kit page, with the numbered design record kept as its own nav section rather than rewritten. The build fails on a dead internal link, so it is also the link check. The Remote-SSH/WSL/devcontainer caveat gets its own page and a translation table, because "localhostmeans the remote" is the single most common confusion (ADR-003) - [ ] P10-T3 (S) Telemetry opt-in flow + documented event list [S7] — open, and it is a decision, not a task. The setting exists, defaults to false, and has no implementation and no transport behind it. Either build one or drop the setting; a setting promising collection that never happens is the one option that is wrong
- [x] P10-T4 (S)
CONTRIBUTING.md,SECURITY.md, four issue templates plus a chooser routing vulnerabilities to private reporting, and a PR template whose checklist is the contract: capability gating, ADR-004 exactness, S1 secrets, S3 binding, and thecontract-changelabel. MIT license was already in place - [ ] P10-T5 (M) semantic-release, signed VSIX — partly done.
release.ymlalready verifies, packages, asserts the VSIX contents, gates publishing behind a reviewed environment, publishes to both marketplaces and cuts a GitHub release, and the changelog and the odd-minor pre-release channel are in place. What is missing is semantic-release itself (the version is bumped by hand, and the tag/manifest check catches the mistake that makes) and a signing certificate
Phase 11 — Multi-model contract generalization
Complete. The first five tasks landed with Redis (T4, T10, T9/T8, T11) before the phase itself was worked; the language, the result shapes, the conformance kit, the language-generic query surfaces and the echo driver landed together afterwards; the five partials were finished last. ADR-050 records one planned change that turned out to be unnecessary, and ADR-060 one that was done differently from how it was written down.
Contract work only. Every task here is a
contract-change-labelled PR by the rule in ADR-021, and PostgreSQL and SQLite behave identically at the end of it. Design:10-ENGINE-MODEL.md. Rationale: ADR-034.
- [x] P11-T1 (M)
EngineLanguageonDriverAdapter(optional, resolved throughlanguageOf, so a driver that says nothing still means SQL);Statement.sql→Statement.textacross core, every driver and the panels;formatCommandhook;splitForLanguagereplaces core's splitter at every call site; UI strings, pickers, progress and tooltips read the language'sdisplayName[10 §2] - [x] P11-T2 (M)
splitStatementsandformatCommandare driver methods and every shipped driver supplies both. Done differently from how the task was written, and ADR-060 says why: moving the scanner intodriver-pgwould have meant four copies of it, and would have fixed none of what was actually wrong. The scanner and the printer stay in core and take aSqlDialecteach driver passes, which found three real bugs the move would not have — a;inside a MySQL backtick identifier split a statement in two, a second/*in a MySQL or SQL Server buffer swallowed the rest of the file, andGOwas handed to SQL Server as if it were T-SQL while[odd;name]was cut down the middle. Core keeps PostgreSQL's dialect only as the floor for a.sqlfile bound to no connection. PostgreSQL is unchanged, since its dialect is what the old default was; SQLite changes in two ways that are both corrections — it has no psql backslash commands and no dollar quoting, and used to be handed both - [~] P11-T3 (M)
— not needed, see ADR-050: drivers classify through the existingclassifyCommandon the adapterparseStatementhook, and ADR-027's combining rule is untouched - [x] P11-T4 (L)
NodeDefinition.fetch+ tree paging +Load more+pitta.explorer.treePageSize[ADR-037] - [x] P11-T5 (M) Open
ObjectKind+NodeKindDescriptor: the type is(typeof OBJECT_KINDS)[number] | (string & {}), so it is a free string with the known kinds still autocompleting, and the explorer's two static tables are gone — the icon map and the folder-label map are nowdescribeNodeKind(driver, kind), layered per field so a driver overriding an icon does not silently turn the data view off, and the browsable-kind set is the descriptor's owncanOpenDatarather than a list of the engines that shipped first. A kind nobody described still draws, Title Cased with a neutral icon. The conformance kit asserts every kind a plan can emit is core's or the driver's, which is the typo check ADR-036 promised in place of the compiler's - [x] P11-T6 (M)
ResultShapeonQueryHandleand inDriverCapabilities.resultShapes, carried through the protocol into both panels; a status reply renders as a sentence and a single value as a value, and adocumentsresult says its columns were sampled [ADR-038] - [x] P11-T7 (L) Document projection: sampled column union,
inferredfields, stable ordering, one level of dotted flattening - [x] P11-T8 (L) Missing-vs-null, both directions. Reading was already done: the
MISSINGvalue in core, the{missing:true}wire cell, a grid token styled apart from NULL, filter-by-value offering exists/does-not-exist, and copy/export stating that they cannot carry the difference. Writing is now built — Remove field in the cell detail pane, where the field is named, rather than in a cell editor where clearing already lives. It stages the missing token, crosses the wire as one, reaches the driver as core'sMISSINGinRowEdit.set, and becomes$unseton MongoDB. Removing a field that is already absent is not an edit, and the host refuses the whole thing on an engine that declareddistinguishesMissing: falserather than writing NULL and calling it the same thing - [x] P11-T9 (M) Cursor page mode, end to end:
QueryHandle.nextCursor(), a host fetch path that reads it off the handle rather than throughqueryAll— the offset path is untouched — and a page control that degrades to Next/Previous when the engine has no offsets. In that mode the grid drops the jump to the first page, numbers rows within the page rather than against a total it does not have, and hides the exact count, which the host refuses outright rather than answering with a full scan; Previous works by remembering the cursors already handed out. Two things the offset path does that this one must not: asking for one row more than the page holds, which a cursor cannot give back, and reporting "more" from a row count rather than from the cursor. Redis keeps its offsets and its visibleSKIP(ADR-049); the echo driver exercises the cursor path, and the conformance kit now asserts it for any engine without offsets - [x] P11-T10 (M) Capability additions + session overlay, resolved for the UI.
ConnectionManager.capabilitiesFor(profileId, database?)overlays an already-open session and never connects — a question about what a connection can do must not be the thing that dials a production database — and every gate reads it: the server-activity command, the notification panel, and the data view's row-id fallback, document shape, atomicity promise and page mode. No call site readsdriver.capabilitiesto decide what to show any more. Before a session exists the answer is the engine's flags, which is the honest answer to "what could this connection do" - [x] P11-T11 (M) Non-atomic apply path: dialog wording, per-edit applied/not-applied report, degraded S4.5 verification [ADR-041]
- [x] P11-T12 (L) Conformance kit →
EngineFixture: the kit issues no statement of its own, builds everything through the adapter, and walks either introspection form. PG and SQLite re-pass throughsqlEngineFixture. Four new assertions: stable column union, missing-is-not-null, unknown-refused-on-prod, and which edits a failed non-atomic batch applied [10 §13] - [x] P11-T13 (M) Query mode, saved queries, history and notebooks are language-generic: directives and cell markers read any of the three comment styles, documents are matched against every registered engine's language rather than against
.sql, history records the language it was written in and reopens in it, saved queries list every engine's extension, and the manifest's when-clauses and activation events cover them - [x] P11-T14 (S) Echo driver in
test/echo-driver, run through the conformance kit intest/unit/echoDriver.test.ts: a newline-split non-SQL language, imperative paged introspection, all five result shapes, missing-not-null, cursor-only paging, a session that narrows capabilities, an unclassifiable command, and one edit that is two statements. Not shipped, not registered — this is the phase's exit test - [x] P11-T15 (S) Benchmark re-run, 28/28 green and measured against a build of the same tree without this work: first page of 1M 48 ms (was 48), stream 1M x 20 3.15 s at +0.7 MB (was 3.13 s), cell encoding 24M cells/s (was 24M), activation 91 ms (was 92, budget 200). No regression. Cold activation has drifted from ADR-023's number as three drivers were added since, which the baseline run shows is not Phase 11's doing
Phase 12 — MongoDB driver
Complete. The driver, the editor language, completion, hover, diagnostics, tree paging, the server level,
readSymbols, the sharding section, the red-flag rules, document import and Extended JSON export. The integration, conformance and security suites are green against MongoDB 7 standalone and a replica set; the security matrix needs no server and runs on every commit.Detail:
11-ENGINE-MONGODB.md. Depends on all of Phase 11.
- [x] P12-T1 (L)
packages/driver-mongodbskeleton, capabilities,connectionSchema, URI parser, topology probe → session capabilities - [x] P12-T2 (L) Connect: standalone / replica set / sharded / SRV, TLS, SCRAM · x509 · AWS IAM, pool, timeouts. SSH through
@pitta/ssh, withdirectConnectionset so a tunnelled member is not left behind by topology discovery; SRV and seed lists are refused rather than half-tunnelled - [x] P12-T3 (M)
IntrospectionPlan: databases, collections, views, indexes, estimated counts, aserverNodelevel listing shards or replica-set members, and paging on the database and collection levels - [x] P12-T4 (L) Shell-dialect parser: acorn → allowlisted call shapes → BSON, constructor literals, diagnostics. No eval [ADR-042]
- [x] P12-T5 (M) Session +
QueryHandleover cursors: batching, streaming,fetch,maxTimeMS.nextCursorarrived with P11-T9 and this driver does not implement it, which is the right answer rather than a gap: a MongoDB cursor is a server-side handle for streaming one result, not a token a later request resumes from, and the grid pages this engine with the skip and limitbuildSelectactually writes.supportsCursorPagingwas claiming otherwise and is now false — the flag has to describe the code - [x] P12-T6 (M) Cancel: operation comments +
$currentOplookup +killOp[ADR-043] - [x] P12-T7 (M) BSON type table: Decimal128 → decimal string, Int64 → bigint, ObjectId, Date, Binary, Regex, Min/MaxKey [ADR-004]
- [x] P12-T8 (L)
buildSelect/buildEdits: filters and sorts → find,$set/$unset, nested paths, transactional apply where the topology allows, and positional array paths — an index writes to that element,$[]to every one, and the two operators that mean "whichever matched" are refused because an edit addressed by_idmatched none - [x] P12-T9 (M) Schema sampling behind the tree's columns and the Fields section, types with percentages, presence, labelled sample, and
readSymbolsfor completion — bounded to a small sample per collection because it sits on a keystroke path [ADR-045] - [x] P12-T10 (M)
readStructure: fields, indexes, validation, statistics, and sharding — shard key, balancing, and how the chunks are spread, which is the only place a collection sharded onto one shard is visible - [x] P12-T11 (M)
explain→QueryPlanwith examined-versus-returned carried onto each node, plus the Mongo red-flag rules: collection scan, examined-versus-returned, blocking sort, spill to disk, multikey index, unindexed$lookup. Engine facts ride onPlanNode.engineand reach the panel throughDriverAdapter.planFlags[ADR-024] - [x] P12-T12 (M)
readActivity/stopBackendfrom$currentOp+killOp;readHealthfrom$indexStats,serverStatus, index shapes - [x] P12-T13 (M) Completion / hover / diagnostics for the shell dialect from the sampled schema, through a new
EngineLanguageServiceon the adapter: collections afterdb., operations after a collection, sampled fields inside a filter, query operators and pipeline stages after$. Every suggestion and hover says the fields came from a sample - [x] P12-T14 (M)
bulkLoadthrough batched unorderedinsertMany, plusimportRecordsfor JSON arrays and NDJSON (the format is read off the file, and one bad line costs one record) andexportRecordswriting Extended JSON so an ObjectId survives the round trip - [x] P12-T15 (M) Guards: empty-filter
deleteMany/updateMany,drop*,$out/$mergepipeline walk, server-side JS flagged [11 §11] - [x] P12-T16 (S)
generateDdl→ runnablecreateCollection+createIndexesscript - [x] P12-T17 (M) docker-compose MongoDB 7 and an 8 replica set,
mongo-seed.jsmounted into both — documents that disagree with each other on purpose — and the conformanceEngineFixture, which is the first time the kit runs against a schemaless engine on a real server. The replica set is on mongo:7 rather than mongo:8, which refuses to start on Linux 6.19+ (SERVER-121912) - [x] P12-T18 (M) Integration + security suites, green against MongoDB 7 standalone and a replica set: edit-verify by reading the document back through a second command, cancel through
$currentOp/killOp, projection and missing-vs-null against real documents, and a prod guard matrix that runs on every commit. Running them found five real bugs, all fixed - an unreadable command classified safe rather than failing closed, an empty-filterdeleteManythat was not destructive, a cursor error escaping as a rawMongoServerError, an explicit null dropped on insert, an_idalways coerced to ObjectId (so a numeric or string key never matched), cancel released before the cursor was pulled (so it killed nothing), and writes inside a transaction issued without the client session (so nothing rolled back)
Phase 13 — Redis driver
Complete. The driver, the
.rediseditor language, the subscription panel, the TTL action, cluster's node level, cross-slot handling, replica reads, the big-key and TTL-coverage findings, and the settings that relaxKEYS/MONITOR. Green against Redis 6.2, 7, redis-stack and a one-node cluster. The 1M-key assertion is opt-in behindPITTA_TEST_REDIS_BIG=1, because writing a million keys takes a minute and nobody wants that on every run - it passes. ADR-049 records how offset paging over a scan is expressed.Detail:
12-ENGINE-REDIS.md.
- [x] P13-T1 (L)
packages/driver-redisskeleton, capabilities,connectionSchema(standalone / sentinel / cluster),redis(s)://parser - [x] P13-T2 (M) Connect: ACL auth, TLS,
CLIENT SETNAME,COMMAND INFOtable, topology probe, and SSH through@pitta/ssh— standalone only, because cluster and sentinel are handed the other nodes' own addresses and one forward cannot serve them - [x] P13-T3 (L) Keyspace tree: databases via
DBSIZE/INFO keyspace(CONFIG-disabled fallback), SCAN prefix folders from a bounded sample, cursor paging, estimate labelling [ADR-044] - [x] P13-T4 (L) Per-type value views +
buildSelect: string · hash · list · set · zset · stream · JSON module - [~] P13-T5 (M)
buildEditsper type and the no-rollback wording — done, including the preview and the partial-apply report; commands run in order withoutMULTI/EXEC, which changes nothing about what is promised - [x] P13-T6 (M) TTL — shown in the structure view, and the editor action is wired: a prompt on the key rather than a cell in the grid, because TTL is a property of the key and not one of its fields. Empty clears it through
PERSIST, which is not the same as an expiry of zero - [x] P13-T7 (M)
.redislanguage: a splitter that ends a command at a newline outside quotes, completion and hover built from the server's ownCOMMAND DOCS, subcommands of the container commands, and diagnostics for unbalanced quotes, refused commands and commands this server does not have. Keys are deliberately never suggested (ADR-044) - [x] P13-T8 (M) Guards from command flags; always-destructive list;
KEYSandMONITORrefusals;EVALhandling; unknown fails closed on prod [12 §9] - [x] P13-T9 (M) The notify panel is now the subscription panel and knows no engine: discovery is
readChannels, publishing isbuildPublish, delivery issession.listen. Redis offersPUBSUB CHANNELSplus the keyspace-notification patterns, and only whennotify-keyspace-eventsis actually set.MONITORis opt-in throughpitta.redis.allowMonitor, stops itself afterpitta.redis.monitorSeconds, and is refused on production whatever the setting says - [x] P13-T10 (M)
readActivity/stopBackendfromCLIENT LIST/CLIENT KILL - [x] P13-T11 (M)
readHealth: memory, eviction, persistence, replication, blocked clients, hit rate, slowlog, and a bounded keyspace sample reporting the largest key and how much of the sample expires — a sample, and labelled as one, because the alternative isKEYS(ADR-044) - [x] P13-T12 (S) Cluster mode: a nodes level reading
CLUSTER NODESwith slot ranges (andINFO replicationoff a cluster), cross-slot commands split per slot and merged back in the caller's key order where that is meaningful and refused with the hash-tag explanation where it is not, and opt-in replica reads — opt-in because a replica can be behind, and a client that quietly read from one makes staleness look like a bug in the data - [x] P13-T13 (M) docker-compose Redis 6.2 and 7 plus an integration suite that seeds and cleans up after itself; redis-stack and a one-node cluster added, and the conformance
EngineFixturewritten against a hash. Green against 6.2, 7, redis-stack and the cluster - [x] P13-T14 (M) Safety tests:
KEYSandMONITORrefusals, the read-only guard, unknown-fails-closed, and value binding against a scripted server and again against a real one, plus the partial-apply promise, the TTL round trip, and the cluster's slot arithmetic checked againstCLUSTER KEYSLOT. The 1M-key assertion runs underPITTA_TEST_REDIS_BIG=1and passes: a million keys written, a prefix folder still expanding in well under the budget. Running the suite found two real bugs - the whole file had never executed (its reachability flag was read at collection time, so every test silently skipped), andCOMMAND INFOwith no arguments is empty on Redis 6.2, which left the oldest supported server with no classification table and every write past the read-only guard
Phase 14 — MySQL / MariaDB driver
Complete. Written alongside MongoDB rather than after it, and it did land against the existing contract almost unchanged - which is the result ADR-047 predicted and the reason it was scheduled last. Results stream, the plan has MySQL's own red flags, and the tunnel is shared with every other driver. The conformance and integration suites are green against MySQL 8 and MariaDB 11 - which is what "supported" means (docs/03-DRIVER-API.md section 6).
- [x] P14-T1 (L)
packages/driver-mysqlonmysql2: connect, TLS, pool,KILL QUERYcancel, and SSH through@pitta/ssh - [x] P14-T2 (L)
information_schemaintrospection; backtick quoting;?placeholders; DECIMAL/BIGINT exact - [x] P14-T3 (M)
EXPLAIN FORMAT=JSON→ plan model, withEXPLAIN ANALYZEsupplying measured time, plus the MySQL red-flag rules: a full scan, an available index the optimizer passed over, examined-versus-returned, a lowfilteredpercentage, a filesort, a temporary table - [x] P14-T4 (M) Processlist monitor;
performance_schemaand status-counter health report;SHOW CREATEDDL - [~] P14-T5 (M) Bulk import through batched INSERTs in one transaction.
LOAD DATA LOCAL INFILEis deliberately not used — see ADR-056 - [x] P14-T6 (M) docker-compose MySQL 8 + MariaDB 11, with the conformance and integration suites green against both (
PITTA_TEST_MYSQL_FLAVOUR=mariadbpicks the second). Running them found two real bugs:EXPLAIN ANALYZEis a syntax error on MariaDB, which spells itANALYZE FORMAT=JSON, and MariaDB's plan JSON names its row countsrows/r_rowsrather thanrows_examined_per_scan- so every MariaDB plan reached the red-flag rules with no numbers in it and reported nothing at all - [x] P14-T8 (M) Streaming results: a query asked to stream holds its own pooled connection, leaves the stream paused and reads only what
fetchpulls, and a connection abandoned mid-result is destroyed rather than handed back half-read.supportsCursorsis now true because the behaviour is - [x] P14-T7 (S) The guide exists (P10-T2) and answers every gap the fourth, fifth and sixth drivers found;
03-DRIVER-API.mdsection 7 is now the index that says which section answers which, rather than a list of things nobody had written down. Finishing Phase 11 against six written drivers added four more, all of them now sections of the guide: whose SQL a dialect is (ADR-060), naming a tree level core has no vocabulary for, reporting the end of a scan withnextCursor, and that removing a field is not clearing it
Phase 15 — SQL Server driver
Complete. Relational and SQL, so most of it landed against the existing contract unchanged - and the parts that did not were about TDS rather than about T-SQL. Every statement goes through
sp_executesql, which makesUSEand sessionSETmeaningless (ADR-059), and the protocol decodesdecimalinto a double, which is the only engine so far where ADR-004 had to be defended on the server (ADR-058). The conformance and integration suites are green against SQL Server 2022 - which is what "supported" means (docs/03-DRIVER-API.md section 6).
- [x] P15-T1 (L)
packages/driver-mssqlonmssql/tedious: connect, TLS mapped ontoencrypt+trustServerCertificate, pool, NTLM for a domain login, named instances, attention-packet cancel, and SSH through@pitta/ssh - [x] P15-T2 (L)
syscatalog introspection with three-part names so the tree crosses databases withoutUSE; bracket quoting;@1placeholders;decimal/bigintexact (ADR-058) - [x] P15-T3 (M)
SHOWPLAN_ALLandSTATISTICS PROFILE→ plan model through a pinned batch (ADR-059), plus the SQL Server red-flag rules: a scan judged against the table's own row count rather than what it returned, a key lookup that ran too often, an estimate far from the actual, aCONVERT_IMPLICITthat quietly disables an index, and the server's own operator warnings - [x] P15-T4 (M)
sys.dm_exec_*session monitor with the blocker named directly; DMV health report (missing indexes, unread indexes, page life expectancy, log space);sys.sql_modulesDDL for modules and a composedCREATE TABLEfor tables - [x] P15-T5 (M) Streaming results: a query asked to stream pauses the request as soon as a page has arrived and resumes only when
fetchasks, and a request abandoned mid-result is cancelled rather than returned to the pool half-read - [x] P15-T7 (M) Security and correctness review of the finished driver, which found five things worth the pass. A failed
explainleftSET SHOWPLAN_ALL ONon its pooled connection - the setting outlives both the statement and the rollback - so every later query that borrowed that connection returned no rows at all rather than an error; the cleanup now runs whatever happened, with a regression test that runs more queries than the pool has connections.readOnlywas enforced nowhere in the driver while the capability claimed the server was doing it (S4.10); it is now refused in the client, the flag says false, and the T-SQL writes the shared heuristic reads as harmless -EXEC,SELECT … INTO,BULK INSERT,RESTORE,BACKUP,DBCC,KILL- are classified by the driver so the read-only block and the production confirmation see them (ADR-007, S4.4). A case-sensitiveLIKEput aCOLLATEclause on whatever column it was given, which is a syntax error on an int or a datetime. Atimecolumn read back as1970-01-01T03:04:05Z, an epoch date in a cell that holds a time of day, and adateas a midnight instant a time zone could move. And the health report's suggested SQL did not quote the identifiers it had read out of the catalog - [x] P15-T6 (M) docker-compose SQL Server 2022, with the conformance and integration suites green against it. Running them found three real bugs:
batch()reports no column metadata at all (onlyquery()does), so every plan rowset arrived unreadable;mssql's type objects are functions that carry adeclarationrather than returning one, so every decimal column was described as an nvarchar and skipped its scale; and a plan's scan node reports the rows it produced rather than the rows it read, so a full scan of twenty thousand rows returning three was not reported at all until the driver started asking the catalog for the table's real size
Phase 16 — Stored routines
A procedure was something Pitta could show. Everything people actually do with one - change it, call it, watch it run, find out where it broke - was done elsewhere, which for a five-hundred-line procedure means a scratch buffer, a paste back, and
RAISEstatements added one run at a time. This phase is that loop, closed inside the editor. What it is not is a step debugger: breakpoints, stepping and variable watch are their own phase, and they belong behind a debug adapter rather than in a panel.
- [x] P16-T1 (M)
RoutineSupporton the driver contract -describe,buildReplace,buildDrop,buildInvoke,locateError- with the data types inmodel/routine.tsso the capability can nameSessionwithout core importing itself in a circle.PittaErrorand the statement wire carrycontext, which is the engine's own stack - [x] P16-T2 (L) Routines are edited as documents: a
FileSystemProvideronpitta-routine, so a definition gets a dirty marker,Ctrl+S, revert and a diff against the server for free. Saving runs the guards, replaces inside a transaction where the engine has one, and puts a failure on the line of the body it happened in. The Postgres overload trap -CREATE OR REPLACE FUNCTIONwith a changed argument type creates a second function and reports success - is detected against the server after the save rather than by parsing the edited text - [x] P16-T3 (M) Run Routine: arguments come from the catalog with their names, declared types and defaults,
OUTparameters are not asked for, and the prompt is the parameters form from P13. The call is built by the driver -CALL,SELECT * FROM,EXEC … OUTPUTand the select that reads it back - and the runner gained a way to be handed statements rather than splitting text into them - [x] P16-T4 (M) Messages while it runs. SQL Server's
PRINTwas never listened for and MySQL's warnings were never asked for, so on two of the three engines a long procedure reported nothing at all; both are wired now, and every notice is pushed to the panel as it arrives instead of being attached to the statement when it ends. A failure shows the engine's stack under Where - [x] P16-T5 (M) SQL Server and MySQL parity for reading, replacing and calling. MySQL is the engine with no
CREATE OR REPLACEand no transactional DDL, so its replacement is a drop and a create that nothing undoes: the editor warns first and restores the old definition when the create fails - [ ] P16-T6 (M) Integration tests against the docker compose: a routine round-trips through
describe → buildReplace → describeunchanged, a failure inside a body lands on the right line, andPRINT/RAISE/SIGNALoutput arrives while the call is still running