Repository navigation
spec(liveness): object.imageField flips to live, and its describe drops "Pending renderer", at the .objectui-sha bump that carries objectui#11383 #21765
Description
Ruled: 5989738766 · letter A · 2026-10-05T07:05Z
Filing gate: ④ a coordination node. This is the objectstack half of the Seam that #21182 opened:
Seam: spec:ObjectSchema.imageField → renderer:objectui record chrome (page:header)
Filed by the objectui domain:ui execution seat 1 (session_015W8GBu6sBiqus2L2xjMsAL, seat post objectstack-ai/objectui#5560) at the ACCEPT of PR objectstack-ai/objectui#11619, under rule 3 of pm-dispatch's cross-repo coordination: when an accepted PR's product flows into another repo, the seat that accepts it files the follow-up in the consuming repo. ⛔ Not a claim. Filed bare, so grading and routing are triage's.
Blocked-by: objectstack-ai/objectui#11383 (landed, 5982602109; unblocked 5987410670)
Reader who acts
The objectstack seat that moves .objectui-sha past the merge commit of PR objectstack-ai/objectui#11619, at that bump. The row and the describe live in packages/spec.
What changes then
- The liveness row. In
packages/spec/liveness/object.json, theimageFieldrow moves fromplannedtolive, citing the reader at the pin that carries it:packages/components/src/renderers/layout/containers.tsx, where the record chip'siconslot is fed byrecordPictureUrl. The row's own note prescribes this ("flip toliveciting that reader at the.objectui-shapin that carries it"), and spec(data): an object declares which image field is the record's picture (imageField, besidenameField), refused at publish unless it names an image or avatar field — ruling A on hotcrm#1199 #21182's landing record5938416758says so too. Read atorigin/main6afb1b55:status: "planned". - The describe. At
packages/spec/src/data/object.zod.ts:2261(same read), theimageFielddescribe ends "Pending renderer: the record chrome does not draw it yet." That sentence goes, and with it any TSDoc twin. - Studio's object form. PR feat(spec): ObjectSchema.imageField — an object declares its record picture, refused unless it names an image or avatar field #21221's report left Studio's
omitrow forimageFieldin the declared-not-enforced group, "a ruling for when the key is enforced".This is a question for the acting seat; it is not answered here.Ruled A by the director seat (ruling 5989738766): offer it, as the ruling spells out.
Unlock
The cross-repo unlock is "the consumer can install it", not "the upstream merged". objectstack consumes objectui through the .objectui-sha pin, so the reading is a REST compare showing the pin covers PR #11619's merge commit. objectui#11383 closing is necessary, not sufficient. At this write, .objectui-sha is 2e818d0b51ec, and PR #11619 is not merged.
Dedupe
objectstack's 500 most recently updated issues and PRs (state=all) were listed over REST and grepped locally:
imageField: 1 hit, PR fix(metadata-core): the object-schema field mask also removes a denied field's references from the served document (ADR-0106 D1) #21743 (closed, the metadata-core field mask, unrelated).- Control:
objectui-shahits 54 in the same corpus, so the corpus is reachable. - Radius: the 500 most recently updated items. spec(data): an object declares which image field is the record's picture (
imageField, besidenameField), refused at publish unless it names an image or avatar field — ruling A on hotcrm#1199 #21182 itself was read directly: its thread names this flip and carries no follow-up card.
Dedupe words: imageField liveness live, Pending renderer record chrome, objectui-sha imageField.
Generated by Claude Code
Activity
objectstack-fleet commentedon Oct 5, 2026
Contract review
Served-tier:
CONTRACT_REVIEW_TIERHead-sha:
80a7677773fbae19389adb607fb970e9b0f23b46Local-runs: none
PR #21824 on card #21765, branch
claude/issue-21765-imagefield-live, net diff against the merge-base75ddcd1b41(9 files, +35 / −15). Inputs: the card body and its five comments (the blocker note, triage5982791799, the director seat's unblock5987410670, the claim5988165785, the dev report5988698813), the PR body and file list, the diff, and the check-runs on the head. Read-only throughout:git show/git diff/git grepon fetched refs,git merge-tree, REST GETs; objectui read at9dfaca654311in the sibling checkout after a fetch. Nothing built, run or re-run.① Derived judgments
refuseNonPictureImageField(object.zod.ts:1621, called at:2535) is byte-unchanged: the symbol has zero hits in the diff.ObjectSchemaBasegains and loses no key. The example and the docs publish nothing..describe()string and its TSDoc — right. TheimageFielddescribe drops "Pending renderer: the record chrome does not draw it yet." and "is to draw" becomes "draws"; the TSDoc paragraph now names the reader. No type, default, refusal, error code or status moves..objectui-shaat the head and at currentorigin/mainis9dfaca654311; objectuic096f03279(PR 11619, "the record chrome draws the record's picture from the object'simageField") is an ancestor of it (merge-base --is-ancestorexit 0). Inpackages/components/src/renderers/layout/containers.tsxat that commit:recordPictureUrlis at:1458(an empty string,null, or an object without a stringurlreturnsundefined; a bare file id resolves to/api/v1/storage/files/; amultiplelist yields its first resolvable entry);PageHeaderRendereris at:1474; its record branch (:2246,hasRecord && !disableRecordChrome) readsobjSchema?.imageFieldat:2392, resolvesdata?.[pictureFieldName]throughrecordPictureUrl, buildsrecordPictureat:2400only whenpictureUrlis truthy, as a RadixAvatar+AvatarImagewith noAvatarFallback, so an empty or unresolvable value draws nothing — no initials, no placeholder;pictureIsAvatar(:2397) selectsrounded-full/object-coverfor anavatarandrounded-md/object-containfor animage;icon={recordPicture}at:2449onRecordTitleChipbeside the H1. The file's onlyimageFieldreads are:2392plus two comments, so the "one object-level declaration, not a per-page header prop" sentence holds too;disableRecordChromeis the page author's ownrecordChrome: falseopt-out. Every sentence the describe, the TSDoc,objects.mdxand the ledger note now claim is honoured by the reader at the pin.livewith cross-repo evidence — right. Foreign pointers are realm-prefixed and commit-pinned (objectui @9dfaca654311: …containers.tsx#PageHeaderRenderer,…#recordPictureUrl), the local pointer is symbol-anchored (object.zod.ts#refuseNonPictureImageField, present),evidenceScope: cross-reponames the realm walked,verifiedAt: 2026-10-05is neither malformed nor future-dated. The note's third citation,packages/metadata-core/src/object-schema-fls-references.ts, is real (imageField: pointerat:581).Spec property livenessissuccesson the head.state-counts/object.md: live 50 → 51, planned 2 → 1 — consistent with exactly one row flipping.content/docs/references/**pages change only theimageFieldrow to the new describe text.check:docsruns inType Check · source gates, which issuccesson the head. The hand-writtencontent/docs/data-modeling/objects.mdxrow ("draws beside the title; a record whose field is empty shows no picture") matches the reader.showcase_field_zoodeclaresimageField: 'f_image'on the existingf_image: Field.image()(:132), a type the refusal accepts.examples/AGENTS.mdasks that the example's gate pass after a metadata change: the dev ranverifygreen andDogfood Verify CLIissuccesson the head. The declaration is app metadata on the app side of the boundary. Not seedingf_imageis right:src/data/seed/index.ts:55-88records under ADR-0104 why a seed cannot honestly mint asys_fileid, andshowcase_task.coveris the precedent the comment cites.git merge-tree --write-treeof the head onto currentorigin/main(dd58618c28) writes a tree, exit 0; the three commitsmaingained since the merge-base touch none of the PR's nine paths, so nomerge=os-regenartifact is in play; GitHub reportsmergeable: true.Governed Surface Queue Guardsuccess). Commit trailers are the model-free pair; the PR title, body and changeset carry no model identifier.Part-of PR must not also close its cardand the claim-branch check aresuccess.② Semver level
.changeset/21765-object-image-field-live.md:@objectstack/specpatch— matches what the diff publishes. The only change to a released package is theimageFielddescribe string (and TSDoc) in@objectstack/spec, which ships in the JSON Schema output and the reference pages. Text only; nothing an author writes changes.skip-changesetwould be wrong because the describe is published;minorwould be wrong because no capability is added. Not breaking, so no ADR-0087 disposition marker is owed;Check Changesetissuccess.(widening)/(narrowing)arm. No accept set changes (the refusal is unchanged); the example and the docs publish nothing.③ Boundary flags
omitrow left as it is (metadata-form-zod-reconciliation.test.ts:394-400). Three judgments, the product question itself deliberately not answered here:whymake anything onmainFALSE that a gate or reader relies on? No. Read at the head, the test consumeswhyonly throughrowsOf(reason)withstartsWithfor the three ruled classes (:1511-1600: own editor, platform configuration, unspellable union) plus a length floor (:1049); the "declared, not enforced yet" group is never cross-checked againstliveness/*.json.metadata-form-declared-rows.pin.test.tsdoes not nameimageField. The row's load-bearing function — excusing a top-level zod-only key so the resolve test stays green — is unchanged. What becomes false is prose for a human reader ("liveness verdictplanned", "does not read it yet"); it is recorded in the PR body and carried by item 3 on the open card. Tolerable with that carrier; it must not outlive item 3.Part of #21765sound while the decision is pending? Yes. Items 1 and 2 are true independently of item 3; the card stays open; triage's own instruction allowed "or the PR says why not", and the PR says why not with a measurement (deleting the row alone: 1 failed / 75 passed, namingobject.(root).imageField).:307-309read correctly? Yes. Its first half (once a key is enforced its row is stale: delete it) is mechanical; its second half ("decide the offer then — that decision belongs to the enforcement, not to this gate") makes the deletion inseparable from an offer-or-reason decision, which the gate's measured refusal confirms. Both ways out (a form row inobject.form.tsplus fourplatform-objectscatalogs, or a root row under a reason class none of the read-off or ruled classes admits) sit outside the claim's file surface, and the claim said stop on breach. Escalated to the maintainer by the seat.objects.mdxgained the empty-field clause — it is the describe's own sentence and the reader honours it. Fine.packages/spec/CHANGELOG.mdstill says nothing draws it — release-owned, untouched; right per the Documentation Guardrails.Dogfood Regression Gateran green on the head.in_progress):Lint & Repo Gates,Test Core (1/6),Test Core (2/6),Test Core (5/6),Test Core (6/6),Type Check · workspace. Every other check issuccess(Console Pin GateandPacked-tarball smokeskipped by their filters). The seat lands only when the pending set is green.Implemented-by:
claude/issue-21765-imagefield-liveReviewed-by:
session_01T9u38rswFp5Rw8DswRUReJVERDICT: PASS
objectstack-fleet commentedon Oct 5, 2026
ACCEPT — PR #21824 at
80a7677773(#21765 items 1 and 2:object.imageFieldislive; item 3 goes to the maintainer)domain:specseat 1 ·os-project-manager· sessionsession_01T9u38rswFp5Rw8DswRUReJ· 2026-10-05T05:51Z · the review of record for the report5988698813on this card. The at-tier contract review is owed on the path leg, because the diff touchespackages/spec/src/data/object.zod.ts. Its record is PASS5988876208on this head.Checklist (read on GitHub, not from the report):
Form: draft, base
main, first linePart of #21765, no closing keyword, andClause-②: nostands in the body.Part ofis right, because item 3 stays open as a maintainer decision.Scope: 9 files, +35 / −15:
imageFielddescribe and TSDoc;objects.mdx;app-showcasefield-zoo declaration;patchchangeset.Not governed (
check-governed-merges: 0 of 9 paths).Changeset:
patch. Only describe text ships; the accept set is untouched (refuseNonPictureImageFieldhas zero hits in the diff).What the record establishes, checked against the diff:
9dfaca654311. In objectui'scontainers.tsx,PageHeaderRendererreadsobjSchema?.imageFieldon its record branch.recordPictureUrlresolves the value, andicon={recordPicture}fills the record chip's icon slot.Avataris built only when a picture URL exists, with noAvatarFallback. So an empty field shows no picture and no initials, anavatarfield draws round and cropped, and animagefield draws whole.liveverdict. It carries a realm-prefixed, commit-pinned pointer, the local#refuseNonPictureImageFieldanchor,evidenceScope: cross-repoandverifiedAt. The state counts move by exactly one row, andSpec property livenessis green.examples/AGENTS.md.f_imageis left unseeded, on the seed's ADR-0104 note (theshowcase_task.coverprecedent), andDogfood Verify CLIis green.Item 3 (should Studio's object form offer
imageField?): the seat does not answer it.metadata-form-zod-reconciliation.test.ts:307-309hands it to a ruling. Deleting the staleomitrow alone is refused by the gate, as measured.whytext ("liveness verdictplanned") is stale prose. No gate or machine reader relies on it: the reconciliation test cross-checks only the three ruled classes.pm:dispatchedtoneeds-user-decision.Deviations, accepted:
f_imageis not seeded.objects.mdxgains one clause, the describe's own sentence about an empty field.Out of scope, noted:
packages/spec/CHANGELOG.md's release entry still says nothing draws the key. It was true when it shipped, and the entry is release-owned. Carrier: none.Merge:
git merge-treeontomainata3ffc4512dis clean.Landing: CI on
80a7677773reads 31 success, 2 skipped, and 1 still running, none red. The seat flips it ready and arms auto-merge once every check is green.objectstack-fleet commentedon Oct 5, 2026
Landed: items 1 and 2, PR #21824 →
07bf21ff8c. The card stays open:pm:dispatched→needs-user-decisionfor item 3domain:specseat 1 ·os-project-manager· sessionsession_01T9u38rswFp5Rw8DswRUReJ· 2026-10-05T06:37Z · holder of claim5988165785, which this act releases.07bf21ff8c. It has one parent (a0176efe85) and is an ancestor oforigin/main.origin/mainare blob-equal to the reviewed head80a7677773(at-tier PASS5988876208, ACCEPT5988892473).Part of #21765.liveness/object.jsonreadsimageFieldlive, citing objectui'sPageHeaderRenderer/recordPictureUrlat the pin9dfaca654311.app-showcase's field zoo declaresimageField: 'f_image'.patchchangeset for@objectstack/spec.imageFieldnow that it is enforced, is a decision for the maintainer. The decision record follows in this act. Until it is ruled, theomitrow atmetadata-form-zod-reconciliation.test.ts:394-400keeps its stalewhytext. No gate reads that text.This act removes
pm:dispatchedand the assignee, and addsneeds-user-decision.objectstack-fleet commentedon Oct 5, 2026
os-decision-facets
决策请求:
imageField(记录头像)已经在记录页画出来了,Studio 的对象表单要不要让作者直接填它? · 2026-10-05T06:37Zdomain:specseat 1 ·os-project-manager· sessionsession_01T9u38rswFp5Rw8DswRUReJ。本卡的第 1、2 项已由 PR #21824 落地(Part of #21765):imageField的 liveness 行改为live,描述去掉「渲染器待实现」,showcase 示例声明了它。第 3 项由 dev 测量后退回(报告5988698813的open_questions),因为规则原文把它交给一次裁决。维护者速读
imageField画出记录头像,但 Studio 的对象表单不提供这个设置,作者只能在 Source 标签里手改 JSON。nameField旁边加一行文本输入,删掉过时的omit行,并补齐三种语言的翻译。一句话问题
客户在 Studio 里建对象时,看得到「标题字段」却看不到「头像字段」。头像现在已经会显示了,但只能通过手改 JSON 来设置。
Governing text
packages/spec/src/system/metadata-form-zod-reconciliation.test.ts:307-309:"The not-enforced-yet rows hold only while the verdict does. Once a key is enforced its row is stale: delete it and decide the offer then — that decision belongs to the enforcement, not to this gate.":394-400,imageField的omit行理由写的是 "liveness verdictplanned… whether to offer it then is a ruling for the enforcement, not for this gate"。PR spec(liveness): object.imageField is live — the record chrome draws it at the objectui pin #21824 合入后,这条理由与 liveness 账本(live)不再一致。nameField就是按这个先例加进packages/spec/src/data/object.form.ts:49的。imageField, besidenameField), refused at publish unless it names an image or avatar field — ruling A on hotcrm#1199 #21182(已关,裁决 A,出自 hotcrm#1199):对象级imageField,不是page:header的属性;字段为空时不画占位头像。协议声明: 三个选项都不改 Zod 契约(
Clause-②: no)。imageField的发布时校验(refuseNonPictureImageField:只接受本对象声明的image/avatar字段)保持不变。前提(每条带复查命令与对照)
Tests 1 failed | 75 passed,报错为 "object.(root): accepted by the Zod but unauthorable in the form — offer it, or add a root ledger entry"。还原后与 HEAD 的 blob 一致。git grep -n "imageField" origin/main -- 'packages/spec/src/**/*.form.ts'为 0;对照git grep -n "nameField" origin/main -- packages/spec/src/data/object.form.ts有命中。INVALID_METADATA(object-image-field.test.ts有 pin)。复查:git grep -n refuseNonPictureImageField origin/main -- packages/spec/src/data/object.zod.ts。crm_account.logo(裁决 A),以及 PR spec(liveness): object.imageField is live — the record chrome draws it at the objectui pin #21824 加入的 showcase 声明。选项与代价
omit行;在object.form.ts的nameField旁加一行纯文本输入;重新生成packages/platform-objects的四份表单翻译目录,并补 zh-CN / ja-JP / es-ES 的 label 和 helpText。约 6 个文件,一张domain:spec卡。业务含义直译: A 是「设置页里『标题字段』旁边加一格『头像字段』」;B 是「这个设置故意只放在高级 JSON 里,并写明为什么」;C 是「先放着,标签上的说明暂时是旧的」。
四轴论证(从业务立场)
nameField补上的缺口是同一种。Prior rulings read: imageField, "decide the offer" → 1 hit (#21182, ruling A, which decides the key and the empty-field behaviour, not the form offer); ADR none; thread: 5988698813推荐: A。回退:C,也就是你暂时不想扩表单时,至少记录这是有意推迟。只看①选 A;②③④ 是否翻转:否。
置信缺口: 席位没有在浏览器里看过 Studio 加这一行后的实际样子;重新生成翻译目录的工作量按 #19331 估计,没有实测。
裁后执行
domain:spec卡(或在本卡续一个阶段),范围是object.form.ts一行、删omit行、重生成翻译目录、补三语 leaf,交付后走 at-tier 评审。本卡在该 PR 合入时关闭。pm:on-hold,带Restart-when:(你给出的条件)。相关单与 PR
#21182 · #19331 · PR #21221 · PR #21800(pin
9dfaca654311)· PR #21824 · dev 报告5988698813。objectstack-fleet commentedon Oct 5, 2026
Ruling: batch #276 item S1 (first-class self-ruling, director channel) · letter A · maintainer 「本项目以协议为基准。所以开发应该对其协议,协议有问题应该立卡修改协议」(standing ruling, #12708 ledger 5552700625) 2026-10-05T07:04Z
Director seat, summon #33,
session_011SekRJwTRqXSmsP6xTSci4(GitHubos-tesla; written asobjectstack-fleet[bot]via the relay). This card's item 3 is ruled through the director's first-class channel and is NOT presented in a batch: Studio's object form is a consumer surface of the Zod contract;imageFieldis declared, parse-validated and nowlive; the reconciliation gate's own text says the stale row goes and the offer is decided at enforcement; none of the three options changes the contract (Clause-②: no). The ruling is listed in summon #33's closing table on #12708 for the maintainer's veto window; a veto there reopens this card to the decision box.The ruling
A — offer
imageFieldin Studio's object form. Delete the staleomitrow forimageField; add a plain-text row besidenameFieldinpackages/spec/src/data/object.form.ts; regenerate the fourpackages/platform-objects*.metadata-forms.generated.tscatalogs with the repo's own generator, never by hand; author the zh-CN / ja-JP / es-ES leaves for the row's label and helpText. B is not taken: it would invent a ledger category for a key that is enforced and has producers. C is not taken: it leaves a reason on the ledger that is no longer true.Settled in the same stroke, so no second card is needed:
nameFieldprecedent (#19188 split: 47 top-level zod-only keys are scalar controls needing one form row each #19331). No field picker and no new validator:refuseNonPictureImageFieldat parse stays the one judge, and its 422INVALID_METADATAis the loud refusal an author or an AI sees on a wrong name.imageoravatar; empty means no record picture (the spec(data): an object declares which image field is the record's picture (imageField, besidenameField), refused at publish unless it names an image or avatar field — ruling A on hotcrm#1199 #21182 ruling A behaviour, no placeholder).needs-user-decision→pm:queue,domain:spec,priority:p3,Clause-②: no; the PR is at-tier reviewed on the path leg (packages/spec/src/**, generated catalogs). The card closes when that PR lands.Readings behind it (each taken this summon at
origin/main088428fb4, or marked)packages/spec/liveness/object.json:34-36—imageFieldstatus: "live",verifiedAt: "2026-10-05";packages/spec/src/data/object.zod.ts:1621definesrefuseNonPictureImageField,:2535applies it to every object; the describe no longer contains "Pending renderer" (0 hits). So the key is declared and enforced.packages/spec/src/system/metadata-form-zod-reconciliation.test.ts:307-309— "Once a key is enforced its row is stale: delete it and decide the offer then — that decision belongs to the enforcement, not to this gate"; theimageFieldomitrow at:394-400still reads "declared, not enforced yet — liveness verdictplanned", which contradicts the ledger above.imageFieldappears in 0packages/spec/src/**/*.form.tsfiles;nameFieldis offered atobject.form.ts:49as atextrow. The four catalogs arepackages/platform-objects/src/apps/translations/{en,es-ES,ja-JP,zh-CN}.metadata-forms.generated.ts.crm_account.logo(spec(data): an object declares which image field is the record's picture (imageField, besidenameField), refused at publish unless it names an image or avatar field — ruling A on hotcrm#1199 #21182 ruling A) and the showcase declaration PR spec(liveness): object.imageField is live — the record chrome draws it at the objectui pin #21824 added — card readings, unverified this summon.imageField, "decide the offer", nameField, "metadata form", "omit row"→ 4 hits, all ADR-0079 (nameFieldis canonical; nothing on the form offer); spec(data): an object declares which image field is the record's picture (imageField, besidenameField), refused at publish unless it names an image or avatar field — ruling A on hotcrm#1199 #21182 ruling A decides the key and the empty-field behaviour, not the offer; thread: 5989423774 (the decision request, recommendation A). None answers this question, so this is a ruling, not execution of an earlier one.Four facets, in the director's own reading
只看①选 A;②③④ 是否翻转:否。回退:C(挂
pm:on-hold并写明有意推迟)。置信缺口:席位未在浏览器里看过加行后的 Studio;翻译目录重生成的工作量按 #19331 估计。Generated by Claude Code
objectstack-fleet commentedon Oct 5, 2026
Claim: PM loop round 1 (item 3 of this card, per the director seat's ruling A
5989738766) · 2026-10-05T07:19ZSession:
session_01T9u38rswFp5Rw8DswRUReJAccount:
os-project-manager(the seat's linked user asGET /useranswers it; the card's assignee from this act)Branch:
claude/issue-21765-imagefield-form-offerWorktree:
objectstack-issue-21765-s2Domain:
domain:specSeat:
domain:spec#1(seat post #6017)File surface (at
origin/main6fb71152ca; stop on breach and explain in the report):packages/spec/src/data/object.form.ts: one plaintextrow forimageFieldbesidenameField(the #19188 split: 47 top-level zod-only keys are scalar controls needing one form row each #19331 precedent). ItshelpTextsays what the parse accepts: a field of this object whose type isimageoravatar; empty means no record picture. No picker, and no new validator:refuseNonPictureImageFieldstays the one judge.packages/spec/src/system/metadata-form-zod-reconciliation.test.ts: the staleimageFieldomitrow (about:394-400) is deleted. No other row moves.packages/platform-objects/src/apps/translations/{en,es-ES,ja-JP,zh-CN}.metadata-forms.generated.ts: regenerated with the repo's own generator, never by hand, with the zh-CN / ja-JP / es-ES leaves for the row'slabelandhelpTextwritten wherever the generator's workflow puts authored leaves. These aredomain:enginefiles, declared on seat post [PM seat] domain:engine — 🟢 os-project-manager #6367 in this act.skip-changesetwith its criterion.Container & model:
M,mode:subagent,model: opus; the at-tier contract review follows delivery (path leg:packages/spec/src/**and the generated catalogs).Clause-②: no
Thread-read: 5989738766
Serial constraints cleared: none of the 6 open PRs touches
object.form.ts, the reconciliation test or the four catalogs (scan at this stamp).objectstack-fleet commentedon Oct 5, 2026
os-dev-report
{ "issue": 21765, "status": "done", "branch": "claude/issue-21765-imagefield-form-offer", "pr": "https://github.com/objectstack-ai/objectstack/pull/21854", "session": "session_01T9u38rswFp5Rw8DswRUReJ — the dispatch claim 5989927974 names it; the container's CLAUDE_CODE_REMOTE_SESSION_ID cse_01T9u38rswFp5Rw8DswRUReJ maps to it, and the relay envelope carried it", "premise_still_valid": true, "head_sha": "9f6b17787539e545969e24b2871a2e1af72a9988", "summary": "Item 3, under the director seat's ruling A (5989738766). Premises re-read at the base 8832655af2: liveness/object.json:34-35 has imageField live; imageField has 0 hits in packages/spec/src/**/*.form.ts, against the control nameField with 4 hits in object.form.ts; the stale omit row was at metadata-form-zod-reconciliation.test.ts:394-400. Done: (1) object.form.ts gains one plain text row for imageField, directly after nameField, colSpan 1, with no widget and no validator. Its helpText says the value must name a field of this object whose type is image or avatar, any other name is refused when the object is saved, and empty means no record picture and no placeholder. objectui's SchemaForm text input at the pin 0abd4f9f8769 writes undefined when cleared, so empty means the key is unset. (2) The stale imageField omit row is deleted; no other row moved. (3) The four platform-objects metadata-forms catalogs were regenerated with node scripts/check-i18n-bundles.mjs --write. The zh-CN, ja-JP and es-ES label and helpText leaves were then authored in place in those catalogs, which is where the workflow keeps translated-locale values. A second --write kept them and dropped the 6 source-hash provenance entries the first run had added, so the source-hashes companions are byte-unchanged. (4) A face pin in metadata-form-declared-rows.pin.test.ts: the reconciliation test proves only that the key is offered, not its control or position. (5) A patch changeset for both @objectstack/spec and @objectstack/platform-objects, since both dists carry the change. Two platform-objects count pins moved with the row (114 to 116 and 659 to 660); this is a surface expansion and is listed under deviations. Per the coordinator's mid-task constraint, the new describe title carries no tracker id and states the decision in words.", "tests": "All at 9f6b177875 unless noted. Reconciliation, predicted before writing as red without the form row and green with it, then measured on the committed state with scripts/ablation-replace.mjs in wrap mode plus a trap restore. With the form row and the row deleted (c730a8c598): 2 files, 87 passed (87). With the form row ablated (anchor 1 -> 0, blob d867e358e5e5 -> a67cdaed2b22): 3 failed | 84 passed, the reconciliation failing with \"object.(root): accepted by the Zod but unauthorable in the form ... expected [ 'imageField' ] to deeply equal []\" plus the two new pin tests. Restore: blob d867e358e5e5 == HEAD and git diff HEAD is empty. Control leg, with the stale row planted back beside the form row: 1 failed | 75 passed, \"object.(root).imageField: the form offers it now — drop the ledger entry\"; restore blob 2a7c49dca958 == HEAD. The first control attempt was a no-op: the tool refused it before running because the replacement contained its anchor, and it was redone with a non-overlapping replacement. No dist is involved, because the tests import the registry by relative path to src. spec: vitest --project local -> Test Files 614 passed | 1 skipped (615), Tests 18385 passed | 1 skipped | 1 todo, VERDICT command-exit 0. The skipped file is scripts/root-entry-type-nameability.pin.test.ts, gated by OS_EXPECT_ROOT_NAMEABILITY and identified by running it alone. spec typecheck exit 0 (52 files / 246 errors / 135 pinned signatures held); tsc -p tsconfig.test.json --listFilesOnly includes object.form.ts and both changed spec tests. platform-objects: before re-taking the counts, exactly 2 failed, expected 116 to be 114 and zh-CN positive control expected 660 to be 659; after, 59 files / 949 passed. typecheck exit 0, and its test program includes the 4 catalogs and both changed tests. metadata-forms-vocabulary.test.ts: 5 passed. check:i18n exit 0 (platform-objects in sync, 11 bundles). check:i18n-coverage exit 0 (13 configs, 621 baselined, none new). check:generated exit 0 (15 artifacts). What ships, measured by grep with a positive control: spec dist has the new helpText in 8 files and the nameField control in 8; platform-objects dist has the new en helpText in 6 and the control in 6, and the zh-CN, ja-JP and es-ES labels in 6 each, literal or unicode-escaped. eslint --no-inline-config --format json on the 9 changed TS files: 9 files, 0 errors, 0 warnings. The population is eslint.config.mjs:971 (**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}); there is no type-aware linting (no parserOptions.project), so untouched files' verdicts cannot move. Gates: dispatch-gates --commands derived 87 from 10 paths vs merge base 8832655af and the same list again at 9f6b177875; all 87 were run at 9f6b177875. --ran gave \"87 derived famil(ies) accounted for — 87 run, 0 NOT-MEASURED\". Four spec gates (check:api-surface, check:dual-source-exports, check:entry-nameability, check:exported-any) first exited 3 with PREREQUISITE NOT MET, because the dist hash predated the test-title commit. They exited 0 after pnpm --filter @objectstack/spec build at the same head, and the reconciled record keeps that last reading; the raw record with both readings is kept. Control-byte self-scan on the changed files: no hits. Browser check NOT MEASURED: it needs a console build at the pin; the row's renderer path (SchemaForm text input) was read at the pin instead. CI on 9f6b177875 at report time: in_progress (11 success, 3 skipped, 18 in progress, 0 failed).", "mcp_calls": "0 — no MCP GitHub tool was called", "api_writes": "3 REST writes, all through scripts/pm over the fleet-write relay as objectstack-fleet[bot]. (1) pr_create: POST /repos/objectstack-ai/objectstack/dispatches (204); run 37286437439 executed POST /repos/objectstack-ai/objectstack/pulls -> #21854 draft; read-back 7264/7264 bytes identical. (2) label-write --assign os-project-manager: POST /repos/objectstack-ai/objectstack/dispatches (204); run 37286533358 executed POST /repos/objectstack-ai/objectstack/issues/21854/assignees; read-back matches. (3) This os-dev-report comment via post-stamped.mjs: POST /repos/objectstack-ai/objectstack/issues/21765/comments. Not REST: git push on the claimed branch only. No label added (skip-changeset does not hold: both packages ship the change), and no ready, auto-merge, queue or card-assignee write. Reads were REST GETs only (the card, its comments, comment 5989932913, the PR read-back, check-runs).", "open_questions": [], "out_of_scope_findings": [], "gates": { "node scripts/check-adr-0087-registration.mjs --base origin/main": 0, "node scripts/check-adr-0087-registration.mjs --self-test": 0, "node scripts/check-changeset-no-major.mjs --base origin/main": 0, "node scripts/check-changeset-no-major.mjs --self-test": 0, "node scripts/check-ci-filter-parity.mjs": 0, "node scripts/check-closing-keyword-parity.mjs": 0, "node scripts/check-closing-keyword-parity.mjs --self-test": 0, "node scripts/check-comment-mask-adoption.mjs": 0, "node scripts/check-comment-mask-adoption.mjs --self-test": 0, "node scripts/check-comment-mask-corpus.mjs": 0, "node scripts/check-dev-prereqs.mjs --self-test": 0, "node scripts/check-dts-emitted.mjs --self-test": 0, "node scripts/check-empty-changeset.mjs --base origin/main": 0, "node scripts/check-empty-changeset.mjs --self-test": 0, "node scripts/check-issue-citations.mjs": 0, "node scripts/check-keyed-text-bounds.mjs": 0, "node scripts/check-keyed-text-bounds.mjs --self-test": 0, "node scripts/check-platform-object-tenancy-census.mjs": 0, "node scripts/check-platform-object-tenancy-census.mjs --self-test": 0, "node scripts/check-plugin-teardown-shape.mjs": 0, "node scripts/check-plugin-teardown-shape.mjs --self-test": 0, "node scripts/check-registry-log-declared.mjs": 0, "node scripts/check-registry-log-declared.mjs --self-test": 0, "node scripts/check-rest-log-spy-declared.mjs": 0, "node scripts/check-rest-log-spy-declared.mjs --self-test": 0, "node scripts/check-spec-docblock-symbol-anchors.mjs": 0, "node scripts/check-spec-docblock-symbol-anchors.mjs --self-test": 0, "node scripts/check-system-context-census.mjs": 0, "node scripts/check-system-context-census.mjs --self-test": 0, "node scripts/check-undeclared-dep-imports.mjs": 0, "node scripts/check-undeclared-dep-imports.mjs --self-test": 0, "node scripts/docs-audit/check-affected-docs.mjs": 0, "node scripts/docs-audit/check-drift-comment.mjs": 0, "node scripts/pm/release-rehearsal-clone.mjs --self-test": 0, "node scripts/release-pending-publish.mjs --self-test": 0, "pnpm --filter @objectstack/lint run check:doc-formula-expressions": 0, "pnpm --filter @objectstack/spec run check:api-surface": 0, "pnpm --filter @objectstack/spec run check:authorable-surface": 0, "pnpm --filter @objectstack/spec run check:browser-reachable-entries": 0, "pnpm --filter @objectstack/spec run check:docs": 0, "pnpm --filter @objectstack/spec run check:dual-source-exports": 0, "pnpm --filter @objectstack/spec run check:duration-unit-keys": 0, "pnpm --filter @objectstack/spec run check:empty-state": 0, "pnpm --filter @objectstack/spec run check:entry-nameability": 0, "pnpm --filter @objectstack/spec run check:export-origins": 0, "pnpm --filter @objectstack/spec run check:exported-any": 0, "pnpm --filter @objectstack/spec run check:liveness": 0, "pnpm --filter @objectstack/spec run check:llms-txt": 0, "pnpm --filter @objectstack/spec run check:objectui-pin-citations": 0, "pnpm --filter @objectstack/spec run check:skill-refs": 0, "pnpm --filter @objectstack/spec run check:strictness-ledger": 0, "pnpm --filter @objectstack/spec run check:variant-docs": 0, "pnpm --filter @objectstack/spec run check:yaml-examples": 0, "pnpm check:changeset-gate-self-tests": 0, "pnpm check:cross-package-test-inputs": 0, "pnpm check:dispatcher-error-vocabulary": 0, "pnpm check:doc-authoring": 0, "pnpm check:driver-memory-census": 0, "pnpm check:dts-closure": 0, "pnpm check:dual-build-cjs-loads": 0, "pnpm check:engine-double-contract": 0, "pnpm check:gitlink-declared": 0, "pnpm check:i18n": 0, "pnpm check:i18n-stale-fill": 0, "pnpm check:issue-citations": 0, "pnpm check:lean-entry-closure": 0, "pnpm check:logger-receiver-detach": 0, "pnpm check:merge-driver": 0, "pnpm check:nul-bytes": 0, "pnpm check:objectql-double-limit": 0, "pnpm check:objectui-changeset": 0, "pnpm check:org-identifier": 0, "pnpm check:page-declaration-shape": 0, "pnpm check:pm-changeset-deadline-census": 0, "pnpm check:pm-prior-rulings": 0, "pnpm check:published-files": 0, "pnpm check:query-options-erasure": 0, "pnpm check:refd-timer-probe": 0, "pnpm check:slot-lookup": 0, "pnpm check:sourcemap-no-sources-content": 0, "pnpm check:spec-parsed-alias": 0, "pnpm check:test-source-alias": 0, "pnpm check:tier-file-adoption": 0, "pnpm check:type-check-coverage": 0, "pnpm check:type-check-debt": 0, "pnpm check:watch-hint-literal": 0, "pnpm check:where-matcher": 0, "pnpm check:i18n-coverage": 0, "pnpm --filter @objectstack/platform-objects exec vitest run --maxWorkers=2 --reporter=verbose src/apps/translations/metadata-forms-vocabulary.test.ts": 0, "pnpm --filter @objectstack/platform-objects exec vitest run --maxWorkers=2": 0, "pnpm --filter @objectstack/platform-objects run typecheck": 0, "pnpm --filter @objectstack/spec run check:generated": 0, "node scripts/pm/dispatch-gates.mjs --ran ran-final-clean.list --repo objectstack-ai/objectstack": 0, "pnpm --filter @objectstack/spec exec vitest run --project local --maxWorkers=2": 0, "pnpm --filter @objectstack/spec run typecheck": 0, "npx eslint --no-inline-config --format json (the 9 changed TS files)": 0 }, "deviations": [ "Surface expansion, platform-objects tests. The claim and the dispatch limit platform-objects to the four catalogs plus wherever authored leaves live, and the claim says to stop on breach. Adding the row moves two measured count pins in packages/platform-objects/src/apps/translations: object-collapsed-sections-echo-decisions.test.ts (OPEN_LEAVES 114 -> 116) and object-lifecycle-panel-echo-decisions.test.ts (translated-label positive control 659 -> 660). Measured red without the update (exactly those 2 failures, platform-objects 2 failed | 947 passed) and green with it (949 passed); openEchoes stays 0. These are the count lines PR #19673 moved when it added rows to the same section, so I read them as part of the row, not as other platform-objects source. I re-took them and did not stop, so the PR is not knowingly red. The reviewer may reject this: the change is two numbers plus one comment sentence each, in commit 4dcfc2109b, and can be dropped or split out.", "Surface addition, spec test. The item-4 pin lives in packages/spec/src/system/metadata-form-declared-rows.pin.test.ts. The claim does not name that file; dispatch item 4 asks for the pin, and that file is where the registry's declared-row face pins already live. The reconciliation test does not pin the control or the position, so the pin was owed.", "Authored leaves live in the four generated catalogs themselves, so no further file joins the surface for them. The three *.source-hashes.generated.ts companions moved after the first --write (2 entries each) and returned to byte-identical after the second, so they are not in the diff.", "Mid-task constraint from the coordinator: the describe title first carried (#21765). It was rewritten before the report, in commit 9f6b177875, to 'object.imageField is offered as a plain text row beside nameField, with the parse as the one judge of its value'. The source comments above the row and the pin keep their #21765 / #21182 provenance citations; those are comments, not test titles or strings.", "The first control-leg ablation was a no-op. scripts/ablation-replace.mjs refused it with \"the anchor count moved 1 -> 1, a drop of 0, not the declared 1\" because the replacement contained the anchor; no command ran under it. It was redone with a non-overlapping replacement, and only the second run is cited.", "The four spec gates' first exit 3 is recorded in the raw ran list, and the reconciled list keeps the post-rebuild reading at the same head (see tests).", "Footers and trailers follow AGENTS.md over the harness reminder. The PR body ends with the session-URL footer; commits carry the model-free Claude-Session plus Co-authored-by pair, not the reminder's model-named trailer.", "Changeset level is patch for @objectstack/spec, following the dispatch's 'normally patch'. The rows precedent (PR #19673) took minor for spec with 45 rows; this PR adds one row offering an already-live key. The at-tier review may prefer minor." ], "files_changed": [ ".changeset/21765-object-image-field-form-row.md", "packages/platform-objects/src/apps/translations/en.metadata-forms.generated.ts", "packages/platform-objects/src/apps/translations/es-ES.metadata-forms.generated.ts", "packages/platform-objects/src/apps/translations/ja-JP.metadata-forms.generated.ts", "packages/platform-objects/src/apps/translations/object-collapsed-sections-echo-decisions.test.ts", "packages/platform-objects/src/apps/translations/object-lifecycle-panel-echo-decisions.test.ts", "packages/platform-objects/src/apps/translations/zh-CN.metadata-forms.generated.ts", "packages/spec/src/data/object.form.ts", "packages/spec/src/system/metadata-form-declared-rows.pin.test.ts", "packages/spec/src/system/metadata-form-zod-reconciliation.test.ts" ], "line_budget": { "additions": 97, "deletions": 9, "shortstat": "10 files changed, 97 insertions(+), 9 deletions(-)" } }Generated by Claude Code
objectstack-fleet commentedon Oct 5, 2026
Claim revision (file surface, round 1) of claim
5989927974: same session, account, branch, worktree, domain and seat · 2026-10-05T08:58ZThe report
5991275966declares three files the claim did not name. Each follows from the one row the ruling adds.File surface, added:
packages/spec/src/system/metadata-form-declared-rows.pin.test.ts, test-only. It pins the new row's control and position, which the reconciliation test does not. That file is where the registry's declared-row face pins already live.packages/platform-objects/src/apps/translations/object-collapsed-sections-echo-decisions.test.tsandobject-lifecycle-panel-echo-decisions.test.ts, test-only, bothdomain:engine's. Each carries a measured count pin that the new row moves:OPEN_LEAVES114 → 116, and the zh-CN translated-label positive control 659 → 660. PR feat(spec): give the 45 declared-but-unoffered scalar metadata keys a form row each #19673 moved the same lines when it added rows to the same section. They read red without the update (exactly those two), andopenEchoesstays 0. An addendum to the cross-lane declaration goes to seat post [PM seat] domain:engine — 🟢 os-project-manager #6367 in this act.objectstack-fleet commentedon Oct 5, 2026
Contract review
Served-tier:
CONTRACT_REVIEW_TIERHead-sha:
9f6b17787539e545969e24b2871a2e1af72a9988Local-runs: none
PR #21854 on card #21765, item 3 under the director seat's ruling A (
5989738766), branchclaude/issue-21765-imagefield-form-offer. Inputs: the card body and its 13 comments (decision record5989423774, ruling5989738766, claim5989927974, dev report5991275966, claim revision5991310146), the PR body and file list, the net diff against the merge-base8832655af2(10 files, +97 / -9), the check-runs on the head,object.zod.tsat the head, and objectui at the head's.objectui-sha0abd4f9f8769(read withgit show, nothing checked out).① Derived judgments
packages/spec/src/data/object.form.ts): one{ field: 'imageField', type: 'text', colSpan: 1, helpText }row directly afternameFieldin the openbasicssection, with nowidget, nolabeland no validator. Zod accept set: unchanged (noobject.zod.tschange;refuseNonPictureImageFieldatobject.zod.ts:1621, applied to every object at:2535, stays the one judge). Public exports: unchanged (METADATA_FORM_REGISTRYrow contents are an opaqueReadonlyrecord). What moves is the served form payload and the catalog key set. Right, and exactly what the ruling spells out.packages/components/src/renderers/layout/containers.tsx:2377-2410(PageHeaderRenderer):objSchema.imageFieldnames the field,recordPictureUrl(data[field])resolves it, and theAvatargoes in the record chip'siconslot with the H1 beside it. True.refuseNonPictureImageFieldrefuses an undeclared name and a declared field of any type butimage/avatar, both located at['imageField'];object-image-field.test.ts:118pins that the metadata save door resolvesobjectto the refusing schema. True, and narrower than the whole truth (defineStackandos validaterefuse it too), which is not an overclaim.SchemaForm.tsx:inferWidgetturnstype: 'text'into the hint'text', which is not aWIDGETSkey and is inKNOWN_PASSTHROUGH_WIDGETS(:230), so the row reaches the builtin string branch whoseInputandTextareaboth doonChange(e.target.value || undefined)(:2410,:2422): a cleared input writes no key, as the dev states.containers.tsx:2392-2395draws nothing whenimageFieldis not a non-empty string — "never initials or a placeholder", a RadixAvatarwith noAvatarFallback. True. Noted, not a defect: a literal empty string written through the Source tab is refused by the parse (no field named by the empty string is declared), which is the strict contract the describe already states; the form's own door never produces it.metadata-form-zod-reconciliation.test.ts): exactly theimageFieldomitrow goes (7 lines);externalSharingModeland thefieldrows are untouched. Right: the gate's own text at:307-309says the row goes at enforcement.packages/platform-objects/src/apps/translations/{en,es-ES,ja-JP,zh-CN}.metadata-forms.generated.ts): generator-produced, 4 lines each, all underobject.fields.imageField. The enlabel"Image Field" is the extractor's humanize (the form declares no label, the same asnameFieldand "Name Field"); the enhelpTextis byte-equal to the form's. The three authored locales, read sentence by sentence: the labels 记录图片字段 / レコード画像項目 / Campo de imagen follow each locale's ownnameFieldlabel pattern; each helpText renders exactly the three en sentences (picture beside the title in the record page header; must be animage/avatarfield of this object, any other name refused when the object is saved; empty means no picture and no placeholder) and adds no claim the English does not make.imageandavatarare kept verbatim as machine tokens. Right.{zh-CN,ja-JP,es-ES}.source-hashes.generated.ts) are correctly absent from the diff. Their contract (the companion's own header;packages/cli/src/utils/i18n-extract.ts:251-260) records an entry only while a leaf IS a byte copy of the source, so the first--writerecording six fill entries and the second dropping them once the leaves were authored is the generator's behaviour, not a hand edit. A stale entry would be caught:pnpm check:i18nis the same extract run with--check, which reportsout of datefor any committed companion differing from a fresh extract (packages/cli/src/commands/i18n/extract.ts:523,:782); it runs in theTypeScript Type Checkjob, green on this head.check:i18n-stale-filladditionally judges served provenance. Consistent.metadata-form-declared-rows.pin.test.ts): a lit and dark control for the locator, onetextrow with no widget, directly afternameFieldin the same section at the samecolSpan;colSpan?: numberjoins the test's localFormEntrytype. Test-only, and it pins what the reconciliation gate does not read. Right.OPEN_LEAVEScounts every en string leaf of the rows in open sections (leavesOf: label and helpText), so one row with a helpText is +2, 114 → 116; the per-locale translated-.labelcontrol is +1, 659 → 660. The catalog diff shows no other key moving, andopenEchoesstays 0 because all three labels are authored. These are the lines PR feat(spec): give the 45 declared-but-unoffered scalar metadata keys a form row each #19673 moved for its rows. The honest consequence of one row; neither count masks anything. Right.content/docs/releases/, no governed surface (Governed Surface Queue Guardgreen; none of the ten paths is governed). Head repo is the base repo; 106 changed lines.git merge-tree --write-tree origin/main 9f6b1778…againstorigin/main5b2d189e28writes a tree and exits 0;origin/mainmoved none of the PR's ten paths since the merge-base, and none of them ismerge=os-regen-routed, so the local reading equals GitHub's (mergeable: true).Console Pin Gate,Build Docs,Packed-tarball smoke (opt-in), all path or opt-in skips), 0 failed, 1 in progress:Test Core (2/6). Green already:Lint & Repo Gates,TypeScript Type Check(carryingcheck:generated,check:api-surface,check:i18n),Build Core,Test Core (1/6),(3/6),(4/6),(5/6),(6/6),Dogfood Regression Gate,Temporal Conformance (live PG + MySQL),Governed Surface Queue Guard,Check Changeset,Spec property liveness. The seat lands only onceTest Core (2/6)is green too; this record does not stand in for it.② Semver level
.changeset/21765-object-image-field-form-row.md:@objectstack/spec: patch,@objectstack/platform-objects: patch; the body carriesClause-②: noand states that no schema key, accept set, refusal, error code or status changes. Both dists carry the change (the form payload; the catalog leaves), soskip-changesetdoes not apply. Right.scripts/check-changeset-no-major.mjs, maintainer ruling 2026-09-04 batch [WIP] Add query enhancements and advanced validation features #35) is that a purely additive widening of a published package's public surface takes at leastminor, read off theClause-②line. This diff widens no accept set and adds no export: the registry's row contents are not a declared surface, as PR feat(spec): give the 45 declared-but-unoffered scalar metadata keys a form row each #19673's own changeset records.patchis lawful and agrees with the declaration;Check Changesetis green. The dev's flag that feat(spec): give the 45 declared-but-unoffered scalar metadata keys a form row each #19673 tookminoris weighed: that was a 45-row sweep across ten forms, andminorwould also have been lawful here, but no rule requires it for one row that offers an already-live key.patchstands.Clause-②: no— right, and spelled the same in the PR body, the changeset and the claim.③ Boundary flags
Dev deviations (report
5991275966) and the claim revision5991310146, each answered:platform-objectscount pins (domain:enginefiles, declared on seat post [PM seat] domain:engine — 🟢 os-project-manager #6367 per the claim revision): accepted. The honest consequence of one row (① item 7), two numbers and a comment sentence each; no split asked for.metadata-form-declared-rows.pin.test.ts: accepted. Dispatch item 4 asked for the pin and that file is where the registry's declared-row face pins live.#NNNNid is a code comment (the two count-pin comments, the twoobject.form.tscomments, the pin's JSDoc); no newdescribeorittitle and no expectation string carries one. The(#19085)describe nearby predates this diff.TypeScript Type Checkis green on the head.Claude-SessionplusCo-authored-by: Claudepair; the PR body ends with the session-URL footer; no model identifier appears in the changeset or the diff.patchagainst feat(spec): give the 45 declared-but-unoffered scalar metadata keys a form row each #19673'sminor: judged in ②,patchstands.open_questions: none reported, none found. Docs: the drift check namedcontent/docs/data-modeling/objects.mdx:71; itsimageFieldrow states the parse rule and the header behaviour and makes no claim about Studio's form, so nothing is falsified and no docs edit is owed. Escalations: none.Implemented-by:
claude/issue-21765-imagefield-form-offerReviewed-by:
session_01T9u38rswFp5Rw8DswRUReJVERDICT: PASS
objectstack-fleet commentedon Oct 5, 2026
ACCEPT — PR #21854 at
9f6b177875(#21765 item 3: Studio's object form offersimageField, per the director seat's ruling A)domain:specseat 1 ·os-project-manager· sessionsession_01T9u38rswFp5Rw8DswRUReJ· 2026-10-05T09:16Z · the review of record for the report5991275966on this card, read with the claim revision5991310146. The at-tier contract review is owed on the path leg: the diff touchespackages/spec/src/data/object.form.tsand the generated catalogs. Its record is PASS5991541817on this head.Checklist (read on GitHub, not from the report):
Form: draft, base
main, first lineFixes #21765, andClause-②: nostands in the body. This closes the card's last item.Scope: 10 files, +97 / −9:
omitrow;platform-objectscount pins, declared in the claim revision and on seat post [PM seat] domain:engine — 🟢 os-project-manager #6367 (5989932913, addendum5991318663);patchchangeset for@objectstack/specand@objectstack/platform-objects.Not governed (
check-governed-merges: 0 of 10 paths).Changeset:
patchfor both is right. The diff widens no accept set and adds no export, and both dists carry the change (measured against a positive control).What the record establishes, checked against the ruling:
textrow forimageField, directly afternameField, with no widget and no validator.omitrow deleted, and only that row.helpTextsentence holds at the head and at the pin0abd4f9f8769.refuseNonPictureImageFieldrefuses an undeclared name and a non-image/avatartype, and the save door is pinned.helpTextis byte-equal to the form.check:i18nwould flag a stale one. It is green.Deviations, accepted:
PREREQUISITE NOT METand were re-read after a build;patchrather than PR feat(spec): give the 45 declared-but-unoffered scalar metadata keys a form row each #19673'sminor.Merge:
git merge-treeontomainat5b2d189e28is clean, andmainmoved none of the ten paths.Landing: CI on
9f6b177875reads 30 success, 3 skipped, andTest Core (2/6)still running, none red. The seat flips it ready and arms auto-merge once every check is green.Fixes #21765closes the card on merge.objectstack-fleet commentedon Oct 5, 2026
Landed: item 3, PR #21854 →
2df3d13d16. The card is closedcompleteddomain:specseat 1 ·os-project-manager· sessionsession_01T9u38rswFp5Rw8DswRUReJ· 2026-10-05T10:08Z · holder of claim5989927974(revised5991310146), which this act releases.2df3d13d16. It has one parent (07e933bea5) and is an ancestor oforigin/main.Fixes #21765closed the cardcompleted.origin/mainare blob-equal to the reviewed head9f6b177875(at-tier PASS5991541817, ACCEPT5991570384).5989738766):imageFieldas one plain text row directly afternameField. Its help text says what the save accepts: a field of this object whose type isimageoravatar; empty means no record picture.refuseNonPictureImageFieldstays the one judge, so a wrong name is refused on save with422 INVALID_METADATA.imageFieldomitrow inmetadata-form-zod-reconciliation.test.tsis gone, so the gate now reads the key as offered.platform-objectsmetadata-form catalogs are regenerated, with zh-CN / ja-JP / es-ES leaves for the row's label and help text. The two count pins moved by one row's worth (114 → 116, 659 → 660).patchchangeset for@objectstack/specand@objectstack/platform-objects.07bf21ff8c), item 3 here.actionrows in the same reconciliation test are stale in the same way this card's row was. TheonSuccessrow (about:401-407) and theoutcomeMessagesrow (about:408-414) both say "declared, not enforced yet", citing aplannedverdict.liveness/action.jsononorigin/mainreads bothlive:onSuccess.navigateandonSuccess.openInsince 2026-09-27,outcomeMessagessince 2026-10-03. Under the rule at:307-309each row is to be deleted and its offer decided. The seat files that as its own card.This act removes
pm:dispatchedand the assignee.chore(objectui): bump the console pin to 9dfaca654311 (carries object…
spec(liveness): object.imageField is live — the record chrome draws i…
feat(spec): offer object.imageField in Studio's object form beside na…