Repository navigation
platform-checklist + cli: three findings from the 18.0 QA sweep at 5b14b7f3 — two clauses mis-asserted against documented contracts, and a refusal that prescribes a withdrawn command (family card) #24567
Description
Filing gate: ① — fold card (the per-session quota is three standalone defect cards; these three findings ride one card with a list, one row per location)
Path: platform-core.v18-boot-refusals · access-security.security-catalog-one-holder-and-boot-report · cli.organization-ownership-ceremony
type: Bug (rows 1–2: the checklist's declared clauses contradict the documented product contract; row 3: a runtime refusal string sends the operator to a command the same release refuses; the relay channel sets no issue type, so it is pre-filled here for triage)
Checklist item priority: row 1 P0 (its acceptance[2] fails → inherits P0) · row 2 P1 (acceptance[1] fails → inherits P1) · row 3 P0 item, clause passes — no inheritance, severity low
Acting reader: rows 1–2 — the seat that owns docs/qa/platform-checklist (domain:devx), one checklist-edit PR revising both clauses (bump revision, add a history entry); row 3 — the domain:cli lane seat, at dispatch (packages/cli/src/commands/migrate/apply.ts:589 and the help example at organization-ownership.ts:332)
Dedupe: search_issues "v18-boot-refusals checklist clause refused boot did not alter the database schema sync before organization ownership guard" (open + closed) → 33 hits; search_issues "security-catalog-one-holder install-local conflicts checklist item clause test-fix" → 31 hits; search_issues "drop gate refusal tells operator run migrate organization-ownership which 18.0 refuses NOT_IMPLEMENTED" → 72 hits. None a duplicate: the only open hits are this card and the two folded into it; nearest closed: #23871 (the boot refusal's prescription, a different message site), #23950 / #23121 (earlier clause re-point family cards, other clauses)
Folded into this card: #24568 (row 2) and #24566 (row 3), closed as folded. Found by the 18.0 release QA sweep; the two fails were confirmed by an independent RUNNER rule 7 re-derivation, which classified both as assertion defects (product right, clause wrong).
Row 1 — platform-core.v18-boot-refusals · acceptance[2] (P0) — re-word the clause
QA-source: #24556 · platform-core.v18-boot-refusals · acceptance[2]
reach: OS_DATABASE_URL=file:COPY.db objectstack serve -p PORT on a copy of a 17.7.0-created SQLite → exit 1 with the ownership refusal (correct), but the additive v18 schema sync has already altered the copy: +37 tables, a __search column on 21 sys tables, bundle_member/draft_changes on sys_metadata, ~40 indexes, no row content changed (measured twice; on a one-object stack the changes sat in the -wal while the main-file checksum stayed equal).
- Clause today: "the refused boot did not alter the database" (verify: checksum before == after).
- Why the clause is wrong:
packages/runtime/src/organization-ownership-boot-guard.tsdocuments the guard as ordered after the engine (whosestart()runs the additive schema sync the ceremony depends on) and ahead of every plugin that writes a row; ADR-0131 D10 forbids auto-migration (drop / delete / attribute), not additive sync. No cited source requires a byte-unchanged file. - Proposed clause: "the refused boot wrote no row and ran no D10 step", verified by a row-level diff read through SQLite (so the
-walis included), not a file checksum. - Open question for the maintainer (not a defect on this evidence): the refusal tells the operator to keep this database on a 17.x runtime after the v18 boot has added v18 schema to it.
- Full reproduction: QA run · priority:P0 (23/23) · 5b14b7f3 · 2026-10-19 · 17 PASS / 5 PARTIAL / 1 FAIL / 0 BLOCKED / 0 NOT-RUN #24556, section "Fails".
Row 2 — access-security.security-catalog-one-holder-and-boot-report · acceptance[1] (P1) — re-point the clause
QA-source: #24558 · access-security.security-catalog-one-holder-and-boot-report · acceptance[1]
reach: POST /api/v1/marketplace/install-local (from a scratch copy of the showcase) with a package redeclaring a shipped permission set / position name → 422 {code:"PLUGIN_REGISTER_FAILED", message}, no conflicts[]; the names and holders are inside the message; nothing installed (27 → 27 packages). Measured with two packages.
- Clause today: "… 422 NAMESPACE_CONFLICT (or PLUGIN_REGISTER_FAILED) with conflicts[], and nothing is recorded as installed".
- Why the clause is wrong: the install-local door (
packages/cloud-connection/src/marketplace-install-local-plugin.ts~1593–1602) answers its OWN registeredPLUGIN_REGISTER_FAILEDinterpolating only the message — that route's documented contract inpackages/spec/src/api/error-code-ledger.zod.ts(~999–1003); no pin in the item'sautomated.refassertsconflicts[]at this door. - Proposed clause: "422 PLUGIN_REGISTER_FAILED whose message names each conflicting name and its holder, and nothing is recorded as installed" (holds today). A structured
conflicts[]on this door would be a separate enhancement decision. - Full reproduction: QA run · since:v18 (48/48) · 5b14b7f3 · 2026-10-19 · 38 PASS / 7 PARTIAL / 3 FAIL / 0 BLOCKED / 0 NOT-RUN #24558, section "Fails".
Row 3 — cli.organization-ownership-ceremony · acceptance[3] (P0 item; clause passes) — fix the refusal text
QA-source: #24556 · cli.organization-ownership-ceremony · acceptance[3]
reach: os migrate apply --allow-destructive --yes --database-url file:COPY.db on a 17.7.0-created copy → the drop-gate refusal says to run os migrate organization-ownership --out PLAN, review it, then --apply --plan-file PLAN; running that command → refused NOT_IMPLEMENTED (measured on a live CLI at 5b14b7f).
- Where:
packages/cli/src/commands/migrate/apply.ts:589(the prescription) againstpackages/cli/src/commands/migrate/organization-ownership.ts:1107-1115(ORGANIZATION_OWNERSHIP_UPGRADE_UNAVAILABLE_CODE = 'NOT_IMPLEMENTED', fresh installs only); the command's own help example atorganization-ownership.ts:332has the same problem. - Expected: the drop-gate refusal states what 18.0 actually supports for this database — the position the boot guard's refusal already states — not a withdrawn command.
Generated by Claude Code
Activity
[-]checklist test-fix: platform-core.v18-boot-refusals acceptance[2] demands a byte-unchanged database, but the guard is documented to run after the additive schema sync[/-][+]platform-checklist + cli: three findings from the 18.0 QA sweep at 5b14b7f3 — two clauses mis-asserted against documented contracts, and a refusal that prescribes a withdrawn command (family card)[/+]objectstack-fleet commentedon Oct 19, 2026
Triage: p1 +
target:v18·bug·domain:devx(rows 1–2),domain:clirider (row 3) ·area:devpath·pm:queue· triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-19T14:01ZTriage seat (objectstack-wide, seat post #6015). ⛔ Not a claim, ⛔ not a dispatch.
failin the sweep (QA run · priority:P0 (23/23) · 5b14b7f3 · 2026-10-19 · 17 PASS / 5 PARTIAL / 1 FAIL / 0 BLOCKED / 0 NOT-RUN #24556,platform-core.v18-boot-refusalsacceptance[2]) is an assertion defect: the product is right and the clause is wrong. An independent RUNNER rule 7 re-derivation confirms it.target:v18.docs/qa/platform-checklist/**,domain:devx), withrevisionbumped and ahistoryentry each.domain:clirider (packages/cli/src/commands/migrate/apply.ts:589, and the help example atorganization-ownership.ts:332). Cut it at the claim, or land it in the same PR if one seat holds both.Generated by Claude Code
objectstack-fleet commentedon Oct 19, 2026
Claim: PM loop round 4 · folded family dispatch: this card's rows 1–2 with #24543 (triage
6269308691: "It can ride #24567's checklist-edit PR")Session:
session_01FM29ZqLTrnPNXxijioZwMpAccount:
os-warren(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-24567-checklist-v18-sweep-clausesWorktree:
objectstack-issue-24567Domain:
domain:devxSeat:
domain:devx#1File surface:
docs/qa/platform-checklist/areas/platform-core.json(row 1,platform-core.v18-boot-refusalsacceptance[2]),docs/qa/platform-checklist/areas/access-security.json(row 2,access-security.security-catalog-one-holder-and-boot-reportacceptance[1]), anddocs/qa/platform-checklist/areas/approvals.json(#24543,approvals.act-door-and-admin-rescue-slateclause 1); each item gets arevisionbump and ahistoryentry (stop on breach; explain in the report). ⛔ Row 3 is not in this claim:packages/cli/src/commands/migrate/apply.ts:589andorganization-ownership.ts:332aredomain:cli's, as the card's acting-reader line says. The PR is a partial landing for this card (Refs #24567 (rows 1–2), ⛔ notFixes), and on its merge the card goes back topm:queuewithpm:retriage, so row 3 reaches the cli lane.Container & model:
S (three checklist clause re-words, each with its history entry),mode:subagent,model: TIER_DEFAULT(dispatch-gates --tier: "no path-derived mandate")Clause-②: no
Responsibility:
the checklist's own clauses contradict the documented product contract (assertion defects; the product is right)|none: the checklist is the 18.0 readiness read, and row 1 holds its one red P0|every reader of the 18.0 readiness read; no product user is reachedThread-read: 6269051623
Serial constraints cleared: none — no open PR touches the three checklist files, and none changed on
maintoday (read at 2026-10-19T14:37Z).Generated by Claude Code
objectstack-fleet commentedon Oct 19, 2026
os-dev-report
{
"issue": 24567,
"status": "done",
"branch": "claude/issue-24567-checklist-v18-sweep-clauses",
"pr": "#24592",
"session": "session_01FM29ZqLTrnPNXxijioZwMp — this run's harness-stamped id (the transcript's Claude-Session line; a subagent of the PM seat, so the parent's)",
"premise_still_valid": true,
"summary": "One draft PR (#24592) re-words the three checklist clauses as ruled: assertion defects, product right. No product code, test or pin is changed. 1) platform-core.v18-boot-refusals acceptance[2] (rev 1 -> 2): the refused boot wrote no row and ran no D10 step, verified by a row-level SQLite diff that includes the -wal, with additive schema sync expected; steps[0] re-worded to match, and its nonexistent
os serve -dreplaced by OS_DATABASE_URL. 2) access-security.security-catalog-one-holder-and-boot-report acceptance[1] (rev 1 -> 2): an inline-manifest install-local answers 422 PLUGIN_REGISTER_FAILED whose message names each conflicting name and its holder, and nothing is installed; no conflicts[]; the title's false NAMESPACE_CONFLICT parenthetical is re-pointed too. 3) approvals.act-door-and-admin-rescue-slate acceptance[1] and title (rev 1 -> 2): a PUT neither wire door claims is the door's ordinary 404 miss with no Allow header. The code is ENDPOINT_NOT_FOUND on the self-hosted os dev boot and ROUTE_NOT_FOUND on the hosted dispatcher door, which is the pin's; 405 + Allow: GET, POST is the in-process member's only. Each item has one revision-2 history row naming its QA source (#24556 / #24558 / #24542) with ref #24592. PR body: Fixes #24543 + Refs #24567 (rows 1-2) + Clause-②: no; assignee os-warren; label skip-changeset. #24567 row 3 (domain:cli) is untouched.","tests": "No package is touched, so no build closure, package test or typecheck is owed. Each clause was re-measured against source at base de43524, which is also the merge base's lineage. Row 1: packages/runtime/src/organization-ownership-boot-guard.ts module doc (judges in start() after the engine's additive sync, ahead of every row writer; the ceremony's boot 'must write nothing before it is refused'), ADR-0131 D10 item 5, and the marker constants in packages/spec/src/system/migration.zod.ts;
os serveflags (packages/cli/src/commands/serve.ts Serve.flags) carry no -d. Row 2: packages/cloud-connection/src/marketplace-install-local-plugin.ts register step 3 (an inline manifest returns 422 PLUGIN_REGISTER_FAILED with the message only, before persisting; a cloud-fetched manifest is lenient and installs, hence the inline qualifier); SecurityCatalogNameConflictError in packages/objectql/src/registry.ts lists every conflict with its holder. grep -l 'install-local|installLocal|marketplace' over the 6 automated.ref files exits 1, all 6 paths existing. #24543: packages/plugins/plugin-approvals/src/approvals-plugin.ts mountActionPages (raw-app GET+POST only), packages/plugins/plugin-hono-server/src/adapter.ts unmatchedResponse (404 ENDPOINT_NOT_FOUND with no Allow when no registered method matches), packages/runtime/src/domains/approvals.ts APPROVALS_ACT_METHODS = GET/HEAD/POST, approvals-act.test.ts asserting {status:404, code:'ROUTE_NOT_FOUND'} for PUT, and approval-service.ts handleActionPage returning 405 Allow: GET, POST. QA subject vs base:git merge-base --is-ancestor 5b14b7f3 de43524606exit 0 (self-proving, no control leg needed);git diff --stat 5b14b7f3 de43524606over those 11 source/pin files plus the 3 area files changes only registry.ts (#24526 bound-action reporting, no SecurityCatalogNameConflict lines). Cross-package reader packages/plugins/plugin-auth/src/checklist-refusal-envelope-consistency.test.ts: its RETIRED_CONVENTION regex matches 0 of 5715 strings in the 3 edited files, positive control true; CI Test Core runs the file. Control-byte self-scan of the 3 files: grep -naP exit 1 (none). Ablation and reverse verification: not applicable (docs only, no tested behaviour changed). NOT MEASURED: live verification re-run of the three clauses on a booted showcase. Reason: it needs a full workspace build, a v17 SQLite minted from npm @objectstack/cli@17.7.0 and two showcase boots in a container shared with another dev agent, and the dispatch asked for a source re-measurement.","gates": "Derived by
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands: 13 families, the same 13 as the PM's dispatch reading; change set 3 paths, 48 changed lines vs merge base 2667e24. Final union at head 596ee73, every exit code captured before any pipe: node scripts/check-ci-filter-parity.mjs :: exit 0 ; node scripts/check-closing-keyword-parity.mjs :: exit 0 ; node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0 ; node scripts/check-comment-mask-corpus.mjs :: exit 0 ; pnpm --filter @objectstack/lint run check:doc-formula-expressions :: exit 0 ; pnpm check:cross-package-test-inputs :: exit 0 ; pnpm check:doc-authoring :: exit 0 ; pnpm check:driver-memory-census :: exit 0 ; pnpm check:gitlink-declared :: exit 0 ; pnpm check:nul-bytes :: exit 0 ; pnpm check:platform-checklist :: exit 0 ; pnpm check:refd-timer-probe :: exit 0 ; pnpm check:watch-hint-literal :: exit 0.--ranreconciliation: '13 derived, 13 run, 0 NOT-MEASURED, 0 UNRUN' (a DERIVED zero). The same union also ran green at 4947d9e and ad55c68; the PR body cites ad55c68. check:platform-checklist line: 'OK — 16 areas, 327 items (322 active, 1 planned) … symbol anchors: 855/865 resolved … 18 file floors held', the same 855/865 as the untouched base, so no anchor was lost or added. PM hypotheses 2 and 3 are falsified: the QA-source history rows do not red the gate, and no anchor was refused or re-pointed. doc-formula-expressions: the first attempt exited 3 PREREQUISITE NOT MET (formula/lint dist absent), which measured nothing; it re-ran exit 0 afterOS_VERIFY_LOCK_SLOT=issue-24567-build bash scripts/pm/os-verify-lock.sh -c 'NODE_OPTIONS=--max-old-space-size=4096 pnpm exec turbo run build --filter=@objectstack/formula --filter=@objectstack/lint --concurrency=2'(VERDICT command-exit 0, 4 tasks, 3 cached). check:platform-checklist runs in no per-PR CI (it is the daily watchdog), so the local reading is its evidence. PR check-runs at 596ee73, read once without waiting: Lint & Repo Gates success, TypeScript Type Check success, Governed Surface Queue Guard success, Build Core skipped, Test Core 2/6–6/6 success, Test Core (1/6) in_progress, Check Changeset skipped (label present); every other completed run success or skipped.","mcp_calls": "0 — no MCP GitHub tool was called (reads went through REST GET via the container proxy; writes through the fleet relay)",
"api_writes": "2 relay strokes (each one POST /repos/objectstack-ai/objectstack/dispatches, executed by fleet-write.yml as objectstack-fleet[bot]): 1) pr_create, run 39275909674 → POST /repos/objectstack-ai/objectstack/pulls (draft, #24592), POST /repos//issues/24592/assignees (os-warren), POST /repos//issues/24592/labels (skip-changeset); 2) this os-dev-report comment via scripts/pm/post-stamped.mjs → POST /repos//issues/24567/comments. Also 5 git pushes to the branch (not REST): the empty claim marker, then fe81662, 4947d9e, ad55c68 and 596ee73. No PATCH, no review request, no ready flip, no assignee write on either card.",
"open_questions": [],
"clauses": {
"platform-core.v18-boot-refusals": {
"before": {
"revision": 1,
"acceptance[2]": {
"clause": "the refused boot did not alter the database",
"oracle": "build",
"verify": "checksum before == after",
"evidence": "the two checksums"
},
"steps[0]": "checksum the v17 DB; run
os serve(v18) against it with -d file:COPY.db; read the output and exit code; checksum again"},
"after": {
"revision": 2,
"acceptance[2]": {
"clause": "the refused boot wrote no row and ran no D10 step: every table the v17 copy held keeps every row and every value in the columns it held (no row added, deleted or changed — so no column dropped, no mirror row deleted, no organization_id attributed), every table the boot created is empty, and
sys_migrationholds noadr-0131-organization-ownershipmarker. The additive schema sync the engine runs before the guard judges (new tables, new columns, new indexes) is expected and is not a failure","oracle": "build",
"verify": "a row-level diff of the two SQLite snapshots from steps[0], read through SQLite so the
-walis included: for each table present before, its pre-existing columns compared row by row (ordered by primary key) — no difference; for each table present only after, its row count — 0;SELECT id FROM sys_migration WHERE id = 'adr-0131-organization-ownership'— no row. ⛔ Not a file checksum: in WAL mode the boot's DDL can sit in COPY.db-wal with the main file's hash unchanged, and the additive sync changes the hash with no row written, so a checksum answers neither question","evidence": "per-table row counts before and after, the (empty) row diff over the pre-existing columns, the tables the boot created with their row counts, and the sys_migration read"
},
"steps[0]": "snapshot the v17 copy through SQLite — its schema (
sqlite_master,pragma_table_infoper table) and every table's rows, read with the sqlite3 CLI or node:sqlite so a-walfile is included (copy the v17 DB together with its-wal, or checkpoint the original before copying); runos serve(v18) against the copy withOS_DATABASE_URL=file:COPY.db(os servehas no-dflag); read the output and exit code; snapshot again and diff the two"},
"history_added": {
"revision": 2,
"date": "2026-10-19",
"change": "acceptance[2] (clause, verify, evidence) and steps[0] re-worded — an assertion defect found by the 18.0 QA sweep (QA run #24556, platform-core.v18-boot-refusals acceptance[2]: FAIL, confirmed by an independent RUNNER rule 7 re-derivation; card #24567 row 1). The product is right and the clause was wrong: the guard judges in its own start(), after the engine (whose start() runs the additive schema sync the ceremony waits for) and ahead of every plugin that writes a row (packages/runtime/src/organization-ownership-boot-guard.ts), and ADR-0131 D10 item 5 says the refusing runtime never auto-migrates (the ceremony's fates); nothing in it forbids additive schema sync. So a refused boot legitimately adds tables, columns and indexes, and 'did not alter the database' (checksum before == after) failed on a correct product. The clause now asserts what the guard promises — no row written, no D10 step run — through a row-level SQLite diff that includes the
-wal(the run's second boot left the main file's hash unchanged with its DDL in the-wal). steps[0] also stops passing-dtoos serve, which declares no such flag (the same run's checklist-accuracy finding);OS_DATABASE_URLis what the run booted with. The other three clauses are unchanged","ref": "#24592"
}
},
"access-security.security-catalog-one-holder-and-boot-report": {
"before": {
"revision": 1,
"acceptance[1]": {
"clause": "install-local of a package redeclaring a catalog name → 422 NAMESPACE_CONFLICT (or PLUGIN_REGISTER_FAILED) with conflicts[], and nothing is recorded as installed",
"oracle": "api",
"verify": "status + code + conflicts; package list unchanged",
"evidence": "refusal body + the list"
},
"title": "The security catalog has exactly one holder per name: two packages declaring one permission-set / position name refuse boot (422 NAMESPACE_CONFLICT on install-local), a body packageId that disagrees with its package is refused,
os migrate security-catalog-overlaysclears environment shadows, and boot reports grants naming undefined catalog entries"},
"after": {
"revision": 2,
"acceptance[1]": {
"clause": "install-local of an inline manifest (a
{ manifest }body) whose package redeclares a catalog name → 422 PLUGIN_REGISTER_FAILED whose message names each conflicting name and its holder, and nothing is recorded as installed","oracle": "api",
"verify": "status + error.code + error.message: every redeclared catalog name (permission set, position or capability) appears in the message with the package, environment or built-in that already holds it; GET /api/v1/packages lists the same packages before and after. ⛔ No
conflicts[]is expected on this door: it answers its own registered PLUGIN_REGISTER_FAILED and interpolates only the register error's message (that route's entry in packages/spec/src/api/error-code-ledger.zod.ts); the structuredconflictsride the thrown SecurityCatalogNameConflictError, which the boot-refusal pins in automated.ref assert","evidence": "the refusal body + the package list before and after"
},
"title": "The security catalog has exactly one holder per name: two packages declaring one permission-set / position name refuse boot (on install-local, 422 PLUGIN_REGISTER_FAILED naming each name and its holder), a body packageId that disagrees with its package is refused,
os migrate security-catalog-overlaysclears environment shadows, and boot reports grants naming undefined catalog entries"},
"history_added": {
"revision": 2,
"date": "2026-10-19",
"change": "acceptance[1] (clause, verify, evidence) and the title's install-local parenthetical re-pointed — an assertion defect found by the 18.0 QA sweep (QA run #24558, access-security.security-catalog-one-holder-and-boot-report acceptance[1]: FAIL, confirmed by an independent RUNNER rule 7 re-derivation; card #24567 row 2, folded from #24568). The product is right and the clause was wrong: on an inline manifest the install-local door (packages/cloud-connection/src/marketplace-install-local-plugin.ts) answers its OWN registered 422 PLUGIN_REGISTER_FAILED and interpolates only the register error's message — that route's documented contract in packages/spec/src/api/error-code-ledger.zod.ts — so it never carried NAMESPACE_CONFLICT or a
conflicts[], and no pin in automated.ref asserts either at this door. The run measured the refusal twice: the names and their holders inside the message, nothing installed (27 packages before and after). The clause now asserts that; a structuredconflicts[]on this door would be a separate enhancement decision, not taken here. The other four clauses are unchanged","ref": "#24592"
}
},
"approvals.act-door-and-admin-rescue-slate": {
"before": {
"revision": 1,
"acceptance[1]": {
"clause": "GET renders the action page, POST redeems, PUT → 405 with Allow: GET, POST, a dead token → a 200 page (not an error envelope)",
"oracle": "api",
"verify": "status + headers per verb",
"evidence": "four lines"
},
"title": "Approvals on v18: the email action door /approvals/act works through the dispatcher exactly as the self-hosted mount (GET renders, POST redeems, PUT 405 Allow: GET, POST, a dead link a 200 page, a policy-held session not 403'd before the token), and an approval over an unstaffed position opens on the org administrators as ordinary approvers"
},
"after": {
"revision": 2,
"acceptance[1]": {
"clause": "GET renders the action page, POST redeems, a dead token → a 200 page (not an error envelope), and PUT — a method neither wire door claims — is that door's ordinary miss: 404 with no Allow header, never reaching the member (ENDPOINT_NOT_FOUND on the self-hosted
os devboot, whose raw-app mount registers only GET and POST; ROUTE_NOT_FOUND on the hosted dispatcher door, whose/approvals/actdomain claims only GET, HEAD and POST). 405 with Allow: GET, POST is the in-process ApprovalService.handleActionPage member's answer only, which no wire request reaches with a PUT","oracle": "api",
"verify": "status + headers per verb; for the PUT also error.code and the absence of an Allow header. The member's 405 is not a wire leg: it is pinned in-process by packages/plugins/plugin-approvals/src/action-page-member.integration.test.ts, and the dispatcher's 404 miss by packages/runtime/src/domains/approvals-act.test.ts (both in automated.ref)",
"evidence": "four lines (the PUT's with its error.code and its headers)"
},
"title": "Approvals on v18: the email action door /approvals/act works through the dispatcher exactly as the self-hosted mount (GET renders, POST redeems, a PUT neither door claims an ordinary 404 miss with no Allow header, a dead link a 200 page, a policy-held session not 403'd before the token), and an approval over an unstaffed position opens on the org administrators as ordinary approvers"
},
"history_added": {
"revision": 2,
"date": "2026-10-19",
"change": "acceptance[1] (clause, verify, evidence) and the title's PUT leg re-worded — an assertion defect found by the 18.0 QA sweep (QA run #24542, approvals.act-door-and-admin-rescue-slate clause 1: FAIL; card #24543). The product is right and the clause was wrong: on a stock
os devshowcase bootPUT /api/v1/approvals/act?token=…answered 404 ENDPOINT_NOT_FOUND with no Allow header (twice; DELETE and PATCH the same), which is the design — the self-hosted mount registers only GET and POST (changeset 22578), the dispatcher domain claims only GET, HEAD and POST and lets every other method fall through (packages/runtime/src/domains/approvals.ts), and the item's own pin packages/runtime/src/domains/approvals-act.test.ts asserts that miss (404 ROUTE_NOT_FOUND) with the member never run. 405 with Allow: GET, POST belongs to the in-process member ApprovalService.handleActionPage alone (packages/plugins/plugin-approvals/src/action-page-member.integration.test.ts). The GET, POST and dead-token legs held and are unchanged, as are the other two clauses","ref": "#24592"
}
}
},
"files_changed": [
"docs/qa/platform-checklist/areas/platform-core.json",
"docs/qa/platform-checklist/areas/access-security.json",
"docs/qa/platform-checklist/areas/approvals.json"
],
"deviations": [
"platform-core.v18-boot-refusals steps[0] edited beyond acceptance[2]: it was the checksum procedure the old verify read. Its
os serve … -d file:COPY.dbwas also an invocation error (os serve declares no -d; QA run #24556's checklist-accuracy finding), corrected to OS_DATABASE_URL under the bounded in-place exemption: same defect class, mechanical, a file this claim holds, same gate family. The claim's file surface names acceptance[2] only, so the seat may append steps[0] to it; the PR body names it under Deviations.","access-security.security-catalog-one-holder-and-boot-report title edited although the ruling named acceptance[1] only: the title carried the same false '422 NAMESPACE_CONFLICT on install-local', and leaving it would leave the item contradicting its own clause.",
"Row 2's clause adds the qualifier 'an inline manifest (a
{ manifest }body)': a cloud-fetched manifest takes the door's lenient path and IS installed (200, hotLoaded false), so without the qualifier 'nothing is recorded as installed' is false of the code. This tightens the wording; the meaning is unchanged.","#24543's clause names both doors' miss codes. The card named ROUTE_NOT_FOUND, the hosted dispatcher's code that the pin asserts; the QA run on os dev saw ENDPOINT_NOT_FOUND, the self-hosted adapter's code. Both are true for their door.",
"origin/main (4 commits, none touching docs/qa) was merged into the branch before the PR opened, as merge commit 4947d9e, because dispatch-gates flagged the derivation tree as stale. This was before the PR existed, so it is not a post-PR merge.",
"The history rows' ref was set to #24592 by a commit after pr_create (596ee73); before it the rows pointed at their cards. The once-written PR body therefore cites the gate union at ad55c68, and the union at the final head 596ee73 lives in this report (all 13 exit 0). The body says the ref was set by a follow-up commit.",
"The relay's pr_create read-back line listed the assignee (os-warren) and printed no label list. An independent REST read of /issues/24592/labels, taken at the end, answers ['size/s','skip-changeset']: the label landed and survived the size labeler.",
"Commit trailers use AGENTS.md's model-free pair (Co-authored-by: Claude), not the harness's model-named suggestion; the PR footer uses AGENTS.md's session-URL form.",
"The first push log was written at the scratchpad root and then moved into scratchpad/issue-24567/; every later scratch file is under that directory."
],
"out_of_scope_findings": [
"carrier: QA records #24556 / #24558 / #24542 (their checklist-accuracy lists, routed by those records to the 18.0 wave anchor card, which has no number yet) · noted, not filed. On these three items, untouched here: platform-core.v18-boot-refusals steps[1] (an os dev stack with services:{auth:false} is refused earlier on three counts) and clause 1 naming the code ORGANIZATION_OWNERSHIP_MIGRATION_REQUIRED, which the CLI output does not print; access-security.security-catalog-one-holder-and-boot-report clause 4's clean-boot info line shows only at OS_LOG_LEVEL=info; approvals.act-door-and-admin-rescue-slate fixtures.requires asks for a mail capture the item does not need (the links sit in sys_notification.payload.actions). These are in the PR's Acceptance notes.",
"carrier: none (承接者:无) · noted, not filed. packages/cloud-connection/src/marketplace-install-local-hot-loaded.test.ts and marketplace-install-local-convert-forward.test.ts assert PLUGIN_REGISTER_FAILED at the install-local door, outside the item's automated.ref. Whether either pins the catalog-conflict message, which would make it an automated.ref candidate (RUNNER rule 6, reverse), was not judged. This is in the PR's Acceptance notes.",
"carrier: none (承接者:无) · noted, not filed, read-only inference with no public-door reach. ApprovalService.handleActionPage's doc (packages/plugins/plugin-approvals/src/approval-service.ts) says it answers 'exactly what the plugin's self-hosted raw-app mount answers for the same token and method', yet for PUT the member answers 405 while the mount's door answers 404 ENDPOINT_NOT_FOUND. No wire request reaches the member with a PUT (the dispatcher domain claims GET/HEAD/POST), so nothing wrong is observable; this is a doc-precision nit. It is NOT in the PR body, which is written once; the seat may append it."
]
}
Generated by Claude Code
objectstack-fleet commentedon Oct 19, 2026
Rows 1–2 landed; row 3 goes back to triage ·
domain:devxseat 1 ·session_01FM29ZqLTrnPNXxijioZwMp· 2026-10-19T16:46Zgh-readonly-queue/main/pr-24592-*heads)5e8000906e(not governed; landed by this seat on its ACCEPT6270897362); it carriedRefs #24567 (rows 1–2), so this card stays openorigin/mainat5e8000906e, by contentplatform-core.v18-boot-refusalsis at revision 2, and acceptance[2] reads "the refused boot wrote no row and ran no D10 step", verified by a row-level SQLite diff that includes the-wal. Row 2:access-security.security-catalog-one-holder-and-boot-reportis at revision 2, and acceptance[1] reads "install-local of an inline manifest … → 422 PLUGIN_REGISTER_FAILED whose message names each conflicting name and its holder"Row 3 is open and is not this lane's. It covers the drop-gate refusal text in
packages/cli/src/commands/migrate/apply.tsand the help example inorganization-ownership.ts, which the card's acting-reader line gives todomain:cli. In this act this seat removespm:dispatched, addspm:queueandpm:retriage, and unassigns itself, so triage can route row 3 to the cli lane. The claims6269843213(here) and6269868242(#24543) are discharged.Row 1's open question is with the maintainer, unanswered. It is quoted in PR #24592's acceptance notes and listed in #24579 §7: the refusal tells the operator to keep this database on a 17.x runtime after the v18 boot has added v18 schema to it.
Generated by Claude Code
4 remaining items
objectstack-fleet commentedon Oct 19, 2026
Claim: PM loop round 6 ·
domain:cliseat 1 · row 3 (the one open row; rows 1–2 landed in PR #24592) · p1 +target:v18· 2026-10-19T17:40ZSession:
session_01SYEJqDL3NXxrJRBVqaMu9TAccount:
zhuangjianguo(the seat's linked user asGET /useranswers it; always the card's assignee)Branch:
claude/issue-24567-drop-gate-refusal-textWorktree:
objectstack-issue-24567Domain:
domain:cliSeat:
domain:cli#1(seat post #6024)File surface (read on
origin/main65a8eeb7d; line numbers move; stop on a breach and explain it in the report):packages/cli/src/commands/migrate/apply.ts: the drop-gate refusal, which prescribesos migrate organization-ownership --out PLANthen--apply --plan-file PLAN(about:589–:590). The status lines at about:575/:577name the same command and are read in the census.packages/cli/src/commands/migrate/organization-ownership.ts: the command's help examples (about:330–:336), as far as they show an upgrade use that 18.0 refuses (ORGANIZATION_OWNERSHIP_UPGRADE_UNAVAILABLE,NOT_IMPLEMENTED, about:1107–:1115).packages/cli(source, help and docs it generates) that sends a 17.x-created database's operator to this command, each changed or kept with its reason in the PR body.6269051623/6272496348: say what 18.0 supports for a 17.x-created database in the same terms as the boot guard's refusal (packages/runtime/src/organization-ownership-boot-guard.tsabout:255: stay on 17.x until the 18.x release that carries the upgrade path). It names no withdrawn command.patchchangeset on@objectstack/cli.packages/runtime/**(the boot guard's own text stays the reference);packages/spec/**; any behaviour, exit code or flag; row 1's open maintainer question (a 17.x database that a v18 boot has already given v18 schema), which stays with the maintainer.Container & model:
S,mode:subagent,model: default tier(no path-derived mandate)Clause-②: no
Basis for the Clause-② line: refusal and help text only. No accept set, flag, code or shape moves.
Responsibility: this lane's own code produces the risk (
packages/cli/src/commands/migrate/apply.ts). No platform path covers it. It reaches every operator who runsos migrate apply --allow-destructiveon a 17.x-created database under 18.0; it was measured by the QA sweep (QA run · priority:P0 (23/23) · 5b14b7f3 · 2026-10-19 · 17 PASS / 5 PARTIAL / 1 FAIL / 0 BLOCKED / 0 NOT-RUN #24556) at5b14b7f3.Thread-read: 6272496348
Serial constraints cleared:
apply.tsororganization-ownership.ts.pm:blocked(Blocked-by: #24550), not dispatched, and touches other files.Generated by Claude Code
objectstack-fleet commentedon Oct 19, 2026
os-dev-report
{
"issue": 24567,
"status": "done",
"branch": "claude/issue-24567-drop-gate-refusal-text",
"pr": "#24635",
"session": "session_01SYEJqDL3NXxrJRBVqaMu9T — the dispatching domain:cli seat's harness-stamped id (this run is its subagent, so the parent's)",
"premise_still_valid": true,
"summary": "Row 3 is fixed in draft PR #24635 (head 69778e4, draft, assignee zhuangjianguo, body read back byte-identical).
os migrate apply --allow-destructiveno longer prescribesos migrate organization-ownership --out PLANthen--apply --plan-file PLAN. Its refusal and its --jsondetailnow say that 18.0 supports fresh installs only and does not upgrade a v17 database: keep a v17 database on a 17.x release until the 18.x release that carries the upgrade path, whose ceremony drops these columns itself. This matches the boot guard and the command's own 18.0 refusal. The registered 18.0 command's --help examples now show the refusal; the ceremony class keeps its six examples for 18.x. Within the claim's census line, os dev's way-on line (utils/dev-organization-ownership-upgrade.tsmanual) was fixed the same way, and the patch changeset carriesClause-②: no. One dispatch mechanism hypothesis is falsified. 'A fresh 18.0 install, where organization-ownership --apply IS supported' does not hold at origin/main: the registered command refuses plan and apply on every database, so no branch of the old text was true anywhere in 18.0. Both refused branches (no marker / unverified marker) changed, and the verified 'drop may proceed' line is kept. The gate does fire on a fresh 18.0 database, measured: an object that newly declaressystemFields: { tenant: false }over its injected organization_id. So the text says 'keep a v17 database', not 'keep this one'. That database has no way on in 18.0, filed below for a decision. Row 1's open maintainer question is touched the same way the boot guard touches it, and is not answered. No file outside the claim's surface (apply.ts, organization-ownership.ts, census places, the pinning tests, the changeset) was edited.","tests": "All at 69778e4 after
pnpm --filter '@objectstack/cli^...' build(lock VERDICT command-exit 0) and the CLI build. Reach, through the real CLI (node packages/cli/bin/run.js) on a 17.x-shaped SQLite (a v18 db fromos migrate apply --yes --json, thenALTER TABLE sys_platform_setting ADD COLUMN organization_id TEXT), withos migrate apply --allow-destructive --yes: exit 1 before and after, column kept. BEFORE (base source, restored unstaged, rebuilt, then restored to HEAD; blob hashes equal HEAD, git diff HEAD empty): '… No run of "os migrate organization-ownership --apply --plan-file FILE" is recorded on this database. … Run "os migrate organization-ownership --out PLAN" to write and review its plan, then "os migrate organization-ownership --apply --plan-file PLAN"; …'. That prescribed command on the same file answers exit 1 '✗ os migrate organization-ownership is not available in 18.0 … (NOT_IMPLEMENTED)', with no plan file. AFTER: '… No run of the organization-ownership ceremony is recorded on this database. … 18.0 supports fresh installs only and does not upgrade a v17 database: keep a v17 database on a 17.x release until the 18.x release that carries the upgrade path, whose ceremony drops these columns itself, in its column-drops step, before it records the run verified. Nothing in this run was applied.' --json after: message refused_organization_ownership_unmigrated, tables [sys_platform_setting], detail 'No run of the organization-ownership ceremony is recorded on this database.', marker null, applied [], created []. Help EXAMPLES: six refused invocations before, two refusal examples after. Unit: new apply.organization-ownership-refusal.test.ts (the real command with the boot, occupancy, exit and marker read replaced) has 5/5: both refused marker states on the human face and under --json, plus a verified-marker control reaching the writes. Also organization-ownership.release-refusal.test.ts with a new examples case, dev-organization-ownership-upgrade.test.ts with updated pins, and environments.test.ts (examples resolve to a registered command): 4 files 99 tests passed. Integration: apply-organization-ownership-gate.integration.test.ts (edited, so run locally) 5/5 passed. Fullpnpm --filter @objectstack/cli exec vitest run --maxWorkers=2 --project unit: 314 files, 4640 tests passed, at c6cea94; the last commit changes only the wording those pins read, and the targeted files were re-run at 69778e4.pnpm --filter @objectstack/cli typecheckexit 0: thetsc --noEmitprogram lists all 7 edited .ts files with 0 errors, and check:test-typecheck is OK with its ledger unchanged. Ablation at 69778e4 via scripts/ablation-replace.mjs put the old prescription back into the refusal (anchor x1→x0, blob 7a6414669b72→e8260625ac6f): '2 failed | 3 passed'. The two human-face cases went red; the --json and control cases stayed green, because the mutation touched the message, notdetail. Restored blob == HEAD and git diff HEAD is empty. The subject is a relative ./apply.js import resolved to src, so no dist leg was owed. A first ablation at c6cea94 was refused by the tool as a no-op (its replacement contained its anchor) and measured nothing; it was re-run with a new anchor and gave the same 2 red. Also measured at 69778e4 on a database this 18.0 CLI created: object acme_note, thensystemFields: { tenant: false }. The drift report prescribes --allow-destructive and the gate refuses it, exit 1, column kept.","gates": "At 69778e4, every exit captured before any pipe.
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commandsderived 68 commands (8 paths, 288 changed lines vs merge base 65a8eeb): all 68 exit 0. check:dual-build-cjs-loads and check:i18n-coverage first exited 3 (PREREQUISITE NOT MET, no dist for untouched packages; these measured nothing). Afterturbo run buildof those packages under the lock (75 tasks, cache hits) both re-ran exit 0: '✓ check:dual-build-cjs-loads — 111 published require entry point(s) across 69 package(s) load' and 'check-i18n-coverage: OK (14 config(s), 621 baselined untranslated string(s), none new)'. The 11 declared-wide families (init-service-contract, live-db-isolation, meta-type-normalized, optional-error-sink, resume-authority-declared, route-envelope, runner-env-posture, settings-bind-window, startup-registry-verdict, verify-stand-in, wildcard-fallthrough) all exit 0.--ran: 'Run reconciliation — 68 derived, 68 run, 0 NOT-MEASURED, 0 UNRUN.' (a DERIVED zero; the 11 wide families are recorded outside the derivation).pnpm lint(eslint . --no-inline-config, under the lock) LINT_EXIT=0, as the dispatch asks. os-dev.md calls this repo-level scan CI-owned and not owed, so running it is a run beyond the contract, not a conflict. eslint --no-inline-config over the 7 changed .ts files exit 0, nothing printed. Control-byte self-scan exit 1 (none). Gate lines: '✓ check-adr-0087-registration: this PR adds no declared-breaking changeset (1 non-breaking changeset(s) seen).', '✓ This diff introduces no major bump.', '✓ doc authoring guard: 19124 customer-facing string(s) across 1437 spec sources clean'. PR check-runs at 69778e4, read once without waiting: 23 runs. 'No other open PR may claim the same issue' success, 'Packed-tarball smoke (opt-in)' skipped, the other 21 in_progress (Check Changeset, Governed Surface Queue Guard, Lint · ESLint, Lint · PM dispatch-gates, Lint · CI, release & engine gates, Lint · docs & code guards, Lint · repo & tooling gates, the three Lint · scoped jobs, Type Check · workspace / source gates / consumer gates / debt ledger, Check PR Size, Check Documentation Links, Flag docs affected by code changes, filter, and the three card/branch guards). Test Core / Build Core had not appeared yet.","mcp_calls": "0 — no MCP GitHub tool was called (reads went through REST GET via gh; writes through the fleet relay)",
"api_writes": "2 relay strokes, each one POST /repos/objectstack-ai/objectstack/dispatches executed by fleet-write.yml as objectstack-fleet[bot]. 1) pr_create, run 39305921521: POST /repos/objectstack-ai/objectstack/pulls (draft, #24635) and POST /repos//issues/24635/assignees (zhuangjianguo). Read-back: 20091 bytes sent and stored, identical; assignee listed. 2) This os-dev-report comment via scripts/pm/post-stamped.mjs: POST /repos//issues/24567/comments. Plus 3 git pushes (not REST): the empty branch marker, c6cea94 and 69778e4. No PATCH, no label, no review request, no ready flip, no assignee write on the card.",
"open_questions": [
{
"question": "A database 18.0 created can hit this drop gate, and the boot guard, with no way on in 18.0. Measured on the apply side at 69778e4: an object that newly declares
systemFields: { tenant: false }over its injected organization_id. The drift report prescribes --allow-destructive, the gate refuses it, andos migrate organization-ownershiprefuses on every database. By source, os serve then calls the database 'still in the v17 organization-ownership shape … keep this one on a 17.x release', which is false for it. What should 18.0 tell, or allow, that author?","options": [
"A — 18.0 known limitation: the drop-gate and boot-guard refusals add one sentence for this case (revert the
systemFields.tenant: falsedeclaration, or wait for the 18.x ceremony, which plans the table). cli plus runtime text only, S.","B — the authoring is refused before it lands:
os validateor a lint rejectssystemFields.tenant: falseon an object whose table already carries organization_id. It needs a database read at author time that lint does not have. M, and a new validation surface.","C — 18.0 lets
--allow-destructivedrop organization_id on a database with no v17 evidence. A behaviour change in the gate and in the boot guard, plus a discriminator for 'created by 18.x' that does not exist today. M–L, and it reopens the ruling's 'no escape hatch'."],
"recommendation": "A, because it is text-only on the two refusals that already own this population, keeps the 18.0 ruling's no-escape-hatch intact, and the 18.x ceremony already plans the table (6074eaf). B and C each add a surface for a case no operator has reported yet."
}
],
"out_of_scope_findings": [
"class: a · reach: public door
os migrate apply --allow-destructive --yes, measured at 69778e4 on a database this 18.0 CLI created. Object acme_note was created with its injected organization_id, then declaredsystemFields: { tenant: false }. The drift report says 'acme_note.organization_id: column exists in the database but not in metadata (orphaned) — "os migrate apply --allow-destructive" to drop it.', and the gate refuses that run (exit 1, column kept). 18.0 has no command that clears it. By source, os serve is then refused as 'still in the v17 organization-ownership shape … keep this one on a 17.x release' (findV17ShapeTables reads only systemFields.tenant === false plus the physical column; the os serve half is unmeasured) · evidence: packages/cli/src/utils/organization-ownership-drop-gate.ts ceremonyOrganizationColumnDrops (every organization_id drop), packages/runtime/src/organization-ownership-boot-guard.ts findV17ShapeTables, packages/spec/src/data/object.zod.ts systemFields.tenant ('Default true (the column is always provisioned …)'), and the cli CHANGELOG entry 6074eaf, which names this population. It needs the maintainer decision in open_questions: outside the 18.0 ruling's v17-upgrade scope · dedupe: systemFields tenant false organization_id fresh 18.0 · drop gate refuses fresh install tenant flip · v17 organization-ownership shape fresh database · allow-destructive refused no way on 18.0","class: a · reach: exception: release-text. The spec's ADR-0087 entries compile into the 18.0 upgrade guide at release; the runtime strings beside them are unmeasured at a door · evidence: the same family as this card's row 3 (a refusal or prescription naming steps of
os migrate organization-ownership, which 18.0 refuses on every database). domain:spec, held off here: packages/spec/src/migrations/entries/semantic/18.sys-metadata{,-audit,-commit,-history}-organization-column-retired.ts (:22-23, :43), 18.ups-permission-set-id-column-retired.ts:25, 18.sharing-rule-declared-mirror-retired.ts:21, 18.cli-organization-ownership-apply-plan-file-required.ts:10-26. Runtime, held off here: organization-ownership-boot-guard.ts, the unverified-marker branch of organizationOwnershipRefusalMessage and the read-failure refusal in assertOrganizationOwnershipMigrated, which name the steps with no 18.0 sentence. Others: packages/metadata-core/src/legacy-organization-row.ts:78, packages/metadata-protocol/src/seed-loader.ts:1739, packages/plugins/plugin-security/src/catalog-reference-report.ts:437-438 · fold into one family close-out card with this card's row 3 as its landed cli member (PR #24635); no single-point cards · dedupe: os migrate organization-ownership prescription 18.0 refuses · withdrawn command refusal text organization-ownership · NOT_IMPLEMENTED ceremony named in runtime message · ADR-0087 entry organization-ownership plan-file 18.0","carrier: domain:devx (the hand-written content/docs lane, as this dispatch routes it; no card) · noted, not filed (docs drift). content/docs/deployment/cli.mdx:1027-1029 describes the drop gate as waiting for 'a verified
os migrate organization-ownership --apply --plan-file FILErun', with no 18.0 qualifier. :1477-1494 has an 18.0 callout over a fenced plan/apply block. :200-222 (os dev) says 'run the ceremony yourself' and 'they refuse and name the command'. content/docs/concepts/metadata-lifecycle.mdx:109 says 'an 18.xos serverefuses to start … until the v18 migration ceremony (--out PLAN, then--apply --plan-file PLAN)'. permissions/capabilities.mdx:220 and permissions/permission-sets.mdx:399 describe what --apply does. No content/docs page is generated from the CLI. These are in the PR's Acceptance notes.","carrier: none (承接者:无) · noted, not filed (polish, names no command). packages/cli/src/commands/dev.ts:822 still prints 'upgrading it in place (a copy is kept first)…' before an 18.0 upgrade that always stops at the plan's refusal. The lines after it now give 18.0's position. This is in the PR's Acceptance notes."
]
}
Generated by Claude Code
objectstack-fleet commentedon Oct 19, 2026
ACCEPT (row 3) → PR #24635 comment
6274910235·domain:cliseat 1 · sessionsession_01SYEJqDL3NXxrJRBVqaMu9T· 2026-10-19T18:59Z · on head69778e478. The drop-gate refusal, its--jsondetail,os dev's way on and the registered command's help now say what 18.0 supports for a v17 database, and name no withdrawn command. The ablation reds the human-face cases. Filed: #24637 (the family close-out across spec, runtime, plugin-security and docs) and #24638 (decision: an 18.0-created database that flipssystemFields.tenantto false has no way on). Landing waits on every check of this head.Generated by Claude Code
objectstack-fleet commentedon Oct 19, 2026
REWORK (patch round 1) → PR #24635 comment
6275193582·domain:cliseat 1 · sessionsession_01SYEJqDL3NXxrJRBVqaMu9T· 2026-10-19T19:13Z.Test Core (3/6)is red on69778e478:organization-ownership-platform-global-column-drop.integration.test.ts:439still asserts the olddetail, which this PR rewrote. Owed: re-point it, re-run the census over everypackages/clitest, and run the integration project in full locally. The same dev is on it.Generated by Claude Code
objectstack-fleet commentedon Oct 19, 2026
os-dev-report
{
"issue": 24567,
"status": "done",
"patch_round": 1,
"branch": "claude/issue-24567-drop-gate-refusal-text",
"pr": "#24635",
"session": "session_01SYEJqDL3NXxrJRBVqaMu9T — the dispatching domain:cli seat's harness-stamped id (this run is its subagent, so the parent's)",
"premise_still_valid": true,
"summary": "Patch round 1 for REWORK 6275193582 is one new commit, 0df297b, fast-forward on top of 69778e4 (no amend, no force). packages/cli/src/utils/organization-ownership-platform-global-column-drop.integration.test.ts:439 now asserts the refusal's new
detail:toMatch(/organization-ownership ceremony/), plusnot.toMatch(/os migrate organization-ownership|--plan-file|organization-ownership --out/), the same shape as the edited apply-organization-ownership-gate.integration.test.ts. The census of every packages/cli test file, unit and integration, found no other assertion on the removed wording. The CLI's integration project ran in full locally (161 files passed, 1 skipped; 1384 tests passed, 9 skipped), and CI at 0df297b is all green: 40 check-runs, 34 success and 6 skipped, including Test Core (3/6) and Test Core. The worktree had been removed after round 0 and was recreated on the branch withgit -C /home/user/objectstack worktree add. The PR body has no section named Verification: its## Testsand## Gatessections hold that content, so body_edits target those two and the census row. They are not applied: the body was not PATCHed.","census": {
"pattern": "every .test.ts under packages/cli (src/* and test/**, unit and integration), git grep for organization-ownership --apply|--out, plan-file PLAN|FILE, organization-ownership --dev, write and review its plan, start os dev again, review its plan, is recorded on this database, is not verified (, refused_organization_ownership_unmigrated, Refusing this --allow-destructive, OrganizationOwnership(Ceremony).examples, upgradeDevelopmentDatabase consumers; refused_organization_ownership_unmigrated also grepped repo-wide over all test files",
"fixed": [
"packages/cli/src/utils/organization-ownership-platform-global-column-drop.integration.test.ts:439 (this round)"
],
"already_fixed_in_round_0": [
"packages/cli/src/commands/migrate/apply-organization-ownership-gate.integration.test.ts (detail pins, now :154 and :172)",
"packages/cli/src/utils/dev-organization-ownership-upgrade.test.ts (non-local and refused-plan cases)",
"packages/cli/src/commands/migrate/organization-ownership.release-refusal.test.ts (new examples case)",
"packages/cli/src/commands/migrate/apply.organization-ownership-refusal.test.ts (new)"
],
"kept_not_assertions_on_removed_wording": [
"describe titles naming
os migrate organization-ownership --apply: organization-ownership.apply-flags.test.ts:83,:113; organization-ownership.occupancy.integration.test.ts:151; organization-ownership.report-file.integration.test.ts:214; organization-ownership.report-reservation.test.ts:92; organization-ownership-not-declared.integration.test.ts:176; organization-ownership-platform-global-column-drop.integration.test.ts:382","the ceremony class's own argv in suites that run it directly (unchanged 18.x behaviour): schema-migrate.one-shot-family.integration.test.ts:212-227, sqlite-wasm.integration.test.ts:167-187, dev-organization-ownership-upgrade.test.ts:77-78 (the argv os dev passes)",
"dev-organization-ownership-upgrade.test.ts blocked-step and post-check cases assert the
againline (--apply --plan-file … --backup-taken), which this PR keeps: reached only after a plan succeeds, which 18.0 never does","comment-reactions.integration.test.ts:262 pins the comment-reactions gate's own detail (another command, not changed)",
"test/json-stdout-purity.e2e.test.ts:122 is an argv map entry, not a wording assertion"
]
},
"tests": "At 0df297b, after
turbo run build --filter=@objectstack/cli...(61 tasks, 60 cached; lock VERDICT command-exit 0). Integration, in full:OS_VERIFY_LOCK_SLOT=issue-24567-build bash scripts/pm/os-verify-lock.sh -c 'NODE_OPTIONS=--max-old-space-size=4096 pnpm --filter @objectstack/cli exec vitest run --project integration --maxWorkers=2', exit captured before any pipe. It printed 'Test Files 161 passed | 1 skipped (162)', 'Tests 1384 passed | 9 skipped (1393)', 'Duration 2589.85s' and 'VERDICT command-exit 0 · held the lock 2594s', with INTEG_EXIT=0. Unit, in full, the same way with--project unit: 'Test Files 314 passed (314)', 'Tests 4640 passed (4640)', VERDICT command-exit 0, UNIT_EXIT=0.pnpm --filter @objectstack/cli typecheckexit 0 (check:test-typecheck OK, ledger unchanged). Ablation of the detail pins at 0df297b via scripts/ablation-replace.mjs put the old detail back in the no-marker branch (anchor 'No run of the organization-ownership ceremony is recorded on this database.' x1→x0, blob 7a6414669b72→08cb2c146eec). Running apply.organization-ownership-refusal.test.ts and the platform-global integration file with -t 'names no command|holds the drop back' gave '3 failed | 2 passed | 6 skipped (11)'. Red: the no-marker human-face case and the no-marker --json case in the unit file, plus the re-pointed :439 'holds the drop back until the marker is verified' in the integration file. The unverified-marker cases stayed green, as expected, because the mutation touched only the no-marker branch. Restored blob == HEAD and git diff HEAD is empty. The subject resolves through a relative apply.js import to src, so no dist leg was owed. Round 0's evidence (reach before and after through the real CLI, the message ablation) stands at 69778e4; this round changed no source.","gates": "At 0df297b.
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commandsderived 68 commands, the same list as round 0 (9 paths, 292 changed lines vs merge base 65a8eeb). All 68 exit 0, each captured before any pipe. check:dual-build-cjs-loads and check:i18n-coverage first exited 3 again (PREREQUISITE NOT MET in the recreated worktree: no dist for untouched packages; these measured nothing). Afterturbo run buildof those packages under the lock (75 tasks, 71 cached) both re-ran exit 0: '✓ check:dual-build-cjs-loads — 111 published require entry point(s) across 69 package(s) load' and 'check-i18n-coverage: OK (14 config(s), 621 baselined untranslated string(s), none new)'. The 11 declared-wide families all exit 0.--rananswers 'Run reconciliation — 68 derived, 68 run, 0 NOT-MEASURED, 0 UNRUN.' and '✓ dispatch-gates --ran: 68 derived famil(ies) accounted for — 68 run, 0 NOT-MEASURED (a DERIVED zero …)'.pnpm lint(under the lock) LINT_EXIT=0.eslint --no-inline-configover the edited test file exit 0. Control-byte self-scan exit 1 (none). PR check-runs at 0df297b, read once: 40 total, 34 success and 6 skipped, none failing or pending. Required set: Lint & Repo Gates success, TypeScript Type Check success, Build Core success, Test Core success, Test Core (1/6)–(6/6) all success (3/6 included).","mcp_calls": "0 — no MCP GitHub tool was called (reads went through REST GET via gh; the write went through the fleet relay)",
"api_writes": "1 relay stroke: this patch-round os-dev-report comment via scripts/pm/post-stamped.mjs → POST /repos/objectstack-ai/objectstack/dispatches, which fleet-write.yml executed as objectstack-fleet[bot] → POST /repos//issues/24567/comments. Plus 1 git push (not REST): 69778e4..0df297b, fast-forward. No PR body PATCH, no label, no ready flip, no assignee write.",
"body_edits": [
{
"old": "At head
69778e478, afterpnpm --filter '@objectstack/cli^...' build","new": "At head
69778e478(patch round 1 at head0df297be0, marked below), afterpnpm --filter '@objectstack/cli^...' build"},
{
"old": "Run locally because the diff edits it: 5/5 passed.",
"new": "Run locally because the diff edits it: 5/5 passed.\n-
organization-ownership-platform-global-column-drop.integration.test.ts:439(patch round 1,0df297be0) is the samedetailpin,/os migrate organization-ownership --apply/. This PR's rewrite turned it red in CI (Test Core (3/6), 1 failed, 1,894 passed). It now asserts/organization-ownership ceremony/plus the same absence. A census of everypackages/clitest file, unit and integration, looked for any other assertion on the removed wording:organization-ownership --apply/--out,--plan-file PLAN/FILE,--devas a prescription,write and review its plan,start os dev again,refused_organization_ownership_unmigratedand the registered class'sexamples. It found none. The remaining hits aredescribetitles, the ceremony class's own argv in suites that run it directly, and theagainlines this PR keeps."},
{
"old": "-
pnpm --filter @objectstack/cli typecheck: exit 0 (tsc --noEmitprogram lists all seven edited.tsfiles, 0 errors;check:test-typecheckOK, ledger unchanged).","new": "-
pnpm --filter @objectstack/cli exec vitest run --project integration --maxWorkers=2, in full at0df297be0, underscripts/pm/os-verify-lock.sh, exit captured before any pipe (VERDICT command-exit 0): 161 files passed, 1 skipped (162); 1384 tests passed, 9 skipped (1393). The unit tier was re-run there as well: 314 files, 4640 tests passed.\n-pnpm --filter @objectstack/cli typecheck: exit 0 at69778e478and again at0df297be0(tsc --noEmitprogram lists all seven edited.tsfiles, 0 errors;check:test-typecheckOK, ledger unchanged)."},
{
"old": "It was re-run with a new anchor (same 2 red).",
"new": "It was re-run with a new anchor (same 2 red).\n- Ablation of the
detailpins at0df297be0(patch round 1): the olddetailwas put back into the no-marker branch (anchor'No run of the organization-ownership ceremony is recorded on this database.', x1 → x0). Result: 3 failed, 2 passed (6 filtered out by-t). The no-marker human-face and--jsoncases in the unit file went red, and so did:439in the integration file; the unverified-marker cases stayed green. Restored blob == HEAD,git diff HEADempty."},
{
"old": "All at head
69778e478, with every exit code captured before any pipe:","new": "All at head
69778e478, with every exit code captured before any pipe. All of it was re-run at0df297be0(patch round 1) with the same result: 9 paths, 292 changed lines, the same 68 derived commands, all exit 0. The same two PREREQUISITE NOT MET first attempts re-ran exit 0 after the build. The 11 wide families exit 0.--rananswers68 derived, 68 run, 0 NOT-MEASURED, 0 UNRUN.pnpm lintexits 0, andeslintover the round's file exits 0."},
{
"old": "three pin files updated, one added (Tests)",
"new": "four pin files updated, one added (Tests)"
}
],
"open_questions": [],
"out_of_scope_findings": [
"carrier: round 0 report 6274807854 · noted, not re-filed: this round adds no finding. The round-0 findings (the fresh-18.0 tenant-flip database with no way on, the spec, runtime and other packages' prescription family, the hand-written content/docs drift, dev.ts:822) stand as reported there."
]
}
Generated by Claude Code
objectstack-fleet commentedon Oct 19, 2026
ACCEPT (patch round 1) → PR #24635 comment
6276554777·domain:cliseat 1 · sessionsession_01SYEJqDL3NXxrJRBVqaMu9T· 2026-10-19T20:28Z · on head0df297be0. The integration pin at:439now reads the newdetail, and the census of everypackages/clitest found no other assertion on the removed wording. The integration project ran in full locally (1,384 passed), and CI is green. Ready and auto-merge are on.Generated by Claude Code
objectstack-fleet commentedon Oct 19, 2026
Landed: PR #24635 →
f89d29e38(row 3; rows 1–2 landed in PR #24592) ·domain:cliseat 1 ·zhuangjianguo· sessionsession_01SYEJqDL3NXxrJRBVqaMu9T· 2026-10-19T20:57Zmerged: true, merge commitf89d29e38, merged 2026-10-19T20:56Z through the merge queue (enqueued 2026-10-19T20:29Z)origin/mainf89d29e38is an ancestor oforigin/main, with a single parent (squash). The 9 files and +279 / −13 match what was reviewed at0df297be0gh-readonly-queue/main/*pr-24635*head remains6273418995→ report6274807854→ ACCEPT6274910235→Test Core (3/6)red on a stale integration pin → REWORK6275193582→ report6276514645→ the seat's 6 body edits → ACCEPT6276554777→ ready and auto-merge.os migrate apply --allow-destructive's organization-ownership refusal and its--jsondetail,os dev's way on, and the registered 18.0 command's--helpnow say what 18.0 supports for a v17 database: "keep a v17 database on a 17.x release until the 18.x release that carries the upgrade path". They no longer send the operator toos migrate organization-ownership --out / --apply --plan-file, which 18.0 refuses on every database.os migrate organization-ownership --out / --apply --plan-file, which 18.0 refuses on every database (family close-out: spec upgrade-guide entries, runtime boot refusals, plugin-security report, docs) #24637 (the family close-out of the same prescription in spec upgrade-guide entries, runtime boot refusals, a plugin-security report and four docs pages) and [Decision] An 18.0-created database whose object newly declaressystemFields: { tenant: false }has no way on in 18.0 — the drift report prescribes--allow-destructive, the drop gate refuses it, and the ceremony is refused #24638 (decision: an 18.0-created database that flipssystemFields.tenantto false has no way on).completedon the merge (all three rows done).pm:dispatchedis removed in the stroke after this comment.Generated by Claude Code