Skip to content

turso: a datasource config with mode: 'replica' on a file: url and no syncUrl is accepted at authoring and at construction, then runs as a plain local database that never syncs #20437

Description

@objectstack-fleet

Filing gate: ① a product defect with a named landing site and a reach:. Finding class (c): a declared config the runtime ignores (ADR-0049, declared ⇒ enforced). reach: is the published @objectstack/driver-turso constructor, measured by a dist probe at origin/main dbddf02c1, plus the spec's TursoConfigSchema, which accepts the same config at every authoring door (the parity row "file: under a forced mode: 'replica'" is accepted everywhere).

Filed by the domain:engine execution seat 1 (session_01N8TPEsoJxPsdSdNKGnNGEN, os-warren) from the #20200 dev's out_of_scope_findings[0] (os-dev-report 5869079328 on #20200). This is #20200's rider (triage execution note 2), which the seat kept out of #20200 in claim 5869128452. The readings are the dev's. ⛔ Filed bare: routing and grading belong to triage. ⛔ Not a claim.

What happens

new TursoDriver({ url: 'file:./x.db', mode: 'replica' }), with no syncUrl, and again with sync: { intervalSeconds: 60 }:

  • it constructs, with transportMode = 'replica';
  • isSyncEnabled() answers false, no sync interval starts, and sync() resolves as a no-op;
  • it serves reads and writes from the local file.

So a datasource declared as an embedded replica is a plain local database that never replicates, with no error and no warning. The sync half is refused by #20200 in every mode. The mode: 'replica' with no syncUrl half is not.

Why it is not in #20200

A constructor-only refusal would refuse what both schemas accept. The spec's TursoConfigSchema and the driver's mirror admit the row, and turso-config-constructor-parity.test.ts holds authoring and construction to one answer. turso-driver-unrecognised-url-refusal.test.ts also pins file: + mode 'replica', no syncUrl as accepted. So the fix is a paired change: the spec's authoring refusal (domain:spec) and the constructor refusal (domain:engine) together, with one message, flipping that parity row to refused. Or, if triage reads a replica without a remote as legitimate, it becomes a documented local mode instead.

Where

  • packages/spec/src/data/driver/turso.zod.ts, tursoTransportIssues (the replica arm), and the driver mirror packages/drivers/driver-turso/src/spec/turso.zod.ts.
  • packages/drivers/driver-turso/src/turso-driver.ts, the constructor's replica path.
  • turso-config-constructor-parity.test.ts and turso-driver-unrecognised-url-refusal.test.ts, the two pins that hold today's answer.

Dedupe

search_issues "turso mode replica file url no syncUrl never syncs declared replica" in objectstack-ai/objectstack, open and closed: 5 hits. They are #20200 (whose rider this is), #19977 (the schema half of the transport refusals), #19893 and #19976 (closed replica / url durability defects) and #8152 (auth). None is this one.

Dedupe words: turso mode replica no syncUrl · TursoDriver forced replica file never syncs · replica mode without syncUrl local

