Skip to content

fix(organizations)!: retire claimOrphanOrgRows — it gives organization-less rows to the first organization, an owner by guess that ADR-0131 D9 and D10 forbid (measured 6342754850) #25204

Closed

Description

@objectstack-fleet

Filing gate ③: an unclassified item of #15212, found by the epic seat's reconciliation at main 2919ddb875.

  • Who acts: the epic seat dispatches the measurement.
  • Dedupe: none ("claimOrphanOrgRows orphan rows first organization" → 0).

Part of #15212.

What is on main

  • packages/plugins/organizations/src/claim-orphan-org-rows.ts:62: claimOrphanOrgRows runs once, when the first organization is created. It back-fills organization_id on every organization_id IS NULL row of every user-defined object that declares the column.
  • Its companion is claim-org-seed-ownership.ts. The caller is organizations-plugin.ts:449-452.
  • It reads NULL rows and gives them an owner by guess. ADR-0131 D8 says NULL is not a state, and D10 says the ceremony never guesses an owner. It is on no stage list.

Wanted (measurement only, no code)

  • On which stores this release serves can it find a row? Check fresh single (the Default Organization exists at boot), walled, an 18.0.0-born store (nullable columns, voluntary ceremony), lean embedding, and --dev.

  • Is any row it would claim one the ceremony also attributes? Could the two disagree?

  • Recommend one of:

    • A: retire it;
    • B: keep it, with the ADR passage that allows it;
    • C: fold it into the ceremony.

    If B or C needs ADR text, the seat files a decision card for the maintainer.

Acceptance

  • An os-dev measurement report on this card, with commands and counts.

