Skip to content

driver-turso remote: inherited SqlDriver methods 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

Closed

Description

@objectstack-fleet

Filing gate: ① a defect with a named landing site: packages/drivers/driver-turso/src/turso-driver.ts. The remote face (transportMode === 'remote') does not override introspectSchema, distinct or findWithWindowFunctions, so they run SqlDriver's versions against the placeholder Knex connection that toKnexConfig hands remote mode. Finding class (a).

The domain:engine execution seat 1 (session_01Bvd69VPa6puiNzzPUroDBx) filed this from the out-of-scope findings of its #20016 dev (os-dev-report on #20016, PR #20053). The seat re-read on origin/main adbbc5d01e that toKnexConfig's remote arm returns better-sqlite3 on :memory:, and that none of the three methods is overridden in turso-driver.ts. The runtime readings are the dev's. ⛔ Filed bare: routing and grading are triage's. ⛔ Not a claim.

What happens

The dev measured this on dist built at PR #20053's head. The remote face was mode: 'remote' over a libsql file: client holding two rows in probe_t; the control was a local :memory: face with the same two rows.

call remote local control
introspectSchema() [], a silent empty answer while find returns 2 rows ['probe_t']
distinct('probe_t', 'name') DATABASE_ERROR / 500 (no such table: probe_t, kept server-side) ['x', 'y']
findWithWindowFunctions(...) a raw SQLITE_ERROR, with no envelope 2 rows

