Skip to content

feat(spec): declare publishMetaItem as an optional MetadataProtocol member with PublishMetaItemRequest - #11426

Merged
os-steve merged 1 commit into
mainfrom
claude/issue-11006-publish-meta-item-member
Aug 23, 2026
Merged

feat(spec): declare publishMetaItem as an optional MetadataProtocol member with PublishMetaItemRequest#11426
os-steve merged 1 commit into
mainfrom
claude/issue-11006-publish-meta-item-member

Conversation

@os-steve

@os-steveos-steve commented Aug 23, 2026

Copy link
Copy Markdown
Collaborator

Fixes#11006

Executes the maintainer ruling recorded on the card (2026-08-22, 「同意所有」, item 5 = B): declare publishMetaItem as an optional member of MetadataProtocol, accepting a newly declared PublishMetaItemRequest and returning a Promise of the already-declared PublishMetaItemResponse (#7294). This closes the half-declared door: the response side was declared while the request and the member were not, so the request literal at the one HTTP call site was checked by nothing (the cast there carried member-existence weight — measured on the card as TS2339, not TS2353).

What changed

  • packages/spec/src/api/protocol.zod.ts
    • PublishMetaItemRequestSchema + PublishMetaItemRequest{ type, name, organizationId?, actor?, message?, packageId? }, mirroring the implementation's parameter type in @objectstack/metadata-protocol member for member. packageId is string-or-null-or-absent with the absent-vs-null sharp edge documented (absent = match any package; null = pin to the package-unbound row).
    • The new optional MetadataProtocol member publishMetaItem — takes PublishMetaItemRequest, returns a Promise of PublishMetaItemResponse; optionality consistent with the deleteMetaItem / getMetaItemLayered precedent (additive to a shipped contract, implementation predating declaration).
  • packages/spec/src/api/protocol.test.ts — schema pins (value-preserving accepts, required type+name, packageId null-vs-absent distinguishability, environmentId and _skipSeedApply shape-absent + stripped) and type-level pins (member optional; an undeclared key in a request literal fails compilation at the member's call shape via @ts-expect-error, compiled by the spec test typecheck program).
  • packages/spec/src/type-alias-convention.pin.test.ts — ADR-0122 pin Iso856 (request schema measured isomorphic: no default/transform/catch/pipe anywhere in its tree), count 836 → 837 with receipt.
  • Regenerated (via check:generated --fix, only the proved-stale set):api-surface/, export-origins/, content/docs/references/**, strictness-ledger counts; the spec build moved authorable-surface/api.json and json-schema.manifest/api.json by exactly the new schema's entries.
  • Changeset:minor for @objectstack/spec (additive public member; not breaking, so no ADR-0087 disposition marker is owed).

Request-shape derivation (wire-measured, not invented)

Declared keyWire evidence
type, name (required)Path params of POST /api/v1/meta/:type/:name/publish; required on the implementation's parameter type
organizationId?REST door resolves it via organizationIdForMetaWrite(...) and always sends it; implementation resolves the draft through the org partition (ADR-0005 / the #8805 fix)
actor?REST door sends resolveMetaWriteActor(...) (authenticated identity, one producer — #7749)
message?REST door reads body.message when it is a string
packageId? (string or null)The package query param (#10063), declared on the implementation with null-vs-absent semantics (#10350 / PR #11005)

Deliberately not declared: environmentId (transport-level multi-kernel routing key — OUT of protocol request shapes by the #9741 maintainer ruling of 2026-08-18; packages/rest layers it via TransportScopedMetaRequest) and _skipSeedApply (internal batch coordination for publishPackageDrafts, never read from the wire).

Cross-lane linkage — call-site consumer for the engine seat

The one HTTP consumer of this member is packages/rest/src/rest-server.ts, the POST ${metaPath}/:type/:name/publish handler, which today reaches the verb as (p as any).publishMetaItem({...}) (feature-detection cast around line 6027, with the #10350 measurement comment above it). Removing that cast (and typing the literal via the #9741TransportScopedMetaRequest wrapper) is the engine lane's work, tracked in #11145#11145 remains open and is deliberately not touched by this PR.

Verification (all at commit 10931f2edf, the branch head — no commits after the runs)

  • pnpm --filter @objectstack/spec build — exit 0 (✓ packages/spec/dist/.build-input-hash)
  • pnpm --filter @objectstack/spec check:generated — after --fix: all 4 stale artifacts regenerated, re-verdict clean
  • pnpm --filter @objectstack/spec test419 files / 11152 tests passed, exit 0
  • pnpm --filter @objectstack/spec typecheck — exit 0, including check:test-typecheck ("OK — test layer compiles"; debt counts held, so the new @ts-expect-error pins compiled and fired)
  • pnpm lint (full repo eslint . --no-inline-config) — exit 0
  • Derived gates (node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack, answered from this tree at 10931f2edf): 36 derived/convention families run locally, all exit 0 — including check:spec-parsed-alias, check:strictness-ledger, check:liveness, check:empty-state, check:merge-driver, check:engine-double-contract, check:where-matcher, check:query-options-erasure, check:type-check-coverage, ADR-0087/changeset gates, docs gates.
  • Reverse verification against the rebuilt dist (consumer-side, two legs): a probe in packages/metadata-protocol importing from @objectstack/spec/api — RED leg: undeclared keys packageID / environmentId answered TS2561/TS2353 naming the full declared shape (proves the rebuilt declaration file carries the type and refuses undeclared keys); GREEN leg: the implementation class's instance type extends MetadataProtocol, and the member-vs-member function check compiles, exit 0 (proves the shipped implementation satisfies the widened interface). Probes deleted; tree clean.
  • Declared narrowings (CI covers the full runs): ① check:type-check-debt --re-measure refuses locally without the full 32-package built closure (its own loud refusal); population = the 13 ledgered packages in scripts/check-type-check-coverage.mjs; the only ledgered package that names the changed surface is @objectstack/metadata-protocol (repo-wide grep: sole implements … MetadataProtocol implementer with a publishMetaItem method), and the green probe above answers exactly that compile question against rebuilt dists; an added optional member + new exports cannot move tsc verdicts in packages that never name them. ② check-dev-prereqs.mjs reds locally on "43 sibling packages have no dist on disk" — a fresh-worktree environment precondition (CI builds the workspace first); the spec-dist half is green from the fresh build.

Generated by Claude Code

…er with PublishMetaItemRequest (#11006)
Maintainer ruling 2026-08-22 (option B) closes the half-declared publish
door: #7294 declared the response side; this declares the request schema
and the optional interface member, mirroring the implementation parameter
type member for member. environmentId stays transport-level per the #9741
ruling; _skipSeedApply stays internal. ADR-0122 pin Iso856 records the
request schema isomorphic.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T9cDbY2NBiVJWYx3BpWfH2
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/spec, touching 8 documentable anchor(s).

4 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:

  • content/docs/api/client-sdk.mdx(via meta.publishItem (sdk), publishItem (sdk))
  • content/docs/deployment/validating-metadata.mdx(via publishMetaItem (symbol))
  • content/docs/kernel/contracts/metadata-service.mdx(via /:type/:name/publish (route), /api/v1/meta/:type/:name/publish (route))
  • content/docs/kernel/services-checklist.mdx(via MetadataProtocol (symbol))

2 release-owned page(s) also name something this change touched. These are read-only:

  • content/docs/releases/v15.mdx(via MetadataProtocol (symbol))
  • content/docs/releases/v17.mdx(via MetadataProtocol (symbol), publishMetaItem (symbol), /:type/:name/publish (route))

content/docs/releases/ is RELEASE-OWNED (AGENTS.md "Documentation Guardrails"): release
notes are written centrally at release time, and a code PR that edits them is the exact PR
that guardrail exists to stop. They are still audited — read-only. If one of them is actually
wrong, file an issue or open a dedicated docs-only PR; do not edit it here.

What this run could not see
  • 4 changed file(s) yielded no anchor (packages/spec/api-surface/api.json, packages/spec/authorable-surface/api.json, packages/spec/export-origins/api.json, …) — pages documenting those are invisible to this run
  • the SDK route bridge reached 45 of 222 client-bound route-ledger rows — the other 177 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run: node scripts/docs-audit/affected-docs.mjs --bridge-coverage

Coarse fallback — 126 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 68e8b4b53c387eb56d3c6ec4a976acf385eb977dpackageMentionDocs.

Which tree this was computed on

This run read content/docs from df001338a45c3bb001eeaacbeb617ea2e751ad95 — the merge of head 10931f2edf02b14bb48edef2ebbf74332251b23d into base 68e8b4b53c387eb56d3c6ec4a976acf385eb977d, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin df001338a45c3bb001eeaacbeb617ea2e751ad95 && git checkout df001338a45c3bb001eeaacbeb617ea2e751ad95
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 68e8b4b53c387eb56d3c6ec4a976acf385eb977d 10931f2edf02b14bb48edef2ebbf74332251b23d && git checkout -B drift-repro 68e8b4b53c387eb56d3c6ec4a976acf385eb977d && git merge --no-ff 10931f2edf02b14bb48edef2ebbf74332251b23d
node scripts/docs-audit/affected-docs.mjs --json 68e8b4b53c387eb56d3c6ec4a976acf385eb977d

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs 68e8b4b53c387eb56d3c6ec4a976acf385eb977d → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation tests tooling labels Aug 23, 2026
@os-steve
os-steve marked this pull request as ready for review August 23, 2026 17:44
@os-steve
os-steve added this pull request to the merge queueAug 23, 2026
Merged via the queue into main with commit cccbe51Aug 23, 2026
42 checks passed
@os-steve
os-steve deleted the claude/issue-11006-publish-meta-item-member branch August 23, 2026 18:01
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/mteststooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[裁决] MetadataProtocol 是否应声明 publishMetaItem 成员 —— 半声明的门(响应已声明、请求未声明)

2 participants

@os-steve@claude