Skip to content

[finding] TursoDriver remote mode silently discards options.transaction — a write between beginTransaction() and rollback() is already durable and the rollback does not undo it #18616

Description

@huangyiirene

Filed by the domain:engine execution seat, session_01CqmCgU5RGDoJYhHUMVp2af, R1, out of the #18116 measurement tranche (dev report 5711799466, which flagged it 「to file」). ⛔ No domain:* and no priority:* asserted — both have exactly one producer, the triage seat.

⭐ Every reading below was re-taken by the filing seat on origin/main before filing, ⛔ not carried over from the report.

The defect

packages/spec/src/data/driver.zod.ts:636 states the contract verbatim:

A transaction handle to be passed to subsequent operations via options.transaction.

In TursoDriver remote mode nothing can receive that handle. A write issued between beginTransaction() and rollback() is already durable, and the rollback does not undo it.

Readings, with a firing control

reading instrument result
members of RemoteTransport naming a transaction signature scan of packages/drivers/driver-turso/src/remote-transport.ts exactly 3: beginTransaction(), commit(transaction), rollback(transaction)
data methods accepting options or a transaction same file, same instrument 0
⭐ firing control — data methods present at all in that file same file 9 ⇒ the zero above is a reading, ⛔ not a dead grep
this.isRemote guards in turso-driver.ts git grep -c 26

The report adds, and the seat did not independently re-derive: the guards forward without options (e.g. find:970, create:1106), and connect():860 skips knex initialisation on the remote arm — which is why no SqlDriver body that would honour a handle ever runs.

Why this is class (b), and arguably (a)

(b) — violates a declared contract, with the contract text quoted above. The declaration is not ambiguous: it names options.transaction as the delivery mechanism, and the remote transport has no parameter to deliver it to.

(a) is also available: the failure is reproducible and user-reachable — begin, write, roll back, observe the row. ⚠️ The filing seat has not run that reproduction (no Turso remote endpoint in this container), so (a) is offered as a claim to be measured, ⛔ not as a measured fact. The (b) limb stands on the quoted text alone.

⭐ The asymmetry that makes this worth a card rather than a note: turso-driver.test.ts:211-214 asserts exactly this shape for LOCAL mode. Nothing asserts it for remote. So the tree already knows what correct looks like here.

⚠️ For triage: this may belong as a sub-issue of #18063, not as a free-standing card

Carried verbatim from the measuring dev, and the filing seat agrees it is a real question it should ⛔ not decide:

this is the SEMANTIC half of #18063's cell while #18063 carries only the DECLARATION half, so it is a candidate sub-issue of #18063 rather than a free-standing card; the triage seat should decide which.

#18063 was returned to the decision box in the same round (5711873237) precisely because the measurement showed the declaration half buys a correct type over a transaction that collects no statements — i.e. this defect is what makes that one hard to price. If the maintainer's answer to #18063 is 「let a transport declare it has no transactions」, this card may be discharged by that ruling rather than fixed separately.

Dedupe words

Turso remote transaction ignored · options.transaction dropped remote · RemoteTransport no transaction handle · remote rollback does not undo · decorative transaction libsql

Re-check

git grep -n "passed to subsequent operations via" origin/main -- packages/spec/src/data/driver.zod.ts
git show origin/main:packages/drivers/driver-turso/src/remote-transport.ts | grep -nE "^\s{2}(async )?[a-zA-Z]+\(" | grep -iE "options|transaction"
git grep -c "this.isRemote" origin/main -- packages/drivers/driver-turso/src/turso-driver.ts

Generated by Claude Code

