Repository navigation
driver-turso remote: a federated object's external.remoteName is ignored — remote find queries a table named after the object and throws a bare LibsqlError (no code, no status), while the local face reads the mapped table #20107
Description
Filing gate: ① a defect with a named landing site: packages/drivers/driver-turso/src/turso-driver.ts, the remote arms of the read doors, and the RemoteTransport statements they build (packages/drivers/driver-turso/src/remote-transport.ts). Finding class (a).
The domain:engine execution seat 1 (session_01Bvd69VPa6puiNzzPUroDBx) filed this from its #20055 dev's out-of-scope findings (os-dev-report on #20055, PR #20104). The runtime reading is the dev's. ⛔ Filed bare: routing and grading are triage's. ⛔ Not a claim.
What happens
Measured by the #20055 dev at origin/main d4c897e0e7 and at PR #20104's head:
- Local face (the control). After
registerExternalObject({ name: 'ext_t', external: { remoteName: 'probe_t' } }),find('ext_t')readsprobe_t's rows. The external-object mapping resolves the table. - Remote face. The same registration, then
find('ext_t'), throws a bareLibsqlError,SQLITE_ERROR: no such table: ext_t. It has nocode/statusenvelope, so REST serves an unclassified 500.
So on a remote Turso database a federated object cannot be read under its own name. The remote read doors compile against the object name, not the registered remote table.
Suggested shape (⛔ not a ruling)
- Resolve the table name on the remote face the way the local face does, through the same external-object mapping, for every remote read and write door. Or refuse
registerExternalObjecton the remote face with the transport'sNOT_IMPLEMENTED/ 501, if federation is out of contract there. Measure which answer the local face's docs and callers expect first. - Whichever it is, a backend "no such table" must not reach a caller as a bare
LibsqlError. - Pin local against remote with one table: find, findOne, count and aggregate on an external object.
Filing-gate answers
- Class: ① (defect, named landing site); finding class (a), measured by the 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 dev. - Acting reader: this lane's seat (
domain:engine, the owner ofdriver-turso). It is sequenced after PR fix(driver-turso)!: a remote TursoDriver answers or refuses every inherited SqlDriver member (#20055) #20104 (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), which edits the remote arms of the same file. That is a region order, not aBlocked-by:. - Dedupe, MCP semantic issue search in this repo,
closedincluded:turso remote external remoteName ignored registerExternalObject federation no such table LibsqlError→ 7 hits, all read: 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 (the source card, the positive control), 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, 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, external-datasource-federated-read: federated read returns empty — the external object→remote-table mapping never registers (boot ordering) #7737, external-datasource-federated-read: the platform injects its org-scoping predicate onto a federated remote table that has no organization_id column #7738, drivers(turso): RemoteTransport 条件层的$-算子键被当列名编译成静默空集 —— SqlDriver 已按 #5348 拒收,remote 是唯一剩余面(cloud#1077 移交) #5769 and drivers(turso): remote 模式没有继承 #5146 的$notNULL-safe —— 同一个 TursoDriver,local 返回 NULL 行、remote 不返回(实测,origin/main) #5903.- external-datasource-federated-read: federated read returns empty — the external object→remote-table mapping never registers (boot ordering) #7737 (closed) is the federated mapping's boot ordering.
- external-datasource-federated-read: the platform injects its org-scoping predicate onto a federated remote table that has no organization_id column #7738 (closed) is the org-scoping predicate on a federated table.
- None covers the remote face ignoring
remoteName.
Dedupe words: turso remote external remoteName ignored · turso remote federation registerExternalObject · turso remote find raw LibsqlError
Activity
objectstack-fleet commentedon Sep 25, 2026
Path: an API a customer can call | integration-system.external-datasource-federated-read | P2
Triage: first grade —
bug·priority:p2·domain:engine·area:api·pm:queueTriage: lands in
packages/drivers/driver-turso(the remote arms inturso-driver.tsand the statementsremote-transport.tsbuilds) ⇒domain:engine; rationale: on a remote Turso database a federated object'sexternal.remoteNameis ignored, sofindqueries a table named after the object and throws a bareLibsqlError(an unclassified 500), where the local face reads the mapped table. A capability on the checklist that fails on one face ⇒ p2.Triage seat #6015 ·
session_01CRZSc7dU8oDStbTbSwhuZe· 2026-09-25T07:59Z. ⛔ Not a claim, ⛔ not a dispatch. Read: this card and its full thread, andorigin/main. Dedupe by this seat:remoteName→ this card only among open cards (the filer's search read #7737 and #7738, both closed, other federation questions).Execution notes
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 edits the remote arms of the same file.registerExternalObjecton the remote face withNOT_IMPLEMENTED/ 501. Either way, ⛔ no bareLibsqlErrorreaches a caller.objectstack-fleet commentedon Sep 28, 2026
Claim: PM loop round 23
Session:
session_01N8TPEsoJxPsdSdNKGnNGENAccount:
os-warren(the seat's linked user asGET /useranswers it; always the card's assignee)Branch:
claude/issue-20107-turso-remote-remote-nameWorktree:
objectstack-issue-20107Domain:
domain:engineSeat:
domain:engine#1File surface:
packages/drivers/driver-turso/src/turso-driver.ts, the remote arms of the read and write doors: the table name they compile against. This covers either triage route: resolve through the same external-object mapping as the local face, or refuseregisterExternalObjecton the remote face with the transport'sNOT_IMPLEMENTED/ 501. The dev measures first which one the local face's docs and callers expect (triage note 2);packages/drivers/driver-turso/src/remote-transport.ts, the statements it builds, and the error envelope, so that no bareLibsqlErrorreaches a caller;packages/drivers/driver-turso;.changeset/20107-*.md.Stop on breach and explain in the report. ⛔ Not the remote
reclaimSpaceroute (#20106, same fire), nor the constructor (#20200). ⛔ Notdriver-sql's external-object mapping: if the local face's mapping must move to be shared, stop and report.Container & model:
M,mode:subagent,model: opus(dispatch-gates --tier: no path-derived mandate, floor sonnet · default opus · ceiling fable)Clause-②: no
Thread-read: 5828997450
Serial constraints cleared: at 2026-09-28T09:11Z, a census of the 14 open PRs (titles, plus the file lists of #20391, #20348, #20404 and #20407) and of the newest
Claim:on every one of the 23 openpm:dispatchedcards finds none ondriver-turso. The region order after PR #20104 is satisfied: it landed as84880f922. #20106 (the remotereclaimSpaceroute) is dispatched in the same fire into another region ofturso-driver.ts, so the later lander mergesmain.Clause-②: no: either route narrows or aligns; neither widens. Resolving the mapping gives the remote face what the local face already does. RefusingregisterExternalObjectremotely narrows, and the report and changeset then declare(narrowing)in the PR body.objectstack-fleet commentedon Sep 28, 2026
os-dev-report
{ "issue": 20107, "status": "done", "branch": "claude/issue-20107-turso-remote-remote-name", "pr": "https://github.com/objectstack-ai/objectstack/pull/20422", "session": "session_01N8TPEsoJxPsdSdNKGnNGEN", "premise_still_valid": true, "summary": "Resolve route. The docs and callers expect it. IDataDriver.registerExternalObject says a driver that carries the member records the remote table 'so queries resolve to the remote table'. ADR-0015 says remoteName 'is honoured on all dialects'. external-datasources.mdx fences no driver or transport out. drivers.mdx says nothing about federation per Turso transport, which is itself a reading. The remote face carries the member ('inherited'), so it delivers. Every remote TursoDriver data door (find, findOne, count, aggregate, distinct, create, update, upsert, delete, bulkCreate, bulkUpdate, bulkDelete, updateMany, deleteMany) goes through a new remoteTableFor(), which reads SqlDriver's protected physicalTableByObject in place. That is the registry getBuilder reads locally, and it is neither moved nor copied. The resolved table is passed to RemoteTransport as a new optional last argument on its 14 data methods; omitted, it defaults to the object. The table is quoted as one SQL name with embedded quotes doubled. The remote find/findOne/count exits now end in SqlDriver.backendStatementFault (DATABASE_ERROR/500, non-enumerable cause, targeted table declared). A federated object whose external.columnMap renames a column is refused NOT_IMPLEMENTED/501 on every remote data door before any statement is sent. That refusal is a bounded in-place fix, and it is owed: with only the table resolved, a filter on a renamed field would turn from a loud 'no such table' into a silent [] (measured with the refusal bypassed). H1 confirmed in behaviour at base 789b2ae54. H2 confirmed: the mapping is protected and readable in place. H4 holds for every read door and for writes on an existing mapped table. H4 does not hold as worded for writes on a mapped table that is really absent: those keep the backend error on both faces, the local control included (SqliteError, no status), which is backendStatementFault's documented write-path boundary.", "tests": "Head 37414c5e8 (the branch merged with origin/main 40b315b03). pnpm --filter @objectstack/driver-turso test: 'Test Files 74 passed (74) / Tests 1975 passed | 16 skipped (1991)'. pnpm --filter @objectstack/driver-turso typecheck: exit 0, and tsc --listFiles includes the new test file. New file turso-local-remote-external-object-parity.test.ts: 'Tests 54 passed (54)'. It uses a real @libsql/client on a file: DB, with a local driver over the same file as the control, and covers: read parity on one table for find/find-filtered/findOne/count/count-filtered/aggregate/aggregate-grouped/distinct, each also checked against the literal answer; write parity per door on fresh copies (create, update, upsert merge and insert, delete, bulkCreate, bulkUpdate, bulkDelete, updateMany, deleteMany), with the same rows after and no ext_t table created; a mapped table that is really absent, where find/findOne/count answer DATABASE_ERROR/500 on both faces, the cause is non-enumerable, the message and JSON withhold absent_t, and Symbol.for('objectstack.driver.targetedTable') is absent_t, matching the libSQL phrase; the renaming columnMap, refused NOT_IMPLEMENTED/501 on 14 doors with a client.execute spy never called and the table unchanged, while the local control translates the map and an identity map is served; a managed-object control. Reverse verification: the fix was committed first (48968c65c), every leg went through node scripts/ablation-replace.mjs (anchor 1 -> 0, blob changed, restore proven by blob == HEAD and git diff HEAD empty), and an outer trap re-verified the restore. The subject resolves from src through a relative import with no vitest alias, so dist is not in the path and there is no rebuild. Leg A (remoteTableFor returns object): 22 failed / 32 passed (8 remote read parity, 10 write parity, 3 phrase-vs-declared, 1 identity map; 'LibsqlError: SQLITE_ERROR: no such table: ext_t', aggregate [] vs [{total:7}]). Leg B (remoteReadExit rethrows bare): 9 failed / 45 passed, all of section 3 ('expected SQLITE_ERROR to be DATABASE_ERROR'). Leg C (column-map refusal deleted): 15 failed / 39 passed (14 doors plus the seeded-rows check; find resolved [], writes SQLITE_ERROR, count DATABASE_ERROR, distinct INVALID_FIELD). The directions matched the predictions written in the test header. Leg A also turned the identity-map case red, which the header did not name; that case reads the mapped table too. Lint, narrowed: eslint --no-inline-config --format json on the 3 changed .ts files gave 3 files, 0 errors, 0 warnings. ① The population is read from eslint.config.mjs (packages/**/*.{ts,tsx,mts,cts}). ② The file count is from the JSON (3). ③ Invariance: the effective parserOptions {ecmaVersion:latest, sourceType:module} have no project, and all 6 active rules are per-file AST rules, so type-aware linting is off and this diff cannot move a verdict on any untouched file. The full pnpm lint is CI's.", "gates": { "measured_head": "37414c5e8", "derivation": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack -> 63 commands (change set: 4 paths vs merge base 40b315b03)", "run": "63 of 63, each exit code captured to a file before any pipe", "first_pass_exit_3": ["pnpm check:dual-build-cjs-loads", "pnpm check:lean-entry-closure", "pnpm check:type-check-debt"], "remedy": "turbo run build --filter='./packages/*' --filter='./packages/*/*' (71 tasks), then re-ran all three: exit 0. Also re-ran check:dts-closure (71 packages swept), check:sourcemap-no-sources-content (68) and check:published-files on the full build: exit 0.", "final": "63 exit 0", "ran_verdict": "dispatch-gates --ran: 63 derived famil(ies) accounted for — 63 run, 0 NOT-MEASURED (a DERIVED zero — all 63 recorded an exit code and none of them is 3)", "driver_conformance": "before (789b2ae54): 'OK — 50 covered cell(s), 0 in the DEBT ledger, 0 exempt'; after (37414c5e8): 'OK — 50 covered cell(s), 0 in the DEBT ledger, 0 exempt'", "not_measured": "CI-only lanes named by the derivation outside its 63 commands (path-scheduled Test Core / Temporal Conformance / Dogfood / Build Core jobs, the four type-check lanes, workflow-valued families): declared to CI", "ci": "in_progress (not awaited)" }, "line_budget": "792 changed lines (+738 / -54) over 4 files vs the 5000 human-merge threshold: under. No governed surface, and no skills/** or ledger line budget in play.", "files_changed": [ ".changeset/20107-turso-remote-external-remote-name.md (+22 / -0)", "packages/drivers/driver-turso/src/remote-transport.ts (+96 / -34)", "packages/drivers/driver-turso/src/turso-driver.ts (+201 / -20)", "packages/drivers/driver-turso/src/turso-local-remote-external-object-parity.test.ts (+419 / -0)" ], "deviations": [ "Bounded in-place fix, declared in the PR body: the NOT_IMPLEMENTED/501 refusal of a renaming external.columnMap on the remote data doors. All four conditions hold (same external-binding defect class, the file's own pinned 501 shape, no other claim on these lines, same package tests). It is owed because the resolve alone would have turned a loud failure into a silent []. It is inside the claimed file surface (the remote arms of turso-driver.ts). The remote reclaimSpace route, the constructor and driver-sql's mapping are untouched.", "origin/main moved to 50e273fd7 after the merge commit 37414c5e8 (one commit, packages/services/service-analytics only, disjoint from this change set). It was not re-merged. The gates and tests are quoted at 37414c5e8. The remote reclaimSpace card (#20106) had not landed at either reading.", "Commit trailers use AGENTS.md's model-free pair (Claude-Session + Co-authored-by: Claude), not the harness reminder's model-named Co-Authored-By. The PR body ends in AGENTS.md's session-URL footer, not the harness reminder's PR ending. AGENTS.md and os-dev.md take precedence, and the pre-push hook refuses a model identifier.", "PR labels documentation, size/l, tests and tooling were already present at label-write step ① and were not written by this run. This run wrote only the assignee (os-warren)." ], "mcp_calls": "0 — no MCP GitHub tool was called", "api_writes": "3 — all through the fleet relay (scripts/pm/fleet-write/dispatch.mjs, route dispatch, session_01N8TPEsoJxPsdSdNKGnNGEN), each one POST /repos/objectstack-ai/objectstack/dispatches executed by the fleet-write workflow: (1) pr_create, POST /repos/objectstack-ai/objectstack/pulls, draft #20422 (run 36408832667); (2) label-write --assign os-warren, POST /repos/objectstack-ai/objectstack/issues/20422/assignees (run 36408936784); (3) post-stamped, POST /repos/objectstack-ai/objectstack/issues/20107/comments, this report. No issue_patch was spent: the PR body read back byte-intact. Plus git push of the branch, which is not a REST write.", "open_questions": [ { "question": "RemoteTransport is exported from @objectstack/driver-turso, and its 14 data methods gained an optional last 'table' parameter. Nothing was removed or narrowed. Does that additive parameter change the claim's 'Clause-②: no', which the PR body copies verbatim?", "options": [ "A keep 'Clause-②: no' + patch: the parameter is optional, only TursoDriver's own delegate uses it, and RemoteTransport's doc says it is not exposed directly to users", "B re-declare as a widening (minor): an exported class's methods accept a new argument" ], "recommendation": "A. The accepted set of every existing call is unchanged, and the class is documented as an internal delegate. The seat owns the line, so it is flagged rather than changed." } ], "out_of_scope_findings": [ "class: a · reach: named producer — REST GET /api/v1/data/:object (ObjectQL find -> TursoDriver.find, remote face) on a declared field whose remote column is absent, and service-analytics' ObjectQL aggregate path (AnalyticsService -> engine.aggregate -> TursoDriver.aggregate, remote face) · evidence: at 37414c5e8, over one libSQL file with the local driver as control: aggregate on a mapped table that is really absent gives local DATABASE_ERROR/500, remote []; aggregate grouped by a declared field whose column is absent gives local INVALID_FIELD/400, remote []; find whose WHERE names a declared field whose column is absent gives local INVALID_FILTER/400, remote []. Sources: the RemoteTransport.aggregate catch ('no such table' / 'no such column' -> []) and the RemoteTransport.find $select backstop (returns [] when no projection is present). It applies to managed objects too, and predates this PR · dedupe words: turso remote aggregate no such table empty · turso remote find no such column empty result · RemoteTransport invented empty read · turso remote read exit swallows missing column", "carrier: 承接者:无 · noted, not filed — translating external.columnMap on the Turso remote face (it is refused NOT_IMPLEMENTED/501 by this PR; implementing it would put a second copy of the local column rule into the transport compiler, and no demand is measured).", "carrier: 承接者:无 · noted, not filed — a remoteName containing a dot: knex splits it into a schema qualifier on the local face, while the remote face quotes it as one name. Unmeasured, and nobody is known to author that shape." ] }Generated by Claude Code
objectstack-fleet commentedon Sep 28, 2026
Claim: PM loop round 23
Session:
session_01N8TPEsoJxPsdSdNKGnNGENAccount:
os-warren(the seat's linked user asGET /useranswers it; always the card's assignee)Branch:
claude/issue-20107-turso-remote-remote-nameWorktree:
objectstack-issue-20107Domain:
domain:engineSeat:
domain:engine#1File surface:
packages/drivers/driver-turso/src/turso-driver.ts, the remote arms of the read and write doors: the table name they compile against. This covers either triage route: resolve through the same external-object mapping as the local face, or refuseregisterExternalObjecton the remote face with the transport'sNOT_IMPLEMENTED/ 501. The dev measures first which one the local face's docs and callers expect (triage note 2);packages/drivers/driver-turso/src/remote-transport.ts, the statements it builds, and the error envelope, so that no bareLibsqlErrorreaches a caller;packages/drivers/driver-turso;.changeset/20107-*.md.Stop on breach and explain in the report. ⛔ Not the remote
reclaimSpaceroute (#20106, same fire), nor the constructor (#20200). ⛔ Notdriver-sql's external-object mapping: if the local face's mapping must move to be shared, stop and report.Container & model:
M,mode:subagent,model: opus(dispatch-gates --tier: no path-derived mandate, floor sonnet · default opus · ceiling fable)Clause-②: yes (widening)
Thread-read: 5868026272
Serial constraints cleared: at 2026-09-28T09:11Z, a census of the 14 open PRs (titles, plus the file lists of #20391, #20348, #20404 and #20407) and of the newest
Claim:on every one of the 23 openpm:dispatchedcards finds none ondriver-turso. The region order after PR #20104 is satisfied: it landed as84880f922. #20106 (the remotereclaimSpaceroute) is dispatched in the same fire into another region ofturso-driver.ts, so the later lander mergesmain.Amended (this re-posted claim supersedes 5866949419's
Clause-②line; everything else is unchanged). The at-tier contract review of PR #20422 (record 5868256854, FAIL on ② only) found thatRemoteTransportis exported from@objectstack/driver-turso's root entry, and that 14 of its methods gain an honoured optionaltableparameter. That is a signature widening of a published export, so the line readsyes (widening)and the changeset shipsminor. The seat rules on the review's flag ③.2: a binding with noremoteName(or one equal to the object name) plus a renamingcolumnMapwas an accidental half-service on the remote face, whose filtered reads were already silently wrong. Refusing it narrows no published accept set, so there is no narrowing arm; the changeset's refusal bullet names that shape.objectstack-fleet commentedon Sep 28, 2026
os-dev-report
{ "issue": 20107, "round": "patch round 1 (contract review record 5868256854: FAIL on ② only)", "status": "done", "branch": "claude/issue-20107-turso-remote-remote-name", "pr": "https://github.com/objectstack-ai/objectstack/pull/20422", "session": "session_01N8TPEsoJxPsdSdNKGnNGEN", "premise_still_valid": true, "claim_check": "Newest Claim: on #20107 is the amended 5868269122. It names branch claude/issue-20107-turso-remote-remote-name and reads 'Clause-②: yes (widening)'.", "head": "20375d3da", "summary": "Only the changeset and the PR body changed, with no code or test change: packages/ at 20375d3da is byte-identical to 37414c5e8. Changeset: '@objectstack/driver-turso': patch -> minor; 'Clause-②: no' -> 'Clause-②: yes (widening)'; a new 'What changes' bullet names the widening (RemoteTransport, exported from the package root, gains an optional trailing table argument on its 14 data methods; omitted, it defaults to the object), replacing the trailing paragraph that said the same; the columnMap refusal bullet now names the binding with no remoteName, or with remoteName equal to the object name, plus a renaming map (before, its unfiltered reads and id-keyed writes answered, while its filtered reads were already silently wrong). Its before-state sentence was also tightened to 'failed with no such table on every door but aggregate, which answered []'. There is no narrowing arm and no ADR-0087 marker, per the seat's ruling. PR body: the Clause-② line now reads yes (widening); the 'Nothing that worked stops working' sentence is replaced by one that names that shape and the seat's half-service ruling; a '## Patch round 1' section cites record 5868256854 and claim 5868269122; the Files line and the RemoteTransport acceptance note now say minor and yes (widening). The body was read back byte-identical (14160 bytes).", "tests": "No code or test changed, so the round-0 measurements at 37414c5e8 stand, and packages/ at 20375d3da is byte-identical to them. Changeset gates at head 20375d3da, each exit captured before any pipe. (1) node scripts/check-changeset-no-major.mjs --base origin/main --event event.json, where event.json is a pull_request payload built from the new PR body and the PR's labels: exit 0, with '✓ This diff introduces no `major` bump.' and '✓ LEVEL AXIS: this PR declares clause-② `yes (widening)`, and no package whose `packages/**/src/**` it moves is graded `patch`.' (declaration line 'Clause-②: yes (widening)', direction arm 'widening'). (2) node scripts/check-adr-0087-registration.mjs --base origin/main: exit 0, '✓ check-adr-0087-registration: this PR adds no declared-breaking changeset (1 non-breaking changeset(s) seen).' (3) node scripts/check-empty-changeset.mjs --base origin/main: exit 0, '✓ No empty-frontmatter changeset introduced by this diff (1 declaring changeset(s) added).' and '✓ No changeset from the merge base modified or deleted by this diff (#17712).' (4) node scripts/check-closing-keyword-parity.mjs --body new-body.md: exit 2, which is this mode's 'declarations bind' answer, not a failure: 'check-closing-keyword-parity --body: 2 closing declaration(s) ... bound by 2 of 3 registered parser(s).' Both bindings are 'Fixes #20107' (duplicate-fix-guard same-repo, h7-partof-closing-keyword bare). No other number binds.", "gates": { "measured_head": "20375d3da", "check-changeset-no-major --event": "exit 0", "check-adr-0087-registration": "exit 0", "check-empty-changeset": "exit 0", "check-closing-keyword-parity --body": "exit 2 (binds only the intended Fixes #20107)", "ci": "in_progress (not awaited)" }, "line_budget": "This round: +4 / -5 in one file. Total vs merge base 40b315b03: +737 / -54, under the 5000 human-merge threshold.", "files_changed": [ ".changeset/20107-turso-remote-external-remote-name.md (+4 / -5)" ], "deviations": [ "Beyond the three dictated changeset edits, one sentence in the refusal bullet was made exact: 'Before this change the same object failed on every door with no such table' now reads 'an object whose remoteName differs from its name failed with no such table on every door but aggregate, which answered []', which matches the measured table. The changeset only.", "The standalone trailing paragraph about RemoteTransport's optional argument was folded into the new 'What changes' bullet rather than kept beside it, so the widening is stated once." ], "mcp_calls": "0 — no MCP GitHub tool was called", "api_writes": "2 — both through the fleet relay (route dispatch, session_01N8TPEsoJxPsdSdNKGnNGEN), each one POST /repos/objectstack-ai/objectstack/dispatches executed by the fleet-write workflow: (1) issue_patch on 20422 with body, PATCH /repos/objectstack-ai/objectstack/issues/20422 (run 36411329614), read back byte-identical; (2) post-stamped comment on 20107, POST /repos/objectstack-ai/objectstack/issues/20107/comments (this report). Plus git push of 20375d3da (fast-forward, no rebase, no force), which is not a REST write.", "open_questions": [], "out_of_scope_findings": [] }Generated by Claude Code
objectstack-fleet commentedon Sep 28, 2026
ACCEPT — PR #20422 at
20375d3da3abeee0feaff6da5c7c4038149787efdomain:engine#1·session_01N8TPEsoJxPsdSdNKGnNGEN(os-warren) · written 2026-09-28T10:59Z. Contract review of record: delta 5868528334 on PR #20422, at-tier, read-only, PASS on this head. It follows the FAIL 5868256854 on37414c5e8, which failed on ② only, and patch round 1.packages/is byte-identical between the two heads.Checklist, verified against GitHub rather than the reports:
main, first lineFixes #20107. That is the only closing keyword in the body, and this card's newest claim (5868269122) names the branch and readsClause-②: yes (widening).turso-driver.ts,remote-transport.ts, one parity test in the same package, and one changeset.@objectstack/driver-tursominor,Clause-②: yes (widening).RemoteTransportis a root export, and 14 of its methods gain an optionaltable. The column-map refusal carries no narrowing arm (seat ruling in 5868269122).check-governed-merges --pr 20422: not governed). Under the human-merge threshold.success, the restsuccessor path/event-skipped, none red.mergeable_state: clean.Out-of-scope findings, one line each:
RemoteTransport.aggregate/findon a missing table or column: filed driver-turso remote:aggregate/findanswer[]for a missing table or a missing column, where the local face refuses DATABASE_ERROR / 500 or INVALID_FIELD / INVALID_FILTER / 400 (the #8790 shape on the remote transport) #20424.external.columnMapon the remote face (now refused 501): Acceptance notes, no pull.remoteNamecontaining a dot: Acceptance notes, unmeasured, no author.deployment/backup-restore.mdxsays the open framework does not ship the Turso driver, which it does (pre-existing, from the review's docs read): filed separately as a docs card.Landing:
readyplus auto-merge through the queue. The merge closes this card (Fixes), and the seat verifies it onmainand removespm:dispatchedin the same act.objectstack-fleet commentedon Sep 28, 2026
Landing record: PR #20422 merged. This card is closed
completedby itsFixeslinedomain:engine#1·session_01N8TPEsoJxPsdSdNKGnNGEN(os-warren) · written 2026-09-28T11:25Z.Verified on
main:dbddf02c1dc580d2cb4e91e8dc6046bf58658433, a queue merge with one parent. It is an ancestor oforigin/main, and theorigin/maintip is the squash itself.driver-tursosource files are byte-identical to the accepted head20375d3da.turso-local-remote-external-object-parity.test.tsand the20107-*changeset are present at the squash and absent at its parent.remoteNameappears inturso-driver.ts5 times at the squash and once at its parent.Fixes #20107, so no other card was closed.Delivered: the remote face of
TursoDriverreads and writes a federated object'sexternal.remoteNametable, as the local face does.RemoteTransport's 14 data methods take an optional trailingtable. A renamingexternal.columnMapis refused on the remote face withNOT_IMPLEMENTED/ 501, and no bareLibsqlErrorreaches a caller.@objectstack/driver-tursoshipsminor(Clause-②: yes (widening), amended claim 5868269122). ACCEPT is 5868539222, and the contract review of record is the delta 5868528334 (PASS), after the FAIL 5868256854 on ② only.Carried out of this card:
aggregate/findanswer[]for a missing table or a missing column, where the local face refuses DATABASE_ERROR / 500 or INVALID_FIELD / INVALID_FILTER / 400 (the #8790 shape on the remote transport) #20424: the remoteaggregate/findanswer[]for a missing table or column.remote-transport.tsis now free for it.@objectstack/driver-tursoships and three other pages document it #20430: the docs contradiction on whether the open framework ships the Turso driver.pm:dispatchedis removed in the same act as this record. The domain, area and type labels stay.docs(driver-turso): two comments this change made false now say what …
fix(driver-turso): the remote face reads and writes a federated objec…
fix(driver-sql, driver-turso): reclaimSpace() returns the whole SQLit…
fix(driver-turso): the remote face refuses a missing table or column …