Repository navigation
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
Copy link
Copy link
Closed
Labels
domain:enginepriority:p1High: required for production / M2High: required for production / M2target:v18
Description
Part of #15211
Handed out of the #15194 epic subtree to the domain:engine lane. The epic PM (session_01Rerax7QTjKMPCUZxQUtPFR, marchtian) did this at the maintainer's request in its session on 2026-10-12: clear next-step work that can be built ahead goes to lane PMs, and the maintainer's tasks are high priority (priority:p1). This card is the lane's claim surface. #15211 stays open and blocked for its landing gate; this card carries no Blocked-by:, because building ahead is not landing.
Why now
- 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 release-cut condition (b) of the final v18 release (6102862135). The
nextprerelease is exempt (maintainer ruling 6117174845). - feat(objectql,cli): inventory + migration — four fates per object, mirrors deleted only after the id→name rewrite is verified, per-table boot report (ADR-0131 D10) #15211's
Blocked-by: #15196/#15204gate its landing. Building ahead follows the epic's rule: "Development runs ahead of landing" (6095755866). - On
main(06cc45dc36),os migrate organization-ownershipalready exists as a read-only plan (packages/cli/src/commands/migrate/organization-ownership.ts,utils/organization-ownership-plan.ts,utils/organization-ownership-inventory.ts). The--applyhalf 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's scope is not built.
Scope (read #15211's body in full first; it governs)
- E5's mappers, in core. Seat answer 6110777865 (E5 → A), and its note 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, 6110790598.
- Add pure functions beside
convertPositionBindingRows(packages/core/src/security/position-binding-conversion.ts:90), each with pins:- a permission-set row → definition, the logic of
permissionSetBodyFromRow(packages/plugins/plugin-security/src/permission-set-projection.ts:409); - a position row → definition, the mapping in
position-environment-backfill.ts.
- a permission-set row → definition, the logic of
- Use new files in core only. ⛔ Do not edit
packages/plugins/plugin-security/**. Those files belong to refactor(plugin-security,platform-objects,spec): retire the catalog seeders, the per-organization catalog machinery and the four catalog objects; Setup creation is an environment write undersingleand refused under a wall (ADR-0131 D2/D3/D5/D13) #15204: stage 8 (session_01MGoWgeE8rhsrig77V4oUZn, building now) and 7a/7b, which will switch to these functions and delete their copies. - This PR changes no behaviour, and may land when green.
- Add pure functions beside
--apply, per feat(objectql,cli): inventory + migration — four fates per object, mirrors deleted only after the id→name rewrite is verified, per-table boot report (ADR-0131 D10) #15211's scope:- the explicit backup acknowledgement;
- the fate order attribution → verified id→name rewrite → mirror deletion → column drops;
- idempotent, and resumable from a recorded checkpoint;
- an operator ceremony, ⛔ never a boot step.
- The id→name rewrite:
sys_user_permission_set.permission_set_id→permission_set. The column stays until C7b (refactor(plugin-security,platform-objects,spec): retire the catalog seeders, the per-organization catalog machinery and the four catalog objects; Setup creation is an environment write undersingleand refused under a wall (ADR-0131 D2/D3/D5/D13) #15204 stage-8 refresh 6116546399, E3): stage 8 redeclares it asField.text, keeping its stored ids, the unique index (user_id,permission_set_id,organization_id) and the(permission_set_id)index. C7b drops the column and both indexes, and judges whether the unique index still means anything once new grants write NULL there. - Mirror deletion stays behind fate 2's own gate: C2's rewrite report shows every reference resolves by name.
- The inventory's
authoredcategories convert through step 1's mappers (6110790598). - It absorbs
sys_business_unit_memberis unadjudicated inPLATFORM_OBJECT_TENANCY, so seed-replayed and system-written membership rows land organization-less #14570 and plugin-sharing: after the #15030 revert, 17.x still cannot reach a NULL-org-seeded business unit from an org-stamped rule — and #14547, its only tracker, is closed #15086, as 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 says. - This PR stays a draft until refactor(plugin-security,platform-objects,spec): retire the catalog seeders, the per-organization catalog machinery and the four catalog objects; Setup creation is an environment write under
singleand refused under a wall (ADR-0131 D2/D3/D5/D13) #15204's stage 8 is onmain. Then mergemain, re-run, and land.
- feat(objectql,cli): inventory + migration — four fates per object, mirrors deleted only after the id→name rewrite is verified, per-table boot report (ADR-0131 D10) #15211's acceptance: a fixture database carrying every fate.
Boundaries
- ⛔ No stacked PRs; every PR is based on
main. - ⛔ Never touch
content/docs/releases/orCHANGELOG.md. - ⛔ Never edit plugin-security files or
content/docs/permissions/system-context.mdxhere. - Coordination: post on this card. Post one pointer on refactor(plugin-security,platform-objects,spec): retire the catalog seeders, the per-organization catalog machinery and the four catalog objects; Setup creation is an environment write under
singleand refused under a wall (ADR-0131 D2/D3/D5/D13) #15204 when a PR opens, so the epic seat can align stage 8 and 7a/7b with it. Questions go here, and the epic seat answers here. - Re-verify on
mainbefore building that no branch or PR already does this (the maintainer's 「不要重复开发」).
Refs
#15211 · ADR-0131 D10, D4 · seat answers 6110777865 and 6116546399 · seat note 6110790598 · release-cut record 6102862135 · ruling 6117174845.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
domain:enginepriority:p1High: required for production / M2High: required for production / M2target:v18
Activity
objectstack-fleet commentedon Oct 12, 2026
Claim: PM loop round 1 · 2026-10-12T04:05Z · PR 1 of 2 (the core mappers)
Session:
session_01ADzJtzYTLUfgrRZHxkagkXAccount:
os-steve(the seat's linked user asGET /useranswers it; always the card's assignee)Branch:
claude/issue-22937-core-row-definition-mappersWorktree:
objectstack-issue-22937Domain:
domain:engineSeat:
domain:engine#2(seat post #20966); the lane's only seated PMPriority: dispatched out of order, beyond the seat's default batch of 3 (4 in flight, inside the ceiling of 5), on the maintainer's order in this session: 「objectstack#22937 插队,现在就派」.
File surface for PR 1 (read on
origin/main1bd612bd68; stop on a breach and explain it in the report). ⛔ Classes, positions and functions only, in every artefact.packages/core/src/security/, besideposition-binding-conversion.ts. They hold two pure functions, each with pins:permissionSetBodyFromRow(packages/plugins/plugin-security/src/permission-set-projection.ts);packages/plugins/plugin-security/src/position-environment-backfill.ts.packages/core/src/security/index.ts: export the two, asconvertPositionBindingRowsis exported.packages/plugins/plugin-security/**(refactor(plugin-security,platform-objects,spec): retire the catalog seeders, the per-organization catalog machinery and the four catalog objects; Setup creation is an environment write undersingleand refused under a wall (ADR-0131 D2/D3/D5/D13) #15204 stage 8 and 7a/7b own those files and switch to these functions later). ⛔ Notcontent/docs/permissions/system-context.mdx, notcontent/docs/releases/, notCHANGELOG.md.--applyinpackages/cli, cross-lanedomain:cli) is claimed after PR 1 lands, based onmain, and stays a draft until refactor(plugin-security,platform-objects,spec): retire the catalog seeders, the per-organization catalog machinery and the four catalog objects; Setup creation is an environment write undersingleand refused under a wall (ADR-0131 D2/D3/D5/D13) #15204 stage 8 is onmain(card body).Container & model:
M,mode:subagent,model: default(dispatch-gates --tier: no path-derived mandate)Clause-②: yes
@objectstack/core's published surface (.re-exports./security/index.js). So the changeset ships@objectstack/coreminor, and PR 1 owes one contract-tier review before the queue.Responsibility: n/a — not a defect card (a build-ahead execution card, part 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)
Thread-read: none
Serial constraints cleared: no open PR touches
packages/core/src/security/or theorganization-ownershipfiles inpackages/cli. No branch or PR builds these mappers or--apply(checked at claim, per the card's 「不要重复开发」). refactor(plugin-security,platform-objects,spec): retire the catalog seeders, the per-organization catalog machinery and the four catalog objects; Setup creation is an environment write undersingleand refused under a wall (ADR-0131 D2/D3/D5/D13) #15204 stage 8 (session_01MGoWgeE8rhsrig77V4oUZn) is building inplugin-security, which is disjoint. This seat's in-flight [Decision] security(objectql): a validation rule that reads one hop through a master-detail FK still reads the header elevated, so an unreadable header's answer varies with its stored state after ruling A #22892, [finding] email_template: a Studio save of the same template in a second locale replaces the first locale's overlay at the next boot (sys_metadata keeps one overlay row per type and name) #22877 and finding: a multi-valued reference field (lookup/userwithmultiple: true) admits an element of the wrong shape: REST stores an embedded record[{ id }]with 201, where the single-valued field refuses itinvalid_type(ADR-0104 D1) #22908 sit inobjectqlandmetadata-*, also disjoint.objectstack-fleet commentedon Oct 12, 2026
os-dev-report
{ "issue": 22937, "status": "done", "branch": "claude/issue-22937-core-row-definition-mappers", "pr": "https://github.com/objectstack-ai/objectstack/pull/22959", "session": "session_01ADzJtzYTLUfgrRZHxkagkX (subagent; the parent PM session)", "premise_still_valid": true, "summary": "PR 1 of 2 (draft #22959, base main, head e975c410bc): two pure functions in @objectstack/core beside convertPositionBindingRows, each in a new file with pins and exported from security/index.ts. permissionSetDefinitionFromRow reproduces plugin-security's permissionSetBodyFromRow (parseMaybeJson and the PermissionSetSchema-shape key filter copied into core); positionDefinitionFromRow reproduces the backfill's mapping, positionBodyFromRow (it lives in position-write-through.ts, not position-environment-backfill.ts). Byte-for-behaviour equivalence with both originals was measured once over 60,244 and 20,737 generated rows with 0 differences and a positive control that does differ; core cannot import plugin-security without a new dependency, so the permanent pins assert the documented outputs. No behaviour change, no plugin-security edit, no new dependency; Section 2's premises held (the export path, purity, core already imports @objectstack/spec/security values). No duplicate: no branch or open PR builds these mappers at start (the #15204 branches were read; S8 only deletes core's row-active.ts). CI not awaited (in progress at report time); contract-tier review is owed (Clause-2 yes).", "tests": "At final head e975c410bc: pnpm --filter @objectstack/core test -> Test Files 96 passed, Tests 2402 passed (both new files listed by vitest list --project local); pnpm --filter @objectstack/core typecheck -> exit 0, check:test-typecheck OK 4 files / 4 errors held, none in the new files (they are in tsconfig.test.json's --listFiles program). New pins: permission-set-row-definition.test.ts 12 tests, position-row-definition.test.ts 9 tests, green. Equivalence (one-time, scratch, not committed): tsx imports the plugin-security originals and the core functions from source and compares with util.isDeepStrictEqual plus key order plus JSON.stringify plus thrown errors -> permission sets 60244 rows 0 differing, positions 20737 rows 0 differing; positive control with mutated variants -> 7174 and 1152 differing. Ablation (fix committed first; subject imported by relative path, so no dist leg): scripts/ablation-replace.mjs WRAP inside a script with an absolute-path trap restore. Leg 1 label fallback 'label: row?.label ?? row?.name,' -> 'label: row?.label,' (anchor 1->0, replacement 0->1, blob f4e53ca6a2cb -> 549050ec1563) -> 2 of 12 failed (label rule, defaults row); restored, blob f4e53ca6a2cb == HEAD, git diff HEAD empty. Leg 2 delegatable \"row.delegatable === '1'\" -> \"row.delegatable === 'one'\" (blob b998eca94d1a -> 45a6a73356db) -> 1 of 9 failed (delegatable rule); restored, blob b998eca94d1a == HEAD, diff empty. Direction observed: red, as expected. Builds: CJS and ESM dist of core both export the two functions; both .d.ts declare them. Lint narrowed and proven: eslint over the 5 changed TS files, 0/0; population read from eslint.config.mjs (all 5 inside, none ignored); invariance: no type-aware linting and the local plugins are per-file AST rules, so no untouched file's verdict can move; full pnpm lint is CI's.", "mcp_calls": "0", "api_writes": "2 relay dispatches (POST /repos/objectstack-ai/objectstack/dispatches, via scripts/pm/with-fleet.sh --via dispatch and scripts/pm/post-stamped.mjs), executed as objectstack-fleet[bot]: POST /repos/objectstack-ai/objectstack/pulls (draft #22959), POST /repos/objectstack-ai/objectstack/issues/22959/assignees (os-steve), POST /repos/objectstack-ai/objectstack/issues/22937/comments (this report). Not REST: 3 git push of the branch (empty probe, WIP commit, doc commit plus merge of origin/main). Label writes: none.", "open_questions": [], "out_of_scope_findings": [ "carrier: PR 2 of #22937 and #15204's 7b · the backfill's two decisions around the mapping stay in plugin-security, by the card's row-to-definition scope: the door's position-name grammar (metadataDoorAcceptsPositionName) and the rows-of-one-name-must-agree check. 7b's deletion of position-write-through.ts removes the predicate; PR 2 can rely on the metadata door's own refusal or move the predicate into core then. The core mapping's key order is pinned so a serialized comparison of two rows' definitions stays meaningful · noted in the PR's Acceptance notes, not filed", "carrier: #15204 S8 (session_01MGoWgeE8rhsrig77V4oUZn) · S8 deletes packages/core/src/security/row-active.ts and its export block in security/index.ts; this PR adds its block after convertPositionBindingRows, a different hunk, and neither new file imports row-active.ts · noted, not filed", "carrier: none needed · @objectstack/runtime and @objectstack/plugin-hono-server export * from @objectstack/core, so they re-export the two functions; git grep finds the four new names only in core, no collision · noted in Acceptance notes, not filed" ], "gates": [ "node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0", "node scripts/check-adr-0087-registration.mjs --self-test :: exit 0", "node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0", "node scripts/check-changeset-no-major.mjs --self-test :: exit 0", "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-adoption.mjs :: exit 0", "node scripts/check-comment-mask-adoption.mjs --self-test :: exit 0", "node scripts/check-comment-mask-corpus.mjs :: exit 0", "node scripts/check-dev-prereqs.mjs --self-test :: exit 0", "node scripts/check-dts-emitted.mjs --self-test :: exit 0", "node scripts/check-empty-changeset.mjs --base origin/main :: exit 0", "node scripts/check-empty-changeset.mjs --self-test :: exit 0", "node scripts/check-issue-citations.mjs :: exit 0", "node scripts/check-keyed-text-bounds.mjs :: exit 0", "node scripts/check-keyed-text-bounds.mjs --self-test :: exit 0", "node scripts/check-platform-object-tenancy-census.mjs :: exit 0", "node scripts/check-platform-object-tenancy-census.mjs --self-test :: exit 0", "node scripts/check-plugin-teardown-shape.mjs :: exit 0", "node scripts/check-plugin-teardown-shape.mjs --self-test :: exit 0", "node scripts/check-registry-log-declared.mjs :: exit 0", "node scripts/check-registry-log-declared.mjs --self-test :: exit 0", "node scripts/check-rest-log-spy-declared.mjs :: exit 0", "node scripts/check-rest-log-spy-declared.mjs --self-test :: exit 0", "node scripts/check-system-context-census.mjs :: exit 0", "node scripts/check-system-context-census.mjs --self-test :: exit 0", "node scripts/check-undeclared-dep-imports.mjs :: exit 0", "node scripts/check-undeclared-dep-imports.mjs --self-test :: exit 0", "node scripts/docs-audit/check-affected-docs.mjs :: exit 0", "node scripts/docs-audit/check-drift-comment.mjs :: exit 0", "node scripts/pm/release-rehearsal-clone.mjs --self-test :: exit 0", "node scripts/release-pending-publish.mjs --self-test :: exit 0", "pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0", "pnpm check:changeset-gate-self-tests :: 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:dts-closure :: exit 0", "pnpm check:dual-build-cjs-loads :: exit 0", "pnpm check:engine-double-contract :: exit 0", "pnpm check:gitlink-declared :: exit 0", "pnpm check:issue-citations :: exit 0", "pnpm check:kernel-hook-pairs :: exit 0", "pnpm check:lean-entry-closure :: exit 0", "pnpm check:logger-receiver-detach :: exit 0", "pnpm check:nul-bytes :: exit 0", "pnpm check:objectql-double-limit :: exit 0", "pnpm check:objectui-changeset :: exit 0", "pnpm check:org-identifier :: exit 0", "pnpm check:page-declaration-shape :: exit 0", "pnpm check:pm-changeset-deadline-census :: exit 0", "pnpm check:published-files :: exit 0", "pnpm check:query-options-erasure :: exit 0", "pnpm check:refd-timer-probe :: exit 0", "pnpm check:slot-lookup :: exit 0", "pnpm check:sourcemap-no-sources-content :: exit 0", "pnpm check:test-source-alias :: exit 0", "pnpm check:tier-file-adoption :: exit 0", "pnpm check:type-check-coverage :: exit 0", "pnpm check:type-check-debt :: exit 0", "pnpm check:watch-hint-literal :: exit 0", "pnpm check:where-matcher :: exit 0", "pnpm --filter @objectstack/core test :: exit 0", "pnpm --filter @objectstack/core typecheck :: exit 0", "OS_VERIFY_LOCK_SLOT=issue-22937-build os-verify-lock.sh -c 'pnpm turbo run build --filter=@objectstack/core --concurrency=2' :: exit 0 (VERDICT command-exit 0; 4 tasks, 3 cached; two earlier attempts exit 99 queue-timeout and one exit 2 filter-matches-nothing, nothing ran)", "os-verify-lock.sh -c 'pnpm turbo run build --filter=@objectstack/objectql --concurrency=2 && pnpm --filter @objectstack/core exec vitest run --maxWorkers=2 (3 files)' at e975c410bc :: exit 0 (14 tasks, 8 cached; 3 files / 28 tests)", "pnpm --filter @objectstack/core exec vitest run --maxWorkers=2 src/security/permission-set-row-definition.test.ts src/security/position-row-definition.test.ts :: exit 0 (2 files / 21 tests)", "tsx equivalence.mts (scratch, one-time) at e975c410bc :: exit 0 (permission sets 60244 rows 0 differing; positions 20737 rows 0 differing)", "tsx equivalence-control.mts (mutated variants) :: exit 1 as expected (7174 and 1152 differing)", "ablate.sh permission-set leg (ablation-replace WRAP) :: wrapped vitest exit 1 as expected (2 of 12 failed); restore proven", "ablate.sh position leg (ablation-replace WRAP) :: wrapped vitest exit 1 as expected (1 of 9 failed); restore proven", "eslint --no-inline-config --format json (5 changed TS files) :: exit 0 (5 files, 0 errors, 0 warnings)", "node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --ran ran.txt :: exit 0 (63 derived, 63 run, 0 NOT-MEASURED derived, 0 UNRUN)" ], "line_budget": "483 (PR additions 483 + deletions 0, 6 files; no generated files)", "deviations": [ "My first dispatch-gates re-derivation ran in the shared checkout /home/user/objectstack, because a trailing & backgrounded the whole cd-chain. It was read-only (exit 2, nothing written), and I re-derived from the worktree.", "Battery 1 at e5c8727332: check:type-check-debt hit my own 400s per-command timeout (exit 124, NOT MEASURED there), and three dist gates exited 3 (no dist, NOT MEASURED). The final union at e975c410bc supersedes it: all 63 exit 0, the dist gates measured real populations (72 / 66 / 15 packages), and check:type-check-debt finished green.", "Those dist populations exist because check:type-check-debt's re-measure builds the closure it type-checks. Between the tree it built (e5c8727332) and e975c410bc, only comment edits in my two core files touched packages/, and core's dist carries the final wording.", "Equivalence with plugin-security was measured once in a scratch script, not as a permanent test, because core cannot import plugin-security without a new dependency (the PM's route allows this).", "I merged origin/main once before opening the PR (AGENTS.md section 10). The incoming 5 commits touch docs, workflows and docs-audit scripts only.", "Commit trailers use AGENTS.md's model-free pair (Claude-Session plus the bare Co-authored-by: Claude), not the harness reminder's model-named Co-Authored-By. The PR footer uses AGENTS.md's session-URL footer, not the reminder's emoji line. The reminder yields to CLAUDE.md and AGENTS.md by its own precedence sentence.", "PR body line 2 is 'Clause-②: yes', verbatim from the claim. The changeset carries 'Clause-②: yes (widening)', following the sibling core changeset convention. These are not a conflict.", "No conflict found between the dispatch and .claude/agents/os-dev.md." ], "files_changed": [ ".changeset/22937-core-row-definition-mappers.md", "packages/core/src/security/index.ts", "packages/core/src/security/permission-set-row-definition.ts", "packages/core/src/security/permission-set-row-definition.test.ts", "packages/core/src/security/position-row-definition.ts", "packages/core/src/security/position-row-definition.test.ts" ] }objectstack-fleet commentedon Oct 12, 2026
os-dev-report
patch round 1
{ "issue": 22937, "status": "done", "branch": "claude/issue-22937-core-row-definition-mappers", "pr": "https://github.com/objectstack-ai/objectstack/pull/22959", "head": "d477e5fbef0f89677a44b55eb93ec1e170497987", "session": "session_01ADzJtzYTLUfgrRZHxkagkX (subagent; the parent PM session)", "premise_still_valid": true, "summary": "Patch round 1, wording only. One commit d477e5fbef on the branch (new head; parent e975c410bc; no merge of main, since the PR reads mergeable=true): the changeset's What-is-new bullet now says the ceremony is to apply the mappers; the permission-set bullet states the label condition (null or absent falls back, an empty-string label is kept, unlike the position rule), lists null and JSON null among the facet defaults, separates 'only the definition columns are read' from 'the body is filtered to the keys PermissionSetSchema declares', and tightens 'adminScope when set' to the code's condition (truthy column that reads to a truthy value); the position bullet says description travels only as a non-empty string (null, '', absent and non-string are absent; whitespace-only travels as stored). position-row-definition.ts's docblock reads 'a null or empty column'. Each clause was read against the code and probed against core and both plugin-security originals; no code changed. The PR body was NOT patched: the role file forbids a dev PATCH of the PR body, which conflicts with this round's permission (see deviations). Its line 11 restates three corrected clauses, and the replacement is given in out_of_scope_findings for the seat to write.", "tests": "At d477e5fbef: node scripts/check-changeset-no-major.mjs --base origin/main exit 0; node scripts/check-adr-0087-registration.mjs --base origin/main exit 0 ('this PR adds no declared-breaking changeset (1 non-breaking changeset(s) seen)'); node scripts/check-empty-changeset.mjs --base origin/main exit 0 ('No empty-frontmatter changeset introduced ... No changeset from the merge base modified or deleted'); eslint --no-inline-config over position-row-definition.ts and its test exit 0, 0 errors 0 warnings each; pnpm check:nul-bytes exit 0 (10979 files, no raw control bytes); vitest on the two pin files 2 passed / 21 tests passed; pnpm --filter @objectstack/core typecheck exit 0 (check:test-typecheck OK, ledger unchanged at 4 files / 4 errors). Clause probe (scratch tsx, core vs plugin-security originals): every corrected clause holds and every case is identical to the original.", "mcp_calls": "0", "api_writes": "1 relay dispatch (POST /repos/objectstack-ai/objectstack/dispatches via scripts/pm/post-stamped.mjs), executed as objectstack-fleet[bot]: POST /repos/objectstack-ai/objectstack/issues/22937/comments (this patch-round report). No issue_patch (declined, see deviations). Not REST: 1 git push of the branch (d477e5fbef). Cumulative for the card: 3 dispatches, 4 executed writes (pull create, PR assignee, 2 report comments), 4 git pushes.", "open_questions": [], "out_of_scope_findings": [ "carrier: the domain:engine seat (PR body write, which the role file reserves to the seat) · PR #22959's body line 11 restates three clauses this round corrected (unconditional label fallback, a facet-default list missing JSON null, 'adminScope travels only when set'). Replace that whole line with: - `permissionSetDefinitionFromRow(row)` (`permission-set-row-definition.ts`): one `sys_permission_set` row into the permission-set definition it carries. It reproduces `permissionSetBodyFromRow` (`plugin-security/src/permission-set-projection.ts`): the JSON-text facet columns become the camelCase body keys; `label` falls back to the name only when the column is `null` or absent (an empty-string label is kept); a facet column that is `null`, absent, an empty string, JSON `null` or unparseable text answers its default; `adminScope` travels only when the column is truthy and reads to a truthy value; only the definition columns are read, and the body is then filtered to the keys `PermissionSetSchema` declares (read from the schema's shape, never transcribed). · No other body line quotes a corrected sentence; the position bullet states no description rule, and the body never says the ceremony applies the mappers · noted, not filed" ], "gates": [ "node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0", "node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0", "node scripts/check-empty-changeset.mjs --base origin/main :: exit 0", "node --stack-size=4000 node_modules/eslint/bin/eslint.js --no-inline-config --format json packages/core/src/security/position-row-definition.ts packages/core/src/security/position-row-definition.test.ts :: exit 0", "pnpm check:nul-bytes :: exit 0", "os-verify-lock.sh -c 'pnpm turbo run build --filter=@objectstack/core --concurrency=2' :: exit 0 (VERDICT command-exit 0; 4 tasks, 3 cached)", "os-verify-lock.sh -c 'pnpm --filter @objectstack/core exec vitest run --maxWorkers=2 src/security/position-row-definition.test.ts src/security/permission-set-row-definition.test.ts && pnpm --filter @objectstack/core typecheck' at d477e5fbef :: exit 0 (VERDICT command-exit 0; 2 files / 21 tests passed; typecheck exit 0, check:test-typecheck OK 4 files / 4 errors held)", "tsx probe.mts (scratch): each corrected clause against core and both plugin-security originals :: exit 0 (whitespace-only description travels; '' and null and 7 descriptions absent; position label '' replaced by the name; permission-set label '' kept and null falls back; admin_scope '0', 'false', 'null' absent; null, '', 'null', unparseable facets answer the default; every case identical to the original)" ], "line_budget": "483 (PR additions 483 + deletions 0 against main, 6 files; this round's commit is +5/-5 inside the PR's new files; no generated files)", "deviations": [ "Conflict, role file applied: this round allows at most one PR-body issue_patch, but .claude/agents/os-dev.md says a dev writes the PR body only once, at creation, never PATCHes it, and names the needed change in the report for the seat to write. The dispatch says the role file wins on conflict, so no PR-body write was made. The exact replacement for line 11 is in out_of_scope_findings.", "Beyond the four listed corrections, also changed to match the code: (a) in the same permission-set bullet, 'admin_scope -> adminScope when set' became 'only when the column is truthy and reads to a truthy value', because a set column of '0', 'false' or 'null' does not travel (probed); (b) the position pin's comment 'A blank description is the same definition as a null one' became 'An empty description ...', because the asserted value is '' and a whitespace-only description serializes differently from null. Both are comment or wording only.", "The worktree was recreated with 'git worktree add ../objectstack-issue-22937 claude/issue-22937-core-row-definition-mappers' (the local branch equals the remote head, e975c410bc). No merge of main: the PR reads mergeable=true.", "No conflict between the PM's four corrections and the code: each matches what core and the plugin originals do." ], "files_changed": [ ".changeset/22937-core-row-definition-mappers.md", "packages/core/src/security/position-row-definition.ts", "packages/core/src/security/position-row-definition.test.ts" ] }objectstack-fleet commentedon Oct 12, 2026
✅ ACCEPT: PR #22959 at
d477e5fbef(PR 1 of 2). Arming held on #22949domain:engineseat 2 (#20966) ·os-steve·session_01ADzJtzYTLUfgrRZHxkagkX· 2026-10-12T06:17Z. Claim 6117549106; reports 6118339780 and 6118594623 (patch round 1). Checked on GitHub rather than taken from the reports. Classes, positions and functions only.main, assigneeos-steve;Part of #22937, with no closing keyword, as PR 1 of 2 should have (PR 2 completes the card);Clause-②: yes, matching the claim and, asyes (widening), the changeset.check-governed-merges --pr 22959: not governed);packages/plugins/plugin-security/**,content/docs/releases/orCHANGELOG.md.permissionSetDefinitionFromRowandpositionDefinitionFromRow, plus their two row types, besideconvertPositionBindingRows, exported from core's.entry. They are re-exported through@objectstack/runtimeand@objectstack/plugin-hono-serverwith no collision. Both are pure, and nothing calls them yet. Read side by side, they give the same output as the plugin originalspermissionSetBodyFromRowandpositionBodyFromRow. The dev's one-time equivalence run agreed: 60,244 and 20,737 rows, 0 differing, with a positive control that does differ. No dependency is added.@objectstack/coreminor, a non-breaking widening, so no ADR-0087 marker is owed. After patch round 1, every sentence matches the code. That round removed the false "blank" sentence and corrected four loose ones, and the seat corrected the matching PR-body line.e975c410bcand a delta PASS ond477e5fbef. Both records are on the PR (CONTRACT_REVIEW_TIER, isolated reviewers, read-only).singleand refused under a wall (ADR-0131 D2/D3/D5/D13) #15204's 7b);security/index.tsis a disjoint hunk;export *are noted.Landing: held. CI on
d477e5fbefis green except theTest Coreaggregator's suite-duration ceiling step:@objectstack/cloud-connection174.50s against 163.89s, which is #22949. Every shard is green, the drift step included. The PR is not armed red.mainhas moved since the merge base, so the dev mergesorigin/mainonce, which is a real merge, not an empty commit. The seat arms on the first head whose required contexts are allsuccess, after confirming that the net diff is unchanged.objectstack-fleet commentedon Oct 12, 2026
os-dev-report
patch round 2 (merge of main)
{ "issue": 22937, "status": "done", "branch": "claude/issue-22937-core-row-definition-mappers", "pr": "https://github.com/objectstack-ai/objectstack/pull/22959", "head": "9e864370ea36d81143dc92610fc1c03912266ec1", "merged_origin_main": "e23eccb164e2e5bd4acc5221b2d9f733818258fa", "session": "session_01ADzJtzYTLUfgrRZHxkagkX (subagent; the parent PM session)", "premise_still_valid": true, "summary": "Patch round 2: one merge of origin/main (e23eccb164) into the branch, with no edits and no conflict; new head 9e864370ea. Before the merge, origin/main was 4 commits past the old merge base 51b43a8dc: git rev-list --count HEAD..origin/main answered 4, and the non-ancestor reading exited 1 with its control leg (51b43a8dc4 is an ancestor) exiting 0. None of those commits touched the PR's six files. No os-regen deferral was recorded. Nothing else changed. The PR API reads head 9e864370ea, +483 / -0 over 6 files, draft, mergeable.", "diff_stat": "git diff origin/main...HEAD --stat -> exactly the PR's six files: .changeset/22937-core-row-definition-mappers.md 12, packages/core/src/security/index.ts 12, permission-set-row-definition.test.ts 160, permission-set-row-definition.ts 119, position-row-definition.test.ts 108, position-row-definition.ts 72; 6 files changed, 483 insertions(+), 0 deletions", "tests": "At 9e864370ea, after pnpm install --frozen-lockfile and a rebuild of core's closure (turbo build --filter=@objectstack/core, 4 tasks, 0 cached, because main moved spec): vitest on the two pin files -> Test Files 2 passed, Tests 21 passed; pnpm --filter @objectstack/core typecheck -> exit 0, check:test-typecheck OK (ledger unchanged at 4 files / 4 errors).", "gates": [ "git merge --no-edit origin/main :: exit 0 (no conflict)", "os-verify-lock.sh -c 'pnpm turbo run build --filter=@objectstack/core --concurrency=2' :: exit 0 (VERDICT command-exit 0)", "os-verify-lock.sh -c 'pnpm --filter @objectstack/core exec vitest run --maxWorkers=2 src/security/position-row-definition.test.ts src/security/permission-set-row-definition.test.ts' :: exit 0 (VERDICT command-exit 0; 2 files / 21 tests)", "os-verify-lock.sh -c 'pnpm --filter @objectstack/core typecheck' :: exit 0 (VERDICT command-exit 0)", "git push origin claude/issue-22937-core-row-definition-mappers :: exit 0 (d477e5fbef..9e864370ea, fast-forward)" ], "mcp_calls": "0", "api_writes": "1 relay dispatch (POST /repos/objectstack-ai/objectstack/dispatches via scripts/pm/post-stamped.mjs), executed as objectstack-fleet[bot]: POST /repos/objectstack-ai/objectstack/issues/22937/comments (this report). No PR-body write. Not REST: 1 git push (9e864370ea).", "line_budget": "483 (PR additions 483 + deletions 0 against main, 6 files; the merge adds nothing to the PR's diff)", "open_questions": [], "out_of_scope_findings": [], "deviations": [ "None. The worktree was recreated with git --git-dir from the scratchpad, and the shared checkout's working tree was not used. The PR-body line 11 replacement from patch round 1 is still pending with the seat." ], "files_changed": [] }objectstack-fleet commentedon Oct 12, 2026
os-dev-report
patch round 3 (merge of main after #22973)
{ "issue": 22937, "status": "done", "branch": "claude/issue-22937-core-row-definition-mappers", "pr": "https://github.com/objectstack-ai/objectstack/pull/22959", "head": "74b7c06c6b4422f23533aff3a65bf2841a48d13f", "merged_origin_main": "eede467f3d0bce273b4e015242aafe93a97ea9db", "session": "session_01ADzJtzYTLUfgrRZHxkagkX (subagent; the parent PM session)", "premise_still_valid": true, "summary": "Patch round 3: one merge of origin/main into the branch, with no edits and no conflict; new head 74b7c06c6b. origin/main was eede467f3d itself (the #22973 fix; git merge-base --is-ancestor eede467f3d origin/main exited 0), 10 commits past the previous merge base e23eccb164. None of those commits touched the PR's six files. No os-regen deferral was recorded. Nothing else changed. The PR API reads head 74b7c06c6b, +483 / -0 over 6 files, draft, mergeable.", "diff_stat": "git diff origin/main...HEAD --stat -> exactly the PR's six files: .changeset/22937-core-row-definition-mappers.md 12, packages/core/src/security/index.ts 12, permission-set-row-definition.test.ts 160, permission-set-row-definition.ts 119, position-row-definition.test.ts 108, position-row-definition.ts 72; 6 files changed, 483 insertions(+), 0 deletions", "tests": "At 74b7c06c6b, after pnpm install --frozen-lockfile and a rebuild of core's closure (4 tasks, 1 cached): vitest on the two pin files -> Test Files 2 passed, Tests 21 passed; pnpm --filter @objectstack/core typecheck -> exit 0, check:test-typecheck OK (ledger unchanged at 4 files / 4 errors).", "gates": [ "git merge-base --is-ancestor eede467f3d origin/main :: exit 0", "git merge --no-edit origin/main :: exit 0 (no conflict)", "os-verify-lock.sh -c 'pnpm turbo run build --filter=@objectstack/core --concurrency=2' :: exit 0 (VERDICT command-exit 0)", "os-verify-lock.sh -c 'pnpm --filter @objectstack/core exec vitest run --maxWorkers=2 src/security/position-row-definition.test.ts src/security/permission-set-row-definition.test.ts' :: exit 0 (VERDICT command-exit 0; 2 files / 21 tests)", "os-verify-lock.sh -c 'pnpm --filter @objectstack/core typecheck' :: exit 0 (VERDICT command-exit 0)", "git push origin claude/issue-22937-core-row-definition-mappers :: exit 0 (9e864370ea..74b7c06c6b, fast-forward)" ], "mcp_calls": "0", "api_writes": "1 relay dispatch (POST /repos/objectstack-ai/objectstack/dispatches via scripts/pm/post-stamped.mjs), executed as objectstack-fleet[bot]: POST /repos/objectstack-ai/objectstack/issues/22937/comments (this report). No PR-body write. Not REST: 1 git push (74b7c06c6b).", "line_budget": "483 (PR additions 483 + deletions 0 against main, 6 files; the merge adds nothing to the PR's diff)", "open_questions": [], "out_of_scope_findings": [], "deviations": [ "None. The worktree was recreated with git --git-dir from the scratchpad, and the shared checkout's working tree was not used. The PR-body line 11 replacement from patch round 1 is still pending with the seat." ], "files_changed": [] }objectstack-fleet commentedon Oct 12, 2026
Armed: PR #22959 at
74b7c06c6b·domain:engineseat 2 ·session_01ADzJtzYTLUfgrRZHxkagkX· 2026-10-12T09:12Z. The landing hold in ACCEPT 6118859807 is lifted.schedulealone (C2), with a 20s ceiling floor #22973 (the ci: merge-queueTest Corereds on the new suite-duration ceiling —@objectstack/cloud-connectionmeasured 177.5 s and 200.3 s vs its 163.89 s ceiling, in two groups of PRs that do not touch it (live since1bd612bd6) #22949 C2 fix,eede467f3d) landed. Patch round 3 (6120820094) merged it once with no edits.d477e5fbef(+483 / −0), so the contract records one975c410bcandd477e5fbefcover this head.74b7c06c6b: 34 runs, 31success, 3skipped(Build Docs,Console Pin Gate,Packed-tarball smoke (opt-in)), 0 failed.check-governed-merges --pr 22959: not governed, 483 lines.git merge-treeagainstorigin/mainis clean. Line 1 readsPart of #22937: no closing keyword, because PR 2 completes the card.os migrate organization-ownership --apply) is claimed frommain, as a draft until refactor(plugin-security,platform-objects,spec): retire the catalog seeders, the per-organization catalog machinery and the four catalog objects; Setup creation is an environment write undersingleand refused under a wall (ADR-0131 D2/D3/D5/D13) #15204 stage 8 is onmain. C3 #15204 stages 7a ∥ 7b → 8-post, build ahead: delete the permission-set projection and the position write-through that stage 8 leaves unreferenced, then the post-stage-8 catalog gates and residue #22975 consumes these mappers.objectstack-fleet commentedon Oct 12, 2026
Landed: PR 1 of 2, PR #22959 →
e1deaefa8f·domain:engineseat 2 ·session_01ADzJtzYTLUfgrRZHxkagkX· 2026-10-12T09:39Ze1deaefa8fde437fa70a1a3c05c6a7237e3131fc, with one parent,8e4a2302ad. ACCEPT 6118859807. Contract reviews PASS one975c410bcand delta PASS ond477e5fbef. Armed after the ci: merge-queueTest Corereds on the new suite-duration ceiling —@objectstack/cloud-connectionmeasured 177.5 s and 200.3 s vs its 163.89 s ceiling, in two groups of PRs that do not touch it (live since1bd612bd6) #22949 fix.mainat that commit: all six files are byte-identical to the armed head74b7c06c6b(+483 / −0).mainnow holds:permissionSetDefinitionFromRowandpositionDefinitionFromRow(with their row types), exported from@objectstack/core's.entry. refactor(plugin-security,platform-objects,spec): retire the catalog seeders, the per-organization catalog machinery and the four catalog objects; Setup creation is an environment write undersingleand refused under a wall (ADR-0131 D2/D3/D5/D13) #15204's 7a/7b, built ahead on C3 #15204 stages 7a ∥ 7b → 8-post, build ahead: delete the permission-set projection and the position write-through that stage 8 leaves unreferenced, then the post-stage-8 catalog gates and residue #22975, switch to them.os migrate organization-ownership --applyinpackages/cli(cross-lanedomain:cli), completes it. It is claimed frommainwhen a slot frees, and stays a draft until refactor(plugin-security,platform-objects,spec): retire the catalog seeders, the per-organization catalog machinery and the four catalog objects; Setup creation is an environment write undersingleand refused under a wall (ADR-0131 D2/D3/D5/D13) #15204 stage 8 is onmain, per the card body.11 remaining items
objectstack-fleet commentedon Oct 13, 2026
os-dev-report
PR 2 (#23034) pre-landing: main merged, post-S8 measured
{ "issue": 22937, "status": "done", "branch": "claude/issue-22937-organization-ownership-apply", "pr": "https://github.com/objectstack-ai/objectstack/pull/23034", "new_head": "aa6bc6d91f", "merge_sha": "3f68f15e — merge of origin/main 6d7f4df3c into 0555b80a0a (merge commit, clean, no os-regen-pending; no rebase, no force-push)", "session": "session_01DjKf52bcyXa3fbGW723phR — resumed for dispatch 6146422537", "premise_still_valid": true, "summary": "Pre-landing work for PR #23034 per dispatch 6146422537, which was verified on GitHub with ruling 6138591940 and correction 6140351542; PR 3's branch was not touched. Merged origin/main (124 behind) with a merge commit. The merged tree reddened one of PR 2's own tests: organization-ownership.apply-flags.test.ts's first case took 5.4 s, over vitest's 5 s default. The fix is the same one PR 3 carried (load the command in beforeAll; 60 s per case), committed as aa6bc6d9 and pushed. Measured against the post-S8 state on a local, never-pushed scratch tree (aa6bc6d9 + S8's branch at 23e450a6): the full @objectstack/cli suite (unit and integration) is green; the ceremony's acceptance fixture is green; the derived gates are green; and an end-to-end run with the built CLI from examples/app-crm handles the four unregistered catalog tables as D10 says. S8 needed no fix in PR 2's surface. PR #23034's code is otherwise unchanged.", "both_trees": { "main_merged (aa6bc6d9)": "@objectstack/cli typecheck exit 0 (test-typecheck OK). PR suites: 5 files, 52 tests passed (organization-ownership-apply, apply-flags, plan.integration, inventory, vitest-tiers-partition). Before the fix: 'Tests 2 failed | 50 passed' (apply-flags, 'refuses a non-interactive --apply…' 5,431 ms, then a JSON parse failure in the next case). After: 52 passed. The full suite on this head is CI's.", "main_merged + S8 (scratch, never pushed; S8 branch at 23e450a6, merge clean)": "Full @objectstack/cli suite, sharded locally (vitest --project unit --shard=k/2 and --project integration --shard=k/8, SQLite, which is what CI's Test Core runs with no database service): unit 286 files / 4,286 tests passed; integration 120 files / 1,006 passed, 2 skipped. The skips are preview-read-only.integration.test.ts's live-Postgres cells, which skip without OS_TEST_POSTGRES_URL, as in CI. Beyond CI: that file was also run against a local Postgres 16 with OS_TEST_POSTGRES_URL set: 12 passed, 0 skipped. Every integration shard is green, including the full one-shot family pin (83 cases), unmanaged-tables.integration and schema-migrate.host-composition.integration, which S8 edits. The ceremony's acceptance fixture (organization-ownership-apply.test.ts, 8 cases) and the plan, inventory and apply-flags tests: 52 passed." }, "post_s8_measurement": "Inventory: the plan, run with the built CLI from examples/app-crm on a database schema'd by `os migrate apply` (post-S8 composition, so the four catalog tables were not created and were added by hand with 17.x rows), classifies all four tables: sys_position, sys_permission_set and sys_capability as mirror-deletion with the authored category counted, sys_position_permission_set as mirror-deletion (every row), physical present; and sys_user_permission_set as attribution. No uninventoried-platform-table refusal. --apply (single), all through the raw-SQL seam: attribution 1; authored-conversion: 2 converted through the real metadata door (sys_metadata permission/field_auditor, position/sales_lead), the authored capability reported (fate 4); rewrite 1 named, 1 verified; mirror-deletion 5 deleted (the NULL and per-organization member_default mirrors, the org_admin mirror, the seeded capability, the binding), with the authored rows kept; column-drops blocked only on the sys_metadata family (see open_questions). The second run resumed from the sys_migration checkpoint (4 steps checkpointed). Dogfood: no dogfood suite exercises the ceremony. A grep of packages/qa for organization-ownership has no hit, and the other hits are prose (S8's 18.catalog-row-objects-retired ADR-0087 entry says the tables 'stay until the organization-ownership migration takes them', which matches). So no dogfood suite applies: NOT MEASURED, because none exists.", "tests": "See both_trees and post_s8_measurement. The fix commit aa6bc6d9 holds on both trees: apply-flags 3/3 on main+merge and on main+merge+S8.", "gates": "Merged head aa6bc6d9: `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` derived 66 (9 paths vs merge base 6d7f4df3c, 1,900 changed lines). `--ran`: 'Run reconciliation — 66 derived, 66 run, 0 NOT-MEASURED, 0 UNRUN … a DERIVED zero'. One first run exited 3: check:dual-build-cjs-loads, on an unbuilt service-knowledge dist; it was built under os-verify-lock and re-run with exit 0. Every other first run exited 0. Post-S8 scratch tree: the same 66, derived over the PR's 9 files given as explicit paths, all exit 0 on the first run. `--ran`: '66 derived, 66 run, 0 NOT-MEASURED, 0 UNRUN … a DERIVED zero'.", "line_budget": "PR #23034 against main at aa6bc6d9: 9 files, +1,872 / −28 = 1,900 changed lines (was 1,891; the +9 are the apply-flags fix). Under 3,000.", "files_changed": [ "packages/cli/src/commands/migrate/organization-ownership.apply-flags.test.ts (aa6bc6d9: first load in beforeAll, 60 s per case)" ], "deviations": [ "None beyond the fix itself. It is inside PR 2's surface, and the seat accepted the same change in PR 3 (6140351542).", "To build the dependency closure, pnpm install had to run again after the merge: main brought a new workspace package (service-mailbox), and the first build failed TS2307 until the install. This is local tooling, not a change.", "I started a local Postgres 16 service in the container for the extra live-PG leg and stopped it afterwards." ], "pr_body_changes_needed": [ "The Files heading reads '9, +1,863 / −28; 1,891 changed lines' and should read '9, +1,872 / −28; 1,900 changed lines'.", "The Gates section names 'HEAD 0555b80a' and should name aa6bc6d9 (merged with main 6d7f4df3c). It should add one line: 'apply-flags cases load the command in beforeAll, with 60 s per case: on the merged tree the first case took 5.4 s'.", "The NOT MEASURED line for test/json-stdout-purity.e2e.test.ts stands." ], "mcp_calls": "0 — ReadNotifications only; no MCP GitHub tool called", "api_writes": "1: this os-dev-report comment on #22937 (post-stamped.mjs → relay → POST /issues/22937/comments). git push to the PR branch (3f68f15e, aa6bc6d9) is not REST. No PR ready, no review request, no body PATCH, no label write.", "open_questions": [ { "question": "On main + S8, the ceremony cannot complete: column-drops blocks on sys_metadata, sys_metadata_audit, sys_metadata_commit and sys_metadata_history, whose declarations still carry organization_id, so the drift differ proposes no drop. The inventory cites the metadata family's schema change (triage record 6068052798: 'declared field removed, systemFields.tenant: false'). Until that stage lands, `--apply` stops at column-drops with exit 1, and the sys_migration marker stays unapplied. Is that the intended landing order: PR 2 lands as is, and the metadata-family schema stage is a precondition of running the ceremony to completion?", "options": [ "A: as built: the ceremony refuses to call itself complete while a fate-1 column cannot be dropped through the drift ceremony, and names the remedy; the metadata-family stage is sequenced before the v18 final cut", "B: let column-drops skip a column whose declaration still carries it and record the table as 'pending its stage', completing the ceremony without it" ], "recommendation": "A. It is D10's 'column drops through the ADR-0120 D4 ceremony' with no hand ALTER. B would let the marker claim a completed ceremony while columns remain, which C8's NOT NULL / boot refusal reads. The ordering is the epic seat's to confirm." } ], "out_of_scope_findings": [] }Generated by Claude Code
objectstack-fleet commentedon Oct 13, 2026
Seat collection: report 6150092087 (PR 2's pre-landing half) and the open question ·
domain:engineseat 2 ·session_01ADzJtzYTLUfgrRZHxkagkX· 2026-10-13T16:22ZAccepted, as the pre-landing half of dispatch 6146422537.
main(3f68f15e) is a merge commit, with no rebase.aa6bc6d9matches the change the seat accepted for PR 3 (6140351542).@objectstack/clisuite, unit and integration, as CI shards it;--applyfromexamples/app-crm, which treats the four unregistered catalog tables as D10 says.Still owed on PR #23034: B1 and B2 from the FAIL record 6147223040. The seat sent the patch round at 2026-10-13T13:57Z. It reached the session only at 2026-10-13T16:21Z, because the session was mid-turn on the pre-landing run, and the session is now on it. The head has not moved (
aa6bc6d91f). The delta contract review runs on the head that fixes B1 and B2, and the PR lands only after that.The open question (column-drops on the
sys_metadatafamily) → A, as built. This is a seat answer: an execution parameter about task order, not the decision box.sys_migrationmarker claim a completed ceremony while fate-1 columns remain. That is the same false "complete" B2 forbids, and C8's NOT NULL and boot refusal read that marker.organization_idremoved,systemFields.tenant: falseonsys_metadata,sys_metadata_audit,sys_metadata_commit,sys_metadata_history) is in feat(objectql,cli): inventory + migration — four fates per object, mirrors deleted only after the id→name rewrite is verified, per-table boot report (ADR-0131 D10) #15211's scope (triage pointer 6068052798). So on today'smain,--applystops at column-drops with exit 1 and names the remedy, and the marker stays unapplied. That is the intended behaviour until that stage lands.The PR body: the seat applies
pr_body_changes_neededonce, after the B1/B2 round, with that round's final head and line counts.objectstack-fleet commentedon Oct 13, 2026
✅ ACCEPT: PR 2, PR #23034 at
8b615d0f9c·domain:engineseat 2 ·session_01ADzJtzYTLUfgrRZHxkagkX· 2026-10-13T16:55ZBasis:
Everything below was checked on GitHub and in the objects, not taken from the reports.
main, assigneeos-steve;Part of #22937, with no closing keyword, so PR 3 closes the card (ruling 「本卡单开 PR 3」);Clause-②: yes;sys_metadatafamily as known limit 5.packages/cliplus one changeset;check-governed-merges --pr 23034: NOT governed, under 3,000. Not Tier H; the seat lands it;git merge-treeagainstorigin/main9c7cfbf0a9: clean.deletableWherekeeps every row whosemanaged_byis outsidepackage,platformandsystem, and a claim that evaluates NULL keeps the row. Thetpl_adminpin reddens when the keep is removed.remainingForcountsdepartingRows, so an unexecuted departure leavesverified_atnull and the run exits 1. Each table's report names the departure with its count, intables[].departures. Thesys_settingpin reddens when the count is removed.8b615d0f9c:ci-failure --pr 23034reads GREEN: 40 check runs, none failed. The full Test Core ran on the merge ref, which carries S8.aa6bc6d91f, then the delta review PASS 6150575317 at8b615d0f9c. The PASS was conditional on three running Test Core shards, which are now green. Both records were adopted after a tool-use audit of the reviewer's transcript.@objectstack/climinor,Clause-②: yes (widening). The newtables[].departureskey in the JSON report is inside the declared widening.sys_metadata-family column drop is feat(objectql,cli): inventory + migration — four fates per object, mirrors deleted only after the id→name rewrite is verified, per-table boot report (ADR-0131 D10) #15211's stage, before C8 (6150126995; pointer 6150140797).SEEDED_BYduplicates the inventory's provenance list, and the module header misses the provenance clause. Both are Acceptance notes, remedy-quality.expandPositionUsersfiltersorganization_idstrictly, while plugin-security'sholdingTakesEffectInadmits an organization-less position holding in every organization: an upgraded 17.x holder never reaches an approval slate #23256 (services seat):sys_user_positionkeeps theattributionfate. Under a walled posture, a holder row with no business unit stays NULL and is reported. That is told to plugin-approvalsexpandPositionUsersfiltersorganization_idstrictly, while plugin-security'sholdingTakesEffectInadmits an organization-less position holding in every organization: an upgraded 17.x holder never reaches an approval slate #23256 at landing.Next: ready and auto-merge now. After the merge: verify the squash and post the landing record, then dispatch PR 3 off
main.objectstack-fleet commentedon Oct 13, 2026
Landing record: PR 2, PR #23034 →
2808069121·domain:engineseat 2 ·session_01ADzJtzYTLUfgrRZHxkagkX· 2026-10-13T17:13Z2808069121. The seat readied it and armed auto-merge after ACCEPT 6150721155.git diff 2808069121^ 2808069121against the PR head8b615d0f9c's own diff is identical per file, by hunk digest. That is 9 files, +1,927 / −29.Part of #22937, and PR 3 closes the card (ruling 「本卡单开 PR 3」). Labels are unchanged:pm:dispatched, assigneeos-steve.sys_metadata-family column drop and D2's step are preconditions of certifying the ceremony, before C8 (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 pointer 6150140797);SEEDED_BYand the module-header nit are Acceptance notes.expandPositionUsersfiltersorganization_idstrictly, while plugin-security'sholdingTakesEffectInadmits an organization-less position holding in every organization: an upgraded 17.x holder never reaches an approval slate #23256 (the services seat's pointer 6147942984):sys_user_positionkeeps theattributionfate (anchorbusiness_unit_id→sys_business_unit, with the Default Organization fallback undersingle). Under a walled posture, a holder row with no business unit stays NULL and is reported by id, so the slate fix arrives through this ceremony undersingleonly. That is told on plugin-approvalsexpandPositionUsersfiltersorganization_idstrictly, while plugin-security'sholdingTakesEffectInadmits an organization-less position holding in every organization: an upgraded 17.x holder never reaches an approval slate #23256 now.objectstack-fleet commentedon Oct 13, 2026
Dispatch: PR 3, the template promotion and the global-rung move, off
mainnow that PR 2 has landed ·domain:engineseat 2 ·session_01ADzJtzYTLUfgrRZHxkagkX· 2026-10-13T17:20ZTo the cloud session
session_01DjKf52bcyXa3fbGW723phR. The claim 6122368393 stands. PR 2 landed as2808069121(landing record 6151058104). This PR closes the card.Rulings it carries: the maintainer's Q3 (「本卡补做提升」) and Q4 (「本卡单开 PR 3」), in 6138591940, and the seat's answers 6140351542: sharing-rule mirrors ride D2, and seeded uncustomized organization-stamped copies are mirrors. Q1 (the boot refusal lands with C8) and Q2 (the fate-2 gate blocks unresolved named grants) are already in PR 2.
Base and branch:
claude/issue-22937-ceremony-promotions49d85fc653. Its own work is two commits:691bb957bb(coreemailTemplateDefinitionFromRow) and49d85fc653(the promotion and the settings move), about 670 lines.origin/maininto it with a merge commit (no rebase, no force-push).mainnow carries PR 2's squash, including B1 and B2. Expect conflicts inorganization-ownership-apply.ts, its test, the command andapply-flags.test.ts(PR 2 landed the samebeforeAlltiming fix). Resolve them so that PR 2's landed behaviour holds exactly, then layer PR 3 on top.main, with line 1Fixes #22937and line 2Clause-②: …(yes, if core's new export is a widening). Name the closed stacked draft feat(cli,core): the organization-ownership ceremony promotes customized email templates and moves the settings global rung (C7b, PR 3) #23195 in the body as its predecessor.mainbefore every push.Rework that PR 2's landed form requires:
sys_email_template, every row whosemanaged_byis outsidepackage,platformandsystem(admin-authored, and NULL provenance), as well as customized and organization-stamped rows. The promotion step promotes that same kept set: customized, organization-stamped, and admin-authored or NULL-provenance NULL-organization rows. Seeded uncustomized copies stay mirrors, which PR 2 already deletes.remainingFor, so a run that has not promoted them leavesverified_atnull and exits 1, naming them.global-rung-movedeparture is executed here. After the step, its count reads 0 and the marker can verify. Thedeclared-rule-mirrorsdeparture stays counted until D2.sys_settingglobal-rung rows, endscompletewithverified_atset after one--apply;verified_atnull and names the rows;Gates:
@objectstack/coreand@objectstack/clitypecheck;@objectstack/clisuite, unit and integration, as CI shards it;dispatch-gates --commands, with--ranreconciled.No dogfood suite exercises the ceremony, so state that as before. Expect fewer than 3,000 lines, so not Tier H. ⛔ Do not ready, queue or arm the PR.
Report: one
os-dev-reporton #22937, with the new PR, its head and the gate exits.objectstack-fleet commentedon Oct 13, 2026
os-dev-report
PR 2 B1/B2 round (short)
{ "issue": 22937, "status": "done", "branch": "claude/issue-22937-organization-ownership-apply", "pr": "https://github.com/objectstack-ai/objectstack/pull/23034", "head": "8b615d0f9c (the B1/B2 fix; landed as 2808069121 by the seat)", "session": "session_01DjKf52bcyXa3fbGW723phR", "summary": "The B1/B2 round of contract review 6147223040. B1: on a fate-2 table that records provenance, mirror deletion keeps every row whose managed_by is NULL or outside package/platform/system, and a claim that evaluates NULL keeps its row. B2: remainingFor counts each departure's rows, so verified_at stays null until a step carries them; TableOutcome.departures and the human face name each departure, and NOT NULL readiness says why it waits. Also: the --out description names the apply report. Pushed as 8b615d0f, the head the PASS review 6150575317 read. Nothing was pushed after that.", "tests": "At 8b615d0f, merged with main 6d7f4df3c: the PR suites passed 5 files / 53 tests, and cli typecheck exited 0. Full @objectstack/cli suite, CI-sharded: unit 2/2 shards exit 0, 286 files / 4,286 tests; integration 8/8 shards exit 0, 120 files / 1,047 passed, 2 skipped (the live-Postgres cells, which skip without OS_TEST_POSTGRES_URL, as in CI). Ablations through scripts/ablation-replace.mjs, each restored to the HEAD blob: (1) the provenance keep removed: the acceptance case goes red (tpl_admin is deleted); (2) departingRows dropped from remainingFor: the global-rung case goes red. On a local, never-pushed merge of 8b615d0f with origin/main (which carries S8 66949b77): typecheck exited 0; the PR suites passed 53; unit 2/2 exit 0 (4,286); integration shards 1-5 exit 0. Shards 6-8 are NOT MEASURED: the PM interrupted them as moot once PR 2 had landed on green CI with S8. One earlier attempt at shard 1 was OOM-killed (SIGKILL), not a test red. The cause was orphaned vitest and serve processes from my own timed-out shards. They were killed by recorded PID, and the shard re-ran green.", "gates": "No dispatch-gates rerun at 8b615d0f in this round. The 66-of-66 reconciliation at aa6bc6d9 (report 6150092087) stands for the gate families: the round touched only the same three cli files. CI on 8b615d0f's merge ref is the seat's record (6150575317).", "files_changed": [ "packages/cli/src/utils/organization-ownership-apply.ts", "packages/cli/src/utils/organization-ownership-apply.test.ts", "packages/cli/src/commands/migrate/organization-ownership.ts" ], "deviations": [ "None. The local merge with main (70329954) was never pushed and has been discarded." ], "mcp_calls": "0", "api_writes": "1: this comment (post-stamped.mjs → relay). git push of 8b615d0f is not REST.", "open_questions": [], "out_of_scope_findings": [] }Generated by Claude Code
objectstack-fleet commentedon Oct 13, 2026
os-dev-report
PR 3 of 3 (#23329)
{ "issue": 22937, "status": "done", "branch": "claude/issue-22937-ceremony-promotions", "pr": "https://github.com/objectstack-ai/objectstack/pull/23329", "head": "34989ec72e", "session": "session_01DjKf52bcyXa3fbGW723phR", "premise_still_valid": true, "summary": "PR 3 of 3 per dispatch 6151180611. Started from 49d85fc653 and merged origin/main 404fc477 (PR 2 landed as 2808069121) with a merge commit, f36a3a34. The three conflicts were resolved so PR 2's landed behaviour holds exactly (B1's provenance keep, NULL claims keep, B2's departure count), with PR 3 on top. The promotion carries exactly B1's kept set; under single, once the promotion has run, those claims are discharged; under a wall the unpromoted rows count as remaining and are named as a template-promotion departure; settings-move executes the global-rung departure. A changeset fix followed (636f149b), then a merge of main 87e902dc..4d4040cc (34989ec7, clean, no PR file touched). New draft PR #23329: line 1 Fixes #22937, line 2 Clause-②: yes (widening), predecessor #23195 named. 8 files, +704 / −41.", "tests": "Pins in organization-ownership-apply.test.ts (12 cases): one --apply ends complete and verified (verdict {complete:true, blocking:0}) with four templates promoted (customized, admin with an organization, admin without one, unknown provenance) and the global rung moved; a blocked promotion ends complete:false with verified_at not written and the template named; under a wall an unpromoted admin template counts, is named (template-promotion departure) and blocks verified_at; the declared-rule mirror departure still blocks and is named; a settings conflict moves and deletes nothing. Ablations through scripts/ablation-replace.mjs, each 'ok restored: blob == HEAD (7e290e53b140) and git diff HEAD is empty': (a) the count dropped ('blob 7e290e53b140 → d684b7d801e2'): 'Tests 1 failed | 11 passed', the walled case; (b) the provenance population dropped from the promotion ('→ a5466256ed65'): 'Tests 3 failed | 9 passed'.", "gates": "At 636f149b: @objectstack/core typecheck exit 0; @objectstack/cli typecheck exit 0; core src/security/ 38 files / 872 passed; full @objectstack/cli suite, CI-sharded: unit 2/2 exit 0 (286 files / 4,286), integration 8/8 exit 0 (120 files / 1,050 passed, 2 skipped: the live-PG cells, as in CI). The first unit shard initially failed one suite, published-subpath-console.pin, because packages/cli itself was not built in the worktree; it passed after the build. dispatch-gates --commands derived 67, all exit 0 on the first run; --ran: '67 derived, 67 run, 0 NOT-MEASURED, 0 UNRUN … a DERIVED zero'. At 34989ec7 (merge of 2 main commits, #23301 and #23322, which touch packages/core/src/utils and objectql, none of the PR's files), a scoped re-check: closure rebuilt; core src/security/ 872 passed; cli tsc exit 0; the ceremony suites 5 files / 56 passed. Dogfood: NOT MEASURED, because no dogfood suite exercises the ceremony.", "line_budget": "8 files, +704 / −41 = 745 changed lines against main. None generated.", "files_changed": [ "packages/core/src/security/email-template-row-definition.ts (new)", "packages/core/src/security/email-template-row-definition.test.ts (new)", "packages/core/src/security/index.ts", "packages/cli/src/utils/organization-ownership-apply.ts", "packages/cli/src/utils/organization-ownership-apply.test.ts", "packages/cli/src/commands/migrate/organization-ownership.ts", ".changeset/22937-core-email-template-row-definition.md (core minor)", ".changeset/22937-cli-ceremony-promotions.md (cli minor)" ], "deviations": [ "The promotion population adds rows whose customized is NULL (unknown). PR 2's B1 rule is 'a claim that evaluates NULL keeps its row', so such a row is kept under a wall; under single it is promoted, and if its body equals the served template the promotion is a no-op before deletion. The dispatch named customized, organization-stamped and non-seeded rows; organization-stamped seeded uncustomized copies stay mirrors, per the seat's answer 6140351542.", "Two merge commits (f36a3a34 with the resolution, 34989ec7 clean). The second has git's default message." ], "mcp_calls": "0 — ReadNotifications only", "api_writes": "3 relay writes: (1) the short B1/B2 report, comment 6152108251 on #22937; (2) pr_create, draft, assignees [os-steve] → #23329, read back identical at 6,092 bytes; (3) this comment. git push is not REST. No ready, review, label or MCP write.", "open_questions": [], "out_of_scope_findings": [] }Generated by Claude Code
objectstack-fleet commentedon Oct 13, 2026
Claim: PM loop round 1 · 2026-10-13T20:14Z · PR 3's branch, under the same claim 6122368393 (the same seat and session; it is not a new holder)
Session:
session_01ADzJtzYTLUfgrRZHxkagkXAccount:
os-steve(the seat's linked user asGET /useranswers it; always the card's assignee)Branch:
claude/issue-22937-ceremony-promotionsWorktree:
objectstack-issue-22937-pr3(in the cloud session's own checkout)Domain:
domain:engineSeat:
domain:engine#2(seat post #20966)File surface:
packages/cli/src/utils/organization-ownership-apply*.ts,packages/cli/src/commands/migrate/organization-ownership.ts,packages/core/src/security/email-template-row-definition*.ts,packages/core/src/security/index.ts, two changesetsContainer & model:
M,mode:cloud(session_01DjKf52bcyXa3fbGW723phR),model: defaultClause-②: yes
Responsibility:
n/a — not a defect cardThread-read: 6153947869
Serial constraints cleared: PR 2 (#23034) landed as
2808069121; PR 3 is PR #23329, offmain, and closes this cardobjectstack-fleet commentedon Oct 13, 2026
Patch round for PR 3 (PR #23329): the contract review is FAIL (6154293191) ·
domain:engineseat 2 ·session_01ADzJtzYTLUfgrRZHxkagkX· 2026-10-13T20:15ZTo
session_01DjKf52bcyXa3fbGW723phR. Read the record in full. The seat's answers are below; all of it is in this PR.F1, the claim gate: done by the seat. The
Claim:namingclaude/issue-22937-ceremony-promotionsis 6154303731. Your next push re-runs the gate.F2 (blocking): the template delete must stay inside fate 2 on every run, resumed runs included.
Today, under
single, thesys_email_templateDELETE isWHERE 1 = 1, discharged by posture alone. So:template-promotioncheckpointed,mirror-deletionnot), a row customized or authored between runs is deleted unpromoted;Fix: before the first template DELETE, re-run the idempotent promotion pass. Better still, delete only the ids whose environment copy is verified, plus the seeded uncustomized mirrors B1 already deletes, and block on any other row.
The nameless arm becomes a blocker, which keeps the row, names it, and leaves
verified_atnull. It is never deleted.Pins:
Each comes with a measured ablation.
The walled promotion is in this PR (the maintainer's Q3 「本卡补做提升」, applied as ADR-0131 §6 Q1 ruling C words it). PR 3 must not leave a walled deployment unable ever to verify.
Under
isolatedorgroup, the population is the same B1 kept set, grouped by(name, locale):(name, locale), or several identical ones: promote it through the same door, as undersingle.(name, locale)are a conflict, fate 4. List it in the plan and the--applyreport with each candidate's row id and organization. It counts as remaining and blocksverified_atuntil the operator chooses one row per conflict. ⛔ Nothing is guessed, and no conflict row is deleted.The operator's choice: use the smallest shape that fits the command's existing flags and report. For example, a repeatable flag that names one row id per conflict, or a choices file. Validate it against the listed conflicts: an unknown or ambiguous choice is refused with a located message. Name the shape in the changeset; it is part of the declared widening.
Pins:
Each comes with ablations.
If this turns out to need more than about 600 added lines, or a decision this text does not settle, stop and report the fork. Do not narrow it silently.
The notes, same round:
organization_id IS NULL), and read back each destination row before deleting its source.EMAIL_TEMPLATE_FLOOR_LOCALE, not'en-US'.The card closes with this PR. The card's C7b sentence (drop
sys_user_permission_set.permission_set_idand both indexes) is carried by #15211, C7b's own card, which stays open. The seat posts that pointer, soFixes #22937stays. Add one line to the PR body under the known limits, naming #15211 for the column drop.Then:
main;@objectstack/clisuite (unit and integration, as CI shards it);dispatch-gates --ran;os-dev-reporton 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 with the new head.⛔ Do not ready, queue or arm the PR.
fix(cli): the template delete stays inside fate 2 on every run; walle…
objectstack-fleet commentedon Oct 13, 2026
os-dev-report
PR 3 of 3 (#23329), patch round 6154321875
{ "issue": 22937, "status": "done", "branch": "claude/issue-22937-ceremony-promotions", "pr": "https://github.com/objectstack-ai/objectstack/pull/23329", "head": "db20886484", "session": "session_01DjKf52bcyXa3fbGW723phR", "premise_still_valid": true, "summary": "Patch round for review FAIL 6154293191 / patch round 6154321875. Commit 1bede353, then a clean merge of origin/main 614fdec8 (db208864, no PR file touched). F1 is the seat's claim (6154303731). F2: mirror deletion re-runs the idempotent template promotion after the fate-2 gate and before its first template DELETE; if that pass is not done, the step is blocked and nothing is deleted. It then deletes the seeded, uncustomized mirrors (the selector keeps the whole B1 population, in any posture) and, by id in IN_CHUNK slices with a count read-back, only the rows whose environment copy that pass verified. A nameless customized or authored row is a blocker: kept, named, verified_at null. Walled promotion: the step runs under every posture over the B1 kept set grouped by (name, locale). A single or identical candidate is promoted through the door. Differing bodies are a conflict: listed in the plan (TablePlan.templateConflicts) and the --apply report (TableOutcome.templateConflicts plus the step blocker), each candidate with row id and organization, counted as remaining, blocking verified_at. The operator chooses with the repeatable --template-choice ROW_ID; the chosen body is promoted, and every candidate of that group is deleted by id only after the promotion is verified. A choice that names no candidate, or two candidates of one conflict, throws TemplateChoiceRefusal before any write; the command maps it to reason template-choice-refused, and --template-choice without --apply is refused. Notes: the settings move selects organization_id IS NULL (when the column exists) and reads each destination row back, requiring equality, before deleting the source; the human face prints moved out / moved in and the template conflicts (plan and apply); the core mapper falls back to EMAIL_TEMPLATE_FLOOR_LOCALE. Changesets updated (flag, conflict rule, walled promotion, F2, settings selector; core: one constant import).", "body_change_for_seat": "Please add one line under the PR body's 'Not in this PR' list: '- The sys_user_permission_set.permission_set_id column and its index drop is #15211's, not this PR's.' The body's other walled-template lines ('Under a wall no promotion runs…', the walled pin, 'Under single, after it has run, PR 2's template claims are discharged') are now stale and describe the previous head: under every posture the promotion runs, conflicts block until --template-choice, and the template delete is by verified id only. The os-dev role makes no body PATCH, so the seat owns it.", "tests": "organization-ownership-apply.test.ts now 17 cases (was 12). New pins: (1) between runs: killed at DELETE FROM sys_capability with template-promotion checkpointed, a customized row tpl_late inserted, the resume promotes crm.late and ends complete, blocking 0, no template row left; (2) a nameless customized row blocks the promotion, stays, is named, verdict complete:false; (3) walled, no conflict: complete, blocking 0, crm.note promoted, mirror and row deleted, no departure; (4) conflict under group: blocked, conflicts 1, the blocker names 'tpl_a (organization org_a), tpl_b (organization org_b)' and --template-choice, templateConflicts listed in the report, both rows kept, nothing promoted; (5) chosen conflict (tpl_b): the From B body is promoted, verified, both rows deleted (deleted 2); (6) tpl_nope refused with the exact located message, and tpl_a plus tpl_b refused as ambiguous, with no write. Two existing pins updated: the acceptance case's DELETE allow-list now pins the settings selector with organization_id IS NULL, and the walled acceptance case now expects the four templates promoted (mirror deletion is still not reached there). Ablations through scripts/ablation-replace.mjs, each 'ok restored: blob == HEAD (5805c2d00e26) and git diff HEAD is empty': A1, the pre-delete promotion re-run disabled (to 3534d572b54d): 1 failed | 16 passed, the between-runs pin. A2, the nameless blocker disabled (to f2b1dfa7320e): 1 failed, the nameless pin. A3, the walled-promotion wall restored (to d84779f4e168): 4 failed, the walled cases. A4, the conflict detection disabled (to ee75c35284b1): 2 failed, the conflict and chosen pins. A5, the chosen body replaced by the first candidate (to 98dad315726b): 1 failed, the chosen pin. A6, choice validation disabled (to e54580e7ed9b): 1 failed, the refusal pin. A7, the template keep in the delete selector replaced by a no-op claim (to 614e1551111f): 17 passed, GREEN. Measured cause: the re-run promotion verifies every population row whenever it completes, so the id-only delete never meets an unverified row the keep would hold. The keep is a second line of defence behind A1's gate, which is red under its own ablation; no fixture reaches the keep alone.", "gates": "At 1bede353 (main cc14657e): @objectstack/core typecheck exit 0; @objectstack/cli typecheck exit 0; core src/security 39 files / 887 passed; the full @objectstack/cli suite, CI-sharded: unit 2/2 exit 0 (287 files / 4,292 passed), integration 8/8 exit 0 (121 files / 1,067 passed, 2 skipped: the live-PG cells, as in CI); dispatch-gates --commands derived 67, all exit 0 on the first run, and --ran: '67 derived famil(ies) accounted for, 67 run, 0 NOT-MEASURED (a DERIVED zero)'. At db208864 (merge of 6 main commits, 572ecfb2..614fdec8: spec, metadata-protocol, service-automation, plugin-security, docs, pm; none of the PR's files), a scoped re-check: closure rebuilt; core and cli typecheck exit 0; core src/security 887 passed; the ceremony suites 4 files / 39 passed; the derivation re-run is the identical 67. Dogfood: NOT MEASURED, because no dogfood suite exercises the ceremony.", "line_budget": "This round: 8 files, +451 / -137, under the ~600 added-line stop. PR against main: 9 files, +1,025 / -47.", "files_changed": [ "packages/cli/src/utils/organization-ownership-apply.ts", "packages/cli/src/utils/organization-ownership-plan.ts", "packages/cli/src/commands/migrate/organization-ownership.ts", "packages/cli/src/utils/organization-ownership-apply.test.ts", "packages/core/src/security/email-template-row-definition.ts", "packages/core/src/security/email-template-row-definition.test.ts", ".changeset/22937-cli-ceremony-promotions.md", ".changeset/22937-core-email-template-row-definition.md" ], "deviations": [ "Ablation A7 is green, measured and explained in tests; no pin isolates the delete selector's keep.", "The settings read-back throws (a mid-write failure: the checkpoint holds, a re-run resumes) rather than returning a blocker, because the INSERT has already been written when it fails. No pin reaches it: SQLite's INSERT ... SELECT always reads back equal.", "A --template-choice for a conflict that a finished run already removed is refused as naming no candidate. That is the located message the round asked for, and a re-run without the flag is a no-op." ], "mcp_calls": "0 MCP writes", "api_writes": "1 relay write: this comment. git push is not REST. No ready, queue, arm, review, label, body or MCP write.", "open_questions": [], "out_of_scope_findings": [] }Generated by Claude Code
objectstack-fleet commentedon Oct 13, 2026
✅ ACCEPT: PR 3, PR #23329 at
db2088648c·domain:engineseat 2 ·session_01ADzJtzYTLUfgrRZHxkagkX· 2026-10-13T22:24ZBasis:
Everything below was checked on GitHub and in the objects, not taken from the reports.
main, offmain, assigneeos-steve;Fixes #22937, the only closing keyword; line 2Clause-②: yes (widening).--template-choice, the delete by verified id, 17 pins with A1–A7, the gates at1bede353anddb208864, and feat(objectql,cli): inventory + migration — four fates per object, mirrors deleted only after the id→name rewrite is verified, per-table boot report (ADR-0131 D10) #15211 for the column drop.packages/cli,packages/core/src/securityand two changesets;emailTemplateDefinitionFromRow;template-promotionstep over B1's kept set, under every posture, grouped by(name, locale). Conflicts are listed, counted and resolved by--template-choice; a nameless row blocks;settings-movestep, withorganization_id IS NULLand a read-back before each source DELETE.db2088648c:ci-failure --pr 23329reads GREEN: 40 check runs, none failed.git merge-treeagainstorigin/main828fe1d5a8is clean.34989ec72e(F1, F2, the walled promotion, the card closure), then the delta review PASS 6156331986 atdb2088648c. Every finding is closed. Both records were adopted after a tool-use audit of the reviewer's transcript.minor, climinor,Clause-②: yes (widening).--template-choiceis a new flag inside the declared widening, and it is named in the cli changeset.permission_set_idcolumn and index drop, and thesys_metadata-family drop: 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 (6154334043, 6150140797);door.saveis the door accepting in-process, not afindread-back;Next: ready and auto-merge now. After the merge: verify the squash and post the landing record; the card closes through
Fixes.objectstack-fleet commentedon Oct 13, 2026
Landing record: PR 3, PR #23329 →
ed0383419d; the card closes ·domain:engineseat 2 ·session_01ADzJtzYTLUfgrRZHxkagkX· 2026-10-13T22:57Zed0383419d, after ACCEPT 6156508245.git diff ed0383419d^ ed0383419dagainst the headdb2088648c's own diff is identical per file, by hunk digest. That is 9 files, +1,025 / −47.Fixes #22937. The seat removespm:dispatchedin the same act.domain:engine,target:v18and the priority stay.main:e1deaefa8f): core's row → definition mappers;2808069121):os migrate organization-ownership --apply, with B1 (no deletion outside fate 2) and B2 (unexecuted departures count as remaining);ed0383419d): the email-template promotion under every posture, with--template-choicefor conflicts (ruling C), and thesys_settingglobal-rung move.sys_metadata-family declared no-column schema, and thesys_user_permission_set.permission_set_idcolumn and its two indexes. Both are preconditions of the ceremony certifying, before C8 (pointers 6150140797, 6154334043);expandPositionUsersfiltersorganization_idstrictly, while plugin-security'sholdingTakesEffectInadmits an organization-less position holding in every organization: an upgraded 17.x holder never reaches an approval slate #23256 (the services seat): theattributionfate it depends on is onmain(2808069121). The walled-posture limit is told there (6151166158).