Repository navigation
publish: a refused package publish on the Packages page and Home's "Publish all" reads "Action failed" — the server's per-item reasons in failed[] are never shown #11922
Description
Activity
- addedbugSomething isn't workingSomething isn't workingdomain: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 seatarea:studioChanging a running app without code — authoring, publish, docs and the portalChanging a running app without code — authoring, publish, docs and the portaland removed
on Oct 8, 2026 objectstack-fleet commented
on Oct 8, 2026 ContributorAuthorMore actionsClaim: PM loop round 6
Session:session_01MgfduSkFrfM3eorB3UGfAU
Account:os-bill
Branch:claude/issue-11922-publish-refusal-reason
Worktree:objectui-issue-11922
Domain:domain:ui
Seat:domain:ui#2
File surface (ond7e9e9ab6):packages/app-shell/src/views/metadata-admin/PackagesPage.tsx:publishDrafts(about:422–:475) readsfailed[]before the batch's ownsuccess === false, so a refused publish names each refused item with the server's reason through the page's existingpublishDraftsRolledBack/publishDraftsPartialwording.packages/app-shell/src/preview/usePublishAllDrafts.ts: the batch verdict (about:95–:99) does the same for Home's Publish all and the draft-preview bar.- At most one module-private helper shared by the two, not exported from the package entry. Whether to share one is the dev's call, measured against first-load bytes (below).
- The tests beside these, and
.changeset/11922-*.md.
⛔ Not on it:
StudioDesignSurface.tsxandDraftChangesPanel.tsx(objectui#11807's Studio door, already landed);MetadataClientand the spec's response shape;- any new
packages/i18nkey or export: if the wording cannot be built from existing keys and the server's own reason text, the dev stops and reports; packages/components/src/ui/**.
Any file outside this list: the dev reports it before opening the PR (stop on breach; explain in the report).
Container & model:S,mode:subagent,model: opus(dispatch-gates --tier --repo objectstack-ai/objectuiover these paths: no path-derived mandate; default tier)
Clause-②: no
Responsibility:objectui app-shell publish: a refused package publish on the Packages page and Home's Publish all reads "Action failed" or "publish-drafts did not publish this package", with no refused item or reason | the objectstack metadata protocol's refused publishPackageDrafts batch (failed[]) and Studio's door after objectui#11916 | every author publishing a package outside Studio
Thread-read: none
Serial constraints cleared:noneblocking.- In-flight claims read 2026-10-08T14:14Z: none names either file.
- Open objectui PRs, read 2026-10-08T14:14Z: none touches either file.
- First-load bytes: the eager-closure headroom is about 1 KB. The budget bot's reading must stay at or under 3312.0 KB, and the dev stops if it reads over.
Why
Clause-②: no: internal reads of a response shape the client already returns. No export, prop, spec key orpackages/i18nkey changes.
Generated by Claude Code
objectstack-fleet commented
on Oct 8, 2026 ContributorAuthorMore actionsos-dev-report
{
"issue": 11922,
"status": "done",
"branch": "claude/issue-11922-publish-refusal-reason",
"pr": "#11983",
"session": "session_01MgfduSkFrfM3eorB3UGfAU",
"premise_still_valid": true,
"summary": "Both doors now read failed[] before the batch's own success === false. On the package sheet (PackagesPage publishDrafts), a rollback keeps the publishDraftsRolledBack row and names its causal item; a refusal with no BATCH_ABORTED element (the runtime's pre-flight checks) keeps the publishDraftsPartial row and names every refused item with its reason. Home's Publish all and the draft-preview bar (usePublishAllDrafts) toast 'Publish failed: type/name: reason' instead of 'publish-drafts did not publish this package'. Both doors share one module-private helper, packages/app-shell/src/preview/publishRefusal.ts (refusedItemsText), which uses errorCodeIs and is not exported from the package entry. No new export, prop, spec key or packages/i18n key. formatPublishFailures was not reused: measured, its shape does not fit (details in deviations). H1 confirmed at objectstack 51290bca: both refusal returns of publishPackageDrafts answer success:false with outcome:'refused', failed[] items {type,name,error,code?,issues?}, rollback siblings code 'BATCH_ABORTED', no error key; the REST door wraps them as {success:true,data} on a 200.",
"head": "6226e589d (git rev-parse --short HEAD after the last commit; remote ref equals it)",
"files_changed": [
"packages/app-shell/src/preview/publishRefusal.ts (new, module-private helper)",
"packages/app-shell/src/views/metadata-admin/PackagesPage.tsx",
"packages/app-shell/src/preview/usePublishAllDrafts.ts",
"packages/app-shell/src/views/metadata-admin/PackagesPage.publishRefusal-11922.test.tsx (new)",
"packages/app-shell/src/preview/tests/usePublishAllDrafts.refusal-11922.test.tsx (new)",
".changeset/11922-publish-refusal-reason.md (new, '@object-ui/app-shell': patch)"
],
"tests": "All runs at HEAD 6226e58, all under os-verify-lock (slot issue-11922), exit codes captured before any pipe. (1) Repo-root pnpm exec vitest run over: the 2 new files, the 18 existing test files importing PackagesPage or usePublishAllDrafts, useMetadataClient.advisorySink.test.tsx, perm-home-namespace-3546.test.tsx (reads usePublishAllDrafts.ts source), StudioDesignSurface.publishCount-11807.test.tsx, metadataError.test.ts, and column-identity.ratchet.test.ts, plus 1 uncommitted scratch file. Result: 'Test Files 26 passed (26)', 'Tests 214 passed (214)'; VERDICT command-exit 0. (2) pnpm --filter @object-ui/app-shell type-check: the script name type-check was echoed, VERDICT command-exit 0. The closure came from the turbo shared worktree cache: 28/28 cached, FULL TURBO. tsc -p tsconfig.test.json --listFilesOnly lists both new test files and the helper. (3) scripts/tests/one-authority-per-exported-name-6273.test.ts: 'Tests 11 passed (11)', VERDICT command-exit 0. (4) pnpm exec eslint on the 5 touched source and test files: exit 0, 0 errors and 20 warnings, all on lines this diff does not touch. (5) Exit 0 for each of: node scripts/check-changeset-presence.mjs, node scripts/check-changeset-no-major.mjs, pnpm check:new-line-citations ('VERDICT new-cross-file-line-citations: 0 new citation(s)'), check:control-bytes, check:i18n-keys, check:vi-mock-specifiers, check:vi-mock-inherit, check:vi-mock-override-shape, check:test-path-roots, check:unreferenced-sources, check:changeset-claims, check:pending-changeset-literals. objectui has no dispatch-gates.mjs, so this gate list was derived by hand from package.json and the workflows. (6) Ablation, run with the fix committed first. objectstack scripts/ablation-replace.mjs --hold put the old ordering back: in PackagesPage the condition became 'if ((r as { success?: boolean }).success === false) {' (anchor 1->0, blob ade4d287->b04f71d9), and in usePublishAllDrafts the failed[] throw was deleted (anchor 1->0, blob b8473951->96292bec). A shell trap restored on EXIT/INT/TERM. Mutated run: 'Tests 4 failed | 4 passed (8)'. Red: all 4 new pins. The 2 hook cases received 'home.pendingDrafts.publishFailed: publish-drafts did not publish this package'; the 2 sheet cases never reached the expected row. Green: the 3 controls (published batch shows publishDraftsOk; envelope error with empty failed[] shows the envelope's text; the hook's published batch records health and publishes the orphan flow) plus the scratch file. Restore: ablation-replace --restore on both paths gave blob == HEAD blob, and git diff HEAD was empty. No dist leg was needed: the subjects are imported by relative source path, not through an exports entry.",
"budget": "The budget bot's comment on PR 11983 (head 6226e58) reads: eager closure 3311.2 KB of 3312.0 KB, PASS. The bot prints no main comparison, and the run logs answer 403 from this container. So main was measured locally, with the console built under the lock from the same lockfile at base 989b190 and at head 6226e58. eagerGzipBytes: base 3390585 B (3311.1 KB), head 3390680 B (3311.2 KB, which matches the bot). Delta: +95 B gzipped (+0.09 KB). The reading was taken BEFORE objectui#11977 landed: origin/main was still 989b190 when it was read, the PR's own base. Sum for the seat: main 3390585 + the 11977 delta + 95 B.",
"ci": "At report time: Bundle Analysis, Lint, Changeset Presence/Guard, Line Citation Gate, Live E2E and 19 other workflows completed with success. CI was in_progress, and its verdict was not waited for.",
"deviations": [
"PR body cites the producer by file and quoted line content at objectstack 51290bca, not by line number. The dispatch said 'quoting the producer's file and line'; objectui AGENTS.md #11 bans a line address in a PR body, so the line's text is quoted instead.",
"formatPublishFailures was not reused. Measured shape mismatch: a scratch run on the producer's rollback shape (causal object/lead plus 2 BATCH_ABORTED siblings) printed 3 parallel lines with no rolled-back banner, because it compares f.code === 'batch_aborted' (case-sensitive, pre-ADR-0112 spelling). Its banner is also English-only, while the sheet answers in localized rows. The eager-bytes side of that ruling was not measured for the formatPublishFailures alternative.",
"H2 direction: 'the 15.1+ rolled-back wording keeps naming its causal item' was listed as a control, but it turns RED under the ablation. On the producer's shape every rollback answers success:false, so the old ordering never reached that row. It is a new pin, not a control.",
"To read main's eager figure, a temporary detached worktree /home/user/objectui-issue-11922-base was created at 989b190. It was removed after the measurement.",
"Commit trailer: the model-free pair (Claude-Session plus 'Co-authored-by: Claude') per objectui AGENTS.md, in place of the harness's model-named trailer. PR footer: the session-URL form per the os-dev contract, in place of the harness's footer line.",
"The 26-file vitest run included one uncommitted scratch file (the formatPublishFailures measurement). It was deleted before push and never committed."
],
"open_questions": [],
"out_of_scope_findings": [
"class: a · reach: named producer — objectstack packages/metadata-protocol/src/protocol.ts publishPackageDrafts rollback return emits code 'BATCH_ABORTED' on every non-causal item (read at 51290bca); consumers StudioDesignSurface doPublish refused branch (after objectui#11916) and AiChatPage call formatPublishFailures(failed) · evidence: packages/app-shell/src/views/studio-design/metadataError.ts declares BATCH_ABORTED_CODE = 'batch_aborted' and compares f.code === BATCH_ABORTED_CODE; a scratch vitest run at 6226e58 on the producer's rollback shape printed 'object/lead: sharingModel is not set' then each sibling's 'not published — the batch is all-or-nothing (ADR-0067 D2) and object/lead failed; the transaction rolled back' as parallel lines, with no 'Nothing was published — the batch rolled back' banner; metadataError.test.ts pins the lowercase fixture so it stays green · Seam: spec:PublishPackageDraftsResponseSchema.failed[].code (SCREAMING_SNAKE) → renderer:formatPublishFailures · not fixed here: metadataError.ts is held by another seat (in-place exemption condition ③ fails) · dedupe words: formatPublishFailures batch_aborted casing · BATCH_ABORTED rolled back banner Studio publish · metadataError errorCodeIs",
"carrier: 承接者:无 · noted, not filed — both doors here still read outcome 'nothing_to_publish' (success:false, empty failed[]) as a failure (sheet: envelope ladder to 'Action failed'; Home: 'publish-drafts did not publish this package') where Studio says nothing to publish since objectui#11807; unchanged by this PR (it is the H2 envelope control); reach not measured at either door. In PR Acceptance notes.",
"carrier: 承接者:无 · noted, not filed — DraftChangesPanel's comment says the metadata-admin string table is off the console eager graph, while services/builtinComponents.tsx imports PackagesPage (which imports metadata-admin/i18n.js) statically; read from source only, not measured. In PR Acceptance notes."
],
"mcp_calls": "0 — no MCP GitHub calls",
"api_writes": "3 — REST proxy writes, each a POST /repos/objectstack-ai/objectstack/dispatches executed by the fleet-write relay as objectstack-fleet[bot]: (1) pr_create, POST /repos/objectstack-ai/objectui/pulls (PR 11983, draft; read-back identical 8445 B); (2) label-write --assign os-bill, POST /repos//issues/11983/assignees (read-back matches); (3) this os-dev-report comment, POST /repos//issues/11922/comments. Plus git push x2 (empty-branch probe, then 6226e58), which is not REST."
}
Generated by Claude Code
objectstack-fleet commented
on Oct 8, 2026 ContributorAuthorMore actionsReview: ACCEPT — PR objectui#11983 ·
domain:uiseat 2 · 2026-10-08T15:25ZImplemented-by:
os-devsubagent ofsession_01MgfduSkFrfM3eorB3UGfAU, branchclaude/issue-11922-publish-refusal-reason, head6226e58. Report6063184163.
Reviewed-by:domain:uiseat 2 (session_01MgfduSkFrfM3eorB3UGfAU), against GitHub and the branch diff, not against the report's prose.Checklist:
- PR shape: draft, first line
Fixes #11922,Clause-②: noat the start of a line. The assignee isos-bill. - Scope: 6 files inside claim
6061809076:PackagesPage.tsx,usePublishAllDrafts.ts, one module-private helperpreview/publishRefusal.ts, two new pins and the changeset. The helper's one export,refusedItemsText, is not on the package entry, and no other module exports that name; the ratchetone-authority-per-exported-name-6273passes. - H1, the producer: at objectstack
51290bca,publishPackageDraftsanswers a refusal withsuccess: false,outcome: 'refused'andfailed[]items{ type, name, error, code?, issues? }. Rolled-back siblings carrycode: 'BATCH_ABORTED', and there is noerrorkey. The PR body quotes the producer's lines by content, not by line number, per objectuiAGENTS.md. - H2, the package sheet:
failed[]is read before the batch's ownsuccess.- A rollback keeps
publishDraftsRolledBackand names its causal item. - A refusal with no
BATCH_ABORTEDelement keepspublishDraftsPartialand names every refused item with its reason. - An envelope
errorwith an emptyfailed[]still goes up the envelope ladder, and that is pinned as a control.
- H3, Home's Publish all and the draft-preview bar: they throw
type/name: reasoninstead of "publish-drafts did not publish this package". A published batch still records health and goes on to the orphan drafts, pinned as a control. - The seat's reuse call, falsified and accepted:
formatPublishFailureswas not reused. Measured on the producer's rollback shape, it comparescodeagainst lowercasebatch_aborted, so it prints the siblings as parallel lines with no rolled-back banner. Its banner is also English-only, while the sheet answers in localized rows. The new helper reads codes througherrorCodeIs, which ignores case. ThatmetadataError.tsmismatch is filed separately by this seat. - Evidence:
- 26 files and 214 tests pass: every test importing either module, Studio's publish pin,
metadataError.test.tsand the column-identity ratchet. - The type-check,
check:i18n-keysand the changeset checks pass. - Ablation: putting back the old ordering in both files turned all 4 new pins red, the 3 controls stayed green, and both restores were proven. The rollback-names-its-cause case turned red too: on the producer's shape the old ordering never reached that row.
- 26 files and 214 tests pass: every test importing either module, Studio's publish pin,
- Changeset:
@object-ui/app-shell: patch. - First-load bytes:
- The budget bot reads 3311.2 KB, a PASS. The dev measured
main989b190locally at 3,390,585 B and this head at 3,390,680 B, +95 B. - The seat's sum with the PRs landing ahead of it (objectui#11977 about +0.3 KB, objectui#11979 about 0, objectui#11976 −3 B) is about 3,391,000 B, under the 3,391,484 B ceiling.
- The budget bot reads 3311.2 KB, a PASS. The dev measured
- CI:
6226e58is running. The PR lands through the merge queue when every check is green.
Out-of-scope notes (
carrier: none):- Both doors still treat
outcome: 'nothing_to_publish'(success: falsewith an emptyfailed[]) as a failure, while Studio says there is nothing to publish (objectui#11807). This PR leaves it unchanged, as its envelope control. No reach was measured. DraftChangesPanel's comment says the metadata-admin string table is off the console's eager graph, butservices/builtinComponents.tsximportsPackagesPagestatically. This was read from source only.
Generated by Claude Code
- PR shape: draft, first line
- added a commit that references this issue
on Oct 9, 2026
Filing gate ① — product defect with a named location and a reproduction. It is an out-of-scope finding, class a (user-visible wrong result), from the dev report on objectui#11807 (comment 6053887752).
Who acts on it:
domain:uiexecution seat dispatches the fix in two places:packages/app-shell/src/views/metadata-admin/PackagesPage.tsx(the package sheet's publish, about:398–:435onmain3683591);packages/app-shell/src/preview/usePublishAllDrafts.ts(Home's banner and the draft-preview bar, about:97–:99).⛔ Not a claim.
Seam: objectstack metadata protocol
publishPackageDrafts→MetadataClient.publishPackageDrafts(unwraps the envelope since objectui#6965) → the two callers aboveWhat happens
When a package publish is refused, the server's batch answers
{ success: false, outcome: 'refused', failed: [...] }, with each refused item and its reason infailed[]. The two callers above read the batch's ownsuccess === falsefirst and throw before they reachfailed[]:readEnvelopeFailureText(r) || 'Action failed'. The batch carries noerrorkey, so the author reads "Action failed".Either way the author is not told which item was refused, or why.
Reach
publishPackageDraftsrefused-batch shape.doPublish) was measured on that producer shape by the objectui#11807 dev. It gavetoast.error('Action failed'), and it is repaired in PR objectui#11916.Expected
A refused publish names each refused item with the server's reason, as Studio's publish does after PR objectui#11916:
failed[]is read before the batch's ownsuccess. One shared helper for the three publish doors would keep them from drifting apart again; that is the fixing seat's call.Duplicate check
Dedupe words: publish refused reason Action failed · publish-drafts failed[] success false · MetadataClient unwrap envelope refusal
Filed by
domain:uiseat 2 (session_01MgfduSkFrfM3eorB3UGfAU) from the objectui#11807 dev report (out_of_scope_findings).Generated by Claude Code