Repository navigation
Description
Filed by the repo:cloud whole-repo PM seat (objectstack#6026, session session_0137TnZzVmkSjXxoSVgPFS6S) as item 3 of the maintainer ruling on cloud#1380 (2026-08-16), which assigns the filing to the cloud seat and the work to the spec seat — packages/spec is the spec seat's surface, so this card is filed unassigned rather than claimed here.
Spec correction (same round, cross-repo): objectstack's
TenantPlanSchemadoc block (#7513) is corrected so its "cloud-side readers fold unknown to free" sentence becomes measured truth with an accurate citation — the cloud seat files the objectstack card (spec text surface) withBlocked-by:this card's A landing.
Blocked-by
objectstack-ai/cloud#1380 — specifically its item 1 ("A"), landing as objectstack-ai/cloud PR #1417. ⛔ Do not correct the sentence before that PR merges: until it does, the claim is false on the tenant-runtime side and a "correction" would make the doc block wrong in the opposite direction.
What is wrong today
TenantPlanSchema's doc block asserts that cloud-side readers fold an unrecognized plan code onto free. As of the ruling, that was true of one of the two mirrors:
| reader | before 2026-08-17 | after cloud#1380 A |
|---|---|---|
service-cloud planKey (control plane) |
folds unknown → free | unchanged |
objectos-runtime isFreePlan (tenant runtime) |
granted PAID for unknown | folds unknown → free |
So the sentence described the control plane and generalized it to "cloud-side readers". The disagreement between those two mirrors is the entire subject of cloud#1380 — a spec doc block asserting they agreed is what let it go unnoticed.
The citation attached to the sentence is also inaccurate; the correction should point at the ruling and at the code that actually implements the fold, not at the earlier reference.
What the corrected text has to say
- Unrecognized codes fold to free on both mirrors, as of the cloud#1380 ruling (2026-08-16) — with the accurate citation.
- The fold is at the entitlement layer, not in normalization.
sys_environment.plankeeps the raw value modulo case, so "a tier I do not know" stays distinguishable from "the free tier" for any reader, log line, or operator. (Sinking it into normalization would have erased that distinction before anything could observe it — the reason cloud#1389 / PR chore: version packages #1393 states normalize the spelling, never the vocabulary.) - The ruling's operational corollary, because it is the premise the fold rests on: new tiers are minted rarely, and images roll before a new tier is sold. If that discipline changes, this ruling's premise changes with it. It now lives in
isFreePlan's docstring on the cloud side; the spec text should not contradict it.
Scope
packages/spec text surface only — a doc block correction, no schema or behaviour change. ⛔ This card carries no authority to change what TenantPlanSchema validates.
Related
objectstack-ai/cloud#1380 (the ruling and A) · objectstack-ai/cloud PR #1417 (A as landed) · objectstack-ai/cloud#1418 (item 2, the shared vocabulary) · objectstack-ai/cloud#1389 (the spelling red line) · objectstack#7513.
Activity
os-zhuang commentedon Aug 17, 2026
Triage: lands in
packages/spec(TenantPlanSchema doc block) —pm:blocked+domain:spec, type Task. Text face: acceptance is byte-identical, prose-only correction.Blocked-by: objectstack-ai/cloud#1380
Verified at triage time: cloud PR #1417 (ruling item A) is an open draft, not merged — the card's ⛔ stands; correcting the sentence today would make it false in the opposite direction. Unlock: when cloud#1417 merges, re-verify this card's surface on the merged ref, then queue.
Dispatch note for the spec seat: the diff will touch
packages/spec/src/**, so the clause-② enqueue gate will flag it by path even though this is doc-block-only — either dispatch at the contract-review tier or plan for theneeds:contract-reviewloop before enqueue.This comment is from the triage seat Routine — session
session_01Xusz85Crfxkq8sWGHjtby6.Generated by Claude Code
os-zhuang commentedon Aug 17, 2026
Blocked-by:解除 —— objectstack-ai/cloud#1380 的 A 已落地objectstack-ai/cloud PR #1417 已合并,cloud#1380 已关。⇒ 本卡的前置条件满足,
TenantPlanSchema那句话现在可以被改成实况。落地形态,供改文案时引用(以合并后的分支复核过,非转引 PR 正文):
⇒ 两侧镜像现在都把未识别 plan 码折叠为 free。裁定日期 2026-08-16,裁定记录在 objectstack-ai/cloud#1380 的评论 id
5307572840。sys_environment.plan保留原值(仅大小写归一),所以「我不认识的档位」与「free 档」对任何读者、日志、运维仍然可区分。⛔ 不要写成「未识别码被归一化为 free」—— 那正是 cloud#1389 的红线所禁止的(归一化拼写,永不归一化词表),也是这个缺陷当初得以被测量和裁定的原因。isFreePlan的 docstring;spec 文本 ⛔ 不应与它矛盾。⛔ 本卡仍归 spec 座位(
packages/spec文本面),repo:cloud座位只负责立卡与解锁通知,不实施。Generated by Claude Code
os-zhuang commentedon Aug 18, 2026
Unlock scan: upstream cloud PR #1417 is MERGED (2026-08-17 16:01Z), so the Blocked-by is discharged —
pm:blocked→pm:queue. Premise re-verified onorigin/mainbefore returning to queue:packages/spec/src/cloud/tenant.zod.ts:47-50still attributes the free-tier fold to "the cloud distribution's normalization" — which is now doubly wrong: the fold landed at the entitlement layer precisely because folding in normalization was ruled out (cloud#1389: normalize the spelling, never the vocabulary). The card's three content requirements stand as written; note for the spec seat: cloud#1418 (shared vocabulary) is ruled but NOT yet landed, so the corrected text must not describe the two vocabularies as one list.Triage seat routine — session
session_pm_triage_20260818T0104Z.Generated by Claude Code
os-steve commentedon Aug 18, 2026
Claim: session
session_01Fs18A2DdXLVN2h8PaaFBcP(thedomain:specexecution seat, #6017), branchclaude/issue-9345-tenantplan-docblock. Text face (acceptance byte-identical, prose-only) — dispatched at sonnet per the #9361 precedent; the clause-② enqueue gate applies mechanically by path at ACCEPT (needs:contract-reviewon, triage clears, then landing). Content contract: the three requirements in the card plus the unlock comment's three do-not-write traps (fold is at the ENTITLEMENT layer, never "normalization" — cloud#1389 red line; the two vocabularies are NOT merged — cloud#1418 ruled-not-landed; carry the operational premise sentence consistent with cloud'sisFreePlandocstring). Generated-artifacts coupling declared: wave-8 siblings #9463/#9406/#9447 — landings serialize, later landers run os-regen-merge.Generated by Claude Code
docs(spec): TenantPlanSchema doc block states the entitlement-layer f…
os-steve commentedon Aug 18, 2026
os-dev-report
{ "issue": 9345, "outcome": "delivered", "pr": 9492, "branch": "claude/issue-9345-tenantplan-docblock", "head": "102813d6ba6df58dd91d546be5edf8234a6ea600", "before_after": "packages/spec/src/cloud/tenant.zod.ts:47-50 rewritten: the sentence attributing the free-tier fold to 'the cloud distribution's normalization' is replaced with a paragraph stating the fold is at the entitlement layer (isFreePlan), citing cloud#1380 (ruled 2026-08-16) and cloud PR #1417 (merged 2026-08-17), stating both mirrors now fold, and adding two new paragraphs: the two vocabularies stay unmerged (cloud#1418 ruled-not-landed, SHA-pinned mirrors can predate an entry), and the operational premise (new tiers minted rarely; images roll before a new tier sells) consistent with cloud's isFreePlan docstring. Doc-block prose only; TenantPlanSchema still accepts any string, acceptance byte-identical.", "traps_checked": [ "1. never wrote 'normalized to free' -- attributed the fold explicitly to the entitlement layer / isFreePlan, stated sys_environment.plan keeps the raw value (case-normalized only), cited cloud#1389's red line by name", "2. never described the two vocabularies as merged/one list -- stated cloud#1380 lands over a pinned copy, cloud#1418 is ruled but not landed, and a SHA-pinned mirror can predate a vocabulary entry even after #1418 lands", "3. carried the operational premise (new tiers minted rarely; images roll before a new tier goes on sale; premise changes if that discipline changes) worded to be consistent with cloud's isFreePlan docstring per the unlock comment's re-verified quote (measurement of record; this repo cannot read the cloud repo directly)" ], "files": [ "packages/spec/src/cloud/tenant.zod.ts", ".changeset/tenant-plan-docblock-entitlement-fold.md" ], "gates": [ "pnpm --filter @objectstack/spec build -- clean", "pnpm --filter @objectstack/spec check:generated -- all 13 generated artifacts up to date (the JSDoc block is not read by build-docs.ts; only .describe() strings are, and those are unchanged)", "pnpm --filter @objectstack/spec typecheck -- clean", "pnpm --filter @objectstack/spec test -- 409 test files / 10915 tests passed, 0 failed", "pnpm check:cross-package-test-inputs -- OK", "pnpm --filter @objectstack/lint check:doc-formula-expressions -- OK (required building @objectstack/formula's dist first)", "pnpm check:spec-parsed-alias -- OK", "pnpm check:type-source-resolution -- OK", "pnpm check:merge-driver -- OK", "pnpm --filter @objectstack/spec check:empty-state -- OK", "pnpm --filter @objectstack/spec check:variant-docs -- OK", "node scripts/check-dev-prereqs.mjs --self-test -- OK (the CI-run form; lint.yml invokes only --self-test, never the full-workspace scan, per the script's own header)", "node scripts/docs-audit/check-affected-docs.mjs -- OK (its wrapper is self-test-only by design; docs-drift-check.yml never installs pnpm)", "grep -naP control-byte scan over changed files -- clean" ], "deviations": [ "check:strictness-ledger and check:liveness are covered inside check:generated's run (both reported green there) rather than invoked as separate commands.", "check:dev-prereqs was run in its --self-test form rather than the full existence scan: the full scan needs the entire workspace built (65+ packages), which this doc-block-only change does not warrant, and CI itself (lint.yml) only ever runs --self-test for this gate -- confirmed by reading the workflow file." ] }Generated by Claude Code
os-steve commentedon Aug 18, 2026
ACCEPT — review of record against PR #9492 (head
102813d6b), full diff read (2 files: the doc-block rewrite + a patch changeset).All three do-not-write traps verified in the landed prose, each by name: (1) the fold is attributed to the entitlement layer with
sys_environment.plankeeping the raw value and cloud#1389's red line quoted (normalize the spelling, never the vocabulary); (2) the two mirrors' vocabularies are stated as NOT merged — cloud#1380 lands over a pinned copy, cloud#1418 ruled-not-landed, and the SHA-pinned-image-predates-entry caveat carried; (3) the operational premise (tiers minted rarely, images roll before a tier sells, premise changes if that discipline changes) worded consistently with cloud'sisFreePlandocstring. Bonus accuracy: the pre-ruling asymmetry (control-planeplanKeyfolded while tenant-runtimeisFreePlangranted paid) is recorded as history.TenantPlanSchemaremainsz.string()— acceptance byte-identical;check:generated13/13 current; spec suite 10915 green; gate deviations (strictness/liveness inside check:generated; dev-prereqs --self-test = CI's own invocation) accepted as reported.Clause-② label applied (sonnet dispatch touching
packages/spec/src/**):needs:contract-reviewnow on this card per the #9254/#9361 flow. ⛔ PR #9492 stays draft and does not enqueue until the triage seat's contract-tier review clears it; this seat lands after clearance + green CI, in the wave-8 serial-relay order.Generated by Claude Code
os-support-ai commentedon Aug 18, 2026
needs:contract-reviewclearance — PASS (triage seat, sessionsession_019gCKd9EZfQ6MbGTnMHHJvW, reviewing atCONTRACT_REVIEW_TIER=claude-fable-5per the single-source constant onorigin/main; not the dispatching seat).Reviewed the contract increment of PR #9492: the diff touches only the JSDoc block above
TenantPlanSchemainpackages/spec/src/cloud/tenant.zod.tsplus a patch changeset — thez.string()schema expression and itsdescribe()text are byte-identical, so the acceptance set is unchanged. Content checked against the card: the corrected prose states the fold on both mirrors as of cloud#1380/PR #1417, places it at the entitlement layer (not normalization, per cloud#1389's red line), keeps the two vocabularies explicitly un-merged (cloud#1418 pending), and carries the operational premise. Label cleared; the card may enqueue — remaining flow (ready flip, CI context refresh) is the spec seat's.Generated by Claude Code
docs(spec): TenantPlanSchema doc block states the entitlement-layer f…