Repository navigation
[Decision] Does cloud re-create the four consumer-less control-plane schemas, or does step 3 just delete them? (follow-on to the #16325 ruling) #16526
Description
Activity
Ruling recorded — option A: cloud does not host the four consumer-less files; step 3 deletes them (director seat, decision batch #77, 2026-09-07)
Maintainer reply, verbatim: 「其他同意」 — presented with A recommended.
Ruling. The #16325 ruling's "six files become the cloud repo's own declarations" is narrowed to the two files cloud consumes (
environment.zod,tenant.zod, as cloud#2037 did).developer-portal.zod,marketplace-admin.zod,app-store.zodandenvironment-package.zodare deleted with the./cloudsubpath in step 3 (#16325); recoverable from history (git show d5d8d50db:packages/spec/src/cloud/…). A schema nothing parses is not a contract, and moving it does not make it one. ⛔ Not B. C is not taken in this window: ifGET /cloud/environments/:environmentId/packagesshould have a declaration, that is an enforce card in cloud (declare what the route actually emits, settle thepackageId/package_iddouble), filed on its own merits, ⛔ not a rider on the move.Declared gap the maintainer did not name a counter-example for: no known external consumer of the
AppStoreListing/DeveloperPortal*/MarketplaceAdmin*families; the step-3 changeset (major on@objectstack/spec, already ruled) is the notice.needs-user-decision→pm:queue. #16325'sBlocked-byon this card is discharged.
Generated by Claude Code
Closing — the decision is made (option A) and this card carries no work of its own. Re-confirmed by the maintainer in a direct session.
Dispatching PM seat, session
session_f95e3874-e532-4748-a921-044aa2752a2b, 2026-09-10T08:2xZ.Two independent approvals of the same option, no conflict.
- Director seat, decision batch 🔗 Broken links detected in documentation #77, 2026-09-07T08:48Z (comment
5567942216) — maintainer verbatim: 「其他同意」, presented with A recommended. - This session, 2026-09-10, maintainer verbatim: 「同意 A」, given after being walked through the measurement below.
Why this card was still open, and why that mattered
Comment
5567942216states "#16325'sBlocked-byon this card is discharged" — but it left this card open withpm:queue. The unlock scan reads whether the target is CLOSED, not whether a comment says it is discharged. So #16325 carried an edge that was satisfied in prose and unsatisfied to the machine, while itself sitting inpm:queue. Closing it now makes the two agree.pm:queuewas also wrong on its own terms: this is a decision card whose decision is made and whose work belongs to #16325. It had no dispatchable work of its own, so a queue label advertised something that was not there.⇒ Closed
completed;pm:queuestripped in the same write;domain:specstays.Evidence gathered after the ruling, recorded because it is the reason A holds — not just that nobody consumes these
The original card argued A from zero consumers. Measured on cloud
origin/main559d0c0d(grep controls:sys_environment116 files,sys_package100,sys_package_version55,installPackageIntoEnvironment7 — so the zeros below are real absences):file what it declares what exists in cloud developer-portal.zod(338 lines)publisher profiles, release channels, publishing analytics nothing — every concept name 0 marketplace-admin.zod(322 lines)submission review, review decisions, featured listings, curated collections, policy violations, health metrics, trending ⭐ the review half was built — and built without this file (below). Featured / curated / policy / trending: nothing, and sys_marketplace/sys_listingdo not existapp-store.zod(413 lines)user reviews and ratings, recommendations, subscriptions, installed-app summaries nothing — sys_reviewdoes not existenvironment-package.zod(193 lines)installed packages per environment, install / upgrade / rollback ⭐ the capability is live ( sys_package_installationin 26 files,GET /cloud/environments/:environmentId/packagesis a real route) — implemented without this file⭐ The sharpest reading, and the one that settles it.
marketplace-admin.zoddeclaresReviewDecisionSchema. Cloud has two hits forReviewDecision— both are cloud's ownReviewDecisionResultinterface, declared locally atpackages/service-cloud/src/routes/package-review.ts:232, a name collision rather than a use. The marketplace review flow was genuinely built (marketplace-review-flow.ts,approveVersion/rejectVersion/withdrawVersionListing) and nobody looked at the declaration while building it.⇒ These are not "declared but not yet implemented". Two of the four describe capabilities that exist, and in both cases the implementation invented its own shapes. Not one of these files has ever constrained any code. Relocating a declaration that has never been a contract does not make it one — which is the argument for A, stronger than the consumer count that was originally offered.
⚠️ The gap this seat could not close, restated so it is not lost in the approval: these families are published today via the@objectstack/spec/cloudsubpath, and no measurement from inside these repos can see an external importer. The maintainer named no counter-example on either pass. The step-3 changeset (major on@objectstack/spec) is the notice.What happens now
Work moves to #16325 (step 3), whose three
Blocked-by:edges are now all closed: #16450 (merged 2026-09-07T08:19Z), objectstack-ai/objectui#8225 (merged 2026-09-07T17:15Z), and this card. ⛔ Option C is not taken in this window: ifGET /cloud/environments/:environmentId/packagesdeserves a declaration, that is an enforce card in cloud on its own merits — declare what the route really emits and settle thepackageId/package_iddouble — ⛔ not a rider on the move.- Director seat, decision batch 🔗 Broken links detected in documentation #77, 2026-09-07T08:48Z (comment
- added a commit that references this issue
on Sep 21, 2026
Narrow follow-on to the #16325 ruling (option B, director batch #62, comment
5563914257, maintainer verbatim 「同意」). Raised by the step-1 dev while implementing objectstack-ai/cloud#2037; ⛔ not self-adjudicated by the PM seat because answering it narrows the literal text of a ruling made the day before — that ruling says the six control-plane files "become the cloud repo's own declarations".Readings 2026-09-07T07:1xZ. objectstack
origin/maind5d8d50db, cloud branchclaude/issue-16450-cloud-owns-control-plane-contracts.The measurement that raises it
Of the six control-plane files the ruling moves, only two have any consumer in cloud:
environment.zodEnvironment,EnvironmentCredential,EnvironmentDriver,ProvisionEnvironment*,ProvisionOrganization*; incl. the runtime.parse()atenvironment-provisioning.ts:750tenant.zodTenantPlan(Schema),TenantRoutingConfig*,ProvisionTenant*,TenantDatabasedeveloper-portal.zodmarketplace-admin.zodapp-store.zodenvironment-package.zodFour files, ~1,266 lines, 90 exported symbols, measured by symbol name across the cloud repo — plus the
zero-consumer members of the two live files (
EnvironmentType(Schema),EnvironmentRole,EnvironmentMember,PackageInstallation(Status)Schema). cloud#2037 did not re-declare them and says so in its report.environment-package.zoddescribesGET /cloud/environments/:environmentId/packages, a live route. Dropping it leaves that route with nodeclaration anywhere — which is today's status quo in effect, since nothing parses it.
The question
The
./cloudsubpath is deleted from@objectstack/speceither way — that is already ruled. This asks onlywhether cloud re-creates a copy of the four.
@objectstack/specand live in the cloud repo? (upstream of #12036) #16325) deletes them; if one is everneeded it is recovered from history (
git show d5d8d50db:packages/spec/src/cloud/…). Zero dead code lands.own declarations". 1,266 lines nobody parses, kept green by tests pinning nothing the runtime does.
environment-package.zod(the one whose concept is live), after making it agree with whatGET …/packagesactually emits (packageIdandpackage_idfor one value). A small follow-up card.environment-package.zod描述的路由是活的,删掉它等于承认那条路由永远没有声明 —— 只是它今天本来就没有(没有任何代码解析它),所以 C 是新增工作而非防止倒退。AppStoreListingSchema存在,以为声明了就会被兑现,而运行时根本不看。这正是「声明即强制,绝不让 AI 声明一个运行时不兑现的能力」所禁止的形状,搬迁不改变它,只是让它换个仓继续存在。为 C 说话:那条活路由的同值双键(packageId+package_id)确实是个诱骗读错的形状。但修它属于 enforce,不属于 move —— 该单独立卡,不该塞进这次搬迁。推荐:A —— 不搬,step 3 直接删。 ①领起(没有解析器的声明不是契约);③指出搬迁不消除「声明不被兑现」只是换个仓;④按 enforce-or-remove 的既定答案办;②确认没有任何一方在等。⚠️ 这四个 schema 今天从
若选 C: 建议拆成 A + 一张独立的
environment-packageenforce 卡(让声明与GET …/packages的实际输出一致,含同值双键的处置),⛔ 不要塞进本次搬迁窗口 —— 那是 enforce 工作,与 move 混在一起会让两者都没法单独复核。⛔ 不荐 B。 它是四棱一致反对的唯一选项:零拉动、纯支出、把 declared≠enforced 原样换仓保存。
置信缺口: 本分析只量了 cloud 与 objectstack 两仓的消费。
@objectstack/spec/cloud公开发布,仓外消费者无法从这里测量 —— 若你知道有外部使用者依赖AppStoreListing/DeveloperPortal*/MarketplaceAdmin*这几族类型,A 的代价会变,请在回复里点名。Governing text:
AGENTS.mdPrime Directive #12 (contract-first); ADR-0049 enforce-or-remove; 维护者 2026-08-04「我们是一个创业项目,应该先专注于核心能力」.
Downstream
@objectstack/specand live in the cloud repo? (upstream of #12036) #16325 (step 3) cannot execute its deletion half until this is answered —Blocked-byadded there.told its dev ⛔ not to act on this question in that PR.
维护者速读
这是什么事 —— 你昨天裁的是「云控制面那六个 schema 文件搬去云端」。实施时量出来:六个里只有两个真的有人用,另外四个(开发者门户、市场后台、应用商店、环境已装包,合计约 1,266 行)在云端仓库里一次都没被引用过。
要你拍的只有一件事 —— 这四个文件从开源包里删掉是已经定了的,不用再问。现在问的只是:云端要不要照抄一份留着?
选项 —— A:不留,直接删(要用时从 git 历史里翻出来)。B:照抄留着(1,266 行没人解析的代码,靠一堆什么都验证不了的测试养着)。C:只留其中一个(「环境已装包」那个,因为它描述的接口是活的 —— 但那个接口今天本来就没人按它校验)。
我的意见 —— 推荐 A。一个没有任何代码去解析的 schema 不是契约,是长得像契约的注释;把它从一个仓搬到另一个仓,不会让它变成契约,只是换个地方继续误导人。如果你觉得 C 有道理,我建议拆开做:先按 A 删,再单独开一张卡去真正兑现那个接口的声明 —— 把"搬家"和"补契约"混在一次改动里,两件事都会没法单独验收。
你要做的 —— 选一个:A / B / C。