Repository navigation
cli: a plain os dev (standalone stack) never runs autoMigrate 'safe' — the documented dev self-heal applies only to host configs, while plan and drift lines say "auto-applied at boot" #21733
Description
Activity
objectstack-fleet commented
on Oct 4, 2026 ContributorAuthorMore actionsTriage: first grade —
bug·priority:p2·domain:cli·area:devpath·pm:queue. One dev-modeautoMigrate: 'safe'rule for both boot pathsTriage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-04T12:13Z. ⛔ Not a claim, ⛔ not a dispatch.Why p2. The verifier judged it medium.
- A plain
os devon a non-host config never self-heals drift thatcli.mdx(about:966) promises it repairs "automatically on restart". - The CLI's own plan and drift lines say "auto-applied at boot" while nothing is applied. The tool states a repair that does not happen.
- This is the first-run road: every scaffold without a
plugins[]host goes this way, and the showcase does not, which is why it hid.
Routing: the standalone stack (
packages/runtime/src/standalone-stack.tsabout:745–:760, reached fromcli/src/commands/serve.ts), sodomain:cli.Direction:
- The dev-mode
autoMigrate: 'safe'decision lives in one place, and both the host-config path and the standalone path read it. Today it is injected only bystorage-driver.ts(about:370), which the standalone path skips because a datasource plugin is present (stack-collections.tsabout:276). - ⛔ No second copy of the condition in
standalone-stack.ts. - The telemetry datasource's
'safe'(serve.tsabout:3283) follows the same rule. The claim states whether the standalone path should have a telemetry datasource at all, which is the card's side observation. - The drift and plan wording stays as it is, because it becomes true.
Pins:
- the card's staged non-NULL-safe unique index comes back NULL-safe after a plain
os devrestart on a no-plugins scaffold; - a production-mode boot does not auto-migrate;
- the host-config path is unchanged.
Generated by Claude Code
- A plain
- addedarea:devpathThe road — create, dev, verify, publish/install, connect an agent, iterateThe road — create, dev, verify, publish/install, connect an agent, iteratebugSomething isn't workingSomething isn't workingpriority:p2Medium: important, M3Medium: important, M3
on Oct 4, 2026 objectstack-fleet commented
on Oct 4, 2026 ContributorAuthorMore actionsClaim: PM loop round 1 (serial: the seat's only active dispatch)
Session:session_016GiHYRmLSNWTfbX9gVQkpz
Account:os-bill(the seat's linked user asget_meanswers it; the card's assignee)
Branch:claude/issue-21733-standalone-dev-automigrate
Worktree:objectstack-issue-21733
Domain:domain:cli
Seat:domain:cli#1
File surface, per triage5979802093(one dev-modeautoMigrate: 'safe'rule, read by both boot paths; ⛔ no second copy of the condition instandalone-stack.ts):packages/runtime/src/standalone-stack.ts: the default datasource'sdriverConfig(around:690–:775). It reads the same devautoMigratedecision the host path reads.packages/cli/src/utils/storage-driver.ts: today the only home of that decision (around:370). It moves to one place both paths read, or is read from where it already is. The dev measures which.packages/cli/src/commands/serve.ts: the standalone branch (around:2763–:2785), and the telemetry provision (around:3260–:3300), which today runs only on the host path.- The card's side observation, answered from governing text. The standalone path gets the telemetry datasource under the same rule.
content/docs/deployment/cli.mdx(around:245–:251) says: "With a file-backed SQLite database, dev also provisions a sibling<db>.telemetry.<ext>file registered as thetelemetrydatasource". It draws no host-or-standalone line.- ADR-0057 §3.6's rationale, keeping telemetry growth out of the business DB, applies to both paths.
- Neither
standalone-stack.tsnor its tests carry a deliberate omission. - Read through
resolveTelemetryDbPath(packages/cli/src/utils/telemetry-datasource.ts), with its'safe'. ⛔ No second copy of the path rule. - If the dev measures a deliberate omission, that is a falsified premise: stop and report, and the seat brings it back to the box.
- Pins:
- triage's three: the staged non-NULL-safe unique index comes back NULL-safe after a plain
os devrestart on a no-plugins scaffold; a production-mode boot does not auto-migrate; the host-config path is unchanged. - A one-shot CLI boot never auto-applies.
os migrate plan, which boots throughcreateStandaloneStackfromschema-migrate.ts, stays write-free on the card's staged DB, including underNODE_ENV=development. - A standalone dev boot on a file-backed SQLite primary provisions the telemetry sibling, and
OS_TELEMETRY_DB=0opts out.
- triage's three: the staged non-NULL-safe unique index comes back NULL-safe after a plain
.changeset/.
⛔ No
packages/services/service-datasourceedit unless measurement puts the one decision there. In that case, stop and report: the seat files the cross-lane declaration first. ⛔ Nopackages/specpath. ⛔ No change to the drift or plan wording: it becomes true. ⛔ No change to what'safe'admits. (stop on breach; explain in the report)
Container & model:M,mode:subagent,model: default (opus)build.dispatch-gates --tiermandates nothing by path (none of the 3 declared globs).
Clause-②: yes (widening)
Re-declared 2026-10-04T17:07Z at review (REWORK5982402012). The route added two exports to@objectstack/runtime's only entry:devAutoMigrateConfigandDevAutoMigrateConfig. That enlarges a published surface, sominoron runtime and a contract review atCONTRACT_REVIEW_TIER. No accept set moves, and no schema or config key changes. The line first read:no— boot behaviour moves to whatcli.mdxalready documents, with the condition that a new key on an exported type makes ityes (widening).
Thread-read: 5979802093
Serial constraints, other open PRs read 2026-10-04T14:38Z onorigin/main8cbba54491:- No open PR touches
standalone-stack.ts,storage-driver.ts,serve.ts,telemetry-datasource.ts,stack-collections.ts,schema-migrate.tsordeployment/cli.mdx. - fix(cli): os migrate plan/apply compose the requires-supplied provider a connector hard-depends on #21739 (another session's cli: os migrate plan / apply cannot boot the stock showcase or a fresh blank app — Dependency 'com.objectstack.service-automation' not found for the connector plugins #21732) is already MERGED (
6afb1b55a9, an ancestor of8cbba54491). It addedschema-migrate.requires-providers.integration.test.tsand editedschema-migration-plugins.ts. It shares no file with this surface, but it does share theos migrateboot, so the dev measures A3 on a tree that carries it. The one-shot pin above stays in its own file. (Corrected 2026-10-04T14:39Z: this line first read fix(cli): os migrate plan/apply compose the requires-supplied provider a connector hard-depends on #21739 as open.)
domain:cliseat ·session_016GiHYRmLSNWTfbX9gVQkpz· 2026-10-04T14:38Z
Generated by Claude Code
objectstack-fleet commented
on Oct 4, 2026 ContributorAuthorMore actionsos-dev-report
{
"issue": 21733,
"status": "done",
"branch": "claude/issue-21733-standalone-dev-automigrate",
"pr": "#21766",
"session": "session_016GiHYRmLSNWTfbX9gVQkpz — subagent run under the PM session (harness Claude-Session line)",
"premise_still_valid": true,
"summary": "A1 reproduced on origin/main 8cbba54 with the built CLI: two plainos dev --no-watch -d file:A.dbrestarts left the staged index bare (CREATE UNIQUE INDEX uniq_scaf_item_organization_id_qa_code ON scaf_item (organization_id, qa_code)) and created no A.telemetry.db. The OS_MODE=off control self-healed it to COALESCE(organization_id, 'global'),qa_codeand created A.telemetry.db. Fix (A2): the dev self-heal decision has ONE home, devAutoMigrateConfig(driver, dev) in packages/runtime/src/dev-auto-migrate.ts. It covers the kinds whose spec contract declares autoMigrate (sqlite, postgres, mysql) and is read by the standalone stack default definition, every resolveStorageDefinition arm and the telemetry sibling. No kind gained or lost safe; the parity pin covers 6 kinds x dev/prod. A3: the standalone stack reads it only under an explicit dev: true. Measured by ablation: keyed on factoryDev (the NODE_ENV default), a non-deferred one-shot bootSchemaStack under NODE_ENV=development auto-applied the staged drift, while os migrate plan stayed write-free (deferred DDL). A4: the telemetry provision was extracted to provisionTelemetryDatasource and runs on both serving paths, keyed on the runtime pre-boot resolveStandaloneDatabase. No deliberate omission was found (falsifier not triggered). Every pin is green on the built packages, and three ablation legs went red where expected and restored clean.",
"tests": "All at c20d26d. Full runtime:pnpm --filter @objectstack/runtime exec vitest run --project local --maxWorkers=2-> Test Files 324 passed, Tests 4617 passed | 19 skipped. Full cli unit:--project unit-> Test Files 258 passed, Tests 3777 passed. Full cli integration (93 files, --shard=1..4/4): 24/23/23/23 files passed, Tests 169+267+238+223 passed, 2 skipped. typecheck runtime and cli (incl. check:test-typecheck): green.pnpm lint(eslint . --no-inline-config, full): exit 0, 99s. New pins: runtime dev-auto-migrate.test.ts (7), cli dev-self-heal-host-parity.test.ts (1, 12 rows), schema-migrate.dev-self-heal-fence.integration.test.ts (3), telemetry-datasource.provision.integration.test.ts (5), test/dev-standalone-self-heal.integration.test.ts (4, built bin/run.js: fresh+OS_TELEMETRY_DB=0, restart NULL-safe + auto-reconciled + A.telemetry.db, production os serve leaves drift). Ablation via scripts/ablation-replace.mjs (anchor x1->x0, blob changed, restored blob == HEAD, git diff HEAD empty), with rebuild and ablation-dist-preflight present (exit 0) then --absent (exit 0, tree clean). Leg A, the standalone read (standalone-stack.ts blob 69295ae4dcb6->3a20c5f19924->69295ae4dcb6): RED restart NULL-safe pin, fence positive control, parity, runtime dev-definition x2. GREEN production, fresh, telemetry, both one-shot fence cases, storage-driver.test.ts (host path). Leg B, the standalone telemetry provision (serve.ts d5486ac90717->42870a5cbc82->d5486ac90717): RED telemetry-sibling pin only, 3 others green. Leg C, the A3 fence keyed on factoryDev (69295ae4dcb6->22ebf7f09362->69295ae4dcb6): RED non-deferred one-shot fence (expected [] to include safe:recreate_index) and runtime NODE_ENV-default case. GREEN migrate plan byte-identical and serving control.",
"gates": "dispatch-gates --commands --repo objectstack-ai/objectstack at c20d26d derived 86 families, and all 86 were run. 85 exit 0. check:dual-build-cjs-loads and check:i18n-coverage first answered PREREQUISITE NOT MET (exit 3, unbuilt packages); after building those packages both re-ran green. check:cli-test-child-env first went red (new built-entry spawner not in the pinned census, and an env hop the scan could not read). Fixed and green: 152 self-test cases, 7 built spawns. NOT MEASURED: check:pm-dispatch-gates, reason: its self-test and its bare check each ran past the 10-minute foreground cap (exit 124 at 590s) on the shared box, with every printed case passing. It gates scripts/pm/dispatch-gates.mjs, which this diff does not touch. dispatch-gates --ran: 86 derived families accounted for, 85 run, 1 NOT-MEASURED (claimed, reasoned). Ledger blind spot: git grep autoMigrate over packages/spec/liveness/** and .ledger. found 0 hits (control: sqlite hits datasource.json); nothing renamed or removed. CI at report time: 13 check runs completed with 0 failures, 18 in_progress.",
"line_budget": "n/a — no skills/** or governed ledger touched",
"deviations": [
"@objectstack/runtime gains one barrel export, devAutoMigrateConfig, plus the DevAutoMigrateConfig type: the existing decision moved out of the CLI so the CLI can read it. No key is added to StandaloneStackConfigSchema or any other exported type or schema, and no accept set moves. Thedevkey TSDoc now states that only an explicit true arms the self-heal. The changeset is patch on both packages, with Clause-② no copied verbatim (precedent 68f5ecc). If the export counts as a public-surface widening, the re-declaration is the seat's.",
"scripts/check-cli-test-child-env.mjs (outside the declared file surface): its self-test pins the built-entrypoint population, so the new restart pin was admitted with a reason comment ("six" -> "seven"). The production leg needs bin/run.js with NODE_ENV unset. Its own --self-test is green (152 cases).",
"origin/main was not merged before the PR. The base is 8cbba54; origin/main a6a7547 is 8 commits ahead and touches serve.ts in hunks disjoint from this diff (AuthPlugin appName). git merge-tree is clean.",
"The restart pin is an .integration.test.ts (per-PR tier), not .e2e, so it runs in Test Core rather than the nightly tier."
],
"files_changed": [
".changeset/21733-standalone-dev-self-heal.md",
"packages/runtime/src/dev-auto-migrate.ts",
"packages/runtime/src/dev-auto-migrate.test.ts",
"packages/runtime/src/index.ts",
"packages/runtime/src/standalone-stack.ts",
"packages/cli/src/utils/storage-driver.ts",
"packages/cli/src/utils/telemetry-datasource.ts",
"packages/cli/src/commands/serve.ts",
"packages/cli/src/utils/dev-self-heal-host-parity.test.ts",
"packages/cli/src/utils/schema-migrate.dev-self-heal-fence.integration.test.ts",
"packages/cli/src/utils/telemetry-datasource.provision.integration.test.ts",
"packages/cli/test/dev-standalone-self-heal.integration.test.ts",
"scripts/check-cli-test-child-env.mjs"
],
"mcp_calls": "0 — no MCP GitHub tool was called; reads went through gh api (single-card REST) and writes through scripts/pm.",
"api_writes": "3 relay strokes, each one repository_dispatch (POST /repos/objectstack-ai/objectstack/dispatches) executed by fleet-write as objectstack-fleet[bot]: (1) pr_create -> POST /repos/objectstack-ai/objectstack/pulls (#21766, draft, body read back identical: 11784 bytes); (2) label-write assign -> POST /repos//issues/21766/assignees (os-bill, read back matching); (3) this os-dev-report comment -> POST /repos//issues/21733/comments. Plus git push of the branch (not REST). No label added (none named by dispatch; changeset present, so no skip-changeset).",
"open_questions": [],
"out_of_scope_findings": [
"carrier: none · noted, not filed — DefaultDatasourcePluginOptions.dev TSDoc (packages/runtime/src/default-datasource-plugin.ts, about :65) says it "Arms the shared factory's dev sqlite step-down (#2229) + loosen-only self-heal passthroughs". It arms the step-down only; the self-heal rides in the definition config.autoMigrate (now decided by devAutoMigrateConfig). Comment-only, so it went into the PR Acceptance notes."
]
}objectstack-fleet commented
on Oct 4, 2026 ContributorAuthorMore actionsREWORK — PR #21766 at
c20d26dd76: re-declaredClause-②: yes (widening), plus three small itemsdomain:cliseat ·session_016GiHYRmLSNWTfbX9gVQkpz· review of record, read on GitHub 2026-10-04T17:06ZWhat holds, read from the diff and the report
5982374446:- A1: reproduced on
8cbba54491with the built CLI. The staged index stays bare across two plain restarts and noA.telemetry.dbappears. TheOS_MODE=offcontrol self-heals it. - A2, one home:
devAutoMigrateConfig(driver, dev)inpackages/runtime/src/dev-auto-migrate.tsis the only place the condition is spelled.- Every reader spreads it: the standalone stack's
defaultdefinition, everyresolveStorageDefinitionarm, and the telemetry sibling. ⛔ No copy remains. - The kind set is
sqlite,postgres,mysql, the kinds whose connection contract declaresautoMigrate. The host-parity pin holds it equal across 6 kinds × dev/prod.
- A3, the fence:
- The standalone stack arms the self-heal on an explicit
dev: trueonly. Both serving doors pass it: the standalone branch andcreateDefaultHostConfig. bootSchemaStackpasses nodev. Leg C proves that keying on theNODE_ENVdefault would apply drift on a non-deferred one-shot boot, and the shipped key does not.
- The standalone stack arms the self-heal on an explicit
- A4:
provisionTelemetryDatasourceis the one provision. Both serving paths call it underresolveTelemetryDbPath.- On the standalone path the primary comes from the runtime's own pre-boot
resolveStandaloneDatabase. - No deliberate omission was found, so the falsifier did not fire.
- A5: three legs, each red exactly where predicted, with the blob restored. On the gates, 86 families were derived and 85 run green.
check:pm-dispatch-gatesis NOT MEASURED, on a surface this diff does not touch, and CI runs it; accepted.
Re-declaration (the seat's, as the claim said it would be).
@objectstack/runtime's only entry (exports["."]→src/index.ts) now exportsdevAutoMigrateConfigandDevAutoMigrateConfig. That enlarges a published surface, so this card isClause-②: yes (widening), andyestakes at leastminor(AGENTS.md, Post-Task Checklist 3). The claim's line is corrected in this act. The contract review of record is now owed atCONTRACT_REVIEW_TIERon the reworked head. 68f5ecc is no precedent forno: it is a refactor changeset that never carried the line.Rework items:
- R1. The changeset.
- Set
@objectstack/runtimetominor;@objectstack/clistayspatch. - Put
Clause-②: yes (widening)on its own line, line-initial. - Replace the "Why patch" bullet with "Why minor". It names the two new exports as the widening and says no config key, schema or accept set moves. Drop the 68f5ecc precedent sentence.
- Set
- R2. The PR body. Its
Clause-②line becomesClause-②: yes (widening), and any "patch" wording follows. Write it aspr-body-v2.mdin your scratchpad subdir; the seat reads it in full and applies it. ⛔ No self-patch. - R3. Merge
origin/maininto the branch with a merge commit (⛔ no rebase or force-push). Main is many commits ahead, includingserve.tshunks from PR fix(auth): TOTP enrollment names the deployment app name as its issuer, not Better Auth #21752.git merge-treeis clean today. - R4. Rides this push, comment only.
packages/runtime/src/default-datasource-plugin.ts(about:65): theDefaultDatasourcePluginOptions.devTSDoc saysdevarms the "self-heal passthroughs". It arms the sqlite step-down only; the self-heal rides inconfig.autoMigrate, asdevAutoMigrateConfigdecides. This is your own out-of-scope note, and it is in this lane.
Deviations, dispositioned:
- The barrel export: accepted, and re-declared as above.
scripts/check-cli-test-child-env.mjs: accepted. Admitting the new built-entry spawner with a reason is that gate's designed admission path, and nothing is loosened.- No
mainmerge before the PR: answered by R3. - The restart pin at the
.integrationtier: accepted. check:pm-dispatch-gatesNOT MEASURED: accepted as above.
Out of scope: none beyond R4.
Generated by Claude Code
- A1: reproduced on
objectstack-fleet commented
on Oct 4, 2026 ContributorAuthorMore actionsos-dev-report
{
"issue": 21733,
"status": "done",
"branch": "claude/issue-21733-standalone-dev-automigrate",
"pr": "#21766",
"session": "session_016GiHYRmLSNWTfbX9gVQkpz — subagent run under the PM session (harness Claude-Session line); REWORK round 2",
"premise_still_valid": true,
"summary": "Round 2 on REWORK 5982402012. I copied the claim 5981147390 lineClause-②: yes (widening)and re-declared nothing. R1: the changeset now has "@objectstack/runtime": minor and "@objectstack/cli": patch, withClause-②: yes (widening)as its own line-initial line. Its "Why patch" bullet became "Why minor": it names devAutoMigrateConfig and DevAutoMigrateConfig as the widening and says no config key, schema or accept set moves. The 68f5ecc sentence is dropped. R2: the full new body is at scratchpad issue-21733/pr-body-v2.md (13047 bytes), not applied. Its Clause-② line is yes (widening), the "Why runtime" bullet names the widening and the runtime minor, and tests, gates, deviations and acceptance notes are restated for round 2. R3: origin/main b7a13c7 merged with merge commit 0774564 (parents c20d26d + b7a13c7). No conflicts, no rebase, no amend, no force-push. The only overlapping file is serve.ts, where #21752 adds the AuthPlugin appName in disjoint hunks. After the merge the diff against main is unchanged: the same 13 files, +1134/-68. R4: the DefaultDatasourcePluginOptions.dev TSDoc now says dev arms the sqlite step-down (#2229) only, and that the self-heal rides in the definition config.autoMigrate, decided by devAutoMigrateConfig (#21733). The round-2 head is 3e28108, pushed.",
"tests": "At 3e28108, after a full turbo rebuild (turbo run build --concurrency=2 --filter=./packages/* --filter=./packages/*/*: Tasks 71 successful, 71 total). Typecheck:pnpm --filter @objectstack/runtime typecheck && pnpm --filter @objectstack/cli typecheckexit 0, both check:test-typecheck OK. Runtime:pnpm --filter @objectstack/runtime exec vitest run --project local --maxWorkers=2 src/default-datasource-plugin.test.ts src/dev-auto-migrate.test.ts-> Test Files 2 passed, Tests 19 passed. CLI pins on the rebuilt packages:pnpm --filter @objectstack/cli exec vitest run --maxWorkers=2over dev-self-heal-host-parity, schema-migrate.dev-self-heal-fence.integration, telemetry-datasource.provision.integration and test/dev-standalone-self-heal.integration -> Test Files 4 passed, Tests 13 passed. The rebuilt cli dist/commands/serve.js carries both standaloneTelemetryPrimary and #21752 resolveDeploymentAppName (3 hits each).pnpm lint(full) exit 0, 104s. Carried from c20d26d, not rerun this round: the full runtime suite (324 files) and the full cli unit and integration suites, plus the three ablation legs. This round touched only the merge, the changeset and one TSDoc.",
"gates": "dispatch-gates --commands --repo objectstack-ai/objectstack at 3e28108 (merge base b7a13c7, 14 paths) derived the same 86 families as round 1. All 85 runnable families were rerun on the merged head, every one exit 0 (prerequisite dists present after the full build). The Clause-② readers:node scripts/check-changeset-no-major.mjs --base origin/mainexit 0 (no major; the level axis is not applicable locally without a pull_request payload). Driven offline with--eventcarrying pr-body-v2.md: exit 0,LEVEL AXIS: this PR declares clause-② yes (widening), and it grades a package ... at minor or above(@objectstack/runtime: minor).pnpm check:adr-0087-registrationexit 0: 441 self-test assertions; no declared-breaking changeset. NOT MEASURED, carried: check:pm-dispatch-gates. Its round-1 cap kill at 590s stands, and its inputs (scripts/pm, .github, .claude, root package.json) are byte-unchanged between c20d26d and 3e28108. --ran: 86 derived families accounted for, 85 run, 1 NOT-MEASURED (claimed). CI on 3e28108 at report time: 32 check runs completed with 0 failures, 1 in_progress.",
"line_budget": "n/a — no skills/** or governed ledger touched",
"deviations": [
"Round 2 only. R4 rode in the same commit as R1 (3e28108), separate from the merge commit 0774564. No other edit this round.",
"PR body not patched (R2 ⛔): pr-body-v2.md is in the scratchpad subdir for the seat to apply. The live body is still v1, which readsClause-②: no, until the seat applies v2.",
"The full runtime and cli suites and the ablation legs were carried from c20d26d rather than rerun; the round-2 gate list did not name them."
],
"files_changed": [
".changeset/21733-standalone-dev-self-heal.md",
"packages/runtime/src/default-datasource-plugin.ts",
"merge commit 0774564 (origin/main b7a13c7; no conflicted hunks)"
],
"mcp_calls": "0 — reads via gh api (single-card and single-comment REST), writes via scripts/pm.",
"api_writes": "Round 2: 1 relay stroke, one repository_dispatch (POST /repos/objectstack-ai/objectstack/dispatches) executed by fleet-write as objectstack-fleet[bot]: this round-2 os-dev-report comment -> POST /repos//issues/21733/comments. Plus git push of 0774564 and 3e28108 (not REST). No PR create, no label write, no body patch.",
"open_questions": [],
"out_of_scope_findings": []
}objectstack-fleet commented
on Oct 4, 2026 ContributorAuthorMore actionsACCEPT — PR #21766 at
3e28108544, pending its contract reviewdomain:cliseat ·session_016GiHYRmLSNWTfbX9gVQkpz· review of record, read on GitHub 2026-10-04T17:39ZRound 2 against REWORK
5982402012, read from the commits and the round-2 report5982653479:- R1. The changeset is
@objectstack/runtime: minorand@objectstack/cli: patch, withClause-②: yes (widening)on its own line. Its "Why minor" names the two new exports as the widening, and the 68f5ecc sentence is gone. - R2. The seat read
pr-body-v2.mdin full and applied it withissue_patch(13104 bytes, read back identical).- The body's first lines are
Fixes #21733andClause-②: yes (widening). - One seat edit: the post-merge count sentence now also gives the final size, 14 files and +1143/−69 after R4.
- The body's first lines are
- R3. Merge commit
07745648c0has parentsc20d26dd76andb7a13c762f. There was no rebase or force-push, and no conflicted hunk.git merge-treeagainstorigin/mainis clean. - R4. The
DefaultDatasourcePluginOptions.devTSDoc now saysdevarms the sqlite step-down only, and that the self-heal rides inconfig.autoMigrate, decided bydevAutoMigrateConfig. It is comment only. - Gates: 85 of 86 families were rerun on the merged head, and all passed.
check-changeset-no-majorgrades the level axis asyes (widening), with runtime atminor.check:adr-0087-registrationpasses.check:pm-dispatch-gatesis still NOT MEASURED, with inputs byte-unchanged; CI runs it.
- Carried from round 1: the full suites and the three ablation legs. This round changed only the merge, the changeset and one comment, and the targeted pins were rerun on rebuilt packages.
Round 1, unchanged: as REWORK
5982402012recorded it. That covers A1 reproduced, A2 one home, the A3 fence proven by leg C, A4 one provision with no falsifier, and the A5 legs red where predicted.Prose checked against the diff:
- The changeset's four bullets match
standalone-stack.ts,storage-driver.ts,serve.tsanddev-auto-migrate.ts. content/docs/deployment/cli.mdxis untouched and is now true on both boot paths: the dev self-heal callout and the telemetry sibling paragraph.
Clause-②: yes (widening), re-declared by the seat on the claim (5981147390).needs:contract-reviewis hung on the PR in this act. The contract review of record is owed atCONTRACT_REVIEW_TIERon this head, once every check run has completed.
Generated by Claude Code
- R1. The changeset is
objectstack-fleet commented
on Oct 4, 2026 ContributorAuthorMore actionsLanded: PR #21766 →
025008ae95domain:cliseat ·session_016GiHYRmLSNWTfbX9gVQkpz· read 2026-10-04T18:33Z- Merged 2026-10-04T18:32Z through the merge queue (enqueued 2026-10-04T17:56Z), at head
3e28108544. That is the head the ACCEPT5982670474and the contract review PASS5982780237both read. - Shape:
git rev-list --parents -n 1 025008ae95gives 2 fields, so it is a single-parent squash. The commit is an ancestor oforigin/main. It is 14 files, +1143/−69, matching the PR. - Content read on
origin/main:packages/runtime/src/index.ts:17exportsdevAutoMigrateConfig;.changeset/21733-standalone-dev-self-heal.mdcarries@objectstack/runtime: minor,@objectstack/cli: patchandClause-②: yes (widening).
- The card closed
completedviaFixes #21733.pm:dispatchedis stripped in this act. - What now holds:
- A plain
os devon a non-host config self-heals safe drift on restart, so the plan and drift lines' "auto-applied at boot" is true. - That boot provisions the
telemetrysibling underresolveTelemetryDbPath. - A one-shot CLI boot never auto-applies drift, under any
NODE_ENV. - Production boots do not change, apart from the documented explicit
OS_TELEMETRY_DB=PATHopt-in, which now reaches the standalone path too.
- A plain
- Re-declaration on record: the claim's
Clause-②went fromnotoyes (widening)at review (REWORK5982402012), because of the two new runtime exports. - Noted, with no carrier: the PR body's "Production boots … do not change" is loose on that opt-in (contract review ① 6). The shipped changeset states it correctly, so nothing is owed.
Generated by Claude Code
- Merged 2026-10-04T18:32Z through the merge queue (enqueued 2026-10-04T17:56Z), at head
- added a commit that references this issue
on Oct 7, 2026
QA-source: #21721 · cli.dev-automigrate-policy · acceptance[5]
Clause A6 of
cli.dev-automigrate-policy(rev 1) fails in the 17.7 pre-release run #21721 (subject251a7dd4); verifier V6 reproduced it on fresh copies: CONFIRMED, medium. Predates 17.6.0.Reproduction
scaf_itemwith an org-scoped fieldqa_code: { unique: true }, no plugins, no datasources.os dev --no-watch -d file:A.dbcreates the NULL-safe indexuniq_scaf_item_organization_id_qa_code … (COALESCE(organization_id,'__global__'), qa_code); stop.DROP INDEX uniq_scaf_item_organization_id_qa_code; CREATE UNIQUE INDEX uniq_scaf_item_organization_id_qa_code ON scaf_item (organization_id, qa_code);os migrate plan --database-url file:A.dblists it as Safe:[recreate_index] … (auto-applied at boot under dev autoMigrate: 'safe').os dev --no-watch -d file:A.db(twice): only[schema-drift] … (auto-applied at boot under dev autoMigrate: 'safe')is logged — itself misleading — and the index stays bare.Control: the same staged DB booted with
OS_MODE=offlogs[schema-drift] auto-reconciled recreate_index on scaf_item.organization_idand the index comes back NULL-safe (it also createsA.telemetry.db, which the default boot does not). Host configs (aplugins[]entry withinit, e.g. the showcase) self-heal too, so a showcase-based run never sees this.Mechanism
Every non-host config goes
shouldBootWithLibrary(packages/cli/src/utils/plugin-detection.ts:47) →createStandaloneStack(serve.ts~2763), which builds the SQLite datasource withdriverConfig = { filename }and noautoMigrate(packages/runtime/src/standalone-stack.ts~745-760);DefaultDatasourcePlugin's factory passesautoMigrateonly when the config has it (service-datasource/src/default-datasource-driver-factory.ts:1140). Because a datasource plugin is present,shouldAutoRegisterStorageDriver(stack-collections.ts:276) is false, so theisDev ? { autoMigrate: 'safe' }injection (storage-driver.ts:370) never runs — nor the telemetry datasource's'safe'(serve.ts:3283).What declares the behaviour
content/docs/deployment/cli.mdx:966: "os devruns the SQL driver withautoMigrate: 'safe'… applied … automatically on restart"; the clause; the CLI's own plan / drift text. (Side observation, not checked for intent: the standalone path also has no telemetry datasource.)Generated by Claude Code