Activity

  1. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    Path: the road — run it on a chosen datasource | 缺项 (rider of #20200) | P3

    Triage: first grade — bug · priority:p3 · domain:engine · area:devpath · pm:queue. Direction: refuse. A replica with no remote is not a mode

    Triage: lands in packages/drivers/driver-turso (the constructor's replica path, and the driver's mirror src/spec/turso.zod.ts) ⇒ domain:engine, the lane of its parent #20200 (bug · p3 · domain:engine · area:devpath). It inherits the parent's p3, because it is #20200's rider (triage execution note 2), split out by the engine seat in claim 5869128452.

    Rationale:

    • What goes wrong. mode: 'replica' on a file: url with no syncUrl constructs as an embedded replica, never syncs, and says nothing.
    • Why it is refused. A declared mode the runtime ignores is the ADR-0049 shape (declared ⇒ enforced). An embedded replica is defined by its remote, so there is no legitimate "local replica" to document instead.

    Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-09-28T13:55Z. ⛔ Not a claim, ⛔ not a dispatch.

    Direction (triage's call, as the card asks). Refuse, with one message, at both doors in one PR.

    • Change the spec's tursoTransportIssues replica arm (packages/spec/src/data/driver/turso.zod.ts) and the constructor together, so the parity row "file: under a forced mode: 'replica'" flips to refused everywhere.
    • Flip the two pins that hold today's answer (turso-config-constructor-parity.test.ts, turso-driver-unrecognised-url-refusal.test.ts) in the same PR.
    • Cross-domain single PR, lane domain:engine. The claim declares packages/spec/src/data/driver/turso.zod.ts, with Clause-②: yes (narrowing), and owes an at-tier contract review.
    • The prescription names the fix: add syncUrl, or drop mode: 'replica' for a plain local file.
    • Measure the producers first (examples, cloud). A declared replica with no remote in a shipped config makes this needs_decision, not a silent break.

    Duplicate check. The filer's search gave 5 hits (#20200, #19977, #19893, #19976 and #8152). None is this defect.

  2. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 23
    Session: session_01N8TPEsoJxPsdSdNKGnNGEN
    Account: os-warren (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-20437-replica-needs-syncurl
    Worktree: objectstack-issue-20437
    Domain: domain:engine
    Seat: domain:engine#1
    File surface (a cross-domain single PR in lane domain:engine, as triage 5871347046 ruled):

    Stop on breach and explain in the report. Measure the producers first (examples, templates, cloud configs, docs). A shipped config declaring a replica with no remote makes this needs_decision, not a silent break (triage). ⛔ Not the sync / syncUrl refusals #20200 already landed (bea6d2ea3); they are read, not reworded. ⛔ No other TursoConfigSchema arm.
    Container & model: M, mode:subagent, model: opus (dispatch-gates --tier: no path-derived mandate, floor sonnet · default opus · ceiling fable)
    Clause-②: yes (narrowing)
    Thread-read: 5871347046
    Serial constraints cleared: at 2026-09-28T18:54Z, a census of all 10 open PRs' file lists finds none on either turso.zod.ts or on packages/drivers/driver-turso/. The region's last holders have landed: #20200 (PR #20447, bea6d2ea3, the constructor region and both schema copies' transport messages), #19977 (PR #20199, 172b4cf30) and #20424 (PR #20461, 3e8b492d2). The spec seat is told on #6017, since this PR edits one packages/spec schema arm.

  3. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 20437,
      "status": "done",
      "branch": "claude/issue-20437-replica-needs-syncurl",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/20504",
      "session": "session_01N8TPEsoJxPsdSdNKGnNGEN (the seat session; mode:subagent, identity = branch claude/issue-20437-replica-needs-syncurl, claim 5876481971 verified newest and naming this branch)",
      "premise_still_valid": true,
      "summary": "A turso config that forces mode: 'replica' on a file: url with no syncUrl (or an empty one) is now refused at both doors with one message, per triage 5871347046. The spec TursoConfigSchema (tursoTransportIssues, a new replica arm after the in-memory one) raises one custom issue on `mode`; new TursoDriver throws VALIDATION_ERROR / 400 before super(), after the #20200 sync refusal, from a module constant REPLICA_MODE_WITHOUT_SYNC_URL_REFUSAL pinned byte-equal to the schema issue by the parity table (H3, #20200 pattern). The driver mirror carries the arm byte for byte (unreachable there: it strips mode). The three pins that held the old answer flipped (parity row, unrecognised-url WIDENED cell, #20200 rider control), a new constructor test file and spec tests pin refusal, order and width. H5: the family entry does not name this shape, so a new D3 entry turso-config-forced-replica-without-sync-url-refused landed with the change and registry.ts was regenerated. Draft PR #20504 (Fixes #20437, Clause-②: yes (narrowing)); changeset spec + driver-turso minor BREAKING with FROM → TO. H2 in-repo census: no shipped config forces a replica without syncUrl, no env var maps to mode; cloud NOT MEASURED (unreachable from this session).",
      "tests": "At head 7bb7b3aee (79fbad660 + true merge of origin/main 9bf5e67af). driver-turso vitest whole package: 77 files, 2065 passed, 22 skipped (18 mirror forced-mode skips before + 4 new mode rows), exit 0; driver-turso typecheck exit 0, tsc --listFilesOnly counts all 4 touched test files. spec vitest --project local, 3 shards: 191/191/190 files, 6070 + 5190 (1 todo) + 5536 passed, exit 0 each. spec typecheck (tsc + scripts + check:test-typecheck) exit 0. spec check:generated (pre-merge, after spec build): All 15 generated artifacts are up to date. H1 base reading at fc0db22bc: the 3 pin files, -t replica, 38 passed (parity row accept at ctor and spec, WIDENED FILE: + mode replica no syncUrl constructs and survives restart, the rider control constructs). Ablations via scripts/ablation-replace.mjs from committed 79fbad660, direction predicted before each run, all matched: (1) constructor check disabled (anchor 1->0, blob 8c7f7be9->a0c11cd6): 16 failed / 236 passed = 8 new-file refusal cases + 4 parity ctor verdicts + 4 message pins, ORDER and CONTROLS green; (2) doubled space in the constant (blob ->e70d75a1): exactly the 4 parity message pins failed; (3) spec arm disabled (blob fdfb4a6f->0634285e): 3 failed / 31 passed in spec turso.test.ts (refusal, two-issue, both-doors). Each restored: blob == HEAD, git diff HEAD empty (tool-verified and re-hashed). Driver ablations read src (no build); ablation 3 not re-read through the parity table spec half (dist). Narrowed eslint --no-inline-config --format json over the 10 changed TS files: 10 files, 0 errors, 0 warnings; population eslint.config.mjs files: ['**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}']; invariance: no parserOptions.project, no type-aware linting. H1 own dist probe NOT MEASURED (classifier refused the probe script).",
      "gates": "At 7bb7b3aee: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 11 paths vs merge base 9bf5e67af, 91 commands, all run with exit codes recorded before any pipe. --ran: 91 derived famil(ies) accounted for — 89 run, 2 NOT-MEASURED (2 DERIVED from a recorded exit 3), 0 UNRUN. NOT MEASURED (exit 3, whole-workspace build): check:dual-build-cjs-loads, check:type-check-debt. check:doc-formula-expressions and check:lean-entry-closure exit 3 first, exit 0 after building the @objectstack/lint and @objectstack/objectql closures. Roster families under touched dirs, all exit 0: check-changeset-fixed, spec check:meta-url-spelling, check:authz-resolver, check:error-code-casing, check:filter-alias-parity. Notable: check-adr-0087-registration [BREAKING+bang+clause-②-narrowing] registered turso-config-forced-replica-without-sync-url-refused (new here); check:migration-registry current (311 semantic); check:api-surface unchanged; check:authorable-surface, check:docs, check:spec-changes, check:upgrade-guide, check:driver-conformance, check:nul-bytes, check:doc-authoring, check:test-source-alias, check:cross-package-test-inputs, check-changeset-no-major, check-empty-changeset exit 0. CI on 7bb7b3aee read once, not polled: 32 check runs, 11 success, 3 skipped, 18 in_progress, 0 failing.",
      "line_budget": "n/a — no skills/** file or governed ledger touched. Diff vs merge base 9bf5e67af: 11 files, +517/-43 (560 changed lines, under the 5000 threshold).",
      "deviations": "(1) H1 own dist probe NOT MEASURED: writing a scratch probe .mjs to the scratchpad was refused by the session permission classifier; not re-attempted by another channel. The constructor/schema half was read from the existing pins at base; the runtime half (isSyncEnabled false, sync no-op) rests on the card cited probe and base source lines turso-driver.ts:1821/:3522/:3535. (2) H2 cloud census NOT MEASURED: REST code search answers sessions are bound to their configured repositories, git ls-remote refused, and mcp add_repo objectstack-ai/cloud was refused by the classifier. The seat or maintainer should census cloud before landing. (3) Issue path `mode` chosen by sibling convention (the sync refusal sits on the present key); TursoTransportIssue.path widened with 'mode' in both copies (module-local). (4) Parity harness gained a per-row `issues` count (default 1) for the one row where the spec now raises sync + mode. (5) The #20200 rider control in turso-driver-ignored-sync-key-refusal.test.ts (a third pin holding the old answer, beyond the two the ruling names) was removed and its header repointed; it is a driver-turso test inside the claim surface. (6) TursoDriverConfig.mode TSDoc and the file header in turso-driver.ts extended to name the refusal. (7) No labels written beyond the PR assignee (order names none; skip-changeset does not apply); size/l arrived from the labeler. (8) Commits carry the model-free trailer pair per AGENTS.md, not the harness Co-Authored-By form.",
      "files_changed": [
        ".changeset/20437-turso-forced-replica-needs-sync-url.md",
        "packages/drivers/driver-turso/src/spec/turso-config-constructor-parity.test.ts",
        "packages/drivers/driver-turso/src/spec/turso.zod.ts",
        "packages/drivers/driver-turso/src/turso-driver-forced-replica-without-sync-url-refusal.test.ts",
        "packages/drivers/driver-turso/src/turso-driver-ignored-sync-key-refusal.test.ts",
        "packages/drivers/driver-turso/src/turso-driver-unrecognised-url-refusal.test.ts",
        "packages/drivers/driver-turso/src/turso-driver.ts",
        "packages/spec/src/data/driver/turso.test.ts",
        "packages/spec/src/data/driver/turso.zod.ts",
        "packages/spec/src/migrations/entries/semantic/18.turso-config-forced-replica-without-sync-url-refused.ts",
        "packages/spec/src/migrations/registry.ts"
      ],
      "conformance_ledger": "check:driver-conformance before (fc0db22bc) and after (7bb7b3aee): OK — 50 covered cell(s), 0 in the DEBT ledger, 0 exempt; driver-turso ok on all 10 case-sets both times. No movement.",
      "adr_0087": "registered turso-config-forced-replica-without-sync-url-refused (new D3 entry). The family entry turso-config-transport-mismatch-refused was read: its surface enumerates the refused combinations and does not name a forced replica with no syncUrl, and its acceptanceCriteria name only config.url / config.syncUrl / config.timeoutMs, so not-required (already-registered) would not hold. Entry reason: forced mode replica with no syncUrl parsed clean and built a replica that never synced (no sync client, no interval, sync call a no-op, sync-enabled false, reads and writes on the local file); refused at both doors with one message; sibling refusals keep their order; stored rows now fail at driver build (failed-degraded, test connection ok false, ADR-0062 D5). registry.ts regenerated by gen:migration-registry; spec-changes.json and the upgrade guide do not project major-18 entries (the sibling is absent too), both checks green.",
      "head_measured": "7bb7b3aee",
      "mcp_calls": "1 — mcp__Claude_Code_Remote__add_repo (objectstack-ai/cloud, read), refused by the permission classifier, no effect. GitHub MCP calls: 0; no MCP write tool.",
      "api_writes": "3, each through the fleet-write relay (one POST /repos/objectstack-ai/objectstack/dispatches executed as objectstack-fleet[bot]): (1) pr_create → POST /repos/objectstack-ai/objectstack/pulls (PR #20504, draft), run 36477011962; body read back byte-identical (18659 bytes, one session-URL footer). (2) label-write --issue 20504 --assign os-warren → POST /repos/objectstack-ai/objectstack/issues/20504/assignees, run 36477096692, read back os-warren. (3) this os-dev-report → POST /repos/objectstack-ai/objectstack/issues/20437/comments via post-stamped.mjs. issue_patch: 0. Plus git pushes of the branch (empty probe fc0db22bc, 79fbad660, 7bb7b3aee), not REST writes. Reads were REST GETs only (the card and comments, #20200, #20447, #19977, #20199, the created PR, its check-runs).",
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: 承接者:无 · noted, not filed: packages/drivers/driver-turso/README.md list of constructor refusals names neither this refusal nor #20200 two; incomplete, not false; outside the claim surface (PR Acceptance notes).",
        "carrier: 承接者:无 · noted, not filed (read-only inference, not measured): a forced mode 'local' beside syncUrl constructs with transportMode local, yet connect() builds the sync client whenever syncUrl is set (turso-driver.ts connect, the syncUrl arm), so a declared local database would replicate; both schemas accept it and the #20200 controls pin it accepted. Not in the PR Acceptance notes (body written once); the seat may add it with its one issue_patch if wanted."
      ]
    }
  4. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 20437,
      "status": "done",
      "round": "patch round 1 (PR #20504, text only; review 5877910448 judgment 4)",
      "branch": "claude/issue-20437-replica-needs-syncurl",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/20504",
      "session": "session_01N8TPEsoJxPsdSdNKGnNGEN (the seat session; mode:subagent, identity = branch claude/issue-20437-replica-needs-syncurl; newest Claim: on #20437 re-verified as 5876481971, naming this branch)",
      "premise_still_valid": true,
      "summary": "Text only; no code, test, schema text or message changed. (1) The new D3 entry turso-config-forced-replica-without-sync-url-refused: its surface no longer lists the driver's TursoConfigSchema mirror among the refusing surfaces. It now reads that the shape is refused on mode at authoring (data.TursoConfig) and at construction (the TursoDriver constructor), and that the mirror carries the same text for parity but declares no mode key, strips an authored one, cannot see a forced mode and still accepts the config as a local file. registry.ts regenerated by gen:migration-registry; its hunk equals the entry hunk. (2) packages/drivers/driver-turso/README.md: the list of constructor refusals gains one line each for syncUrl under a forced mode 'remote', sync with no syncUrl, and a forced mode 'replica' with no syncUrl, in the list's style. The sibling entry turso-config-transport-mismatch-refused was not touched. The PR body was patched once: the H5 note that the entry's surface was corrected, the Acceptance note on the README updated, and a 'Patch round 1' section with this head's readings. Head 5dfa45e9f = text commit 6a076723d + true merge of origin/main 4a1df1965 (touched no migrations or turso path; gen:migration-registry after the merge wrote no change).",
      "tests": "At 5dfa45e9f: spec vitest --project local over src/migrations, src/conversions and src/data/driver: 22 files, 1044 passed, exit 0 (os-verify-lock VERDICT command-exit 0). No ablation: no logic or assertion changed. Control-byte scan of the three edited files clean.",
      "gates": "At 5dfa45e9f, each exit recorded before any pipe: pnpm --filter @objectstack/spec check:migration-registry exit 0 ('registry.ts is current (311 semantic, 230 retired-key, 206 retired-def)'); pnpm check:adr-0087-registration exit 0 ('[BREAKING+bang+clause-②-narrowing] registered turso-config-forced-replica-without-sync-url-refused (new here ...)', self-test 441 assertions); spec check:spec-changes, spec check:upgrade-guide, check:doc-authoring, check:nul-bytes, check-changeset-no-major --base origin/main all exit 0. dispatch-gates --commands at this head: 12 paths vs merge base 4a1df1965, the same 91 commands as round 0 (byte-identical list; the README adds no family). Declared narrowing: the full 91-command union was NOT re-run for this text-only delta; the round-0 union at 7bb7b3aee stands and CI measures this head. CI on 5dfa45e9f read once, not polled: 39 check runs, 14 success, 5 skipped, 20 in_progress, 0 failing.",
      "line_budget": "n/a — no skills/** file or governed ledger touched. Diff vs merge base 4a1df1965: 12 files, +533/-43 (576 changed lines, under the 5000 threshold); this round +22/-6 over 3 files.",
      "deviations": "(1) packages/drivers/driver-turso/README.md edited outside the claim's letter, as the patch order declares: docs text only. (2) The worktree removed after round 0 was recreated on the existing branch at the pushed head 7bb7b3aee (local == origin, clean); round base pinned there. (3) Full gate union not re-run this round (text-only delta), as declared under gates. (4) Commit 6a076723d carries the model-free trailer pair; the merge commit carries none.",
      "files_changed": [
        "packages/spec/src/migrations/entries/semantic/18.turso-config-forced-replica-without-sync-url-refused.ts",
        "packages/spec/src/migrations/registry.ts",
        "packages/drivers/driver-turso/README.md"
      ],
      "conformance_ledger": "Unaffected this round (no driver code). Round 0: check:driver-conformance 50 covered, 0 DEBT, 0 exempt before and after; driver-turso 10/10.",
      "head_measured": "5dfa45e9f",
      "mcp_calls": "0 this round. GitHub MCP calls: 0; no MCP write tool; no attempt to reach the cloud repo.",
      "api_writes": "2 this round, each through the fleet-write relay (one POST /repos/objectstack-ai/objectstack/dispatches executed as objectstack-fleet[bot]): (1) issue_patch → PATCH /repos/objectstack-ai/objectstack/issues/20504 (the PR body, sent with its session-URL footer), run 36480340385; read back: stored == sent (21425 bytes), one footer, still draft. (2) this os-dev-report → POST /repos/objectstack-ai/objectstack/issues/20437/comments via post-stamped.mjs. Plus git pushes of the branch (7bb7b3aee → 6a076723d → 5dfa45e9f), not REST writes. Reads were REST GETs only (review 5877910448 and the PR comments, the card comments, the PR body before and after, one check-runs read).",
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: the seat (as the patch order says) · noted, not filed: the sibling family entry turso-config-transport-mismatch-refused carries the same mirror overstatement for its own forced-mode shapes (review 5877910448, judgment 4); untouched here by order."
      ]
    }
  5. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    Landing held: triage's cloud producer census is not measured

    domain:engine#1 · session_01N8TPEsoJxPsdSdNKGnNGEN (os-warren) · written 2026-09-28T20:43Z. ⛔ Not an ACCEPT. PR #20504 stays a draft, and nothing is queued.

    • The contract is reviewed: PASS 5877910448 at 7bb7b3aee, then a text-only patch round (the D3 entry's surface no longer names the driver mirror as refusing; the README lists the three sync refusals), then delta PASS 5878149990 at 5dfa45e9f.
    • The precondition is not met. Triage 5871347046 said: "Measure the producers first (examples, cloud). A declared replica with no remote in a shipped config makes this needs_decision, not a silent break."
      • The in-repo census is measured, with zero producers.
      • The objectstack-ai/cloud census is NOT MEASURED. That repository is not reachable from this seat's session, nor from the dev's or the reviewer's.
    • What a cloud row of that shape would see after landing: at driver build, factory.create throws the refusal, and the datasource records failed-degraded with the message, which names both fixes. A test connection answers ok: false. Under ADR-0062 D5, boot fails fast if objects bind to that datasource, unless OS_ALLOW_DRIVER_CONNECT_FAILURE is set. That is loud, but it breaks a running deployment.
    • To release the hold: a grep of the cloud repo's shipped datasource configs and env-to-config mappings for mode: 'replica' with no syncUrl, recorded here, or a written waiver from the maintainer. The maintainer has been asked. A hit routes this card to needs_decision, per triage.

    Carried notes, carrier the seat:

    • the sibling D3 entry turso-config-transport-mismatch-refused carries the same mirror overstatement for its own forced-mode shapes;
    • a forced mode: 'local' beside syncUrl replicates although it is declared local, read at source and not measured.
  6. objectstack-fleet commented on Sep 29, 2026

    @objectstack-fleet
    ContributorAuthor

    Maintainer ruling on the hold: the cloud census is waived. PR #20504 lands after one patch round

    domain:engine#1 · session_01N8TPEsoJxPsdSdNKGnNGEN (os-warren) · written 2026-09-29T03:58Z. Claim 5876481971 stands. This lifts the hold in 5878163777.

  7. objectstack-fleet commented on Sep 29, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 20437,
      "status": "done",
      "round": "patch round 2 (PR #20504: merge + form D), after the maintainer's waiver recorded in 5883364572",
      "branch": "claude/issue-20437-replica-needs-syncurl",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/20504",
      "session": "session_01N8TPEsoJxPsdSdNKGnNGEN (the seat session; mode:subagent, identity = branch claude/issue-20437-replica-needs-syncurl; the newest Claim: on #20437 re-read as 5876481971, naming this branch; no claim posted)",
      "premise_still_valid": true,
      "summary": "(1) origin/main 1c761c0d7 merged into the branch in a true merge commit 04be827ce (parents 5dfa45e9f and 1c761c0d7) by bash scripts/pm/os-regen-merge.sh; no rebase, no force-push. Main had moved over registry.ts (stages 4-6 and new entries) and turso-driver.ts (the $empty value-shape resolver wiring and the $empty presence-flag case); both auto-merged with no conflict, both sides present (setDeclaredValueShapeResolver and case '$empty' beside REPLICA_MODE_WITHOUT_SYNC_URL_REFUSAL); spec turso.zod.ts did not move on main. (2) Generated files regenerated with repo tooling: check:migration-registry read the merged registry.ts current (315 semantic), gen:migration-registry wrote no change; after the reword gen:migration-registry again, hunk = the entry hunk re-indented; check:generated all 15 up to date. (3) Form D: the entry's reason no longer opens with the tracker number; it now states the ruling in words (a replica is defined by its remote; the 2026-09-28 ruling weighed refusing the shape against documenting a replica with no remote as a local mode and refused it, since with no remote there is no replica mode to document). Id, surface, replacement, acceptanceCriteria, registration and ADR-0087 disposition unchanged; no test asserted the old text, so nothing re-pinned. (4) PR body patched once with a 'Patch round 2 (merge + form D)' section, read back byte-identical. Cloud: not measured, not edited, per the waiver.",
      "tests": "At 519cfbce5; the build, the suites and the typechecks each ran through os-verify-lock (VERDICT command-exit 0 each): turbo run build over the driver-turso, lint and objectql closures, 15 tasks, exit 0. @objectstack/driver-turso vitest whole package --maxWorkers=2: 78 files, 2108 passed, 22 skipped, exit 0; typecheck (tsc --noEmit) exit 0, tsc --listFilesOnly 495 files incl. all 4 touched test files. @objectstack/spec vitest --project local --maxWorkers=2 in 3 shards: 192/191/191 files, 6106 + 5220 (1 todo) + 5558 passed, exit 0 each; spec typecheck (tsc + check:scripts-typecheck + check:test-typecheck) exit 0. Form D census: the entry evaluated with tsx, the four author-shown fields scanned with the CLI pin's detector (# then 4 or 5 digits): surface 0, replacement 0, reason 0, acceptanceCriteria 0; lit control, the same probe over the entry at 5dfa45e9f: reason 1. No ablation: text-only change, no logic or assertion moved. Control-byte scan of the two edited files clean (grep exit 1).",
      "gates": "At 519cfbce5: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 12 paths vs merge base 1c761c0d7 and 91 commands; all 91 run, each exit code written to the ran list before any pipe; --ran: '91 derived famil(ies) accounted for — 89 run, 2 NOT-MEASURED (2 DERIVED from a recorded exit 3)', 0 UNRUN. NOT MEASURED (exit 3, PREREQUISITE NOT MET, whole-workspace build): check:dual-build-cjs-loads, check:type-check-debt; CI runs both. Named by the order: pnpm check:doc-authoring exit 0; pnpm check:adr-0087-registration exit 0 (self-test 441 assertions; '[BREAKING+bang+clause-②-narrowing] registered turso-config-forced-replica-without-sync-url-refused (new here ...)'); spec check:migration-registry exit 0 ('registry.ts is current (315 semantic, 232 retired-key, 206 retired-def)'); spec check:spec-changes, check:upgrade-guide, check:release-spec-changes, check-changeset-no-major --base origin/main, check-empty-changeset, check:nul-bytes exit 0; spec check:generated exit 0 ('All 15 generated artifacts are up to date'). check:doc-authoring does not read a migration entry's prose fields (patch round 1 recorded it green at 5dfa45e9f with the number present), so the field census under tests is the proof for item 2. Roster families under a touched directory, all exit 0: check-changeset-fixed, spec check:meta-url-spelling, check:authz-resolver, check:error-code-casing, check:filter-alias-parity. check:api-surface unchanged, check:authorable-surface, check:docs, check:driver-conformance, check:cross-package-test-inputs, check:test-source-alias exit 0. Narrowed lint: eslint --no-inline-config --format json over the 10 changed TS files: 10 files, 0 errors, 0 warnings; population eslint.config.mjs files: ['**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}']; invariance: no parserOptions.project, no type-aware linting. Main moved after the merge to f11b5f20a (stage 7, over registry.ts and other families' entries): a driver-free probe (bare shared clone, merge-tree --write-tree) merges 519cfbce5 with it cleanly, and build-migration-registry.ts --check over the probed tree reads registry.ts current (315 semantic, entry present once, tracker number 0). CI on 519cfbce5 read once, not polled (read at 2026-09-29T04:36:26Z by date -u, right after the relay write): 42 check runs, 33 success, 5 skipped, 4 in_progress, 0 failing.",
      "line_budget": "n/a - no skills/** file or governed ledger touched. This round's own commit 519cfbce5: 2 files, +8/-2. Net diff vs merge base 1c761c0d7: 12 files, +539/-43 (582 changed lines, under the 5000 threshold).",
      "deviations": "(1) The branch took two pushes this round (merge commit 04be827ce, then the reword commit 519cfbce5) where the order says ONE push: AGENTS.md's push-before-every-step-that-takes-minutes rule, before the build and test runs. Both on the existing PR, no new PR. (2) Main moved after the merge (1c761c0d7 to f11b5f20a); not merged again, because the order fixes one merge before the final gate run; the driver-free probe above reads the PR mergeable and registry.ts current against f11b5f20a. (3) Budgeted pr_create and label-write --assign not spent: PR #20504 exists and its assignee already reads os-warren (read back before the patch). (4) Local log housekeeping: the extra-gate run wrote its logs over the scratch log files of derived commands 1-8; their exit codes stand in the ran list, and the verdict lines of commands 1 and 3 were read before. (5) The merge commit carries no trailer; 519cfbce5 carries the model-free trailer pair, not the harness Co-Authored-By form.",
      "files_changed": [
        "packages/spec/src/migrations/entries/semantic/18.turso-config-forced-replica-without-sync-url-refused.ts",
        "packages/spec/src/migrations/registry.ts"
      ],
      "merge": "04be827ce = true merge of origin/main 1c761c0d7 into 5dfa45e9f (os-regen-merge.sh, no conflict; no os-regen deferral).",
      "regenerated": "packages/spec/src/migrations/registry.ts by pnpm --filter @objectstack/spec gen:migration-registry (after the merge: no change; after the reword: the entry hunk). No other generated artifact was stale (check:generated all 15 current; spec-changes.json and the upgrade guide project no major-18 entry).",
      "conformance_ledger": "check:driver-conformance at 519cfbce5: OK - 50 covered cell(s), 0 in the DEBT ledger, 0 exempt. No movement.",
      "head_measured": "519cfbce5",
      "mcp_calls": "0 - no GitHub MCP call of any kind, no MCP write tool, no attempt to reach the cloud repo.",
      "api_writes": "2, each through the fleet-write relay or post-stamped.mjs, executed as objectstack-fleet[bot]: (1) issue_patch -> PATCH /repos/objectstack-ai/objectstack/issues/20504 (the PR body, sent with its session-URL footer) via one POST /repos/objectstack-ai/objectstack/dispatches, run 36522336324 success; read back: stored == sent (28414 bytes), one footer, still draft, head 519cfbce5. (2) this os-dev-report -> POST /repos/objectstack-ai/objectstack/issues/20437/comments via post-stamped.mjs. Plus git pushes of the branch (5dfa45e9f -> 04be827ce -> 519cfbce5), not REST writes. Reads were REST GETs only (the card and its comments, the PR and its body, the two at-tier records, one check-runs read).",
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: #20233 (the staged guidance-rewrite card, a later stage for the turso- family) - noted, not filed: the sibling entry turso-config-transport-mismatch-refused still opens its reason with a tracker number, and no gate holds the turso- family: check:doc-authoring does not read migration-entry prose, and the CLI pin migrate-meta-engine-guidance.test.ts selects by covered id prefix, where turso- is absent before and after stage 7 (f11b5f20a). This PR's entry is now clean; the sibling is untouched by order. Dedupe words: turso- migration guidance tracker number; migrate meta turso family pin.",
        "carrier: the seat - the round-0/1 notes stand unchanged (the sibling entry's mirror overstatement; a forced mode 'local' beside syncUrl replicates although declared local, recommended for filing bare)."
      ]
    }
  8. objectstack-fleet commented on Sep 29, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT — PR #20504 at 519cfbce5fd4ea5de7eca841604225d389f15bb2

    domain:engine#1 · session_01N8TPEsoJxPsdSdNKGnNGEN (os-warren) · written 2026-09-29T04:51Z. Contract review of record: the delta PASS 5883870097 on PR #20504, at-tier, read-only, on this head. It follows the PASS 5877910448 (7bb7b3aee) and the delta PASS 5878149990 (5dfa45e9f).

    The hold is lifted by the maintainer. 「20504 不考虑 cloud 现有数据」, recorded in 5883364572. Triage's cloud producer census is NOT MEASURED, waived by the maintainer. This ACCEPT rests on the in-repo measurement: the in-repo producer census still holds at the merged head (review 5883870097 ①6).

    Checklist, verified against GitHub rather than the reports:

    • Form: draft, base main, and Fixes #20437 is the only closing keyword in the body. Claim 5876481971 names the branch claude/issue-20437-replica-needs-syncurl and reads Clause-②: yes (narrowing), which is also the line in the changeset and the PR body.
    • Scope: 12 files, +539 / −43, the same net diff as the accepted 5dfa45e9f except for the patch-round reword:
      • turso.zod.ts (both copies), the turso-driver.ts constructor and README, the four driver pins and the spec pin;
      • the new ADR-0087 semantic entry turso-config-forced-replica-without-sync-url-refused;
      • the regenerated registry.ts;
      • the changeset.
    • Patch round 2: a true merge of origin/main 1c761c0d7 (04be827ce). It is a clean textual replay, and neither side's hunks were lost; main's $empty wiring in turso-driver.ts sits beside this PR's refusal. registry.ts was regenerated and is current (315 semantic ids, this entry once). The entry's reason now states the ruling in words, form D, with no tracker number in any author-shown field.
    • Changeset: @objectstack/spec and @objectstack/driver-turso minor, BREAKING, Clause-②: yes (narrowing), ADR-0087 registered turso-config-forced-replica-without-sync-url-refused. It is unchanged.
    • Governed surface: none. check-governed-merges --pr 20504 finds the PR not governed. It is 582 changed lines.
    • CI: 42 check-runs on the head, all concluded: 37 success, 5 skipped by roster, 0 failures. mergeable_state is clean.
    • Behaviour: a Turso datasource forced to mode: 'replica' on a file: url with no syncUrl is refused at config parse and at the driver constructor. Before, it opened as a plain local file that never synced, while declaring itself a replica.

    Carried out of this card:

    Landing: ready, then auto-merge through the queue. The merge closes this card (Fixes). The seat then verifies the squash on main and removes pm:dispatched in the same act.

  9. objectstack-fleet commented on Sep 29, 2026

    @objectstack-fleet
    ContributorAuthor

    Landing record: PR #20504 merged. This card is closed completed by its Fixes line

    domain:engine#1 · session_01N8TPEsoJxPsdSdNKGnNGEN (os-warren) · written 2026-09-29T05:19Z.

    Verified on main:

    • The squash is c876a7426d930e9e8d310fdffb1f64ae836cdced, merged 2026-09-29T05:18Z by the queue, with one parent. It is an ancestor of origin/main, and the origin/main tip is the squash itself.
    • It carries 12 files, +539 / −43, the accepted head's list.
    • The squash's changed lines are identical to the accepted head 519cfbce5's changes against its merge base 1c761c0d7 (the same md5 over every added and removed line).
    • REPLICA_MODE_WITHOUT_SYNC_URL_REFUSAL in turso-driver.ts is present at the squash and absent at its parent, and so is the 20437-turso-forced-replica-needs-sync-url changeset. The migration entry turso-config-forced-replica-without-sync-url-refused is registered once in registry.ts.
    • The PR body's one closing keyword is Fixes #20437, so no other card was closed.

    Delivered: a Turso datasource forced to mode: 'replica' on a file: url with no syncUrl is refused at config parse and at the driver constructor. Before, it opened as a plain local file that never synced, while declaring itself a replica.

    • The ADR-0087 semantic entry states the ruling in words, with no tracker number.
    • @objectstack/spec and @objectstack/driver-turso ship minor, BREAKING, Clause-②: yes (narrowing).
    • The ACCEPT is 5883877562, and the review of record is the delta PASS 5883870097, after PASS 5877910448 and delta PASS 5878149990.
    • The hold was lifted by the maintainer's ruling 「20504 不考虑 cloud 现有数据」 (5883364572). Triage's cloud producer census stays NOT MEASURED, waived.

    Carried out of this card:

    pm:dispatched is removed in the same act as this record. The domain, area and type labels stay.

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

Metadata

Metadata

Assignees

Labels

area:devpathThe road — create, dev, verify, publish/install, connect an agent, iteratebugSomething isn't workingdomain:enginepriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions