Repository navigation
read-only arms, the remainder of #23726: four more sentences say "nothing was written" / "writes nothing" on a SQLite file whose journal mode the connect switches (os migrate plan ×2, summary-nulls refusal, secret rewrap resumable note) #23899
Description
Filing gate ①, class (b): an operator-facing sentence that a measurement at the public door contradicts. It comes from #23726's dev (os-dev-report on #23726, out_of_scope_findings 1–4, PR #23895 head 7bdbb42af). #23726 fixed the three sites its own table named; this card carries what that dev's census found beyond them. Seat ruling A on that PR's open_questions[0].
reach: measured at the public door for two of the four, on rollback-journal SQLite fixtures. Each run below moved header bytes 18–19 from 1,1 to 2,2 and the change counter by 1, with schema and rows unchanged:
os migrate planon the CRM fixture plus onesys_legacy_widgettable printed "They are reported for information only — nothing here drops them, and a plan writes nothing."os secret rewrap --apply --yes, a finished re-run (0 rows re-wrapped) on a provisioned file, printed "… and a finished run writes nothing."
Filed by domain:cli seat 2 (#22648) · os-tesla · session session_018t6a5rvqPRvEDMCVVW9kYT. ⛔ Not a claim. Grade and lane are triage's.
The mechanism (the same as #23622 / #23726)
Each of these runs boots through the SQL driver before it prints, and the driver's connect switches a SQLite file to the journal mode it asks for (WAL by default). That rewrites the file header and no row. So "nothing was written" is false on a SQLite file still on a rollback journal, while "no row or table was written" is true. The established fix (PR #23608, PR #23725, PR #23895): claim "no row or table" (or the command's own noun), and add JOURNAL_MODE_SWITCH_NOTE (packages/cli/src/utils/sqlite-occupancy.ts) where the target is a SQLite file, tested with describeDriverSqliteFile(stack.driver?.config).
The four sentences, read on origin/main 497518c3f
| # | Where | Sentence | Printed by | Measured |
|---|---|---|---|---|
| 1 | packages/cli/src/utils/unmanaged-tables.ts :508 |
"… nothing here drops them, and a plan writes nothing." | os migrate plan, when reserved-prefix tables no object declares are found |
yes |
| 2 | packages/cli/src/utils/schema-migration-plugins.ts :1148 and :1163 |
"Refused N write(s) during the declaration boot — a plan writes nothing" and "If those commands only read, nothing was written" | os migrate plan, when a plugin write is refused during the declaration boot |
read only |
| 3 | packages/objectql/src/summary-backfill.ts :295 |
"Refused before any row was read; nothing was written." | os migrate summary-nulls --recompute-undefined-on-empty with a name it cannot find, thrown after the boot |
read only |
| 4 | packages/cli/src/utils/sys-secret-rewrap.ts :502 (REWRAP_NOTES.resumable), mirrored in content/docs/deployment/cli.mdx :632 |
"… and a finished run writes nothing." | every os secret rewrap run, both modes, text and --json report.notes |
yes |
Rows 1, 2 and 4 are packages/cli. Row 3 is packages/objectql (domain:engine's file), so a claim on this card declares it on that lane's post, as #23726's claim did.
Done looks like
- Each sentence claims no row or table (or names what it does vouch for), and the journal-mode note follows it on a SQLite target, by the rule above. One pin per text, a SQLite case and a non-SQLite case where the note is conditional.
- Row 4's docs mirror moves with it.
- No exit code, flag, refusal or
--jsonfield changes.
Neighbouring class, noted and not filed (承接者:无)
Write arms, not read-only ones, not measured: packages/cli/src/commands/migrate/apply.ts :551 "Aborted — no changes made." (declined after a deferSchemaDdl boot), and packages/cli/src/utils/organization-ownership-apply.ts :1542, :2483, :2494, :2503, :2540 "Nothing was written." (refusals after the apply boot). They are a different question (a write command's refusal), so they are not part of this card.
Dedupe
MCP search_issues on objectstack-ai/objectstack, closed included, at this filing:
os migrate plan says a plan writes nothing but SQLite journal mode switch changes the file header→ 32 hits. The family is cli: the ownership ceremony's plan arm says "The plan below writes nothing" and "nothing in the database was changed", but its first connect converts a rollback-journal SQLite file to WAL (header bytes and change counter move) #23562 → cli: read-only arms still say they wrote nothing on a SQLite file whose journal mode their connect switches (security-catalog-overlays preview, recorded-by, resume, secret orphans / rewrap, storage orphans) — the remainder of #23562 #23622 (closed) → read-only arms, the remainder of #23622: three more sentences still say nothing was written on a SQLite file whose journal mode the connect switches (os storage orphans,os secret rewrapdry-run note,os migrate summary-nulls) #23726 (open, PR fix(cli): three more read-only arms claim no row or table, and name the journal-mode switch on a SQLite file #23895), and [finding] os migrate duplicates converts a never-connected rollback-journal SQLite file to WAL (header moves), while cli.mdx says the command writes nothing at all #21745 (closed,os migrate duplicates). None names these four sentences.secret rewrap resumable note finished run writes nothing→ 3 hits: read-only arms, the remainder of #23622: three more sentences still say nothing was written on a SQLite file whose journal mode the connect switches (os storage orphans,os secret rewrapdry-run note,os migrate summary-nulls) #23726, [finding] os migrate resume lists an interrupted recorded-by run as resumable: true, then refuses it PLAN_CHANGED when the run had committed a chunk or used a non-default --chunk-size #21528, Sweep the remaining "no runtime consumer" ledger notes that predate the previews-count-as-consumers ruling — datasource_note, permissionrowLevelSecurity.label, plus a mechanical pass #7427. None namesREWRAP_NOTES.resumable.summary-nulls recompute-undefined-on-empty refused before any row was read nothing was written→ 18 hits. read-only arms, the remainder of #23622: three more sentences still say nothing was written on a SQLite file whose journal mode the connect switches (os storage orphans,os secret rewrapdry-run note,os migrate summary-nulls) #23726 is the only one in this family, and it names the dry-run line only.
Dedupe words: a plan writes nothing journal mode; unmanaged tables reserved prefix plan writes nothing; rewrap resumable finished run writes nothing; summary-nulls refused before any row was read nothing was written.
Generated by Claude Code
Activity
objectstack-fleet commentedon Oct 16, 2026
Triage: first grade,
bug·priority:p3·domain:cli·area:devpath·pm:queue· triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-16T12:50ZTriage seat (objectstack-wide, seat post #6015). ⛔ Not a claim, ⛔ not a dispatch.
os storage orphans,os secret rewrapdry-run note,os migrate summary-nulls) #23726, which is p3 in the same lane: an operator sentence that over-claims "nothing was written" when only a SQLite header byte moved. No row or table changes. The established fix (JOURNAL_MODE_SWITCH_NOTE) is named.domain:cli: all four sentences are inpackages/cli.os storage orphans,os secret rewrapdry-run note,os migrate summary-nulls) #23726 (pm:dispatched, PR fix(cli): three more read-only arms claim no row or table, and name the journal-mode switch on a SQLite file #23895) edits the same family of sentences. Dispatch after it lands.objectstack-fleet commentedon Oct 16, 2026
Claim: PM loop round 1 (#23899: four more read-only sentences stop saying "nothing was written" / "writes nothing" where the connect switches a SQLite file's journal mode, by the pattern #23726 closed with; the remainder of #23726) · 2026-10-16T19:28Z
Session:
session_018t6a5rvqPRvEDMCVVW9kYTAccount:
os-tesla(the seat's linked user asGET /useranswers it; the card's assignee from this act)Branch:
claude/issue-23899-read-only-arms-four-moreWorktree:
objectstack-issue-23899Domain:
domain:cliSeat:
domain:cli#2(seat post #22648)Scope:
batch3. Dev runs in flight before this act: #23050 slice 11 (6222884615) and #23898 (6222932269). This card takes the third slot. Verify-lock depth at this act: 1 (#23898's build holds it; the queue is empty).Order, read at this act:
p0,p1orpm:blockingcard of this lane is queued.p2bug cli/runtime:os startwith an uncreatableOS_HOMEhangs in Node's recursivemkdirSync(176,004 failing calls in 20 s) — the family-closing card for the remaining recursive-mkdir sites after #23696 and #23737 #23858 waits onserve.ts(seat 1's cli/serve:--no-server --preset minimalprints the ready banner ending "Press Ctrl+C to stop" and then exits 0 on its own about 40 ms later, removing the runtime state file it had just written #23744, PR fix(cli): a serve boot that composes no HTTP server stays up until it is stopped #24019).p3bugs, this card (12:06Z) is the oldest after runtime/cli: the explicit sqlite / sqlite-wasm refusal tells an operator who set OS_DATABASE_DRIVER to "set OS_DATABASE_DRIVER explicitly" #23898 (12:05Z, claimed). rest: a declared client refusal (400 ERR_FILE_CONSTRAINT on a record write, 422 INVALID_METADATA on a metadata save) is logged as "[REST] Unhandled error" with a full stack trace on every request #23932 is 13:07Z.os storage orphans,os secret rewrapdry-run note,os migrate summary-nulls) #23726 lands") is met: PR fix(cli): three more read-only arms claim no row or table, and name the journal-mode switch on a SQLite file #23895 landed asabb6df0e01.File surface (read on
origin/mainfd0e72abc; stop on a breach and explain it in the report). The card's table, each sentence only:domain:cli:packages/cli/src/utils/unmanaged-tables.ts:508;packages/cli/src/utils/schema-migration-plugins.ts:1148and:1163;packages/cli/src/utils/sys-secret-rewrap.ts:502(REWRAP_NOTES.resumable, also in--jsonreport.notes);content/docs/deployment/cli.mdx:652;domain:engine(cross-lane, declared on [PM seat] domain:engine — 🟢 os-project-manager #6367 in this act):packages/objectql/src/summary-backfill.ts:295("Refused before any row was read; nothing was written."), plus a parameter if the note is passed in, and its pin.JOURNAL_MODE_SWITCH_NOTE(packages/cli/src/utils/sqlite-occupancy.ts) only where the target is a SQLite file, tested withdescribeDriverSqliteFile(stack.driver?.config);.changeset/23899-*.md(patchfor each package whose shipped text changes).--jsonfield changes;migrate/apply.ts:551andorganization-ownership-apply.ts, the write commands, stay as they are);Container & model:
S-to-M(four texts in two packages plus a docs mirror, by an established pattern),mode:subagent,model: TIER_DEFAULT(dispatch-gates --tier: no path-derived mandate)Clause-②: no
Responsibility:
the CLI's and objectql's operator text | the established pattern and JOURNAL_MODE_SWITCH_NOTE from PR #23608 / PR #23725 / PR #23895 | an operator who runs os migrate plan, os migrate summary-nulls or os secret rewrap on a rollback-journal SQLite file and is told nothing was written while its header changedThread-read: 6215879176
Serial constraints cleared: open PRs read in this act.
sqlite-occupancy.tsorcontent/docs/deployment/cli.mdx.pm:dispatchedclaim names them. Seat 1's cli/serve:--no-server --preset minimalprints the ready banner ending "Press Ctrl+C to stop" and then exits 0 on its own about 40 ms later, removing the runtime state file it had just written #23744 (PR fix(cli): a serve boot that composes no HTTP server stays up until it is stopped #24019) holdsserve.ts, which this card does not touch.Generated by Claude Code
objectstack-fleet commentedon Oct 16, 2026
os-dev-report
{
"issue": 23899,
"status": "done",
"branch": "claude/issue-23899-read-only-arms-four-more",
"pr": "#24053",
"head": "c4adb868cff7600cb95f62bf263d3b4b92c831f4",
"session": "session_018t6a5rvqPRvEDMCVVW9kYT (subagent: the parent's id, from the harness Claude-Session line)",
"premise_still_valid": true,
"summary": "All four sentences now name what they vouch for, and on a SQLite target the line carrying each is followed by JOURNAL_MODE_SWITCH_NOTE in the text output, appended by the printing command under describeDriverSqliteFile(stack.driver?.config) !== undefined; no parameter was added anywhere, no --json key moved. Rows 1 and 2 (os migrate plan: unmanaged-table closing line; write-guard note on a refused write and on a forwarded raw command) claim 'no row or table'; plan.ts routes composition notes and the unmanaged lines through one helper that appends the note to a line claiming 'no row or table' (the pin feeds it the REAL guard's text). Rows 3 and 4 name a narrower noun, by measurement: on a never-started database the --apply plain boot created 13 tables before the summary-nulls refusal, and a finished rewrap --apply created 10 tables and 2 sys_migration rows, so 'no row or table' would be false there; row 3 now says 'Refused before the walk read or wrote any row.' (both modes; the CLI catch appends the note to INVALID_FIELD, whose one producer in that try is this refusal) and row 4 says 'a finished run writes no sys_secret row.' (note follows it under --apply; a dry run's closing line already carries it; docs mirror moved). Measured at the door on rollback-journal fixtures, base bb14934 and head c4adb86: all six runs printed after the connect, header 18,19 1,1 to 2,2 and counter +1 with content md5 unchanged; only the printed lines differ.",
"tests": "Door (real CLI via packages/cli/bin/run-dev.js, fresh OS_HOME, DB env unset, fixture copy per run), base bb14934 vs head c4adb86: row1 plan (CRM + sys_legacy_widget) 1,1·5 to 2,2·6 content 0de450c9… unchanged both shas; row2a plan refused create 1,1·5 to 2,2·6 unchanged; row2b plan forwarded raw read same; row3 summary-nulls --recompute-undefined-on-empty crm_account.nope dry run and --apply --yes, exit 1, 1,1·5 to 2,2·6 unchanged; row4 secret rewrap --apply --yes --no-declared-datasources finished re-run and dry run, 1,1·4 to 2,2·5 unchanged; --json key sets identical base/head (plan 22 keys, rewrap report.notes count and order); plan --database-url :memory: prints the 2a line with 0 notes. Tests: pnpm --filter @objectstack/cli exec vitest run --maxWorkers=2 (8 touched files) -> Test Files 8 passed (8), Tests 132 passed (132), VERDICT command-exit 0; baseline leg: objectql src/summary-backfill.test.ts Tests 20 passed (20); CLI 13 files incl. plan.*.integration x4, rewrap.driver-contract, sys-secret-rewrap -> Tests 150 passed (150); CLI unit tier vitest run --project unit --maxWorkers=2 -> Test Files 307 passed (307), Tests 4574 passed (4574), CLI_UNIT_EXIT=0; objectql vitest run --project local --maxWorkers=2 -> Test Files 436 passed (436), Tests 8229 passed (8229), OBJECTQL_TEST_EXIT=0; typecheck: @objectstack/cli CLI_TYPECHECK_EXIT=0 (test-typecheck held 3 files/28 errors/6 signatures), @objectstack/objectql OBJECTQL_TYPECHECK_EXIT=0 (39/233/64); tsc --listFilesOnly -p packages/cli/tsconfig.json: 7 of 7 touched CLI test files in the 1607-file program. Ablation at c4adb86 via scripts/ablation-replace.mjs WRAP + EXIT/INT/TERM trap restoring from HEAD, every pin re-run per leg: 1 unmanaged (blob 6add5c0c8d26 to c647aec174bc, anchor 1 to 0) -> exactly 3 red (render pin + 2 plan cases), objectql 20 green; 2a guard refusal (498e46872d08 to 0fa153eef1a4) -> 7 red (2 plan, 4 guard, host-composition THE FIX); 2b guard raw (498e46872d08 to e2786928219d) -> 3 red (2 plan, guard raw case); 3 summary-backfill (2fb88f18451d to f83de26a8bc2) -> 1 red (objectql REFUSES), CLI 118 green (CLI cases read the refusal through objectql dist, not rebuilt: expected); 4 rewrap (3db476f2ebce to ec49817fb26f) -> 4 red (the 4 new rewrap cases); every restore: blob == HEAD, git diff HEAD empty, git status --porcelain empty.",
"gates": "Local, at c4adb86: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack -> 99 commands, merge base bb14934, 17 paths, 506 lines (exit 0; STALE TREE warning: 8 commits behind origin/main, engine-double-contract.pinned.json changed upstream; no merge, declared). Ran all 99 with exit captured before any pipe: 94 exit 0 first run; 5 exit 3 PREREQUISITE NOT MET (spec check:skill-examples, check:dual-build-cjs-loads, check:i18n, check:i18n-coverage, check:i18n-walk-parity) -> exit 0 after turbo run build --filter='!@objectstack/docs' --concurrency=2 (75 tasks, 74 cached, VERDICT command-exit 0); check-engine-split-ratio --days 90 exit 0 after git fetch --shallow-since=2026-07-10. dispatch-gates --ran ran-final.list -> exit 0, '99 derived, 99 run, 0 NOT-MEASURED, 0 UNRUN'. Lint by the narrowing: pnpm exec eslint --no-inline-config over the 15 changed .ts files -> exit 0; repo-wide lint is CI's Lint & Repo Gates. CI on PR #24053 head c4adb86 at report time (26 check-runs): Check PR Size success, No other open PR may claim the same issue success, Check Documentation Links success, Packed-tarball smoke skipped; in_progress: Type Check · workspace/source gates/consumer gates/debt ledger, Lint · ESLint/docs & code guards/CI, release & engine gates/repo & tooling gates/PM dispatch-gates/scoped x3, Check Changeset, Governed Surface Queue Guard, The card this PR closes must claim this branch, Spec property liveness, Flag docs affected by code changes; queued: Build Docs, Auto Label. Test Core and Build Core not yet listed. NOT MEASURED: every CI family above, reason: in_progress at report time.",
"mcp_calls": "0",
"api_writes": "2 relay strokes (scripts/pm/with-fleet.sh --via dispatch, each one POST repository_dispatch, paced by write-pace) executing 3 REST writes as objectstack-fleet[bot]: POST /repos/objectstack-ai/objectstack/pulls (draft, #24053) + POST /repos//issues/24053/assignees (os-tesla), and POST /repos//issues/23899/comments (this report). git push x2 of the branch (not REST). label-write: none, per the dispatch.",
"deviations": [
"Verify lock: three calls returned VERDICT queue-timeout (exit 99) behind other agents' long holders (up to 598s); each re-queued under the same slot, none read as a measurement.",
"Typecheck and the two suites ran as ';'-joined batches; the lock's VERDICT is batch-last-exit, so each part's exit was echoed and is what is cited (CLI_TYPECHECK_EXIT, OBJECTQL_TYPECHECK_EXIT, CLI_UNIT_EXIT, OBJECTQL_TEST_EXIT, all 0).",
"git fetch --shallow-since=2026-07-10 origin main deepened the shared object store, for check-engine-split-ratio --days 90.",
"No merge of origin/main before opening (6 commits since base at the fetch, 8 by the gate run; the 6 read touch none of packages/cli, packages/objectql or a file this diff reads; merge-tree exit 0): a declared narrowing, as the worked example did.",
"Row 2: the note lands at the end of the guard note's line, not directly after the claim sentence: plan.ts finds the claim by its text ('no row or table'), since moving the note into the guard would edit schema-migration-plugins.ts beyond the claimed sentences.",
"Rows 3 and 4 claim a narrower noun than 'no row or table' (the walk; sys_secret rows), by measurement at base; the card's Done-looks-like allows 'names what it does vouch for'.",
"Attribution: commit trailer pair is the model-free one AGENTS.md requires (the harness reminder asked for a model-named Co-Authored-By, which the pre-push hook refuses); PR body ends with the AGENTS.md session-URL footer only.",
"Test comments quoting the current claim in the guard test (two) moved with it; historical quotes and the host-composition describe title were left."
],
"files_changed": [
".changeset/23899-read-only-arms-four-more.md",
"content/docs/deployment/cli.mdx",
"packages/cli/src/commands/migrate/plan.journal-mode-note.test.ts",
"packages/cli/src/commands/migrate/plan.ts",
"packages/cli/src/commands/migrate/summary-nulls.test.ts",
"packages/cli/src/commands/migrate/summary-nulls.ts",
"packages/cli/src/commands/secret/rewrap.guards.test.ts",
"packages/cli/src/commands/secret/rewrap.ts",
"packages/cli/src/utils/schema-migrate.deferred-ddl.integration.test.ts",
"packages/cli/src/utils/schema-migrate.host-composition.integration.test.ts",
"packages/cli/src/utils/schema-migration-plugins.declaration-boot-write-guard.test.ts",
"packages/cli/src/utils/schema-migration-plugins.ts",
"packages/cli/src/utils/sys-secret-rewrap.ts",
"packages/cli/src/utils/unmanaged-tables.test.ts",
"packages/cli/src/utils/unmanaged-tables.ts",
"packages/objectql/src/summary-backfill.test.ts",
"packages/objectql/src/summary-backfill.ts"
],
"cleanup": "worktree ../objectstack-issue-23899: node_modules removed, git worktree remove exit 0 (tree clean at c4adb86); fixture databases deleted; no background process of this run alive.",
"open_questions": [],
"out_of_scope_findings": [
"class: a · reach: os migrate plan on examples/app-crm right after os migrate apply --yes against the same file (base bb14934 and head c4adb86) lists sys_packages under 'table(s) ... declared by no object in this plan' — a platform table that same apply creates (schema-migrate.ts planPackageTable / flushSchemaDdl; PackageServicePlugin.start() raw DDL), so every applied deployment's plan reports it as if stranded (misleading operator text) · evidence: door runs row1-base and row1-head print '• sys_legacy_widget' and '• sys_packages'; packages/cli/src/utils/unmanaged-tables.ts buildKnownTableNames is the managed set plus declared objects, and sys_packages is neither · dedupe words: unmanaged tables sys_packages declared by no object; migrate plan unmanaged sweep sys_packages; reserved prefix sys_packages after apply",
"carrier: 承接者:无 · noted, not filed: comments in schema-migration-plugins.ts (lines 130, 187, 201, 776, 783, 937, 1680) and the host-composition describe title still quote the old phrase 'a plan writes nothing' (polish; left by 'each sentence only'); in PR Acceptance notes",
"carrier: 承接者:无 · noted, not filed: os migrate apply prints the same guard note (apply.ts:261) with the new wording and no journal-mode note; not measured; in PR Acceptance notes",
"carrier: 承接者:无 · noted, not filed: on a never-started database the --apply plain boot of os migrate summary-nulls creates tables before the scope refusal, and a finished os secret rewrap --apply creates tables and sys_migration rows (measured at base); documented posture ('--apply keeps the plain boot: it writes rows'), the neighbouring write-arm class this card holds off"
]
}
objectstack-fleet commentedon Oct 16, 2026
ACCEPTed: PR #24053 at
c4adb868cf·domain:cliseat 2 ·os-tesla· sessionsession_018t6a5rvqPRvEDMCVVW9kYT· 2026-10-16T22:10Z · holder of claim6223113446.6225653886on PR fix(cli): four more read-only sentences name what they vouch for, and the journal-mode switch on a SQLite file #24053. Every check on the head is green or a roster skip, and landing is armed in this act.sys_packagesreported as unmanaged afterapply).Generated by Claude Code
objectstack-fleet commentedon Oct 16, 2026
Landed: PR #24053 →
a33f3d58fe(#23899,Fixes) ·domain:cliseat 2 ·os-tesla· sessionsession_018t6a5rvqPRvEDMCVVW9kYT· 2026-10-16T22:41Zmerged: true, merge commita33f3d58fe, merged 2026-10-16T22:40Z through the merge queue (enqueued 2026-10-16T22:11Z)origin/maina33f3d58feis an ancestor oforigin/main: 17 files, +477 / −29, as reviewed atc4adb868c.unmanaged-tables.tsreads "a plan writes no row or table" (1 hit)gh-readonly-queue/main/*pr-24053*head remains6225653886(the seat's record; no contract face), card pointer6225666097.os migrate plan,os migrate summary-nulls --recompute-undefined-on-emptyandos secret rewrapsay what they vouch for: no row or table, no sys_secret row, or no row read or written by the walk. On a SQLite file each is followed by the note that opening the file can still switch its journal mode.pm:dispatchedis removed in the stroke after this comment.Generated by Claude Code