Skip to content

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

@objectstack-fleet

Unblocked: objectstack-ai/objectstack#21182 closed completed through PR objectstack-ai/objectstack#21221 (9969228626), and the fix is installable in @objectstack/spec 17.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 the Ruling: comment on hotcrm#1199. ⛔ Not a claim.

What to build

Unlock

  • This card is blocked on objectstack#21182 and on an installable @objectstack/spec release that carries imageField. objectui consumes the spec from npm, so the unlock check is the installed package accepting the key, not the upstream merge.
  • Probe at unlock time: the installed @objectstack/spec ObjectSchema parses { …, imageField: 'logo' } (logo being an image field) without an unknown-key refusal.

Acceptance

  • A pin over the record chrome: with imageField, the image renders from the row value; without it, the header is unchanged; with an empty value, nothing renders; with recordChrome: false, it is unchanged.
  • A changeset for the released package.
  • The Seam's acceptance on objectstack#21182 is this read: its liveness-ledger row leaves planned when this lands and the spec pin moves past it.
  • The first app reader is hotcrm#1199 (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_issues repo-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

Activity

  1. added
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    area:recordsBusiness objects, records, the views that show data, usable forms, search
    on Oct 1, 2026
  2. objectstack-fleet commented on Oct 1, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: pm:blocked → pm:on-hold. The upstream half landed, but it is not installable yet

    Triage 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/spec release that carries 9969228626 (PR objectstack-ai/objectstack#21221) is published on npm, and objectui resolves it. 17.5.0 does not (read at this write).


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 4, 2026

    @objectstack-fleet
    ContributorAuthor

    Hold released: pm:on-hold → pm:queue. The Restart-when: condition holds on the installed @objectstack/spec 17.6.0

    domain:ui execution 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 version answers 17.6.0.
    • objectui origin/main fd060f0767: pnpm-lock.yaml resolves @objectstack/spec only at 17.6.0 (2 entries, no other version).
    • REST compare/9969228626...617f25f8a (617f25f8a is the commit tag @objectstack/spec@17.6.0 points at): ahead 34, behind 0, so 9969228626 is in the 17.6.0 release.
    • Install-face probe, with @objectstack/spec installed from npm into a scratch directory at each version. 17.5.0 is the control, and shows the probe can fire:
      • data.ObjectSchema.safeParse of an object with a logo image field and imageField: 'logo': 17.5.0 refuses it (Unrecognized key(s) on this object: \imageField`); **17.6.0 accepts** it and keeps imageField: "logo"`.
      • Control in both versions: the same object with a bogus key imageFieldBogus is 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. 5938525466 predicted that 17.6.0 would not carry 9969228626, 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 ObjectSchema accepts imageField") is the one run above. The card returns to the domain:ui queue.


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 4, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: 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 (the page:header record branch, which resolves the title from nameField today), 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 and QUICK_REFERENCE.md) and the three pm:dispatched cards (objectui#11610, #10202, #8347) by their claims; none touches this surface.

    Why Clause-②: no: the renderer reads imageField, a key the installed @objectstack/spec 17.6.0 already publishes and judges at parse (liveness row object.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

  5. objectstack-fleet commented on Oct 4, 2026

    @objectstack-fleet
    ContributorAuthor

    os-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)'; full pnpm 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 closure pnpm --filter \"@object-ui/components^...\" build then pnpm --filter @object-ui/components type-check at 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

  6. objectstack-fleet commented on Oct 4, 2026

    @objectstack-fleet
    ContributorAuthor

    Seat answers to the dev's two open questions on PR objectui#11619 · patch round · file surface amended

    domain:ui execution seat 1 @ objectui · session_015W8GBu6sBiqus2L2xjMsAL (os-steve) · 2026-10-04T15:59Z. ⛔ Not a new claim: claim 5980934061 stands, 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.

    1. The second URL resolution (recordPictureUrl vs @object-ui/fields' readFileValue) → option C. Keep the private copy, and add a test-only parity pin in @object-ui/fields: render page:header over a value corpus covering every read form, and assert that the drawn src equals what readFileValues(value)[0].url resolves. 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 below fields, so option B's new @object-ui/core export has no measured pull. A red test turns silent drift into a loud failure at no cost to the public surface.
    2. 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 an imageField. 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 under packages/fields/src/ (the parity pin) and content/docs/layout/page-header.mdx. Clause-②: no is unchanged: no export, prop, type member or i18n key.


    Generated by Claude Code

  7. objectstack-fleet commented on Oct 4, 2026

    @objectstack-fleet
    ContributorAuthor

    os-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 name type-check (not typecheck), after pnpm --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 it readFileValues(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]?.url answers '' 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

  8. objectstack-fleet commented on Oct 4, 2026

    @objectstack-fleet
    ContributorAuthor

    os-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.tsx keeps 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

  9. objectstack-fleet commented on Oct 4, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT: PR objectui#11619, head 1a13128

    domain:ui execution seat 1 @ objectui · session_015W8GBu6sBiqus2L2xjMsAL (os-steve) · 2026-10-04T16:59Z. Reviewed against GitHub and origin/main, not against the report. There were two patch rounds after the seat's answers in 5981856796.

    Checklist

    • Shape: draft, base main, first line Fixes #11383, Clause-②: no at 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/fields parity pin (test only), content/docs/layout/page-header.mdx, and the changeset. Nothing under content/docs/releases/.

    • Changeset: @object-ui/components: minor, a new visible capability. Its sentences were checked against recordPictureUrl and 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 imageField and the record's value for that field is not empty") matches the code: pictureUrl resolves only from the declared field's value, and nothing is drawn otherwise.

    • Contract faces: none. objectui check-governed-queue-guard.mjs --test answers NOT GOVERNED for all 5 paths. Clause-②: no holds: there is no export, prop, type member or i18n key, and RecordTitleChip's icon slot 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_PATH v1 → v2) went red on exactly the three bare-id cases and was restored. The installed 17.6.0's imageField refusal half was measured (undeclared name, text/file field and bogus key all refused). CI on 1a13128 was 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's aria-hidden slot), 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 readFileValues entry that has a url, as ImageCellRenderer draws it. The literal [0]?.url in my order would have been wrong for a list led by an empty entry.
    • The type-check spelling: my order's typecheck would 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:

    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

  10. objectstack-fleet commented on Oct 4, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed: PR objectui#11619 → main c096f03, verified by content

    domain:ui execution seat 1 @ objectui · session_015W8GBu6sBiqus2L2xjMsAL (os-steve) · 2026-10-04T17:30Z.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:recordsBusiness objects, records, the views that show data, usable forms, searchdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpriority:p2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions