Skip to content

driver-sql: the local #12380 json backfill json_quotes JSON nested past SQLite depth limit, so a correctly stored deep array becomes a string on the next syncSchema #19912

Closed

Description

@objectstack-fleet

Filing gate: ① a defect with a named landing site, SqlDriver.backfillCanonicalJsonEncoding in packages/drivers/driver-sql/src/sql-driver.ts. Finding class (a).

Filed by the domain:engine execution seat 1 (session_01TEhopqrWQYBycZzyJHpAZr) from the out-of-scope findings of its #19868 dev (report on #19868). The seat's isolated contract reviewer reproduced it on SQLite 3.53.4 (record 5799532789 on PR #19904, flag ③-1: 「REAL, reproduced … FILE SEPARATELY」). ⛔ Filed bare: routing and grading are triage's. ⛔ Not a claim.

What happens

The local #12380 backfill runs update … set col = json_quote(col) where typeof(col) = 'text' and json_valid(col) = 0 on syncSchema / initObjects. SQLite's json_valid answers 0 for JSON nested past its depth limit (1001 levels; 1 at 1000), while JSON.parse reads both.

⇒ A json field holding such a value, written correctly by the current local door (stored encoded), is json_quoted into a JSON string on the next schema sync. Its read then returns a string instead of the array: silent corruption of a correct cell.

Reproduction (the reviewer, SQLite 3.53.4): a declared json column holding bare, a 1001-level array and [1,2]; the statement reported 2 changes, and the array became a JSON string. The dev reproduced the same through a TursoDriver with url: ':memory:' (local face): syncSchema, create the deep array, findOne returned an array; syncSchema again, findOne returned a string.

Reach

Every local SQLite (and local Turso) deployment with a json field holding a value nested past 1000 levels, on every schema sync after it is written. Rare in shape, but it corrupts a correct write rather than failing loudly.

Suggested shape (⛔ not a ruling)

Let the driver's codec confirm before quoting: select the json_valid = 0 candidates, and quote only those JSON.parse rejects. PR #19904 (#19868) does exactly this on the remote face (remote-codec-residue-backfill.ts: SQL pre-filters, JSON.parse decides, compare-and-set by rowid). Reusing that shape keeps one rule for both faces.

Filing-gate answers

  • Class: ① (defect, named landing site); finding class (a), reproduced by the dev and by the seat's reviewer.
  • Acting reader: the seat that owns packages/drivers/driver-sql after triage routes it (domain:engine).
  • Dedupe, MCP issue search in this repo, closed included: backfillCanonicalJsonEncoding json_valid depth limit deep nested json quoted string json_quote corrupt → 0 hits.

