Skip to content

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

Open

Description

@objectstack-fleet

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

Scope (read #15211's body in full first; it governs)

  1. 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.
  2. --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:
  3. 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

Refs

#15211 · ADR-0131 D10, D4 · seat answers 6110777865 and 6116546399 · seat note 6110790598 · release-cut record 6102862135 · ruling 6117174845.

Activity

  1. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1 · 2026-10-12T04:05Z · PR 1 of 2 (the core mappers)
    Session: session_01ADzJtzYTLUfgrRZHxkagkX
    Account: os-steve (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-22937-core-row-definition-mappers
    Worktree: objectstack-issue-22937
    Domain: domain:engine
    Seat: domain:engine#2 (seat post #20966); the lane's only seated PM
    Priority: 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/main 1bd612bd68; stop on a breach and explain it in the report). ⛔ Classes, positions and functions only, in every artefact.

  2. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    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"
      ]
    }
  3. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    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"
      ]
    }
  4. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    ✅ ACCEPT: PR #22959 at d477e5fbef (PR 1 of 2). Arming held on #22949

    domain:engine seat 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.

    • Form:
      • draft to main, assignee os-steve;
      • line 1 Part of #22937, with no closing keyword, as PR 1 of 2 should have (PR 2 completes the card);
      • line 2 Clause-②: yes, matching the claim and, as yes (widening), the changeset.
    • Scope:
      • 6 files, +483 / −0, none generated, none governed (check-governed-merges --pr 22959: not governed);
      • nothing under packages/plugins/plugin-security/**, content/docs/releases/ or CHANGELOG.md.
    • What it adds: permissionSetDefinitionFromRow and positionDefinitionFromRow, plus their two row types, beside convertPositionBindingRows, exported from core's . entry. They are re-exported through @objectstack/runtime and @objectstack/plugin-hono-server with no collision. Both are pure, and nothing calls them yet. Read side by side, they give the same output as the plugin originals permissionSetBodyFromRow and positionBodyFromRow. 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.
    • Changeset: @objectstack/core minor, 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.
    • Evidence:
      • 21 pins (12 and 9), including a spec-rename tripwire;
      • two ablation legs went red as expected and were restored;
      • core: 2402 tests pass;
      • 63 derived gate commands, all exit 0.
    • Contract review: PASS on e975c410bc and a delta PASS on d477e5fbef. Both records are on the PR (CONTRACT_REVIEW_TIER, isolated reviewers, read-only).
    • Out-of-scope findings: these become Acceptance notes and are not filed, because none is in a filing class:
    • Deviations accepted:
      • the equivalence harness is not committed: core cannot import plugin-security, and the permanent proof is 7a/7b deleting the copies;
      • the first gate derivation ran read-only in the shared checkout;
      • the dev declined a PR-body write under its role file, which wins on conflict, and the seat wrote the line.

    Landing: held. CI on d477e5fbef is green except the Test Core aggregator's suite-duration ceiling step: @objectstack/cloud-connection 174.50s against 163.89s, which is #22949. Every shard is green, the drift step included. The PR is not armed red. main has moved since the merge base, so the dev merges origin/main once, which is a real merge, not an empty commit. The seat arms on the first head whose required contexts are all success, after confirming that the net diff is unchanged.

  5. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    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": []
    }
  6. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    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": []
    }
  7. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    Armed: PR #22959 at 74b7c06c6b · domain:engine seat 2 · session_01ADzJtzYTLUfgrRZHxkagkX · 2026-10-12T09:12Z. The landing hold in ACCEPT 6118859807 is lifted.

  8. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed: PR 1 of 2, PR #22959 → e1deaefa8f · domain:engine seat 2 · session_01ADzJtzYTLUfgrRZHxkagkX · 2026-10-12T09:39Z

  9. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1 · 2026-10-12T10:24Z · PR 2 of 2 (os migrate organization-ownership --apply); built now, a draft until #15204 stage 8 is on main
    Session: session_01ADzJtzYTLUfgrRZHxkagkX
    Account: os-steve (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-22937-organization-ownership-apply
    Worktree: objectstack-issue-22937-apply (in the cloud session's own checkout)
    Domain: domain:engine (the card's lane, by the #15194 epic hand-out). The surface is cross-lane domain:cli.
    Seat: domain:engine#2 (seat post #20966)
    File surface (read on origin/main e1deaefa8f, where PR 1's mappers now live; stop on a breach and explain it in the report). ⛔ Classes, positions and functions only, in every artefact.

  10. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 22937,
      "status": "done",
      "branch": "claude/issue-22937-organization-ownership-apply",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/23034",
      "session": "session_01DjKf52bcyXa3fbGW723phR — this run's harness-stamped id (commit Claude-Session line)",
      "premise_still_valid": true,
      "summary": "Claim 6122368393 names this branch. The no-duplicate check came back clean: no branch named for 22937, 15211 or organization-ownership on the remote, and none of the 16 open PRs builds --apply. Built `os migrate organization-ownership --apply` on the read-only plan already on main; no second inventory. The plan's walk gains an attribution sink, so the apply writes exactly the owners the plan derives. The new organization-ownership-apply.ts runs, in fate order: attribution (to a fixed point), authored catalog rows to environment metadata through the metadata door via core's three mappers, the verified id-to-name rewrite of sys_user_permission_set.permission_set (permission_set_id stays), mirror deletion behind the gate re-read before the first delete, and column drops through the schema-drift ceremony's drop_column entries. It is checkpointed in sys_migration row adr-0131-organization-ownership and resumable, then the post-check runs. The command adds --apply and --backup-taken (a non-interactive run without the flag is refused before the boot). The acceptance fixture carries every fate: effective access identical, a positive control, mirrors gone, owners written, the orphan row reported, counts reconciling. Draft PR #23034 (Fixes #22937, Clause-② yes), 1,891 changed lines; it stays a draft until #15204 stage 8 is on main.",
      "tests": "vitest at the tree of HEAD 0555b80a (a squash, tree-identical to the tested 0054df69): organization-ownership-apply.test.ts (8), organization-ownership.apply-flags.test.ts (3), organization-ownership-plan.integration.test.ts, organization-ownership-inventory.test.ts, test/vitest-tiers-partition.test.ts — 'Test Files 5 passed (5) / Tests 52 passed (52)'. schema-migrate.one-shot-family.integration.test.ts -t 'organization-ownership|every module': 'Tests 6 passed | 77 skipped', including the new --apply write mode. pnpm --filter @objectstack/cli typecheck: exit 0 ('check:test-typecheck: OK'). Ablations through scripts/ablation-replace.mjs, each 'ok restored: blob == HEAD and git diff HEAD is empty'. (1) Dropping the category exclusion from the delete predicate ('anchor 1 → 0, blob 3c8c9b6f8ba0 → bef51455e363'): the acceptance case goes red, because the customized template is deleted. (2) Disabling the pre-delete gate re-read ('blob 3c8c9b6f8ba0 → a28185750018'): 'Tests 1 failed | 7 passed', the between-runs gate case. No build or dist step is involved: the cli tests import src. End-to-end smoke with the built CLI on today's main composition, against a SQLite database that `os migrate apply` had schema'd, plus 17.x rows. The metadata door wrote permission/field_auditor to sys_metadata, and it resolved within the run. Both grants were named and verified. sys_job.organization_id was dropped through detectManagedDrift and applyMigrationEntries. The sys_metadata family was reported as not proposed, because its declarations on main still carry the column. Run 2 resumed from the sys_migration checkpoint (4 steps checkpointed). NOT MEASURED: test/json-stdout-purity.e2e.test.ts, reason: a comment-only edit, and the file is in the nightly e2e tier, outside both local projects.",
      "gates": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 66 at 0054df69 (the same tree as 0555b80a). All 66 were run, with exit codes captured before any pipe. `--ran` reconciliation: 'Run reconciliation — 66 derived, 66 run, 0 NOT-MEASURED, 0 UNRUN ... a DERIVED zero — all 66 recorded an exit code and none of them is 3'. Three first runs exited 3 (PREREQUISITE NOT MET) and were re-run green after the prerequisite was met: check-plugin-teardown-shape --self-test (shallow clone; fetched the pinned fixture commit 621a4876 with --depth=1); pnpm check:dual-build-cjs-loads (9 unbuilt sibling dists, built under os-verify-lock); pnpm check:i18n-coverage. Every other first run exited 0. CI timing steps: report-only under the #22949 ruling, not read.",
      "line_budget": "PR #23034: 9 files, +1,863 / -28 = 1,891 changed lines (generated files: none), under the 3,000 ceiling. The PR is not split: one PR, based on main, not stacked.",
      "files_changed": [
        "packages/cli/src/utils/organization-ownership-apply.ts (new)",
        "packages/cli/src/utils/organization-ownership-apply.test.ts (new)",
        "packages/cli/src/commands/migrate/organization-ownership.apply-flags.test.ts (new)",
        "packages/cli/src/utils/organization-ownership-plan.ts",
        "packages/cli/src/commands/migrate/organization-ownership.ts",
        "packages/cli/src/utils/schema-migrate.one-shot-family.integration.test.ts",
        "packages/cli/src/utils/schema-migrate.ts (doc comments only)",
        "packages/cli/test/json-stdout-purity.e2e.test.ts (comment only)",
        ".changeset/22937-cli-organization-ownership-apply.md"
      ],
      "deviations": [
        "File surface. The claim names organization-ownership.ts, -plan.ts and -inventory.ts, plus new apply modules and their tests. Three further packages/cli files changed. (1) schema-migrate.one-shot-family.integration.test.ts: the family pin enumerates every bootSchemaStack caller's modes, and its row for this command read 'write: [] … no writing mode until the ceremony's apply lands'. Leaving it would have left the new write mode undeclared and unpinned. (2) schema-migrate.ts: doc comments on composeHostStack, composeServedPlatform and composeAuthGatedSecurity say which callers set them, 'and by nothing else'; they now name this caller. (3) json-stdout-purity.e2e.test.ts: a comment saying the bare form is the command's only mode. All three are mechanical and inside packages/cli. No inventory file, no core/security file and no plugin-security file was touched.",
        "git push went direct, not through the relay. The dispatch says writes go through scripts/pm. .claude/agents/os-dev.md rule 3 says `git push` is not a REST write and does not go through the relay, and the role file wins on a conflict.",
        "One --force-with-lease push (lease = the last pushed sha 0054df69). It squashed four WIP commits into one commit carrying the model-free trailer pair AGENTS.md requires (Claude-Session + Co-authored-by: Claude). The tree is identical. All five unshared-branch criteria held: a claude/issue-* branch, this worktree created it, the only author was this session, there was no PR yet, and the push named its lease.",
        "Commit trailer: the harness reminder asks for a model-named Co-Authored-By line. AGENTS.md's model-free pair wins (the pre-push hook enforces it); this is not otherwise a deviation.",
        "The boot refusal (#15211's schema marker check) is not built. Per the dispatch: 'If it lives outside packages/cli, stop and report the location.' The location: CREATION_ATTESTED_MIGRATION_IDS (packages/spec/src/system/migration.zod.ts) and attestFreshDatastore (packages/platform-objects/src/system/migration-flag.ts) for fresh databases; the refusal itself at the serving boot (packages/cli/src/commands/serve.ts, and the runtime for hosts that do not boot through serve). This PR writes the marker the refusal reads (sys_migration row adr-0131-organization-ownership; applied_at plus verified_at through the existing isDataMigrationFlagVerified contract)."
      ],
      "mcp_calls": "0 — no MCP GitHub tool was called",
      "api_writes": "3 relay writes, all as objectstack-fleet[bot] through the fleet-write relay. (1) pr_create, draft, assignees [os-steve] → PR #23034: POST /repos/objectstack-ai/objectstack/pulls, plus the assignee leg POST /issues/23034/assignees; read back identical (13,280 bytes). (2) The #15204 pointer comment 6123345438 (post-stamped.mjs → POST /issues/15204/comments); read back identical. (3) This os-dev-report comment on #22937 (post-stamped.mjs → POST /issues/22937/comments). No label write, no issue write, no MCP write. git push is not counted: it is not REST.",
      "open_questions": [
        {
          "question": "Where does the v18 boot refusal (D10 item 5) land, given that it lives outside packages/cli?",
          "options": [
            "A: with C8 (protocol 18), which reads the sys_migration marker this PR writes and adds the id to CREATION_ATTESTED_MIGRATION_IDS so fresh databases are attested",
            "B: a separate C7b follow-up card now, in spec + platform-objects + serve"
          ],
          "recommendation": "A. Practical need: no runtime can refuse before the ceremony is runnable end to end on main (stage 8 has not landed). Long-term soundness: the refusal and the NOT NULL constraint are one 'protocol 18 is enforced' switch. Agent error-proofing: a refusal that lands early would refuse every existing dev database on main. Startup focus: no new gate without a maintainer naming it."
        },
        {
          "question": "The fate-2 gate is read literally: every grant must name a set the catalog resolves, including named grants whose set no longer resolves (they grant nothing either way). Should those block mirror deletion?",
          "options": [
            "A: block (as built), with a per-name remedy",
            "B: block only on unnamed grants whose id still points at a real row; report named-but-unresolved ones as advisory"
          ],
          "recommendation": "A. It is the card's wording ('every reference resolves by name'); the contract is strict and loud; the operator fixes and re-runs."
        },
        {
          "question": "Customized and organization-stamped sys_email_template rows (ruling C: 'promoted to environment templates before deletion') — this PR keeps and reports them, because no row→email_template converter exists. Who builds the promotion?",
          "options": [
            "A: a follow-up in this ceremony, with a pure row→definition mapper beside the core ones",
            "B: accept the loss under the startup posture with a release note (D10's other branch)"
          ],
          "recommendation": "A, scheduled after S8. The send path no longer reads rows, so keeping them changes nothing meanwhile."
        },
        {
          "question": "The inventory's two departures — sys_sharing_rule declared-rule mirrors (as: mirror-deletion) and the sys_setting global-rung move (as: moved) — are not performed here; both stay untouched and are counted as departures. Who performs them?",
          "options": [
            "A: the ceremony, once D2 retires the declared-rule seeder and the rule-sourced sys_record_share rows (source_id) are re-pointed or proven unaffected; and C6's move as a ceremony step",
            "B: their owning stages (D2, C6) as their own migrations"
          ],
          "recommendation": "A for the rule mirrors (fate 2 is the ceremony's one deletion), after a measurement of the source_id references; B for the global-rung move (C6 owns it)."
        }
      ],
      "out_of_scope_findings": [
        "class: none filed · noted only: the composeHostStack doc in packages/cli/src/utils/schema-migrate.ts said 'Set by the two SCHEMA commands … and by nothing else', while unmapped-columns and security-catalog-overlays already set it. The sentence was corrected in this PR because it had to name the new caller anyway. carrier: PR #23034"
      ]
    }

    Generated by Claude Code

  11. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    Seat review: PR #23034 (PR 2 of 2), a draft until stage 8 · domain:engine seat 2 · session_01ADzJtzYTLUfgrRZHxkagkX · 2026-10-12T12:12Z

    This reviews report 6123371167, against claim 6122368393. It was checked on GitHub, not taken from the report.

    • Form:
      • draft to main, assignee os-steve;
      • line 1 Fixes #22937;
      • line 2 Clause-②: yes, matching the claim.
    • Scope:
      • 9 files, +1,863 / −28 (1,891 lines, none generated), all in packages/cli plus one changeset;
      • none governed;
      • nothing under content/docs/releases/.
      • Three files are beyond the claim: the one-shot family pin, schema-migrate.ts doc comments, and one e2e comment. They are accepted deviations: mechanical and inside packages/cli. The family pin had to declare the new write mode.
    • CI on 0555b80a0a: 34 check runs, 31 success, 3 skipped, none failed.
    • Other deviations accepted:
      • the direct git push (role file rule 3);
      • the one lease-named force-push on its own unshared branch before the PR opened;
      • the model-free trailer pair (AGENTS.md).
    • Not yet done: the seat's diff read and the contract-tier review (Clause-② yes) wait for the epic seat's answers below, because Q2–Q4 can change the code. Both run before the PR leaves draft, on the head that merges main after stage 8.

    For the epic seat (this card: "Questions go here, and the epic seat answers here")

    The report's four questions follow, each with this seat's view. Please answer here, and this seat relays the answers to the dev.

    1. Where the v18 boot refusal lands (D10 item 5), given that it lives outside packages/cli. The report recommends A: with C8 (protocol 18), which reads the sys_migration marker this PR writes. This seat's view: A. A refusal on main before the ceremony can run would refuse every existing dev database. This PR writes the marker, 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 stays open for the refusal.
    2. Does fate 2's gate block on named grants whose set no longer resolves? It is built as A: it blocks, with a per-name remedy. This seat's view: A. It is the card's own wording ("every reference resolves by name"), and it is strict and loud: the operator fixes the grant and re-runs.
    3. Customized and organization-stamped sys_email_template rows ("promoted to environment templates before deletion"). This PR keeps and reports them, because no row→email_template converter exists. This seat's view: A, a follow-up inside this ceremony with a pure row→definition mapper beside core's. The quoted text names promotion, and B (accept the loss) would depart from it, so B needs the maintainer. Who builds it, and when, is the epic seat's call.
    4. The inventory's two departures: the sys_sharing_rule declared-rule mirrors, and the sys_setting global-rung move. This seat's view matches the report:
      • the rule mirrors go with the ceremony, after a measurement of the source_id references;
      • the global-rung move goes with C6.
        The epic seat owns the D2 and C6 sequencing.

    State: the card stays pm:dispatched, with PR #23034 open as a draft. It waits on:

    Then the dev merges main and applies the answers, the seat reads the diff, the contract review runs, and the PR is readied.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions