Repository navigation
C7a (ADR-0131 D10, split from #15211): the migration inventory file, the read-only os migrate --plan, and the design of the ceremony's completion marker #22617
Description
Activity
- addedenhancementNew feature or requestNew feature or requestpriority:p1High: required for production / M2High: required for production / M2area:devpathThe road — create, dev, verify, publish/install, connect an agent, iterateThe road — create, dev, verify, publish/install, connect an agent, iterateand removed
on Oct 10, 2026 objectstack-fleet commented
on Oct 10, 2026 ContributorAuthorMore actionsClaim: PM loop round 2 · 2026-10-10T06:52Z
Session:session_01Bw3y2DWhT9RPnrmDsNqEVG
Account:os-tesla(the seat's linked user, asget_meanswers it; the card's assignee)
Branch:claude/issue-22617-c7a-inventory-plan
Worktree: the cloud session's own checkout (mode:cloud)
Domain:domain:engine
Seat:domain:engine#2(seat post #20966)
Provenance:- C7a of feat(objectql,cli): inventory + migration — four fates per object, mirrors deleted only after the id→name rewrite is verified, per-table boot report (ADR-0131 D10) #15211 (
Part of #15211), per the maintainer's ruling 6094175435 (batch Release version 0.4.0 #310 item 2): 「cloud 冻结在 v17 没问题,其他同意你的建议。」 - ADR-0131 D10 (four fates; the ceremony's preflight, read-only) and its D10 ceremony item 5 (the boot refusal reads a completion marker; ADR-0093 D5 shape, ⛔ no escape hatch).
File surface (read onorigin/main83b8b80728): - The inventory file: one fate and one citation per object, for the 59 + 28 objects of measure: census the dependents of the SQL driver's orWhereNull tenant-wall carve-out before deciding its future (NULL org_id rows are globally visible on shared-DB walled deployments) #13564's two censuses plus the cloud supplement, with
sys_business_unit_memberis unadjudicated inPLATFORM_OBJECT_TENANCY, so seed-replayed and system-written membership rows land organization-less #14570 and plugin-sharing: after the #15030 revert, 17.x still cannot reach a NULL-org-seeded business unit from an org-stamped rule — and #14547, its only tracker, is closed #15086 read in. Its home (a data file beside the command, or underscripts/) is the dev's measured choice, named in the report. domain:cli, declared in this act before any edit:packages/cli/src/commands/migrate/, a read-only plan for the v18 ceremony. It is per table: the fate, the row counts, the unattributable row ids, and which tables will receiveNOT NULL. It is written to a file, and it refuses a table it cannot enumerate. It sits beside the existing schema-driftos migrate plan, without changing what that command does.- The completion-marker design: recorded on feat(objectql,cli): inventory + migration — four fates per object, mirrors deleted only after the id→name rewrite is verified, per-table boot report (ADR-0131 D10) #15211 for C7b. It is design only, with no code that writes or reads the marker.
- Tests and a changeset.
- ⛔ Any write to a row or a column. C7a never changes data (the card's stop line). ⛔ No
--apply, post-check or boot refusal; those are C7b. - Stop on a breach and explain in the report.
Container & model:L,mode:cloud,model: default(dispatch-gates --tier: no path-derived mandate)
Clause-②: yes - Widening: a new read-only command surface (the plan). No existing command or verdict changes. It owes a contract review at tier before the queue.
Responsibility: n/a — not a defect card
Thread-read: none
Serial constraints cleared: at 2026-10-10T06:52Z, 13 open PRs were read byfilename. None touchespackages/cli/src/commands/migrate/. - This seat's in-flight feat(metadata-core,metadata-protocol,objectql,plugin-security): the
sys_metadatafamily goes tenant-less; the per-organization overlay axis retires; managed content is sealed (ADR-0131 D6/D7/D13) #15206 S5 (metadata-protocolreads) and metadata-protocol: a refused save of a package-held position name tells the author to "Edit the source artifact and redeploy", which is wrong for a create, where the remedy is a name no package or built-in holds #22591 (PR fix(metadata-protocol): a sealed-item refusal of a create names a free name, not the edit remedy (#22591) #22623, in the queue) touch other files. - C7b stays on feat(objectql,cli): inventory + migration — four fates per object, mirrors deleted only after the id→name rewrite is verified, per-table boot report (ADR-0131 D10) #15211, blocked on refactor(plugin-security,platform-objects,spec): retire the catalog seeders, the per-organization catalog machinery and the four catalog objects; Setup creation is an environment write under
singleand refused under a wall (ADR-0131 D2/D3/D5/D13) #15204, refactor(plugin-email): templates resolve the registry; the seed and the provenance stamp retire; organization-level editing is closed (ADR-0131 D6/D10) #15205 and feat(metadata-core,metadata-protocol,objectql,plugin-security): thesys_metadatafamily goes tenant-less; the per-organization overlay axis retires; managed content is sealed (ADR-0131 D6/D7/D13) #15206 as the ruling keeps it.
- C7a of feat(objectql,cli): inventory + migration — four fates per object, mirrors deleted only after the id→name rewrite is verified, per-table boot report (ADR-0131 D10) #15211 (
objectstack-fleet commented
on Oct 10, 2026 ContributorAuthorMore actionsos-dev-report
{ "issue": 22617, "status": "done", "branch": "claude/issue-22617-c7a-inventory-plan", "pr": "https://github.com/objectstack-ai/objectstack/pull/22643", "session": "session_01AB6Nvx7Ue6yzJypw7VTvkj — this run's harness-stamped id; dispatched by the PM seat domain:engine#2 (session_01Bw3y2DWhT9RPnrmDsNqEVG), claim 6094844899", "premise_still_valid": true, "summary": "C7a delivered as one draft PR, #22643, with 2,011 changed lines across 7 files, under the 3,000 threshold. (1) The inventory, packages/cli/src/utils/organization-ownership-inventory.ts, gives 128 objects one D10 fate each, with a citation. (2) os migrate organization-ownership is the read-only D10 plan. Per table it gives the fate, the row counts, the ruled categories, the derivable rows per anchor, the unattributable ids with a reason, and NOT NULL readiness. It writes a plan file and never overwrites one. It refuses, naming the table, any table it cannot enumerate; an inventoried object with no table is listed as absent, never as empty. (3) The completion-marker design is in the PR body and under marker_design, with no code. Zone 2 findings: assumption 1 holds (a new subcommand; the existing plan is untouched). Assumption 2 is corrected: the census JSON on main lists 84 platform objects (49 in reach), not the 59 of #13564. The first census's 84 were read at 00d8f6541b; 3 have since left the tree and 3 are new. Its '28 example objects' are 28 files declaring 33 objects. Assumption 4 is refined: a physically absent table is a catalog fact, listed as 'absent' rather than refused, because refusing would block every deployment that does not install every plugin. A failed read, a missing column, an uninventoried platform table, an unquotable name, an unsupported dialect and a database with no inventoried platform table all refuse. The card assignee was not written.", "tests": "Head a3f7ab26. (a) Unit tier: OS_VERIFY_LOCK_SLOT=issue-22617 scripts/pm/os-verify-lock.sh -c 'pnpm --filter @objectstack/cli typecheck && pnpm --filter @objectstack/cli exec vitest run --project unit --maxWorkers=2' gave 'Test Files 278 passed (278) / Tests 4115 passed (4115)', VERDICT command-exit 0. An earlier run showed 2 suites failing only on the 'packages/cli is not built' prerequisite; after pnpm --filter @objectstack/cli build they passed (29 tests). (b) Integration tier, the files the diff touches: vitest run --project integration on src/utils/organization-ownership-plan.integration.test.ts and src/utils/schema-migrate.one-shot-family.integration.test.ts, -t 'organization-ownership|ADR-0131|missing from CALLERS', gave 14 passed, VERDICT 0. That covers each fate under isolated and single, six refusals each naming its table, the write-nothing control (sha256 of the file and a full dump byte-equal, every statement a SELECT), and the family pin's no-write and no-file-created cases for the new command. The rest of the cli integration tier is declared to CI. (c) Probe: on the family pin's served database the plan planned 20 tables (9 column-drop, 11 attribution, sys_activity folded from its shard). The temporary probe line was removed with git checkout HEAD and git status was clean. (d) Ablation via scripts/ablation-replace.mjs: anchor 'if (hasPlatformObjectPrefix(base)) {' changed to '&& false'; anchor 1 to 0, blob 1787b6437ca0 to c73567cdaabc; the uninventoried pin went red ('1 failed | 9 passed'); restored, blob == HEAD and git diff HEAD empty. (e) eslint --no-inline-config on the 5 changed source and test files: exit 0. Repo-wide lint is CI's.", "gates": { "head": "a3f7ab26", "derived_by": "node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands (65 commands)", "results": { "node scripts/check-adr-0087-registration.mjs --base origin/main": 0, "node scripts/check-adr-0087-registration.mjs --self-test": 0, "node scripts/check-changeset-no-major.mjs --base origin/main": 0, "node scripts/check-changeset-no-major.mjs --self-test": 0, "node scripts/check-ci-filter-parity.mjs": 0, "node scripts/check-closing-keyword-parity.mjs": 0, "node scripts/check-closing-keyword-parity.mjs --self-test": 0, "node scripts/check-comment-mask-adoption.mjs": 0, "node scripts/check-comment-mask-adoption.mjs --self-test": 0, "node scripts/check-comment-mask-corpus.mjs": 0, "node scripts/check-dts-emitted.mjs --self-test": 0, "node scripts/check-empty-changeset.mjs --base origin/main": 0, "node scripts/check-empty-changeset.mjs --self-test": 0, "node scripts/check-issue-citations.mjs": 0, "node scripts/check-keyed-text-bounds.mjs": 0, "node scripts/check-keyed-text-bounds.mjs --self-test": 0, "node scripts/check-platform-object-tenancy-census.mjs": 0, "node scripts/check-platform-object-tenancy-census.mjs --self-test": 0, "node scripts/check-plugin-teardown-shape.mjs": 0, "node scripts/check-plugin-teardown-shape.mjs --self-test": 0, "node scripts/check-registry-log-declared.mjs": 0, "node scripts/check-registry-log-declared.mjs --self-test": 0, "node scripts/check-rest-log-spy-declared.mjs": 0, "node scripts/check-rest-log-spy-declared.mjs --self-test": 0, "node scripts/check-system-context-census.mjs": 0, "node scripts/check-system-context-census.mjs --self-test": 0, "node scripts/check-undeclared-dep-imports.mjs": 0, "node scripts/check-undeclared-dep-imports.mjs --self-test": 0, "node scripts/docs-audit/check-affected-docs.mjs": 0, "node scripts/docs-audit/check-drift-comment.mjs": 0, "node scripts/pm/release-rehearsal-clone.mjs --self-test": 0, "node scripts/release-pending-publish.mjs --self-test": 0, "pnpm --filter @objectstack/spec run check:duration-unit-keys": 0, "pnpm check:changeset-gate-self-tests": 0, "pnpm check:cross-package-test-inputs": 0, "pnpm check:doc-authoring": 0, "pnpm check:driver-memory-census": 0, "pnpm check:dts-closure": 0, "pnpm check:dual-build-cjs-loads": 0, "pnpm check:engine-double-contract": 0, "pnpm check:error-status-conformance": 0, "pnpm check:gitlink-declared": 0, "pnpm check:i18n": 0, "pnpm check:i18n-coverage": 0, "pnpm check:i18n-walk-parity": 0, "pnpm check:issue-citations": 0, "pnpm check:lean-entry-closure": 0, "pnpm check:logger-receiver-detach": 0, "pnpm check:nul-bytes": 0, "pnpm check:objectql-double-limit": 0, "pnpm check:objectui-changeset": 0, "pnpm check:org-identifier": 0, "pnpm check:page-declaration-shape": 0, "pnpm check:pm-changeset-deadline-census": 0, "pnpm check:published-files": 0, "pnpm check:query-options-erasure": 0, "pnpm check:refd-timer-probe": 0, "pnpm check:slot-lookup": 0, "pnpm check:sourcemap-no-sources-content": 0, "pnpm check:test-source-alias": 0, "pnpm check:tier-file-adoption": 0, "pnpm check:type-check-coverage": 0, "pnpm check:type-check-debt": 0, "pnpm check:watch-hint-literal": 0, "pnpm check:where-matcher": 0 }, "reconcile": "dispatch-gates --ran: 65 derived famil(ies) accounted for — 65 run, 0 NOT-MEASURED (a DERIVED zero — all 65 recorded an exit code and none of them is 3)", "earlier_reds_fixed": [ "pnpm check:doc-authoring exit 1 on 889d4e39: tracker ids in inventory citation strings; rewritten to ADR sections and ruling-record ids", "pnpm check:dispatcher-error-vocabulary exit 1 on 889d4e39: unregistered code PLAN_REFUSED; class field dropped, the refusal carries reason" ], "prerequisites_cleared": [ "check-plugin-teardown-shape --self-test exit 3 (shallow clone) cleared by fetching its pinned commit 621a4876 into refs/c7a/teardown-control", "check:dual-build-cjs-loads and check:i18n-coverage exit 3 (unbuilt packages) cleared by building" ] }, "files_changed": [ ".changeset/22617-cli-organization-ownership-plan.md", "packages/cli/src/commands/migrate/organization-ownership.ts", "packages/cli/src/utils/organization-ownership-inventory.ts", "packages/cli/src/utils/organization-ownership-inventory.test.ts", "packages/cli/src/utils/organization-ownership-plan.ts", "packages/cli/src/utils/organization-ownership-plan.integration.test.ts", "packages/cli/src/utils/schema-migrate.one-shot-family.integration.test.ts" ], "inventory_location": "packages/cli/src/utils/organization-ownership-inventory.ts. A typed TS table: the CLI ships it in dist, and the planner and the pin read one spelling. Under src/commands it would become a command (oclif pattern strategy).", "inventory_census": { "total": 128, "by_fate": { "column-drop": 38, "mirror-deletion": 5, "attribution": 71, "report": 14 }, "sources": { "platform-census-2026-08-31 (census record 5479883784 on #13564, at 00d8f6541b)": { "objects": 84, "column-drop": 37, "mirror-deletion": 5, "attribution": 38, "report": 4 }, "platform-census-main (scripts/platform-object-tenancy-census.json; objects added since: sys_comment_reaction, sys_flow_credential, sys_platform_setting)": { "objects": 3, "column-drop": 1, "attribution": 2 }, "example-census-2026-08-31 (the census's '28' = 28 files declaring 33 objects; unchanged on main)": { "objects": 33, "attribution": 31, "report": 2 }, "cloud-supplement (CLOUD_PROVIDED_OBJECT_NAMES; the 2026-09-03 cloud-side supplement is NOT MEASURED, it is out of this session's reach)": { "objects": 8, "report": 8, "cloudCarried": 8 } }, "read_in": { "#14570 sys_business_unit_member": "attribution: parent business_unit_id -> sys_business_unit (5536484221, 6067123924)", "#15086 sys_business_unit": "attribution: parent_business_unit_id -> sys_business_unit; D3 (pointer 5536478573)" }, "not_measured": [ "#13564's 2026-09-02 ledger 5507087600 answers 404 (evidence destroyed or never on this repo)", "the 2026-09-03 cloud-side supplement (cloud repo out of scope)" ], "cloud_carried_meaning": "Cloud stays on v17 by ruling 6094175435, so no v18 ceremony runs against a cloud database. The 8 rows carry fate 4 with cloudCarried, listed rather than dropped; C10 assigns their fates when cloud moves. If such a table ever appears on a planned database, it is enumerated and its NULL rows are reported." }, "marker_design": "## The completion marker — design only (C7b builds it)\n\n⛔ This PR contains no code that writes or reads the marker. This section is the design that C7b's last step writes and the v18 boot refusal reads.\n\n**Where it lives.** One row in `sys_migration`, the deployment-level migration-flag table (`platform-objects/src/system/migration-flag.ts`, #3617). The row's primary key is a new spec constant, `ORGANIZATION_OWNERSHIP_MIGRATION_ID = 'adr-0131-organization-ownership'`, which sits beside `FILE_REFERENCES_MIGRATION_ID` and `VALUE_SHAPES_MIGRATION_ID`. No new table. `sys_migration` is itself a D7 column-drop object. Its drop runs inside the ceremony before the marker is written, so the marker is always written to the table's final, tenant-less shape.\n\n**What it records.** It reuses the existing columns:\n- `applied_at`: when the apply finished.\n- `verified_at`: when the post-check passed.\n- `blocking`: the number of tables whose post-check did not complete. This is not the count of reported rows. Reported rows are D10 fate 4: they are named at boot and do not block it.\n- `details`: one JSON document:\n - `ceremonyVersion`: the integer `1`, the same `ceremonyVersion` this plan prints;\n - `inventoryDigest`: the sha256 the plan prints, which ties the marker to the inventory it executed;\n - `posture`;\n - `tables`: per table, `{ object, fate, remainingNull, notNull: 'applied' | 'withheld', reason }`.\n\n `verified_at` is set only by a post-check that re-ran the plan and found zero tables left mid-fate.\n\n**When it is written.** Only as the ceremony's last statement, after the post-check. An interrupted apply leaves no marker; its checkpoint lives in the ADR-0119 journal (`os migrate resume`). A fresh v18 database gets the marker when it is created, the way `attestFreshDatastore` attests the creation-attested migration ids. A database born on v18 has nothing to migrate.\n\n**How a v18 boot reads it.** This has the same fail-fast shape as ADR-0093 D5, with no escape hatch.\n- **When:** before schema sync and before any plugin `start()`. Additive sync could otherwise create tables on a database the boot is about to refuse.\n- **How:** a primary-key read of that one row, through the raw read seam, in the same pre-boot gate as the tenancy-posture refusal.\n- **What it decides:**\n - A database with no ObjectStack tables is fresh, and is attested.\n - A database that holds `sys_organization` but no marker row is refused, and the refusal names `os migrate organization-ownership --apply`.\n - A marker that is unreadable, malformed, at a `ceremonyVersion` below the runtime's required version, missing `verified_at`, or with `blocking > 0` is refused.\n- **Reads fail toward refused:** the same asymmetry as `readDataMigrationFlag`.\n- **The refusal text** says what was found, that the server is refusing to start, the command to run, and that a 17.x runtime is the way to keep 17.x semantics.\n- ⛔ There is no `OS_ALLOW_*` / `OS_SKIP_*` variable and no flag that skips the read (ADR-0131 D10 item 5). A marker with tables still reporting NULL rows boots. Those tables are listed at boot with counts and the remedy (fate 4), and they stay unconstrained.\n", "mcp_calls": "2 — mcp__github__issue_read (get, get_comments on #22617); both reads, no write tool. Every other read went through gh api REST reads (issue and comment GETs).", "api_writes": "3 relay writes as objectstack-fleet[bot]: (1) pr_create POST /repos/objectstack-ai/objectstack/pulls, draft, giving #22643 (run 38036501559, body read back identical, 11374 bytes); (2) label-write --assign os-tesla, POST /issues/22643/assignees (run 38036527636, read back matches); (3) this os-dev-report comment, POST /issues/22617/comments. Plus git push, which is not a REST write.", "deviations": [ "Dispatch line 3 asks for line-start 'Clause-②: yes'. The PR body and changeset spell 'Clause-②: yes (widening)', the arm AGENTS.md's closed pair allows. Line-start is kept.", "Zone 2.4 lists 'missing' among the refusal cases. A table physically absent from the catalog is reported as physical 'absent' with rows null, never as zero rows; refusal is kept for every unreadable case. See open_questions.", "No worktree under ../objectstack-issue-N was created by git worktree add -b: the outcome branch already existed in the session checkout. It was checked out into the worktree ../objectstack-issue-22617 after detaching the primary checkout, and fast-forwarded to origin/main e8c6666 before any edit." ], "open_questions": [ { "question": "Should a table that is physically absent refuse the plan (Zone 2.4 lists 'missing') or be listed as absent?", "options": [ "A: list it as physical 'absent' with rows null (implemented). Refuse every read that fails.", "B: refuse whenever an inventoried table is missing." ], "recommendation": "A. Real business need: a deployment that does not compose plugin-approvals has no sys_approval_* tables, so B would refuse forever on every such deployment. Long-term soundness: the catalog's answer is a measurement, not a guess. AI-mistake resistance: 'absent' is a distinct, typed state that is never 0. Startup scope: no new surface. The wrong-database case B guards against is refused separately ('not-an-objectstack-database')." }, { "question": "sys_sso_provider carries better-auth's organization relation under tenancy.enabled:false. Is it outside D1, or should the column go?", "options": [ "A: fate 4 report with notNullExempt (implemented): listed, never attributed or constrained.", "B: fate 1 column drop, which would break better-auth's provider-to-organization binding." ], "recommendation": "A, until C8 says otherwise. D1 bans a nullable TENANT column; this one is not the tenancy anchor (ADR-0066 D2), and dropping it removes a working better-auth feature." }, { "question": "sys_notification_template: ADR §6 says its seed retires, but no column marks a seeded row.", "options": [ "A: fate 3 attribution, never deleted (implemented).", "B: fate 2 on every row, which would delete authored templates." ], "recommendation": "A. D10 sanctions no deletion of a row that is not provably a mirror, and B would delete authored rows. C4 can add a selector if it needs one." } ], "out_of_scope_findings": [ "carrier: C7b (#15211): parent chains are resolved one level in the plan; a child whose parent is attributable in the same apply is listed as unattributable with the reason 'parent row … has no organization'. Noted in the PR's Acceptance notes, not filed.", "carrier: none: #13564 comment 5507087600 (the second ledger, cited by ADR-0131's Evidence line) answers 404. Noted, not filed." ], "cleanup": "worktree removed after the report (node_modules first); the scratch refs refs/c7a/census1 and refs/c7a/teardown-control deleted" }
Generated by Claude Code
objectstack-fleet commented
on Oct 10, 2026 ContributorAuthorMore actionsACCEPT (seat review): PR #22643 at head
a3f7ab26ad. C7a ships the D10 inventory andos migrate organization-ownership, a read-only plan; the marker design is recorded on #15211domain:engine#2·session_01Bw3y2DWhT9RPnrmDsNqEVG(os-tesla), claim 6094844899 · 2026-10-10T08:23Z. Read against GitHub and the branch, not the report (os-dev-report 6095493258).Contract review at
CONTRACT_REVIEW_TIER: 6095623275, PASS on this head. It is owed because of theClause-②: yesline.Shape.
- Draft, base
main. Line 1 isFixes #22617, line 2 isPart of #15211, and line 3 isClause-②: yes (widening). That is the claim'syes, written in its explicit widening arm. - 7 files, +2,011/−0, all in
packages/clias the claim declared (cross-lane declaration 6095536022 on [PM seat] domain:cli — 🟢 marchtian · session_01B5CHJNXuuqzChM4w6hkTN4 #6024). - NOT governed (
check-governed-merges). 2,011 changed lines, under the 3,000-line human-merge threshold. - The head merges clean with
origin/main(git merge-tree).
Acceptance, line by line
- "The inventory names a fate and a citation for every object": met for both censuses.
- The censuses are 84 platform objects (as read at
00d8f6541b), the 3 platform objects added since, and the example census's 28 files, which declare 33 objects. The card's "59" is corrected by measurement in the report. - Inventory total: 128 objects, one fate and one citation each.
- The cloud supplement is met against the in-repo cloud-provided list: 8 objects, fate 4,
cloudCarried, under the v17 freeze (6094175435). - The 2026-09-03 supplement document itself, and measure: census the dependents of the SQL driver's orWhereNull tenant-wall carve-out before deciding its future (NULL org_id rows are globally visible on shared-DB walled deployments) #13564's ledger 5507087600 (which answers 404), are NOT MEASURED. Both are carried on feat(objectql,cli): inventory + migration — four fates per object, mirrors deleted only after the id→name rewrite is verified, per-table boot report (ADR-0131 D10) #15211 (6095639085).
- The censuses are 84 platform objects (as read at
- "
--plan… prints the per-table plan": met. It ships as a new subcommand,os migrate organization-ownership, beside the family; bareos migrateis untouched.- The integration pins cover each fate under
isolatedandsingle. - A probe on the family pin's database planned 20 tables.
- The plan file is written once and never overwritten.
- The integration pins cover each fate under
- "
--planrefuses a table it cannot enumerate, naming it": met.- Six refusals are pinned, each naming its table.
- A table the catalog says is absent is listed as
absentwithrows: null, never as empty. That is the review's ③ Q1, answered A.
- "The marker design is recorded on feat(objectql,cli): inventory + migration — four fates per object, mirrors deleted only after the id→name rewrite is verified, per-table boot report (ADR-0131 D10) #15211 for C7b": met by this seat in 6095639085. The dev's relay writes did not include it, and the review flagged the gap.
- ⛔ "any write": none.
- The planner is SELECT-only.
- The write-nothing control is pinned: the file sha256 and a full dump are byte-equal before and after.
- The family pin's no-write and no-file-created cases cover the new command.
Boundary.
- Q3 (
sys_notification_templatetakes attribution and is never deleted) is answered A by the review, on D10's own text. - Q2 (
sys_sso_provider'snotNullExempt) is right for a read-only plan, and escalated for C7b. It is recorded on feat(objectql,cli): inventory + migration — four fates per object, mirrors deleted only after the id→name rewrite is verified, per-table boot report (ADR-0131 D10) #15211 (6095639085) as an item to rule before C7b applies anything. ⛔ This seat does not answer it. - The dev wrote its
open_questionsin English. Nothing to correct.
CI on
a3f7ab26ad. 34 runs: 31 success, 3 skipped, 0 failure. All seven required contexts are success. The skips (Build Docs, Console Pin Gate, Packed-tarball smoke) are path or opt-in skips on the roster.Next: ready, then auto-merge, in this act. On merge,
Fixes #22617closes this card. #15211 stays open for C7b.- Draft, base
objectstack-fleet commented
on Oct 10, 2026 ContributorAuthorMore actionsLanded: PR #22643 →
cc305a3cfcthrough the merge queue, at 2026-10-10T08:42Z.domain:engine#2·session_01Bw3y2DWhT9RPnrmDsNqEVG· 2026-10-10T08:44Z.- Content on
origin/main: all 7 files are blob-identical to the reviewed heada3f7ab26ad.- The changeset, the command, the inventory and its test, the planner and its integration test, and the family pin.
cc305a3cfcis an ancestor oforigin/main.
- Card.
Fixes #22617closed it as completed.pm:dispatchedis removed in this act. - Records: ACCEPT 6095646063 and contract review 6095623275 (PASS).
- feat(objectql,cli): inventory + migration — four fates per object, mirrors deleted only after the id→name rewrite is verified, per-table boot report (ADR-0131 D10) #15211, for C7b: the marker design and the open
sys_sso_providerquestion are carried there in 6095639085.- ⛔ C7b applies no
notNullExemptbefore that question is ruled. - feat(objectql,cli): inventory + migration — four fates per object, mirrors deleted only after the id→name rewrite is verified, per-table boot report (ADR-0131 D10) #15211 stays open for C7b.
- ⛔ C7b applies no
- Dev session:
session_01AB6Nvx7Ue6yzJypw7VTvkjis archived in this act.
- Content on
Part of #15211
Filing gate ③: a task the maintainer directed. The maintainer accepted batch #310 item 2, verbatim: 「cloud 冻结在 v17 没问题,其他同意你的建议。」 (director record
6094175435on #15211, 2026-10-10T05:22Z). C7 splits in two, and this first half starts now. Filed by the triage seat (seat post #6015,session_01AavokzJ5DndAwitDXvKy4U) as the carrier the ruling names. ⛔ Not a claim.Reader: the
domain:enginelane, withdomain:clifor the command surface. The claim declares thepackages/clifiles under the cross-domain exception path.Scope (C7a)
The inventory file. It starts from the two measure: census the dependents of the SQL driver's orWhereNull tenant-wall carve-out before deciding its future (NULL org_id rows are globally visible on shared-DB walled deployments) #13564 censuses (59 platform objects, 28 example objects) plus the cloud supplement. Each object gets one fate, with its citation:
sys_business_unit_memberis unadjudicated inPLATFORM_OBJECT_TENANCY, so seed-replayed and system-written membership rows land organization-less #14570 (sys_business_unit_member) and plugin-sharing: after the #15030 revert, 17.x still cannot reach a NULL-org-seeded business unit from an org-stamped rule — and #14547, its only tracker, is closed #15086 (the NULL-org business unit) are read in, and each gets its fate. Re-read feat(objectql,cli): inventory + migration — four fates per object, mirrors deleted only after the id→name rewrite is verified, per-table boot report (ADR-0131 D10) #15211's pointers before writing:6018712820,6020279837(three categories ruled into the plan),6051723395,6061638897,6068052798,6071418113and6081248392.os migrate --plan, read-only. Per table it reports the fate, the row counts, the unattributable row ids, and which tables will receiveNOT NULL. It is written to a file. It refuses rather than reporting a table it cannot enumerate.The completion-marker design. This is the schema marker the ceremony's last step writes, and the one the v18 boot refusal reads (ADR-0093 D5 shape, ⛔ no env escape hatch). This card designs it and records it. C7b builds the refusal.
Not in this card (C7b, which stays on #15211)
--apply(fate order: attribution, then the verified id→name rewrite, then mirror deletion, then column drops; idempotent and resumable), the post-check, and the boot refusal. C7b stays blocked on the cutover (#15204, which now carries C2's remainder), C4 (#15205) and C5 (#15206).Why it can start now
None of C7a depends on the data shape that C2–C5 produce. It is an inventory, a read-only plan and a design. So the critical path does not idle through the cutover window (
6094175435).Acceptance
--planagainst a fixture database carrying each fate prints the per-table plan.--planrefuses a table it cannot enumerate, naming it.⛔ Stop and report: any write. C7a never changes a row or a column.
Refs: ADR-0131 D10 · ADR-0093 D5 · ADR-0120 D4 · #13564 · #14570 · #15086.