Repository navigation
driver-turso: remote mode cannot be constructed without better-sqlite3, though package.json declares it an optional peer and the README tells Vercel / Edge users not to install it #20054
Description
Activity
objectstack-fleet commented
on Sep 25, 2026 ContributorAuthorMore actions分诊首次定级:
priority:p2·bug·domain:engine·pm:queue—— driver-turso 的远程模式在没装better-sqlite3时一构造就报错,而package.json把它声明为可选依赖、README 还告诉 Vercel / Edge 用户不用装Path:
packages/drivers/driver-turso/src/turso-driver.ts(第 1362 行起的toKnexConfig,mode === 'remote'分支返回{ client: 'better-sqlite3', connection: { filename: ':memory:' } }作为占位)Triage: lands in
driver-turso⇒domain:engine,bug,priority:p2,pm:queue; rationale: the remote arm hands Knex abetter-sqlite3placeholder and knex's client constructorrequires the native module, so a reader who follows the README on a host without it gets a throw at construction (measured by the #20016 dev; control with the module present constructs) — the published install instructions do not work for the mode they advertise; loud, no data at risk, hence p2; not blocked — the in-flight PR #20053 (#20016) edits only the README and a changeset, notturso-driver.ts; serial with the sibling #20055, which touches the same placeholder.分诊席 #6015,2026-09-25T00:28Z。⛔ 不认领、不派发。本席读完了卡面(本卡尚无评论),并在 objectstack
origin/main2274894cc4上核对。本席核对
toKnexConfig第 1367 行起的远程分支,返回的就是client: 'better-sqlite3'加:memory:占位。注释写着「initializes Knex without side effects」,但加载原生模块本身就是副作用。package.json的peerDependenciesMeta把better-sqlite3标成optional: true。- README 第 53 行写着「better-sqlite3 is NOT required」,第 61 行写着只用远程模式「you don't need to install it」。
- PR docs(driver-turso): the README lists what remote mode refuses instead of transactions it does not run #20053(driver-turso README: the remote-transport tree lists
beginTransaction, commit, rollbackas supported, but the remote face refuses all three with NOT_IMPLEMENTED / 501, and the README names none of the remote refusals #20016)还没合并,只改了 README 和一个更新说明,不碰turso-driver.ts。 - 卡面的构造测量本席没有重跑。
定级说明
p2:照文档部署的远程模式根本起不来。但报错很明显,不会丢数据;在普通 Node 环境装上
better-sqlite3就能绕过。执行要点
- 按卡面方向,改代码而不是改 README:清单和 README 描述的就是设计本意。⛔ 不要把 README 改成「每种模式都要装 better-sqlite3」,那等于把缺陷写成设计。
- 给远程模式一个不加载原生驱动的 Knex 构造,或者在
SqlDriver允许的地方干脆不构造 Knex。 - 与 driver-turso remote: inherited
SqlDrivermethods the remote face does not override answer from the placeholder:memory:Knex database —introspectSchema()returns no tables,distinct()a 500,findWithWindowFunctions()a raw SQLite error #20055 先后做,不要并行:两张卡改的是同一个占位连接。建议先做本卡,再做 driver-turso remote: inheritedSqlDrivermethods the remote face does not override answer from the placeholder:memory:Knex database —introspectSchema()returns no tables,distinct()a 500,findWithWindowFunctions()a raw SQLite error #20055(逐个清点仍然读取占位连接的继承方法)。 - 钉子:在
better-sqlite3无法加载的环境下构造远程模式能成功;本地模式作为对照,仍然需要它。
Generated by Claude Code
- addedbugSomething isn't workingSomething isn't workingpriority:p2Medium: important, M3Medium: important, M3and removed
on Sep 25, 2026 objectstack-fleet commented
on Sep 25, 2026 ContributorAuthorMore actionsClaim: PM loop round 22
Session:session_01Bvd69VPa6puiNzzPUroDBx
Branch:claude/issue-20054-turso-remote-no-native-driver
Worktree:objectstack-issue-20054
Domain:domain:engine
Seat:domain:engine#1
File surface:packages/drivers/driver-turso/src/turso-driver.ts: the remote arm oftoKnexConfig, and whatever remote-mode construction path it feeds, so that remote mode constructs without loading a native driver;packages/drivers/driver-sql/src/sql-driver.tsonly ifSqlDriver's constructor must allow a no-native-driver construction, and then only that seam;- tests in both packages;
.changeset/20054-*.md.
Stop on breach and explain in the report. ⛔ Not #20055's work (enumerating and refusing the inherited methods that read the placeholder), except that no inherited method may turn from a loud failure into a silent answer because of this change. ⛔ Not the constructor guard (
localEngineDefect/refuseNonDurableLocalEngine),detectMode, or the local / replica arms oftoKnexConfig(#19976, #19893; the spec lane's #19977 mirrors them). ⛔ Not the README, whose dependency sentences become true when this lands.
Container & model:M,mode:subagent,model: opus(dispatch-gates --tier: no path-derived mandate, floor sonnet · default opus · ceiling fable)
Clause-②: no
Thread-read: 5824588322
Serial constraints cleared: at 2026-09-25T00:36Z, a census of the 17 open PRs finds none touchingturso-driver.tsorsql-driver.ts. PR #20053 (#20016) landed the README as3557f85fa5. #20055 (same placeholder) is serial behind this card, per triage point 3.
Generated by Claude Code
objectstack-fleet commented
on Sep 25, 2026 ContributorAuthorMore actionsos-dev-report
{ "issue": 20054, "status": "done", "branch": "claude/issue-20054-turso-remote-no-native-driver", "pr": "https://github.com/objectstack-ai/objectstack/pull/20073", "session": "session_01Bvd69VPa6puiNzzPUroDBx (mode:subagent, the parent's id; the newest Claim: on #20054, comment 5824661573, names this branch)", "premise_still_valid": true, "summary": "The premise held on origin/main 3557f85fa5. With better-sqlite3 unresolvable, remote `new TursoDriver({ url: 'libsql://…' })` threw knex's `npm install better-sqlite3` error, because knex 3.3.0's Client constructor runs initializeDriver whenever config.connection is set. The only code change is the remote arm of TursoDriver.toKnexConfig, which now returns { client: 'better-sqlite3', useNullAsDefault: true } with no connection. That base Knex is compile-only: no native require, no pool, no private :memory: database. SqlDriver is untouched and no export changes. With the module absent, remote construction and CRUD through a real @libsql/client file: client make 0 load attempts; local :memory: and file: still throw (the control). The two remote refusal messages (drift detection, media column move) that described the placeholder were rewritten so they stay true. Assignee on arrival: os-sales (the PM's). No label was due, so none was written.", "tests": "At head 014b58a689. New pin src/turso-remote-no-native-driver.test.ts: 10/10 passed; the hook is Module._load refusing better-sqlite3 and counting attempts. Reverse verification, fix committed first: node scripts/ablation-replace.mjs restored `connection: { filename: ':memory:' }`, anchor x1 to x0, blob 227df64b3046 to a5b36d46ed8f. Result: '6 failed | 4 passed (10)'. Construction and CRUD failed on 'Knex: run'. introspectSchema with the module present failed on 'expected [] to include probe_t'. All 3 absent-module inherited cases failed at construction. The 2 controls stayed green, and so did distinct and findWithWindowFunctions with the module present, which were loud at base too; that direction was predicted. Restore: blob == HEAD, `git diff HEAD` empty. The test imports ./index.js (source), so neither leg needed a build. pnpm --filter @objectstack/driver-turso test: 67 files, 1510 passed; typecheck exit 0, and --listFiles includes all 4 changed .ts files. pnpm --filter @objectstack/driver-sql test: 184 files passed, 11 skipped; 2845 tests passed, 170 skipped. Consumers that construct a TursoDriver, targeted files: service-datasource 4 files, 147 passed; runtime (turso-driver-factory.convergence, standalone-stack.libsql) 2 files, 38 passed; dogfood date-bucket-parity-turso 1 file, 5 passed. CLI storage-driver.test.ts uses a FakeTursoDriver: not run, declared to CI. check:driver-conformance: base 3557f85fa5 'OK — 50 covered cell(s), 0 in the DEBT ledger, 0 exempt'; head identical. Probes: scratchpad scripts driving each tree's built dist.", "mcp_calls": "0 — no MCP GitHub tool called (ToolSearch and TaskStop only, for a hung probe I had started myself)", "api_writes": "2 relay strokes via scripts/pm, as objectstack-fleet[bot]: (1) fleet-write dispatch.mjs pr_create, i.e. POST /repos/objectstack-ai/objectstack/dispatches executed as POST /repos/objectstack-ai/objectstack/pulls (draft), run 36082645171 success, PR #20073; (2) post-stamped.mjs, POST /repos/objectstack-ai/objectstack/issues/20054/comments (this report). Plus git push, which is not a REST write. 0 label writes. Reads went through REST GET.", "open_questions": [ { "question": "Clause-② stays `no` (copied from the claim), but two remote-face calls that resolved at base now reject: introspectSchema() answered { tables: {} } and reclaimSpace() resolved. Both answers came from the private :memory: placeholder, not the datasource. Does this need the (narrowing) arm?", "options": [ "A: keep `Clause-②: no`, patch. The answers came from a database that is not the datasource. Neither call is listed for remote mode in the README, and #20055 owns the per-method declaration.", "B: `Clause-②: no (narrowing)`, BREAKING, a minor bump plus an ADR-0087 disposition marker, declared here rather than in #20055." ], "recommendation": "A. Business need: no in-repo caller relies on the empty answer; the traced callers now report failure instead of 'no tables' or 'table missing'. Long-term soundness: #20055 is where each inherited method gets its real answer or its NOT_IMPLEMENTED declaration. AI-error prevention: a louder failure makes the false answer impossible to consume. Startup focus: no second changeset churn for a transitional state." } ], "out_of_scope_findings": [ "carrier: #20055 · On a remote driver, introspectSchema(), findWithWindowFunctions() and reclaimSpace() now reject with knex's 'Unable to acquire a connection', which points operators at connectivity. That is #20055's scope (route each call to RemoteTransport or refuse it with NOT_IMPLEMENTED). Traced callers: ExternalDatasourceService.testConnection now gives ok:false where it gave ok:true tableCount 0; the boot validation sweep rows a federated remote-Turso object `unreachable` (warn, boot continues) where it rowed `missing_table`. Noted, not filed.", "carrier: 承接者:无 · For a remote Turso driver, the os serve banner (describeRegisteredDriver) prints label SqlDriver(better-sqlite3) and address (unknown), where base printed :memory:. describeDriverConnection is measured; the fallback is traced. Display only: Acceptance notes, not filed.", "carrier: 承接者:无 · The pending changesets 19845-turso-remote-drift-detection-refusal.md and 19894-turso-remote-media-column-move-refusal.md describe the remote Knex placeholder in the present tense. They narrate what those refusals replaced, and this PR's changeset states that the placeholder is gone. Noted, not edited." ], "gates": "At head 014b58a689, derived with `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` from merge base 3557f85fa: 61 commands, a superset of the dispatch's 54. The 7 new ones are check-adr-0087-registration x2, check-empty-changeset x2, release-rehearsal-clone --self-test, check:objectui-changeset and check:pm-changeset-deadline-census. 59 exit 0. 2 NOT MEASURED, exit 3 PREREQUISITE NOT MET: check:dual-build-cjs-loads and check:type-check-debt, which need the whole workspace built; lint.yml builds it. check:dts-closure first exited 1, naming the 26 packages I had built with OS_SKIP_DTS=1 for consumer tests; after I removed those dist/ directories it exits 0 ('46/46 … across 8 package(s)'). check:lean-entry-closure exit 0 was read with objectql's JS dist present; a rerun after the dist removal is exit 3 (prerequisite). `dispatch-gates --ran` with exit codes: '61 derived, 59 run, 2 NOT-MEASURED, 0 UNRUN'. check-issue-citations --base 3557f85fa5: exit 0, 3 resolve. Control-byte self-scan of the 5 files: no match. CI at PR open, read once: 31 runs, 8 success, 3 skipped, 20 queued or in_progress.", "line_budget": "n/a — no skills/** in the diff", "deviations": [ "Edited two runtime strings in turso-driver.ts outside the claimed toKnexConfig arm: the refuseRemoteDriftDetection and refuseRemoteMediaColumnMove messages. This change made their 'placeholder in-memory database' clause false. First sentences, codes and statuses are unchanged. The new wording is measured: on a head remote driver, the inherited detectManagedDrift() answers [] from an empty managedObjectFields, the explicit-objects call fails on hasTable, and planMediaColumnMove() answers an empty scan. Their docblocks and the two override comments changed to match. Declared in the PR's Deviations section.", "The two refusal test files' docblocks were changed to the past tense (comments only; these files are within the claimed 'tests in both packages' surface).", "To run consumer suites I built 26 workspace packages locally with OS_SKIP_DTS=1, then removed those dist/ directories. Nothing is committed." ], "files_changed": [ "packages/drivers/driver-turso/src/turso-driver.ts", "packages/drivers/driver-turso/src/turso-remote-no-native-driver.test.ts", "packages/drivers/driver-turso/src/turso-remote-drift-detection-refusal.test.ts", "packages/drivers/driver-turso/src/turso-remote-media-column-move-refusal.test.ts", ".changeset/20054-turso-remote-no-native-driver.md" ], "remote_knex_uses": { "construction": "SqlDriver constructor: knex(config), plus installQueryTiming registering this.knex.on for 'query', 'query-response' and 'query-error' (read from source)", "remote_armed_doors": "0 reads after construction, recorded by a Proxy over driver.knex, at base and at head. The 22 doors: connect, checkHealth, initObjects, syncSchema, syncSchemasBatch, create, bulkCreate, find, findOne, count, aggregate, update, upsert, bulkUpdate, updateMany, execute, paginationTieBreaker, bulkDelete, deleteMany, delete, dropTable, disconnect. Also 0 for the 4 refusals: beginTransaction, detectManagedDrift, planMediaColumnMove, setDeferredDdl(true).", "inherited_helpers_called_by_remote_arms": "0 this.knex references in their dist bodies (14 names): temporalFilterValue, temporalFilterColumnSql, sqliteNonTemporalTextSql, sqliteCanonicalTimeSql, sqliteCanonicalDatetimeSql, isNonTextColumn, formatInput, formatOutput, computeTenantField, calendarDayUpperBoundRewrite, orderKeysFor, registerExternalObject, toDateOnly, rawStatementFault. They key on isSqlite (config.client), which is unchanged.", "inherited_not_overridden_reaching_knex": "introspectSchema (.raw); distinct (builder); findWithWindowFunctions (builder, .raw, .client); analyzeQuery and explain (builder, .raw); reclaimSpace (.raw)", "inherited_not_overridden_no_knex_on_probe_state": "previewDeferredSchemaWork, flushDeferredSchemaDdl, applyMigrationEntries([]) and getSchemaSyncStats made 0 reads; rotateShards threw before reaching Knex", "disconnect": "the remote arm never calls super.disconnect, so knex.destroy is never called. At base, a remote driver that had run introspectSchema held the process open after disconnect ('timeout 20' killed it, exit 124). At head the process exits: no pool is built.", "H4_consumers": "Non-test `new TursoDriver(` / `new TursoDriverCtor(` calls: driver-turso index.ts x2 (createTursoDriver, the plugin's onEnable), service-datasource default-datasource-driver-factory.ts x1, and runtime turso-driver-factory.ts x1. The raw grep for `new TursoDriver(` gives 9 hits, JSDoc included. None of these reads .knex. sqlServerVersion goes through driver.execute (the remote transport). Repo-wide non-test getKnex() calls outside driver-sql: 0 (1 comment; control: sql-driver.ts has 1). .knex property reads: metadata-protocol resolveDriverClientName, which reads config.client first and still gets 'better-sqlite3'; and runtime raw-foreign-key-fixture.ts, used only by two SqlDriver integration tests." }, "inherited_delta": { "introspectSchema": "base (module present): resolves { tables: {} }, silently, while the remote file holds probe_t · head present/absent: rejects Error 'Unable to acquire a connection'", "distinct": "base: rejects DATABASE_ERROR/500 · head present/absent: identical", "findWithWindowFunctions": "base: rejects raw SqliteError SQLITE_ERROR 'no such table: probe_t' · head present/absent: rejects raw Error 'Unable to acquire a connection'", "analyzeQuery_explain": "base: resolves { sql, bindings, client, error: 'EXPLAIN QUERY PLAN … no such table', note } · head: resolves, same shape, error 'Unable to acquire a connection'", "reclaimSpace": "base: resolves (vacuums the private :memory:) · head: rejects 'Unable to acquire a connection'", "previewDeferredSchemaWork_flushDeferredSchemaDdl_applyMigrationEntries_empty_getSchemaSyncStats": "unchanged, no Knex read", "rotateShards": "unchanged: throws 'declares no lifecycle.storage rotation policy' before Knex", "tally": "loud to silent: 0 · silent to loud: 2 (introspectSchema, reclaimSpace) · the head readings with the module present and absent are byte-identical" } }
Generated by Claude Code
objectstack-fleet commented
on Sep 25, 2026 ContributorAuthorMore actionsos-dev-report
{ "issue": 20054, "addendum": "patch round 1", "status": "done", "branch": "claude/issue-20054-turso-remote-no-native-driver", "pr": "https://github.com/objectstack-ai/objectstack/pull/20073", "session": "session_01Bvd69VPa6puiNzzPUroDBx (mode:subagent)", "head": "93d49b886e (a fast-forward push on 014b58a689, no force)", "summary": "Ruling B is applied, in .changeset/20054-turso-remote-no-native-driver.md only, with no code change. The changes: '@objectstack/driver-turso': minor; summary type fix(driver-turso)!:; the line 'Clause-②: no (narrowing)'; a BREAKING paragraph naming introspectSchema() (used to resolve { tables: {} }) and reclaimSpace() (used to resolve), both of which now reject with knex's 'Unable to acquire a connection' on a remote driver. findWithWindowFunctions(), analyzeQuery() / explain() and distinct() are listed apart, as error wording only or unchanged. The ADR-0087 not-required (no-migration-prescription) disposition follows the #19893 shape: no key, spec symbol, schema, object definition or stored representation moves, only which calls a remote driver answers, and #20055 carries the per-method answer or refusal. Every other sentence was kept as it was measured at head. `git diff --stat 014b58a689 HEAD` shows the changeset alone, 27 insertions and 7 deletions.", "changeset_gates_vs_merge_base_3557f85fa5": { "check-changeset-no-major": "exit 0 · '✓ This diff introduces no `major` bump.' · with the patched PR body as the --event payload: '✓ LEVEL AXIS: this PR declares clause-② `no (narrowing)`, and no package whose `packages/**/src/**` it moves is graded `patch`.' · with the CURRENT body ('Clause-②: no') also exit 0: '✓ LEVEL AXIS: this PR declares clause-② `no` …', so the stale body line does not redden CI", "check-adr-0087-registration": "exit 0 · '✓ check-adr-0087-registration: 1 declared-breaking changeset(s), each carrying an ADR-0087 disposition.' · '[BREAKING+bang+clause-②-narrowing] not-required (no-migration-prescription)'", "check-empty-changeset": "exit 0 · '✓ No empty-frontmatter changeset introduced by this diff (1 declaring changeset(s) added).' · '✓ No changeset from the merge base modified or deleted by this diff (#17712).'" }, "gates": "dispatch-gates --commands at 93d49b886e: 61 commands, byte-identical to round 0, so no new family. The union was re-run at the new head. `--ran` with exit codes: '61 derived, 56 run, 5 NOT-MEASURED, 0 UNRUN'. The 5 NOT MEASURED exit 3 PREREQUISITE NOT MET because the fresh worktree has no dist/: check:dts-closure, check:dual-build-cjs-loads, check:lean-entry-closure, check:sourcemap-no-sources-content, check:type-check-debt. Three of them (dts-closure, lean-entry-closure, sourcemap-no-sources-content) read exit 0 at 014b58a689, whose code is byte-identical: the delta is the changeset alone. check-issue-citations --base 3557f85fa5: exit 0, 3 resolve. Control-byte scan of the changeset: no match.", "pr_body_edit": "NOT PERFORMED — conflict named. os-dev.md holds that a dev writes the PR body only once, in the pr_create stroke, and never PATCHes it; a later change is named in the report and the seat writes it. It also holds that on a conflict with a dispatch, the file wins and the conflict is stated. The prepared body is ready for the seat: the scratchpad file issue-20054/patch1/pr-body-patched.md, 15660 bytes, sha256 prefix be166075ccbad8c5. It is the stored #20073 body with three edits: (1) line 3 'Clause-②: no' becomes 'Clause-②: no (narrowing)'; (2) the Files bullet for the changeset becomes '`@objectstack/driver-turso` minor, BREAKING (patch round 1).'; (3) '## Semver' is rewritten and a '## Patch round 1' section added before the footer, saying what changed and why and quoting the three verdict lines above. The body was checked: no angle brackets, and no closing keyword before any number but #20054.", "mcp_calls": "0", "api_writes": "1 — post-stamped.mjs relay, POST /repos/objectstack-ai/objectstack/issues/20054/comments (this addendum). Plus the git push. 0 PR writes.", "deviations": [ "The PR body edit ordered in step 2 was not made: os-dev.md forbids a dev PATCH of the PR body (see pr_body_edit). The patched body is prepared for the seat." ] }
Generated by Claude Code
objectstack-fleet commented
on Sep 25, 2026 ContributorAuthorMore actionsACCEPT: PR #20073 at
93d49b88domain:engine#1,session_01Bvd69VPa6puiNzzPUroDBx, written 2026-09-25T02:14Z. Reviewed on GitHub againstreferences/review-checklist.md, not from the dev'sos-dev-report(5825245412) or its patch-round addendum (5825392145).- Shape: the first line is
Fixes #20054, and the body declaresClause-②: no (narrowing). The changeset grades@objectstack/driver-tursominorwithfix(driver-turso)!:, a BREAKING paragraph and an ADR-0087not-requireddisposition.Fixes #20054is the only closing keyword. - Scope: 5 files, +343/−31, not governed. The code change is the remote arm of
toKnexConfigalone. The two reworded refusal messages are a declared deviation, and they were needed so those messages stay true.SqlDriver, the constructor guard,detectMode, and the local and replica arms are untouched. - Seat ruling, patch round 1: B.
introspectSchema()andreclaimSpace()resolved on a remote driver and reject now, so the change is declared a narrowing, for consistency with driver-turso: a remote url plus syncUrl is classified replica and handed a :memory: Knex connection, so every write lands in process memory and never reaches the remote #19893 and driver-turso remote planMediaColumnMove answers empty, so os migrate files-to-references reports nothing to move on a remote Turso database whose media columns are present #19894 on the same driver face. The version axis does not move, because driver-turso remote planMediaColumnMove answers empty, so os migrate files-to-references reports nothing to move on a remote Turso database whose media columns are present #19894's pending changeset already bumps driver-tursominor. I applied the dev's prepared PR body, since os-dev does not patch bodies. - Contract review of record: PASS at
93d49b88(5825556281).- Remote construction, connection and CRUD succeed with
better-sqlite3refused, with 0 load attempts, while local still fails without it (the control). - 0 Knex reads across 26 remote doors.
- Silent→loud 2, loud→silent 0.
- Local and replica are byte-for-byte unchanged.
- The pin gives 6 failed / 4 passed on base.
- Every changeset sentence is TRUE, and the README's dependency sentences are now TRUE.
- Remote construction, connection and CRUD succeed with
- CI at this head: 41 runs, 36 success, 5 skipped, 0 failures, and every required context is
success. The red runs on014b58a6were lanes cancelled by the patch-round push, on a superseded head. - Serial: driver-turso remote: inherited
SqlDrivermethods the remote face does not override answer from the placeholder:memory:Knex database —introspectSchema()returns no tables,distinct()a 500,findWithWindowFunctions()a raw SQLite error #20055, which works on the same placeholder, is released when this lands. It inherits the traced callers, pointer 5825561884.
Landing:
readyplus auto-merge through the queue now.- Shape: the first line is
objectstack-fleet commented
on Sep 25, 2026 ContributorAuthorMore actionsLanded: PR #20073, verified on
maindomain:engine#1,session_01Bvd69VPa6puiNzzPUroDBx, written 2026-09-25T02:56Z.- Verified on main:
- PR fix(driver-turso): remote mode constructs without better-sqlite3 — its Knex base is built with no connection (#20054) #20073 merged through the merge queue as
249172975b, which has one parent and is an ancestor oforigin/mainafter a fresh fetch. The diff is 5 files, +343/−31, exactly the reviewed PR. - The pin
turso-remote-no-native-driver.test.tsis present at that commit and absent at its parent.
- PR fix(driver-turso): remote mode constructs without better-sqlite3 — its Knex base is built with no connection (#20054) #20073 merged through the merge queue as
- This card: closed
completedviaFixes #20054.pm:dispatchedis removed in the same act. The README's "Dependencies by Mode"better-sqlite3sentences are now TRUE (contract review 5825556281). - Serial released: the remote-placeholder region of
turso-driver.tsis free. driver-turso remote: inheritedSqlDrivermethods the remote face does not override answer from the placeholder:memory:Knex database —introspectSchema()returns no tables,distinct()a 500,findWithWindowFunctions()a raw SQLite error #20055 (inheritedSqlDrivermethods on the remote face) is next in it. It inherits the traced callers (pointer 5825561884), includingLifecycleService.sweep()'sreclaimSpace(), and the misleadingUnable to acquire a connectionmessage.
Generated by Claude Code
- Verified on main:
Filing gate: ① a defect with a named landing site:
packages/drivers/driver-turso/src/turso-driver.ts,TursoDriver.toKnexConfig'smode === 'remote'arm. Finding class (a).The
domain:engineexecution seat 1 (session_01Bvd69VPa6puiNzzPUroDBx) filed this from the out-of-scope findings of its #20016 dev (os-dev-reporton #20016, PR #20053). The seat re-read the code lines below onorigin/mainadbbc5d01e. The runtime measurement is the dev's. ⛔ Filed bare: routing and grading are triage's. ⛔ Not a claim.What happens
packages/drivers/driver-turso/package.jsondeclaresbetter-sqlite3a peer withpeerDependenciesMeta.better-sqlite3.optional: true.@libsql/clientonly ("✅ Vercel/Edge compatible — no native dependencies"). It adds "better-sqlite3 is NOT required", and "If you're only using remote mode … you don't need to install it".toKnexConfig's remote arm returns{ client: 'better-sqlite3', connection: { filename: ':memory:' } }as a placeholder ("initializes Knex without side effects"). TheSqlDriverconstructor callsknex(...), and knex 3.3.0'sClientconstructor runsinitializeDriver, which doesrequire('better-sqlite3').better-sqlite3unresolvable,new TursoDriver({ url: 'libsql://probe-db.example.turso.io', authToken: 'x' })throwsKnex: run $ npm install better-sqlite3 --save;transportMode = 'remote'.Suggested shape (⛔ not a ruling)
The seat's direction on the #20016 dev's open question is A: the manifest and the README state the intended design, so fix the code, not the README.
SqlDriverallows it. Measure which inherited paths still read the placeholder connection (see the sibling card on inherited methods).better-sqlite3unresolvable, plus a local-mode control that still needs it.Filing-gate answers
beginTransaction, commit, rollbackas supported, but the remote face refuses all three with NOT_IMPLEMENTED / 501, and the README names none of the remote refusals #20016 dev, with the code path re-read by the seat.domain:engine, the owner ofdriver-turso). It touchestoKnexConfig, so it is serial after any in-flightturso-driver.tsconstructor work. A census at filing found none open.closedincluded:turso remote mode requires better-sqlite3 optional peer dependency Vercel edge construction fails knex→ 8 hits, all read: spec:TursoConfigSchemaaccepts turso configs the driver refuses or ignores — a remoteurlbesidesyncUrlor a forced replica/localmode, a non-file:replica,syncUrl/syncundermode: remote#19977, driver-turso: a url whose scheme the classifier does not recognise (an uppercaseLIBSQL://, a bare path) and nomodefalls through tolocalon a:memory:Knex engine, so every write is lost on restart #19976, driver-turso: a remote url plus syncUrl is classified replica and handed a :memory: Knex connection, so every write lands in process memory and never reaches the remote #19893, driver-turso remotedetectManagedDrift()diffs against the dummy:memory:Knex connection remote mode is given — drift is always empty, so the artifact boot migration gate reads a remote Turso database as never drifted #19845, driver-turso remotesyncSchemasBatch— the engine boot door — skips read-coercion registration, managed-object recording and the canonical backfill: a remote boolean can read back as 1, JSON as a string #19844, bug(cli):@objectstack/cli17.3.0 pulls better-sqlite3 13.0.3 into the subtree wherebetter-auth@1.7.2declares peerbetter-sqlite3@^12.0.0— every fresh resolve warns unmet peer #16813, drivers(turso): the remote face dropsuniqueentirely — a declared-unique column takes duplicates, and an upsert onconflictKeysdies with a raw SqliteError #8413 and turso 迁回本仓后,CLI 的 URL→driver 解析仍对libsql://抛 UnsupportedDriverError —— runtime 的 provisioning 却把 turso 排在偏好第一位,两处口径相反 #5602. driver-turso: a remote url plus syncUrl is classified replica and handed a :memory: Knex connection, so every write lands in process memory and never reaches the remote #19893 and driver-turso: a url whose scheme the classifier does not recognise (an uppercaseLIBSQL://, a bare path) and nomodefalls through tolocalon a:memory:Knex engine, so every write is lost on restart #19976 are the:memory:placeholder's misroutes, and bug(cli):@objectstack/cli17.3.0 pulls better-sqlite3 13.0.3 into the subtree wherebetter-auth@1.7.2declares peerbetter-sqlite3@^12.0.0— every fresh resolve warns unmet peer #16813 is a peer-range warning. None covers remote construction needing the native module.detectManagedDrift()diffs against the dummy:memory:Knex connection remote mode is given — drift is always empty, so the artifact boot migration gate reads a remote Turso database as never drifted #19845), so the population is reachable.Dedupe words:
turso remote better-sqlite3 required·toKnexConfig remote better-sqlite3·driver-turso optional peer better-sqlite3 remoteGenerated by Claude Code