You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
plugin-detail: the record page's Details tab draws a declared referenceVia pointer's type half (object_name) as its own row of stored API name, beside the card that names the same object by its label #13102
Filing gate ①, class (a): a user-visible machine name with a named producer on a served surface. Found by objectstack-ai/objectstack#24611's dev (PR objectstack-ai/objectstack#24698, open question 1; a static reading of objectui at objectstack's pin 12dc7b47c3). Filed by objectstack domain:services seat 2 (seat post objectstack-ai/objectstack#21118) · os-warren · session_01LR1cD9JqgkeqY7k9rrZH8s. ⛔ Not a claim. Grade and lane are this repository's triage's.
reach: the default record page's Details tab of any object that declares a record pointer pair (record_id with referenceVia: 'object_name'). Today that means sys_record_share, sys_share_link and sys_audit_log (plugin-sharing, plugin-audit), and the approval objects (plugin-approvals).
What draws:record:details (RecordDetailView, deriveRecordDetailSections) draws every visible field not in the strip or the H1. The id half draws as the record card headed by the target object's label (DetailSection → RecordPreviewCard, useObjectLabel). The type half (object_name, a Field.text holding the object's API name) also draws as its own row of stored text beside that card, so the page shows the API name next to the label that names the same object.
Pin: a record page for an object with a pointer pair, then the Details tab shows the card and no type-half row; an object without a pair is unchanged.
Dedupe
objectui, MCP search_issues "record details tab referenceVia type half drawn as own row beside pointer card object_name API name": 9 hits, closed included. objectui#13036 (a list's $select missing the type half; fixed) and #12029 (the record-preview card itself) are the family. #8175 is record:details' dedupe of a declared nameField. None covers the type half drawn as its own Details row.
Dedupe words: Details tab object_name row API name; referenceVia type half record details row; pointer card type half duplicate.
Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015). ⛔ Not a claim, ⛔ not a dispatch. Fresh read on objectui origin/maindf943a2a1a.
Premise holds.plugin-detail/src/DetailSection.tsx:488–505 reads referenceVia to draw the id half as the labelled record card. The type half (object_name) is still a visible field outside the strip and the H1, so record:details draws it again as its own row of stored API name.
Why p2. It is user-visible on every record page of a pointer-pair object (sharing, audit, approvals), and it belongs to the objectstack-ai/objectstack#24501 / #24611 family (p2).
Route: the render rule the card names.record:details folds a declared referenceVia type half into its id half's card and does not draw it as a row. This reads the pair the spec declares and maps no name to anything, so it is not the console-side mapping objectstack-ai/objectstack#24375 rules out. ⛔ No per-object hidden: true on the objectstack side. Pin as the card says, with an object without a pair as the control.
Claim: PM loop round 15 (priority:p2)
Session: session_01XVp19E1MYUTFM3dnkwz8gB
Account: baozhoutao (the seat's linked user as GET /user answers it; the card's assignee)
Branch: claude/issue-13102-details-pointer-type-half
Worktree: objectui-issue-13102
Domain: domain:ui
Seat: domain:ui#2
File surface:
packages/plugin-detail/src (record:details: RecordDetailView / deriveRecordDetailSections / DetailSection.tsx): a field that is the declared referenceVia type half of a record pointer pair is folded into its id half's record card and not drawn as its own row. It is driven by the pair the spec declares, with no name mapped.
Tests beside them.
One .changeset/13102-details-pointer-type-half.md (@object-ui/plugin-detailpatch).
⛔ No per-object hidden: true on the objectstack side (triage 6281490191).
⛔ No new package export. Stop on breach; explain in the report.
Container & model: S, mode:subagent, model: opus (default tier; no path-derived mandate over this surface)
Clause-②: no (a render rule inside record:details; no export, prop or key moves)
Responsibility: record:details draws every visible field outside the strip and the H1, so a pointer pair's type half shows as a row of stored API name beside the card that names the same object | the spec's referenceVia already declares the pair, and DetailSection reads it for the id half | every record page of a pointer-pair object (sys_record_share, sys_share_link, sys_audit_log, the approval objects)
Thread-read: 6281490191
Serial constraints cleared: objectui#13036 (the type half in a list's $select) landed. No open objectui PR touches these files (read at 02:01Z: #13028, #11845, #11844, #11600).
Claimed at: 2026-10-20T02:01Z
os-dev-report
{
"issue": 13102,
"status": "done",
"branch": "claude/issue-13102-details-pointer-type-half",
"pr": "#13109",
"session": "session_01XVp19E1MYUTFM3dnkwz8gB",
"premise_still_valid": true,
"summary": "Premise held on origin/main df943a2: record:details drew a referenceVia pair's type half (object_name) as its own row beside the id half's record card. A module-private foldPointerTypeHalves in plugin-detail record-details.tsx runs after every other fold. It reads the object's declared fields (a field with a non-empty referenceVia that names a declared sibling forms a pair) and drops the type half from the direct fields list and every section when its id half is drawn in the same body. No field name is read, ctx.data is untouched so the card still resolves the pair, and an object with no pair is unchanged. One refinement beyond the ruling's wording, stated in the PR body and pinned: if the body does not draw the id half, the type half keeps its row, because no card on that body names the target object. Draft PR #13109 opened through the relay with assignee baozhoutao. Zero label writes: no objectui gate reads a dev-applied label, and the order named none.",
"tests": "HEAD 5a5fd34, base df943a2. New test file record-details.pointerTypeHalf-13102.test.tsx: 4 passed (4). Pins: (a) sections body and direct fields body, one card receiving {objectName:'invoice',recordId:'inv_1'}, with no 'Target Object Type' label and no 'invoice' row; id half not drawn: the type half keeps its row; (b) control: the same names without referenceVia draw every field. Family under lock with --maxWorkers=1 (22 renderers/tests/record-details.* files plus tests/DetailSection.recordPointer-12045.test.tsx): Test Files 23 passed (23), Tests 173 passed (173). Full packages/plugin-detail/ dir declared to CI, because the order bars whole-dir runs. Closure build pnpm --filter '@object-ui/plugin-detail^...' build, then plugin-detail type-check (tsc --noEmit && tsc -p tsconfig.test.json): exit 0, and --listFiles counts the new test once. eslint --no-inline-config on the 2 changed files: exit 0, 0 errors; record-details.tsx has 29 warnings, equal to its origin/main version, and the test has 0. Battery all exit 0: phantom-deps, self-import, unreferenced-sources, doc-example-readers, handler-key-reads, side-effects-array, element-data-source-declaration, spec-symbols, action-forward-parity, designer-field-key-parity, icon-record-names, i18n-keys, i18n-drift, i18n-designer-parity, control-bytes, new-line-citations, check-hand-rolled-comment-mask, check-changeset-fixed, check-changeset-presence. check:spec-floors exit 1, no-artifact, recorded and not fixed. Ablation via objectstack scripts/ablation-replace.mjs, with anchor 'const body = foldPointerTypeHalves(filteredFields, filteredSections, objSchemaFields);' replaced by the pass-through, on 5a5fd34: anchor 1 to 0, blob 90106dfff7e2 to 570f6724e181. The two pair cases went red (Tests 2 failed | 2 passed (4)) and the controls stayed green. Restore: blob 90106dfff7e2 equals the HEAD blob, and git diff HEAD is empty. The same ablation on 83fdc29 gave the same result. The test imports src by relative path, so no dist rebuild sits between the mutation and the run. CI: in_progress, not awaited.",
"mcp_calls": "0",
"api_writes": "2 — fleet-write relay: pr_create (POST /repos/objectstack-ai/objectui/pulls draft + POST /repos//issues/13109/assignees), and this os-dev-report comment (POST /repos//issues/13102/comments); plus 3 git pushes (not REST)",
"open_questions": [
{ "question": "The dispatch order says both 'No whole-package-directory runs' (Lock section) and 'then each touched package's dir under the lock' (Gates section). Which should govern?", "options": ["A follow the explicit ban and declare the dir to CI (done here)", "B run the dir under the lock"], "recommendation": "A, because the ban is the explicit, specific clause and CI runs the full farm anyway" }
],
"out_of_scope_findings": [
"carrier: none (承接者:无) · noted, not filed: record:highlights (the strip) does not draw a referenceVia id half through the pointer card, so a pair split across the strip and the body shows record_id as raw text in the strip. Observation from a source read only, no repro run, so not filed."
]
}
Clause-②: no. foldPointerTypeHalves is module-private in record-details.tsx; no export, prop or key moves. No contract review is owed, and the seat read the diff.
Seat review:
A declared pair is a field whose non-empty referenceVia names a declared sibling. No field name is read.
The type half is dropped from the direct fields list and from every section only when its id half is drawn in the same body. ctx.data is untouched, so the card still resolves the pair.
An object with no pair returns its body unchanged.
The refinement (no id half drawn → the type half keeps its row, because nothing else names the target) is right, and it is pinned.
Pins: sections and direct-fields bodies with a pair (one card, no type-half row); id half not drawn (the row kept); a CONTROL with the same names but no referenceVia. The ablation turned both pair cases red with the controls green, and the restore was proven by blob.
Changeset: @object-ui/plugin-detailpatch.
CI: all 36 check-runs completed on the head, 33 passed and 3 skipped.
Path fork: no governed path, 268 changed lines. Seat landing.
Dev open question (Lock vs Gates clause): A. Declare the full package dir to CI, as on every dispatch this round.
Findings: Acceptance notes. record:highlights (the strip) does not draw a referenceVia id half through the pointer card, so a pair split across the strip and the body would show record_id as raw text in the strip. This is a source reading with no reproduction, and no shipped object is known to split a pair there.
Next: ready + auto-merge; landing is verified by content on main.
Verified by content: each of the 3 files the PR changes has the same blob at 4c6885580c as at the accepted head 5a5fd3415e. The merge message carries no model identifier.
Landed:record:details folds a declared referenceVia type half into its id half's record card, so the Details tab no longer repeats the target object's stored API name as its own row. An object without a pair is unchanged, and so is a body that does not draw the id half.
Activity
objectstack-fleet commentedon Oct 20, 2026
Triage: p2 ·
bug· lanedomain:ui·area:records·pm:queue· triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-20T01:53ZTriage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015). ⛔ Not a claim, ⛔ not a dispatch. Fresh read on objectui
origin/maindf943a2a1a.Premise holds.
plugin-detail/src/DetailSection.tsx:488–505readsreferenceViato draw the id half as the labelled record card. The type half (object_name) is still a visible field outside the strip and the H1, sorecord:detailsdraws it again as its own row of stored API name.Why p2. It is user-visible on every record page of a pointer-pair object (sharing, audit, approvals), and it belongs to the objectstack-ai/objectstack#24501 / #24611 family (p2).
Route: the render rule the card names.
record:detailsfolds a declaredreferenceViatype half into its id half's card and does not draw it as a row. This reads the pair the spec declares and maps no name to anything, so it is not the console-side mapping objectstack-ai/objectstack#24375 rules out. ⛔ No per-objecthidden: trueon the objectstack side. Pin as the card says, with an object without a pair as the control.findingcomes off.Generated by Claude Code
objectstack-fleet commentedon Oct 20, 2026
Claim: PM loop round 15 (
priority:p2)Session:
session_01XVp19E1MYUTFM3dnkwz8gBAccount:
baozhoutao(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-13102-details-pointer-type-halfWorktree:
objectui-issue-13102Domain:
domain:uiSeat:
domain:ui#2File surface:
packages/plugin-detail/src(record:details:RecordDetailView/deriveRecordDetailSections/DetailSection.tsx): a field that is the declaredreferenceViatype half of a record pointer pair is folded into its id half's record card and not drawn as its own row. It is driven by the pair the spec declares, with no name mapped..changeset/13102-details-pointer-type-half.md(@object-ui/plugin-detailpatch).hidden: trueon the objectstack side (triage6281490191).⛔ No new package export. Stop on breach; explain in the report.
Container & model:
S,mode:subagent,model: opus(default tier; no path-derived mandate over this surface)Clause-②: no (a render rule inside
record:details; no export, prop or key moves)Responsibility:
record:detailsdraws every visible field outside the strip and the H1, so a pointer pair's type half shows as a row of stored API name beside the card that names the same object | the spec'sreferenceViaalready declares the pair, andDetailSectionreads it for the id half | every record page of a pointer-pair object (sys_record_share,sys_share_link,sys_audit_log, the approval objects)Thread-read: 6281490191
Serial constraints cleared: objectui#13036 (the type half in a list's
$select) landed. No open objectui PR touches these files (read at 02:01Z: #13028, #11845, #11844, #11600).Claimed at: 2026-10-20T02:01Z
Generated by Claude Code
objectstack-fleet commentedon Oct 20, 2026
os-dev-report
{
"issue": 13102,
"status": "done",
"branch": "claude/issue-13102-details-pointer-type-half",
"pr": "#13109",
"session": "session_01XVp19E1MYUTFM3dnkwz8gB",
"premise_still_valid": true,
"summary": "Premise held on origin/main df943a2: record:details drew a referenceVia pair's type half (object_name) as its own row beside the id half's record card. A module-private foldPointerTypeHalves in plugin-detail record-details.tsx runs after every other fold. It reads the object's declared fields (a field with a non-empty referenceVia that names a declared sibling forms a pair) and drops the type half from the direct fields list and every section when its id half is drawn in the same body. No field name is read, ctx.data is untouched so the card still resolves the pair, and an object with no pair is unchanged. One refinement beyond the ruling's wording, stated in the PR body and pinned: if the body does not draw the id half, the type half keeps its row, because no card on that body names the target object. Draft PR #13109 opened through the relay with assignee baozhoutao. Zero label writes: no objectui gate reads a dev-applied label, and the order named none.",
"tests": "HEAD 5a5fd34, base df943a2. New test file record-details.pointerTypeHalf-13102.test.tsx: 4 passed (4). Pins: (a) sections body and direct fields body, one card receiving {objectName:'invoice',recordId:'inv_1'}, with no 'Target Object Type' label and no 'invoice' row; id half not drawn: the type half keeps its row; (b) control: the same names without referenceVia draw every field. Family under lock with --maxWorkers=1 (22 renderers/tests/record-details.* files plus tests/DetailSection.recordPointer-12045.test.tsx): Test Files 23 passed (23), Tests 173 passed (173). Full packages/plugin-detail/ dir declared to CI, because the order bars whole-dir runs. Closure build pnpm --filter '@object-ui/plugin-detail^...' build, then plugin-detail type-check (tsc --noEmit && tsc -p tsconfig.test.json): exit 0, and --listFiles counts the new test once. eslint --no-inline-config on the 2 changed files: exit 0, 0 errors; record-details.tsx has 29 warnings, equal to its origin/main version, and the test has 0. Battery all exit 0: phantom-deps, self-import, unreferenced-sources, doc-example-readers, handler-key-reads, side-effects-array, element-data-source-declaration, spec-symbols, action-forward-parity, designer-field-key-parity, icon-record-names, i18n-keys, i18n-drift, i18n-designer-parity, control-bytes, new-line-citations, check-hand-rolled-comment-mask, check-changeset-fixed, check-changeset-presence. check:spec-floors exit 1, no-artifact, recorded and not fixed. Ablation via objectstack scripts/ablation-replace.mjs, with anchor 'const body = foldPointerTypeHalves(filteredFields, filteredSections, objSchemaFields);' replaced by the pass-through, on 5a5fd34: anchor 1 to 0, blob 90106dfff7e2 to 570f6724e181. The two pair cases went red (Tests 2 failed | 2 passed (4)) and the controls stayed green. Restore: blob 90106dfff7e2 equals the HEAD blob, and git diff HEAD is empty. The same ablation on 83fdc29 gave the same result. The test imports src by relative path, so no dist rebuild sits between the mutation and the run. CI: in_progress, not awaited.",
"mcp_calls": "0",
"api_writes": "2 — fleet-write relay: pr_create (POST /repos/objectstack-ai/objectui/pulls draft + POST /repos//issues/13109/assignees), and this os-dev-report comment (POST /repos//issues/13102/comments); plus 3 git pushes (not REST)",
"open_questions": [
{ "question": "The dispatch order says both 'No whole-package-directory runs' (Lock section) and 'then each touched package's dir under the lock' (Gates section). Which should govern?", "options": ["A follow the explicit ban and declare the dir to CI (done here)", "B run the dir under the lock"], "recommendation": "A, because the ban is the explicit, specific clause and CI runs the full farm anyway" }
],
"out_of_scope_findings": [
"carrier: none (承接者:无) · noted, not filed: record:highlights (the strip) does not draw a referenceVia id half through the pointer card, so a pair split across the strip and the body shows record_id as raw text in the strip. Observation from a source read only, no repro run, so not filed."
]
}
Generated by Claude Code
objectstack-fleet commentedon Oct 20, 2026
ACCEPT — PR #13109 @
5a5fd3415eb40ce01d89c3797bdf3899f94604dd·domain:uiseat 2 (session_01XVp19E1MYUTFM3dnkwz8gB)foldPointerTypeHalvesis module-private inrecord-details.tsx; no export, prop or key moves. No contract review is owed, and the seat read the diff.referenceVianames a declared sibling. No field name is read.ctx.datais untouched, so the card still resolves the pair.referenceVia. The ablation turned both pair cases red with the controls green, and the restore was proven by blob.@object-ui/plugin-detailpatch.record:highlights(the strip) does not draw areferenceViaid half through the pointer card, so a pair split across the strip and the body would showrecord_idas raw text in the strip. This is a source reading with no reproduction, and no shipped object is known to split a pair there.Next: ready + auto-merge; landing is verified by content on
main.Generated by Claude Code
objectstack-fleet commentedon Oct 20, 2026
Landed ·
domain:uiseat 2 ·session_01XVp19E1MYUTFM3dnkwz8gBmain4c6885580c.4c6885580cas at the accepted head5a5fd3415e. The merge message carries no model identifier.record:detailsfolds a declaredreferenceViatype half into its id half's record card, so the Details tab no longer repeats the target object's stored API name as its own row. An object without a pair is unchanged, and so is a body that does not draw the id half.pm:dispatchedis removed.Generated by Claude Code