You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
metadata: after #23469, the legacy-organization read seam's loose ends (ambient transaction, filter-after-limit, an unpinned by-name filter, DatabaseLoader._count, a 404 where a named refusal belongs) and the ceremony wording #23609
Filing gate: (c) a read-only finding from a contract review, not run. The PASS record 6184549574 on PR #23469 (#23429, C7b S2 + S5) lists these as non-blocking.
Reader who acts: domain:engine triage, to grade and route.
Filed by domain:engine seat 1 · marchtian · session session_01Rerax7QTjKMPCUZxQUtPFR. ⛔ Not a claim.
⛔ Blocked on PR #23469. None of this code is on main until that PR merges. The seat flips this card to pm:queue on MERGED.
Why it is low priority
Every path below matters only on an unmigrated (v17-shape) database, where legacy organization rows still sit in the sys_metadata family. os serve refuses to boot such a database (S5's guard) until os migrate organization-ownership has verified. So no served door reaches these paths in a supported posture today. They are latent, and worth closing before anything else starts reading the family off the served boot.
What the review found (PR #23469 at e4811b67f2, read only)
findServedOverlayRow's filter has no pin of its own. In meta-stored-legacy-organization.integration.test.ts, the _lock case asserts only lock and editable. With that filter alone removed, getMetaItem would serve the organization's body as item, and no pin goes red.
Wanted: assert that read.item is not the organization's body.
The seam joins only an explicit context.transaction.
legacyOrganizationRowsOf's raw listPhysicalColumns / execute calls do not read ObjectQL's ambient transaction.
The protocol passes none: every call site passes { isSystem: true }.
Inside publishPackageDrafts' ambient engine.transaction, on a v17-shape SQLite file, the column read would wait on a second pool connection. The paths are promoteDraftForPublish's draft read, the active-row read, repo.get and repo.promoteDraft.
Wanted: take the engine's ambient transaction, or thread trxCtx into those reads.
The plural form filters after limit, so a page under-fills, or a single-row read misreads, when legacy rows sit in it:
auditMetaItem (orderBy plus limit);
listCommits (limit);
revertStoredPackage (limit: 1), which answers 409 "never been published" when its first active row is a legacy one;
the repository's list(filter.limit).
Wanted: filter before limiting, or page until the limit is met.
DatabaseLoader._count does not filter. So exists() answers true for an address that only a legacy row holds, while load() answers null, and the history total counts legacy rows. This is pre-existing: main's loader never filtered.
rollbackToPackageCommit answers COMMIT_NOT_FOUND (404) for a legacy commit, where revertCommit gives a named refusal. Wanted: the same named refusal.
Inert plumbing to remove, behaviour-neutral:
rowsRead;
ServedOverlayRowCandidate.scope / organizationId;
orgId / itemOrgId in protocol.ts.
Every row that reaches them is now the environment's (the dev's report 6184164699; verified inert in 6184549574).
Wording:
The four ADR-0087 entries 18.sys-metadata{,-audit,-commit,-history}-organization-column-retired, and content/docs/concepts/metadata-lifecycle.mdx, name os migrate organization-ownership --apply without --plan-file. main's 18.cli-organization-ownership-apply-plan-file-required makes --plan-file required.
E1's refusal sentence in os migrate apply reads "which the organization-ownership ceremony owns that drop", which is garbled.
The changeset gaps the review named are not here: S5's unnamed runtime exports, and the ApiError.code widening by ORGANIZATION_OWNERSHIP_MIGRATION_REQUIRED. Changesets are consumed at release, so these ride the release notes, not a code change.
Dedupe
The words legacyOrganizationRowsOf findEnvironmentRows ambient transaction rollbackToPackageCommit DatabaseLoader _count rowsRead itemOrgId match only PR #23469 and #23429.
Claim: PM loop round 2 · 2026-10-15T23:59Z
Session: session_01GP3comALHRcRBixS2TEnLF (the dispatching seat; the dev runs as its own cloud session, named in the dispatch comment)
Account: sunhaolin (the seat's linked user as GET /user answers it; always the card's assignee)
Branch: claude/issue-23609-legacy-org-read-seam
Worktree: objectstack-issue-23609
Domain: domain:engine
Seat: domain:engine#1 (seat post #6367)
File surface, by the card's items (the dev re-measures each item on main first; an item already closed on main is reported, not re-done):
packages/metadata-protocol/src/protocol.ts, the legacy-organization read seam only: legacyOrganizationRowsOf and its callers' transaction (item 2); the plural reads that filter after limit, namely auditMetaItem, listCommits and revertStoredPackage (item 3); rollbackToPackageCommit's answer for a legacy commit (item 5); the inert rowsRead, ServedOverlayRowCandidate.scope / organizationId and orgId / itemOrgId plumbing (item 6). packages/metadata-protocol/src/sys-metadata-repository.ts: list's filter.limit only (item 3). packages/metadata/src/loaders/database-loader.ts: _count only (item 4).
Activity
objectstack-fleet commentedon Oct 16, 2026
Claim: PM loop round 2 · 2026-10-15T23:59Z
Session:
session_01GP3comALHRcRBixS2TEnLF(the dispatching seat; the dev runs as its own cloud session, named in the dispatch comment)Account:
sunhaolin(the seat's linked user asGET /useranswers it; always the card's assignee)Branch:
claude/issue-23609-legacy-org-read-seamWorktree:
objectstack-issue-23609Domain:
domain:engineSeat:
domain:engine#1(seat post #6367)File surface, by the card's items (the dev re-measures each item on
mainfirst; an item already closed onmainis reported, not re-done):packages/metadata-protocol/src/protocol.ts, the legacy-organization read seam only:legacyOrganizationRowsOfand its callers' transaction (item 2); the plural reads that filter afterlimit, namelyauditMetaItem,listCommitsandrevertStoredPackage(item 3);rollbackToPackageCommit's answer for a legacy commit (item 5); the inertrowsRead,ServedOverlayRowCandidate.scope/organizationIdandorgId/itemOrgIdplumbing (item 6).packages/metadata-protocol/src/sys-metadata-repository.ts:list'sfilter.limitonly (item 3).packages/metadata/src/loaders/database-loader.ts:_countonly (item 4).packages/cli/src/commands/migrate/meta-stored-legacy-organization.integration.test.ts(item 1's pin) andpackages/cli/src/commands/migrate/apply.ts's E1 refusal sentence (item 7),domain:cli, declared on [PM seat] domain:cli — 🟢 os-bill · session_01FLwgbTSmGMrqsXkBDsiwfG · round 4 · batch 3 (maintainer) · landed 16 PRs · in flight 3 (#23623, #23633, #23714) #6024; the fourpackages/spec/src/migrations/entries/semantic/18.sys-metadata{,-audit,-commit,-history}-organization-column-retired.tstexts (item 7,--plan-file) with their regenerated artifacts,domain:spec, declared on [PM seat] domain:spec · seat 3 — 🟢 baozhoutao · session_01D6F9axfoPzR7t8G1J7Ytzz #18883;content/docs/concepts/metadata-lifecycle.mdx(item 7),domain:devx, declared on [PM seat] domain:devx · seat 2 — 🟢 os-sales · session_016PVjjuVPte5XEJvaQx1E4t · serial (maintainer) #20163..changeset/23609-*.md. ⛔ NotsaveMetaItem, its D9.9 call orunboundOwnerPackageRefusal(metadata-protocol: over legacy object rows [package-less, Q], a draft save naming no package answers 200 into Q's draft, which no publish can serve: the save door's D9.9 check judges the request's package before the draft address resolves to Q #23712, in flight), not the promote door's D9.9 call, not the draft address. Stop on any other breach and explain it in the report.Container & model:
M,mode:cloud(the maintainer's order on seat post [PM seat] domain:engine — 🟢 sunhaolin #6367: 「后续 重活开发 都可以单独开云卡」; a spec regeneration plus three packages is build-heavy),model: TIER_DEFAULT(this run'sdispatch-gates.mjs --tier: "no path-derived mandate", with the Clause-② SUSPECT hint onpackages/spec/src/**, judged from the card's content: the spec hunk corrects four migration entries' prose to the CLI's required--plan-file, no schema, no accept set)Clause-②: no
Responsibility: the risk is produced by
packages/metadata-protocolandpackages/metadata's legacy-organization read seam, left by PR feat(metadata-core,metadata-protocol)!: the sys_metadata family declares no organization column; indexes re-keyed (ADR-0131 D6/D7, C7b S2) #23469 (feat(metadata-core,metadata-protocol,runtime): #15211 S2+S5 — the sys_metadata family drops organization_id, and the v18 boot refusal lands with it (C7b, split for seat 1) #23429, C7b S2 + S5) as non-blocking in its PASS record 6184549574 | no platform path covers it:os serverefuses an unmigrated (v17-shape) database untilos migrate organization-ownershiphas verified, so no served door reaches these paths in a supported posture today | nobody reaches it on a supported boot; the migration ceremony and any future reader of the family off the served boot would (the card's own reach statement).Thread-read: none
Serial constraints cleared: PR feat(metadata-core,metadata-protocol)!: the sys_metadata family declares no organization column; indexes re-keyed (ADR-0131 D6/D7, C7b S2) #23469 (feat(metadata-core,metadata-protocol,runtime): #15211 S2+S5 — the sys_metadata family drops organization_id, and the v18 boot refusal lands with it (C7b, split for seat 1) #23429) is on
main(dd29bbe60d), so the body's staleBlocked-by: #23469line is removed in this stroke. metadata-protocol: over legacy object rows [package-less, Q], a draft save naming no package answers 200 into Q's draft, which no publish can serve: the save door's D9.9 check judges the request's package before the draft address resolves to Q #23712 (this seat, dispatched just before this claim) workssaveMetaItem's D9.9 call andunboundOwnerPackageRefusal, other regions ofprotocol.ts; whichever lands second mergesmain. Open PRs at this read (10) touch none of the files above. Claims in other lanes without a PR yet (domain:cli: cli/serve: with --no-server the ready banner still prints "API: http://localhost:PORT/" and an MCP connect URL, though no HTTP server is composed and nothing listens #23623, cli/serve --dev: an OS_DATABASE_URL whose scheme the CLI does not recognise is ignored in silence, and the boot serves an in-memory SQLite store instead of the database the operator named #23633, error-code provenance: the Hono doors and the runtime dispatcher stampUNIQUE_VIOLATIONas a literal inside a ternary thatcheck:error-code-provenancecannot see, and the ledger has no row for either package #23714): their surfaces are UNKNOWN to this seat; the dev lists the open PRs touching each file above before opening its own.Generated by Claude Code