You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
runtime(standalone host): with an explicit OS_DATABASE_DRIVER=sqlite, an opaque-scheme OS_DATABASE_URL (jdbc:postgresql://…) still opens a SQLite file at a path made of the URL — the explicit-driver path of #23765 #23863
Filing gate ①, class (a). Parent: #23765 (in flight, PR #23861). This card carries the explicit-driver path of #23765's defect; #23765 keeps the URL-classification path (detectDriverFromUrl), which its PR fixes.
reach: measured at the public door by #23765's dev on that branch (runtime dist at c01539665, os-dev-report on #23765, out-of-scope finding 1):
OS_DATABASE_DRIVER=sqlite OS_DATABASE_URL=jdbc:postgresql://127.0.0.1:5999/db os serve --dev over a plain config printed ✓ Server is ready with Driver: SqlDriver(better-sqlite3) → jdbc:postgresql://127.0.0.1:5999/db, and created ./jdbc:postgresql:/127.0.0.1:5999/db plus .telemetry.db siblings.
CONTROL, same build: OS_DATABASE_DRIVER=sqlite with redis://h/x.db exits 1 with sqlite driver was selected but the URL does not look like a file path (its scheme is "redis://").
Filed by domain:cli seat 2 (#22648) · os-tesla · session session_018t6a5rvqPRvEDMCVVW9kYT, from that report. ⛔ Not a claim.
sqliteFilenameFromUrl (packages/runtime/src/standalone-stack.ts) refuses only what urlSchemeOf recognises, the SCHEME:// forms. An opaque scheme (two or more characters and a : with no //) passes through as a filename. That is the bogus directory the module header (:34) says never happens.
The CLI host, under the same explicit selection (resolveStorageDefinition('sqlite', …), read on the built dist, not at the door), returns the whole URL as the filename for both jdbc:… and redis://h/x.db, so today the two hosts also disagree on redis://h/x.db.
Seam: env:OS_DATABASE_DRIVER=sqlite → runtime:sqliteFilenameFromUrl (packages/runtime/src/standalone-stack.ts) | cli:resolveStorageDefinition sqlite arm (packages/cli/src/utils/storage-driver.ts)
Reader who acts
domain:cli seat 2, after the #23794 + #23796 fold lands (claim 6211181834). That fold is rewriting sqliteFilenameFromUrl into the one exported filename rule both hosts call; this card then adds the opaque-scheme refusal to that one rule, so both hosts refuse the same values under an explicit sqlite / sqlite-wasm selection.
Pins: under an explicit sqlite and sqlite-wasm selection, jdbc:postgresql://…, redis:h and redis://h/x.db are refused on both hosts, naming the scheme only and creating nothing on disk. CONTROL: file:./x.db, ./x.db, C:\data\x.db and :memory: resolve as before.
Order: serial behind the fold, on sqliteFilenameFromUrl. The fold's own defect (how a file: URL becomes a filename) is a different shape, so this is not folded into it mid-flight.
Dedupe
MCP search_issues on objectstack-ai/objectstack, closed included: explicit OS_DATABASE_DRIVER sqlite opaque scheme URL opened as file path sqliteFilenameFromUrl bogus directory → 11 hits. #23765, #23794 and #23796 are this family (URL classification; the file: filename rule, two halves); #23633, #23764, #23737, #23696, #23648, #19976 and #15374 are neighbours, none of which names the explicit-driver path.
A second location of this card's defect: the sqlite-wasm kind. From domain:cli seat 2 (#22648) · os-tesla · session session_018t6a5rvqPRvEDMCVVW9kYT · 2026-10-16T10:03Z · ⛔ not a claim, no label change.
What this card's fix then covers: under an explicit sqlite or sqlite-wasm selection, the one rule refuses every URL that is not a file path: a SCHEME:// server URL (the wasm kind today), an opaque scheme (both kinds today). It names the scheme only and creates nothing on disk, on both hosts. Add postgres://… under sqlite-wasm to the pins.
Not dispatched by domain:cli seat 1, on the maintainer's choice · marchtian · session session_01PFB9ZGRWYvjhTXsd8i6KBp · 2026-10-16T10:38Z · ⛔ Not a claim; the card stays in pm:queue.
Claim: PM loop round 1 (#23863: under an explicit sqlite or sqlite-wasm selection, the one filename rule sqliteFilenameFromUrl refuses every value that is not a file path, an opaque scheme on both kinds and a SCHEME:// URL on the sqlite-wasm kind, naming the scheme only and creating nothing on disk, so both hosts refuse the same values) · 2026-10-16T10:53Z
Session: session_018t6a5rvqPRvEDMCVVW9kYT
Account: os-tesla (the seat's linked user as GET /user answers it; the card's assignee from this act)
Branch: claude/issue-23863-explicit-sqlite-refuses-non-file
Worktree: objectstack-issue-23863
Domain: domain:cli
Seat: domain:cli#2 (seat post #22648)
Scope: batch 3. Dev runs in flight before this act: #23050 slice 8 and #23726. #23765 (PR #23861) and #23820 (PR #23867) are ACCEPTed and in the merge queue. This card takes the slot #23794 + #23796 freed when PR #23862 merged.
Order, read at this act: #23826 and #23848 (p1 target:v18) are seat 1's claims (6213051032, 6213346689). No other open p0, p1 or pm:blockingdomain:cli card is in pm:queue. This card is the lane's only queued p2 bug. Its own Order line put it serial behind PR #23862, which merged as 34b740f2d1 at 2026-10-16T10:21Z. Seat 1's note 6213663716 releases it to either seat on that merge.
File surface (read on origin/main34b740f2d1; stop on a breach and explain it in the report):
packages/runtime/src/standalone-stack.ts, sqliteFilenameFromUrl and its docblock only (about :590-:622):
Pins: a new test file in packages/runtime beside the standalone database-URL tests, and explicit-driver rows in packages/cli/src/utils/driver-vocabulary-parity.test.ts with both hosts' answers equal.
One .changeset/23863-*.md (@objectstack/runtimepatch).
not inferDriverTypeFromUrl or resolveStorageDefinition's logic in storage-driver.ts.
Container & model: S-to-M (one rule on two kinds, both hosts through one export, pins on both), mode:subagent, model: TIER_DEFAULT (dispatch-gates --tier on this surface: no path-derived mandate; Clause ② sets the default tier)
Clause-②: no
Basis for the Clause-② line:
The values this card refuses are ones the published text already refuses. The module header (standalone-stack.ts, about :34) says "Unknown URL schemes throw — we never silently fall back to sqlite, since that historically created bogus directories on disk". The sqlite kind's own refusal says "the URL does not look like a file path".
One file name changes answer: a first path segment that holds a colon (backup:2026.db) under an explicit selection is now refused, as it is on the classification path after PR fix(runtime): the standalone host refuses an opaque-scheme OS_DATABASE_URL, and a .wasm.db ending no longer rescues an unrecognised scheme #23861. ./backup:2026.db and file:backup:2026.db still name that file, and the changeset says so.
Responsibility: the runtime's one SQLite filename rule in packages/runtime, which both hosts call (this lane) | the URL classifier's opaque-scheme refusal (PR #23861) and the module header's rule; neither reaches an explicit driver selection, which skips classification | an operator who sets OS_DATABASE_DRIVER=sqlite or sqlite-wasm beside a server URL: a ready server on a SQLite file at a path made of the URL, and on the WASM kind a directory name carrying the URL's credentials (measured, 6213066437)
Thread-read: 6213663716
Serial constraints cleared: open PRs read in this act.
os-dev-report
{
"issue": 23863,
"status": "done",
"branch": "claude/issue-23863-explicit-sqlite-refuses-non-file",
"pr": "#23896",
"session": "session_018t6a5rvqPRvEDMCVVW9kYT (the dispatching PM session, the harness-stamped Claude-Session; this run is mode:subagent)",
"premise_still_valid": true,
"summary": "Premise held at the public door on base 34b740f: OS_DATABASE_DRIVER=sqlite OS_DATABASE_URL=jdbc:postgresql://127.0.0.1:5999/db os serve --dev printed 'Server is ready' and created ./jdbc:postgresql:/127.0.0.1:5999/db plus telemetry siblings, and OS_DATABASE_DRIVER=sqlite-wasm beside postgres://PLACEHOLDER-USER:PLACEHOLDER-SECRET@127.0.0.1:5999/db booted ready and created ./postgres:/PLACEHOLDER-USER:PLACEHOLDER-SECRET@127.0.0.1:5999/db. PR #23861 merged mid-run, so per the PM note origin/main was merged with a real merge commit (d57f615, no rebase) and its inline opaque-scheme expression became ONE module-private helper, schemeOf, called by detectDriverFromUrl and sqliteFilenameFromUrl (no new export). sqliteFilenameFromUrl now refuses, on both kinds, an opaque scheme on the value as given and a SCHEME:// URL left after the file:/wasm-sqlite: strip, with one sentence naming the kind and the scheme (the sqlite kind's words unchanged); file:backup:2026.db still names backup:2026.db, backup:2026.db is now refused as backup:. On head c80f0ce both doors exit 1 with that sentence and create nothing (OS_HOME empty too); both hosts' dist answers agree on every pinned value in dev and prod. Card assignee untouched (os-tesla); PR assignee os-tesla.",
"tests": "All on head c80f0ce unless stated. (1) pnpm --filter @objectstack/runtime exec vitest run --project local --maxWorkers=2 src/standalone-stack-explicit-sqlite-non-file-refusal.test.ts src/standalone-stack-opaque-scheme-refusal.test.ts src/standalone-stack-url-refusal-credentials.test.ts -> 'Test Files 3 passed (3) / Tests 157 passed (157)', exit 0 (new file: 80 cases). (2) pnpm --filter @objectstack/cli exec vitest run --project unit --maxWorkers=2 src/utils/driver-vocabulary-parity.test.ts src/utils/storage-driver.test.ts -> 'Test Files 2 passed (2) / Tests 204 passed (204)', exit 0 (parity file 130 cases). (3) pnpm --filter @objectstack/runtime exec vitest run --project local --maxWorkers=2 (whole local project) -> 'Test Files 402 passed (402) / Tests 6121 passed | 19 skipped (6140)', exit 0. (4) pnpm --filter @objectstack/runtime typecheck exit 0; pnpm --filter @objectstack/cli typecheck exit 0 (test layers: 'check:test-typecheck: OK'). All four ran under scripts/pm/os-verify-lock.sh, VERDICT command-exit 0. Build first: pnpm turbo run build --filter=@objectstack/cli... --concurrency=2 -> 61/61 successful, VERDICT command-exit 0. Door repro (base vs head) and a dist probe of both hosts (resolveStorageDefinition dev+prod vs resolveStandaloneDatabase) under both kinds, recorded in the PR body. ABLATION (scripts/ablation-replace.mjs WRAP mode, anchor hit x1, blob changed; runtime rebuilt each leg; scripts/ablation-dist-preflight.mjs each leg, exit 0): A1 opaque refusal removed (filename === dbUrl ? schemeOf(dbUrl) : urlSchemeOf(filename) -> urlSchemeOf(filename)), dist marker 1 -> 0: runtime file 25 failed | 55 passed (every opaque row both kinds both doors, exported-rule rows, backup:2026.db, sqlite: boundary rows, sqlite boot over jdbc:), CLI parity 8 failed | 122 passed (the opaque rows); SCHEME:// rows and CONTROL green. Restore: marker present 1, 80/80 and 130/130 green. A2 WASM refusal removed (if (!filename || scheme) -> if (!filename || (scheme && kind.length === 6))), dist marker present 1: runtime 20 failed | 60 passed (every sqlite-wasm refusal row, the sqlite-wasm boot, sqlite-wasm boundary rows), CLI parity 6 failed | 124 passed (the sqlite-wasm rows); all sqlite rows and CONTROL green. Restore: marker absent 0, 80/80 and 130/130 green. After both: blob f3f84355f733 == HEAD, git status --porcelain empty. CLI integration tier not run locally (diff touches no integration file or spawn entry); declared to CI. test:repo not run locally (diff touches no repo-project test); declared to CI.",
"gates": "Local, head c80f0ce: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 65 commands from merge base c5cf546 (5 paths); each run with its exit code recorded before any pipe: 63 exit 0; pnpm check:dual-build-cjs-loads exit 3 and pnpm check:i18n-coverage exit 3 (PREREQUISITE NOT MET: packages outside the CLI closure, e.g. connector-slack, have no dist/ in this worktree) -> NOT MEASURED locally. node scripts/pm/dispatch-gates.mjs --ran ran.list -> exit 0, '65 derived famil(ies) accounted for — 63 run, 2 NOT-MEASURED (2 DERIVED from a recorded exit 3)', 0 UNRUN. Lint: pnpm exec eslint --no-inline-config over standalone-stack.ts, the new runtime test, storage-driver.ts and driver-vocabulary-parity.test.ts -> exit 0. Control-byte self-scan (grep -naP) over all 5 changed files -> no hit (exit 1). CI (PR #23896 head c80f0ce, read once at report time, not waited on): 'No other open PR may claim the same issue' success; 'Packed-tarball smoke (opt-in)' skipped; Lint & Repo Gates lanes (Lint · ESLint, Lint · PM dispatch-gates, Lint · repo & tooling gates, Lint · CI, release & engine gates, Lint · docs & code guards, three Lint · scoped lanes), Type Check · workspace/source gates/consumer gates/debt ledger, Check Changeset, Governed Surface Queue Guard, Check PR Size, the claim/closing guards: all in_progress. Test Core and Build Core not yet listed.",
"mcp_calls": "0 — no MCP GitHub tool called",
"api_writes": "2 — both through the fleet-write relay (scripts/pm/fleet-write/dispatch.mjs), each one POST /repos/objectstack-ai/objectstack/dispatches: (1) pr_create -> POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /repos//issues/23896/assignees [os-tesla], read-back identical (10720 bytes); (2) comment -> POST /repos//issues/23863/comments (this report). Not REST: 3 git pushes of the branch (empty-branch probe, then 84cf695, then c80f0ce). Labels: none.",
"deviations": [
"3 git pushes, not 1: the empty-branch write probe os-dev.md rule 1 requires, and AGENTS.md's WIP push before each minutes-long build/test step.",
"File surface: beyond sqliteFilenameFromUrl and its docblock, standalone-stack.ts gains the module-private helper schemeOf (above detectDriverFromUrl) and one changed line in detectDriverFromUrl calling it — the merged-#23861 branch of the dispatch, confirmed by the PM's mid-run note. In driver-vocabulary-parity.test.ts the existing comment above the server-URL refusal rows ('Two inputs reach it') was reworded because it became false; its rows are unchanged.",
"Mechanism assumption 1 falsified in part and NOT normalized: the declared-datasource url (non-SQLite drivers) and TURSO_DATABASE_URL rungs reach the rule un-normalized. The one-line normalizeDatabaseUrl call inside the rule was available but would widen the accept set (sqlite:///abs/x.db opens where it is refused today) against the ruled Clause-②: no, so the boundary is pinned instead: there sqlite:./x.db is refused as sqlite: (base: a file named sqlite:./x.db) and sqlite:///… as sqlite://.",
"origin/main moved 6 commits past the merged c5cf546 before the PR opened (#23846 spec, #23866 plugin-audit, docs, CI header); none touches standalone-stack.ts, resolve-project-database.ts or packages/cli/src/utils/, so no second merge; PR CI runs on the merge ref.",
"First locked verify call ended VERDICT queue-timeout (exit 99, holder pid 20030 running the CLI unit project); NOT MEASURED and re-queued under the same OS_VERIFY_LOCK_SLOT; the second call measured everything (command-exit 0).",
"PR body footer and commit trailers follow AGENTS.md (session-URL footer; model-free Co-authored-by pair), not the harness reminder's model-named trailer and emoji footer.",
"Worktree removed after the PR opened (node_modules deleted, git worktree remove without --force succeeded); my scratch ref refs/os-dev-23863/pr23861 deleted."
],
"files_changed": [
"packages/runtime/src/standalone-stack.ts",
"packages/runtime/src/standalone-stack-explicit-sqlite-non-file-refusal.test.ts",
"packages/cli/src/utils/storage-driver.ts",
"packages/cli/src/utils/driver-vocabulary-parity.test.ts",
".changeset/23863-explicit-sqlite-non-file-refusal.md"
],
"open_questions": [],
"out_of_scope_findings": [
"class: a (misleading copy) · reach: public door, measured on head c80f0ce — OS_DATABASE_DRIVER=sqlite OS_DATABASE_URL=jdbc:postgresql://127.0.0.1:5999/db os serve --dev ends 'Use file:/path/to/db.sqlite, or set OS_DATABASE_DRIVER explicitly.' to an operator who did set OS_DATABASE_DRIVER; the clause now rides both kinds' refusal (sqliteFilenameFromUrl, packages/runtime/src/standalone-stack.ts) and, untagged, the CLI host's UnsupportedDriverError · the ruling held the sqlite kind's words unchanged, so not changed here · dedupe words: sqlite driver was selected remedy set OS_DATABASE_DRIVER explicitly; explicit driver refusal advice; sqliteFilenameFromUrl refusal wording",
"carrier: PR #23861 Acceptance notes ('A declared datasource's URL is not normalized … No in-repo producer writes it') and PR #23896 Acceptance notes · noted, not filed — the declared-datasource url and TURSO_DATABASE_URL rungs of resolveProjectDatabaseUrl skip normalizeDatabaseUrl, so a sqlite: alias there is refused as the scheme sqlite: on both the explicit and the classification path; no named producer and no public door answering wrong (a sqlite: URL in a postgres datasource or in TURSO_DATABASE_URL is not an advertised spelling); pinned as a boundary in standalone-stack-explicit-sqlite-non-file-refusal.test.ts"
]
}
ACCEPTed: PR #23896 at c80f0ceaa · domain:cli seat 2 · os-tesla · session session_018t6a5rvqPRvEDMCVVW9kYT · 2026-10-16T12:25Z · holder of claim 6213923568. The seat's checklist is 6215447953 on the PR. Every check on the head is green or a roster skip, and landing is armed in this act. The refusal's "set OS_DATABASE_DRIVER explicitly" remedy (dev finding 1) is filed as #23898, ⛔ not a claim.
merged: true, merge commit 0cb45e9e0a, merged 2026-10-16T12:56Z through the merge queue (enqueued 2026-10-16T12:28Z)
origin/main
0cb45e9e0a is an ancestor of origin/main at this reading; 5 files, +447 / −22, as reviewed at c80f0ceaa. standalone-stack.ts there declares schemeOf (1 hit), and .changeset/23863-explicit-sqlite-non-file-refusal.md is present.
queue branch
no gh-readonly-queue/main/*pr-23896* head remains
State change: this card closed completed by Fixes #23863 when the PR merged; pm:dispatched is removed in this act. Issues closed since the merge: this card alone.
Activity
objectstack-fleet commentedon Oct 16, 2026
A second location of this card's defect: the
sqlite-wasmkind. Fromdomain:cliseat 2 (#22648) ·os-tesla· sessionsession_018t6a5rvqPRvEDMCVVW9kYT· 2026-10-16T10:03Z · ⛔ not a claim, no label change.sqliteFilenameFromUrl's'sqlite-wasm'branch (packages/runtime/src/standalone-stack.ts, exported by PR fix(runtime,cli): one file-URL filename rule for both hosts — FILE: strips case-insensitively, file://NAME opens NAME on the CLI host #23862). It stripswasm-sqlite:andfile:and refuses nothing. The'sqlite'branch at least refuses aSCHEME://URL.reach:, measured at the public door by the runtime(standalone host): an upper-caseFILE:database URL is classified as SQLite but its prefix is not stripped, soOS_DATABASE_URL=FILE:./app.dbcreates a directory literally namedFILE:.and a database inside it #23794 + cli(storage):OS_DATABASE_URL=file://NAMEopens//NAMEat the filesystem root on the CLI host, where the runtime host opens./NAME(thefile:twin of thesqlite://alias #23633 fixed) #23796 dev (os-dev-report6212949127on runtime(standalone host): an upper-caseFILE:database URL is classified as SQLite but its prefix is not stripped, soOS_DATABASE_URL=FILE:./app.dbcreates a directory literally namedFILE:.and a database inside it #23794, out-of-scope finding 1), on the runtime host over a plain project.OS_DATABASE_DRIVER=sqlite-wasm OS_DATABASE_URL=postgres://PLACEHOLDER-USER:PLACEHOLDER-SECRET@127.0.0.1:5999/db os serve --devprintedServer is readyand createdpostgres:/PLACEHOLDER-USER:PLACEHOLDER-SECRET@127.0.0.1:5999/dbunder the cwd. That puts credentials into a directory name. The CLI host's wasm arm yields the same file name by the same rule, before and after PR fix(runtime,cli): one file-URL filename rule for both hosts — FILE: strips case-insensitively, file://NAME opens NAME on the CLI host #23862.sqliteorsqlite-wasmselection, the one rule refuses every URL that is not a file path: aSCHEME://server URL (the wasm kind today), an opaque scheme (both kinds today). It names the scheme only and creates nothing on disk, on both hosts. Addpostgres://…undersqlite-wasmto the pins.Generated by Claude Code
objectstack-fleet commentedon Oct 16, 2026
Not dispatched by
domain:cliseat 1, on the maintainer's choice ·marchtian· sessionsession_01PFB9ZGRWYvjhTXsd8i6KBp· 2026-10-16T10:38Z · ⛔ Not a claim; the card stays inpm:queue.FILE:database URL is classified as SQLite but its prefix is not stripped, soOS_DATABASE_URL=FILE:./app.dbcreates a directory literally namedFILE:.and a database inside it #23794 + cli(storage):OS_DATABASE_URL=file://NAMEopens//NAMEat the filesystem root on the CLI host, where the runtime host opens./NAME(thefile:twin of thesqlite://alias #23633 fixed) #23796, seat 2, draft, all checks green when read) is rewriting and exporting, and this card's own Order line puts it serial behind that fold. The answer, verbatim: 「换一个卡派」. The slot went to cli/serve --no-server, the remainder of #23623: theobjectstack:listeningIPC message and the runtime state file still announcehttp://localhost:PORTwith nothing listening, and a config-mounted server's banner names an unmounted MCP route #23743 instead.Generated by Claude Code
objectstack-fleet commentedon Oct 16, 2026
Claim: PM loop round 1 (#23863: under an explicit
sqliteorsqlite-wasmselection, the one filename rulesqliteFilenameFromUrlrefuses every value that is not a file path, an opaque scheme on both kinds and aSCHEME://URL on thesqlite-wasmkind, naming the scheme only and creating nothing on disk, so both hosts refuse the same values) · 2026-10-16T10:53ZSession:
session_018t6a5rvqPRvEDMCVVW9kYTAccount:
os-tesla(the seat's linked user asGET /useranswers it; the card's assignee from this act)Branch:
claude/issue-23863-explicit-sqlite-refuses-non-fileWorktree:
objectstack-issue-23863Domain:
domain:cliSeat:
domain:cli#2(seat post #22648)Scope:
batch3. Dev runs in flight before this act: #23050 slice 8 and #23726. #23765 (PR #23861) and #23820 (PR #23867) are ACCEPTed and in the merge queue. This card takes the slot #23794 + #23796 freed when PR #23862 merged.Order, read at this act: #23826 and #23848 (p1
target:v18) are seat 1's claims (6213051032,6213346689). No other openp0,p1orpm:blockingdomain:clicard is inpm:queue. This card is the lane's only queuedp2bug. Its own Order line put it serial behind PR #23862, which merged as34b740f2d1at 2026-10-16T10:21Z. Seat 1's note6213663716releases it to either seat on that merge.File surface (read on
origin/main34b740f2d1; stop on a breach and explain it in the report):packages/runtime/src/standalone-stack.ts,sqliteFilenameFromUrland its docblock only (about:590-:622)::with no//) on the value as given. A value whosefile:(or, on the WASM kind,wasm-sqlite:) prefix the rule strips is a file, sofile:backup:2026.dbkeeps namingbackup:2026.db, as PR fix(runtime): the standalone host refuses an opaque-scheme OS_DATABASE_URL, and a .wasm.db ending no longer rescues an unrecognised scheme #23861's CONTROL pins it on the URL-classification path.sqlite-wasmkind also refuses aSCHEME://URL, as thesqlitekind already does.sqlitekind's existing words are otherwise unchanged.OS_DATABASE_URLwith an opaque scheme (jdbc:postgresql://…,redis:h) is opened as a SQLite file path and creates directories, against the module's own "unknown URL schemes throw" #23765) has merged when the dev pushes,mainis merged in and the opaque-scheme expression it adds todetectDriverFromUrlbecomes one module-private helper that both functions call (no new export). If it has not, the same regex is written character for character, and the parity rows hold the two equal.packages/cli/src/utils/storage-driver.ts,sqliteFileFor's docblock only: its "Two inputs reach that" sentence becomes false. The CLI host already calls the runtime rule and re-raises its refusal typed (PR fix(runtime,cli): one file-URL filename rule for both hosts — FILE: strips case-insensitively, file://NAME opens NAME on the CLI host #23862), so no CLI code changes.packages/runtimebeside the standalone database-URL tests, and explicit-driver rows inpackages/cli/src/utils/driver-vocabulary-parity.test.tswith both hosts' answers equal..changeset/23863-*.md(@objectstack/runtimepatch).detectDriverFromUrl(PR fix(runtime): the standalone host refuses an opaque-scheme OS_DATABASE_URL, and a .wasm.db ending no longer rescues an unrecognised scheme #23861, in the queue), beyond the helper call named above;createStandaloneStack's directory preparation (PR fix(runtime,cli): refuse an uncreatable SQLite database directory at once instead of hanging in recursive mkdir #23851);StandaloneStackConfigSchemaor the boot options (PR fix(driver-turso,cli): the v18 organization-ownership ceremony runs on a Turso remote database #23843);inferDriverTypeFromUrlorresolveStorageDefinition's logic instorage-driver.ts.Container & model:
S-to-M(one rule on two kinds, both hosts through one export, pins on both),mode:subagent,model: TIER_DEFAULT(dispatch-gates --tieron this surface: no path-derived mandate; Clause ② sets the default tier)Clause-②: no
Basis for the Clause-② line:
standalone-stack.ts, about:34) says "Unknown URL schemes throw — we never silently fall back to sqlite, since that historically created bogus directories on disk". Thesqlitekind's own refusal says "the URL does not look like a file path".jdbc:postgresql://…orpostgres://user:password@…as a file under an explicit SQLite selection is the misbehaviour that text rules out, not an accepted input. This is the same reading as runtime(standalone host): anOS_DATABASE_URLwith an opaque scheme (jdbc:postgresql://…,redis:h) is opened as a SQLite file path and creates directories, against the module's own "unknown URL schemes throw" #23765'sClause-②: noon the URL-classification path (PR fix(runtime): the standalone host refuses an opaque-scheme OS_DATABASE_URL, and a .wasm.db ending no longer rescues an unrecognised scheme #23861).sqliteFilenameFromUrlbecame an export of@objectstack/runtimewith PR fix(runtime,cli): one file-URL filename rule for both hosts — FILE: strips case-insensitively, file://NAME opens NAME on the CLI host #23862 today, and no released version carries it yet: the Version Packages PR chore: version packages (next) #23825 is open.backup:2026.db) under an explicit selection is now refused, as it is on the classification path after PR fix(runtime): the standalone host refuses an opaque-scheme OS_DATABASE_URL, and a .wasm.db ending no longer rescues an unrecognised scheme #23861../backup:2026.dbandfile:backup:2026.dbstill name that file, and the changeset says so.Responsibility:
the runtime's one SQLite filename rule in packages/runtime, which both hosts call (this lane) | the URL classifier's opaque-scheme refusal (PR #23861) and the module header's rule; neither reaches an explicit driver selection, which skips classification | an operator who sets OS_DATABASE_DRIVER=sqlite or sqlite-wasm beside a server URL: a ready server on a SQLite file at a path made of the URL, and on the WASM kind a directory name carrying the URL's credentials (measured, 6213066437)Thread-read: 6213663716
Serial constraints cleared: open PRs read in this act.
OS_DATABASE_URLwith an opaque scheme (jdbc:postgresql://…,redis:h) is opened as a SQLite file path and creates directories, against the module's own "unknown URL schemes throw" #23765) editsdetectDriverFromUrl, addsstandalone-stack-opaque-scheme-refusal.test.ts, moves rows indriver-vocabulary-parity.test.tsand changes two comments instorage-driver.ts(inferDriverTypeFromUrl). None of those is this card's function or docblock. The parity file is shared, so whichever lands second mergesmain.pm:dispatchedclaim namessqliteFilenameFromUrlorsqliteFileFor. Seat 1's cli(migrate organization-ownership --apply): with an existing--outfile, the ceremony executes every step and then refusesapply_refused/report-file-unwritable, which under--jsonreads as if nothing ran #23826 and os migrate apply cannot run on a Turso remote database (it arms deferred DDL), so destructive drift on a remote primary has no CLI remedy #23848 hold the migrate commands anddriver-turso.standalone-stack.tstoday.Generated by Claude Code
objectstack-fleet commentedon Oct 16, 2026
os-dev-report
{
"issue": 23863,
"status": "done",
"branch": "claude/issue-23863-explicit-sqlite-refuses-non-file",
"pr": "#23896",
"session": "session_018t6a5rvqPRvEDMCVVW9kYT (the dispatching PM session, the harness-stamped Claude-Session; this run is mode:subagent)",
"premise_still_valid": true,
"summary": "Premise held at the public door on base 34b740f: OS_DATABASE_DRIVER=sqlite OS_DATABASE_URL=jdbc:postgresql://127.0.0.1:5999/db os serve --dev printed 'Server is ready' and created ./jdbc:postgresql:/127.0.0.1:5999/db plus telemetry siblings, and OS_DATABASE_DRIVER=sqlite-wasm beside postgres://PLACEHOLDER-USER:PLACEHOLDER-SECRET@127.0.0.1:5999/db booted ready and created ./postgres:/PLACEHOLDER-USER:PLACEHOLDER-SECRET@127.0.0.1:5999/db. PR #23861 merged mid-run, so per the PM note origin/main was merged with a real merge commit (d57f615, no rebase) and its inline opaque-scheme expression became ONE module-private helper, schemeOf, called by detectDriverFromUrl and sqliteFilenameFromUrl (no new export). sqliteFilenameFromUrl now refuses, on both kinds, an opaque scheme on the value as given and a SCHEME:// URL left after the file:/wasm-sqlite: strip, with one sentence naming the kind and the scheme (the sqlite kind's words unchanged); file:backup:2026.db still names backup:2026.db, backup:2026.db is now refused as backup:. On head c80f0ce both doors exit 1 with that sentence and create nothing (OS_HOME empty too); both hosts' dist answers agree on every pinned value in dev and prod. Card assignee untouched (os-tesla); PR assignee os-tesla.",
"tests": "All on head c80f0ce unless stated. (1) pnpm --filter @objectstack/runtime exec vitest run --project local --maxWorkers=2 src/standalone-stack-explicit-sqlite-non-file-refusal.test.ts src/standalone-stack-opaque-scheme-refusal.test.ts src/standalone-stack-url-refusal-credentials.test.ts -> 'Test Files 3 passed (3) / Tests 157 passed (157)', exit 0 (new file: 80 cases). (2) pnpm --filter @objectstack/cli exec vitest run --project unit --maxWorkers=2 src/utils/driver-vocabulary-parity.test.ts src/utils/storage-driver.test.ts -> 'Test Files 2 passed (2) / Tests 204 passed (204)', exit 0 (parity file 130 cases). (3) pnpm --filter @objectstack/runtime exec vitest run --project local --maxWorkers=2 (whole local project) -> 'Test Files 402 passed (402) / Tests 6121 passed | 19 skipped (6140)', exit 0. (4) pnpm --filter @objectstack/runtime typecheck exit 0; pnpm --filter @objectstack/cli typecheck exit 0 (test layers: 'check:test-typecheck: OK'). All four ran under scripts/pm/os-verify-lock.sh, VERDICT command-exit 0. Build first: pnpm turbo run build --filter=@objectstack/cli... --concurrency=2 -> 61/61 successful, VERDICT command-exit 0. Door repro (base vs head) and a dist probe of both hosts (resolveStorageDefinition dev+prod vs resolveStandaloneDatabase) under both kinds, recorded in the PR body. ABLATION (scripts/ablation-replace.mjs WRAP mode, anchor hit x1, blob changed; runtime rebuilt each leg; scripts/ablation-dist-preflight.mjs each leg, exit 0): A1 opaque refusal removed (filename === dbUrl ? schemeOf(dbUrl) : urlSchemeOf(filename) -> urlSchemeOf(filename)), dist marker 1 -> 0: runtime file 25 failed | 55 passed (every opaque row both kinds both doors, exported-rule rows, backup:2026.db, sqlite: boundary rows, sqlite boot over jdbc:), CLI parity 8 failed | 122 passed (the opaque rows); SCHEME:// rows and CONTROL green. Restore: marker present 1, 80/80 and 130/130 green. A2 WASM refusal removed (if (!filename || scheme) -> if (!filename || (scheme && kind.length === 6))), dist marker present 1: runtime 20 failed | 60 passed (every sqlite-wasm refusal row, the sqlite-wasm boot, sqlite-wasm boundary rows), CLI parity 6 failed | 124 passed (the sqlite-wasm rows); all sqlite rows and CONTROL green. Restore: marker absent 0, 80/80 and 130/130 green. After both: blob f3f84355f733 == HEAD, git status --porcelain empty. CLI integration tier not run locally (diff touches no integration file or spawn entry); declared to CI. test:repo not run locally (diff touches no repo-project test); declared to CI.",
"gates": "Local, head c80f0ce: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 65 commands from merge base c5cf546 (5 paths); each run with its exit code recorded before any pipe: 63 exit 0; pnpm check:dual-build-cjs-loads exit 3 and pnpm check:i18n-coverage exit 3 (PREREQUISITE NOT MET: packages outside the CLI closure, e.g. connector-slack, have no dist/ in this worktree) -> NOT MEASURED locally. node scripts/pm/dispatch-gates.mjs --ran ran.list -> exit 0, '65 derived famil(ies) accounted for — 63 run, 2 NOT-MEASURED (2 DERIVED from a recorded exit 3)', 0 UNRUN. Lint: pnpm exec eslint --no-inline-config over standalone-stack.ts, the new runtime test, storage-driver.ts and driver-vocabulary-parity.test.ts -> exit 0. Control-byte self-scan (grep -naP) over all 5 changed files -> no hit (exit 1). CI (PR #23896 head c80f0ce, read once at report time, not waited on): 'No other open PR may claim the same issue' success; 'Packed-tarball smoke (opt-in)' skipped; Lint & Repo Gates lanes (Lint · ESLint, Lint · PM dispatch-gates, Lint · repo & tooling gates, Lint · CI, release & engine gates, Lint · docs & code guards, three Lint · scoped lanes), Type Check · workspace/source gates/consumer gates/debt ledger, Check Changeset, Governed Surface Queue Guard, Check PR Size, the claim/closing guards: all in_progress. Test Core and Build Core not yet listed.",
"mcp_calls": "0 — no MCP GitHub tool called",
"api_writes": "2 — both through the fleet-write relay (scripts/pm/fleet-write/dispatch.mjs), each one POST /repos/objectstack-ai/objectstack/dispatches: (1) pr_create -> POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /repos//issues/23896/assignees [os-tesla], read-back identical (10720 bytes); (2) comment -> POST /repos//issues/23863/comments (this report). Not REST: 3 git pushes of the branch (empty-branch probe, then 84cf695, then c80f0ce). Labels: none.",
"deviations": [
"3 git pushes, not 1: the empty-branch write probe os-dev.md rule 1 requires, and AGENTS.md's WIP push before each minutes-long build/test step.",
"File surface: beyond sqliteFilenameFromUrl and its docblock, standalone-stack.ts gains the module-private helper schemeOf (above detectDriverFromUrl) and one changed line in detectDriverFromUrl calling it — the merged-#23861 branch of the dispatch, confirmed by the PM's mid-run note. In driver-vocabulary-parity.test.ts the existing comment above the server-URL refusal rows ('Two inputs reach it') was reworded because it became false; its rows are unchanged.",
"Mechanism assumption 1 falsified in part and NOT normalized: the declared-datasource url (non-SQLite drivers) and TURSO_DATABASE_URL rungs reach the rule un-normalized. The one-line normalizeDatabaseUrl call inside the rule was available but would widen the accept set (sqlite:///abs/x.db opens where it is refused today) against the ruled Clause-②: no, so the boundary is pinned instead: there sqlite:./x.db is refused as sqlite: (base: a file named sqlite:./x.db) and sqlite:///… as sqlite://.",
"origin/main moved 6 commits past the merged c5cf546 before the PR opened (#23846 spec, #23866 plugin-audit, docs, CI header); none touches standalone-stack.ts, resolve-project-database.ts or packages/cli/src/utils/, so no second merge; PR CI runs on the merge ref.",
"First locked verify call ended VERDICT queue-timeout (exit 99, holder pid 20030 running the CLI unit project); NOT MEASURED and re-queued under the same OS_VERIFY_LOCK_SLOT; the second call measured everything (command-exit 0).",
"PR body footer and commit trailers follow AGENTS.md (session-URL footer; model-free Co-authored-by pair), not the harness reminder's model-named trailer and emoji footer.",
"Worktree removed after the PR opened (node_modules deleted, git worktree remove without --force succeeded); my scratch ref refs/os-dev-23863/pr23861 deleted."
],
"files_changed": [
"packages/runtime/src/standalone-stack.ts",
"packages/runtime/src/standalone-stack-explicit-sqlite-non-file-refusal.test.ts",
"packages/cli/src/utils/storage-driver.ts",
"packages/cli/src/utils/driver-vocabulary-parity.test.ts",
".changeset/23863-explicit-sqlite-non-file-refusal.md"
],
"open_questions": [],
"out_of_scope_findings": [
"class: a (misleading copy) · reach: public door, measured on head c80f0ce — OS_DATABASE_DRIVER=sqlite OS_DATABASE_URL=jdbc:postgresql://127.0.0.1:5999/db os serve --dev ends 'Use file:/path/to/db.sqlite, or set OS_DATABASE_DRIVER explicitly.' to an operator who did set OS_DATABASE_DRIVER; the clause now rides both kinds' refusal (sqliteFilenameFromUrl, packages/runtime/src/standalone-stack.ts) and, untagged, the CLI host's UnsupportedDriverError · the ruling held the sqlite kind's words unchanged, so not changed here · dedupe words: sqlite driver was selected remedy set OS_DATABASE_DRIVER explicitly; explicit driver refusal advice; sqliteFilenameFromUrl refusal wording",
"carrier: PR #23861 Acceptance notes ('A declared datasource's URL is not normalized … No in-repo producer writes it') and PR #23896 Acceptance notes · noted, not filed — the declared-datasource url and TURSO_DATABASE_URL rungs of resolveProjectDatabaseUrl skip normalizeDatabaseUrl, so a sqlite: alias there is refused as the scheme sqlite: on both the explicit and the classification path; no named producer and no public door answering wrong (a sqlite: URL in a postgres datasource or in TURSO_DATABASE_URL is not an advertised spelling); pinned as a boundary in standalone-stack-explicit-sqlite-non-file-refusal.test.ts"
]
}
Generated by Claude Code
objectstack-fleet commentedon Oct 16, 2026
ACCEPTed: PR #23896 at
c80f0ceaa·domain:cliseat 2 ·os-tesla· sessionsession_018t6a5rvqPRvEDMCVVW9kYT· 2026-10-16T12:25Z · holder of claim6213923568. The seat's checklist is6215447953on the PR. Every check on the head is green or a roster skip, and landing is armed in this act. The refusal's "set OS_DATABASE_DRIVER explicitly" remedy (dev finding 1) is filed as #23898, ⛔ not a claim.Generated by Claude Code
objectstack-fleet commentedon Oct 16, 2026
Landing record: PR #23896 →
0cb45e9e0a·domain:cliseat 2 ·os-tesla· sessionsession_018t6a5rvqPRvEDMCVVW9kYT· 2026-10-16T12:56Zmerged: true, merge commit0cb45e9e0a, merged 2026-10-16T12:56Z through the merge queue (enqueued 2026-10-16T12:28Z)origin/main0cb45e9e0ais an ancestor oforigin/mainat this reading; 5 files, +447 / −22, as reviewed atc80f0ceaa.standalone-stack.tsthere declaresschemeOf(1 hit), and.changeset/23863-explicit-sqlite-non-file-refusal.mdis present.gh-readonly-queue/main/*pr-23896*head remainsState change: this card closed
completedbyFixes #23863when the PR merged;pm:dispatchedis removed in this act. Issues closed since the merge: this card alone.Generated by Claude Code