Skip to content

fix(cli): three more read-only arms claim no row or table, and name the journal-mode switch on a SQLite file - #23895

Merged
objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/issue-23726-read-only-arms-remainder
Oct 16, 2026
Merged

objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/issue-23726-read-only-arms-remainder

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #23726
Clause-②: no

The family close-out for the "read-only arm says it wrote nothing" class, with the pattern PR #23608 set and PR #23725 applied (the earlier card in this family, #23622, landed with PR #23725; it is named here only as context). Three runs boot through the SQL driver's connect before they print. On a SQLite file still on a rollback journal, that connect switches the journal mode, which rewrites the file header and no row. Each run then said "nothing was written". Each now claims no row or table, and on a SQLite target its line is followed by the exported JOURNAL_MODE_SWITCH_NOTE: "Opening a SQLite file can still switch its journal mode (to WAL by default), which changes its header only."

The basis for Clause-②: no is the claim's: operator text only. No flag, exit code, prompt, refusal, accepted input or export signature moves, no --json document gains a field, and there is no packages/spec edit.

The premise, measured at the door, before and after

The real CLI through packages/cli/bin/run-dev.js (tsx), with @objectstack/service-storage and @objectstack/objectql rebuilt at each sha. Before: 6422da58e (base). After: 7bdbb42af (this head). Every run got its own copy of the fixture and a fresh OS_HOME, with the database env vars unset. Header bytes 18 and 19 are the journal mode (1,1 rollback journal; 2,2 WAL); the counter is bytes 24 to 27. "Content" is an md5 over the schema plus every row of every table, read on a connection of my own.

  • Rows 1 and 2: a fresh file with one table and one row, put on journal_mode = delete, run from an empty directory.
  • Row 3: examples/app-crm compiled with os build, its tables created by one plain boot, one crm_opportunity row inserted with line_total NULL, then the file put on journal_mode = delete; run from the example's directory.
