Repository navigation
record chrome draws the record's picture from the object's imageField in the record page header — the renderer half of objectstack#21182 (ruling A on hotcrm#1199) #11383
Description
Activity
- addeddomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatobjectui ui stream: fix lands on the published library or apps — objectui execution seatarea:recordsBusiness objects, records, the views that show data, usable forms, searchBusiness objects, records, the views that show data, usable forms, search
on Oct 1, 2026 objectstack-fleet commented
on Oct 1, 2026 ContributorAuthorMore actionsTriage:
pm:blocked→pm:on-hold. The upstream half landed, but it is not installable yetTriage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-01T19:03Z. ⛔ Not a claim, ⛔ not a dispatch.Restart-when: an
@objectstack/specrelease that carries9969228626(PR objectstack-ai/objectstack#21221) is published on npm, and objectui resolves it. 17.5.0 does not (read at this write).- 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 objectstack#21182 closedcompletedat 2026-10-01T18:56Z, landed by PR feat(spec): ObjectSchema.imageField — an object declares its record picture, refused unless it names an image or avatar field objectstack#21221. The cross-repo unlock keys on the install face, not on the merge, as this card's own Unlock section says. 9969228626is not in the current head of chore: version packages objectstack#20639 (the 17.6.0 release PR), so 17.6.0 cut from that head would not carry it. The line names the commit, not a version number, for that reason.- At the restart, the card's own probe runs first: the installed
ObjectSchemaacceptsimageField.
Generated by Claude Code
- spec(data): an object declares which image field is the record's picture (
objectstack-fleet commented
on Oct 4, 2026 ContributorAuthorMore actionsHold released:
pm:on-hold→pm:queue. TheRestart-when:condition holds on the installed@objectstack/spec17.6.0domain:uiexecution seat 1 @ objectui (seat post #5560) ·session_015W8GBu6sBiqus2L2xjMsAL(os-steve) · 2026-10-04T14:04Z. ⛔ Not a claim, ⛔ not a dispatch.The condition is the
Restart-when:line of the latest transition comment,5938525466.Readings at this write:
npm view @objectstack/spec versionanswers17.6.0.- objectui
origin/mainfd060f0767:pnpm-lock.yamlresolves@objectstack/speconly at17.6.0(2 entries, no other version). - REST
compare/9969228626...617f25f8a(617f25f8ais the commit tag@objectstack/spec@17.6.0points at):ahead 34, behind 0, so9969228626is in the 17.6.0 release. - Install-face probe, with
@objectstack/specinstalled from npm into a scratch directory at each version. 17.5.0 is the control, and shows the probe can fire:data.ObjectSchema.safeParseof an object with alogoimagefield andimageField: 'logo': 17.5.0 refuses it (Unrecognized key(s) on this object: \imageField`); **17.6.0 accepts** it and keepsimageField: "logo"`.- Control in both versions: the same object with a bogus key
imageFieldBogusis refused, so the schema is still closed.
- Release double-check ②: the card's timeline shows no merged PR referencing it after
5938525466.
Correction to two earlier readings.
5938525466predicted that 17.6.0 would not carry9969228626, because the commit was not in the release PR's head at that moment. That head moved before the release was cut. The seat post's later lines ("waits on a release newer than 17.6.0") repeated the prediction without re-measuring it. The installed package is the reading, and it carries the key.The card's own unlock probe ("the installed
ObjectSchemaacceptsimageField") is the one run above. The card returns to thedomain:uiqueue.
Generated by Claude Code
objectstack-fleet commented
on Oct 4, 2026 ContributorAuthorMore actionsClaim: PM loop round 1
Session:session_015W8GBu6sBiqus2L2xjMsAL
Account:os-steve
Branch:claude/issue-11383-record-chrome-image
Worktree:objectui-issue-11383
Domain:domain:ui
Seat:domain:ui#1
File surface:packages/components/src/renderers/layout/containers.tsx(thepage:headerrecord branch, which resolves the title fromnameFieldtoday), the tests beside it, and.changeset/11383-*.md(stop on breach; explain in the report)
Container & model:M,mode:subagent,model: default tier(dispatch-gates --tier --repo objectstack-ai/objectui: no path-derived mandate; floor sonnet · default opus · ceiling fable)
Clause-②: no
Thread-read: 5980846960
Serial constraints cleared: none, read 2026-10-04T14:14Z: the four open objectui PRs (objectui#11614, #11607, #11600 the release PR, #11069) were read in full (29, 202, 101 and 15 files; the release PR touches only changesets, CHANGELOGs, manifests andQUICK_REFERENCE.md) and the threepm:dispatchedcards (objectui#11610, #10202, #8347) by their claims; none touches this surface.Why
Clause-②: no: the renderer readsimageField, a key the installed@objectstack/spec17.6.0 already publishes and judges at parse (liveness rowobject.imageField:planned, carrier this card). No@object-ui/*export, prop, type member or i18n key is added, and the dispatch fences that: a route that needs one stops and reports.
Generated by Claude Code
objectstack-fleet commented
on Oct 4, 2026 ContributorAuthorMore actionsos-dev-report
{
"issue": 11383,
"status": "done",
"branch": "claude/issue-11383-record-chrome-image",
"pr": "#11619",
"session": "session_015W8GBu6sBiqus2L2xjMsAL (dispatched subagent; the parent seat's id)",
"premise_still_valid": true,
"summary": "page:header's record chip now draws the record's picture in the existing RecordTitleChip icon slot, from objectSchema.imageField and the served row's value. It is a Radix Avatar + AvatarImage with no AvatarFallback, so there are no initials and no broken-image icon. Nothing is drawn, and the header markup equals the undeclared header's, for no declaration, an empty value, an absent (masked) field, or recordChrome false. No page:header prop and no conventional key is read. Zone 2 #3 is falsified as a reuse route: the resolver objectui already has (readFileValue in @object-ui/fields) cannot be imported from @object-ui/components because fields depends on components, and moving it to core would add a core export (Clause-2 fence). So containers.tsx carries a small private recordPictureUrl that covers exactly the spec's read forms: expanded {url}, a bare sys_file id via isFileIdToken to the storage path, a URL string, and the first drawable entry of a list. It is labelled in code as a second resolution; consolidating it is open question 1. Landing site as expected: packages/components/src/renderers/layout/containers.tsx.",
"tests": "New pin packages/components/src/tests/page-header-record-picture-11383.test.tsx (13 cases, real SchemaRenderer + registry). At 711adb9: 'Tests 13 passed (13)'; fullpnpm exec vitest run packages/components/gave 'Test Files 358 passed | 1 skipped (359) / Tests 3643 passed | 24 skipped', exit 0. At merged head 4a34ea4 (origin/main 2abec3a merged), the same set ran as --shard=1/2 + --shard=2/2 because a single run nears the 10-minute foreground cap: 'Test Files 180 passed (180) / Tests 1754 passed' and 'Test Files 178 passed | 1 skipped (179) / Tests 1889 passed', exit 0 / 0. That is 359 files and 3643 tests, matching the pre-merge run, and the new file is in that set. A separate single-file rerun at 4a34ea4 was NOT MEASURED: queue-timeout exit 99 twice, with the lock held by another agent's app-shell run. Deps closurepnpm --filter \"@object-ui/components^...\" buildthenpnpm --filter @object-ui/components type-checkat 4a34ea4: exit 0, both tsc projects. --listFiles counts 1 for the new test in tsconfig.test.json and 1 for containers.tsx in tsconfig.json. The first type-check, before deps were built, exited 2 with TS2307 cannot find @object-ui/core: a prerequisite failure, not a red gate. Lint at 4a34ea4: exit 0, '0 errors'; no warning on a changed line (the only nearby hits sit on the pre-existing PageHeaderRenderer declaration). Ablations, all run on committed code via objectstack scripts/ablation-replace.mjs; each mutation was proven on disk (anchor 1 -> 0, blob changed) and each restore by 'blob == HEAD and git diff HEAD is empty'. (1) Deleting 'icon={recordPicture}': '6 failed | 7 passed'; every positive pin went red and the 7 'nothing drawn' controls stayed green. (2) Changing imageField to 'objSchema?.imageField ?? logo': '1 failed'; the conventional-key control went red. (3) 'pictureFieldName ? (' in place of 'pictureUrl ? (': '5 failed'; every empty-value markup-equality control went red. The direction was as expected in all three. Spec probe on the installed 17.6.0 ObjectSchema.safeParse: image and avatar are accepted; an undeclared name is REFUSED ('declares no field'); text and file are REFUSED ('which is not a picture'); the control key imageFieldBogus is REFUSED as unrecognized. So the PM's unverified refusal half holds.",
"mcp_calls": "0",
"api_writes": "3 relayed writes as objectstack-fleet[bot], each carried by one POST /repos/objectstack-ai/objectstack/dispatches: (1) pr_create POST /repos/objectstack-ai/objectui/pulls (draft, read back 9491 bytes sent = 9491 stored); (2) label-write assign POST /repos//issues/11619/assignees (os-steve; read back MATCHES); (3) post-stamped POST /repos//issues/11383/comments (this report). Plus git push of the branch (3 pushes: empty probe, 711adb9, 4a34ea4). Reads only otherwise: REST GET issue 11383 + comments, GET pulls/11619, GET /rate_limit.",
"gates": [
{
"gate": "pnpm exec vitest run packages/components/",
"head": "711adb9",
"exit": 0
},
{
"gate": "pnpm exec vitest run packages/components/ --shard=1/2",
"head": "4a34ea4",
"exit": 0
},
{
"gate": "pnpm exec vitest run packages/components/ --shard=2/2",
"head": "4a34ea4",
"exit": 0
},
{
"gate": "pnpm exec vitest run packages/components/src/tests/page-header-record-picture-11383.test.tsx",
"head": "711adb9",
"exit": 0
},
{
"gate": "same single file at merged head",
"head": "4a34ea4",
"exit": "NOT MEASURED (queue-timeout 99 x2; covered by the shards)"
},
{
"gate": "pnpm --filter "@object-ui/components^..." build && pnpm --filter @object-ui/components type-check",
"head": "4a34ea4",
"exit": 0
},
{
"gate": "pnpm --filter @object-ui/components lint",
"head": "4a34ea4",
"exit": 0
},
{
"gate": "check:new-line-citations",
"head": "711adb9",
"exit": 0
},
{
"gate": "check:control-bytes",
"head": "711adb9",
"exit": 0
},
{
"gate": "check:phantom-deps",
"head": "711adb9",
"exit": 0
},
{
"gate": "check:changeset-claims",
"head": "4a34ea4",
"exit": 0
},
{
"gate": "check:pending-changeset-literals",
"head": "4a34ea4",
"exit": 0
},
{
"gate": "check:unreferenced-sources",
"head": "4a34ea4",
"exit": 0
},
{
"gate": "check:test-path-roots",
"head": "4a34ea4",
"exit": 0
},
{
"gate": "node scripts/check-changeset-no-major.mjs",
"head": "4a34ea4",
"exit": 0
},
{
"gate": "node scripts/check-changeset-presence.mjs",
"head": "711adb9 tree",
"exit": 0
},
{
"gate": "check:spec-floors",
"head": "-",
"exit": "NOT MEASURED: needs every released package's dist; direct reading instead: isFileIdToken is exported by @objectstack/spec/data at 17.0.0 (npm tarball d.ts + mjs), the components floor"
},
{
"gate": "check:eager-closure",
"head": "-",
"exit": "NOT MEASURED: needs the console production build"
}
],
"files_changed": [
".changeset/11383-record-chrome-image.md (+5, @object-ui/components minor)",
"packages/components/src/tests/page-header-record-picture-11383.test.tsx (+233)",
"packages/components/src/renderers/layout/containers.tsx (+87)"
],
"line_budget": "n/a: no skills/** and no governed surface touched (Tier: not governed)",
"deviations": [
"Zone 2 #3 (reuse the existing resolution) falsified by the package graph: @object-ui/fields depends on @object-ui/components, and the core move breaches the Clause-2 fence. So a private, labelled second resolution lives in containers.tsx (recordPictureUrl). It is narrower than readFileValue: an object with no url is not drawn. See open question 1.",
"Zone 3 suggested the record title as the picture's accessible name. Instead the picture is decorative (alt empty, inside the chip's aria-hidden icon slot), because the H1 beside it already names the record and a titled image would read the name twice.",
"The dispatch and the PM heads-up spell the script 'typecheck'; @object-ui/components names it 'type-check'. A 'typecheck' filter matches no script, so 'type-check' was run.",
"Components tests at the merged head ran as two shards rather than one run (the single run took 569s against the ~600s foreground cap).",
"The merge commit message was amended before its first push, to carry the model-free trailer pair. No pushed history was rewritten."
],
"open_questions": [
{
"question": "The header's picture URL resolution is a second copy of readFileValue (in @object-ui/fields), and nothing pins the two together. Should they be consolidated?",
"options": [
"A: keep the private copy (as landed). Cost: silent drift if the storage path or the read forms move.",
"B: move fields' file-value module down into @object-ui/core, have fields re-export it, and have page:header import it. This gives one resolver, but adds public core exports (a Clause-2 yes card).",
"C: keep the copy and add a test-only parity pin in @object-ui/fields that renders page:header over a value corpus and compares the drawn src with readFileValues(value)[0].url (no export; outside this claim's file surface)."
],
"recommendation": "C, by the four axes. Business need: there is one real consumer (hotcrm#1199 crm_account.logo) and no second one below fields, so B's new core surface has no measured pull. Long-term: B is the single-source shape, and C keeps the drift visible until a second consumer justifies B. AI-error: C turns a silent divergence into a red test, while A leaves it silent. Startup focus: C costs one test file and no public surface. Take B only when a further package below fields needs the resolver."
},
{
"question": "content/docs/layout/page-header.mdx (Layout, the record-chip bullet) lists the chip's parts without the picture, and AGENTS.md #2 asks docs to move with the code. The file is outside the claim's declared surface, so it was not edited.",
"options": [
"A: amend the claim's surface and add one clause to the record-chip bullet on this PR as a patch round: '..., and the record's picture when the object names an imageField'.",
"B: a docs-only follow-up after landing."
],
"recommendation": "A: it is a one-line change, docs should land with the behaviour, and the PR stays in one package's docs plus source."
}
],
"out_of_scope_findings": [
"carrier: 承接者:无 · noted, not filed. RecordDetailPanel (@object-ui/plugin-detail) renders DetailView's own heading, not page:header, so the record side panel draws no imageField picture. The spec describe says 'one object-level declaration every record detail page reads'. Not measured in a running app, and the card scopes the change to page:header. Dedupe words: DetailView imageField record panel picture.",
"carrier: the objectstack .objectui-sha pin-bump follow-up (PM-filed, per dispatch Zone 2 #4) · noted, not filed. The @objectstack/spec imageField describe still reads 'Pending renderer: the record chrome does not draw it yet.' and should move with the liveness row object.imageField."
]
}
Generated by Claude Code
objectstack-fleet commented
on Oct 4, 2026 ContributorAuthorMore actionsSeat answers to the dev's two open questions on PR objectui#11619 · patch round · file surface amended
domain:uiexecution seat 1 @ objectui ·session_015W8GBu6sBiqus2L2xjMsAL(os-steve) · 2026-10-04T15:59Z. ⛔ Not a new claim: claim5980934061stands, and this amends its file surface.Both questions fall in the classes a seat answers without escalation: verification strategy, and docs that lag the code. Neither changes product behaviour or a public contract.
- The second URL resolution (
recordPictureUrlvs@object-ui/fields'readFileValue) → option C. Keep the private copy, and add a test-only parity pin in@object-ui/fields: renderpage:headerover a value corpus covering every read form, and assert that the drawnsrcequals whatreadFileValues(value)[0].urlresolves. The one deliberate divergence (an id-only object, which the header does not draw) is asserted as a divergence, not skipped. Why: there is no second consumer belowfields, so option B's new@object-ui/coreexport has no measured pull. A red test turns silent drift into a loud failure at no cost to the public surface. content/docs/layout/page-header.mdx→ option A. On this PR, add one clause to the record-chip description: the record's picture shows when the object names animageField. The docs move with the behaviour.
File surface, amended:
packages/components/src/renderers/layout/containers.tsx, its tests,.changeset/11383-*.md, plus one test file underpackages/fields/src/(the parity pin) andcontent/docs/layout/page-header.mdx.Clause-②: nois unchanged: no export, prop, type member or i18n key.
Generated by Claude Code
- The second URL resolution (
objectstack-fleet commented
on Oct 4, 2026 ContributorAuthorMore actionsos-dev-report
{
"issue": 11383,
"status": "done",
"branch": "claude/issue-11383-record-chrome-image",
"pr": "#11619",
"session": "session_015W8GBu6sBiqus2L2xjMsAL (dispatched subagent; the parent seat's id)",
"premise_still_valid": true,
"summary": "Patch round per seat comment 5981856796 (Q1 -> C, Q2 -> A), pushed as e2df897 on top of 4a34ea4. (1) Added a test-only parity pin, packages/fields/src/widgets/file-value.recordChromeParity-11383.test.tsx, with no export and no fields source change. It renders page:header through the real SchemaRenderer + registry over every read form the header admits: expanded {url}, a legacy blob that has a url, a bare sys_file id, absolute and relative URL strings, a data: URI, lists led by each of those, lists whose first drawable entry follows empties, and 7 empties. Each case asserts that the drawn src equals the URL the image cell draws, or that neither side draws. The id-only object is asserted as an explicit DIVERGENCE case: fields resolves it to /api/v1/storage/files/ID and the header draws nothing. (2) Added one clause to the Record chip bullet of content/docs/layout/page-header.mdx: the record's picture shows beside the heading when the object names an imageField and the record's value for it is not empty. The PR body was not touched. It is now stale in two places (see deviations), and the seat should carry these additions into it.",
"tests": "At e2df897. Parity pin + components pin + the two tests that read page-header docs (scripts/tests/extract-mdx-demos.test.ts, examples/schema-catalog/test/pageheader-with-actions.test.tsx) in one run: 'Test Files 4 passed (4) / Tests 67 passed (67)', exit 0. The parity pin has 19 cases: 11 drawn, 7 empty, 1 divergence. Ablation on committed code via objectstack scripts/ablation-replace.mjs: RECORD_PICTURE_FILE_PATH changed from '/api/v1/storage/files/' to '/api/v2/storage/files/' in containers.tsx. The mutation landed (anchor x1 -> x0, blob 3f3532a4 -> a63151a5). The parity pin went 'Tests 3 failed | 16 passed (19)', red on exactly the three bare-id cases ('Expected: "/api/v1/storage/files/f_abc123" Received: "/api/v2/storage/files/f_abc123"', plus f_first and f_after). Restore was proven by 'blob after restore 3f3532a4 == blob at HEAD 3f3532a4, git diff HEAD empty'. Fields package by the root spelling,pnpm exec vitest run packages/fields/: 'Test Files 234 passed | 1 skipped (235) / Tests 3666 passed | 7 skipped', exit 0. Fields type-check under its real script nametype-check(nottypecheck), afterpnpm --filter \"@object-ui/fields^...\" build(11 projects): exit 0, both tsc projects. tsconfig.test.json --listFilesOnly counts 1 for the parity file. eslint on the parity file: exit 0. Docs gates: check:doc-types 0, check:doc-fences 0, check:doc-example-ids 0, check:doc-example-readers 0. check:doc-snippets and check:doc-examples are NOT MEASURED (exit 2, 'THE GATE COULD NOT RUN — the packages these examples import are not built'). Both type-check TypeScript code blocks across about 34 packages' dist; the docs edit is prose inside a bullet, outside every fenced block, so their subject is untouched. CI owns them. Also check:new-line-citations 0, check:control-bytes 0, check:phantom-deps 0, check:test-path-roots 0, check:changeset-claims 0, check:pending-changeset-literals 0, check-changeset-presence 0 ('3 source file(s) of 2 released package(s) changed ... declares 1 changeset'). The previous round's components suite (359 files / 3643 tests at 4a34ea4) and components type-check / lint stand: this round changed no components file. origin/main 9db9ff3 merges with no conflict (git merge-tree exit 0), so it was not merged again, as instructed.",
"mcp_calls": "0",
"api_writes": "This round: 1 relayed write, the post-stamped POST /repos//issues/11383/comments (this report), carried by one POST /repos/objectstack-ai/objectstack/dispatches as objectstack-fleet[bot]. Plus 1 git push (4a34ea4..e2df897). No PR body PATCH, no label or assignee write. Reads: REST GET comment 5981856796, git fetch.",
"gates": [
{
"gate": "pnpm exec vitest run (parity pin + components pin + extract-mdx-demos + pageheader-with-actions)",
"head": "e2df897",
"exit": 0
},
{
"gate": "ablation RECORD_PICTURE_FILE_PATH v1 -> v2, parity pin",
"head": "e2df897",
"exit": "1 as intended (3 failed | 16 passed), restored blob == HEAD"
},
{
"gate": "pnpm exec vitest run packages/fields/",
"head": "e2df897",
"exit": 0
},
{
"gate": "pnpm --filter "@object-ui/fields^..." build && pnpm --filter @object-ui/fields type-check",
"head": "e2df897",
"exit": 0
},
{
"gate": "eslint packages/fields/src/widgets/file-value.recordChromeParity-11383.test.tsx",
"head": "e2df897",
"exit": 0
},
{
"gate": "check:doc-types",
"head": "e2df897",
"exit": 0
},
{
"gate": "check:doc-fences",
"head": "e2df897",
"exit": 0
},
{
"gate": "check:doc-example-ids",
"head": "e2df897",
"exit": 0
},
{
"gate": "check:doc-example-readers",
"head": "e2df897",
"exit": 0
},
{
"gate": "check:doc-snippets",
"head": "e2df897",
"exit": "NOT MEASURED (prerequisite: unbuilt packages; prose-only edit outside code fences)"
},
{
"gate": "check:doc-examples",
"head": "e2df897",
"exit": "NOT MEASURED (prerequisite: unbuilt packages; prose-only edit outside code fences)"
},
{
"gate": "check:new-line-citations",
"head": "e2df897",
"exit": 0
},
{
"gate": "check:control-bytes",
"head": "e2df897",
"exit": 0
},
{
"gate": "check:phantom-deps",
"head": "e2df897",
"exit": 0
},
{
"gate": "check:test-path-roots",
"head": "e2df897",
"exit": 0
},
{
"gate": "check:changeset-claims",
"head": "e2df897",
"exit": 0
},
{
"gate": "check:pending-changeset-literals",
"head": "e2df897",
"exit": 0
},
{
"gate": "node scripts/check-changeset-presence.mjs",
"head": "e2df897",
"exit": 0
}
],
"files_changed": [
".changeset/11383-record-chrome-image.md (+5, @object-ui/components minor; unchanged this round)",
"packages/components/src/tests/page-header-record-picture-11383.test.tsx (+233; unchanged this round)",
"packages/components/src/renderers/layout/containers.tsx (+87; unchanged this round)",
"packages/fields/src/widgets/file-value.recordChromeParity-11383.test.tsx (+162, NEW this round: test-only parity pin)",
"content/docs/layout/page-header.mdx (+2 -1, NEW this round: record-chip bullet names the picture)"
],
"line_budget": "n/a: no skills/** and no governed surface touched (Tier: not governed)",
"deviations": [
"Comparator: the order and my earlier option C spell itreadFileValues(value)[0]?.url. The pin compares with the first readFileValues view that has a url, which is the filter ImageCellRenderer applies through displayableImagesOf. Taken literally,[0]?.urlanswers '' for a list led by an undrawable entry (for example ['', {url}]), and the cell itself draws the second entry, so the literal spelling would make the 'first drawable entry after empties' cases false failures. My open question 1 text was imprecise on this point.",
"Placement: the pin sits beside the module it pins, at packages/fields/src/widgets/ (inside the amended surface 'one test file under packages/fields/src/').",
"The PR body (written once) is now stale in two places. The seat should carry: (a) in '## Acceptance notes', the Docs bullet is now done; replace it with 'content/docs/layout/page-header.mdx: the record-chip bullet names the picture (imageField)'. (b) In '## Tests', add the parity pin 'packages/fields/src/widgets/file-value.recordChromeParity-11383.test.tsx (19 cases; ablation RECORD_PICTURE_FILE_PATH v1 -> v2 gave 3 failed | 16 passed, restored blob == HEAD)'. In '## Measured premises' item 3, the sentence 'Nothing pins the two together ... Consolidating them is an open question' should become 'the parity pin in @object-ui/fields keeps them together (seat ruling 5981856796, option C)'. The source comment on recordPictureUrl in containers.tsx still says 'Nothing pins the two together (AGENTS.md #9)'. That is now false, but containers.tsx was not edited this round because the order did not list it. A one-line comment fix pointing at the parity pin is owed: the seat can add it, or send a second patch round.",
"The changeset still names only @object-ui/components. The fields file is a test (no shipped change), and check-changeset-presence passes on the existing changeset."
],
"open_questions": [],
"out_of_scope_findings": [
"carrier: 承接者:无 · noted, not filed. RecordDetailPanel (@object-ui/plugin-detail) renders DetailView's own heading, not page:header, so the record side panel draws no imageField picture. Not measured in a running app. Dedupe words: DetailView imageField record panel picture.",
"carrier: the objectstack .objectui-sha pin-bump follow-up (PM-filed) · noted, not filed. The @objectstack/spec imageField describe still reads 'Pending renderer: the record chrome does not draw it yet.'"
]
}
Generated by Claude Code
objectstack-fleet commented
on Oct 4, 2026 ContributorAuthorMore actionsos-dev-report
{
"issue": 11383,
"status": "done",
"branch": "claude/issue-11383-record-chrome-image",
"pr": "#11619",
"session": "session_015W8GBu6sBiqus2L2xjMsAL (dispatched subagent; the parent seat's id)",
"premise_still_valid": true,
"summary": "Patch round 2: one comment sentence. In the recordPictureUrl docblock in packages/components/src/renderers/layout/containers.tsx, 'Nothing pins the two together (AGENTS.md #9): a change to either has to be made in both.' now reads: 'packages/fields/src/widgets/file-value.recordChromeParity-11383.test.tsxkeeps the two resolutions together (seat ruling 5981856796, option C), and a change to either still has to be made in both.' Nothing else is touched (+4 -2, comment only). New head: 1a13128, pushed e2df897..1a13128. The PR body was not edited.",
"tests": "At 1a13128. Components pin + fields parity pin in one run: 'Test Files 2 passed (2) / Tests 32 passed (32)', exit 0.pnpm --filter @object-ui/components lint: exit 0, '972 problems (0 errors, 972 warnings)', the same count as round 1. No warning on a changed line; the only hits near the edit are the pre-existing PageHeaderRenderer declaration's, shifted by 2 lines. Also check:new-line-citations 0 and check:control-bytes 0.",
"mcp_calls": "0",
"api_writes": "1 relayed write: post-stamped POST /repos//issues/11383/comments (this report), carried by one POST /repos/objectstack-ai/objectstack/dispatches as objectstack-fleet[bot]. Plus 1 git push (e2df897..1a13128). No PR body edit.",
"gates": [
{
"gate": "pnpm exec vitest run packages/components/src/tests/page-header-record-picture-11383.test.tsx packages/fields/src/widgets/file-value.recordChromeParity-11383.test.tsx",
"head": "1a13128",
"exit": 0
},
{
"gate": "pnpm --filter @object-ui/components lint",
"head": "1a13128",
"exit": 0
},
{
"gate": "check:new-line-citations",
"head": "1a13128",
"exit": 0
},
{
"gate": "check:control-bytes",
"head": "1a13128",
"exit": 0
}
],
"files_changed": [
"packages/components/src/renderers/layout/containers.tsx (+4 -2 this round, comment only)"
],
"line_budget": "n/a: no skills/** and no governed surface touched",
"deviations": [],
"open_questions": [],
"out_of_scope_findings": []
}
Generated by Claude Code
objectstack-fleet commented
on Oct 4, 2026 ContributorAuthorMore actionsACCEPT: PR objectui#11619, head
1a13128domain:uiexecution seat 1 @ objectui ·session_015W8GBu6sBiqus2L2xjMsAL(os-steve) · 2026-10-04T16:59Z. Reviewed against GitHub andorigin/main, not against the report. There were two patch rounds after the seat's answers in5981856796.Checklist
-
Shape: draft, base
main, first lineFixes #11383,Clause-②: noat the start of its own line. The body has no other closing keyword. -
Scope: 5 files, all inside the claim's surface as amended in
5981856796:containers.tsx, its pin, the@object-ui/fieldsparity pin (test only),content/docs/layout/page-header.mdx, and the changeset. Nothing undercontent/docs/releases/. -
Changeset:
@object-ui/components: minor, a new visible capability. Its sentences were checked againstrecordPictureUrland the record branch:- the four read forms;
- "nothing drawn" for no declaration, an empty value or a masked field;
recordChrome: false;- no prop and no conventional key.
All hold. The fields file is a test, so it owes no changeset.
-
Docs prose (seat-checked): the record-chip bullet's new clause ("with the record's picture beside the heading when the object names an
imageFieldand the record's value for that field is not empty") matches the code:pictureUrlresolves only from the declared field's value, and nothing is drawn otherwise. -
Contract faces: none. objectui
check-governed-queue-guard.mjs --testanswers NOT GOVERNED for all 5 paths.Clause-②: noholds: there is no export, prop, type member or i18n key, andRecordTitleChip'siconslot already existed. -
Evidence: the components pin has 13 cases, with three ablations, each red in the predicted direction and restored. The parity pin has 19 cases; its ablation (
RECORD_PICTURE_FILE_PATHv1 → v2) went red on exactly the three bare-id cases and was restored. The installed 17.6.0'simageFieldrefusal half was measured (undeclared name,text/filefield and bogus key all refused). CI on1a13128was in progress at this write. Landing waits for every check on the head to be green.
Deviations accepted:
- The picture is decorative (
alt=""in the chip'saria-hiddenslot), because the H1 beside it already names the record. My Zone 3 suggested otherwise, and that suggestion was optional. - The parity comparator takes the first
readFileValuesentry that has a url, asImageCellRendererdraws it. The literal[0]?.urlin my order would have been wrong for a list led by an empty entry. - The
type-checkspelling: my order'stypecheckwould have run nothing.
The PR body was rewritten by the seat, because the dev writes it once. Three stale passages were updated: the premise-3 sentence, the parity pin added under Tests, and the Docs acceptance note marked done. The duplicated footer was reduced to one. It was read back identical, 10,186 bytes.
Out-of-scope findings:
- The record side panel (
RecordDetailPanel) draws no picture. → Acceptance notes: not measured in a running app, and the card scopes this topage:header. - The objectstack describe "Pending renderer…" and the liveness row
object.imageField. → filed spec(liveness):object.imageFieldflips tolive, and its describe drops "Pending renderer", at the.objectui-shabump that carries objectui#11383 objectstack#21765 (a ④ coordination node,Blocked-by: objectstack-ai/objectui#11383), for the seat at the.objectui-shabump that carries this PR.
Landing: not governed. Once every check on the head is green, the seat marks it ready and arms auto-merge through the merge queue.
Generated by Claude Code
-
objectstack-fleet commented
on Oct 4, 2026 ContributorAuthorMore actionsLanded: PR objectui#11619 →
mainc096f03, verified by contentdomain:uiexecution seat 1 @ objectui ·session_015W8GBu6sBiqus2L2xjMsAL(os-steve) · 2026-10-04T17:30Z.-
Merged through the merge queue as squash commit
c096f03(one parent,6e9090c), an ancestor oforigin/main. -
Content check against the first parent:
reading 6e9090cc096f03function recordPictureUrlincontainers.tsx0 1 icon={recordPicture}incontainers.tsx0 1 const PageHeaderRenderer(control)1 1 the @object-ui/fieldsparity pin existsno yes imageFieldincontent/docs/layout/page-header.mdx0 1 -
The card closed
completedthrough the PR'sFixesline. It was the only issue closed in that window.pm:dispatchedis removed in this stroke. -
Downstream: spec(liveness):
object.imageFieldflips tolive, and its describe drops "Pending renderer", at the.objectui-shabump that carries objectui#11383 objectstack#21765 (the liveness flip and the describe) is now waiting only on objectstack's.objectui-shacoveringc096f03. A note is posted there. The object-aware scan surfaces 14 more inert fields, 5 of them masked by a shared name — a second enforce-or-remove ledger hotcrm#1199'scrm_account.logoreader gets the picture once that pin moves.
Generated by Claude Code
-
Unblocked: objectstack-ai/objectstack#21182 closed completed through PR objectstack-ai/objectstack#21221 (
9969228626), and the fix is installable in@objectstack/spec17.6.0 (hold released in the comment below).Filed by the director seat, summon #32, objectstack-ai/objectstack
session_016tKoy8NJa35Yih1FdzrVmn, as the renderer half of the maintainer's ruling A on objectstack-ai/hotcrm#1199. The ruling is batch #261 item 3, maintainer 「其他四张同意」; the record is theRuling:comment on hotcrm#1199. ⛔ Not a claim.What to build
imageField(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 objectstack#21182). The chrome lives inpage:header'sPageHeaderRenderer,packages/components/src/renderers/layout/containers.tsx, the record branch at about:2157–:2194onmain8001068b9c.recordChrome: falsekeeps today's bare header.page:headerprop and no private fallback key (logo,avatar,image, …) read by name. The object declaration is the only channel.Unlock
@objectstack/specrelease that carriesimageField. objectui consumes the spec from npm, so the unlock check is the installed package accepting the key, not the upstream merge.@objectstack/specObjectSchemaparses{ …, imageField: 'logo' }(logo being animagefield) without an unknown-key refusal.Acceptance
imageField, the image renders from the row value; without it, the header is unchanged; with an empty value, nothing renders; withrecordChrome: false, it is unchanged.plannedwhen this lands and the spec pin moves past it.crm_account.logo), which waits on this card.Lane
domain:ui, level S–M,mode:subagent,Clause-②: no(it reads a key the spec publishes; no objectui export changes).Dedupe:
mcp__github__search_issuesrepo-scoped, open and closed, 「record header image avatar logo record chrome page header」 → 2 hits (#10499, #7281), both closed and unrelated: title masking and width arbitration.Generated by Claude Code