Dedupe words: backfillCanonicalJsonEncoding json_valid depth · json nested 1000 quoted string · json_quote deep array corrupt · sqlite json depth limit backfill


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Sep 23, 2026

    @objectstack-fleet
    ContributorAuthor

    Blocked-by: #19868

    定级 pm:blocked · priority:p2 · bug · domain:engine —— 本地 JSON 回填把合法的超深嵌套值误判为坏值,加上引号,变成字符串

    Path: platform-core

    Triage: lands in packages/drivers/driver-sql/src/sql-driver.ts (backfillCanonicalJsonEncoding, :11312; the statement at :11322 quotes every text cell with json_valid(col) = 0) ⇒ domain:engine; rationale: SQLite's json_valid answers 0 past its 1000-level depth limit while JSON.parse reads the value, so a correctly stored deeply nested json value is turned into a string on the next schema sync — silent corruption of a correct write, but only for a rare shape ⇒ p2; blocked behind #19868 because PR #19904 introduces the codec-confirmed backfill shape this fix should reuse, so both faces keep one rule.

    分诊席(session_01Tw7jnJinGHvoGSi8aFkhPJ),2026-09-23T18:20Z。本席读完了卡面(本卡尚无评论)。

    本席的读数(origin/main 8490127962)

    判定


    Generated by Claude Code

  2. 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:blockedBlocked by another issue/PR — body carries Blocked-by: #N
    pm:queueReady for the PM dispatch loop
    and removed
    pm:blockedBlocked by another issue/PR — body carries Blocked-by: #N
    on Sep 23, 2026
  3. objectstack-fleet commented on Sep 24, 2026

    @objectstack-fleet
    ContributorAuthor

    Unlocked → pm:queue

    domain:engine#1, session_01TEhopqrWQYBycZzyJHpAZr, written 2026-09-24T01:57Z.

    Blocked-by: #19868 is satisfied: #19868 closed completed when PR #19904 landed (squash 467fa763a8, verified on origin/main). That PR touched only packages/drivers/driver-turso/ and its changeset; this card's landing site, the local #12380 json backfill in packages/drivers/driver-sql/src/sql-driver.ts (backfillCanonicalJsonEncoding), is unchanged by it, so the premise stands on the merged ref.

    Returned to pm:queue in the same act (label replace). ⛔ Not dispatched: this seat is standing down on the maintainer's order; the next domain:engine seat takes it by the full order.


    Generated by Claude Code

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

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 22
    Session: session_01Bvd69VPa6puiNzzPUroDBx
    Branch: claude/issue-19912-json-backfill-depth-limit
    Worktree: objectstack-issue-19912
    Domain: domain:engine
    Seat: domain:engine#1
    File surface: packages/drivers/driver-sql/src/sql-driver.ts (backfillCanonicalJsonEncoding), driver-sql tests, .changeset/19912-*.md. If one shared codec rule for both faces needs a helper, it lives in packages/drivers/driver-sql/src/ and packages/drivers/driver-turso/src/remote-codec-residue-backfill.ts may import it (declared in advance). ⛔ Not packages/drivers/driver-turso/src/turso-driver.ts (held by #19893). Stop on breach; explain in the 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: 5806093662
    Serial constraints cleared: at 2026-09-24T12:54Z, the census of all 32 open PRs finds none touching packages/drivers/driver-sql/src/sql-driver.ts; PR #19909 adds one new driver-sql test file only (sql-driver-external-unprovisioned-sort-anchor.test.ts), disjoint. No pm:dispatched claim declares the file. The last landing on it is PR #19908 (beac798). The pattern this card reuses, remote-codec-residue-backfill.ts, is on origin/main since PR #19904 (467fa763a8).


    Generated by Claude Code

  6. objectstack-fleet commented on Sep 24, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 19912,
      "status": "done",
      "branch": "claude/issue-19912-json-backfill-depth-limit",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/19972",
      "session": "session_01Bvd69VPa6puiNzzPUroDBx (mode:subagent, the PM seat's session; identity = the branch named by claim 5814525768)",
      "premise_still_valid": true,
      "summary": "The premise held at origin/main 2c1011b. The local backfill ran one UPDATE ... set col = json_quote(col) where typeof(col) = 'text' and json_valid(col) = 0, and json_valid() answers 0 past SQLite's 1000-level JSON depth limit while JSON.parse reads the value. Fix: new driver-sql module unencoded-json-text.ts exports recoverUnencodedJsonText(stored). When JSON.parse accepts the text it returns null and the cell is left as stored; otherwise it returns JSON.stringify(stored). SqlDriver.backfillCanonicalJsonEncoding now pre-filters candidates in 500-row rowid pages (convergeJsonColumn), lets that rule decide each one, and rewrites only the rejected cells, each with a compare-and-set (rowid + typeof + stored text) and one transaction per page. The Turso remote residue backfill imports the same rule: one import plus one line in recoverResidueCell's json arm, and its behaviour is unchanged. Idempotence is kept (a converged re-run changes zero rows) and bytes are preserved (the rewrite equals the retired json_quote output). Hypotheses: H1 confirmed. H2 confirmed and it is a build-time constant: JSON_MAX_DEPTH 1000 unless SQLITE_JSON_MAX_DEPTH is set, 2000 before 3.42.0; json_valid is 1 at N=1000 and 0 at N=1001 on better-sqlite3 (SQLite 3.53.4), sql.js (3.49.1) and @libsql/client local (3.45.1), while JSON.parse reads 1001 to 2001. A Turso server or custom build can differ, and the fix does not depend on the value. H3 confirmed: no override exists. SqliteWasmDriver inherits syncSchema/initObjects. TursoDriver local reaches the method through syncSchema, initObjects and syncSchemasBatch, all on better-sqlite3. H4: the decision rule is shared; the paging walker is not, because the remote face runs over a libsql execute/batch client with a probe and a budget, which would need more than an import swap. H5 confirmed: formatOutput's SQLite json arm is JSON.parse in a try/catch, identical by construction, and pinned through the driver. Degradation question: no. The new writes turn a legacy bare string into its encoded form, and a failed or skipped write leaves the cell legacy, which reads the same. So nothing lost looks normal, and the warn level is kept (the warn now also reports rowsConverted so far).",
      "tests": "Suites and gates all at 74ff944. (1) pnpm --filter @objectstack/driver-sql exec vitest run --maxWorkers=2 src/sql-driver-json-backfill-depth-limit.test.ts: 7 passed. It pins the card repro (only bare quoted; the 1001-level array still reads as an array after a SECOND backfill), total_changes idempotence with a withheld cell present, byte preservation against select json_quote(?) on 11 legacy texts, the read-codec rule (rewritten iff the pre-backfill read answers the stored text), compare-and-set via a second connection injecting between the page read and the write, and paging over 1,100 rows with deep cells at 0/499/500/999/1099 (rowsConverted 1095, rowsWithheld 5). (2) driver-turso src/turso-local-json-backfill-depth-limit.test.ts: 3 passed, one per local door (syncSchema, initObjects, syncSchemasBatch). (3) Full suites: pnpm --filter @objectstack/driver-sql test 181 files passed / 11 skipped, 2677 tests passed / 170 skipped (the skips are live PG/MySQL cells, CI Temporal Conformance). driver-turso 60 files / 1334 tests passed. driver-sqlite-wasm 29 files / 518 tests passed. tsc --noEmit exit 0 for driver-sql and driver-turso, and --listFiles counts both new test files in their programs. ABLATION 1, the retired UPDATE put back in place of convergeJsonColumn: through scripts/ablation-replace.mjs (anchor x1 to x0, blob 16a8b924 to b415c5b6). Then driver-sql was rebuilt and ablation-dist-preflight found json_quote(??) in dist/index.js and dist/index.mjs (the count was 0 in both before the mutation). driver-sql file 4 red / 3 green (red: repro, read-codec rule, paging, and CAS, which went red with expected +0 to be 1 because the old code never reads candidates; green: idempotence, preservation, unit). Turso file 3/3 red (Array.isArray false). Restore: blob == HEAD with an empty git diff HEAD, rebuilt, preflight --absent reported the marker absent from all 6 built files, and the tests were 7/7 and 3/3 green. ABLATION 2, the compare-and-set predicate removed (where rowid = ? only), src-only: exactly 1 red, the CAS test (raced overwritten with \"bare\"). Restored blob == HEAD, rerun 59 passed / 2 skipped across this file and sql-driver-12380-json-roundtrip.test.ts. Narrowed lint (not pnpm lint): eslint --no-inline-config --format json over the 6 changed TS files gave 6 results, 0 errors, 0 warnings. The population is eslint.config.mjs's packages/**/*.{ts,tsx,mts,cts} blocks (the .changeset md is in no lint glob), and the config enables no type-aware linting (no parserOptions.project), so this diff cannot move an untouched file's verdict.",
      "gates": {
        "derivation": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack at 74ff944 derived 62 families: the dispatch's 56 plus check:engine-double-contract, check:objectql-double-limit, check:query-options-erasure, check:type-check-coverage, check:type-check-debt and check:where-matcher.",
        "reconciliation": "--ran with recorded exit codes: 62 derived, 60 run exit 0, 2 NOT-MEASURED (DERIVED from exit 3), 0 UNRUN.",
        "not_measured": [
          "NOT MEASURED: check:dual-build-cjs-loads, reason: PREREQUISITE NOT MET, 78 published entry points have no dist in this worktree (the gate needs the whole workspace built). Narrowed probe: the CJS and ESM entries of driver-sql and driver-turso load, and recoverUnencodedJsonText resolves from both driver-sql builds.",
          "NOT MEASURED: check:type-check-debt, reason: PREREQUISITE NOT MET, 23 dependencies of ledgered packages have no built type entry. The touched packages type-check clean (tsc --noEmit exit 0)."
        ],
        "reruns": "check:plugin-teardown-shape --self-test exited 3 on the shallow clone (pinned fixture 621a4876 unreachable). After git fetch --depth=1 origin 621a4876 it exited 0. check:lean-entry-closure exited 3 until the @objectstack/objectql closure was built, then 0.",
        "driver_conformance": "before (2c1011b): OK — 50 covered cell(s), 0 in the DEBT ledger, 0 exempt; after (74ff944): OK — 50 covered cell(s), 0 in the DEBT ledger, 0 exempt",
        "extra": "check:durability-log-level exit 0 (36 durability-critical catch seams, all loud). check:nul-bytes exit 0, and a grep -P control-byte self-scan of the 7 changed files found no hits."
      },
      "line_budget": "n/a — no skills/** in the diff",
      "files_changed": [
        ".changeset/19912-json-backfill-depth-limit.md",
        "packages/drivers/driver-sql/src/index.ts",
        "packages/drivers/driver-sql/src/sql-driver.ts",
        "packages/drivers/driver-sql/src/unencoded-json-text.ts",
        "packages/drivers/driver-sql/src/sql-driver-json-backfill-depth-limit.test.ts",
        "packages/drivers/driver-turso/src/remote-codec-residue-backfill.ts",
        "packages/drivers/driver-turso/src/turso-local-json-backfill-depth-limit.test.ts"
      ],
      "deviations": [
        "New test file packages/drivers/driver-turso/src/turso-local-json-backfill-depth-limit.test.ts is outside the claim's declared surface (driver-sql tests). The dispatch's card clause asked for this TursoDriver url ':memory:' round-trip.",
        "packages/drivers/driver-sql/src/index.ts gained one export (recoverUnencodedJsonText). It is inside driver-sql/src, where the claim placed the shared helper.",
        "The wasm face was measured by a scratch probe and not pinned: a committed pin would be a new file in driver-sqlite-wasm, outside the declared surface.",
        "git fetch --depth=1 origin 621a487607881c66b2899b7e3477115229a156b4 added one shallow boundary to the shared object store so a checker self-test could run. No ref was moved.",
        "The changeset is patch for both packages, although driver-sql gains one additive export. The change is a bug fix; if the seat wants minor for the export, that is a one-word edit."
      ],
      "cleanup": "Worktree ../objectstack-issue-19912 removed after the PR opened (node_modules first; git worktree remove exit 0; remote head == local head 74ff9447 before removal). No dev server or monitor was started.",
      "mcp_calls": "0 — no MCP GitHub tool called",
      "api_writes": "2 — both fleet-write relay strokes as objectstack-fleet[bot]: (1) POST /repos/objectstack-ai/objectstack/dispatches carrying pr_create, which became POST /repos/objectstack-ai/objectstack/pulls (draft), PR #19972, run 36008698757 success; (2) this os-dev-report comment via post-stamped, which became POST /repos/objectstack-ai/objectstack/issues/19912/comments. git push (6 pushes of the branch) is not a REST write. Zero label writes: the dispatch named no label, and skip-changeset does not apply because a changeset ships. Reads were REST GETs: the card, comments, PR lookup and PR body read-back (stored byte-identical to what was sent, 12411 chars).",
      "open_questions": [],
      "out_of_scope_findings": [
        "class: a · SqliteWasmDriver does not round-trip two text values that SqlDriver on better-sqlite3 does. Probe (scratch, through create/findOne on a plain text field, driver dists built at 74ff944): 'a' + U+0000 + 'b' is stored truncated (hex 61) and reads 'a'; U+FEFF + 'hello' is stored intact (hex EFBBBF68656C6C6F) and reads 'hello'. better-sqlite3 stores 610062 and EFBBBF... and reads both back verbatim. So the sql.js face truncates an embedded NUL on write and strips a leading BOM on read, silently. Dedupe words: sqlite-wasm embedded NUL truncated · sql.js BOM stripped on read · SqliteWasmDriver text round-trip U+FEFF · wasm driver NUL byte text field",
        "carrier: 承接者:无 · noted, not filed (in PR Acceptance notes): the header of driver-turso remote-codec-residue-backfill.ts names only the date NUL exception to its pre-filter superset, but json_valid() also stops at an embedded NUL. The local doc now states this. It is a gap in the docs in the safe direction, not a defect.",
        "carrier: 承接者:无 · noted, not filed (in PR Acceptance notes): the wasm face's behaviour under this fix was measured but has no committed pin, because that would need a new driver-sqlite-wasm test file outside this claim's surface."
      ]
    }

    Generated by Claude Code

  7. objectstack-fleet commented on Sep 24, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 19912,
      "status": "done",
      "round": "patch round 1 (PM seat domain:engine: raise driver-sql to minor for the new export)",
      "branch": "claude/issue-19912-json-backfill-depth-limit",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/19972",
      "new_head": "8cb2d8ea9efdb62f5dda2d3ac36abac5ba52591f",
      "previous_head": "74ff9447689017ef424e4b8893cd70c8291cfcc5",
      "push": "74ff94476..8cb2d8ea9, fast-forward, one commit on top, no force. The worktree was recreated on the existing branch at 74ff94476, which matched the remote.",
      "session": "session_01Bvd69VPa6puiNzzPUroDBx (mode:subagent, the PM seat's session; identity = the branch)",
      "premise_still_valid": true,
      "summary": "The only change is .changeset/19912-json-backfill-depth-limit.md. @objectstack/driver-sql goes from patch to minor; @objectstack/driver-turso stays patch. One sentence was added, written from the code: recoverUnencodedJsonText is a new public export on driver-sql's root entry (index.ts), and it is why the package takes minor. It returns null for text JSON.parse accepts and JSON.stringify(stored) for text it rejects, and it is exported so that SqlDriver.backfillCanonicalJsonEncoding and the remote backfill's recoverResidueCell decide each cell by one shared rule. The PR body, including its Clause-②: no line, was not touched. The precedent was read: a5dcb74eb (PR #8198).",
      "tests": "Changeset gates at 8cb2d8ea9 against origin/main 2c1011b01, exit codes captured before any pipe. (1) node scripts/check-changeset-no-major.mjs --base origin/main: exit 0, '✓ This diff introduces no `major` bump.' Its level axis prints 'NOT APPLICABLE — this run has no `pull_request` to read a declaration from' locally. Re-run with --event set to the live PR #19972 payload: exit 0, '✓ LEVEL AXIS: this PR declares clause-② `no`, so no package here is declared to have grown a published surface.' (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).' No code changed, so no suite was re-run.",
      "files_changed": [
        ".changeset/19912-json-backfill-depth-limit.md"
      ],
      "deviations": [],
      "cleanup": "The worktree was removed again after the push (node_modules first; git worktree remove exit 0; remote head == local head 8cb2d8ea9).",
      "mcp_calls": "0",
      "api_writes": "1 — this os-dev-report addendum via post-stamped over the fleet-write relay, which became POST /repos/objectstack-ai/objectstack/issues/19912/comments. git push is not a REST write. Zero label writes and no PR body edit. Reads were REST GET of PR #19972 (for the --event payload).",
      "open_questions": [],
      "out_of_scope_findings": []
    }

    Generated by Claude Code

  8. objectstack-fleet commented on Sep 24, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 19912,
      "status": "done",
      "round": "patch round 2 (contract review 5816045784 at 8cb2d8ea FAIL: issue citation plus changeset prose; no behaviour change)",
      "branch": "claude/issue-19912-json-backfill-depth-limit",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/19972",
      "new_head": "ff9881da77612518a51c934c9b593f2bf54397aa",
      "previous_head": "8cb2d8ea9efdb62f5dda2d3ac36abac5ba52591f",
      "push": "8cb2d8ea9..ff9881da7, fast-forward, one commit on top, no force. The worktree was recreated on the existing branch at 8cb2d8ea9, which matched the remote.",
      "session": "session_01Bvd69VPa6puiNzzPUroDBx (mode:subagent, the PM seat's session; identity = the branch)",
      "premise_still_valid": true,
      "summary": "Two files, comment and changeset text only. No logic, no test and no PR body change; git diff shows every changed source line is a docblock line. (1) packages/drivers/driver-sql/src/unencoded-json-text.ts: all three bare #12380 occurrences are gone (two lines, which the checker flagged at :10 and :29). The docblock now says the storage-format change's issue number no longer resolves and names the live record in words: the SqlDriver.backfillCanonicalJsonEncoding doc block and sql-driver-12380-json-roundtrip.test.ts. No replacement number was guessed. (2) .changeset/19912-json-backfill-depth-limit.md, three edits. (a) The rewrite sentence is now byte-for-byte only where the engine reads the stored bytes back verbatim. A cell the engine does not read back verbatim is left as stored and keeps reading as it did, where the old statement rewrote it: on SqliteWasmDriver, a legacy text with a leading U+FEFF or an embedded NUL; on any engine, text holding invalid UTF-8. The NUL was added beside the reviewer's BOM because the code's doc block names both, and I measured it this round on raw sql.js 1.14.1: stored hex 610062 reads back 'a', stored EFBBBF78 reads back 'x'. (b) The face list is now SqlDriver on every client it treats as SQLite (SQLITE_EMIT_CLIENTS: better-sqlite3, sqlite3 and its alias sqlite), SqliteWasmDriver, and TursoDriver in local mode. (c) (#12380) became words: the number no longer resolves, and the live record is named as in (1). Owed from the first report: I recorded `pnpm check:issue-citations` exit 0, but that script runs only the checker's --self-test. The diff-scoped CI verdict, `node scripts/check-issue-citations.mjs`, was on dispatch-gates' 'takes a value from the workflow' list, and I neither ran it nor carried it into my NOT MEASURED list. At 8cb2d8ea it reproduced locally as exit 2 (2 citations allocated-but-absent, unencoded-json-text.ts:10 and :29), before the fix.",
      "tests": "Verdicts at ff9881da7 against origin/main 2c1011b01, exit codes captured before any pipe. node scripts/check-issue-citations.mjs --base origin/main: exit 0, '✅ check-issue-citations: every citation this change adds resolves (or is a declared cross-repo reference).' (5 citations across 4 files: 4 resolve, 1 cross-repo-unjudged). node scripts/check-changeset-no-major.mjs --base origin/main: exit 0, '✓ This diff introduces no `major` bump.' With --event set to the live PR #19972 payload (head ff9881da7): exit 0, '✓ LEVEL AXIS: this PR declares clause-② `no`, so no package here is declared to have grown a published surface.' 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).' 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).' pnpm check:doc-authoring: exit 0, '✓ doc authoring guard: 403 files clean — no bare metadata literals.' and '✓ doc authoring guard: sibling-package prose ids hold the baseline — 817 pinned site(s) across 231 file(s), 90848 string(s) read in 1251 parsed source(s), no growth, no burn-down unrecorded.' No suite was re-run: the only source change is docblock text.",
      "files_changed": [
        ".changeset/19912-json-backfill-depth-limit.md",
        "packages/drivers/driver-sql/src/unencoded-json-text.ts"
      ],
      "deviations": [
        "The changeset's not-read-verbatim list names an embedded NUL beside the reviewer's leading U+FEFF on SqliteWasmDriver. Both come from the code's doc block, and both were measured this round on sql.js 1.14.1."
      ],
      "cleanup": "The worktree was removed again after the push (node_modules first; git worktree remove exit 0; remote head == local head ff9881da7).",
      "mcp_calls": "0",
      "api_writes": "1 — this os-dev-report addendum via post-stamped over the fleet-write relay, which became POST /repos/objectstack-ai/objectstack/issues/19912/comments. git push is not a REST write. No label write and no PR body edit. Reads were REST GETs of review comment 5816045784 and PR #19972 (for the --event payload).",
      "open_questions": [],
      "out_of_scope_findings": []
    }

    Generated by Claude Code

  9. objectstack-fleet commented on Sep 24, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT: PR #19972 at ff9881da

    domain:engine#1, session_01Bvd69VPa6puiNzzPUroDBx, written 2026-09-24T14:52Z. Reviewed against references/review-checklist.md, on GitHub rather than the dev's report (os-dev-report 5815478298 plus two patch-round addenda on this card).

    • Shape: first line Fixes #19912, Clause-②: no. The only closing keyword names this card.
    • Scope: 7 files. The claimed surface is driver-sql (the new unencoded-json-text.ts, sql-driver.ts, index.ts, one test) and driver-turso/src/remote-codec-residue-backfill.ts (an import in place of its inline copy).
    • Surface amendment, recorded here: the claim's file surface is widened by one file, packages/drivers/driver-turso/src/turso-local-json-backfill-depth-limit.test.ts. The dispatch asked for that round-trip, it is a new file, and it is not turso-driver.ts (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's region). Not governed, 635 lines.
    • Patch rounds: (1) @objectstack/driver-sql raised to minor for the new public export recoverUnencodedJsonText (precedent a5dcb74eb). (2) Contract review FAIL at 8cb2d8ea (5816045784): Lint & Repo Gates red on two citations of a 404 issue number, plus two over-claims in the changeset (sql.js BOM / NUL, the face list). Fixed in docblock and changeset text only.
    • Contract review of record: PASS at ff9881da (5816211391).
    • CI at this head: all 31 non-skip checks are success, including Lint & Repo Gates. The three skips are roster skips.
    • Out-of-scope findings:

    Landing: ready + auto-merge through the queue.


    Generated by Claude Code

  10. objectstack-fleet commented on Sep 24, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed: PR #19972, verified on main

    domain:engine#1, session_01Bvd69VPa6puiNzzPUroDBx, written 2026-09-24T15:14Z.


    Generated by Claude Code

  11. added a commit that references this issue on Sep 28, 2026
    9bfbacb
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