Activity

  1. self-assigned this
    on Sep 17, 2026
  2. huangyiirene commented on Sep 17, 2026

    @huangyiirene
    CollaboratorAuthor

    Claim: PM loop round 3
    Session: session_01CqmCgU5RGDoJYhHUMVp2af
    Branch: claude/issue-18616-turso-remote-transaction-refusal
    Worktree: objectstack-issue-18616
    Domain: domain:engine
    Seat: domain:engine#1
    File surface: packages/drivers/driver-turso/src/ (stop on breach; explain in the report)
    Container & model: M, mode:subagent, model: opus (default judgement tier) — quoting this dispatch's own dispatch-gates.mjs --tier packages/drivers/driver-turso/src/remote-transport.ts: 「Model tier — no path-derived mandate: the surface hits none of the 3 declared glob(s) … The tier stays the PM's per-card judgment call (floor sonnet · default opus · ceiling fable).」 ⇒ default judgement tier: the deliverable is a refusal boundary on a data-integrity path, ⛔ not a mechanical edit.
    Clause-②: yes
    Thread-read: 5716552116
    Serial constraints cleared: No in-flight card in this lane touches packages/drivers/driver-turso. The only pm:dispatched card at claim time is #18554 (file surface packages/formula/src/), disjoint. ⭐ #18408's PR #18668 landed at 14:59:50Z as ef67b47afb and DID touch driver-turso/src/remote-transport.ts (mapFieldTypeToSQL) — it is merged, not in flight, so this is a predecessor to branch from, ⛔ not a conflict; branch from a main that contains it. ⚠️ #18063 sits pm:awaiting-maintainer and this card's own body raised it as a possible parent; triage answered that question in 5716552116 and graded this free-standing and dispatchable with no new ruling needed, so the seat does ⛔ not re-open it.

    The deliverable, and the line triage drew

    ⛔ The deliverable is「stop the silence」, NOT「implement remote transactions」. Triage wrote that boundary into the card and this dispatch adopts it verbatim:

    止损(本卡):remote 模式遇到 options.transaction 或 beginTransaction() 时大声拒绝 / 声明不支持,让调用者立刻知道自己没有事务语义。
    实现远程事务:那是 #18116 已完成的那次「measure, do not implement」量出来的半径,是另一件事、另一个量级。⛔ 不要把它折进本卡。

    ⇒ If your measurement says the honest refusal is cheap and remote transactions are one file further, that is ⛔ not an invitation to do both. Report the radius; do not spend it.

    What this seat owes you, measured before dispatch

    The card's readings were re-taken by the filing seat on origin/main before filing, and the zero carries its own firing control — 0 data methods accepting options or a transaction, against 9 data methods present in the file. ⛔ Re-derive both anyway on your head: packages/drivers/driver-turso/src/remote-transport.ts was edited by PR #18668 since the card was written, so the line numbers in the card body may have moved. ⭐ Locate by content, ⛔ not by line.

    ⚠️ The part that needs your judgement, ⛔ not this seat's

    Where does the refusal live, and what shape is it? Three candidates the seat can see, and it is ⛔ not ruling between them:

    1. beginTransaction() on the remote arm throws instead of returning a decorative handle.
    2. Every remote data method that receives options.transaction throws.
    3. Both.

    ⭐ (1) alone may be the whole fix or may be a false floor — a caller that never calls beginTransaction() but passes a handle it got elsewhere would still be silently ignored. Measure which callers can reach a remote data method with a transaction in hand, then choose, and say why the one you did not choose is not needed. ⛔ A choice with no stated alternative is not a measurement.

    ⚠️ The existing local-mode pin is your model: turso-driver.test.ts:211-214 already asserts this shape for LOCAL mode. ⇒ The tree knows what correct looks like here; the remote face is what is unpinned.

    Clause-② is yes, and here is the seat's reasoning — argue it down if you measure otherwise

    This card changes what the driver accepts: a call that today succeeds silently will refuse. That is contract accept/reject behaviour moving, so the conservative grade applies and needs:contract-review rides with it.

    ⚠️ If your fix needs a NEW error code, that lands in packages/spec/src/api/error-code-ledger.zod.ts, which is ⛔ outside your file surface and belongs to the domain:spec seat. Report it as a blocker with the code you would want and why an existing one does not fit — ⛔ do not reach into packages/spec.

    ⛔ skip-changeset is almost certainly wrong here: @objectstack/driver-turso publishes and this moves its behaviour. Measure it the way your role file prescribes rather than taking this line as the finding.

    Report

    Per .claude/agents/os-dev.md — that file governs your report's field set, your write budget and your label discipline, ⛔ not this comment. Where this dispatch and the role file differ, the role file wins and you say so in the report.


    Generated by Claude Code

  3. huangyiirene commented on Sep 17, 2026

    @huangyiirene
    CollaboratorAuthor

    os-dev-report

    {
      "issue": 18616,
      "status": "done",
      "branch": "claude/issue-18616-turso-remote-transaction-refusal",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/18717",
      "session": "session_01CqmCgU5RGDoJYhHUMVp2af",
      "premise_still_valid": true,
      "summary": "The Turso REMOTE face now refuses transactions with NOT_IMPLEMENTED/501 instead of accepting them and dropping them: the trio (beginTransaction/commit/rollback) on the remote arm, plus every remote-arm override that arrives carrying options.transaction (17 doors: find, findOne, count, aggregate, create, update, upsert, delete, the three bulk methods, updateMany, deleteMany, execute, syncSchema, syncSchemasBatch, dropTable). BOTH doors, and that was the judgement the dispatch left open: measured, there are two independent producers of a handle, because objectql's buildDriverOptions reads execCtx.transaction FIRST and transactionCoversDriverFor declines to judge a handle that is not the ambient store's, so an ExecutionContext-threaded handle never passes through beginTransaction() — ablation 2 below measures that false floor rather than arguing it. The refusal lives on TursoDriver, not RemoteTransport, because the transport's data methods have no options parameter at all. NO new error code and packages/spec untouched: NOT_IMPLEMENTED is a StandardErrorCode member and the ledger registers extension codes only, so the blocker the dispatch anticipated did not materialise. Local and embedded-replica behaviour unchanged (the guard returns unless isRemote). Card readings re-derived by content on base f8eaf670454a (contains ef67b47afb/#18668): transaction-naming members 3, data methods taking options 0, this.isRemote guards 26 — all match; the firing control re-derives to 13 data methods, not the card's 9, which strengthens the zero rather than weakening it and is recorded in the PR body. Radius NOT spent, as instructed: implementing remote transactions means an options parameter on 13 transport data methods, threading a libsql Transaction through each statement builder, and deciding what the knex-free remote connect() does about SqlDriver's openTransactions accounting. The card arrived assigned (huangyiirene) with pm:dispatched/priority:p1/domain:engine; assignee untouched. No dispatch-vs-role-file conflict arose in substance: the role file governs the field set and the write budget and it did; on labels the role file's 'label the PR as soon as it opens' resolves to ZERO label writes here, because the only dev-owned label is skip-changeset (measured inapplicable) and needs:contract-review is the seat's by the dispatch and by check-clause2-carriers' own report-only stance.",
      "tests": "ALL GREEN. (1) pnpm --filter @objectstack/driver-turso test :: exit 0 — 'Test Files 54 passed (54) / Tests 1278 passed (1278)', which contains the pre-existing local-mode transaction pins. (2) pnpm --filter @objectstack/driver-turso typecheck :: exit 0. (3) pnpm --filter '@objectstack/driver-turso^...' build :: VERDICT command-exit 0 (dependency closure, via scripts/pm/os-verify-lock.sh, OS_VERIFY_LOCK_SLOT=issue-18616 on every locked call). (4) Full package build 'pnpm exec turbo run build --filter=./packages/* --filter=./packages/*/*' :: VERDICT command-exit 0, 'Tasks: 72 successful, 72 total'. (5) GATE FAMILIES derived mechanically with 'node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack' (never from a hand-written diff; derivation run twice and byte-identical both times; its only STALE-TREE complaint names scripts/pm/post-stamped.mjs, a PM tool in the always-runs tail, not a family judging this diff): 60 derived, 60 run, 0 NOT MEASURED, 0 UNRUN, reconciled back through --ran with 'command :: exit N' per family, verdict line 'dispatch-gates --ran: 60 derived famil(ies) accounted for — 60 run, 0 NOT-MEASURED (a DERIVED zero)'. Every exit code captured BEFORE any pipe (redirect-then-capture). One family was a REAL RED and is fixed in this PR: check:doc-authoring refused the tracker id inside the refusal's runtime string; the id moved to the docblock and the re-run is exit 0 ('sibling-package prose ids hold the baseline — 821 pinned site(s) ... no growth'). Three families answered PREREQUISITE NOT MET (exit 3 = NOT MEASURED, not a failure) until the full build above, then exit 0: check:dual-build-cjs-loads, check:lean-entry-closure, check:type-check-debt. check:error-code-casing run additionally :: exit 0. (6) pnpm lint :: exit 0 — the repo-wide 'eslint . --no-inline-config' UNION, not a narrowed run, at final commit 97009bc42e, so no narrowing evidence is owed. ABLATION — two legs, both run from the COMMITTED fix, direction predicted before either ran, each mutating turso-driver.ts on disk under a trap whose restore is 'git checkout HEAD -- ABSOLUTE_PATH' verified by blob equality AND empty 'git diff HEAD'. Subject HEAD blob 4b2b21a0da4e1b65f67d0f8f803a2283bff64c6c. ON-DISK MUTATION PROOF per leg, by grep count and by a changed blob, with a hard abort wired for a no-op: leg 1 'guard-body lines 1 -> 0, injected ABLATED-OPTIONS-DOOR marker 1, injected ABLATED-TRIO markers 3, refuseRemoteTransaction call sites 4 -> 1, blob 0dffa9731274'; leg 2 'guard-body lines 1 -> 0, marker 1, ABLATED-TRIO 0, call sites 4 -> 4, blob 4ca762d9e647'. LEG 1 (both doors removed, trio restored to its pre-fix delegation) predicted the two REMOTE blocks red and the silence controls green; measured '21 failed | 5 passed (26)' — 4 trio + 17 options red, 5 controls green, and the failures REPRINT the defect ('expected the remote face to refuse, but it resolved with ...'). LEG 2 (only the options door removed, i.e. exactly a fix that had stopped at beginTransaction()) predicted 17 red / 9 green; measured '17 failed | 9 passed (26)' — the false floor, measured rather than argued. Both legs closed with 'RESTORE OK — on-disk blob 4b2b21a0da4e... == HEAD blob 4b2b21a0da4e..., and git diff HEAD is empty'. REBUILD NOTE: the ablation needs no dist round trip and none is claimed — the pin suite imports the package's own source relatively ('./index.js' -> src/index.ts), so the resolution path is src/, not dist/; the full-package build above is separate and was run for the three prerequisite gates. CHANGESET MEASURED, not assumed: skip-changeset is WRONG here. driver-turso publishes with files[] = dist, README.md, CHANGELOG.md; after building, a symbol unique to this change hits dist/index.js:1 and dist/index.mjs:1, the positive control (a pre-existing shipped refusal sentence) hits dist/index.js:2, dist/index.mjs:2, CHANGELOG.md:2, and the negative control (a test-only helper name) hits 0 anywhere in files[] — so it publishes and .changeset/18616-turso-remote-transaction-refusal.md grades @objectstack/driver-turso minor (clause-② level axis satisfied; launch-window major ban respected). CONTRACT-REVIEW READINGS, as the dispatch asked: needs:contract-review is NOT on PR 18717 and not on card 18616 (PR labels read back: ['size/l'], added by the repo labeler, not by me); 'node scripts/pm/check-clause2-carriers.mjs --pair 18717' :: exit 4, row C3 — 'card #18616 declares Clause-②: yes while NEITHER it nor its delivering open PR #18717 (draft) carries needs:contract-review, and the event stream shows the gate was NEVER HUNG on either carrier'. Reported, not acted on: that label is the seat's, and the checker itself states it never writes one. PR body read back after creation: byte-identical to what was sent apart from a trailing newline, one footer in the session-URL form, 'Fixes #18616' on line 1, 'Clause-②: yes' at column 0 — no sanitizer mutation. CI not waited on, per the role file; nothing on the PR has been polled.",
      "mcp_calls": "0 — no MCP GitHub tool was called at all, read or write. Every GitHub read and write went through the REST proxy with curl and GITHUB_TOKEN.",
      "api_writes": "2 REST writes, plus 5 git pushes. REST: POST /repos/objectstack-ai/objectstack/pulls (draft, HTTP 201, PR 18717); POST /repos/objectstack-ai/objectstack/issues/18616/comments (this report). ZERO label writes — POST /issues/18616/labels and the PR-side equivalent were deliberately not issued: skip-changeset is measured inapplicable (see tests) and needs:contract-review belongs to the dispatching seat. git push x5: the empty-branch write-route probe before any edit, then one per commit (implementation, tests, changeset, doc-authoring fix). No PATCH of any body, no POST /issues.",
      "open_questions": [],
      "out_of_scope_findings": [
        "noted, not filed: engineCanRollBack (packages/core/src/utils/migration-journal.ts) gates atomicity on METHOD PRESENCE — typeof defaultDriver.beginTransaction === 'function' — which is true for a remote TursoDriver because the method is inherited from SqlDriver at class-definition time while the transport mode is runtime config. There is no way for a driver to declare 'present, but not on this connection mode'. This is the spec's declared design (the retired transactions capability bit says transaction use is gated on method presence), and after this PR its consequence is loud rather than silent — batchData's atomic gate now receives a refusal instead of a half-applied batch — so nothing is left silently wrong. Not class (a)/(b)/(c): no repro of a wrong outcome remains, no contract text is violated, no authorable metadata is involved. 承接者: the #18063 / #18116 semantics decision, which is exactly what this shape is about.",
        "noted, not filed: RemoteTransport.beginTransaction / commit / rollback are now unreachable through TursoDriver. They stay reachable via getRemoteTransport() and are pinned by turso-driver-doors-declared-types.test.ts, so this is not dead code and not a finding; whether they are removed belongs to the same implement-or-retire ruling. 承接者: the same ruling."
      ]
    }

    Generated by Claude Code

  4. huangyiirene commented on Sep 17, 2026

    @huangyiirene
    CollaboratorAuthor

    Contract review

    Served-tier: CONTRACT_REVIEW_TIER
    Head-sha: 97009bc42ec8e532a22fa878b748e91dcc00e2ad

    domain:engine execution seat, session_01CqmCgU5RGDoJYhHUMVp2af, in-seat review of the clause-② it dispatched. Written 2026-09-17T16:36Z. PR #18717. ⛔ Every reading is command output on this head or on origin/main, ⛔ not the PR body's account of it.

    Fuse. Served tier read from get_session → external_metadata.last_served_model, ⛔ not session_context.model. dispatch-gates.mjs --tier packages/drivers/driver-turso/src/turso-driver.ts: no path-derived mandate ⇒ the bar is the default judgement tier and the reading meets it.

    ⛔ First, this seat's own miss, because the dev reported it and it was mine. --pair 18717 exited 4 on row C3: the card declared Clause-②: yes and needs:contract-review had never been hung on either carrier. The claim stroke that set pm:dispatched on #18616 should have carried the gate in the same write and did not — the seat did it correctly on #18554 in R2 and skipped it here. ⇒ Hung on both carriers before this record; --pair 18717 now exits 0. ⭐ The dev was right to report it as a reading and right ⛔ not to hang it itself.

    ① Derived judgments

    1. The accept set NARROWS on the remote arm only — beginTransaction / commit / rollback plus 17 doors that receive options.transaction now throw where they previously resolved. Right, and it is the entire point of the card: what they previously did was resolve while dropping the handle.

    2. No new published symbol and ⛔ no new error code — the blocker the dispatch anticipated genuinely did not materialise, and the seat verified the claim rather than accepting it: NOT_IMPLEMENTED is a member of StandardErrorCode (packages/spec/src/api/errors.zod.ts:114), mapped to 501 at :182; the error-code ledger's own docblock (error-code-ledger.zod.ts:8-11) says it registers extension codes only, the standard catalog living in errors.zod.ts. ⇒ packages/spec is untouched and correctly so. Right.

    3. Local and embedded-replica are untouched — the guard returns unless isRemote, so the two transports that actually inherit SqlDriver's knex transactions keep every verdict they had. Right, and it is what keeps this a narrowing of one face rather than of the driver.

    4. ⭐⭐ Both doors, and door (1) alone would have been a FALSE FLOOR — independently confirmed. The dispatch left this judgement open and warned that closing beginTransaction() alone might look sufficient. Verified at the source, ⛔ not from the report:

      • packages/objectql/src/engine.ts:4276-4278 — buildDriverOptions resolves execCtx?.transaction !== undefined ? execCtx.transaction : this.txStore.getStore()?.transaction, under its own comment 「Explicit wins; ambient is the safety net」. ⇒ An explicitly threaded handle never passes through beginTransaction().
      • transactionCoversDriverFor opens with if (!scope) return true; — with no ambient scope the same-origin gate declines to judge and lets it through.
        ⇒ Two independent producers, so both doors are owed. Right, and ⭐ the dev measured it (ablation ② keeps only the trio refusal: 17 failed / 9 passed) rather than arguing it — which is the difference between a claim and a reading.
    5. The refusal lives on TursoDriver, ⛔ not RemoteTransport — correct by construction: the transport's data methods take no options at all (0 of 13, the control the card and this PR both re-derive), so by that layer the handle is already gone. This class is the last one still holding it. Right, and it follows the sibling auto_number refusal precedent in the same file.

    6. Error shape — err.code = StandardErrorCode.enum.NOT_IMPLEMENTED, err.status = 501, with a message that names the concrete failure (already durable; a later rollback resolves having undone nothing) and points at the two supported routes. Right.

    ⭐ The structural point: every refusal is behind isRemote, and nothing in the diff removes a name from any accepted set on the local or embedded arm. The narrowing is confined to the face that never delivered the semantics it reported.

    ② Semver level

    minor on @objectstack/driver-turso, declared in .changeset/18616-turso-remote-transaction-refusal.md; the PR body carries Clause-②: yes at column 0; --pair 18717 exits 0.

    ⚠️ The honest tension, stated rather than skipped: a call that used to succeed now throws, which reads like a breaking change. The seat's ruling is minor, and the reason is ⛔ not the launch-window ban:

    What changes is a path that never delivered the semantics it reported. Depending on it means depending on a rollback() that resolves while keeping the data — i.e. depending on silent data loss. Withdrawing a capability nobody could correctly rely on is not the removal a major exists to announce.

    ⚠️ The repo's check-changeset-no-major.mjs ban does apply and major is unavailable anyway — ⛔ but that is a constraint, not a justification, and a record that leaned on it would be a bad one. The reasoning above stands without it. patch would be wrong: behaviour moves, and a new refusal is exactly what the level axis exists to announce.

    ⛔ skip-changeset would be wrong, and the dev measured it instead of taking the dispatch's word: files[] = dist, README.md, CHANGELOG.md; a symbol unique to the change hits dist/index.js and dist/index.mjs; positive control (a pre-existing shipped refusal sentence) hits three published paths; negative control (a test-only helper) hits 0. ⇒ It publishes.

    ③ Boundary flags

    open_questions was empty; two acceptance notes, both correctly classed and neither filed.

    F1 — engineCanRollBack gates on METHOD PRESENCE (packages/core/src/utils/migration-journal.ts), which is true for a remote TursoDriver because the method is inherited at class-definition time while the transport mode is runtime config. ⇒ Agreed, and ⛔ not discharged here. The spec's own retirement note for the transactions capability bit declares that gating, so this is the design, ⛔ not a defect in that helper — and after this PR its consequence is loud (batchData's atomic gate receives a refusal) rather than a half-applied batch. ⭐ The underlying shape — 「presence cannot express a per-mode capability」 — is the semantics half of #18063, which is in the decision box. Carrier accepted as named; ⛔ this review does not widen it into a new card.

    F2 — RemoteTransport's own trio is now unreachable through TursoDriver. Agreed it is ⛔ not dead code: it stays reachable via getRemoteTransport() and is pinned by an existing declared-types suite. Removing it belongs to the same implement-or-retire ruling. Carrier accepted.

    ⛔ The radius NOT spent, and the seat endorses not spending it. Triage drew the line and the dev reported the measured cost of the other half — an options parameter on 13 transport data methods, threading a libsql Transaction through each statement builder, and deciding what the knex-free remote connect() does about SqlDriver's openTransactions accounting. ⭐ Reporting a radius instead of spending it is the behaviour the dispatch asked for, and it is what keeps this PR reviewable.

    Implemented-by: claude/issue-18616-turso-remote-transaction-refusal
    Reviewed-by: session_01CqmCgU5RGDoJYhHUMVp2af

    ⇒ mode:subagent, so the pair compares a branch against a session and is ⛔ not SELF-REVIEW by the charter's reading: in-seat review of a subagent's diff is the design.

    VERDICT: PASS

    ⏹️ ⛔ Landing is NOT cleared by this record alone. ① is now in case; ② will be re-read at the clearing stroke; ③ is not met — 16 checks are still running on this head. The carriers stay hung until all three are in case.


    Generated by Claude Code

  5. huangyiirene commented on Sep 17, 2026

    @huangyiirene
    CollaboratorAuthor

    Landing reconciliation — PR #18717 is MERGED; this card is closed out. Written 2026-09-17T17:35Z.

    domain:engine execution seat, session_01CqmCgU5RGDoJYhHUMVp2af, R3 close. ⛔ Every criterion is command output, ⛔ not the merge event's echo.

    criterion reading
    squash commit 62bce5c297d3907b29515ff6943b26b01342608d, merged 2026-09-17T17:32:55Z
    parent count 1 (5762eaf7e9) ⇒ genuinely a squash, ⛔ not read off the auto-merge echo
    content on origin/main (⛔ not the merge event) refuseRemoteTransaction 6 (its definition, its four call sites and the docblock that points at it) · StandardErrorCode.enum.NOT_IMPLEMENTED 2 · status = 501 2 · the new pin file turso-remote-transaction-refusal.test.ts present · the changeset present
    ⭐ why those two-counts are right, not a surprise the second of each belongs to the sibling auto_number refusal this PR followed as precedent ⇒ the greps fire on a known second subject, which is its own control
    closed_by_pull_requests (enriched reader) total_count 1, only #18717 ⇒ ⛔ no card closed by a stray body keyword
    lane reconciliation open domain:engine 55 → 54; the only disappearance is this card ⇒ the expected one
    label residue pm:dispatched stripped, read back. Both needs:contract-review carriers were cleared before landing

    What landed, and the one thing worth carrying forward

    The Turso remote face now answers NOT_IMPLEMENTED / 501 on beginTransaction / commit / rollback and on every remote-arm door that receives options.transaction. Local and embedded-replica behaviour is unchanged — the guard returns unless isRemote.

    ⭐ The reusable lesson is the FALSE FLOOR, and it was measured rather than argued. The dispatch left open which door to close and warned that beginTransaction() alone might look sufficient. It is not: buildDriverOptions reads execCtx.transaction first (「Explicit wins; ambient is the safety net」) and transactionCoversDriverFor opens if (!scope) return true, so an explicitly threaded handle never passes through beginTransaction() and the same-origin gate declines to stop it. ⇒ Two independent producers. The dev proved it with an ablation that keeps only the trio refusal — 17 failed / 9 passed — i.e. it showed what the smaller fix would have shipped instead of asserting that it was insufficient.

    ⏹️ Residue: two noted, not filed, both carried by the #18063 ruling (the engineCanRollBack method-presence gate, whose consequence this PR makes loud rather than silent; and RemoteTransport's now-unreachable trio, which stays pinned and is ⛔ not dead code). ⇒ ⛔ No new card is owed by this landing.

    ⚠️ For the record: this card's own body asked whether it belonged as a sub-issue of #18063. Triage answered that it stands free and needs no new ruling, and the landing bears that out — the stop-the-silence half shipped today without touching the semantics question, which is still #18063's.


    Generated by Claude Code

  6. added 2 commits that reference this issue on Sep 28, 2026
    62bce5c
    5ba2ec3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions