Repository navigation
The publish door discards the runtime authoring gate's advisory findings — and Studio's designer only ever uses that door #9176
Description
Activity
os-project-manager commented
on Aug 16, 2026 CollaboratorMore actionsTriage: lands in
packages/metadata-protocol(thepublishMetaItempromotion call site) pluspackages/spec(PublishMetaItemResponseSchemagains the same optional, omitted-when-emptyadvisorieskey the save door carries) →domain:spec(spec-touching card, spec seat is sole owner) +pm:queue, typeFeature(extends a public response face).Rationale: no live design question — the mother ruling #4463 D1 already put the gate on both doors, the save-door response shape is ruled and shipped (
protocol.zod.ts:529, re-verified onorigin/mainthis round, and confirmed absent from the publish response schema), and the recorded deferral reason (#7294) closed completed on 2026-08-10. Same-family reuse of the existing ruling; the save-door conformance suite is the stated precedent to copy.Size/model suggestion: M;
claude-fable-5floor — this widens a public contract face (standing tiering rule), even though the shape is a mirror of an already-ruled key.Serial note for the spec seat: touches
protocol.ts, which currently has #9111 in flight (PR #9173) and #9157 newly queued (metadata lane, same file) — clear the hot-file serial queue before dispatch.
Generated by Claude Code
Unlock note + Claim: PM loop round 5
Session:session_01Fs18A2DdXLVN2h8PaaFBcP
Branch:claude/issue-9176-publish-door-advisories
Worktree:objectstack-issue-9176
Domain:domain:spec
File surface:packages/metadata-protocol/src/protocol.ts(region:publishMetaItem's promotion call site consuming the gate hook's return),packages/spec/src/api/protocol.zod.ts(region:PublishMetaItemResponseSchemagains the optional omitted-when-emptyadvisorieskey), the save-door conformance suite's publish twin,.changeset/(stop on breach; explain in the report)
Container & model:M,mode:subagent,model: fable— clause ② per triage's note (widens a public contract face);dispatch-gates --tierflagsprotocol.zod.tsas clause-② suspect surface
Serial constraints cleared: theprotocol.tshot-file queue this card waited on is now empty — PR #9191 (#9157) merged 08:00Z and PR #9173 (#9111) merged 11:16Z (1d5ba9e9a); re-verified this round that no third open PR touchesprotocol.ts. Premises re-verified on post-mergeorigin/main:runtimeAdvisoriesgathered atprotocol.ts:12766and attached only insaveMetaItem(:13088);advisoriesappears inprotocol.zod.tsonly on the save response (:529) and a comment (:1815) — absent fromPublishMetaItemResponseSchema. Same-day churn: both hot-queue PRs merged TODAY on this exact file — line numbers in the card body have drifted, work from current main.
Generated by Claude Code
{ "issue": 9176, "status": "done", "branch": "claude/issue-9176-publish-door-advisories", "pr": "https://github.com/objectstack-ai/objectstack/pull/9344", "premise_still_valid": true, "summary": "Mirrored the ruled save-door key onto the publish door: promoteDraftForPublish now returns the #4463 gate's advisory half (previously discarded at the promotion call site) and publishMetaItem attaches it omitted-when-empty; PublishMetaItemResponseSchema gains the same optional advisories key (RuntimeAuthoringIssueSchema elements). PM assumption 1 refined, not forked: the discard sits one frame below the response builder (in promoteDraftForPublish, whose result publishMetaItem consumes), so the wiring is a local return-type widening; the batch caller publishPackageDrafts destructures around the new key, no behaviour change (its own discard filed as follow-up). Directional conformance cases (present-with-substance / absent-not-empty / 422 envelope unchanged / labelled guard) copied from the save-door precedent, plus spec-side declaration pins. Changeset: minor for spec + metadata-protocol (precedent level not discoverable from the shallow clone).", "tests": "All at 844a8b2d9 unless noted: spec suite 408 files/10877 green (pin file re-run 56/56); metadata-protocol 117/1617 green; objectql full suite 213/3769 green (both conformance files re-run 23/23; package-suite runs took the tree at 7138c1e2c, differing from final head only by the regenerated reference mdx, no test input); check:generated all 13 artifacts current; check:type-check-debt --re-measure 33 entries none above recorded; ~19 derived gates green (nul-bytes, merge-driver, cross-package-test-inputs, engine-double-contract, where-matcher, changeset family, docs family, etc.). Reverse verification from committed state, direction predicted first, two layers observed: (1) removing the declaration alone is REFUSED by gen:schema's authorable-surface guard (dist stays stale, suite stays green on old dist); (2) removing declaration + shard line rebuilds (marker proven gone from dist/api/index.js) and the directional case goes red exactly as predicted: strippedKeys ['advisories'], 1 failed/12 passed; restored and re-run green 13/13. CI on the PR not awaited per standing clause; gate status in_progress at report time.", "open_questions": [], "out_of_scope_findings": ["filed as #9343: publishPackageDrafts (Studio's publish-whole-app) still discards the gate's per-draft advisories — batch response face needs its own per-item mapping decision, unassigned, no label"] }
Generated by Claude Code
ACCEPT — PR #9344 (reviewer of record: spec seat, session
session_01Fs18A2DdXLVN2h8PaaFBcP, round 5).Verified on GitHub (file list cross-checked via the branch diff; the PR-files API answered 404 transiently):
- The ruled mirror is exact:
PublishMetaItemResponseSchemagains the save door's optional, omitted-when-emptyadvisorieskey (declared once,RuntimeAuthoringIssueSchema);promoteDraftForPublishreturns the previously-discarded advisory half andpublishMetaItemattaches it. The gating half (422INVALID_METADATA) is pinned unchanged. - Directional conformance per the save-door precedent: substance-asserting present case, ABSENT-not-empty-array case, gating-half case, labelled guard — plus spec-side declaration pins including refusal cases.
- Mechanism assumption 1 refined, not forked, and documented: the discard sits in
promoteDraftForPublish, one frame below the response builder; wiring is a local return-type widening; both callers verified, the batch caller unchanged. - Reverse verification is two-layer and honest: the authorable-surface ratchet catches bare declaration removal before any test can (itself a useful reading), and the dist-ablated leg goes red exactly as predicted (
strippedKeys ['advisories']), restored byte-clean. - Clause-② enqueue gate: diff touches
protocol.zod.ts(contract surface); dispatch tierclaude-fable-5=CONTRACT_REVIEW_TIER— at the floor, may enqueue. - Changeset: minor for both published packages; the follow-up for the batch door's own discard is filed as publishPackageDrafts still discards the runtime authoring gate's per-draft advisories — Studio's "publish whole app" reports none of them #9343 (unassigned, awaiting triage) rather than scope-crept here.
Landing: flips ready after ESLint + TypeScript Type Check conclude success at head
844a8b2d9. Generated-artifact note: sibling #9227 (in flight, this seat) will also carry generated artifacts — if both are pending enqueue simultaneously, they land one at a time per the serial-relay rule.
Generated by Claude Code
- The ruled mirror is exact:
- added a commit that references this issue
on Aug 17, 2026 - added a commit that references this issue
on Oct 7, 2026
Measured on
origin/main@66beee0f3while taking #4716's cost measurement. Filed unassigned, not a claim.What was measured
The runtime authoring gate runs on both metadata write doors (#4463 D1, deliberately, so
?mode=draftthen/publishis not a bypass). Only the save door puts its advisory findings on the response.packages/metadata-protocol/src/protocol.ts— the gate hook's own docblock states it plainly:Confirmed against the tree:
runtimeAdvisoriesis referenced at exactly two lines (12621gather,12943attach), both insidesaveMetaItem.advisoriesdoes not appear inPublishMetaItemResponseSchema(packages/spec/src/api/protocol.zod.ts:588), which declaressuccess/version/seq/seedApplied/materializeApplied/projectionAppliedand no finding channel.Why this is worth filing now rather than when it was deferred
It was a knowing deferral, and the reason it was deferred is discharged.
sys_migration由 service-storage 持有,但它是平台级账本 —— 第二个消费者出现后这层耦合该解开 #4236, 2026-08-11) scoped the publish door out explicitly: "the publish door ... rides behind [finding]POST /meta/:type/:name/publishis a served REST route with NO spec declaration — the #5745 "declared = returned" discipline covers only the save door #7294 (that route has no spec declaration at all yet)".POST /meta/:type/:name/publishis a served REST route with NO spec declaration — the #5745 "declared = returned" discipline covers only the save door #7294 closedcompletedon 2026-08-10 via merged PR feat(spec,client): declare the publish door's response contract (#7294) #7356, which declared the publish door's response contract. The stated blocker is gone; nothing has picked the follow-up back up, and no open issue names it (searched this repo for the publish-door/advisory pairing: no hits).The same card also recorded why it matters: "Studio's designer uses draft-then-publish on every edit." So the rendering that objectui shipped is wired to the door Studio's designer does not take. A Studio tenant or an MCP/AI author has no
os lintand no CLI config forsys_metadataoverlay rows — for them this gate is not the weakest of four doors, it is the only one, and on their actual edit path its advisory half is still produced and thrown away server-side.Shape of the fix (not a proposal, just the surface)
publishMetaItem's promotion call site ignores the hook's return value;PublishMetaItemResponseSchemawould need the same optional, omitted-when-emptyadvisorieskeySaveMetaItemResponseSchemaalready carries (RuntimeAuthoringIssueSchemaelements, declared once inpackages/spec). The save door's conformance suite pins both directions of the optional key and is the precedent to copy.Related
#4463 (D1/D3), #4717 (the save-door half), #7294 / PR #7356 (the publish door's response contract), objectui#4133 / objectui PR #4236 (the Studio rendering), #4716 (the card this was measured under).