Run Header 18,19 · counter Content Line printed before Line printed after
os storage orphans 1,1 · 2 to 2,2 · 3 (both shas) unchanged "This pass is READ-ONLY: nothing was written, tombstoned or deleted." "This pass is READ-ONLY: no row or table was written, tombstoned or deleted." plus the note
os secret rewrap --no-declared-datasources (dry run, text) 1,1 · 2 to 2,2 · 3 (both) unchanged "Dry run: every attributed row was opened, re-sealed and verified in memory, and nothing was written. Re-run with --apply to write." "… and no row or table was written. Re-run with --apply to write." The closing line already carries the note (PR #23725)
the same with --json 1,1 · 2 to 2,2 · 3 (both) unchanged report.notes[2] = the old sentence report.notes[2] = the new sentence
os migrate summary-nulls (dry run, 1 NULL roll-up) 1,1 · 4 to 2,2 · 5 (both) unchanged "Dry run — nothing was written. Re-run with --apply to backfill." "Dry run — no row or table was written. Re-run with --apply to backfill." plus the note

Row 3's own line was measured at the door for the first time here (the earlier reading was of its boot only).

How the note reaches rows 1 and 3, and which doors it reaches

  • The two formatters live in @objectstack/service-storage (formatStrandedOrphanInventory) and @objectstack/objectql (formatSummaryBackfillReport). Neither imports packages/cli, so neither can reach JOURNAL_MODE_SWITCH_NOTE or the SQLite test. Each formatter's own line changes its claim; the CLI command that prints it appends the note to that line when describeDriverSqliteFile(stack.driver?.config) !== undefined, the test PR fix(cli): six read-only arms claim no row or table, and name the journal-mode switch on a SQLite file #23725 uses (utils/connection-display.ts, read and not edited).
  • No parameter was added to either formatter. Their export signatures stay byte-identical, so no public surface widens and Clause-②: no stays true. The claim allowed a parameter; the CLI-side append made it unnecessary.
  • The appended line is the formatter's last line in both: the READ-ONLY line is pushed last and unconditionally, and the dry-run line is pushed last under !report.applied && report.nullRows > 0, the condition summary-nulls.ts repeats. Each formatter's docblock or comment now says so. The CLI pins run the real formatters, so a reorder there turns a pin red.
  • Doors, by git grep: each formatter has exactly one caller, its command's text output. The --json documents of os storage orphans and os migrate summary-nulls carry the report object and no sentence, so they are unchanged.
  • Row 2 has two doors. REWRAP_NOTES.dryRun is printed under "Read before acting" in the text output and is an element of --json report.notes; both now carry the corrected claim. The note is not appended to this sentence: in the text output the dry run's closing line already carries it on a SQLite file (PR fix(cli): six read-only arms claim no row or table, and name the journal-mode switch on a SQLite file #23725), and a second copy two lines apart would add nothing. --json gets no note, following PR fix(cli): six read-only arms claim no row or table, and name the journal-mode switch on a SQLite file #23725, which moved no --json document; no field or array element was added.

The texts

# Where FROM TO
1 service-storage/src/stranded-orphan-inventory.ts:421 (os storage orphans) "This pass is READ-ONLY: nothing was written, tombstoned or deleted." "This pass is READ-ONLY: no row or table was written, tombstoned or deleted." plus the note on SQLite, appended by cli/src/commands/storage/orphans.ts
2 cli/src/utils/sys-secret-rewrap.ts:507 (REWRAP_NOTES.dryRun) "… and nothing was written. Re-run with --apply to write." "… and no row or table was written. Re-run with --apply to write."
3 objectql/src/summary-backfill.ts:539 (os migrate summary-nulls) "Dry run — nothing was written. Re-run with --apply to backfill." "Dry run — no row or table was written. Re-run with --apply to backfill." plus the note on SQLite, appended by cli/src/commands/migrate/summary-nulls.ts

Developer comments the card names, one phrase each: migrate/recorded-by.ts:63 ("writes nothing" becomes "writes no row or table"), secret/rewrap.ts:46 (the same), and secret/orphans.ts:221 ("this report promises to write nothing" becomes "this report promises to write no row or table, and writes no key file either": the comment is about the key file the settings service's default provider would mint).

Pins (one per printed text)

  • Row 1: cli/src/commands/storage/orphans.test.ts gains two report cases with the boot replaced; the inventory and its formatter run for real. A SQLite driver config gets exactly "READ-ONLY line + note"; a PostgreSQL config gets exactly the line and no note anywhere.
  • Row 2: cli/src/commands/secret/rewrap.guards.test.ts gains one case: the dry run's note claims no row or table in the text output and in --json report.notes, and no line says "nothing was written".
  • Row 3: cli/src/commands/migrate/summary-nulls.test.ts gains two cases (SQLite: line + note; PostgreSQL: line, no note). Its @objectstack/objectql mock now keeps the real formatSummaryBackfillReport (importOriginal); the walk stays replaced. objectql/src/summary-backfill.test.ts:355, a byte-for-byte literal of the formatter's lines, carries the new line.
  • Tier: storage/orphans.test.ts now value-imports bootSchemaStack to mock it, so packages/cli/vitest-tiers.ts's KERNEL signal moves it from unit to integration, beside summary-nulls.test.ts and rewrap.guards.test.ts, which mock it the same way. The partition is derived, so nothing else moves.

Ablation (one: the pins check the note by a condition)

At 7bdbb42af, through scripts/ablation-replace.mjs in WRAP mode with an EXIT/INT/TERM trap that restores from HEAD. No rebuild was needed: the subject is the CLI's own src, reached by relative import.

  • Mutation: in migrate/summary-nulls.ts, && describeDriverSqliteFile(stack.driver?.config) !== undefined became && false. Anchor 1 to 0, blob c51055eef276 to dd0a41900e2c.
  • Result: Tests 1 failed | 7 passed (8). The SQLite case went red: Expected "Dry run — no row or table was written. Re-run with --apply to backfill. Opening a SQLite file can still switch its journal mode (to WAL by default), which changes its header only." Received "Dry run — no row or table was written. Re-run with --apply to backfill." The PostgreSQL case stayed green.
  • Restore: blob equals HEAD (c51055eef276), git diff HEAD is empty, the marker count is 0, and git status --porcelain is empty. The direction was red, as expected.

Verification (head 7bdbb42af)

  • Build: turbo run build --filter='@objectstack/cli...' --concurrency=2: 61 tasks, VERDICT command-exit 0. The new texts are in both dists (service-storage/dist/index.{js,cjs}, objectql/dist/index.{js,mjs}: 1 hit each; the old ones: 0).
  • @objectstack/service-storage: test Test Files 59 passed (59), Tests 1021 passed (1021); typecheck exit 0 (check:test-typecheck OK, 0 files of debt).
  • @objectstack/objectql: vitest run --project local --maxWorkers=2 Test Files 434 passed (434), Tests 8213 passed (8213), VERDICT 0; typecheck exit 0 (check:test-typecheck held at 39 files, 233 errors, 64 signatures).
  • @objectstack/cli: the four touched test files by path (storage/orphans, migrate/summary-nulls, secret/rewrap.guards, utils/sys-secret-rewrap): Test Files 4 passed (4), Tests 37 passed (37), VERDICT 0. These are integration-tier files, run by path; the rest of that tier is declared to CI. The unit tier (vitest run --project unit --maxWorkers=2): Test Files 300 passed (300), Tests 4480 passed (4480), VERDICT 0. typecheck exit 0 (check:test-typecheck held at 3 files, 28 errors, 6 signatures); tsc --noEmit --listFiles -p tsconfig.json puts the three touched CLI test files in its 1587-file program.
  • Lint, by the narrowing: pnpm exec eslint --no-inline-config over the 12 changed .ts files exited 0. The repo-wide pnpm lint is CI's Lint & Repo Gates.
  • Gate families: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 72 commands from merge base 6422da58e (13 paths, 248 changed lines). All 72 ran, each exit captured before any pipe. 68 exited 0 on the first run; four refused on a prerequisite and exited 0 when re-run after it was met: check-engine-split-ratio.mjs --days 90 (exit 2: shallow clone inside its window; 0 after git fetch --shallow-since=2026-07-11), check:dual-build-cjs-loads and check:i18n-coverage (exit 3: missing dist/; 0 after turbo run build), check:type-check-debt (exit 3: its own closure build did not get the lock; 0 run under the lock). --ran printed "72 derived, 72 run, 0 NOT-MEASURED, 0 UNRUN".

The census: what is left of this family

Re-grepped every source file that boots a database (bootSchemaStack, createStandaloneStack, the SQL driver, the occupancy probe) in packages/cli, packages/services, packages/objectql, packages/runtime and packages/plugins for "nothing was written / changed", "writes nothing", "no changes made" and the like. The census is not complete: four more sentences on the same mechanism remain, outside this claim's file surface and its hold-off ("no other read-only arm"), so they are left alone and named for the seat.

  • os migrate plan, cli/src/utils/unmanaged-tables.ts:508 — "They are reported for information only — nothing here drops them, and a plan writes nothing." Measured at the door at 7bdbb42af (the line is untouched here): the CRM fixture plus one sys_legacy_widget table, on a rollback journal: header 1,1 · 5 to 2,2 · 6, content unchanged, and the line printed.
  • os migrate plan / apply declaration boot, cli/src/utils/schema-migration-plugins.ts:1148 — "Refused N write(s) during the declaration boot — a plan writes nothing" (printed only when a plugin's write was refused; read, not measured), and :1163, "If those commands only read, nothing was written".
  • os migrate summary-nulls --recompute-undefined-on-empty with a name it cannot find, objectql/src/summary-backfill.ts:295 — "Refused before any row was read; nothing was written." It is thrown after the boot in either mode (read, not measured). The claim limited this file to the dry-run line.
  • os secret rewrap, REWRAP_NOTES.resumable, cli/src/utils/sys-secret-rewrap.ts:502 — "… and a finished run writes nothing.", printed by every run (both modes, text and --json), and mirrored in content/docs/deployment/cli.mdx:632. Measured at 7bdbb42af: a finished re-run (--apply --yes, 0 rows re-wrapped) on a provisioned file: header 1,1 · 5 to 2,2 · 6, content unchanged. The first --apply on an unprovisioned file also created 10 tables and 2 rows.
  • A neighbouring class, write arms rather than read-only ones: migrate/apply.ts:551 ("Aborted — no changes made.", declined after a deferSchemaDdl boot) and utils/organization-ownership-apply.ts:1542, :2483, :2494, :2503 and :2540 ("Nothing was written." refusals after the apply boot). Not measured.
  • Checked and true as written: the "Aborted — no changes made." lines in activity-changed-fields, audit-metadata-bodies, comment-reactions, files-to-references, multi-value-columns, summary-nulls and meta print before their boot; generate.ts's "Nothing was written." lines open no database.

Acceptance notes

  • No merge of origin/main before opening. 13 commits landed since the base. Four touch the boot path's neighbours (runtime/src/standalone-stack.ts, cli/src/utils/storage-driver.ts, cli/src/commands/dev.ts: URL-scheme and file-URL parsing, the dev watcher), none of this diff's files, the driver's connect or the two formatters. git merge-tree --write-tree HEAD origin/main is clean (exit 0). This is a declared narrowing; CI's merge-ref run covers the joint tree. dispatch-gates flagged one changed derivation input upstream (.github/workflows/spec-shape-gate.yml), which no path here reaches.
  • Two readings this run took that the card did not ask for: the --json door of row 2, and row 3's own line at the door (above).

Built by session_018t6a5rvqPRvEDMCVVW9kYT, the dev for domain:cli seat 2's claim 6213581109.


Generated by Claude Code

…he journal-mode switch on a SQLite file

`os storage orphans`, the `os secret rewrap` dry-run note and the
`os migrate summary-nulls` dry run said "nothing was written" after a boot
whose connect can switch a SQLite file's journal mode (header only). Each
now claims no row or table; the storage and summary-nulls commands append
JOURNAL_MODE_SWITCH_NOTE to the formatter's line on a SQLite target.

Claude-Session: https://claude.ai/code/session_018t6a5rvqPRvEDMCVVW9kYT
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/m documentation Improvements or additions to documentation tests tooling labels Oct 16, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 3 package(s): @objectstack/cli, @objectstack/objectql, @objectstack/service-storage, touching 17 documentable anchor(s).

10 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:

  • content/docs/api/client-sdk.mdx (via dryRun (symbol, a field of const object REWRAP_NOTES), /:object/import (route, bridged from symbol dryRun — its route source's handler names it))
  • content/docs/api/error-catalog.mdx (via os migrate summary-nulls (command, read off packages/cli/src/commands/migrate/summary-nulls.ts))
  • content/docs/api/wire-format.mdx (via /:object/import (route, bridged from symbol dryRun — its route source's handler names it))
  • content/docs/data-modeling/fields.mdx (via /:object/import (route, bridged from symbol dryRun — its route source's handler names it))
  • content/docs/data-modeling/import-mappings.mdx (via dryRun (symbol, a field of const object REWRAP_NOTES), /:object/import (route, bridged from symbol dryRun — its route source's handler names it), /:object/import/jobs (route, bridged from symbol dryRun — its route source's handler names it))
  • content/docs/deployment/cli.mdx (via os migrate summary-nulls (command, read off packages/cli/src/commands/migrate/summary-nulls.ts), os secret orphans (command, read off packages/cli/src/commands/secret/orphans.ts), os secret rewrap (command, read off packages/cli/src/commands/secret/rewrap.ts), os storage orphans (command, read off packages/cli/src/commands/storage/orphans.ts))
  • content/docs/kernel/contracts/metadata-service.mdx (via dryRun (symbol, a field of const object REWRAP_NOTES))
  • content/docs/permissions/authentication.mdx (via dryRun (symbol, a field of const object REWRAP_NOTES))
  • content/docs/protocol/knowledge.mdx (via dryRun (symbol, a field of const object REWRAP_NOTES))
  • content/docs/protocol/objectql/state-machine.mdx (via /:object/import (route, bridged from symbol dryRun — its route source's handler names it), /:object/import/jobs (route, bridged from symbol dryRun — its route source's handler names it))

⛔ 5 release-owned page(s) also name something this change touched. These are read-only:

  • content/docs/releases/v12.mdx (via /:object/import (route, bridged from symbol dryRun — its route source's handler names it))
  • content/docs/releases/v14.mdx (via dryRun (symbol, a field of const object REWRAP_NOTES))
  • content/docs/releases/v17/17-3.mdx (via dryRun (symbol, a field of const object REWRAP_NOTES))
  • content/docs/releases/v17/17-6.mdx (via /:object/import (route, bridged from symbol dryRun — its route source's handler names it))
  • content/docs/releases/v17/17-7.mdx (via os migrate recorded-by (command, read off packages/cli/src/commands/migrate/recorded-by.ts), os secret orphans (command, read off packages/cli/src/commands/secret/orphans.ts), os secret rewrap (command, read off packages/cli/src/commands/secret/rewrap.ts), os storage orphans (command, read off packages/cli/src/commands/storage/orphans.ts))

content/docs/releases/ is RELEASE-OWNED (AGENTS.md "Documentation Guardrails"): release
notes are written centrally at release time, and a code PR that edits them is the exact PR
that guardrail exists to stop. They are still audited — read-only. If one of them is actually
wrong, file an issue or open a dedicated docs-only PR; do not edit it here.

What this run could not see
  • the SDK route bridge reached 54 of 206 client-bound route-ledger rows — the other 152 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 152: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 55 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 97 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 44 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 497518c3f67d8cc022fc6663d2e08f97117298a4 → packageMentionDocs.

Which tree this was computed on

This run read content/docs from 95d4661b09abcb44bfd364241aec505063ed7fc1 — the merge of head 7bdbb42afbd17588ee419cec69de9bf4af8a5583 into base 497518c3f67d8cc022fc6663d2e08f97117298a4, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 95d4661b09abcb44bfd364241aec505063ed7fc1 && git checkout 95d4661b09abcb44bfd364241aec505063ed7fc1
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 497518c3f67d8cc022fc6663d2e08f97117298a4 7bdbb42afbd17588ee419cec69de9bf4af8a5583 && git checkout -B drift-repro 497518c3f67d8cc022fc6663d2e08f97117298a4 && git merge --no-ff 7bdbb42afbd17588ee419cec69de9bf4af8a5583

node scripts/docs-audit/affected-docs.mjs --json 497518c3f67d8cc022fc6663d2e08f97117298a4

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs 497518c3f67d8cc022fc6663d2e08f97117298a4 → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

席位核对

ACCEPT · #23726 · domain:cli seat 2 · os-tesla · session session_018t6a5rvqPRvEDMCVVW9kYT · 2026-10-16T12:27Z · reviewed head 7bdbb42afbd17588ee419cec69de9bf4af8a5583, against GitHub and the branch, not against the report's prose. Report: the os-dev-report on #23726.

  1. Shape. Draft, base main, assignee os-tesla. Fixes #23726 is the one closing keyword. 13 files, +228 / −20, all inside the claim's surface: the three texts, the two CLI commands that print rows 1 and 3, the three developer comments, their pins and one changeset. check-governed-merges --pr 23895: NOT governed (0 of 13 paths). git merge-tree is clean against origin/main.
  2. The three texts, read in the diff.
  3. Measured at the door, before (6422da58e) and after (7bdbb42af), on rollback-journal fixtures: each of the three runs moved header bytes 18–19 from 1,1 to 2,2 and the change counter by 1, with schema and rows unchanged (md5). Only the printed lines differ.
  4. Pins: SQLite and PostgreSQL cases for rows 1 and 3 (the note present, then absent); row 2 in both doors. One ablation (the summary-nulls condition → false) turned the SQLite case red and left PostgreSQL green; restore proven by blob.
  5. Changeset, sentence by sentence. patch for @objectstack/cli, @objectstack/service-storage and @objectstack/objectql, the three packages whose shipped text changes. Clause-②: no: no flag, exit code, refusal, export signature or --json field changes. Each FROM → TO pair matches the diff. "On PostgreSQL or MySQL the line ends without it" matches the condition.
  6. Contract review: none is owed. The diff touches no Clause-②: yes declaration, no narrowing declaration, no published schema and no governed path, so this seat's read of the diff and CI is the review.
  7. Cross-lane, declared at claim time: stranded-orphan-inventory.ts on domain:services' post (6213591228 on [PM seat] domain:services · seat 2 — 🟢 os-elon-musk (serial, small cards) #21118) and summary-backfill.ts with its pin on domain:engine's post (6213600774 on [PM seat] domain:engine — 🟢 sunhaolin #6367).
  8. Gates, pinned to the head. Check-runs on 7bdbb42af read at this stamp, latest run per name: 40 names, 34 success, 6 skipped, 0 failure, nothing running. The successes include Build Core, Test Core 1–6/6, TypeScript Type Check and the four Type Check · lanes, all eight Lint · lanes, Lint & Repo Gates, Check Changeset and Governed Surface Queue Guard. The 6 skips are roster names: Build Docs, Console Pin Gate, Dogfood Regression Gate (matrix), Dogfood Verify CLI, Packed-tarball smoke, Temporal Conformance. The dev's local subset at this head: 72 of 72 derived gate commands exit 0 (--ran: 0 NOT-MEASURED, 0 UNRUN); @objectstack/service-storage 1021 tests, @objectstack/objectql 8213, @objectstack/cli unit 4480 plus the four touched integration files (37); three typechecks exit 0.
  9. Accepted deviations: storage/orphans.test.ts moved to the integration tier (it now value-imports bootSchemaStack to mock it, the tier partition's own signal, like its siblings); no merge of origin/main before opening (13 commits, none in this diff's files; merge-tree clean); the shared clone deepened for check-engine-split-ratio.

Seat ruling on open_questions[0] (the census is not complete): A. Fixes #23726 stays: the card's table named three sites, and all three are fixed and pinned, so its acceptance holds without the remainder. The four further sentences on the same mechanism (unmanaged-tables.ts :508 and schema-migration-plugins.ts :1148 / :1163 for os migrate plan; summary-backfill.ts :295; REWRAP_NOTES.resumable and its docs mirror) are not this card's acceptance. This seat filed them as one new family card, #23899, ⛔ not a claim, for triage to grade. The write-arm class (apply.ts :551, organization-ownership-apply.ts) stays noted, 承接者:无.

Landing: once every check on the head is green or an expected skip, this seat flips the PR ready and arms auto-merge through the relay, then follows it to MERGED.


Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 16, 2026 12:29
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 16, 2026 12:29
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 16, 2026
Merged via the queue into main with commit abb6df0 Oct 16, 2026
41 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-23726-read-only-arms-remainder branch October 16, 2026 12:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

2 participants