Activity

  1. objectstack-fleet commented on Oct 22, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: epic seat round · 2026-10-22T12:38Z · measurement only, for the unclassified item of #15212 found by the reconciliation note 6339761793
    Session: session_01Y5583bs2RDd53MH6kM1ca3
    Account: os-steve
    Branch: none this round
    Worktree: the cloud session's own checkout (mode:cloud)
    Domain: domain:services
    Seat: epic:#15194
    File surface:

  2. objectstack-fleet commented on Oct 22, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim withdrawn · epic PM session_01Y5583bs2RDd53MH6kM1ca3 (os-steve) · 2026-10-22T12:42Z. The claim 6340943400 is withdrawn before any work landed. The maintainer capped the epic's concurrency at two dev sessions, verbatim 「后续并发不要超过2」, and two are already in flight (#25201, #25202). The measurement session was stopped and archived; it wrote nothing. This card goes back to waiting (pm:dispatched removed). It is re-dispatched when a slot frees.

  3. objectstack-fleet commented on Oct 22, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: epic seat round · 2026-10-22T13:43Z · re-dispatch (the slot #25201 freed; concurrency cap 2, record 6341036187) · measurement only, for the unclassified item of #15212 found by the reconciliation note 6339761793
    Session: session_01Y5583bs2RDd53MH6kM1ca3
    Account: os-steve
    Branch: none this round
    Worktree: the cloud session's own checkout (mode:cloud)
    Domain: domain:services
    Seat: epic:#15194
    File surface:

  4. objectstack-fleet commented on Oct 22, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 25204,
    "status": "done",
    "branch": "none (measurement round; no branch, no commit, no PR)",
    "pr": null,
    "session": "session_01Cfa8o4JmHM7iREGWgUybnk, dispatched by the epic seat session_01Y5583bs2RDd53MH6kM1ca3 under the claim 6342271149",
    "reading": "2026-10-22T14:05Z on origin/main 03de83b0 (a descendant of 3a440b0), repository objectstack-ai/objectstack",
    "premise_still_valid": true,
    "recommendation": "A: retire claimOrphanOrgRows. No ADR text is needed: D9 and D10 already forbid what it does, and no passage of ADR-0131 or any ruling allows it.",
    "summary": "WHAT IT IS. Two functions. (1) claimOrphanOrgRows (packages/plugins/organizations/src/claim-orphan-org-rows.ts:62) walks every registered object that is not managedBy, not sys_-prefixed and declares organization_id. It reads up to 10 000 rows WHERE organization_id IS NULL as isSystem, then writes organization_id = one id at a time. It is reached from one place: Middleware B in organizations-plugin.ts (Fallback A, lines 449-466), after a sys_organization insert, only when the per-org seed replay landed 0 rows (inserted + updated = 0) AND the organization count read just after the insert is 1, i.e. the first organization the store ever holds. That count, read at limit 2, is the only idempotency guard. The header's sentence 'Idempotent: a no-op once an organization-tagged row exists' describes a check the code does not make. (2) claimOrgSeedOwnership (claim-org-seed-ownership.ts) is NOT an organization_id writer. It sets owner_id on rows the org's own seed replay reported landing on (seededRecordIds, ADR-0138 D1), scoped organization_id = org. It runs from the default-org owner bind, takes nothing from claimOrphanOrgRows, and does not depend on it. Only its header prose names it. WHO MOUNTS IT. os serve and os dev mount OrganizationsPlugin only when the posture is not single (packages/cli/src/commands/serve.ts:4359, multiTenant = tenancyPosture !== 'single'), and the plugin entitles only group and isolated (supportedPostures). So under single the claim is not composed at all. CAN IT FIND A ROW? Only one population reaches it: a walled store whose first organization is created while it holds NULL-organization rows on app objects, with a replay that lands nothing. No store this release produces holds such a row. Every write through the engine is stamped or refused (D9, Engine.resolveSystemInsertOrganization: derived under single, refused under a wall, refused under single with the organization object registered and no organization). 18.0.0 (06cab48) already had both halves. A table the driver creates since 7b-0 refuses the row at NOT NULL, measured below. A v17 or pre-release store boots only certified, and certification holds every unattributable row against it. Measured per store below: 0 rows claimable on every store this release produces or serves. OVERLAP AND DISAGREEMENT. Yes. The claim's population (application objects, not sys_, not managedBy) is exactly the ceremony's APPLICATION_OBJECT_FATE population (organization-ownership-inventory.ts:272, fate 3 'attribution', anchors: []). Under single, the ceremony gives a NULL row to the Default Organization. Under a wall, no anchor names an owner, so the row is reported, left NULL and held against certification (organization-ownership-apply.ts UNATTRIBUTABLE_REMEDY: 'the ceremony never guesses an owner'). The claim gives that same row to whichever organization is created first. They agree under single, where the claim is not composed. They disagree under a wall, where the claim is composed. Reproduced end to end on a hand-made store (below): the ceremony refused to attribute 11 rows, then a real os dev boot gave all 11 to the first organization. DEPENDENTS. None. Neither shipped example (app-showcase, app-crm) declares @objectstack/organizations, so a walled os dev of either is refused at boot (measured). In a walled host that does declare it, an app with seeds always replays (+132 in the group boot) and returns before Fallback A. Its tests are claim-orphan-org-rows.test.ts, 8 cases against a mock engine. No test drives Fallback A through the plugin. Its other references are bookkeeping and prose (list under 'retirement_cut').",
    "measurement": {
    "build": "pnpm install --frozen-lockfile && OS_SKIP_DTS=1 pnpm build -> 76/76 tasks, exit 0, on 03de83b0",
    "counter": "node /count-nulls.mjs <db|sql>: per table carrying organization_id, NOT NULL flag and COUNT(*) WHERE organization_id IS NULL, split into the claim's population (not sys_) and the rest",
    "stores": [
    "fresh single, os dev (Default Organization at boot): pnpm dev -- --fresh -p 38611 (showcase). Tenancy: single. OrganizationsPlugin not mounted (0 '[org-scoping]' lines, 0 'organizations' lines). 1 organization; 59 tables with the column, 1 nullable (sys_sso_provider); claim population 22 tables / 127 rows / 0 NULL. Claim: not composed.",
    "fresh isolated, os dev, real OrganizationsPlugin: showcase copied to a scratch host that declares @objectstack/organizations (the shipped showcase is refused: 'tenancy posture isolated was requested but @objectstack/organizations could not be loaded ... the host app does not declare it'); OS_TENANCY_POSTURE=isolated OS_PLATFORM_OWNER_EMAIL=admin@objectos.ai OS_AUTH_MEMBERSHIP_POLICY=invite-only objectstack dev --seed-admin --fresh -p 38615. 1 organization (default); claim population 22 tables / 127 rows / 0 NULL; every seed row stamped with the default org. Fallback A not reached (the replay landed rows).",
    "fresh group, same host, OS_LOG_LEVEL=info: [org-scoping] per-org seed replay for org_mvjlx9qdc7g5yx24: +132 inserted, 0 updated, 0 error(s) and then handed 127 seeded row(s) ... to owner (claimOrgSeedOwnership); 0 'claimed ... orphan' lines; 1 organization; 22 tables / 127 rows / 0 NULL.",
    "fresh isolated, SEEDLESS (same host with data: []), the one fresh shape that reaches Fallback A: no replay line; the claim ran, with 2 x WARN [org-scoping] claim scan failed for showcase_ext_customer|showcase_ext_order (federated objects whose remote has no organization_id column), and claimed 0 (no 'claimed' line). 22 tables / 0 rows / 0 NULL. A raw INSERT INTO showcase_task (id, organization_id) VALUES ('probe', NULL) on a copy of that database: NOT NULL constraint failed: showcase_task.organization_id.",
    "18.0.0-born store (upgrade harness fixture-18.0.0, ref @objectstack/cli@18.0.0, sha 06cab48), loaded from database.sql: 1 organization; 65 tables with the column, 65 nullable; claim population 22 tables / 128 rows / 0 NULL; 0 NULL on sys_ tables. fixture-18.0 (5b14b7f): 1 organization, 67/67 nullable, 22 tables / 128 rows / 0 NULL. With an organization already present, a new organization reads a count of 2 and Fallback A is closed, under any posture. The 18.0.0 engine already refused a walled organization-less insert (system-write-organization.ts: refuse 'walled-posture'), which agrees with #24919's 0 NULL rows on 18.0.0-born stores under all three postures (6323585273).",
    "ceremonied store: fixture-18.0.0 through os migrate organization-ownership --database-url file:<copy> --out plan.json then --apply --plan-file plan.json --backup-taken (cwd examples/app-showcase, OS_AUTH_SECRET set): plan exit 0, apply exit 0; posture single, 134 tables planned, 0 unattributable; after: 1 organization, 4 nullable tenant columns, claim population 22 tables / 128 rows / 0 NULL.",
    "lean embedding: examples/embed-objectql references neither @objectstack/organizations nor sys_organization (grep 0); npx vitest run 2/2 passed. No organization object means no sys_organization insert, and no OrganizationsPlugin means no middleware. Claim unreachable. The NULL rows the D9 lean exception allows live where the claim never runs.",
    "os dev / --dev: every boot above is os dev. The composition gate (serve.ts:4359) is shared with os serve, so the walled verdicts hold for a served production boot too; a production os serve was not booted separately."
    ],
    "disagreement_repro": "Hand-made, not producible by this release's engine. Took a copy of fixture-18.0.0, set showcase_task.organization_id = NULL on its 11 rows, and deleted sys_member and sys_organization (0 organizations). CEREMONY: OS_TENANCY_POSTURE=isolated os migrate organization-ownership --out gave showcase_task fate attribution, attribution {}, unattributable 11 ('no anchor names the owner'), notNull.willReceive false ('11 row(s) whose owner cannot be derived stay NULL and are reported'). --apply exit 1: complete true, blocking 11, so the store is not certified. Under OS_TENANCY_POSTURE=single the same plan gave attribution {default-organization: 11} plus the 'creates the Default Organization' warning. CLAIM: a seedless walled os dev over the un-ceremonied copy (OS_TENANCY_POSTURE=isolated ... objectstack dev --seed-admin -d file:<copy> -p 38618). The boot guard let it through: the store is 18.0.0-born and the ceremony is voluntary. The log then read [org-scoping] claimed 11 orphan seed row(s) for first organization org_mvjm2fc6q7b17s1y {breakdown:[{object:showcase_task,count:11}]}. Read back: showcase_task 11/11 on org_mvjm2fc6q7b17s1y (slug default). The ceremony reported these 11 rows and refused to guess an owner. The claim gave them all to the first organization."
    },
    "reasoning": "A, because: (1) It is a guess. D10 fate 4: 'a row whose owner cannot be derived is left NULL and listed ... Never guessed, never deleted'. D9: 'Nothing defaults to any owner other than the derivable one'. D11: ownership rules are 'identical under single, group and isolated'. Being the first organization created is not an anchor, and under a wall it is the only posture in which the claim runs. (2) No passage allows it. The one place ADR-0131 allows an owner without an anchor is D10 fate 3 'under single, the Default Organization', and the claim is not composed under single. So B has nothing to quote. (3) C would be redundant or would contradict the ruling. Its single-posture half is already the ceremony's (Default Organization attribution). Its walled half is the guess the ceremony was built to refuse (ruling C on the C8 decision, held against certification). Folding it in would mean an ADR amendment that reverses D10 fate 4 under a wall. Nobody has asked for that, and it would revive the cloud#1345 class: the first customer's organization receiving rows it never wrote. (4) It does no work this release needs: 0 claimable rows on every store this release produces or serves. Its only real reach is the disagreement above: an un-certified 18.0.0-born walled store that someone left holding NULL application rows and no organization. There, retiring the claim is the fix: the rows stay NULL; os migrate plan's advisory (#25179) lists their column as still nullable, and the ceremony names each row with the remedy.",
    "retirement_cut": [
    "delete packages/plugins/organizations/src/claim-orphan-org-rows.ts and claim-orphan-org-rows.test.ts (8 mock-engine cases; no other test drives Fallback A)",
    "organizations-plugin.ts: remove the import and Fallback A (lines 449-466). Decide the first organization's log line: today orgCount > 1 && !replayed logs 'starts empty'; once Fallback A is gone, a first organization with no replay logs nothing unless the guard becomes !replayed. Update header item 2b ('for the FIRST org, claimOrphanOrgRows adopts any NULL-org rows').",
    "index.ts:64: drop the export. @objectstack/organizations is published, so this is a public-API removal: patch changeset, BREAKING banner, migration line ('no replacement: run os migrate organization-ownership; it attributes under single and reports under a wall'), Metadata-protocol: none, and an ADR-0087 disposition marker as the gate prints it.",
    "bookkeeping: scripts/engine-double-contract.pinned.json (the entry for claim-orphan-org-rows.test.ts, verb update, pinned 2); docs/audits/2026-08-tenant-audit-write-call-sites.counts.md:107 (the claim's census row; regenerate it with scripts/tenant-audit-census.mjs, never by hand); packages/plugins/organizations/README.md:55 (API table row)",
    "prose that names it: claim-org-seed-ownership.ts header ('scoped to an org by claimOrphanOrgRows / per-org replay' becomes 'by the per-org replay'); org-scoping-engine.ts:7; plugin-security claim-seed-ownership.ts:43; security-plugin.ts:4976 (which also still names the retired cloneOrgSeedData); runtime app-plugin.ts:2153 (a quotation; reword it, never edit the quoted header out from under it)"
    ],
    "tests": "packages/plugins/organizations: npx vitest run src/claim-orphan-org-rows.test.ts src/claim-org-seed-ownership.test.ts -> Test Files 2 passed (2), Tests 19 passed (19). examples/embed-objectql: npx vitest run -> 1 file, 2 tests passed. The real boots and ceremony runs are listed under measurement, with commands and counts.",
    "gates": "n/a: no diff. The shared checkout's git status --short is empty after the round. Every edit (the scratch host's package.json and data: []) was to a copy in the session scratchpad.",
    "dogfood_battery": "n/a: no PR",
    "mcp_calls": "2: mcp__github__issue_read (get #25204; get_comments #25204). One authenticated REST read: GET issues/comments/6339761793.",
    "api_writes": "1: this comment, through scripts/pm/post-stamped.mjs --comment=25204",
    "open_questions": [],
    "out_of_scope_findings": [
    "carrier: #25204's retirement build. claimOrphanOrgRows scans federated objects (showcase_ext_customer, showcase_ext_order), whose remote has no organization_id, and so warns 'claim scan failed' twice each time a seedless walled store creates its first organization. It goes away with the retirement. Noted, not filed.",
    "carrier: #25204's retirement build. The claim-orphan-org-rows.ts header says 'Idempotent: a no-op once an organization-tagged row exists'. The code makes no such check; the only guard is the caller's first-organization count. It goes away with the retirement. Noted, not filed.",
    "carrier: #25203 (stale texts). security-plugin.ts:4976 still names cloneOrgSeedData, which was retired by cloud#1345. Noted, not filed."
    ]
    }


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 22, 2026

    @objectstack-fleet
    ContributorAuthor

    Seat decision · epic PM session_01Y5583bs2RDd53MH6kM1ca3 (os-steve) · 2026-10-22T14:10Z. Recommendation A (retire) is taken. The measurement is os-dev-report 6342754850, on origin/main 03de83b0. The seat re-checked its two load-bearing facts on f2ade4afb0:

    • the claim is reached only from organizations-plugin.ts's Fallback A, and only when the organization count is 1 (:449-466);
    • os serve composes OrganizationsPlugin only when the posture is not single (serve.ts:4359).

    Why A:

    • The defect, reproduced on a store a walled 18.x can boot. The store is an 18.0.0-born copy with 11 showcase_task rows set to NULL organization.
      • Under isolated, the ceremony marked all 11 rows unattributable and refused to certify.
      • A seedless isolated boot of the un-ceremonied copy, voluntary on an 18.0.0-born store, then gave the 11 rows to the first organization: "claimed 11 orphan seed row(s)".
      • That is an owner by guess. D10 fate 4 says it is never guessed; D9 says nothing defaults to any owner other than the derivable one.
    • Nothing to keep it for. No passage allows it (B), and folding it into the ceremony (C) would duplicate single's Default Organization or reverse fate 4 under a wall.
    • Dependents: none in the shipped examples; only 8 mock-engine tests.

    State: this card becomes the build. Its title moves from measure(…) to fix(…)!. The cut list is the report's.

    • Delete the function, its test, Fallback A and its log line.
    • Remove the index.ts export: patch, with a BREAKING banner, migration lines and the ADR-0087 marker.
    • Update the pinned engine-double contract and regenerate the census row with its script.
    • Fix the README row and the prose in five files.

    The measurement session is archived. The seat dispatches the build into the free slot (concurrency cap 2) with a new claim.

  6. changed the title [-]measure(organizations): claimOrphanOrgRows assigns organization-less seed rows to the first organization created — does it still write on any served store, and does it retire under ADR-0131 D8/D10?[/-] [+]fix(organizations)!: retire claimOrphanOrgRows — it gives organization-less rows to the first organization, an owner by guess that ADR-0131 D9 and D10 forbid (measured 6342754850)[/+] on Oct 22, 2026
  7. objectstack-fleet commented on Oct 22, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: epic seat round · 2026-10-22T14:28Z · the build of decision A (6342853688), from the measurement os-dev-report 6342754850
    Session: session_01Y5583bs2RDd53MH6kM1ca3
    Account: os-steve
    Branch: claude/issue-25204-retire-claim-orphan-org-rows
    Worktree: the cloud session's own checkout (mode:cloud)
    Domain: domain:services
    Seat: epic:#15194
    File surface (the report's cut list; re-measure on current main):

  8. objectstack-fleet commented on Oct 22, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 25204,
    "status": "done",
    "branch": "claude/issue-25204-retire-claim-orphan-org-rows",
    "pr": "#25246",
    "session": "session_0146UznqonWCqNdiHePZ9Xy3, dispatched by the epic seat session_01Y5583bs2RDd53MH6kM1ca3 under the claim 6343237947 (its Branch line names this branch)",
    "premise_still_valid": true,
    "summary": "Head edd5882 on base f2ade4a. Re-measured on f2ade4a before cutting: every site in the report's cut list was where the report put it (claim-orphan-org-rows.ts:62, organizations-plugin.ts Fallback A, index.ts:64, README.md:55, counts.md:107, engine-double-contract.pinned.json, and the five prose sites). Done: claim-orphan-org-rows.ts and its test deleted; Fallback A, its 'claimed ... orphan seed row(s)' log line and header item 2b removed from organizations-plugin.ts (the header now says both retired paths, donor clone and orphan claim, must not come back, and why); the false idempotency sentence lived only in the deleted file. The sys_organization count read (limit 2) existed only to pick Fallback A, so it is gone too, and a first organization with no replay now logs the same 'starts empty' line every later one logs; this is the one decision the report left open. The export and its README row are removed. The engine-double ledger and the tenant-audit census were regenerated by their own scripts (--write); the census page's hand-written prose counts (237 to 236, 77 to 76, 135 to 134) were restated because check-tenant-audit-census reds on them, the historical carried figures in the first column left as quoted. Prose fixed at the five sites (security-plugin.ts also drops the retired cloneOrgSeedData name; app-plugin.ts no longer quotes the plugin-security header). claim-org-seed-ownership.ts changes in header prose only; no ceremony change, no ORGANIZATION_OWNERSHIP_SHAPE_GENERATION change. New pin first-organization-orphan-rows.pin.test.ts (4 cases). Changeset: @objectstack/organizations patch, BREAKING banner, FROM/TO line, marker not-required (runtime-export-retired @objectstack/organizations#claimOrphanOrgRows); Clause-2: no (narrowing), Metadata-protocol: none. Size 15 files, +316/-387. check-governed-merges --branch: 0 of 15 paths governed, so the Tier is the contract-review tier the declared narrowing picks, not Tier H/S.",
    "tests": "@objectstack/organizations: pnpm --filter @objectstack/organizations test under the lock -> Test Files 15 passed (15), Tests 229 passed (229), VERDICT command-exit 0 (taken at 78b1ed1; the later commits change only the pin's docblock, generated files, prose and the changeset). Typecheck: dependency closures rebuilt with declarations, then pnpm --filter @objectstack/organizations --filter @objectstack/plugin-security --filter @objectstack/runtime run typecheck -> VERDICT command-exit 0 (organizations test layer: 0 errors). ABLATION (Fallback A put back): claim-orphan-org-rows.ts restored from origin/main under an EXIT trap, and node scripts/ablation-replace.mjs --file packages/plugins/organizations/src/organizations-plugin.ts --anchor '// NO ORPHAN CLAIM (ADR-0131 D9, D10).' --replacement <Fallback A with the org count read>: anchor 1 -> 0, marker ABLATION-FALLBACK-A grep -c 1 on disk before the run; the pin read Tests 1 failed | 3 passed (4), the failure the seedless case: expected [] to deeply equal [ 'crm_account:acc_orphan', ...(2) ] (all three rows claimed); restore proven by blob dd2e6514de97 == HEAD and an empty git diff HEAD, and the restored claim file removed (git status clean). The first ablation attempt was a no-op refused by the tool (my replacement contained its own anchor, drop 0); it ran nothing and was redone with a different anchor. The tool does not rebuild: the pin imports the plugin from src by relative path, so no dist is on the resolution path. UPGRADE HARNESS: pnpm --filter @objectstack/dogfood exec vitest run --maxWorkers=2 test/upgrade-18x-harness.dogfood.test.ts -> Test Files 1 passed (1), Tests 15 passed (15), both fixture legs (fixture-18.0 and fixture-18.0.0), VERDICT command-exit 0, at edd5882's tree. R1 (fresh boot): pnpm dev -- --fresh -p 38731 (showcase): health 200 after 16 s, 'Tenancy: single', 0 '[org-scoping]' lines; admin sign-in 200 (Origin http://localhost:38731), GET /api/v1/data/showcase_task?limit=1 200 with total 10; stopped (port pid 10542). R4 (walled os serve): the fixture-18.0.0 database loaded into a scratch store, showcase_task.organization_id set NULL on all 11 rows, sys_member and sys_organization emptied (before: 1 org, 11 tasks, 0 NULL; after: 0 orgs, 11 tasks, 11 NULL). A throwaway host copied from examples/app-showcase, declaring @objectstack/organizations and with data: [] (seedless, the only shape that reached Fallback A), served with OS_TENANCY_POSTURE=isolated OS_PLATFORM_OWNER_EMAIL=admin@objectos.ai OS_AUTH_MEMBERSHIP_POLICY=invite-only OS_AUTH_SECRET=... OS_SECRET_KEY=... OS_DATABASE_URL=file:STORE objectstack serve -p 38742 --log-level info: health 200; '[security] tenancy posture isolated, the Layer 0 organization wall is ACTIVE'; the first organization was created at boot ('created Default Organization org_mvjoq40zzyshb9gh'), logged 'starts empty', 0 'claimed ... orphan' lines and 0 'claim scan failed'. Read back after stop: 1 organization, showcase_task 11/11 still NULL. The same shape on origin/main is the report's repro (6342754850: 'claimed 11 orphan seed row(s)', 11/11 given to the first organization). Host directory removed after; the worktree is clean. FULL DOGFOOD (title carries !): see dogfood_battery.",
    "gates": "Derived: node scripts/pm/dispatch-gates.mjs --commands -> exit 0, 111 commands for 15 paths vs merge base f2ade4a, each run with its exit code captured before any pipe (plus 3 outside the derivation: check:published-readme-exports, check-platform-checklist --changed-from origin/main, check-nul-bytes, all exit 0). Red at 86cf826 and fixed: check-tenant-audit-census and its --self-test (exit 1: the census page's hand-written prose still read 237/77/135); after edd5882 both exit 0. NOT MEASURED, exit 3 (prerequisite): check-plugin-teardown-shape --self-test (its positive control is a commit this shallow clone cannot reach), spec check:skill-examples and check:dual-build-cjs-loads (built with OS_SKIP_DTS / not every dist at that moment), check:i18n (CLI not yet built at that moment); all four run in CI's Lint jobs, green. Reconciliation node scripts/pm/dispatch-gates.mjs --ran FILE (each line CMD :: exit N) -> exit 0, '111 derived famil(ies) accounted for, 107 run, 4 NOT-MEASURED (4 DERIVED from a recorded exit 3)'. node scripts/pm/check-governed-merges.mjs --branch claude/issue-25204-retire-claim-orphan-org-rows -> exit 0, 'NOT governed', 691 changed lines. CI on head edd5882: Lint & Repo Gates success, TypeScript Type Check success, Test Core success (shards 1-6 all success), Build Core success, Governed Surface Queue Guard success, Check Changeset success, Lint · PM dispatch-gates success, Type Check · workspace / source gates / consumer gates / debt ledger success, Build Docs success, Spec property liveness success; Console Pin Gate, Dogfood shards, Temporal Conformance and the opt-in upgrade-harness job skipped on a PR by their own if:.",
    "dogfood_battery": "edd58828 · pnpm --filter @objectstack/dogfood test under the lock, VERDICT command-exit 0 (held 18m44s) · Test Files 287 passed | 3 skipped (290) · Tests 2398 passed | 18 skipped (2416) · no failure",
    "mcp_calls": "6: mcp__github__issue_read (get #25204, get_comments #25204); mcp__github__pull_request_read (get_check_runs x2, get, get_status on #25246). No MCP write.",
    "api_writes": "2: (1) pr_create through the fleet-write relay (node scripts/pm/fleet-write/dispatch.mjs, run 39800293080, success): POST /repos/objectstack-ai/objectstack/pulls (draft) and POST .../issues/25246/assignees [os-steve]; body read back 3989 bytes sent = stored. (2) this comment through scripts/pm/post-stamped.mjs --comment=25204. git push is not counted.",
    "open_questions": [],
    "out_of_scope_findings": [
    "carrier: none. organizations-plugin.ts still logs 'per-org seed replay failed, falling back' when the replayer throws; with both fallbacks retired, the only thing it falls back to is the 'starts empty' line. Kept verbatim because organizations-plugin.test.ts pins its absence by that text. Noted, not filed.",
    "carrier: none. A local os dev sign-in against 127.0.0.1 answers 403 INVALID_ORIGIN while localhost answers 200: the trusted origin is spelled localhost. Expected behaviour of the origin check, not a defect. Noted, not filed."
    ]
    }


    Generated by Claude Code

  9. objectstack-fleet commented on Oct 22, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · epic PM session_01Y5583bs2RDd53MH6kM1ca3 (os-steve) · 2026-10-22T16:26Z. PR #25246 merged into main as e3190b9494. It closes this card (decision A, 6342853688).

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

Metadata

Metadata

Assignees

Labels

area:accessPermissions that actually hold — RLS/FLS, sharing model, write-path guardsbugSomething isn't workingdomain:servicespm:dispatchedpm:epicpriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions