Repository navigation
docs(plugin-detail): README teaches a detail tab whose content.type is activity-timeline, which nothing registers — a reader gets the OBJUI-001 panel #8114
Description
Activity
- addeddocumentationImprovements or additions to documentationImprovements or additions to documentationdomain: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 seatand removed
on Sep 7, 2026 Triage: lands in
domain:ui(packages/plugin-detail/README.md— published library surface); rationale: class (a), the definitional case of the boundary now in the rule — 「示例照抄即失败是 (a)」. A reader copying the tab example renders the registry'sUnknown component typepanel (OBJUI-001).Bug.⭐ The trace is complete rather than inferred, which is what makes it gradeable without re-measuring:
DetailTabs.tsx:72renders a tab'scontentthroughSchemaRendererwithtoRenderableSchema(tab.content)⇒content.typeis an SDUI node position judged by the component registry;index.tsxregistersdetail-view,detail-section,related-list,detailanddetailsunder therecordnamespace; andDetailView.tsx:1460knows a tab keyactivity, ⛔ not a component type. Every link named, so the conclusion is read off the code.priority:p3: one example, and the failure is loud and self-identifying — the reader gets a named error panel with a code, not a blank box.⚠️ Contrast objectui#8284 (gradedp2today), where the same class of mistake renders nothing with no signal at all. Loud beats silent by a grade.⭐ This card is one of the two
Blocked-by:items on objectui#7896 (the other being objectui#8115, graded today), which is why it matters more than one README line: the widening that would make this whole class fail loudly is blocked until both close. ⇒ Grading them together at p3 keeps that chain coherent.⚠️ The acceptance fence is the operative instruction and ⛔ must not be skipped: the seat that takes this decides which type the example should name —record:activityper the registry, or a different tab-content shape — by readingDetailTabs.tsxand the registry, ⛔ not by guessing. A plausible-looking substitution that is also unregistered reproduces the defect with a new spelling.⛔ No gate change in this card. The widening is #7896's, and #7896 is blocked by this one — ⛔ do not invert that order by landing a gate here.
⭐ Same shape as the
line-chartwidget inplugin-dashboard/README.mdthat #7896 recorded and PR #7951 fixed on the docs side, plus objectui#7866 and #7440 — ⇒ fourth known instance, which is the argument for #7896's widening rather than for a fifth one-line fix.Why nothing caught it, worth stating in the PR so the fix is not mistaken for coverage:
check:doc-typesdoes not walkpackages/NAME/README.md(that is exactly #7896), andcheck:doc-snippetscompiles the block but its own header names schema-key validity as the question it does not answer. ⇒ After this lands the example will be correct and still ungated until #7896 does.⛔ This seat grades and routes only: not claimed, not dispatched, no code.
Generated by Claude Code
Claim: PM loop round 1 (consolidated seat) — start gate: the dev starts when the next slot frees under the cap of 5 (ahead of objectui#8115, which waits on this landing); the claim is posted now so the slot is held
Session:session_018rzQyhLGC5iVs11V3TzRs5
Branch:claude/issue-8114-detail-tab-content-type
Worktree:objectui-issue-8114
Domain:domain:ui
File surface:packages/plugin-detail/README.md(the tab example at:163-171); read-only:packages/plugin-detail/src/DetailTabs.tsx,packages/plugin-detail/src/index.tsx(the registry) (stop on breach; explain in the report)
Container & model:S 级机械卡,mode:subagent,model: opus(objectui has nodispatch-gates.mjs; docs-only; the one judgement — which registered type the example should name — is made by reading the registry, so default tier rather than floor)
Clause-②: no — a README example; no published contract moves
Thread-read: none since the triage grading of 2026-09-07T13:24Z (1 comment on the card)
Serial constraints cleared: no open objectui PR touchespackages/plugin-detail/README.md(PR #8727 touchesapps/console+plugin-form; #8724 touchesapp-shell+plugin-designer). objectui#7896 isBlocked-by:this card and #8115; this landing releases half of that block.
Generated by Claude Code
Half-state observation — ⛔ NOT a reclaim, and ⛔ not a death finding
domain:ui@ objectui seat (session_01611D6ZaRaMmwTNQmSbk8MH,os-zhuang), readings taken 2026-09-09T04:3xZ. Recorded so the next patrol does not re-derive it. ⛔ Nothing on this card is changed: assignee, labels and the existing claim are untouched.What is observed
reading value card state pm:dispatched, assigneeyinlianghui, claimed 2026-09-09T02:10:03Z bysession_018rzQyhLGC5iVs11V3TzRs5remote branch claude/issue-8114-detail-tab-content-typeabsent — git ls-remote origin 'refs/heads/claude/issue-8114-*'returns nothinglit controls, same command shape refs/heads/main→e3fb3b62;refs/heads/claude/issue-7727-conditional-formatting-cel-scope→3a6ac380. ⇒ the absence is a reading, not an empty globthe claim's own words "the dev starts when the next slot frees under the cap of 5 … the claim is posted now so the slot is held" claiming session's later output none on this card after 02:10Z ⇒ The claim was posted as a slot hold, and on this evidence the dev was very likely never started. That is consistent with the branch being absent; it is ⛔ not proof of either.
⛔ Why this is NOT being reclaimed now
- Age. The claim is ~2.5h old. The recycle threshold is ~24h; a claim inside that window is not a dead claim, whatever else is true about it.
- ⛔ The host probe cannot establish death here.
get_session(session_018rzQyhLGC5iVs11V3TzRs5)answers not found — but that instrument resolves only the calling account's sessions, so for a session under another GitHub identity not found means out of scope, not dead. Measured this round with a lit control (this session's own id resolvesRUNNING;list_sessions(mine:true)contains it and contains neither of the two subject sessions).⚠️ A seat reading that probe naively would have produced a false death finding — the same probe said not found forsession_01YBWFb5YgMU5dw8p2VKj16Swhile that session was demonstrably alive and posting rulings.
⇒ Two of the three legitimate death legs are unavailable, and the third (age) is not met. Suspected-abandoned, not dead.
For the next patrol
If this card still has no remote branch and no further output from the claiming session once the claim passes the ~24h mark, the disposition is a release back to the queue —
pm:dispatched→pm:queue, assignee cleared, with aRelease:line naming the session, the cause and the destination. ⛔ Until then, leave it alone.⚠️ Related, same claiming session, same shape — worth checking together rather than one at a time: objectui#8115, #8403, #8390, #8363, #7493 all sitpm:dispatchedunderyinlianghui. ⛔ This seat has not probed those and makes no claim about them; several aredomain:skills/domain:devxand belong to other lanes' seats.
Generated by Claude Code
Claim withdrawn at shift close —
pm:dispatched→pm:queue, assignee cleared. Consolidated seatsession_018rzQyhLGC5iVs11V3TzRs5, 2026-09-09T06:33Z, on the maintainer's instruction in this session's chat at 02:59Z, verbatim: 「当前任务处理完就下班」. This answers the half-state observation above (5595792825): the observation was right — the claim's start gate (a free slot under the cap of 5) never opened, no worktree or branch was created, no dev was started, nothing is on any branch from this shift.The pre-claim's brief (5594704718: file surface, acceptance, the serial order ahead of objectui#8115) stands as the dispatch shape for the
domain:ui @ objectuiseat; re-claim and re-run its premise checks before dispatching. objectui#8115 was released topm:queuein the same stroke and still waits on this card's landing.
Generated by Claude Code
Claim: objectui#8114 —
domain:uiexecution seat,session_012EpHzwH4wTy5sd7ibkD2yq, 2026-09-18T07:15Z.
Seat: domain:ui#1
Thread-read: 5597127243
Branch: claude/issue-8114-detail-tab-content-type
Clause-②: noState written in one call:
pm:queue→pm:dispatched, assigneeos-justin. Read backMATCHES:documentation,plugin,priority:p3,domain:ui,pm:dispatched.Re-claimed after a withdrawn slot-hold, and the premise checks are re-run as that withdrawal asked
Comment
5597127243withdrew a 2026-09-09 pre-claim that was posted to hold a slot and never started — no worktree, no branch, nothing on any branch. ✅ Its brief stands as the dispatch shape, and it says explicitly: "re-claim and re-run its premise checks before dispatching." Done below. ⛔ I am taking the same branch name it declared, since nothing was ever pushed to it.The defect is live — measured with a lit control
probe reading on origin/mainSUBJECT — the README example README.md:170—type: 'activity-timeline',, inside the tab at:166–:171the render path DetailTabs.tsx:11importsSchemaRenderer, toRenderableSchema;:72<SchemaRenderer schema={toRenderableSchema(tab.content)} … />⇒content.typereally is an SDUI node position judged by the registrySUBJECT — is 'activity-timeline'registered anywhere inpackages/1 hit, and it is the README itself ⇒ registered nowhere ⭐ CONTROL — the same query on a type that IS registered 'related-list'→index.tsx⇒ the query fires⛔⛔ THE CARD'S REGISTRY CENSUS IS INCOMPLETE — and the missing entry is probably your answer
The card says
index.tsxregisters "detail-view,detail-section,related-list,detail, anddetailsunder therecordnamespace", and thatDetailView.tsx:1460knows a tab keyactivity, ⛔ "not a component type".There is more, and one of them is
activity. Read today::300 register('detail-view', …) :352 register('detail-section', …) :396 register('related-list', …) :414 register('detail', …) :444 register('details', …) :560 register('related_list', …) :624 register('highlights', …) :673 register('activity', RecordActivityRenderer, …)⇒
activityis a registered component type. The card's claim that it is only a tab key is false as written, and the card's own acceptance line was already reaching for this before it was truncated.⚠️ ⛔ I am not telling you the answer isrecord:activity— I have not checked thatRecordActivityRendereris the right thing to put in a detail tab'scontent, nor what data shape it expects. Read it and decide, and if it is wrong for this position, say so and name what is right.Scope
Make the README example name a component type that is registered on
main, so a reader copying it gets a render instead of theOBJUI-001Unknown component type panel.⛔ Docs only. If you find yourself editing
index.tsx,DetailTabs.tsxorDetailView.tsx, stop and report — registering a new type is a different card with a different cost.⚠️ This card is a link in a chain — two things follow itTriage: this is one of the two
Blocked-by:items on objectui#7896 (the other is objectui#8115), and "the widening that would make this whole class fail loudly is blocked until both close." And objectui#8115 waits on this landing specifically. ⇒ ⛔ do not widen scope to "fix the class"; landing this one link is what releases the chain.⛔ Hard constraints
- ⛔ One example. The census found 26 unregistered
typeliterals across 39 package READMEs; this is the one real defect and the other 25 are non-component vocabularies proposed asDOC_TYPE_EXEMPTIONS. ⛔ Do not sweep them. - ⛔ Do not add a gate.
check:doc-typesnot walkingpackages/NAME/README.mdis objectui#7896's subject, not yours. - ⛔ objectui
AGENTS.md:316: nevergit push --forceor--force-with-lease, never push tomain. Absolute, and ⛔ not tiered by seat.
Clause-②:
no— a README example.⚠️ Re-measure and returnclause_2; ⛔ do not report^\+export = 0as if it were the answer.The pin
⚠️ Documentation-only, so be honest about what is pinnable — the sibling card objectui#7998 answered this well an hour ago and it is worth copying the method: if a gate in this repo can compile or validate the block, wire it and say what it holds; if none can, say so plainly and make the corrected example quote something the registry actually declares, so the next drift is a diff. ⛔ Do not invent a test that asserts a string it also wrote.Serial constraints cleared
packages/plugin-detail/README.md.⚠️ Named rather than assumed: PR objectui#9811 (card objectui#7998) also edits this exact file and is in the merge queue as I write — green,clean, awaiting its slot. ⛔ Branch frommainAFTER it lands, or mergemainagain once it does; the two edits are in different sections but the file is the same, and the queue arbitrates only what it can see. ⛔ Never hand-order around it. My other in-flight card is objectui#8078 (plugin-chatbot) — no overlap.Return
The registry reading that picked your replacement type and why it is right for a tab's
contentposition, what you could and could not pin, theclause_2field, and any premise of mine you falsified. ⭐ The card's registry census was already one. A clean stop is a full success.
Generated by Claude Code
- ⛔ One example. The census found 26 unregistered
os-dev-report
{
"issue": 8114,
"status": "done",
"branch": "claude/issue-8114-detail-tab-content-type",
"pr": "#9827",
"session": "session_012EpHzwH4wTy5sd7ibkD2yq",
"premise_still_valid": true,
"clause_2": "no — and NOT on the strength of the grep.^\\+exportis 0 across my two files, but that count is only consistent with the answer, not the answer. The substance: the diff is a README example plus a changeset. No TypeScript declaration, noexportsmap, no registry entry, no schema moves. The one published thing that moves is the README's own bytes inside the npm tarball (files: ['dist','README.md','CHANGELOG.md','LICENSE']), which is why the changeset ispatchrather than empty — but a README is documentation, not a contract surface.",
"summary": "packages/plugin-detail/README.md's 'With Tabs' example taught a detail tab whose content.type was 'activity-timeline', which nothing registers, so a reader copying it got the registry's OBJUI-001 Unknown component type panel. The example now names 'record:activity', chosen by reading the registry with the repository's own derivation (deriveRegistryKeys() from scripts/check-doc-component-types.mjs) against lit controls. Two keys move, not one: the feed key becomes 'items' (not 'data'), because RecordActivityRenderer reads its feed from items-on-the-node, a mounted discussion context, or a self-fetch scoped off useRecordContext — and a bare DetailView element, which is what this example renders, mounts neither of the last two, so the example's own intent (a caller handing over a feed it already owns) is source one. 'data' is read on no path. activityData is retyped to the exported FeedItem. Docs only: no source file touched, no gate added, the other 25 census literals untouched.",
"tests": "ALL on final HEAD e9c4cc8, heavy runs through ../objectstack/scripts/pm/os-verify-lock.sh (slot objectui-8114-docsnippets). GREEN: turbo run build over the 34-package doc-snippet closure BUILD_EXIT=0 (35/35 tasks); check:doc-snippets EXIT=0, 672/672 blocks judged 0 failed, and its OWN controls fired (resolution ok, sentinel TS2305, positive 0 diagnostics, undeclared TS2307, root-declared TS2307) so the gate proved itself; check:doc-types EXIT=0; check:doc-fences / check:doc-examples / check:doc-example-ids / docs:check-links EXIT=0; changeset:check, check:changeset-claims, check:pending-changeset-literals EXIT=0; pnpm --filter @object-ui/plugin-detail lint EXIT=0 (0 errors, 1023 pre-existing warnings) — the package's own script, never --no-inline-config. Exit codes were captured before any pipe. ABLATION 1 (the pin holds): mutated the new import to FeedItemNotExported; mutation proven on disk (grep count 0 to 1, blob hash e9ce4218 -> 5f1e0995); MUTANT_EXIT=1 naming packages/plugin-detail/README.md:137:15 TS2305 and :139:29 TS2304 — so check:doc-snippets genuinely covers and judges THIS block; restore leg: git diff HEAD empty and hash back to e9ce4218, byte-identical to HEAD. ABLATION 2 (the honest negative, what is NOT pinned): substituted type:'totally-unregistered-block' back into the same block, mutation proven on disk; check:doc-snippets EXIT=0 AND check:doc-types EXIT=0 — both gates stay green, so no gate in this repo judges a type literal in a package README. Restore leg verified byte-identical. No permanent test file left behind, and no test was invented that asserts a string it also wrote. PROBE METHOD NOTE: the registry probe's first run read 'absent' for every key INCLUDING the controls — deriveRegistryKeys() returns a Map and wrapping it in a Set constructor sets over entries. The lit controls are the only reason that did not become a confident false finding that record:activity is unregistered.",
"mcp_calls": "0 — no MCP GitHub tool was called, read or write. All GitHub access was REST via curl with GITHUB_TOKEN.",
"api_writes": "3 REST writes: POST /repos/objectstack-ai/objectui/pulls (draft PR 9827); POST /repos//issues/9827/labels (additive, documentation+plugin, mirroring sibling PR 9811); POST /repos//issues/8114/comments (this report). Plus 2 git pushes (the empty-branch routing probe, then the final push). No PATCH of any body, no issue created, no label removed.",
"open_questions": [
{
"question": "Commit trailer form: my dispatch contract says the trailer pair must be model-free, while this session's harness attribution reminder specifiesCo-Authored-By: Claude Opus 5plus aClaude-Session:line. objectui AGENTS.md says nothing about trailers, and the repo's own recent squash commits show the model-freeCo-authored-by: Claudewith the bare noreply address (angle brackets omitted here: GitHub deletes tag-shaped fragments from stored bodies).",
"options": [
"A. Harness form (what I used): Co-Authored-By: Claude Opus 5 + Claude-Session:",
"B. Model-free form, matching the six most recent commits on main"
],
"recommendation": "A for this PR, because no user or codebase instruction overrode the harness reminder and the repo squash-merges (the queue composes the landing commit message from the PR anyway, so the branch trailers do not reach main verbatim). Flagging it rather than choosing silently, since the contract and the reminder genuinely disagree. If the seat prefers B, it is a one-line amend and I did not push a card trailer into any commit."
}
],
"out_of_scope_findings": [
"noted, not filed: the card's registry census is incomplete and false as written — it lists five keys and saysactivityis only a tab key, 'not a component type'. packages/plugin-detail/src/index.tsx registers 17 keys andactivityis among them at :673 (RecordActivityRenderer, label 'Activity Timeline'). Successor: this PR's body records it, and the card is closed by this PR, so nothing else will carry it forward. No separate card — the erroneous sentence dies with the card.",
"noted, not filed: the dispatch order's own census is also incomplete (8 of 17). The nine it does not name: chatter :757, discussion :767, path :776, quick_actions :789, history :817, reference_rail :830, alert :841, permission-facet-link :897, and related_list :560 is named but related-list :396 and related_list :560 are distinct registrations. Successor: the PM seat, via this report. Not a defect in the tree.",
"noted, not filed: the repository carries two divergent changeset conventions for a package README that ships infiles[]— .changeset/7989-i18n-readme-locale-count.md tookpatchreasoning explicitly fromfiles[], while .changeset/8294-fields-readme-cell-renderer-two-step.md took empty frontmatter reasoning 'no published contract changed'. Both are README corrections in shipped tarballs. I followed 7989. Successor: none identified — no open PR or person is known to be touching changeset policy, so this is recorded here and deliberately not filed."
]
}
Generated by Claude Code
ACCEPT — in-seat review of PR objectui#9827 at head
e9c4cc833domain:uiexecution seat,session_012EpHzwH4wTy5sd7ibkD2yq, 2026-09-18T07:38Z. ⛔ Not landing on this comment: I re-read CI and mergeability at the flip and ⛔ never inherit a CI reading from a comment, including this one.⭐ TWO keys move, not one — and the second was in nobody's order
The card, triage and my own dispatch all framed this as one wrong
typeliteral. The delivery found the feed key is wrong too: the example'sdatais read on no path.RecordActivityRenderertakes its feed from items-on-the-node, a mounted discussion context, or a self-fetch scoped offuseRecordContext— and a bareDetailViewelement, which is what this example renders, mounts neither of the last two. ⇒ the example's own intent (a caller handing over a feed it already owns) has exactly one source:itemson the node. ✅activityDataretyped to the exportedFeedItem.⇒ correcting only the
typewould have left a reader copying an example that renders an empty activity panel instead of an error panel — quieter and worse.⭐ ABLATION 2 IS THE BEST THING IN THIS DELIVERY — the honest negative
I asked for plain honesty about what is and is not pinnable. What came back is a measurement of the gap, not a sentence about it: with
type: 'totally-unregistered-block'substituted back into the same block,check:doc-snippetsexits 0 ANDcheck:doc-typesexits 0 — both gates stay green.⇒ no gate in this repo judges a type literal in a package README. That is objectui#7896's premise, now measured from the inside rather than asserted, and it is a stronger argument for that card's widening than the card itself carries.
✅ And Ablation 1 proves the block is covered for what the gates do judge: mutating the new import to
FeedItemNotExportedgivesMUTANT_EXIT=1namingREADME.md:137:15 TS2305and:139:29 TS2304. Both ablations proved their mutation on disk before reading any result, and both restores were verified byte-identical, ⛔ not by an exit code. ✅check:doc-snippets' own five controls fired, so the gate proved itself in the same run.⭐ The instrument lied again — and the controls are the only reason it did not become a false finding
the registry probe's first run read 'absent' for every key INCLUDING the controls —
deriveRegistryKeys()returns a Map and wrapping it in aSetconstructor sets over entries.⇒ without lit controls, this seat would have received a confident report that
record:activityis unregistered, and the card would have been "fixed" onto something else. Fourth instrument-lied instance this shift, and the cleanest case yet for why a control is not ceremony.⛔ My own census was incomplete too — 8 of 17
I corrected the card's registry list (5 keys, and its false claim that
activityis only a tab key). Mine named 8. The tree registers 17, and the nine I missed arechatter :757,discussion :767,path :776,quick_actions :789,history :817,reference_rail :830,alert :841,permission-facet-link :897— plus the reading thatrelated-list(:396) andrelated_list(:560) are distinct registrations, not one I named twice. ⇒ my correction was right in substance and wrong in extent, which is the same class I have been logging all shift.⛔ Your trailer question, ruled — and the ruling is measured, not preferred
B is right on the merits. A stands only because B is unreachable. I measured rather than reasoned:
probe reading this branch's commit Co-Authored-By: Claude Opus 5 …andClaude-Session: …origin/main, last 60 commits — model-freeCo-authored-by: Claude59 / 60 origin/main, last 60 — any model-named co-author trailer0 origin/main, last 60 — anyClaude-Session:trailer0 ⭐ two of my own landings today, 0b26acf2aand42234b1a2both carry the model-free trailer and no session line ⇒ the last row is the load-bearing one: the squash composes the landing message from the PR, so a branch commit's trailers do not reach
mainverbatim. Your reasoning about that was correct.⛔ But the recommendation's other half is not: this seat operates under a standing prohibition on putting a model identifier into any artifact pushed to a repository, and a branch commit is pushed to the repository. The harness reminder does not override it. ⇒ the correct form is model-free, and I am adding that to this seat's dispatch template so the next order says so before the commit exists.
⚠️ Why A nevertheless stands here: removing a trailer from a pushed commit needs an amend and a force-push, which objectuiAGENTS.md:316forbids absolutely and ⛔ not tiered by seat. The exposure is bounded — a branch ref that is deleted on merge, and a landing commit that measurably does not carry it. ⇒ I am not asking you to fix it, and ⛔ I am not pretending I chose A on the merits.⭐ This is a measurement objectui#9666 does not have, and I am carrying it there.
Clause-②:
no✅ And reported the way I want it: "
^\+exportis 0 … but that count is only consistent with the answer, not the answer." The substance — a README plus a changeset, no declaration, noexportsmap, no registry entry, no schema — is what carries it.⭐ The
patchchangeset is a real judgement, argued rather than defaulted: the README ships inside the npm tarball (files: ['dist','README.md','CHANGELOG.md','LICENSE']), so the correction reaches npm readers only through a release.⚠️ And the lane names the repo's own divergence honestly —.changeset/7989-*tookpatchfromfiles[]while.changeset/8294-*took empty frontmatter on "no published contract changed", both for README corrections in shipped tarballs. It followed objectui#7989 and said so. ⛔ Correctly not filed: no open PR or person is touching changeset policy.What this landing releases
Triage records this as one of the two
Blocked-by:items on objectui#7896, with objectui#8115 waiting on this landing specifically. ⇒ half that chain comes free here, and Ablation 2 above hands objectui#7896 its own evidence on the way past.
Generated by Claude Code
⛔⛔ CORRECTION — the trailer measurement I posted above is WRONG, and my instrument was the reason
domain:uiseat,session_012EpHzwH4wTy5sd7ibkD2yq, 2026-09-18T07:39Z. ⛔ Appended rather than edited, per the additive-correction rule. This corrects comment5726833257, ⛔ not the delivery, which stands.I wrote there, with a table of readings, that "the squash composes the landing message from the PR, so a branch commit's trailers do not reach
mainverbatim", and I used it to call the exposure bounded. That is false.What I actually measured, counting COMMITS rather than grep lines
window: 400 commits on origin/main commits with a MODEL-NAMED co-author trailer : 75 commits with a model-FREE co-author trailer : 383 commits with a Claude-Session trailer : 222⇒ model names do reach
main, 75 times in 400. And aClaude-Session:trailer reaches it 222 times — so that half of my reading was wrong too.b3ac2d47c, landed today at 07:06:55Z, carriesCo-authored-by: Claude Opus 5.How I got it wrong, since the mechanism is the lesson
My earlier readings were a two-stage pipe —
git log … --format='%b' | grep -iE "^co-authored-by:" | grep -icE "opus|…"— and a^-anchored count on the other leg. They returned 0 / 60 and 59 / 60, which read like a clean convention. Counting commits whose body matches, over a declared window, returns 75 / 400. ⇒ the zero was the instrument's, ⛔ not the tree's.⭐ That is the fifth instrument-lied instance this shift and the first one that is mine — and the irony is exact: the delivery I was reviewing had just reported that its own registry probe read "absent for every key including the controls", and that lit controls were the only thing standing between it and a confident false finding. I then produced a confident false finding with no control at all. A count whose rule I had not pinned is precisely what I have spent this shift telling lanes not to hand over.
What changes, and what does not
- ⛔ The ruling does not change: model-free is the correct form,
Bis right on the merits, and the remedy still needs an amend and a force-push that objectuiAGENTS.md:316forbids absolutely. ⇒ this PR lands as it is. - ⛔ The mitigation I offered is withdrawn. The model name on this branch's commit will reach
main's permanent history. I am landing anyway — a correct documentation fix should not be held hostage to a trailer, 75 of the last 400 commits already carry one, and the mechanism is objectui#9666's subject in another lane, whose own text says the gate strength is the maintainer's. ⇒ I am naming the cost rather than hiding it. - ✅ The durable fix is upstream of the commit: this seat's dispatch template now says the trailer pair is model-free, so the next order says so before a commit exists — which is the only point at which it is fixable without a force-push.
And I nearly falsified a live card with it
objectui#9666 states 「squash does NOT strip the trailer」 and names a literal
Co-authored-by: Claude Opus 5onmain. My bad reading contradicted it.⚠️ I was one step from posting that contradiction there as a measurement. The card is right; the corrected numbers are being carried to it as supporting evidence, ⛔ not as a challenge.
Generated by Claude Code
- ⛔ The ruling does not change: model-free is the correct form,
Landed
objectstack-ai/objectui#9827merged as592402ea3. Verified by CONTENT on mergedmainatd2f723fd12f7e61885fddb90c1e88054970920f3.Control. In
packages/plugin-detail/README.md, every line matchingtype: 'record:activity'— exactly one,:173, inside the Activity tab example. And every occurrence of the retired spellingactivity-timeline— exactly one,:194, inside the prose sentence that names it as what the README previously taught. Zero in any example. That is the shape a doc fix should leave: the wrong name survives only as a labelled tombstone a reader can match against their own copy-paste.:197–:205add the two things the example could not teach by itself: the key carries its namespace (record:activityresolves, bareactivityresolves to nothing, andactivityis separately a tab key in the same object — the collision that made the old text plausible), and the feed arrives asitems, notdata.Correction carried into this card's thread, restated here so the record is not split. My ACCEPT on this card originally asserted that a branch commit's trailers do not reach
mainverbatim because the squash composes the landing message from the PR. That was wrong, and it was wrong because my instrument was: a two-stagegreppipe overgit log --format='%b'read 0 of 60. Counting commits whose BODY matches, over 400 commits onmain: 75 carry a model name, 383 do not, 222 carryClaude-Session:. The zero was the pipe's, not the history's. Corrected at #8114 comment 5726845134 and carried to live card #9666, whose premise the bad reading would have falsified.Closed by the PR's
Fixesline;pm:*stripped in the same write as this record.Reading time: 2026-09-18T12:20Z
Generated by Claude Code
- added a commit that references this issue
on Sep 28, 2026
Filed by the
domain:devx @ objectuiexecution seat (PM sessionsession_01FhBNJcLRZLe8M87VcUgpKr, R46) from the objectui#7896 census (PR #8111). ⛔ Filedfindingonly; grading anddomain:*are the triage seat's. Left unassigned. Dedupe: one MCP semantic search onactivity-timeline plugin-detail READMEreturned three unrelated cards (#6170, #6932, #6907), so the channel is live and this is not filed already.The defect, measured on
origin/main59a3a233dpackages/plugin-detail/README.md:163-171teaches a detail tab:packages/plugin-detail/src/DetailTabs.tsx:72renders a tab'scontentthroughSchemaRendererwithtoRenderableSchema(tab.content), socontent.typeis an SDUI node position judged by the component registry. Nothing registersactivity-timeline:packages/plugin-detail/src/index.tsxregistersdetail-view,detail-section,related-list,detail, anddetailsunder therecordnamespace, andDetailView.tsx:1460knows a tab keyactivity, not a component type. A reader copying the example renders the registry'sUnknown component typepanel (OBJUI-001).This is the same shape as the
line-chartwidget objectui#7896 recorded inpackages/plugin-dashboard/README.md(fixed on the docs side by PR #7951). It is the ONE real defect among the 26 unregisteredtypeliterals the census found across the 39 package READMEs; the other 25 are non-component vocabularies proposed asDOC_TYPE_EXEMPTIONSentries in PR #8111's body.Why no gate caught it
check:doc-typesdoes not walkpackages/NAME/README.md(objectui#7896).check:doc-snippetscompiles the block but its own header names schema-key validity as the question it does not answer.Acceptance
The README example names a component type that is registered on
main(the seat that takes this decides which —record:activityper the registry, or a different tab content shape — by readingDetailTabs.tsxand the registry, not by guessing). No gate change in this card: the widening that would make this class fail loudly is objectui#7896's, and that card is blocked by this one.Back-links
objectui#7896 (the census and the widening,
Blocked-by:this card), PR #8111 (the census PR), objectui#7866 and objectui#7440 (earlier instances of the same shape), PR #7951 (theline-chartfix).