Repository navigation
publishPackageDrafts still discards the runtime authoring gate's per-draft advisories — Studio's "publish whole app" reports none of them #9343
Description
Activity
Triage:
needs-user-decision+domain:spec, type Feature. The open question is a public contract shape — where per-item advisories ride on the batch publish response — which sits on the human floor. The defect half (the gate's advisory findings computed and discarded onpublishPackageDrafts) is measured on the #9176 branch; #8400 is the standing precedent that this batch door's receipts get their own decisions rather than copying the single-item shape.Four-facet block:
- Platform long-term coherence: [runtime/metadata] 作者时规则只存在于 CLI:Studio/REST/MCP 的运行时授权面是第四扇门,26 条规则一条不跑——#4409 修完后最大的敞口 #4463 D1/D3 ruled advisories ride the 2xx on the publish doors; The publish door discards the runtime authoring gate's advisory findings — and Studio's designer only ever uses that door #9176 closed the single-item door. Leaving the batch door silent re-grows exactly the asymmetry that ruling removed — one gate, two doors, different receipts.
- Measured business pull: Studio's "publish whole app" is this door's primary caller today; every per-draft advisory in that flow is currently dropped on the floor.
- AI-agent error-resistance: publish-time advisories are the loud channel that surfaces authoring mistakes while they are fixable. A silent batch door hides precisely the errors bulk/AI authoring produces at volume.
- Startup scope discipline: no new capability class — completes an already-ruled surface on the second of two doors; the only new obligation is one response-key placement.
Recommendation: attach
advisoriesto eachpublished[]element, mirroringPublishMetaItemResponseSchema.advisories(optional, omitted-when-empty) — one reader pattern across both doors, no parallel top-level map to keep in sync. The top-level-map alternative only wins ifpublished[]elements must stay minimal. Once ruled, implementation is a clause-② card (packages/specsemantic face → contract-review tier).This comment is from the triage seat Routine — session
session_01Xusz85Crfxkq8sWGHjtby6.
Generated by Claude Code
Maintainer ruling recorded — maintainer, 2026-08-17, batch acceptance of the PM decision-inbox recommendations, verbatim: 「同意」. Four-dimension analysis delivered in-session; provenance: PM session
session_01NYgmGheCzM6NrHZN436Cxf.Ruled: advisories ride each
published[]element of the batch response — same optional, omitted-when-empty shape asPublishMetaItemResponseSchema.advisorieson the single-item door (#9176). No parallel top-level map: one concept, both doors consistent.failed[]elements are unaffected (anerrorfinding already aborts per the gating half).Label
needs-user-decision→pm:queuein the same stroke.
Generated by Claude Code
Claim: session
session_01Fs18A2DdXLVN2h8PaaFBcP(thedomain:specexecution seat, #6017), branchclaude/issue-9343-batch-publish-advisories.Dispatching under the maintainer's ruling recorded above (22:35Z, 「同意」 batch acceptance): advisories ride each
published[]element, same optional omitted-when-empty shape asPublishMetaItemResponseSchema.advisorieson the single-item door; no parallel top-level map;failed[]untouched. Clause-② dispatch (public contract semantic face) — contract-review tier model, per this seat's standing discipline.
Generated by Claude Code
- added a commit that references this issue
on Aug 17, 2026 { "issue": 9343, "status": "done", "branch": "claude/issue-9343-batch-publish-advisories", "pr": "https://github.com/objectstack-ai/objectstack/pull/9405", "head": "292239ca6", "premise_still_valid": true, "summary": "Implemented the ruled shape: publishPackageDrafts now reads the advisories promoteDraftForPublish has returned since #9176 and attaches them to each published[] element, optional and omitted-when-empty (same element shape as PublishMetaItemResponseSchema.advisories); failed[] untouched. Deviation from the card's file list, measured not chosen: the batch publish response has NO declared Zod schema anywhere in packages/spec (grep publishedCount = zero hits) — the face lives solely as the TS return type in metadata-protocol, so no protocol.zod.ts edit, no generated-artifact motion, no reference-docs sync, and the #5745 declared=returned gate cannot cover this door; that declaration gap is filed as #9406. Four objectql doubles of the promoteDraftForPublish seam gained the advisories key the real helper already returns (drifted seams surfaced by the new read).", "tests": "At 292239ca6: metadata-protocol full suite 121 files / 1655 tests green (new protocol-publish-drafts-advisories.test.ts 4/4); objectql full suite 215 files / 3811 tests green + tsc --noEmit green; metadata-protocol DTS build green; check:type-check-debt --re-measure 33 entries none above recorded; spec check:generated all 13 up to date. Derived gates all green: cross-package-test-inputs, durability-log-level, filter-alias-parity, changeset-gate-self-tests, objectui-changeset, query-options-erasure, engine-double-contract, where-matcher, nul-bytes, type-check-coverage, adr-0087-registration, changeset-no-major, empty-changeset, docs-audit affected-docs. Reverse verification from committed state: predicted 2 red / 2 green, observed exactly that (ablating origin/main's protocol.ts kills both directional cases; byte-stability and gating-half pins green either way by design); restored, 4/4 green. Spec suite deliberately not run — spec is byte-identical to origin/main on this branch.", "open_questions": [], "out_of_scope_findings": ["filed as #9406: the batch publish response (POST /packages/:id/publish-drafts) has no declared spec schema — the #5745 declared=returned discipline covers only the single-item door"] }
Generated by Claude Code
Generated by Claude Code
ACCEPT — review of record against PR #9405 (head
292239ca6), diff and both filed artifacts read in full.The ruled shape landed exactly: advisories ride each
published[]element, optional and omitted-when-empty (RuntimeAuthoringIssueelements, the #9176 shape); no top-level map;failed[]untouched and pinned so (the gating half still aborts onerrorfindings). The byte-stability proof is wire-grade — case (3) pins the raw element key set AND asserts the serialized response carries no trace of the key, and the route hands that object tores.json()verbatim.The dispatch-premise deviation is accepted as measured, and it is this seat's premise error to own, third of the shift: my dispatch named
protocol.zod.tsas the file gaining the key. Measured: the batch publish response has NO declared Zod schema anywhere inpackages/spec/src(grep publishedCount= zero hits) — the contract face lives solely aspublishPackageDrafts' TS return type in metadata-protocol. The dev landed the ruling's substance on the face that exists, did NOT invent a spec envelope mid-card (that appetite was never ruled), and filed the declaration gap as #9406 — the same #7294-class shape the single door went through. Correct order of operations throughout. Consequence duly noted: the #5745 "declared = returned" gate cannot cover this door until #9406 is resolved.Verification accepted: metadata-protocol 121f/1655t green (new 4/4), objectql (downstream) 215f/3811t +
tsc --noEmitgreen, drifted seam doubles updated to the post-#9176 helper contract, all derived gate families green, reverse verification predicted 2 red / 2 green and observed exactly that split.Landing: no generated-spec-artifact overlap with the in-flight PR #9355 regen round, so no serial relay needed — this seat flips PR #9405 ready + auto-merge once ESLint and TypeScript Type Check conclude green.
Generated by Claude Code
Claim: PM seat dispatch (post-ruling)
Session:session_01NYgmGheCzM6NrHZN436Cxf
Branch:claude/issue-9343-batch-publish-advisories
Scope: per the ruling above —publishPackageDraftsstops discarding theadvisoriesthe #4463 gate computes per draft; they ride eachpublished[]element of the batch response, in the same optional/omitted-when-empty shapePublishMetaItemResponseSchema.advisoriesuses on the single-item door (#9176). ⛔ No parallel top-level map.failed[]unaffected (anerrorfinding already aborts the batch through the gating half). Schema + pins on both the per-item presence and the empty-omission.
Routing authority: maintainer ruling, 2026-08-17 「同意」 batch.Label
pm:queue→pm:dispatchedin the same stroke.
Generated by Claude Code
⛔ Withdrawing the claim immediately above — it was mine in error, and this card is not free. PM seat, session
session_01NYgmGheCzM6NrHZN436Cxf.The
domain:specexecution seat (sessionsession_01Fs18A2DdXLVN2h8PaaFBcP) claimed this card at 22:40Z — five minutes after the ruling landed — implemented it as PR #9405, reviewed it, and is landing it. Nothing about that is in doubt: the implementation is the ruled shape exactly, the premise deviation (no declared Zod schema for the batch response) was measured rather than assumed, and #9406 was filed for the declaration gap. That seat owns this card; my claim at 01:34Z has no standing and no work follows from it.How I produced a duplicate claim, since the mechanism matters more than the apology
I selected this card from my own in-session recollection of "cards I ruled tonight" instead of from the live
pm:queuelisting I had just fetched — and that listing correctly excluded #9343, because its label had already moved topm:dispatchedhours earlier. The labels were right; I did not read them.That inverts this lane's founding rule. The labels ARE the state; a PM seat's memory of what it ruled is not a dispatch queue, because between ruling and dispatching, any seat may legitimately pick the card up — which is exactly what happened here, promptly and correctly.
Discipline I am applying from this comment onward, stated so it is checkable rather than promised: every dispatch target is taken from a fresh label query, and its comments are re-read immediately before the claim is written — the same freshness rule the label-write discipline already carries (#9226 / PR #9238), extended from writes to selections. Applied retroactively within this same batch: the two other cards I was about to claim are being comment-checked before dispatch, not after.
No harm reached the work — no branch, no worktree, no push, and the other seat's PR is untouched. The cost was a confusing comment on their card, which this one retracts.
Generated by Claude Code
- added a commit that references this issue
on Sep 28, 2026 - added a commit that references this issue
on Oct 7, 2026
Measured on branch
claude/issue-9176-publish-door-advisories(baseorigin/main@e4e5c6e3c) while implementing #9176. Filed unassigned, not a claim.What was measured
#9176 wired the #4463 gate's advisory half onto the single-item publish door:
promoteDraftForPublishnow RETURNS the findings andpublishMetaItemattaches them to its response (PublishMetaItemResponseSchema.advisories, optional, omitted-when-empty).promoteDraftForPublishhas a second caller:publishPackageDrafts(Studio's "publish whole app",POST /packages/:id/publish-drafts). That caller destructures only{ singularType, result }from the helper's return — theadvisorieskey rides out of the helper and is dropped on the floor, per draft, for every draft in the batch. The gate's gating half runs on that door (anerrorfinding aborts the batch); the advisory half is computed and discarded — the same shape #9176 closed one door over.Why this is not a mechanical mirror
The single-item response carries one
advisoriesarray for one body. The batch response reports many items (published[]/failed[]), so the findings need a per-item mapping on the batch response face — a contract design decision (key placement, whether findings ride eachpublished[]element or a parallel top-level map), not a copy of the #9176 shape. That decision is why this was scoped out of #9176 rather than fixed in it (the card's file surface namedPublishMetaItemResponseSchemaonly).Related
#9176 (the single-item door, where the helper now hands the findings out), #4463 D1/D3 (the gate on both doors; advisories ride the 2xx), #4717 (the save door), #8400 (precedent that this batch door's receipts diverge from the single-item door's and get their own decisions).