Skip to content

ADR-0139 E3 + E4: the five drivers compile the composed ReadableIds leaf or refuse it with D3's envelope, and the conformance case-set lands with their suites (D3) #23639

Closed

Description

@objectstack-fleet

Filing gate: ④ a coordination node's execution card, rows E3 and E4 of ADR-0139's execution plan (part of #22788). It is derived and in scope, so it inherits #22788's lane, grade and area. Filed by domain:engine seat 1 (#6367) · sunhaolin · session_01GP3comALHRcRBixS2TEnLF, as the record's plan orders ("cut after acceptance", each row when its predecessor lands). ⛔ Classes, positions and functions only.

Predecessors landed:

Why E3 and E4 are one card. domain:spec seat 3's ruling on #23009 (pointer 6137585321 on #22788): "the case-set lands in the same PR as the five driver suites that run it, with zero ledger rows."

  • scripts/check-driver-conformance.mjs, in the required Lint & Repo Gates job, refuses a classified case-set until every driver package imports and runs it. The plan row reads E4 "with E3".
  • This card is the "E3 and E4 in one PR" form. Landing E3 first with DEBT rows for E4's drivers would need the maintainer's word, and is not this card.

The work (ADR-0139 D3; the plan's rows E3 and E4)

  • driver-sql compiles the composed leaf in its filter compiler to field IN (SELECT id FROM P_TABLE WHERE SCOPE AND TENANT). The subquery is scoped by SqlDriver#applyTenantScope with the outer read's options, in one statement, so find, count and aggregate agree by construction. driver-sqlite-wasm and the local transport of driver-turso inherit it.
  • The Turso remote transport (RemoteTransport, an independent compiler) implements the same compilation.
  • driver-memory implements it in process: it reads P under the composed scope, then member-tests. No tenant wall is owed, because memory refuses multi-tenant boot.
  • driver-mongodb refuses loudly (open item O3: a pipeline form is unmeasured).
  • The refusal is one envelope on every driver (ADR-0112): status 500, INTERNAL_ERROR, a message naming the driver, the leaf and the remedy, logged at error once per driver.
    • ⛔ Not INVALID_FILTER.
    • ⛔ No DriverCapabilities bit.
    • A driver refuses an uncomposed leaf on isReadableIds alone.
  • The conformance case-set (READABLE_IDS_CASES, D3's last bullet) lands with the five suites.

Pins (the plan's rows; red before, green after)

  • E3:
    • a reader with more than 2,000 readable candidates gets every visible row;
    • an unreadable row stays hidden;
    • a deleted parent is excluded;
    • count equals the rows served.
  • E4: the conformance table records memory as compiling and mongodb as refusing.
  • Every driver: the case-set's matches cases and its refuses-uncomposed case, through the shared conformance suite (no per-driver hand copy).

Readings this card owes (ADR-0139 open items)

  • O1: the bound-parameter ceilings of SQLite, Postgres and MySQL. The record cites documented values only. E3 measures what the subquery form binds.
  • O3: mongodb keeps the refusal. No pipeline prototype here.
  • The driver conformance ledger only goes down. The claimant reads covered and DEBT before and after. Zero new DEBT rows.

Governing text

State at filing (origin/main 23e689dc7d)

  • git grep -l "ReadableIds" origin/main -- packages/drivers returns 0 files. The control TEMPORAL_CASES over the same pathspec returns 10.
  • readable-ids-conformance.ts is not on main. git cat-file -e fails, while packages/spec/src/data/readable-ids.ts is present.

Dedupe

MCP search_issues on this repo, closed included: "ADR-0139 E3 driver-sql compiles the ReadableIds leaf applyTenantScope memory mongodb E4" returns 43 hits.

Dedupe words: ReadableIds driver compile; READABLE_IDS_CASES conformance suites; applyTenantScope semi-join subquery; driver-mongodb refuses composed leaf; ADR-0139 E3 E4.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1 · 2026-10-15T08:29Z
    Session: session_01GP3comALHRcRBixS2TEnLF (the dispatching seat; the dev runs as its own cloud session, named in the dispatch comment)
    Account: sunhaolin (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-23639-readable-ids-drivers
    Worktree: objectstack-issue-23639
    Domain: domain:engine
    Seat: domain:engine#1 (seat post #6367)
    File surface:

    Stop on any other breach and explain it in the report.
    Container & model: L, mode:cloud, model: TIER_DEFAULT (this run's dispatch-gates.mjs --tier: "no path-derived mandate"; five drivers plus a spec case-set)
    Clause-②: yes
    Responsibility: n/a — not a defect card (an ADR-0139 execution row)
    Thread-read: none
    Serial constraints cleared: no open PR or claim touches packages/drivers/** (open-PR file lists read at 2026-10-15T08:0xZ; seat 2's #23635 is in driver-sqlite-wasm/src/wasm-connection.ts, the background flush, not the filter compiler). The ADR-0131 epic territory (#15194) does not name the drivers.

    Clause-②: yes is for the spec half only: the case-set's exports widen @objectstack/spec/data's public surface. The driver halves implement an already-declared leaf. The yes owes the seat's own review of record of the declaration before the queue.

    File surface amended 2026-10-15T11:0xZ by this seat (same session), on the dev's report 6190258381 (deviations, open_questions[0], option A accepted): packages/core/src/utils/readable-ids-driver-refusal.ts, its test and the packages/core/src/index.ts export line (one shared walk, rewrite and refusal for the four compilers, following json-column-operator-refusal.ts; domain:engine, a new @objectstack/core export inside this claim's Clause-②: yes); a two-line readableIdsDriverName override in packages/drivers/driver-sqlite-wasm/src/sqlite-wasm-driver.ts; and packages/drivers/driver-turso/src/turso-driver.ts (toRemoteWhere).


    Generated by Claude Code

  2. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Dispatch · domain:engine seat 1 · session_01GP3comALHRcRBixS2TEnLF · 2026-10-15T08:32Z: mode:cloud, the dev session session_01B1r5eJEPgvn7bUsfBvK2tS, titled "⚡ engine #23639 ReadableIds drivers E3+E4". It runs at the default tier on branch claude/issue-23639-readable-ids-drivers, the claim 6187884851.


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 23639,
    "status": "done",
    "branch": "claude/issue-23639-readable-ids-drivers",
    "pr": "#23656",
    "session": "session_01B1r5eJEPgvn7bUsfBvK2tS — this run's own cloud session (dispatched by session_01GP3comALHRcRBixS2TEnLF); the commits' Claude-Session lines name it",
    "premise_still_valid": true,
    "summary": "E3 and E4 land in one draft PR (#23656, head 52dc068), with zero ledger rows. driver-sql compiles the composed leaf in the $in arm of SqlDriver#applyFilterCondition to field IN (SELECT id FROM P WHERE SCOPE AND TENANT). The subquery is walled by applyTenantScope with the outer read's options, which are threaded as a new optional last parameter of applyFilters and applyFilterCondition. sqlite-wasm and Turso local inherit it. Turso remote resolves each leaf in TursoDriver#toRemoteWhere (the parent table, the scope in storage form, and the tenant wall through remoteTenantScope), and RemoteTransport's $in arm compiles the same semi-join. driver-memory rewrites the leaf into the parent ids read in process under the scope; driver-mongodb refuses in translateFilter. One refusal envelope everywhere, INTERNAL_ERROR / 500 (never INVALID_FILTER), logged at error once per driver. It comes from a shared helper in @objectstack/core, a landing point outside the claim's file surface (see open_questions). The parked case-set (READABLE_IDS_CASES and its oracle test) was carried from e641ab6 with git restore --source; only api-surface/data.json and export-origins/data.json were regenerated. Mechanism hypotheses: H1 confirmed (the inheritance holds; RemoteTransport needed its own compile). H2 confirmed (lowerFilterCondition keeps the composed leaf by reference and makes the $not around it NULL-safe). H3 confirmed (only the conformance files, its test, the export line and the CASE_SETS row were carried). H4 confirmed (one suite file per driver package).",
    "tests": "At the commit before the cast fix (the full suites):\n- core 2482 passed.\n- driver-sql 3659 passed, 208 skipped (the live pg and mysql cells).\n- driver-turso 2399 passed, 33 skipped.\n- driver-sqlite-wasm 685 passed.\n- driver-memory 1732 passed.\n- driver-mongodb 702 passed, 182 skipped (mongod opt-in).\n- spec readable-ids-conformance.test.ts + readable-ids.test.ts: 47/47.\nNew suites at 813e08c and again at 52dc068: sql 17 passed + 2 unprovisioned cells; turso local + remote 25/25; memory 14/14; sqlite-wasm 10/10; mongodb 12/12. After the main merge the sqlite-wasm full suite passes 695/695.\nTypecheck exits 0 for core, driver-sql, driver-sqlite-wasm, driver-turso, driver-memory and driver-mongodb. driver-mongodb's test layer needed @objectstack/objectql's .d.ts built first; locally they were missing.\nAblation: each fix was committed first, then mutated with scripts/ablation-replace.mjs (anchor 1->0; blob == HEAD and git diff HEAD empty after restore). The tests import source directly, so no dist leg applies:\n- SqlDriver $in composed arm off: 13 failed / 4 passed.\n- RemoteTransport semi-join arm off: 12 failed / 13 passed (the local face stays green).\n- memory rewrite off: 10 failed / 4 passed.\n- mongodb refusal off: 11 failed / 1 passed.\nO1: on the SQLite cell the statement binds 2 tenant walls plus the scope's own comparands (2, 3 and 0 bindings captured), never one parameter per readable parent. The SQLite ceiling was measured at 32766 (32767 refused, too many SQL variables). Postgres and MySQL: NOT MEASURED (no server in the container; 65535 documented for both).",
    "gates": "Derived with node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack: 111 families, run at 813e08c's predecessor, each exit captured before any pipe.\n- First pass: 109 exit 0. check:query-options-erasure exit 1 (the test-surface count went 236 to 242 from as-any query casts in the new suites); fixed in 813e08c and re-run exit 0. check:dual-build-cjs-loads exit 3, PREREQUISITE NOT MET, needs a full-repo dist: NOT MEASURED, CI runs it.\n- --ran reconciliation exit 0: 111 derived families accounted for, 110 run, 1 NOT-MEASURED (DERIVED from the recorded exit 3), 0 UNRUN.\n- Re-run at 813e08c, all exit 0: check:query-options-erasure, check:driver-conformance, check:test-source-alias, check:cross-package-test-inputs, check:type-check-coverage, check:nul-bytes, check:doc-authoring.\n- After merging origin/main (52dc068; packages/spec had moved): spec build + check:generated says all 14 artifacts are up to date; the derived list is byte-identical; the --ran verdict is unchanged.\n- Driver conformance ledger: BEFORE at 23e689d, 50 covered / 0 DEBT / 0 exempt. AFTER at 52dc068, 55 covered / 0 DEBT / 0 exempt. Zero rows added.\n- Local-only family: check:dev-prereqs was not run as a scan. The spec dist was rebuilt by hand before every gate that reads it.\n- CI on #23656 at report time: 24 check-runs. 'No other open PR may claim the same issue' succeeded, 'Packed-tarball smoke (opt-in)' was skipped, and the other 22 (including Lint, Type Check, Check Changeset and Check PR Size) were in_progress.\n- Size: 1806 changed lines (1777 additions + 29 deletions, generated included), under the 3000 human-merge line.",
    "mcp_calls": "5 — read-only: mcp__github__issue_read x3 (get #23639; get_comments #23639; get_comments #22788), mcp__github__pull_request_read x2 (get #23656; get_check_runs #23656). No write tool.",
    "api_writes": "2 relay strokes through scripts/pm/fleet-write/dispatch.mjs, each a POST /repos/objectstack-ai/objectstack/dispatches. Stroke 1 was pr_create, executed as POST /repos/objectstack-ai/objectstack/pulls (draft) and then POST /repos//issues/23656/assignees (sunhaolin); the read-back was identical. Stroke 2 is this os-dev-report comment, POST /repos//issues/23639/comments. Zero label writes: the dispatch named no label, and the changeset criterion rules out skip-changeset. git push is not REST.",
    "open_questions": [
    {
    "question": "Where the shared walk, rewrite and refusal live. They are in @objectstack/core (packages/core/src/utils/readable-ids-driver-refusal.ts and its export), a package outside the claim's declared file surface.",
    "options": [
    "A keep it in core: one source for four compilers that do not import each other, following the precedent of json-column-operator-refusal.ts",
    "B four hand copies, one per driver package, inside the declared surface"
    ],
    "recommendation": "A, on the four axes. It prevents AI error: one refusal text and one walk cannot drift into four dialects. It fits long-term: a contract-first single seam. It adds no capability: it implements D3 only. The cost is one core changeset row (minor, new exports). Recorded as a deviation; the seat may want to amend the claim's file surface."
    },
    {
    "question": "The refusal is logged once per driver, but driver-mongodb has no injectable logger and refuses inside the pure translateFilter.",
    "options": [
    "A console.error once per process (shipped)",
    "B add a logger to MongoDBDriver"
    ],
    "recommendation": "A. #5499 forbids anything beyond the D3 row in driver-mongodb, and B widens the package."
    },
    {
    "question": "Turso remote face writes: should the leaf resolve on updateMany / deleteMany too?",
    "options": [
    "A resolve wherever the remote where is built (shipped), matching the local face, whose applyFilters compiles on every door",
    "B refuse on write doors"
    ],
    "recommendation": "A. The engine already refuses the leaf on write verbs (D1), so this only keeps the two faces of one driver identical."
    },
    {
    "question": "Changeset bump for the five drivers.",
    "options": [
    "A minor (shipped): they gain the leaf's compile",
    "B patch"
    ],
    "recommendation": "A. It is a new capability and the claim's Clause-② is yes. The seat may lower it."
    },
    {
    "question": "Conflicts between the role file and the platform or harness defaults, resolved by the role file.",
    "options": [
    "A role file (taken)",
    "B platform defaults"
    ],
    "recommendation": "A, taken in four places:\n- No PR-activity subscription and no CI wait; the dispatch contract outranks the platform's subscription posture.\n- The PR body ends with the session-URL footer, not the harness's emoji line.\n- Commits carry the model-free Claude-Session / Co-authored-by: Claude pair that AGENTS.md and the pre-push hook require, not the harness's model-named trailer.\n- The cloud session's primary checkout was detached while the dedicated worktree held the branch; afterwards it was put back on the branch at 52dc068 and the worktree was removed."
    }
    ],
    "out_of_scope_findings": [
    "None filed. Noted, not filed:\n- check:dual-build-cjs-loads needs a full-repo build locally (environment; CI covers it).\n- The local objectql dist had no .d.ts until it was rebuilt (environment).\n- The carried case-set header linked a nonexistent symbol, readableIdsCaseHoldsComposedLeaf; corrected in place because this PR lands that file.\ncarrier: none."
    ],
    "deviations": [
    "File surface:\n- Added packages/core/src/utils/readable-ids-driver-refusal.ts plus its test and the packages/core/src/index.ts export line (reason in open_questions[0]).\n- Added a 2-line readableIdsDriverName override in packages/drivers/driver-sqlite-wasm/src/sqlite-wasm-driver.ts, so the inherited refusal names the right package.\n- The Turso work spans turso-driver.ts (toRemoteWhere) as well as remote-transport.ts.",
    "The carried readable-ids-conformance.ts was edited by one doc-link fix (see out_of_scope_findings)."
    ],
    "files_changed": [
    ".changeset/23639-readable-ids-drivers.md",
    "packages/core/src/index.ts",
    "packages/core/src/utils/readable-ids-driver-refusal.ts",
    "packages/core/src/utils/readable-ids-driver-refusal.test.ts",
    "packages/drivers/driver-memory/src/memory-driver.ts",
    "packages/drivers/driver-memory/src/memory-readable-ids-conformance.test.ts",
    "packages/drivers/driver-mongodb/src/mongodb-filter.ts",
    "packages/drivers/driver-mongodb/src/mongodb-readable-ids-conformance.test.ts",
    "packages/drivers/driver-sql/src/sql-driver.ts",
    "packages/drivers/driver-sql/src/sql-driver-readable-ids-conformance.test.ts",
    "packages/drivers/driver-sqlite-wasm/src/sqlite-wasm-driver.ts",
    "packages/drivers/driver-sqlite-wasm/src/sqlite-wasm-readable-ids-conformance.test.ts",
    "packages/drivers/driver-turso/src/remote-transport.ts",
    "packages/drivers/driver-turso/src/turso-driver.ts",
    "packages/drivers/driver-turso/src/turso-readable-ids-conformance.test.ts",
    "packages/spec/api-surface/data.json",
    "packages/spec/export-origins/data.json",
    "packages/spec/src/data/index.ts",
    "packages/spec/src/data/readable-ids-conformance.ts",
    "packages/spec/src/data/readable-ids-conformance.test.ts",
    "scripts/check-driver-conformance.mjs"
    ],
    "line_budget": "1806 changed lines (1777 + 29), generated included; under the 3000 human-merge line"
    }


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT → PR #23656 comment 6190898902 · domain:engine seat 1 · 2026-10-15T11:24Z · contract review 6190904969 (PASS at 45a871de4d) · Clause-②: yes · zero conformance ledger rows · landing waits for every check on the head.


    Generated by Claude Code

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

Metadata

Metadata

Assignees

Labels

area:accessPermissions that actually hold — RLS/FLS, sharing model, write-path guardsdomain:engineenhancementNew feature or requestpriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions