Repository navigation
Description
Filed from objectstack-ai/objectui#5418 (Studio dogfood, 17.1.0). Filed here, not in objectui, because the fix is producer-side: de-duplicating in the consumer is the alias-tolerance shape Prime Directive #12 forbids, so objectui deliberately did not touch it.
Measured
The publish-drafts response's failed[] entries carry both:
error— a summary string that already contains the rendered issue text, andissues[]— the same findings, structured ({ path, message }).
objectui's formatPublishFailures renders ${type}/${name}: ${error} and then one • path — message line per issue, which is the right thing to do with that contract — it is what turns an opaque banner into a field-anchored list. The result on the card's walk was the same sentence twice:
object/crmext_visit: [invalid_metadata] object/crmext_visit failed author-time validation:
objects[71].sharingModel: [security-owd-unset] custom object "crmext_visit" declares no
sharingModel (OWD). The runtime fails CLOSED to 'private' (ADR-0090 D1), but the baseline
must be an authored decision, not an accident — this is the exact shape of the leave_request
incident (objectstack-ai/objectui#2348). • objects[71].sharingModel — custom object "crmext_visit" declares
no sharingModel (OWD). …
The original reporter called this out directly: "a wall of English ADR prose (the same sentence twice, once as a summary and once as a bullet)".
Why the consumer must not fix it
Every plausible client-side fix is a guess about producer text — strip the summary when issues.length > 0 (loses the summary's own framing for non-validation failures), or substring-match the issue text out of error (a parser for prose). Both are exactly the consumer tolerance that hides producer drift.
Suggested shape
error should be the headline — what failed and why, one sentence — with the per-path detail left to issues[], which is the structured channel that exists for it. Consumers that render only error (logs, CLI) keep a usable message; consumers that render both stop repeating themselves.
Confidence / what I did NOT measure
The duplication is read off the reporter's captured console output plus objectui's formatter, which I did read. I did not run a live publish against a framework build to confirm which server-side site composes error — worth confirming before choosing where the change lands.
Related
- Studio's
新建对象produces an object that cannot be published:sharingModelis required, never asked for at creation, and the refusal arrives only at publish as a paragraph of ADR prose objectui#5418 — the console-side card. Its fix asks for the baseline at creation and mirrorsvalidateSecurityPosturein the pre-publish review sheet, so the OWD case is now usually reported before this string is ever produced. That narrows how often the duplication is seen; it does not change the contract.
Activity
os-zhuang commentedon Aug 21, 2026
Triage: producer-side fix (the publish-drafts
failed[]composer, framework side) →domain:engine,pm:queue, type Task. The consumer-side non-fix is already ruled posture (alias-tolerance forbidden), so the only landing site is whereerroris composed.Dispatch notes, premise-first: the filer did not confirm which server-side site composes
error— the dev's first step is locating it (likely the metadata publish path that buildsfailed[]entries; verify, don't inherit). Target shape as suggested:error= one-sentence headline, per-path detail stays inissues[]. Check consumers that render onlyerror(CLI, logs) keep a usable message — that is the acceptance criterion, not string equality with today. Relation: #10462 (open decision card onpublishPackageDraftssuccess:false semantics) touches the same response contract — if its ruling lands first, re-read this card's shape against it; do not pre-empt that ruling here.Size/model suggestion: S–M,
mode:subagent, opus.Generated by Claude Code
fix(metadata-protocol): render the spec-validation 422 findings claus…
Publish refusals: declare failed[].issues + seedApplied.issues, then …
test(metadata-protocol): inventory the DESTRUCTIVE_CHANGE 409's faces…
fix(metadata-protocol): render the spec-validation 422 findings claus…
feat(cli,metadata-protocol): the save door compiles an html page's so…
test(spec): the second api/ file group's test titles state each cited…