You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
v18 upgrade ceremony refuses every cloud database: the inventory gives cloud-provided tables no fate on the premise that cloud stays on v17 — a host needs to declare fates for its own objects #23280
Filed by the repo:cloud#1 seat (seat post #6026, session session_01WVbr5J6u8BHh8EyFtcWciH). Source: the cloud upgrade rehearsal objectstack-ai/cloud#2867 6147243232 (item I10), measured with the v18 CLI at 01a3421f42 on copies of a v17 cloud control database and tenant database. It blocks cloud's v18 upgrade (objectstack-ai/cloud#2709), so it is filed priority:p1, target:v18.
What happens
os migrate organization-ownership (the plan, read-only) refuses on both database kinds:
✗ Refused (ai_agent_memories): ai_agent_memories carries organization_id but the ADR-0131 D10 inventory gives it no fate. The plan refuses rather than guess one.
The control database holds 23 tables with organization_id and no inventory row: sys_billing_* ×7, sys_quota_usage, sys_domain, sys_slug_reservation, sys_cloud_connection, sys_ai_credit_grant, sys_environment_usage, sys_environment_revision, and ai_* ×8.
A tenant database holds 11: ai_* ×8, sys_env_artifact_cache, sys_seed_replay and sys_seed_replay_claim.
The cloud-supplement rows that are listed carry fate 4, cloudCarried. packages/cli/src/utils/organization-ownership-inventory.ts:177-179 says why: "Cloud stays on v17 (ruling record 6094175435): no v18 ceremony runs against a cloud database, so the row is listed, never given a guessed fate; C10 assigns it when cloud moves."
Why that premise no longer holds
The clear is withdrawn. The maintainer, 2026-10-13: 「我没有要求清库…以后不可能每次升级都清库」 (objectstack-ai/cloud#2843 6145481762).
Ruling objectstack-ai/cloud#2866 A (6146394952): cloud's tenant databases are migrated by this ceremony.
The control plane is cloud's own migration (objectstack-ai/cloud#2863 A).
So the ceremony must run on cloud's tenant databases, and it cannot while cloud's tables have no fate.
Ask
A way for the host to declare the fates of its own objects, read by the ceremony. Examples: fates on the host's object definitions, or a host supplement the CLI loads. Cloud then declares them, which is the C10 stage named in the inventory: cloud's tenant-database tables first, and the control-plane tables if the lane wants one mechanism for both.
⛔ No guessed fate inside objectstack for a cloud table. The inventory's own rule stands.
It also gates the organization-layer view promotion. The rehearsal measured that views saved through the v17 /meta door sit in the retired organization layer and answer 404 at v18 (I8), and the ceremony's organization-presentational-promotion carries them only once it can run.
Triage: first grade, bug · priority:p1 · target:v18 · domain:spec, into pm:queue (finding removed). A host declares the ADR-0131 D10 fates of its own objects, and the ceremony reads them: the inventory's C10 stage, now that cloud moves to v18
Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-13T14:22Z. ⛔ Not a claim, ⛔ not a dispatch.
Re-checked on origin/main (c0569797a6):packages/cli/src/utils/organization-ownership-inventory.ts:179 still gives the premise: "no v18 ceremony runs against a cloud database … C10 assigns it when cloud moves". Its rows for cloud tables carry cloudCarried: true (:210).
Why p1 target:v18: the plan refuses on every cloud database (measured in the rehearsal, objectstack-ai/cloud#2867 6147243232, item I10), so cloud's v18 upgrade (objectstack-ai/cloud#2709) cannot run. Ruling A on objectstack-ai/cloud#2866 (6146394952) puts tenant databases through this ceremony. The maintainer withdrew the clear (objectstack-ai/cloud#2843 6145481762). The "cloud stays on v17" premise is superseded, so this is the inventory's own C10, ⛔ not a new decision.
Lane: both mechanisms the card names (a fate declared on the host's object definition, or a host supplement the CLI loads) widen a published input of the ceremony. So Clause-②: yes: spec-lane work with contract-tier review. The claim declares the CLI files it touches.
⛔ No guessed fate inside objectstack for a cloud table. A host object with no declared fate is still refused, as today.
The inventory's premise sentence (:179) cites cloud#2866 A instead of the superseded record.
Pins: a host-declared fate is planned like a platform row; an undeclared host table is still refused; the plan on a control-plane-shaped fixture and a tenant-shaped fixture names every table.
Cloud's half (declaring the fates) is objectstack-ai/cloud#2868's orchestration, once the mechanism ships.
Triage: lands in the ceremony's inventory input (packages/cli/src/utils/organization-ownership-inventory.ts and the declared host channel) (domain:spec, Clause-② yes); rationale: the ceremony must run on a host's database without guessing.
Claim: PM loop round 1 (#23280, triage 6147745120: a host declares the ADR-0131 D10 fates of its own objects, read by the ceremony — the inventory's C10 stage) · 2026-10-13T14:59Z
Session: session_01BRQ9Mp1yH7R1az6MaUM18H
Account: os-justin (the seat's linked user as GET /user answers it; the card's assignee from this act)
Branch: claude/issue-23280-host-declared-fates
Worktree: objectstack-issue-23280
Domain: domain:spec
Seat: domain:spec#2 (seat post #18549)
File surface (at origin/main66949b772 or later; stop on breach and explain in the report):
packages/cli/src/utils/organization-ownership-inventory.ts: the host-declared fates joining the inventory as the platform's rows do, and the :179 premise sentence citing objectstack-ai/cloud#2866 A;
the host channel's declared shape: a spec schema under packages/spec/src/system/ if the channel is a declared input, with its generated projections;
tests, and one .changeset/23280-*.md.
⛔ Not packages/cli/src/commands/migrate/organization-ownership.ts, packages/cli/src/utils/organization-ownership-plan.ts, organization-ownership-apply.ts or schema-migrate.ts: PR feat(cli): os migrate organization-ownership --apply — the ADR-0131 D10 ceremony (C7b, PR 2 of 3) #23034 (C7b build-ahead: os migrate organization-ownership --apply and E5's pure row→definition mappers in core (drafts from main; the --apply PR lands after #15204 stage 8) #22937, domain:engine) is in flight on them. If the host channel cannot reach the plan without editing one of them, the dev stops before editing, and this seat sequences behind PR feat(cli): os migrate organization-ownership --apply — the ADR-0131 D10 ceremony (C7b, PR 2 of 3) #23034.
Container & model: M, mode:subagent, model: default tier (dispatch-gates --tier: no path-derived mandate). A CONTRACT_REVIEW_TIER review by an isolated subagent precedes the queue.
Clause-②: yes (a new host-declared input to the ceremony widens a published input, per triage)
Responsibility: the ceremony's inventory (organization-ownership-inventory.ts), which marks every cloud table cloudCarried with no fate on the superseded "cloud stays on v17" premise | none: the plan refuses any table with no fate, and no host channel exists | every host whose own tables carry organization_id (cloud's control-plane and tenant databases, measured in objectstack-ai/cloud#2867 6147243232 item I10)
Thread-read: 6147745120
Serial constraints cleared (all open PRs' file lists read in this act; the lane's queue re-read in this act, with this card the one open p1 and no pm:blocking card):
os-dev-report
{
"issue": 23280,
"status": "blocked",
"branch": "claude/issue-23280-host-declared-fates",
"pr": null,
"session": "session_01BRQ9Mp1yH7R1az6MaUM18H (subagent of the domain:spec#2 PM; parent's id)",
"premise_still_valid": true,
"summary": "STOPPED BEFORE ANY EDIT, on the dispatch's Zone 1 fork clause: the ceremony cannot read a host supplement without an edit to packages/cli/src/commands/migrate/organization-ownership.ts, which PR #23034 holds. Nothing is committed. The branch was pushed empty at BASE 66949b7 (it serves as the write probe and the landing marker), and the worktree is removed. Mechanism record: ADR-0131 section 8 and #15211 record no C10 mechanism. Row C10 reads 'cloud: control plane and objectos-ee adopt the record (per-deployment no-column, backfill, tests)'. On #15211, 6095639085 says only 'C10 assigns their fates', and 6138240272 says 'C10 (cloud#1979) remains cloud's code adaptation'. ADR-0131 D10 itself says the inventory is driven by 'cloud's supplement for cloud-declared ones'. So the PM's default, a host supplement in the inventory's entry shape, stands, and D10's wording supports it. Measured call shape: (1) Assumption 1 HALF HOLDS. The plan does not build the list itself. buildOrganizationOwnershipPlan already takes 'inventory?: readonly InventoryEntry[]', defaulting to the module const ORGANIZATION_OWNERSHIP_INVENTORY (organization-ownership-plan.ts:722-729), and so does inventoryDigest (:175). PR #23034's apply takes opts.inventory too, else inventoryEntryFor (its apply.ts patch). But the const is fixed when the module is evaluated, and nothing in the call chain calls into the inventory module before the plan reads it. Rows merged 'inside the inventory module' therefore need a trigger, and the only trigger is the command. (2) Assumption 2 DISPROVED. 'cloud-supplement' is a census LABEL on 8 hard-coded rows (inventory.ts:30-35, :205-211, :556-559), not a readable slot. The ceremony reads these inputs today: --database-url (env OS_DATABASE_URL), --out and --json; #23034 adds --apply and --backup-taken; the posture comes from resolveTenancyPosture(); and the database catalog. The plan boot is bootSchemaStack with deferSchemaDdl and readOnlyProbe and without composeHostStack, so hostConfigLoaded is false (schema-migrate.ts:923-946). The command passes the plan only the driver and dbLabel, never 'inventory' (organization-ownership.ts:113-143). That one call site is the only production caller (git grep). (3) The one path that touches no fenced file is an ambient read inside the inventory module at import time, an env var or a conventional file path. NOT TAKEN: it is a new, undeclared input, which conflicts with AGENTS.md 'Explicit composition over default magic'. An import-time refusal would also escape the command's refuse() envelope, so --json would emit no plan_refused payload. And the flag the design really wants would later make it a second spelling to retire. (4) The fenced edit is small. One flag on the command (e.g. --fates FILE) is read in both modes and passed as 'inventory:' to buildOrganizationOwnershipPlan and to #23034's applyOrganizationOwnership; an invalid supplement maps to a refusal through refuse(). organization-ownership-plan.ts, organization-ownership-apply.ts and schema-migrate.ts need no edit, and the plan's undeclared-table refusal (plan.ts:769-775) stays byte-identical. The digest already covers the merged list, so the marker and #23034's checkpoint are tied to the supplement. Sequencing fact: #23034's body holds it in draft 'until #15204 stage 8 is on main', and stage 8 is #23222, which is commit 66949b7, an ancestor of origin/main (merge-base --is-ancestor exit 0). The fenced files are unchanged between 66949b7 and origin/main bae5841 (git diff exit 0, empty).",
"tests": "No code was written, so no test was run. Gate derivation on the final (empty) tree: 'node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack' exited 2: 'this branch changes nothing against origin/main (merge base 66949b7) — nothing to derive'; the --repo check held. NOT MEASURED: every gate family, because there is no diff (the PM lead list in gates-23280.txt is moot). No ablation was run.",
"mcp_calls": "0",
"api_writes": "1 — POST /repos//issues/23280/comments (this os-dev-report, through scripts/pm/post-stamped.mjs). Not a REST write: one 'git push -u origin claude/issue-23280-host-declared-fates', of an empty branch at 66949b7. Reads only otherwise (gh api GET): issue 23280 and its comments, issue 15211 and its comments, pulls/23034 and its files. One read was refused: GET /repos/objectstack-ai/cloud/issues/2868 answered 403 (cloud GitHub access is not enabled for this session); add_repo was not called.",
"open_questions": [
{
"question": "Sequencing: build the whole card after PR #23034 lands, or split a build-ahead half off now?",
"options": [
"A — one PR after #23034 lands: the spec schema for supplement rows, mergeHostFateSupplement in the inventory module, the :179 sentence, the flag on the command and the three pins. The card is closed by Fixes.",
"B — split now: a 'Part of #23280' PR with the spec schema, the merge function, the :179 sentence and the pins, driven through the plan's existing 'inventory' option (no fenced file); then a second PR for the flag after #23034."
],
"recommendation": "A. Critical path: cloud's orchestration (cloud#2868) is itself blocked on #23034 (pointer 6146512692), so B starts cloud no sooner. B also publishes a spec schema with no CLI reader in the window between the PRs: a declared input nothing reads, which the startup-stage axis and declared-is-enforced weigh against. And A is one review of one contract, not two."
},
{
"question": "The two fixture pins need the table names, and the card does not spell them. The control list counts to 22, not 23: sys_billing_* x7, plus 7 named tables, plus ai_* x8. The 7 sys_billing_* and the 8 ai_* names are wildcards. The source, cloud#2867 6147243232 item I10, is not readable from this session.",
"options": [
"A — the PM or the cloud seat pastes the exact 23 control and 11 tenant names into the resumed dispatch",
"B — the resumed run attaches objectstack-ai/cloud read-only (add_repo) and reads the rehearsal record"
],
"recommendation": "A, because the dispatch fences these names as 'names only', and the seat that measured them holds the authoritative list."
},
{
"question": "Zone 2.3 asks that a supplement row naming 'an object the host does not provide' be refused. The plan boot does not compose the host stack (hostConfigLoaded false), so the plan holds no list of the host's objects. Which rule should replace it?",
"options": [
"A — refuse only platform objects (PLATFORM_OBJECTS_BY_PACKAGE, plus every inventory row whose census is not cloud-supplement). A supplement row whose object has no table on this database is listed 'absent', the way an inventoried object is today. One host supplement then serves both the control-plane and tenant database kinds.",
"B — compose the host stack on the plan boot to read the declared object set. That is a fenced edit (organization-ownership.ts / schema-migrate.ts), and it widens the read-only plan's boot."
],
"recommendation": "A. It keeps the plan's read-only boot and reuses the plan's existing 'absent' fact. Drift still cannot pass silently: an undeclared host table with data is still refused by name at plan.ts:769-775."
},
{
"question": "Wording: once the flag exists, the undeclared-table refusal (plan.ts:772-773) still says 'the inventory (packages/cli/src/utils/organization-ownership-inventory.ts) owes it a row'. For a host's table, that sends the operator to objectstack's source rather than to their own supplement. The text is accurate today, because no supplement exists. Zone 3 asks for it to stay byte-identical.",
"options": [
"A — keep it byte-identical (Zone 3), and name the flag in the command's description and in the changeset",
"B — the resumed run adds one remedy clause naming the flag (plan.ts is fenced until #23034 lands)"
],
"recommendation": "B, once #23034 is on main. This is author-facing remedy text, and AGENTS.md's 'Absence must be loud ... naming the remedy' fits it. Zone 3 is optional by the dispatch's own terms."
}
],
"out_of_scope_findings": [
"carrier: the resumed #23280 run (the refusal-remedy wording at plan.ts:772-773, open question 4) · noted, not filed; no defect today",
"carrier: the PM (the card's '23 control-plane tables' enumerates 22; open question 2) · noted, not filed"
]
}
Release: session session_01BRQ9Mp1yH7R1az6MaUM18H (domain:spec#2) · cause: the dev stopped before any edit (report 6148706704): the ceremony reads a host supplement only through packages/cli/src/commands/migrate/organization-ownership.ts, which open draft PR #23034 holds · to: pm:blocked, unassigned. Branch claude/issue-23280-host-declared-fates was pushed empty at 66949b772, so the next claim starts from zero.
#23034 is Part of #22937, so #22937 does not close when it merges; the line names the PR itself, which closes at that moment. #23034's own hold ("until #15204 stage 8 is on main") is met: stage 8 is 66949b772, an ancestor of main (read by the dev).
The seat's answers to the report's four questions
They are sequencing, test data and wording calls, so the seat answers them and does not escalate. The next claim's dispatch carries them verbatim.
Fixture names → neither A nor B. The tests take the tables the card names (seven on the control database, three on a tenant database), and labelled placeholder names (for example sys_billing_fixture_1) for the two wildcard families. The real list is cloud's to declare in its own supplement (the C10 stage), so no objectstack test pins cloud's table names. Note for the record: the card's "23 control-plane tables" enumerates 22 (7 + 7 + 8).
What a supplement may name → A. A supplement row is refused when it names a platform object (one the platform inventory already gives a fate). A supplement row whose table this database lacks is listed "absent", as an inventoried object is today, so one supplement serves both the control-plane and the tenant database. An undeclared table that holds data is still refused by name.
The ambient path the report measured and declined (an environment variable or a conventional file read when the inventory module is imported) stays declined: it is an undeclared input, and it would refuse outside the command's --json envelope.
At landing, the seat records the mechanism (a host supplement read through the command's flag) on #15211, where the C10 row names no mechanism today.
Unlock scan: pm:blocked → pm:queue. Blocked-by: #23034 is satisfied: PR #23034 (the ceremony's --apply, C7b) merged as 2808069121
Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-13T17:57Z. ⛔ Not a claim, ⛔ not a dispatch.
Re-derived at this act: the merge was at 2026-10-13T17:12Z. The file the released claim could not touch, packages/cli/src/commands/migrate/organization-ownership.ts, is now free on main.
Grade and lane kept: p1 target:v18, domain:spec (Clause-②: yes). The seat's four answers in its release (6148865508) travel with the next claim's dispatch verbatim. Sequencing is A: one PR with the supplement schema, the inventory merge, the corrected :177–:179 sentence, one flag read in both plan and apply modes, and the pins.
Waiting on it: objectstack-ai/cloud#2868 (cloud's run of the ceremony, p1).
Claim: PM loop round 1, rolling slot (#23280: a host declares the ADR-0131 D10 fates of its own objects through one supplement the ceremony reads, the inventory's C10 stage) · 2026-10-13T18:15Z
Session: session_012uFegdfR6K6uqvLzt7XsdZ
Account: os-support-ai (the seat's linked user as GET /user answers it; the card's assignee from this act)
Branch: claude/issue-23280-host-fate-supplement
Worktree: objectstack-issue-23280
Domain: domain:spec
Seat: domain:spec#3 (seat post #18883)
Ruling-ref: triage 6147745120; domain:spec#2's release 6148865508, whose four answers (sequencing A, fixture names, what a supplement may name A, refusal wording B) travel with this dispatch verbatim; triage's unlock 6151838864 (PR #23034 merged as 2808069121). All read in this act, along with the released dev report 6148706704 (the measured call shape).
File surface (at origin/main404fc477e or later; stop on a breach and explain it in the report):
host-supplement rows merge into the inventory on the same terms as the platform's rows;
the CLOUD premise sentence (:177-179) cites objectstack-ai/cloud#2866 A in place of the superseded record 6094175435.
packages/cli/src/commands/migrate/organization-ownership.ts: one flag, read in both plan and apply modes and passed as inventory to buildOrganizationOwnershipPlan and to applyOrganizationOwnership. An invalid supplement maps to a refusal through refuse(), inside the --json envelope.
packages/cli/src/utils/organization-ownership-plan.ts: text only. The undeclared-table refusal (:821) gains one remedy clause naming the flag (answer 4, B). Its condition does not change.
The supplement's declared shape: a spec schema under packages/spec/src/system/, with its generated projections, so the input is declared, not ambient.
The command's docs page, if it lists the flags.
Tests, with the pins triage names:
a host-declared fate is planned like a platform row;
an undeclared host table that holds data is still refused, by name;
a supplement row naming a platform object is refused (answer 3, A);
a supplement row whose table this database lacks is listed "absent";
the plan on a control-plane-shaped fixture and on a tenant-shaped fixture names every table. It uses the card's named tables plus labelled placeholders for the two wildcard families (answer 2), and ⛔ no real cloud table list.
One .changeset/23280-*.md.
⛔ No guessed fate inside objectstack for any cloud table. ⛔ No ambient input (an env var, or a conventional file read at import time): declined in 6148865508. ⛔ No change to the apply path's semantics (PR feat(cli): os migrate organization-ownership --apply — the ADR-0131 D10 ceremony (C7b, PR 2 of 3) #23034) beyond passing inventory.
Container & model: M, mode:subagent, model: default tier. It widens a published input of the ceremony, so it owes a review at CONTRACT_REVIEW_TIER before the queue, by an isolated at-tier subagent.
Clause-②: yes (a host-declared fate supplement becomes a published input of os migrate organization-ownership)
Responsibility: the ceremony's inventory and its command (packages/cli), routed to the spec lane by triage under 强制条款② | none today: the plan refuses every table with no fate, and no host channel exists | every host whose own tables carry organization_id; cloud's tenant and control databases first (objectstack-ai/cloud#2867 item I10; objectstack-ai/cloud#2868 waits)
Thread-read: 6151838864
Serial constraints cleared (the file lists of all 6 open PRs and all open pm:dispatched claims, read in this act):
domain:spec#2's released claim (6148505516) left an empty branch claude/issue-23280-host-declared-fates at 66949b772. This claim starts from zero on its own branch.
os-dev-report
{
"issue": 23280,
"status": "done",
"branch": "claude/issue-23280-host-fate-supplement",
"pr": "#23348",
"pr_number": 23348,
"head_sha": "066963bb09de94ff3cc138bcd16a33ceb59e58f9",
"session": "session_012uFegdfR6K6uqvLzt7XsdZ (mode:subagent; the domain:spec#3 PM's id)",
"premise_still_valid": true,
"summary": "A host declares the ADR-0131 D10 fates of the objects it provides in one JSON file. os migrate organization-ownership --fate-supplement FILE reads it in both modes and passes the merged list as inventory to buildOrganizationOwnershipPlan and to applyOrganizationOwnership. The apply path is otherwise unchanged. The file is declared in the spec: OrganizationOwnershipSupplementSchema, a JSON array of OrganizationOwnershipSupplementEntrySchema rows, in packages/spec/src/system/fate-supplement.zod.ts. Each fate is a strict discriminated arm that admits only the keys that fate reads, and census, cloudCarried and external are not authorable. mergeHostFateSupplement in organization-ownership-inventory.ts stamps each row with census host-supplement. A row that replaces one of the 8 cloud(...) placeholders keeps that placeholder's place. Refusals: a row naming an object the platform inventory already gives a fate (answer 3); two rows naming one object (H5). A row whose table this database lacks is planned absent. Every refusal of the file (missing, not JSON, not an array, a row the schema refuses, a duplicate, a platform object) is a HostFateSupplementRefusal mapped through refuse() inside the --json envelope, naming file, row (zero-based) and object, before the database is opened. The undeclared-table refusal in plan.ts gained one remedy clause naming --fate-supplement FILE (answer 4); its condition is unchanged and that is the only edit in plan.ts. The CLOUD premise sentence now cites cloud ruling record 6146394952 (objectstack-ai/cloud#2866 A) instead of 6094175435. It is written as a record id because it is a runtime string. No fate is guessed for any cloud table, and there is no ambient input.",
"flag": "--fate-supplement FILE. Reason (stated in the PR body): 'supplement' is ADR-0131 D10's own word for this input, and 'fate' names what it supplements. '--fates' reads like a filter over the plan's fates, and '--supplement' alone does not say what it supplements.",
"supplement_schema": "OrganizationOwnershipSupplementSchema (the file) and OrganizationOwnershipSupplementEntrySchema (one row) in packages/spec/src/system/fate-supplement.zod.ts, exported from @objectstack/spec/system. Building blocks exported alongside: OrganizationOwnershipFateSchema, ...RowConditionSchema, ...AnchorSchema, ...CategorySchema, ...DepartureSchema. Type aliases are z.input (ADR-0122); the seven input==infer equalities are pinned in type-alias-convention.pin.test.ts.",
"one_shape": "Derived plus pinned. The CLI's OrganizationOwnershipFate, RowCondition, Anchor, InventoryCategory and InventoryDeparture are now aliases of the spec types, and ORGANIZATION_OWNERSHIP_FATES is OrganizationOwnershipFateSchema.options. Only the top-level key list stays in the CLI, held equal three ways: (1) compile-time spec to CLI, because the merge assigns a parsed spec row into InventoryEntry; (2) the compile-time KEYS_AGREE equality in organization-ownership-inventory.test.ts, reverse-verified red (TS2322 at 161:7) when a key was added to InventoryEntry; (3) runtime CLI to spec, because every platform row minus census/cloudCarried/external parses under the spec row schema. The platform rows use all 5 condition forms, 3 anchor kinds, 2 category forms and 2 departure forms.",
"H3_measured": "cloudCarried is an output marker only. The plan copies it onto TablePlan (planPresentTable / absentTable) and apply never reads it. So the 8 cloud(...) rows are fate-4 placeholders: a supplement row naming one replaces it in place and is not a 'platform object'. Without a supplement the rows stand unchanged; their citation text changed, per the claim. The rows were not deleted and were given no fate.",
"H4_measured": "inventoryDigest hashes the merged list, so the plan's digest and the apply checkpoint are keyed on the supplement (pinned: plan.inventoryDigest == inventoryDigest(merged), and differs from the platform-only digest). --apply with a different supplement, or none, than the checkpoint it resumes is NOT refused. applyOrganizationOwnership discards a checkpoint whose digest mismatches, logs 'the inventory changed since the recorded checkpoint, so every step runs again (each is idempotent)', and re-runs every step. The kept plan file is not an input of --apply. Reported as a finding; no mechanism built.",
"H1_H2_H5_H6": "H1 as stated: no census in the row; the merge stamps it. H2: JSON only, because no migrate sibling reads YAML. H5: duplicates are refused in the CLI merge; a spec .refine would be a dropped refinement in the shrink-only dropped-refinements.baseline.json. H6: reused the better-sqlite3 + PlanReader harness of organization-ownership-plan.integration.test.ts.",
"files_changed": [
".changeset/23280-host-fate-supplement.md",
"content/docs/getting-started/quick-reference.mdx",
"content/docs/references/index.mdx",
"content/docs/references/system/fate-supplement.mdx",
"content/docs/references/system/index.mdx",
"content/docs/references/system/meta.json",
"docs/audits/2026-07-unknown-key-strictness-ledger.counts/system.md",
"packages/cli/src/commands/migrate/organization-ownership.fate-supplement.integration.test.ts",
"packages/cli/src/commands/migrate/organization-ownership.ts",
"packages/cli/src/utils/organization-ownership-host-supplement.integration.test.ts",
"packages/cli/src/utils/organization-ownership-inventory.test.ts",
"packages/cli/src/utils/organization-ownership-inventory.ts",
"packages/cli/src/utils/organization-ownership-plan.ts",
"packages/spec/api-surface/system.json",
"packages/spec/authorable-surface/system.json",
"packages/spec/declaration-map/system.json",
"packages/spec/export-origins/system.json",
"packages/spec/json-schema.manifest/system.json",
"packages/spec/llms.txt",
"packages/spec/scripts/liveness/empty-state-registry.mts",
"packages/spec/src/system/fate-supplement.test.ts",
"packages/spec/src/system/fate-supplement.zod.ts",
"packages/spec/src/system/index.ts",
"packages/spec/src/type-alias-convention.pin.test.ts",
"packages/spec/variant-docs.json"
],
"line_budget": "1930 changed lines (+1855 / -75) across 25 files vs merge base cc14657, generated files included (dispatch-gates reading at 066963b); under the 3000 human-merge threshold.",
"gates": "At 066963b, node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derives 114 commands. All 114 ran on that head with each exit captured before any pipe; all exited 0, none 3. --ran reconciliation: '114 derived, 114 run, 0 NOT-MEASURED, 0 UNRUN (a DERIVED zero)'. check:dts-closure and check:dual-build-cjs-loads first exited 1 on one partial @objectstack/organizations dist that my own killed stray build had left; both were re-run green after a turbo rebuild under the lock. check:type-check-debt ran under the lock because it builds the workspace. Earlier gates that exited 3 (check:i18n family, check:dual-build-cjs-loads) were re-run after real builds and not counted. Real findings fixed on the way, all spec-gate registrations a new exported schema needs: check:spec-parsed-alias (ADR-0122), check:empty-state, check:llms-txt, check:variant-docs, check:quick-reference-counts.",
"tests": "CLI on merged head 2da5e78: the six ceremony files (inventory 22, plan.integration 11, apply 9, host-supplement.integration 7, apply-flags 3, fate-supplement.integration 7) = 59 passed; pnpm --filter @objectstack/cli typecheck green (tsc + check:test-typecheck OK); whole unit layer vitest run --project unit --shard=N/4 = 287 files / 4306 tests passed (shard 4 at 066963b, docs-only delta). Spec: pnpm --filter @objectstack/spec test (local) 670 files / 20284 passed at 11764ed (pre-merge); on the merged head fate-supplement.test.ts (8) and type-alias-convention.pin.test.ts (3) green; check:generated all 14 artifacts current. Spec test:repo, 3 shards on merged head: 58 of 59 files fully green (307 + 280 tests in shards 1-2, 18 complete files in shard 3). DECLARED NARROWING: scripts/build-schemas-check-mode.test.ts ran 20 of 88 cases green; each case re-runs build-schemas (13-28 s), so the file is about 30 min of serial lock time on this shared box. The remaining 68 cases are NOT MEASURED locally and left to CI's repo project; the diff touches neither build-schemas.ts nor authorable-surface.base.json. Ablations through scripts/ablation-replace.mjs (wrap mode, under the lock, trap restore from HEAD by absolute path, restore proven blob == HEAD with git diff HEAD empty): (1) command does not pass inventory (anchor x2 -> x0, blob b5aa7463 -> 901af2d0): exactly 'with it, the host-declared fate is planned like a platform row' and 'with --fate-supplement, the apply step receives the host row' went red (2 failed / 27 passed), restored to b5aa7463 == HEAD; (2) platform-object refusal dropped (anchor x1 -> x0, blob c9791d01 -> e0e81f8c): the three pin-3 tests went red (3 failed / 26 passed), restored to c9791d01 == HEAD. Reverse verification of KEYS_AGREE: the first attempt was a NO-OP, because the tool refused when the replacement contained its anchor and tsc did not run. Re-anchored: blob c9791d01 -> a8716c85, then tsc --noEmit gave exactly 'organization-ownership-inventory.test.ts(161,7): error TS2322', restored to c9791d01 == HEAD. These are CLI-src subjects resolved relatively, so no dist preflight was needed. eslint --no-inline-config on the 10 touched TS files: exit 0.",
"mcp_calls": "0 MCP GitHub calls. One SendMessage reply to the PM's status probe, which is not a GitHub tool.",
"api_writes": "3 REST requests in 2 relay strokes, all through scripts/pm as objectstack-fleet[bot]: (1) pr_create via scripts/pm/fleet-write/dispatch.mjs (run 38483113693): POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /repos//issues/23348/assignees [os-support-ai]; read back as 15613 bytes sent, 15613 stored, identical; (2) this os-dev-report: POST /repos//issues/23280/comments via scripts/pm/post-stamped.mjs. Not REST: git push of the branch (empty probe first, then WIP commits; never force). Zero label writes, because the dispatch's write budget names none and skip-changeset does not apply (a changeset exists).",
"deviations": [
"File surface: beyond the claim's literal list, the spec gates required registrations every new exported spec schema needs. These are packages/spec/llms.txt (inventory count 204 to 205, system 35 to 36), packages/spec/scripts/liveness/empty-state-registry.mts (two 'scope' rows: category where, mirror), packages/spec/variant-docs.json (two generated-reference-only exemptions stating the docs gap), packages/spec/src/type-alias-convention.pin.test.ts (seven isomorphic pins instead of seven XParsed synonyms), and content/docs/getting-started/quick-reference.mdx (System total 35 to 36). Read as part of 'its generated projections'; the triggering gate is named for each in the PR body.",
"Spec module named fate-supplement.zod.ts, not organization-ownership-supplement.zod.ts. gen:docs refused the longer name: the reference page title was 51 characters, outside the 36-46 band, and no ladder rung fits. Renaming was the in-scope fix; adding a rung to the docs tooling was not.",
"The command's docs page: none exists. No file under content/docs names --fate-supplement or --backup-taken; measured with a control hit on the command source. So no docs page was edited.",
"Declared narrowing: 68 of 88 cases of packages/spec/scripts/build-schemas-check-mode.test.ts are NOT MEASURED locally (see tests); left to CI.",
"Spec local suite (670 files) ran pre-merge at 11764ed. Post-merge only my two spec test files re-ran (green). The merge brought main's own spec changes, which are disjoint from this diff; check:generated was green on the merged tree.",
"My own background gate runner's check:type-check-debt launched an unlocked whole-workspace turbo build that raced my locked builds and produced two transient dts failures. I stopped it by PID (my process tree only), rebuilt under the lock, and ran that gate under the lock from then on."
],
"open_questions": [],
"out_of_scope_findings": [
"carrier: the domain:spec#3 seat at landing (its #15211 mechanism record) - H4: --apply resuming with a different supplement, or none, than its checkpoint is not refused; the mismatched checkpoint is discarded and every idempotent step re-runs, and the kept plan file is not an input of --apply. Existing behaviour from #23034, not a defect or a contract violation; noted, not filed. Dedupe words: organization-ownership checkpoint digest supplement, apply resume inventory changed, plan file not read by apply",
"carrier: none (Acceptance notes only) - the corrected CLOUD citation is part of the hashed rows, so an apply checkpoint recorded on a pre-merge build re-runs its steps once (each is idempotent); v18 is unreleased. Noted, not filed.",
"carrier: none (Acceptance notes only) - packages/cli/test/hook-timeout-override-refusal.test.ts: each of its two CONTROL legs spawns vitest list against vitest's 5 s default timeout and measured 3.9-5.1 s here. One leg timed out on each of two of three runs under load (load average 4-9); the third run passed 4/4. The file is untouched by this diff. Not one of the three filing classes (no public door, no named producer). Dedupe words: hook-timeout-override-refusal CONTROL timeout, vitest list 5000ms",
"carrier: none (Acceptance notes only) - no hand-written page documents the v18 ceremony's inputs (--fate-supplement, --backup-taken); variant-docs.json now states that gap on its two new exemptions."
],
"worktree": "/home/user/objectstack-issue-23280: node_modules removed and worktree removed after this report is posted (see the final message)."
}
✅ ACCEPT (seat review): PR #23348 at a0cbcf9cf. The contract-tier review is owed before the queue · domain:spec seat 3 (seat post #18883) · session_012uFegdfR6K6uqvLzt7XsdZ · 2026-10-14T00:41Z
PR shape.
Draft against main, assigned to os-support-ai. Line 1 is Fixes #23280; line 2 is the claim's Clause-②: line, verbatim.
25 files, +1861 / −75 against bbb975771. It touches no governed path and stays under the human-merge threshold.
The flag.--fate-supplement FILE is read before the database is opened, in both modes, and passed as inventory to buildOrganizationOwnershipPlan and to applyOrganizationOwnership. A file that cannot be used is refused through refuse() inside the --json envelope, with a reason code, the file, the row index and the object. Nothing is read without the flag.
The declared shape.OrganizationOwnershipSupplementSchema / ...EntrySchema (@objectstack/spec/system, fate-supplement.zod.ts) has strict per-fate arms. census, cloudCarried and external are not authorable. The CLI's row vocabulary (fate, condition, anchor, category, departure) is now derived from the spec types, and the top-level key list is held equal by a compile-time equality (reverse-verified red) and a runtime parse of every platform row.
The merge (mergeHostFateSupplement):
a row naming an inventoried object is refused (answer 3), unless that row is one of the 8 cloud-supplement placeholders, which it replaces in place (H3);
two rows for one object are refused (H5);
new rows are appended in name order, so the digest names content, not file order.
The refusal at plan.ts:821 gains only the remedy clause naming the flag (answer 4); its condition is unchanged.
The CLOUD premise now cites cloud ruling record 6146394952 (objectstack-ai/cloud#2866 A) in place of 6094175435.
The pins, each with a control:
A host row is planned like a platform row, with the flag, on the command and through apply.
An undeclared host table that holds data is still refused by name, and the refusal names the flag.
A row naming a platform object is refused.
A row whose table is absent is listed absent.
The control-plane-shaped and tenant-shaped fixtures name every table. They use the card's named tables plus labelled placeholders (answer 2); no cloud list appears anywhere.
The H4 digest pin: the plan digest equals the merged list's, and differs from the platform-only digest.
The ablations, re-run on the merged head, each restored to blob == HEAD:
the command not passing inventory turns the two pin-1 tests red;
dropping the platform-object refusal turns the three pin-3 tests red.
The surface grew by the registrations a new exported spec schema owes (llms.txt, the empty-state registry, variant-docs.json with two stated docs-gap exemptions, the alias pins, the quick-reference count). Each is named with its triggering gate in the PR body; they are read as "its generated projections".
Landing to-do, recorded now:
needs:contract-review goes on the PR in this act. The review runs on a0cbcf9cf.
When the review is PASS and every check is green: ready, then auto-merge, then the queue.
Landed: PR #23348 → 707b3cd91 (Fixes #23280). A host declares the ADR-0131 D10 fates of its own objects through os migrate organization-ownership --fate-supplement FILE
The contract-tier review PASSed on a0cbcf9cf (6158469179).
Every check was green or an expected skip (12 of 12 in the roster), with mergeable: clean. check-governed-merges reported it NOT governed, at 1936 lines.
Ready and auto-merge went on at 2026-10-14T01:01Z. The PR entered the queue at 2026-10-14T01:02Z, and the queue merged it at 2026-10-14T01:30Z.
On main at 707b3cd91: 25 files, +1861 / −75. The patch-id --stable equals that of bbb975771..a0cbcf9cf: byte-identical to the reviewed head.
What a host now does:
It writes one JSON file against OrganizationOwnershipSupplementSchema (@objectstack/spec/system) and passes it with --fate-supplement in both plan and apply modes.
A row naming a platform object, a duplicate row, or a row the schema refuses is refused before the database is opened, inside the --json envelope.
A row for one of the 8 cloudCarried placeholders replaces it in place.
A table the database lacks is listed absent.
An undeclared host table is still refused by name, and the refusal names the flag.
Activity
objectstack-fleet commentedon Oct 13, 2026
Triage: first grade,
bug·priority:p1·target:v18·domain:spec, intopm:queue(findingremoved). A host declares the ADR-0131 D10 fates of its own objects, and the ceremony reads them: the inventory's C10 stage, now that cloud moves to v18Triage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-13T14:22Z. ⛔ Not a claim, ⛔ not a dispatch.origin/main(c0569797a6):packages/cli/src/utils/organization-ownership-inventory.ts:179still gives the premise: "no v18 ceremony runs against a cloud database … C10 assigns it when cloud moves". Its rows for cloud tables carrycloudCarried: true(:210).target:v18: the plan refuses on every cloud database (measured in the rehearsal, objectstack-ai/cloud#28676147243232, item I10), so cloud's v18 upgrade (objectstack-ai/cloud#2709) cannot run. Ruling A on objectstack-ai/cloud#2866 (6146394952) puts tenant databases through this ceremony. The maintainer withdrew the clear (objectstack-ai/cloud#28436145481762). The "cloud stays on v17" premise is superseded, so this is the inventory's own C10, ⛔ not a new decision.Clause-②: yes: spec-lane work with contract-tier review. The claim declares the CLI files it touches.--apply, C7b 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) is in flight on the same inventory and plan files. The claim reads its state and sequences behind it or with it.:179) cites cloud#2866 A instead of the superseded record.packages/cli/src/utils/organization-ownership-inventory.tsand the declared host channel) (domain:spec, Clause-② yes); rationale: the ceremony must run on a host's database without guessing.objectstack-fleet commentedon Oct 13, 2026
Claim: PM loop round 1 (#23280, triage
6147745120: a host declares the ADR-0131 D10 fates of its own objects, read by the ceremony — the inventory's C10 stage) · 2026-10-13T14:59ZSession:
session_01BRQ9Mp1yH7R1az6MaUM18HAccount:
os-justin(the seat's linked user asGET /useranswers it; the card's assignee from this act)Branch:
claude/issue-23280-host-declared-fatesWorktree:
objectstack-issue-23280Domain:
domain:specSeat:
domain:spec#2(seat post #18549)File surface (at
origin/main66949b772or later; stop on breach and explain in the report):packages/cli/src/utils/organization-ownership-inventory.ts: the host-declared fates joining the inventory as the platform's rows do, and the:179premise sentence citing objectstack-ai/cloud#2866 A;packages/spec/src/system/if the channel is a declared input, with its generated projections;.changeset/23280-*.md.packages/cli/src/commands/migrate/organization-ownership.ts,packages/cli/src/utils/organization-ownership-plan.ts,organization-ownership-apply.tsorschema-migrate.ts: PR feat(cli): os migrate organization-ownership --apply — the ADR-0131 D10 ceremony (C7b, PR 2 of 3) #23034 (C7b build-ahead:os migrate organization-ownership --applyand E5's pure row→definition mappers in core (drafts from main; the --apply PR lands after #15204 stage 8) #22937,domain:engine) is in flight on them. If the host channel cannot reach the plan without editing one of them, the dev stops before editing, and this seat sequences behind PR feat(cli): os migrate organization-ownership --apply — the ADR-0131 D10 ceremony (C7b, PR 2 of 3) #23034.Container & model:
M,mode:subagent,model: default tier(dispatch-gates --tier: no path-derived mandate). ACONTRACT_REVIEW_TIERreview by an isolated subagent precedes the queue.Clause-②: yes (a new host-declared input to the ceremony widens a published input, per triage)
Responsibility: the ceremony's inventory (
organization-ownership-inventory.ts), which marks every cloud tablecloudCarriedwith no fate on the superseded "cloud stays on v17" premise | none: the plan refuses any table with no fate, and no host channel exists | every host whose own tables carryorganization_id(cloud's control-plane and tenant databases, measured in objectstack-ai/cloud#28676147243232item I10)Thread-read: 6147745120
Serial constraints cleared (all open PRs' file lists read in this act; the lane's queue re-read in this act, with this card the one open p1 and no
pm:blockingcard):os migrate organization-ownership --applyand E5's pure row→definition mappers in core (drafts from main; the --apply PR lands after #15204 stage 8) #22937,domain:engineseat, in flight) editsorganization-ownership.ts,-plan.ts,-apply.tsandschema-migrate.ts, so those are fenced off above. The plan is the inventory's only reader.pm:blocked,domain:engine) is the family's parent. The mechanism is recorded there at landing, as triage asks.packages/specconversions and migrations, which is disjoint from this surface.This act moves the card
pm:queue→pm:dispatchedand assignsos-justin.Generated by Claude Code
objectstack-fleet commentedon Oct 13, 2026
os-dev-report
{
"issue": 23280,
"status": "blocked",
"branch": "claude/issue-23280-host-declared-fates",
"pr": null,
"session": "session_01BRQ9Mp1yH7R1az6MaUM18H (subagent of the domain:spec#2 PM; parent's id)",
"premise_still_valid": true,
"summary": "STOPPED BEFORE ANY EDIT, on the dispatch's Zone 1 fork clause: the ceremony cannot read a host supplement without an edit to packages/cli/src/commands/migrate/organization-ownership.ts, which PR #23034 holds. Nothing is committed. The branch was pushed empty at BASE 66949b7 (it serves as the write probe and the landing marker), and the worktree is removed. Mechanism record: ADR-0131 section 8 and #15211 record no C10 mechanism. Row C10 reads 'cloud: control plane and objectos-ee adopt the record (per-deployment no-column, backfill, tests)'. On #15211, 6095639085 says only 'C10 assigns their fates', and 6138240272 says 'C10 (cloud#1979) remains cloud's code adaptation'. ADR-0131 D10 itself says the inventory is driven by 'cloud's supplement for cloud-declared ones'. So the PM's default, a host supplement in the inventory's entry shape, stands, and D10's wording supports it. Measured call shape: (1) Assumption 1 HALF HOLDS. The plan does not build the list itself. buildOrganizationOwnershipPlan already takes 'inventory?: readonly InventoryEntry[]', defaulting to the module const ORGANIZATION_OWNERSHIP_INVENTORY (organization-ownership-plan.ts:722-729), and so does inventoryDigest (:175). PR #23034's apply takes opts.inventory too, else inventoryEntryFor (its apply.ts patch). But the const is fixed when the module is evaluated, and nothing in the call chain calls into the inventory module before the plan reads it. Rows merged 'inside the inventory module' therefore need a trigger, and the only trigger is the command. (2) Assumption 2 DISPROVED. 'cloud-supplement' is a census LABEL on 8 hard-coded rows (inventory.ts:30-35, :205-211, :556-559), not a readable slot. The ceremony reads these inputs today: --database-url (env OS_DATABASE_URL), --out and --json; #23034 adds --apply and --backup-taken; the posture comes from resolveTenancyPosture(); and the database catalog. The plan boot is bootSchemaStack with deferSchemaDdl and readOnlyProbe and without composeHostStack, so hostConfigLoaded is false (schema-migrate.ts:923-946). The command passes the plan only the driver and dbLabel, never 'inventory' (organization-ownership.ts:113-143). That one call site is the only production caller (git grep). (3) The one path that touches no fenced file is an ambient read inside the inventory module at import time, an env var or a conventional file path. NOT TAKEN: it is a new, undeclared input, which conflicts with AGENTS.md 'Explicit composition over default magic'. An import-time refusal would also escape the command's refuse() envelope, so --json would emit no plan_refused payload. And the flag the design really wants would later make it a second spelling to retire. (4) The fenced edit is small. One flag on the command (e.g. --fates FILE) is read in both modes and passed as 'inventory:' to buildOrganizationOwnershipPlan and to #23034's applyOrganizationOwnership; an invalid supplement maps to a refusal through refuse(). organization-ownership-plan.ts, organization-ownership-apply.ts and schema-migrate.ts need no edit, and the plan's undeclared-table refusal (plan.ts:769-775) stays byte-identical. The digest already covers the merged list, so the marker and #23034's checkpoint are tied to the supplement. Sequencing fact: #23034's body holds it in draft 'until #15204 stage 8 is on main', and stage 8 is #23222, which is commit 66949b7, an ancestor of origin/main (merge-base --is-ancestor exit 0). The fenced files are unchanged between 66949b7 and origin/main bae5841 (git diff exit 0, empty).",
"tests": "No code was written, so no test was run. Gate derivation on the final (empty) tree: 'node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack' exited 2: 'this branch changes nothing against origin/main (merge base 66949b7) — nothing to derive'; the --repo check held. NOT MEASURED: every gate family, because there is no diff (the PM lead list in gates-23280.txt is moot). No ablation was run.",
"mcp_calls": "0",
"api_writes": "1 — POST /repos//issues/23280/comments (this os-dev-report, through scripts/pm/post-stamped.mjs). Not a REST write: one 'git push -u origin claude/issue-23280-host-declared-fates', of an empty branch at 66949b7. Reads only otherwise (gh api GET): issue 23280 and its comments, issue 15211 and its comments, pulls/23034 and its files. One read was refused: GET /repos/objectstack-ai/cloud/issues/2868 answered 403 (cloud GitHub access is not enabled for this session); add_repo was not called.",
"open_questions": [
{
"question": "Sequencing: build the whole card after PR #23034 lands, or split a build-ahead half off now?",
"options": [
"A — one PR after #23034 lands: the spec schema for supplement rows, mergeHostFateSupplement in the inventory module, the :179 sentence, the flag on the command and the three pins. The card is closed by Fixes.",
"B — split now: a 'Part of #23280' PR with the spec schema, the merge function, the :179 sentence and the pins, driven through the plan's existing 'inventory' option (no fenced file); then a second PR for the flag after #23034."
],
"recommendation": "A. Critical path: cloud's orchestration (cloud#2868) is itself blocked on #23034 (pointer 6146512692), so B starts cloud no sooner. B also publishes a spec schema with no CLI reader in the window between the PRs: a declared input nothing reads, which the startup-stage axis and declared-is-enforced weigh against. And A is one review of one contract, not two."
},
{
"question": "The two fixture pins need the table names, and the card does not spell them. The control list counts to 22, not 23: sys_billing_* x7, plus 7 named tables, plus ai_* x8. The 7 sys_billing_* and the 8 ai_* names are wildcards. The source, cloud#2867 6147243232 item I10, is not readable from this session.",
"options": [
"A — the PM or the cloud seat pastes the exact 23 control and 11 tenant names into the resumed dispatch",
"B — the resumed run attaches objectstack-ai/cloud read-only (add_repo) and reads the rehearsal record"
],
"recommendation": "A, because the dispatch fences these names as 'names only', and the seat that measured them holds the authoritative list."
},
{
"question": "Zone 2.3 asks that a supplement row naming 'an object the host does not provide' be refused. The plan boot does not compose the host stack (hostConfigLoaded false), so the plan holds no list of the host's objects. Which rule should replace it?",
"options": [
"A — refuse only platform objects (PLATFORM_OBJECTS_BY_PACKAGE, plus every inventory row whose census is not cloud-supplement). A supplement row whose object has no table on this database is listed 'absent', the way an inventoried object is today. One host supplement then serves both the control-plane and tenant database kinds.",
"B — compose the host stack on the plan boot to read the declared object set. That is a fenced edit (organization-ownership.ts / schema-migrate.ts), and it widens the read-only plan's boot."
],
"recommendation": "A. It keeps the plan's read-only boot and reuses the plan's existing 'absent' fact. Drift still cannot pass silently: an undeclared host table with data is still refused by name at plan.ts:769-775."
},
{
"question": "Wording: once the flag exists, the undeclared-table refusal (plan.ts:772-773) still says 'the inventory (packages/cli/src/utils/organization-ownership-inventory.ts) owes it a row'. For a host's table, that sends the operator to objectstack's source rather than to their own supplement. The text is accurate today, because no supplement exists. Zone 3 asks for it to stay byte-identical.",
"options": [
"A — keep it byte-identical (Zone 3), and name the flag in the command's description and in the changeset",
"B — the resumed run adds one remedy clause naming the flag (plan.ts is fenced until #23034 lands)"
],
"recommendation": "B, once #23034 is on main. This is author-facing remedy text, and AGENTS.md's 'Absence must be loud ... naming the remedy' fits it. Zone 3 is optional by the dispatch's own terms."
}
],
"out_of_scope_findings": [
"carrier: the resumed #23280 run (the refusal-remedy wording at plan.ts:772-773, open question 4) · noted, not filed; no defect today",
"carrier: the PM (the card's '23 control-plane tables' enumerates 22; open question 2) · noted, not filed"
]
}
Generated by Claude Code
objectstack-fleet commentedon Oct 13, 2026
Release: session
session_01BRQ9Mp1yH7R1az6MaUM18H(domain:spec#2) · cause: the dev stopped before any edit (report6148706704): the ceremony reads a host supplement only throughpackages/cli/src/commands/migrate/organization-ownership.ts, which open draft PR #23034 holds · to:pm:blocked, unassigned. Branchclaude/issue-23280-host-declared-fateswas pushed empty at66949b772, so the next claim starts from zero.Blocked-by: #23034
#23034 is
Part of #22937, so #22937 does not close when it merges; the line names the PR itself, which closes at that moment. #23034's own hold ("until #15204 stage 8 is on main") is met: stage 8 is66949b772, an ancestor ofmain(read by the dev).The seat's answers to the report's four questions
They are sequencing, test data and wording calls, so the seat answers them and does not escalate. The next claim's dispatch carries them verbatim.
organization-ownership-inventory.ts:177-179, one flag on the command read in both plan and apply modes and passed asinventoryto both builders, and the pins. The PR closes this card withFixes. B is declined: it would publish a supplement schema with no CLI reader between the two PRs, and cloud's orchestration (objectstack-ai/cloud#2868) waits on feat(cli): os migrate organization-ownership --apply — the ADR-0131 D10 ceremony (C7b, PR 2 of 3) #23034 either way, so B starts cloud no sooner.sys_billing_fixture_1) for the two wildcard families. The real list is cloud's to declare in its own supplement (the C10 stage), so no objectstack test pins cloud's table names. Note for the record: the card's "23 control-plane tables" enumerates 22 (7 + 7 + 8).main, the undeclared-table refusal gains one remedy clause naming the flag, so an operator is sent to their own supplement rather than to objectstack's source.The ambient path the report measured and declined (an environment variable or a conventional file read when the inventory module is imported) stays declined: it is an undeclared input, and it would refuse outside the command's
--jsonenvelope.At landing, the seat records the mechanism (a host supplement read through the command's flag) on #15211, where the C10 row names no mechanism today.
Generated by Claude Code
1 remaining item
objectstack-fleet commentedon Oct 13, 2026
Unlock scan:
pm:blocked→pm:queue.Blocked-by: #23034is satisfied: PR #23034 (the ceremony's--apply, C7b) merged as2808069121Triage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-13T17:57Z. ⛔ Not a claim, ⛔ not a dispatch.packages/cli/src/commands/migrate/organization-ownership.ts, is now free onmain.target:v18,domain:spec(Clause-②: yes). The seat's four answers in its release (6148865508) travel with the next claim's dispatch verbatim. Sequencing is A: one PR with the supplement schema, the inventory merge, the corrected:177–:179sentence, one flag read in both plan and apply modes, and the pins.objectstack-fleet commentedon Oct 13, 2026
Claim: PM loop round 1, rolling slot (#23280: a host declares the ADR-0131 D10 fates of its own objects through one supplement the ceremony reads, the inventory's C10 stage) · 2026-10-13T18:15Z
Session:
session_012uFegdfR6K6uqvLzt7XsdZAccount:
os-support-ai(the seat's linked user asGET /useranswers it; the card's assignee from this act)Branch:
claude/issue-23280-host-fate-supplementWorktree:
objectstack-issue-23280Domain:
domain:specSeat:
domain:spec#3(seat post #18883)Ruling-ref: triage
6147745120;domain:spec#2's release6148865508, whose four answers (sequencing A, fixture names, what a supplement may name A, refusal wording B) travel with this dispatch verbatim; triage's unlock6151838864(PR #23034 merged as2808069121). All read in this act, along with the released dev report6148706704(the measured call shape).File surface (at
origin/main404fc477eor later; stop on a breach and explain it in the report):packages/cli/src/utils/organization-ownership-inventory.ts:CLOUDpremise sentence (:177-179) cites objectstack-ai/cloud#2866 A in place of the superseded record6094175435.packages/cli/src/commands/migrate/organization-ownership.ts: one flag, read in both plan and apply modes and passed asinventorytobuildOrganizationOwnershipPlanand toapplyOrganizationOwnership. An invalid supplement maps to a refusal throughrefuse(), inside the--jsonenvelope.packages/cli/src/utils/organization-ownership-plan.ts: text only. The undeclared-table refusal (:821) gains one remedy clause naming the flag (answer 4, B). Its condition does not change.packages/spec/src/system/, with its generated projections, so the input is declared, not ambient..changeset/23280-*.md.6148865508. ⛔ No change to the apply path's semantics (PR feat(cli): os migrate organization-ownership --apply — the ADR-0131 D10 ceremony (C7b, PR 2 of 3) #23034) beyond passinginventory.Container & model:
M,mode:subagent,model: default tier. It widens a published input of the ceremony, so it owes a review atCONTRACT_REVIEW_TIERbefore the queue, by an isolated at-tier subagent.Clause-②: yes (a host-declared fate supplement becomes a published input of
os migrate organization-ownership)Responsibility: the ceremony's inventory and its command (
packages/cli), routed to the spec lane by triage under 强制条款② | none today: the plan refuses every table with no fate, and no host channel exists | every host whose own tables carryorganization_id; cloud's tenant and control databases first (objectstack-ai/cloud#2867 item I10; objectstack-ai/cloud#2868 waits)Thread-read: 6151838864
Serial constraints cleared (the file lists of all 6 open PRs and all open
pm:dispatchedclaims, read in this act):organization-ownership*.tsorschema-migrate.ts. PR feat(cli): os migrate organization-ownership --apply — the ADR-0131 D10 ceremony (C7b, PR 2 of 3) #23034 merged as2808069121.domain:spec#2's released claim (6148505516) left an empty branchclaude/issue-23280-host-declared-fatesat66949b772. This claim starts from zero on its own branch.Generated by Claude Code
objectstack-fleet commentedon Oct 13, 2026
os-dev-report
{
"issue": 23280,
"status": "done",
"branch": "claude/issue-23280-host-fate-supplement",
"pr": "#23348",
"pr_number": 23348,
"head_sha": "066963bb09de94ff3cc138bcd16a33ceb59e58f9",
"session": "session_012uFegdfR6K6uqvLzt7XsdZ (mode:subagent; the domain:spec#3 PM's id)",
"premise_still_valid": true,
"summary": "A host declares the ADR-0131 D10 fates of the objects it provides in one JSON file.
os migrate organization-ownership --fate-supplement FILEreads it in both modes and passes the merged list asinventoryto buildOrganizationOwnershipPlan and to applyOrganizationOwnership. The apply path is otherwise unchanged. The file is declared in the spec: OrganizationOwnershipSupplementSchema, a JSON array of OrganizationOwnershipSupplementEntrySchema rows, in packages/spec/src/system/fate-supplement.zod.ts. Each fate is a strict discriminated arm that admits only the keys that fate reads, and census, cloudCarried and external are not authorable. mergeHostFateSupplement in organization-ownership-inventory.ts stamps each row with census host-supplement. A row that replaces one of the 8 cloud(...) placeholders keeps that placeholder's place. Refusals: a row naming an object the platform inventory already gives a fate (answer 3); two rows naming one object (H5). A row whose table this database lacks is plannedabsent. Every refusal of the file (missing, not JSON, not an array, a row the schema refuses, a duplicate, a platform object) is a HostFateSupplementRefusal mapped through refuse() inside the --json envelope, naming file, row (zero-based) and object, before the database is opened. The undeclared-table refusal in plan.ts gained one remedy clause naming--fate-supplement FILE(answer 4); its condition is unchanged and that is the only edit in plan.ts. The CLOUD premise sentence now cites cloud ruling record 6146394952 (objectstack-ai/cloud#2866 A) instead of 6094175435. It is written as a record id because it is a runtime string. No fate is guessed for any cloud table, and there is no ambient input.","flag": "--fate-supplement FILE. Reason (stated in the PR body): 'supplement' is ADR-0131 D10's own word for this input, and 'fate' names what it supplements. '--fates' reads like a filter over the plan's fates, and '--supplement' alone does not say what it supplements.",
"supplement_schema": "OrganizationOwnershipSupplementSchema (the file) and OrganizationOwnershipSupplementEntrySchema (one row) in packages/spec/src/system/fate-supplement.zod.ts, exported from @objectstack/spec/system. Building blocks exported alongside: OrganizationOwnershipFateSchema, ...RowConditionSchema, ...AnchorSchema, ...CategorySchema, ...DepartureSchema. Type aliases are z.input (ADR-0122); the seven input==infer equalities are pinned in type-alias-convention.pin.test.ts.",
"one_shape": "Derived plus pinned. The CLI's OrganizationOwnershipFate, RowCondition, Anchor, InventoryCategory and InventoryDeparture are now aliases of the spec types, and ORGANIZATION_OWNERSHIP_FATES is OrganizationOwnershipFateSchema.options. Only the top-level key list stays in the CLI, held equal three ways: (1) compile-time spec to CLI, because the merge assigns a parsed spec row into InventoryEntry; (2) the compile-time KEYS_AGREE equality in organization-ownership-inventory.test.ts, reverse-verified red (TS2322 at 161:7) when a key was added to InventoryEntry; (3) runtime CLI to spec, because every platform row minus census/cloudCarried/external parses under the spec row schema. The platform rows use all 5 condition forms, 3 anchor kinds, 2 category forms and 2 departure forms.",
"H3_measured": "cloudCarried is an output marker only. The plan copies it onto TablePlan (planPresentTable / absentTable) and apply never reads it. So the 8 cloud(...) rows are fate-4 placeholders: a supplement row naming one replaces it in place and is not a 'platform object'. Without a supplement the rows stand unchanged; their citation text changed, per the claim. The rows were not deleted and were given no fate.",
"H4_measured": "inventoryDigest hashes the merged list, so the plan's digest and the apply checkpoint are keyed on the supplement (pinned: plan.inventoryDigest == inventoryDigest(merged), and differs from the platform-only digest). --apply with a different supplement, or none, than the checkpoint it resumes is NOT refused. applyOrganizationOwnership discards a checkpoint whose digest mismatches, logs 'the inventory changed since the recorded checkpoint, so every step runs again (each is idempotent)', and re-runs every step. The kept plan file is not an input of --apply. Reported as a finding; no mechanism built.",
"H1_H2_H5_H6": "H1 as stated: no census in the row; the merge stamps it. H2: JSON only, because no migrate sibling reads YAML. H5: duplicates are refused in the CLI merge; a spec .refine would be a dropped refinement in the shrink-only dropped-refinements.baseline.json. H6: reused the better-sqlite3 + PlanReader harness of organization-ownership-plan.integration.test.ts.",
"files_changed": [
".changeset/23280-host-fate-supplement.md",
"content/docs/getting-started/quick-reference.mdx",
"content/docs/references/index.mdx",
"content/docs/references/system/fate-supplement.mdx",
"content/docs/references/system/index.mdx",
"content/docs/references/system/meta.json",
"docs/audits/2026-07-unknown-key-strictness-ledger.counts/system.md",
"packages/cli/src/commands/migrate/organization-ownership.fate-supplement.integration.test.ts",
"packages/cli/src/commands/migrate/organization-ownership.ts",
"packages/cli/src/utils/organization-ownership-host-supplement.integration.test.ts",
"packages/cli/src/utils/organization-ownership-inventory.test.ts",
"packages/cli/src/utils/organization-ownership-inventory.ts",
"packages/cli/src/utils/organization-ownership-plan.ts",
"packages/spec/api-surface/system.json",
"packages/spec/authorable-surface/system.json",
"packages/spec/declaration-map/system.json",
"packages/spec/export-origins/system.json",
"packages/spec/json-schema.manifest/system.json",
"packages/spec/llms.txt",
"packages/spec/scripts/liveness/empty-state-registry.mts",
"packages/spec/src/system/fate-supplement.test.ts",
"packages/spec/src/system/fate-supplement.zod.ts",
"packages/spec/src/system/index.ts",
"packages/spec/src/type-alias-convention.pin.test.ts",
"packages/spec/variant-docs.json"
],
"line_budget": "1930 changed lines (+1855 / -75) across 25 files vs merge base cc14657, generated files included (dispatch-gates reading at 066963b); under the 3000 human-merge threshold.",
"gates": "At 066963b,
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderives 114 commands. All 114 ran on that head with each exit captured before any pipe; all exited 0, none 3.--ranreconciliation: '114 derived, 114 run, 0 NOT-MEASURED, 0 UNRUN (a DERIVED zero)'. check:dts-closure and check:dual-build-cjs-loads first exited 1 on one partial @objectstack/organizations dist that my own killed stray build had left; both were re-run green after a turbo rebuild under the lock. check:type-check-debt ran under the lock because it builds the workspace. Earlier gates that exited 3 (check:i18n family, check:dual-build-cjs-loads) were re-run after real builds and not counted. Real findings fixed on the way, all spec-gate registrations a new exported schema needs: check:spec-parsed-alias (ADR-0122), check:empty-state, check:llms-txt, check:variant-docs, check:quick-reference-counts.","tests": "CLI on merged head 2da5e78: the six ceremony files (inventory 22, plan.integration 11, apply 9, host-supplement.integration 7, apply-flags 3, fate-supplement.integration 7) = 59 passed;
pnpm --filter @objectstack/cli typecheckgreen (tsc + check:test-typecheck OK); whole unit layervitest run --project unit --shard=N/4= 287 files / 4306 tests passed (shard 4 at 066963b, docs-only delta). Spec:pnpm --filter @objectstack/spec test(local) 670 files / 20284 passed at 11764ed (pre-merge); on the merged head fate-supplement.test.ts (8) and type-alias-convention.pin.test.ts (3) green; check:generated all 14 artifacts current. Spec test:repo, 3 shards on merged head: 58 of 59 files fully green (307 + 280 tests in shards 1-2, 18 complete files in shard 3). DECLARED NARROWING: scripts/build-schemas-check-mode.test.ts ran 20 of 88 cases green; each case re-runs build-schemas (13-28 s), so the file is about 30 min of serial lock time on this shared box. The remaining 68 cases are NOT MEASURED locally and left to CI's repo project; the diff touches neither build-schemas.ts nor authorable-surface.base.json. Ablations through scripts/ablation-replace.mjs (wrap mode, under the lock, trap restore from HEAD by absolute path, restore proven blob == HEAD withgit diff HEADempty): (1) command does not pass inventory (anchor x2 -> x0, blob b5aa7463 -> 901af2d0): exactly 'with it, the host-declared fate is planned like a platform row' and 'with --fate-supplement, the apply step receives the host row' went red (2 failed / 27 passed), restored to b5aa7463 == HEAD; (2) platform-object refusal dropped (anchor x1 -> x0, blob c9791d01 -> e0e81f8c): the three pin-3 tests went red (3 failed / 26 passed), restored to c9791d01 == HEAD. Reverse verification of KEYS_AGREE: the first attempt was a NO-OP, because the tool refused when the replacement contained its anchor and tsc did not run. Re-anchored: blob c9791d01 -> a8716c85, thentsc --noEmitgave exactly 'organization-ownership-inventory.test.ts(161,7): error TS2322', restored to c9791d01 == HEAD. These are CLI-src subjects resolved relatively, so no dist preflight was needed. eslint --no-inline-config on the 10 touched TS files: exit 0.","mcp_calls": "0 MCP GitHub calls. One SendMessage reply to the PM's status probe, which is not a GitHub tool.",
"api_writes": "3 REST requests in 2 relay strokes, all through scripts/pm as objectstack-fleet[bot]: (1) pr_create via scripts/pm/fleet-write/dispatch.mjs (run 38483113693): POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /repos//issues/23348/assignees [os-support-ai]; read back as 15613 bytes sent, 15613 stored, identical; (2) this os-dev-report: POST /repos//issues/23280/comments via scripts/pm/post-stamped.mjs. Not REST: git push of the branch (empty probe first, then WIP commits; never force). Zero label writes, because the dispatch's write budget names none and skip-changeset does not apply (a changeset exists).",
"deviations": [
"File surface: beyond the claim's literal list, the spec gates required registrations every new exported spec schema needs. These are packages/spec/llms.txt (inventory count 204 to 205, system 35 to 36), packages/spec/scripts/liveness/empty-state-registry.mts (two 'scope' rows: category where, mirror), packages/spec/variant-docs.json (two generated-reference-only exemptions stating the docs gap), packages/spec/src/type-alias-convention.pin.test.ts (seven isomorphic pins instead of seven XParsed synonyms), and content/docs/getting-started/quick-reference.mdx (System total 35 to 36). Read as part of 'its generated projections'; the triggering gate is named for each in the PR body.",
"Spec module named fate-supplement.zod.ts, not organization-ownership-supplement.zod.ts. gen:docs refused the longer name: the reference page title was 51 characters, outside the 36-46 band, and no ladder rung fits. Renaming was the in-scope fix; adding a rung to the docs tooling was not.",
"The command's docs page: none exists. No file under content/docs names --fate-supplement or --backup-taken; measured with a control hit on the command source. So no docs page was edited.",
"Declared narrowing: 68 of 88 cases of packages/spec/scripts/build-schemas-check-mode.test.ts are NOT MEASURED locally (see tests); left to CI.",
"Spec local suite (670 files) ran pre-merge at 11764ed. Post-merge only my two spec test files re-ran (green). The merge brought main's own spec changes, which are disjoint from this diff; check:generated was green on the merged tree.",
"My own background gate runner's check:type-check-debt launched an unlocked whole-workspace turbo build that raced my locked builds and produced two transient dts failures. I stopped it by PID (my process tree only), rebuilt under the lock, and ran that gate under the lock from then on."
],
"open_questions": [],
"out_of_scope_findings": [
"carrier: the domain:spec#3 seat at landing (its #15211 mechanism record) - H4: --apply resuming with a different supplement, or none, than its checkpoint is not refused; the mismatched checkpoint is discarded and every idempotent step re-runs, and the kept plan file is not an input of --apply. Existing behaviour from #23034, not a defect or a contract violation; noted, not filed. Dedupe words: organization-ownership checkpoint digest supplement, apply resume inventory changed, plan file not read by apply",
"carrier: none (Acceptance notes only) - the corrected CLOUD citation is part of the hashed rows, so an apply checkpoint recorded on a pre-merge build re-runs its steps once (each is idempotent); v18 is unreleased. Noted, not filed.",
"carrier: none (Acceptance notes only) - packages/cli/test/hook-timeout-override-refusal.test.ts: each of its two CONTROL legs spawns
vitest listagainst vitest's 5 s default timeout and measured 3.9-5.1 s here. One leg timed out on each of two of three runs under load (load average 4-9); the third run passed 4/4. The file is untouched by this diff. Not one of the three filing classes (no public door, no named producer). Dedupe words: hook-timeout-override-refusal CONTROL timeout, vitest list 5000ms","carrier: none (Acceptance notes only) - no hand-written page documents the v18 ceremony's inputs (--fate-supplement, --backup-taken); variant-docs.json now states that gap on its two new exemptions."
],
"worktree": "/home/user/objectstack-issue-23280: node_modules removed and worktree removed after this report is posted (see the final message)."
}
Generated by Claude Code
objectstack-fleet commentedon Oct 14, 2026
✅ ACCEPT (seat review): PR #23348 at
a0cbcf9cf. The contract-tier review is owed before the queue ·domain:specseat 3 (seat post #18883) ·session_012uFegdfR6K6uqvLzt7XsdZ· 2026-10-14T00:41ZPR shape.
main, assigned toos-support-ai. Line 1 isFixes #23280; line 2 is the claim'sClause-②:line, verbatim.bbb975771. It touches no governed path and stays under the human-merge threshold.mainwas merged twice with merge commits. The second merge (a133014ac) resolved one conflict with PR feat(cli,core): the organization-ownership ceremony promotes customized email templates and moves the settings global rung (C7b, PR 3 of 3) #23329 (C7b PR 3,ed0383419): both flags were kept byte-identical,--template-choiceand--fate-supplement. One type-only fix (a0cbcf9cf) keeps the derived row condition's lists read-only, so the mergedSEEDED_BYtypechecks.The change, read in the diff.
--fate-supplement FILEis read before the database is opened, in both modes, and passed asinventorytobuildOrganizationOwnershipPlanand toapplyOrganizationOwnership. A file that cannot be used is refused throughrefuse()inside the--jsonenvelope, with a reason code, the file, the row index and the object. Nothing is read without the flag.OrganizationOwnershipSupplementSchema/...EntrySchema(@objectstack/spec/system,fate-supplement.zod.ts) has strict per-fate arms.census,cloudCarriedandexternalare not authorable. The CLI's row vocabulary (fate, condition, anchor, category, departure) is now derived from the spec types, and the top-level key list is held equal by a compile-time equality (reverse-verified red) and a runtime parse of every platform row.mergeHostFateSupplement):cloud-supplementplaceholders, which it replaces in place (H3);plan.ts:821gains only the remedy clause naming the flag (answer 4); its condition is unchanged.CLOUDpremise now cites cloud ruling record6146394952(objectstack-ai/cloud#2866 A) in place of6094175435.The pins, each with a control:
absent.The H4 digest pin: the plan digest equals the merged list's, and differs from the platform-only digest.
The ablations, re-run on the merged head, each restored to blob == HEAD:
inventoryturns the two pin-1 tests red;Measurements on
a0cbcf9cf:spectest:repo58 of 59 files green;check:generatedcurrent;dispatch-gates --ran: 114 derived, 114 run, all exit 0.Declared narrowing: 68 of 88
build-schemas-check-mode.test.tscases are left to CI.Accepted with notes:
--applyresuming with a different supplement than its checkpoint, or none, is not refused. The checkpoint is discarded and every idempotent step re-runs. The kept plan file is not an input of--apply. The seat records this 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 at landing, beside the mechanism.llms.txt, the empty-state registry,variant-docs.jsonwith two stated docs-gap exemptions, the alias pins, the quick-reference count). Each is named with its triggering gate in the PR body; they are read as "its generated projections".Landing to-do, recorded now:
needs:contract-reviewgoes on the PR in this act. The review runs ona0cbcf9cf.pm:dispatchedcomes off.Generated by Claude Code
objectstack-fleet commentedon Oct 14, 2026
Landed: PR #23348 →
707b3cd91(Fixes #23280). A host declares the ADR-0131 D10 fates of its own objects throughos migrate organization-ownership --fate-supplement FILEdomain:specseat 3 (#18883) ·os-support-ai· sessionsession_012uFegdfR6K6uqvLzt7XsdZ· 2026-10-14T01:31Z · holder of claim6152165219.6158272200.a0cbcf9cf(6158469179).mergeable: clean.check-governed-mergesreported it NOT governed, at 1936 lines.mainat707b3cd91: 25 files, +1861 / −75. Thepatch-id --stableequals that ofbbb975771..a0cbcf9cf: byte-identical to the reviewed head.OrganizationOwnershipSupplementSchema(@objectstack/spec/system) and passes it with--fate-supplementin both plan and apply modes.--jsonenvelope.cloudCarriedplaceholders replaces it in place.absent.6148865508said, together with the H4 reading.completed, and the PR names no other issue.pm:dispatchedcomes off in this act.Generated by Claude Code
fix(cli): the apply refuses a plan reviewed under another tenancy pos…
revert(changeset): leave the consumed #22937 and #23280 notes as they…