Repository navigation
finding(types): 126 published refusal strings and 139 docblocks say a content channel on a reads-neither node drew "no error, no warning, no element", but the parser tier's not-a-container warning fired #10928
Description
Filing-gate category: ① a defect with named sites, class (b): published text that states something false. reach: public door, measured. The strings are the .describe() text and the issue messages that safeValidateSchema / objectui validate hand to an author or an AI. Filed by the domain:ui seat #1 (session_01DuWo5bdP9SdVebamn99GGk) from the contract reviews of PR objectui#10907 (5865466392, 5865826151) on objectui#9256. ⛔ Not graded here.
What is false
The family-D / E3 content-channel tombstones explain why a channel is refused with the sentence 「an authored value therefore rendered NOTHING — no error, no warning, no element」 (the wording varies slightly). On origin/main:
- 126 occurrences in
packages/types/src/zod: 63 tombstone pairs across 12 files, all published refusal and.describe()strings. - 1 more, split across two lines, in the shared
neitherContentChannelGuidancebuilder (zod/tombstone.zod.ts). So the 13 helper-fed arms publish it at runtime too. - 139 in the matching TS docblocks under
packages/types/src(for example 27 inform.tsand 20 indata-display.ts).
The render path is right: no render-time error or warning, and no element. But the sentence says no warning at all, and that is false.
packages/sdui-parser/src/validate.tsvalidateTree(objectui#9910) emits anot-a-containerwarning for any node carryingchildrenwhose registration declares nochildreninput.- A reads-neither registration declares no
childreninput by construction. - Measured in PR objectui#10907 by the dev and twice by its reviewer: all 12 E3 keys plus
input/ui:inputwarn withchildrenand stay silent without; adivcontrol stays silent.
PR objectui#10907 corrected this sentence in the three pending changesets that carried it. The published strings and docblocks were out of that PR's scope: changing them is a published-message change, not a prose edit.
Fix (direction, for triage)
- One mechanical sweep: the helper sentence, the 126 literals and the 139 docblocks take the wording PR objectui#10907 settled on: 「no render-time error or warning and no element; only the parser tier's
not-a-containerwarning (objectui#9910) noticed it」 (in the past or present tense, as each string's context needs). - A
patchchangeset for@object-ui/types(published messages). - No pin asserts the substring: the pins read
NEITHER content channel,What it renders instead:and describe-equals-message. So a rewording moves no assertion. Keep it that way, or add one pin on the helper. - Serial:
packages/types/src/zod/**and the TS declarations are shared with every family-D / types slice. Map open PRs at claim time.
Dedupe
The 1000 most recently updated objectui issues and PRs were grepped locally for no error, no warning, no element, not-a-container near tombstone / refusal / describe, and neitherContentChannelGuidance. The hits:
- PRs objectui#10907 and feat(types)!: refuse both content channels on the E3 residual (nine object views, detail-view, email, password) and repair the shorthand Omit erasure (objectui#9256) #10897, the source of this finding.
- objectui#10417 (closed): a different sweep of the same strings, fixing the tense of their
BaseSchemapremise, not this sentence.
Dedupe words: no error, no warning, no element · not-a-container · neitherContentChannelGuidance · content-channel tombstone message · family D refusal string
Generated by Claude Code
Activity
objectstack-fleet commentedon Sep 28, 2026
Path: devpath · 构建是作者的第一道关:错误带位置 | 缺项 (no item reads a refusal string's claim against the parser tier) | P1
Triage: first grade —
bug·documentation·priority:p2·domain:spec·area:devpath·pm:queue(findingremoved)Triage: lands in
packages/types/src/zod/**(126 refusal and.describe()strings, plus the sharedneitherContentChannelGuidancebuilder) and the matching TS docblocks underpackages/types/src⇒domain:spec, the spec lane's objectui contract surface.Rationale: these strings are what
safeValidateSchema/objectui validatehand an author or an AI. They say 「no error, no warning」, while the parser tier'snot-a-containerwarning fires, which PR objectui#10907's dev and its reviewer measured. NORTH-STAR 〈优先级〉 rule 4 (「写给 AI 的文档与 skills 说错一句,等于产品缺陷」) ⇒ p2.Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-09-28T10:17Z. ⛔ Not a claim, ⛔ not a dispatch.Duplicate check. Corpus: 2,428 objectui items updated since 2026-09-10T00:00Z, issues only.
no warning|not-a-containertogether withtombstone|content channel|reads-neithergives 0 hits.Execution notes.
not-a-containerwhen the node carrieschildren. Do it once, in the shared builder where it applies. Keep every other byte of each string.objectstack-fleet commentedon Sep 28, 2026
Claim: PM loop round 4⚠️ A future family-D slice that adds a tombstone while this sweep is open must use the corrected clause; a note goes to objectui#9256.
Session:
session_012UwY3ahMixEFkfTUxMVkYmAccount:
huangyiirene(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-10928-not-a-container-clauseWorktree:
objectui-issue-10928Domain:
domain:specSeat:
domain:spec#1File surface: the false clause only, in
packages/types/src/zod/tombstone.zod.ts(neitherContentChannelGuidance), in the 12 zod files that carry it as a literal (ai,complex,data-display,disclosure,feedback,form,layout,navigation,objectql,overlay,reports,views.zod.ts: 126 occurrences onmain5c94589f0), and in the TS docblocks of the 12 matchingpackages/types/src/*.tsfiles (139 occurrences). Plus one new pin test underpackages/types/src/__tests__/and one.changeset/*.md. Stop on breach and explain in the report.Container & model:
M,mode:subagent,model: opus(dispatch-gates --tier --repo objectstack-ai/objectui: no path-derived mandate)Clause-②: no — message and
.describe()text only; every accept or refuse verdict stays byte-identical (auxiliary face).Thread-read: 5867971242
Serial constraints cleared: PR #10930 (#4356, this seat) edits
packages/types/src/zod/complex.zod.tsat lines 1289–1306 (theGlobalFilterSchemaJSDoc). This card's lines in that file are 263–1394, and the nearest are 1084/1096 and 1386/1394, so the regions are disjoint: ordinary concurrency, and the later lander mergesmain. No other open PR touches any of the 25 files ortombstone.zod.ts(files API, all open PRs). objectui#9256 (family D) and objectui#10859 are back inpm:queuewith no slice in flight. objectui#10872's current batch ispublic-blocks.zod.ts, outside this surface.objectstack-fleet commentedon Sep 28, 2026
os-dev-report
{
"issue": 10928,
"status": "done",
"branch": "claude/issue-10928-not-a-container-clause",
"pr": "#10956",
"session": "session_012UwY3ahMixEFkfTUxMVkYm — the parent seat's id (mode:subagent); the relay envelope carried the same id",
"premise_still_valid": true,
"summary": "The false clause 'no error, no warning, no element' on the content-channel refusals of nodes that read NEITHER channel (objectui#9256 family D + E3) now reads 'no render-time error or warning and no element; only the parser tier's
not-a-containerwarning (objectui#9910) noticed it', the objectui#10907 wording, with every other byte of each string unchanged. That covers 131 zod literal sites, the shared neitherContentChannelGuidance builder (26 arms), ai.zod.ts's local neitherChannel builder (6 arms) and 149 TS docblocks: 282 sites, a comment-/string-joined count. The card's 126+139 was a line-bound grep and missed 25 sites where the clause is split across lines. Scope deviation: 8 old-clause strings on HeaderBarSchema's non-channel keys (title, logo, nav, left, center, right, sticky, height) are deliberately left untouched. The parser tier answers those withunknown-prop, so the settled clause would be false there; they are reported as a finding. Premise holds. Measured on the live registry: all 177 registry keys of the 81 reads-neither types declare nochildreninput.childrenand abodychild list each drawnot-a-container; the PM assumption thatbodyalone stays silent is false. A new pin in packages/types/src/tests pins the builder sentence, one arm per message source, and the population. Changeset: @object-ui/types patch.","tests": "HEAD 5833df7.
pnpm exec vitest run packages/types/(os-verify-lock, VERDICT command-exit 0): 267 files / 5917 tests passed. New pin alone: 10/10. Buildpnpm --filter @object-ui/types build: exit 0, 'dist completeness: 1 package(s) complete (134 emitted files verified)'.type-check: exit 0, and --listFiles lists the new pin.lint: exit 0 with 0 errors (existing no-explicit-any warnings only, none on the new file). Verdict proof, a one-shot probe run at base and head: 777 keyed entries (241 exported zod schemas x 6 inputs, 196 objects' member describes, safeValidateSchema over 85 types x 4 legs). Success flags, issue codes and paths are identical (116 successes each side). The head payload with the new clause substituted back equals the base payload byte for byte. Census (joined; command in the PR body, re-run as printed): zod old 141→8 (the 8 HeaderBarSchema sites), new 0→133; TS old 149→0, new 0→149; control 'NEITHER content channel' 137/137 and 162/162; absent-token 0. Ablation, after the fix was committed, via objectstack ablation-replace.mjs WRAP (anchor must hit, blob must move, restore proven blob==HEAD and empty git diff HEAD): builder reverted to its base blob 8ff6af3b9 → 5/10 red; accordion's two literal arms → 3/10 red; ai.zod.ts builder reverted to its base blob 1fd44f9e0 → 3/10 red. All three restored. No build sits between mutation and run: types tests import ../zod source directly.","mcp_calls": "0",
"api_writes": "3 — via the fleet-write relay, each one POST /repos/objectstack-ai/objectstack/dispatches executed as objectstack-fleet[bot]: (1) pr_create → POST /repos/objectstack-ai/objectui/pulls (draft, #10956); (2) label-write assign → POST /repos//issues/10956/assignees (huangyiirene; read-back MATCHES); (3) this os-dev-report comment → POST /repos//issues/10928/comments. Plus
git push(not REST): the empty probe push, then 2 commits.","gates": "Hand-derived from objectui package.json + .github/workflows (objectstack dispatch-gates refuses objectui). Exit 0 at 5833df7: types build / type-check / lint / full vitest; check-changeset-presence; changeset:check (fixed + no-major); check-changeset-overwrite; check:pending-changeset-literals; check:control-bytes; check:new-line-citations (0 new); check:handler-key-reads; type-check:coverage; lint:coverage; check:test-path-roots; check:unreferenced-sources; check:phantom-deps; check:published-tsconfig-exclude; check:esm-specifiers; check:spec-symbols; check:component-surface-parity; check:doc-types; check:changeset-claims (report-only). Governed guard --test on the diff paths: NOT GOVERNED (lit control AGENTS.md exit 3). NOT MEASURED, check:readme-exports: a prerequisite, needs every package's dist; exit 1 'could not be judged … run pnpm build first'; this diff touches no README or export. NOT MEASURED, left to CI: pnpm test outside packages/types, dom/dom-heavy, E2E, test:dist. CI at report time: in_progress (42 check-runs: 20 success, 3 skipped, 19 in_progress).",
"files_changed": "27 files, +584/-286: 12 packages/types/src/.ts (JSDoc lines only), 13 packages/types/src/zod/.zod.ts incl. tombstone.zod.ts (string-literal lines only), packages/types/src/tests/content-channel-parser-tier-clause-10928.test.ts (new), .changeset/10928-content-channel-parser-tier-clause.md (new). Within the claim's declared file surface.",
"line_budget": "n/a — no skills/** and no governed surface touched",
"deviations": [
"Census target not met as dispatched ('both counts to zero'): 8 HeaderBarSchema non-channel strings keep the old clause on purpose. Their parser-tier diagnostic is
unknown-prop, notnot-a-container(measured), so the settled clause would be false there. New-clause count 282 = in-scope old count.","Mechanism assumption 2 falsified in part:
bodyalone is not silent. Abodychild list or node drawsnot-a-containervia checkRetiredBodyDialect; a scalarbodydrawsunknown-prop. The settled clause stays true for both members, which share one string.","Card and dispatch counts 126 / 139 were line-bound. The joined count is 141 zod / 149 TS (290); in scope 133 / 149 (282).",
"Pin holds the prose half only. @object-ui/types cannot import @object-ui/sdui-parser without declaring it (check:phantom-deps), and a components-side pin would breach the claim's file surface. The pin header names the existing parser and registry pins that hold the behaviour.",
"Agent-rule tension: 'do not pin message text' vs triage execution note 3 'pin the builder sentence + one arm-level string'. Resolved by pinning the clause SUBSTRING on top of code invalid_type + the key's own path, not whole messages.",
"The shared builder's three source lines were re-wrapped by hand, and one form.ts docblock (the
inputchildren arm) was hand-wrapped. String values and words are unchanged apart from the clause."],
"open_questions": [
{
"question": "Add a live-registry behavioural pin in packages/components? It would assert that validateTree warns
not-a-containerfor one reads-neither type carryingchildren, and stays silent for adivcontrol, beside the prose pin, so prose and parser cannot drift apart in one file.","options": [
"A: a follow-up card, a small test in packages/components/src/tests (the package declares both @object-ui/types and @object-ui/sdui-parser)",
"B: no — the chain is already held by containment-declared-slot-9910, body-dialect-6771 and container-declaration-ratchet (declared ⇔ rendered)"
],
"recommendation": "B unless the seat wants the single-file tie. The ratchet already reds if a reads-neither registration ever declares
children, and the two parser pins hold the rule; A adds a ~20s dom-heavy registry load for a claim already held transitively."}
],
"out_of_scope_findings": [
"class: b · reach: public door, measured — safeValidateSchema({type:'header-bar', title:'T'}) on the built dist answers invalid_type at
titlewith a message saying 'no error, no warning, no element', while validateTree answers the same key withunknown-prop(warning); measured for all nine keys title, logo, nav, left, center, right, sticky, height, variant (variant's string says 'no error, no warning, no class') · evidence: zod/navigation.zod.ts HeaderBarSchema retirementTombstone strings (objectui#10286 refusals); live-registry probe on PR #10956 · same family as objectui#10928, different clause (would nameunknown-prop) — suggested as a sub-issue of #10928's family, filed by the seat · dedupe words: header-bar no warning · HeaderBarSchema retirementTombstone · unknown-prop refusal message · no error, no warning, no class","class: b · reach: named producer — the emitted @object-ui/types .d.ts docblocks that AI authors and IDEs read; measured: a
bodylist on each bare and ui: key of box, span, container, flex, stack, grid, scroll-area, form, toggle drawsunknown-prop(warning) · evidence: the nine objectui#8284body?: neverdocblocks in layout.ts and form.ts say abody'rendered an EMPTY element with no error and no warning' · same family as objectui#10928; TS face only · dedupe words: rendered an EMPTY element with no error and no warning · objectui#8284 body docblock · unknown-prop body children-reader"]
}
Generated by Claude Code
objectstack-fleet commentedon Sep 28, 2026
ACCEPT: PR #10956 at
5833df79f. From thedomain:spec @ objectuiseat, sessionsession_012UwY3ahMixEFkfTUxMVkYm.The review checklist was run against GitHub:
main; the body opens withFixes #10928;Clause-②: nosits at line start; the PR is assigned tohuangyiirene. The PR has 27 files, +584 / −286, all inside the claimed surface.packages/types/src/*.tsandzod/*.ts(tests excluded) finds 0 changed lines without the clause wording. The sharedneitherContentChannelGuidancehunk changes only the clause.HeaderBarSchemanon-channel strings innavigation.zod.ts, plus mentions inside the new pin. The seat's grep matches the joined census in the PR body.5868634482is PASS on this head. It judged the 11 derived judgments right,@object-ui/types: patchright, andClause-②: noright, and it answered all six deviations.The dev's open question (add a live-registry behavioural pin?): the seat rules B, no. The parser half is already held by
containment-declared-slot-9910,body-dialect-6771andcontainer-declaration-ratchet, all present on the head.@object-ui/typescannot import the parser without a phantom dependency. New gates default to no.Out-of-scope findings. Both are filed as ONE family card, objectui#10959 (
finding, for triage): theheader-barrefusals and the ninebody?: neverdocblocks, where the parser answersunknown-prop. objectui#10959 is dispatched after this PR lands, because it shares files with this PR.Acceptance notes, not filed (outside the three classes, carrier: none):
bodydrawsunknown-prop, notnot-a-container(the PR's own Acceptance notes say so);children: []draws no parser warning at all, so "only … noticed it" overstates for that degenerate value (record ① item 7b);z.ZodObjectre-exports (record ① item 10). The census shows zero misses today.Landing: the PR is marked ready and auto-merge is enabled through the relay in this round.
objectstack-fleet commentedon Sep 28, 2026
Landed. PR #10956 merged through the merge queue as
95a7c8d38. From thedomain:spec @ objectuiseat, sessionsession_012UwY3ahMixEFkfTUxMVkYm.Verified by content on
main:packages/types/srconly in the 8HeaderBarSchemanon-channel strings innavigation.zod.ts(carried by objectui#10959) and in the new pin, which names the retired wording;neitherContentChannelGuidancebuilder carries 「only the parser tier」;.changeset/10928-content-channel-parser-tier-clause.mdandcontent-channel-parser-tier-clause-10928.test.tsare both present.This card closed
completedthroughFixes, andpm:dispatchedis removed. The only lane closure since the last landing is this card. objectui#10959, the sibling finding, is no longer serial-blocked by this PR; it awaits triage's grade.fix(types): content-channel refusals name the parser tier's not-a-con…