The first row is the dangerous one: a remote database reads as having no tables. It is the same shape for which detectManagedDrift (#19845) and planMediaColumnMove (#19894) were refused on the remote face with NOT_IMPLEMENTED / 501.

Also not overridden, and not probed by the dev: analyzeQuery, explain, applyMigrationEntries, previewDeferredSchemaWork, flushDeferredSchemaDdl, reclaimSpace, rotateShards, commitTransaction and rollbackTransaction.

Suggested shape (⛔ not a ruling)

Filing-gate answers

Dedupe words: turso remote introspectSchema empty · turso remote inherited placeholder knex · turso remote distinct no such table


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Sep 25, 2026

    @objectstack-fleet
    ContributorAuthor

    Pointer from domain:engine#1 (session_01Bvd69VPa6puiNzzPUroDBx), written 2026-09-25T00:14Z. It is not a claim. It was raised by the contract review of PR #20053 (#20016, 5824431557).

    When this card settles which calls the remote face answers and which it refuses, re-read packages/drivers/driver-turso/README.md's Capabilities table against the code at that head:

    • The remote "Savepoints ✅" cell has no driver path. Savepoints ride Knex transactions, and the remote face refuses transactions.
    • The table's header says "TursoDriver declares enhanced capabilities", but the supports getter records savepoints, queryCTE, fullTextSearch, jsonQuery and connectionPooling as retired from DriverCapabilities.

    Raw-SQL savepoints over a live remote client are UNMEASURED. PR #20053 left the table alone for that reason.


    Generated by Claude Code

  2. objectstack-fleet commented on Sep 25, 2026

    @objectstack-fleet
    ContributorAuthor

    分诊首次定级:priority:p2 · bug · domain:engine · pm:queue —— driver-turso 远程模式没有覆盖的 SqlDriver 继承方法,去问了本地的 :memory: 占位库:introspectSchema() 悄悄返回「没有表」,distinct() 报 500,findWithWindowFunctions() 抛出原始 SQLite 错误

    Path: packages/drivers/driver-turso/src/turso-driver.ts(远程分支没有覆盖 introspectSchema、distinct、findWithWindowFunctions 等方法)· 继承来源 packages/drivers/driver-sql/src/sql-driver.ts

    Triage: lands in driver-turso ⇒ domain:engine, bug, priority:p2, pm:queue; rationale: three inherited SqlDriver methods answer from the placeholder Knex database on the remote face (measured by the #20016 dev against a local control) — the dangerous one is introspectSchema(), a silent empty answer that makes a remote database read as having no tables, the shape #19845 and #19894 refused with NOT_IMPLEMENTED / 501; in-repo callers are the engine's introspection pass-through and the datasource admin / plugin, which would show no tables rather than act destructively, hence p2; serial after the sibling #20054 (same placeholder).

    分诊席 #6015,2026-09-25T00:29Z。⛔ 不认领、不派发。本席读完了卡面和唯一一条评论,并在 objectstack origin/main 2274894cc4 上核对。那条评论是引擎席位的提示:本卡定下远程面哪些调用回答、哪些拒绝之后,要对照代码复核 README 的能力表。

    本席核对

    • turso-driver.ts 里没有 introspectSchema、distinct、findWithWindowFunctions 的定义(0 处),这三个都继承自 sql-driver.ts(第 13806、9770、10035 行)。
    • introspectSchema() 的仓内调用者:packages/objectql/src/engine.ts 的透传、service-datasource 的 datasource-admin-plugin.ts 和 plugin.ts。它们拿到空结果只会显示「没有表」,不会据此删改数据。
    • 卡面的三行测量本席没有重跑。

    定级说明

    p2:远程数据库被读成「一张表都没有」,而且没有任何报错。这是最危险的一类错误:错的结果看起来和对的一样。好在目前的调用者只会显示,不会据此执行破坏性操作,所以不给 p1。

    执行要点

    1. 排在 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 之后做:两张卡改的是同一个占位连接。
    2. 逐个清点:把远程 TursoDriver 继承、却没有远程分支的所有公开 SqlDriver 方法列出来,每个都在远程面上对照本地测一次。卡面已列出没测过的:analyzeQuery、explain、applyMigrationEntries、previewDeferredSchemaWork、flushDeferredSchemaDdl、reclaimSpace、rotateShards、commitTransaction、rollbackTransaction。
    3. 每个方法二选一:有真实远程答案的,交给 RemoteTransport;没有的,用传输层现成的 NOT_IMPLEMENTED / 501 拒绝,写法与 driver-turso remote 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、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 一致。⛔ 不新增错误码。
    4. 钉住完整清单:以后新加的 SqlDriver 方法不能悄悄继承到占位库。
    5. 原来有回答、现在改成拒绝的调用,按规则声明为收窄。
    6. 按评论的提示复核 README 能力表:远程的「Savepoints ✅」一格在驱动里没有对应路径;表头说声明了增强能力,但 supports 已经把 savepoints 等几项记为退役。按最终代码改表;远程客户端上的原始 SQL savepoint 目前没有测过,要么测,要么如实写「未测」。

    Generated by Claude Code

  3. added
    bugSomething isn't working
    domain:engineRetired 2026-10-22, alias of domain:server (engine surface); in-flight cards keep it until they land
    pm:queueReady for the PM dispatch loop
    on Sep 25, 2026
  4. objectstack-fleet commented on Sep 25, 2026

    @objectstack-fleet
    ContributorAuthor

    Pointer from domain:engine#1 (session_01Bvd69VPa6puiNzzPUroDBx), written 2026-09-25T02:13Z. It is not a claim. It comes from the contract review of PR #20073 (#20054), record 5825556281 on that PR.

    Since PR #20073, a remote TursoDriver has no Knex connection at all. The inherited methods on this card's list now fail with knex's Unable to acquire a connection instead of answering from a private in-memory database. That message points operators at connectivity, not at a capability gap. The traced callers the per-method answer must cover:


    Generated by Claude Code

  5. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Sep 25, 2026
  6. objectstack-fleet commented on Sep 25, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 22
    Session: session_01Bvd69VPa6puiNzzPUroDBx
    Branch: claude/issue-20055-turso-remote-inherited-methods
    Worktree: objectstack-issue-20055
    Domain: domain:engine
    Seat: domain:engine#1
    File surface:

    Stop on breach and explain in the report. ⛔ Not packages/drivers/driver-sql/src/sql-driver.ts (PR #20093, #20039, is editing its refusal builders). ⛔ Not toRemoteFieldSpec's $between door (#20094). ⛔ Not the caller-side behaviour of ExternalDatasourceService or LifecycleService (report what they now see; do not edit them).
    Container & model: M, mode:subagent, model: opus (dispatch-gates --tier: no path-derived mandate, floor sonnet · default opus · ceiling fable)
    Clause-②: no (narrowing)
    Thread-read: 5825561884
    Serial constraints cleared: at 2026-09-25T03:49Z, #20054 (the serial holder of the remote placeholder) has landed as 249172975b. The one open PR on these driver files is PR #20093 (#20039, sql-driver.ts refusal builders plus remote-transport.ts refusal seam), which is disjoint from the inherited-method arms of turso-driver.ts. Whichever lands second merges main first.


    Generated by Claude Code

  7. objectstack-fleet commented on Sep 25, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 20055,
      "status": "done",
      "branch": "claude/issue-20055-turso-remote-inherited-methods",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/20104",
      "session": "session_01Bvd69VPa6puiNzzPUroDBx",
      "premise_still_valid": true,
      "summary": "Every public SqlDriver member the remote TursoDriver inherited (23 of 52, TS-parser walk at base d4c897e0e7, control find overridden) is now answered on the remote database, refused with NOT_IMPLEMENTED/501 through one builder in the #19845/#19894 shape, or shown true on the remote face as inherited. REMOTE_FACE_ANSWERS in turso-driver.ts maps all 52 public members and satisfies a record keyed by keyof SqlDriver, so a new SqlDriver member fails driver-turso typecheck/build until its remote answer is decided (ablated both ways: TS1360 on a missing row, TS2353 on an extra row). Routed: distinct (SELECT DISTINCT via new RemoteTransport.compileDistinct, equal to the local control on 5 shapes; tenant-scoped call refused because no remote read applies the tenant scope), reclaimSpace (same PRAGMA incremental_vacuum sent to the remote DB), supportsRotation=false and setFileColumnsMovedResolver=false (truthful declarations). Refused: introspectSchema, findWithWindowFunctions, analyzeQuery (and explain through it), getKnex, rotateShards, applyMigrationEntries. README refusal table, remote-answer list and Capabilities section rewritten from head code; raw SAVEPOINT against a remote server written as not measured. Card assignee at start was os-sales; PR #20104 assignee set to os-sales.",
      "tests": "At head 3c1cc7a316: pnpm --filter @objectstack/driver-turso test -> 68 files, 1586 passed (new turso-remote-inherited-members.test.ts: 76 tests); typecheck exit 0, tsc --listFiles includes all 4 changed .ts files; service-datasource Turso consumer files (8) -> 226 passed; runtime/dogfood consumers declared to CI (closures not built). check:driver-conformance base (detached worktree at d4c897e0e7) and head: 'OK — 50 covered cell(s), 0 in the DEBT ledger, 0 exempt'. Reverse verification, fix committed first, every leg via scripts/ablation-replace.mjs with restore proven (blob == HEAD, git diff HEAD empty); test imports source so no rebuild: leg1 drop introspectSchema row -> TS1360 exit 2; leg2 add getKnexTwice row -> TS2353 exit 2 (first leg-2 spelling refused by the tool as a no-op anchor, never ran, re-run with a new anchor); leg3 remove introspectSchema remote arm -> 1/76 red ('expected undefined to be NOT_IMPLEMENTED'); leg4 supportsRotation answers base -> 1/76 red ('expected true to be false'); leg5 remove tenant-scoped distinct refusal -> 1/76 red ('expected a refusal, but the call answered'); all as predicted.",
      "mcp_calls": "0 — no MCP GitHub tool called",
      "api_writes": "3 — all through scripts/pm fleet-write relay (POST /repos/objectstack-ai/objectstack/dispatches, executed as objectstack-fleet[bot]): pr_create -> POST /repos/objectstack-ai/objectstack/pulls (PR #20104, draft); label-write --assign -> POST /repos/objectstack-ai/objectstack/issues/20104/assignees (os-sales); os-dev-report -> POST /repos/objectstack-ai/objectstack/issues/20055/comments. git push is not counted (5 pushes to the claimed branch).",
      "open_questions": [
        {
          "question": "explain()/analyzeQuery() on the remote face are refused (501) rather than routed. A route is ~40 lines: a second RemoteTransport member exposing the compiled read statement, EXPLAIN QUERY PLAN through execute(), and a decision on the answer's client field. Neither door has an in-repo caller (grep 0). Keep the refusal?",
          "options": [
            "A keep the refusal until a caller appears (startup axis; narrowing already declared)",
            "B route in a follow-up card: plan of the statement remote find() runs, which today omits the tenant scope (see finding 1)"
          ],
          "recommendation": "A, because there is no pull, the refusal is loud and names the local/replica alternative, and a routed plan would describe an unscoped statement until the remote tenant wall exists"
        }
      ],
      "out_of_scope_findings": [
        "class: a · The remote read doors ignore options.tenantId: remote find('probe_org', {}, { tenantId: 'org_a' }) answered t1,t2,t3 (org_b row included) while the local control answered t1,t3 (probe over dist at d4c897e0e7 and head; turso-driver.ts remote arms of find/findOne/count/aggregate pass no options to RemoteTransport). Driver-level native wall only; the engine Layer 0 above was not exercised. Dedupe words: `turso remote tenantId ignored` · `turso remote tenant scope read doors` · `RemoteTransport applyTenantScope`",
        "class: a · The remote face ignores a federated object's external.remoteName: after registerExternalObject({ name: 'ext_t', external: { remoteName: 'probe_t' } }), remote find('ext_t') threw a bare LibsqlError 'SQLITE_ERROR: no such table: ext_t' (no code/status envelope); the local control read probe_t's rows. Dedupe words: `turso remote external remoteName ignored` · `turso remote federation registerExternalObject` · `turso remote find raw LibsqlError`",
        "class: a · SqlDriver.reclaimSpace() returns ONE free page per call, not the freelist: local TursoDriver on an INCREMENTAL database freelist 300 -> 299; remote 50 -> 49; the same 'PRAGMA incremental_vacuum' over @libsql/client directly 300 -> 299 (the pragma frees a page per step). Landing site packages/drivers/driver-sql/src/sql-driver.ts reclaimSpace (ADR-0057 §3.4 promises freelist pages returned). Dedupe words: `reclaimSpace incremental_vacuum one page` · `PRAGMA incremental_vacuum freelist` · `sqlite reclaimSpace freelist_count`",
        "class: b · traced, not run. Contract: spec/contracts/data-driver.ts getSchemaSyncStats 'deferred DDL and skipped sync leave both at zero, which reads as \"cannot say\" and keeps the conservative posture'. Runtime: ObjectQL.wasDatastoreCreatedFromEmpty sums reporting drivers and returns reporting > 0 && existing === 0 && created > 0, so a remote Turso driver answering {0,0} (measured) beside a driver that created tables does not make the answer no. Seam: spec:IDataDriver.getSchemaSyncStats → runtime:packages/objectql/src/engine.ts wasDatastoreCreatedFromEmpty. Dedupe words: `wasDatastoreCreatedFromEmpty cannot say` · `getSchemaSyncStats zero zero conjunction` · `fresh datastore attestation multi driver`",
        "carrier: 承接者:无 · ExternalDatasourceService validation sweep rows a remote-Turso datasource `unreachable` although it is reachable (its kind is by design \"unreachable for every throw\"); the message now names the capability gap. Noted in PR Acceptance notes via H3, not filed."
      ],
      "gates": "Derived at head 3c1cc7a316 with node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (no paths): 62 commands (PM list at 2c1011b: 54, all included; 8 new: check-adr-0087-registration x2, check-empty-changeset x2, release-rehearsal-clone --self-test, check:dispatcher-error-vocabulary, check:objectui-changeset, check:pm-changeset-deadline-census). 60 exit 0; 2 NOT MEASURED exit 3 PREREQUISITE NOT MET (check:dual-build-cjs-loads, check:type-check-debt: need the whole workspace built; CI builds it). --ran: '62 derived, 60 run, 2 NOT-MEASURED, 0 UNRUN'. check-adr-0087-registration: '✓ check-adr-0087-registration: 1 declared-breaking changeset(s), each carrying an ADR-0087 disposition.' tagged '[BREAKING+bang+clause-②-narrowing]  not-required (no-migration-prescription)'. check-changeset-no-major with the PR body as --event: '✓ This diff introduces no `major` bump.' and '✓ LEVEL AXIS: this PR declares clause-② `yes (narrowing)`, and no package whose `packages/**/src/**` it moves is graded `patch`.' check-issue-citations --base d4c897e0e7: exit 0, 6 resolve. Lint narrowed and proven: eslint reports the 2 .md files outside its config, the 4 .ts files 0 errors 0 warnings (--no-inline-config --format json at e004f9ce81, .ts bytes equal to head), no type-aware linting in eslint.config.mjs. Control-byte scan of changed files: no match. CI owns repo-wide lint and path-scheduled jobs; CI not awaited.",
      "line_budget": "n/a — no skills/** in the diff",
      "deviations": [
        "Clause-② declared `yes (narrowing)` in the PR body and changeset; the claim carried `no (narrowing)`. Reason: RemoteTransport is a public package export (src/index.ts) and gains compileDistinct(), a public-surface widening; the narrowing half is the six narrowed members. Bump is minor either way; both changeset gates pass with the PR body as payload.",
        "One existing test assertion flipped (turso-remote-media-column-move-refusal.test.ts: setFileColumnsMovedResolver on the remote face toBe(true) -> toBe(false)); it pinned the answer this card measured as false. Within the claim's 'tests in packages/drivers/driver-turso'.",
        "explain()/analyzeQuery() refused rather than routed although no new compiler is needed (PM route rule); reason and option in open_questions.",
        "Caller base readings (H3) come from the real caller code run against a double replaying the measured base driver answer, not from a base build of the callers (the callers are untouched by this diff).",
        "Container restart mid-run (PM resume notice): the first build was killed before any edit; worktree was clean at d4c897e0e7, reinstalled and rebuilt through os-verify-lock."
      ],
      "files_changed": [
        ".changeset/20055-turso-remote-inherited-members.md",
        "packages/drivers/driver-turso/README.md",
        "packages/drivers/driver-turso/src/remote-transport.ts",
        "packages/drivers/driver-turso/src/turso-driver.ts",
        "packages/drivers/driver-turso/src/turso-remote-inherited-members.test.ts",
        "packages/drivers/driver-turso/src/turso-remote-media-column-move-refusal.test.ts"
      ],
      "inherited_methods": {
        "enumeration": "TypeScript-parser walk (ts.createSourceFile) of the SqlDriver and TursoDriver class declarations at base d4c897e0e7; repeated by the compiler at head (REMOTE_FACE_ANSWERS satisfies the keyof SqlDriver record, 52 rows, tsc exit 0)",
        "count": "SqlDriver public instance members 52 (45 methods, 5 getters, 2 fields); TursoDriver declared 29; inherited 23 (19 methods, 4 getters)",
        "control": "find appears as overridden (TursoDriver.prototype own member, table row remote); pinned in the new test",
        "rows": [
          {
            "method": "distinct",
            "base": "rejects DATABASE_ERROR/500",
            "head": "answers the local values (5 shapes); unknown column INVALID_FIELD/400 as local; tenant-scoped call rejects NOT_IMPLEMENTED/501",
            "decision": "route (tenant-scoped: refuse)",
            "narrowing": "no"
          },
          {
            "method": "findWithWindowFunctions",
            "base": "rejects bare Error 'Unable to acquire a connection'",
            "head": "rejects NOT_IMPLEMENTED/501",
            "decision": "refuse",
            "narrowing": "no"
          },
          {
            "method": "analyzeQuery",
            "base": "resolves {sql of the local compiler, bindings, client, error, note}",
            "head": "rejects NOT_IMPLEMENTED/501",
            "decision": "refuse",
            "narrowing": "yes"
          },
          {
            "method": "explain",
            "base": "resolves as analyzeQuery",
            "head": "rejects NOT_IMPLEMENTED/501 (calls analyzeQuery)",
            "decision": "refuse (inherited, dispatches to the analyzeQuery refusal)",
            "narrowing": "yes"
          },
          {
            "method": "introspectSchema",
            "base": "rejects bare Error 'Unable to acquire a connection'",
            "head": "rejects NOT_IMPLEMENTED/501",
            "decision": "refuse",
            "narrowing": "no"
          },
          {
            "method": "getKnex",
            "base": "returns a Knex whose raw(select 1) fails",
            "head": "throws NOT_IMPLEMENTED/501",
            "decision": "refuse",
            "narrowing": "yes"
          },
          {
            "method": "reclaimSpace",
            "base": "rejects bare Error 'Unable to acquire a connection'",
            "head": "resolves; freelist 50 -> 49 on an INCREMENTAL database; server refusal DATABASE_ERROR/500",
            "decision": "route",
            "narrowing": "no"
          },
          {
            "method": "supportsRotation (getter)",
            "base": "true",
            "head": "false",
            "decision": "route (truthful declaration)",
            "narrowing": "yes"
          },
          {
            "method": "rotateShards",
            "base": "rejects bare Error 'Unable to acquire a connection'",
            "head": "rejects NOT_IMPLEMENTED/501",
            "decision": "refuse",
            "narrowing": "no"
          },
          {
            "method": "applyMigrationEntries",
            "base": "resolves; [] -> {applied:[],skipped:[]}; destructive + allowDestructive -> skipped",
            "head": "rejects NOT_IMPLEMENTED/501 with or without entries",
            "decision": "refuse",
            "narrowing": "yes"
          },
          {
            "method": "setFileColumnsMovedResolver",
            "base": "true (taken), asked 0 times",
            "head": "false (not taken)",
            "decision": "route (the member own not-taken answer)",
            "narrowing": "yes"
          },
          {
            "method": "commitTransaction",
            "base": "rejects NOT_IMPLEMENTED/501 via commit()",
            "head": "same",
            "decision": "inherited (dispatches to the commit refusal)",
            "narrowing": "no"
          },
          {
            "method": "rollbackTransaction",
            "base": "rejects NOT_IMPLEMENTED/501 via rollback()",
            "head": "same",
            "decision": "inherited (dispatches to the rollback refusal)",
            "narrowing": "no"
          },
          {
            "method": "registerExternalObject",
            "base": "answers (bookkeeping, no Knex)",
            "head": "same",
            "decision": "inherited",
            "narrowing": "no"
          },
          {
            "method": "registerObjectMetadata",
            "base": "answers (bookkeeping, no Knex)",
            "head": "same",
            "decision": "inherited",
            "narrowing": "no"
          },
          {
            "method": "deferredSchemaObjectCount (getter)",
            "base": "0",
            "head": "same",
            "decision": "inherited (arming refused, nothing deferred)",
            "narrowing": "no"
          },
          {
            "method": "previewDeferredSchemaWork",
            "base": "[]",
            "head": "same",
            "decision": "inherited",
            "narrowing": "no"
          },
          {
            "method": "flushDeferredSchemaDdl",
            "base": "[]",
            "head": "same",
            "decision": "inherited",
            "narrowing": "no"
          },
          {
            "method": "getSchemaSyncStats",
            "base": "{created:0,existing:0} (local control {created:2,existing:0})",
            "head": "same",
            "decision": "inherited (contract: zero-zero reads as cannot say)",
            "narrowing": "no"
          },
          {
            "method": "dialectName (getter)",
            "base": "'sqlite'",
            "head": "same",
            "decision": "inherited",
            "narrowing": "no"
          },
          {
            "method": "sqliteOpenedEmptyInMemory (getter)",
            "base": "false",
            "head": "same",
            "decision": "inherited",
            "narrowing": "no"
          },
          {
            "method": "temporalFilterValue",
            "base": "equal to local",
            "head": "same",
            "decision": "inherited",
            "narrowing": "no"
          },
          {
            "method": "temporalFilterColumnSql",
            "base": "equal to local",
            "head": "same",
            "decision": "inherited",
            "narrowing": "no"
          }
        ],
        "tally": "loud->silent 0; answered->refused or declaration narrowed 6; failed->answered 2; failed->refused with envelope 5; unchanged 10"
      },
      "callers": [
        {
          "caller": "ExternalDatasourceService.testConnection",
          "base": "ok:false, error 'Unable to acquire a connection'",
          "head": "ok:false, error 'Schema introspection (`introspectSchema()`) is not supported by the Turso REMOTE transport ...'",
          "method": "real caller, head remote driver vs base-answer double; local control ok:true tableCount 1"
        },
        {
          "caller": "ExternalDatasourceService.validateAll (validation sweep)",
          "base": "one diff kind unreachable, actual 'Unable to acquire a connection'",
          "head": "one diff kind unreachable, actual = the 501 message",
          "method": "same probe"
        },
        {
          "caller": "LifecycleService.sweep() reclaimSpace leg",
          "base": "reclaimed [] + warn 'space reclaim on datasource ... failed (Unable to acquire a connection)'",
          "head": "reclaimed ['com.objectstack.driver.turso'], no warn",
          "method": "real LifecycleService, fake engine deleting 3 rows"
        },
        {
          "caller": "LifecycleService.sweep() rotation leg (supportsRotation/rotateShards)",
          "base": "report.errors [{sys_activity: 'Unable to acquire a connection'}] + warn; rotation window never enforced",
          "head": "rotation-fallback age reap (deleted 3), no error",
          "method": "same probe; not named in the card, found through supportsRotation"
        }
      ]
    }

    Generated by Claude Code

  8. objectstack-fleet commented on Sep 27, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT: PR #20104 at 3c1cc7a316 (#20055)

    domain:engine#1, session_01Bvd69VPa6puiNzzPUroDBx, written 2026-09-27T03:56Z. Reviewed on GitHub against references/review-checklist.md, not from the dev's os-dev-report.

    • Shape: the first line is Fixes #20055. The body and changeset declare Clause-②: yes (narrowing), as corrected by the dev and confirmed by the review.
    • Scope: 6 files, +872/−19. Not governed (check-governed-merges: 0 of 6 paths, 891 lines, under the threshold).
      • turso-driver.ts: REMOTE_FACE_ANSWERS, refuseRemoteInheritedMember() and 10 overrides.
      • remote-transport.ts: compileDistinct().
      • A new pin, one flipped assertion, README.md and the changeset.
    • Contract review of record: PASS at 3c1cc7a316 (5827309177).
      • All 23 inherited members' before-and-after answers were reproduced. Every refusal uses the standard NOT_IMPLEMENTED / 501 shape.
      • The compile-time pin discriminates in both directions (TS1360 / TS2353).
      • distinct refuses unsafe column names before any SQL is built.
      • Remote explain keeps its refusal (ruling A).
      • No sentence in the changeset, README or PR body is false.
    • CI at this head: 34 runs, 31 success, 3 skipped, 0 failed. git merge-tree against current main (49144fccc8, 31 commits ahead of the merge base) is clean. The merge queue re-runs the full suite on current main.
    • Why it waited: the seat held this landing for a maintainer decision. The maintainer ruled 「先落地 fix(driver-turso)!: a remote TursoDriver answers or refuses every inherited SqlDriver member (#20055) #20104」 (land fix(driver-turso)!: a remote TursoDriver answers or refuses every inherited SqlDriver member (#20055) #20104 first).

    Landing: ready plus auto-merge through the queue now.

  9. objectstack-fleet commented on Sep 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed: PR #20104, verified on main

    domain:engine#1, session_01Bvd69VPa6puiNzzPUroDBx, written 2026-09-27T04:16Z.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingdomain:engineRetired 2026-10-22, alias of domain:server (engine surface); in-flight cards keep it until they landpriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions