Repository navigation
Description
Found while implementing #11145 (the publishMetaItem consumer cleanup). This is the sharper of the two siblings that turned up, because it reads as already done and is not.
Measured on origin/main @ c251ef4213
MetadataProtocol does declare the member (packages/spec/src/api/protocol.zod.ts, in the same optional family as getMetaItemLayered):
deleteMetaItem?(request: DeleteMetaItemRequest): Promise<DeleteMetaItemResponse>;But DeleteMetaItemRequestSchema (line 1121) declares exactly two members:
export const DeleteMetaItemRequestSchema = lazySchema(() => z.object({
type: z.string().describe('Metadata type name'),
name: z.string().describe('Item name'),
}));The REST reset door (packages/rest/src/rest-server.ts:5704) sends eight:
const result = await (p as any).deleteMetaItem({
type: req.params.type,
name: req.params.name,
organizationId,
...(environmentId ? { environmentId } : {}),
...(parentVersion !== undefined ? { parentVersion } : {}),
...(actor ? { actor } : {}),
...(stateParam ? { state: stateParam } : {}),
...(dropStorage ? { dropStorage: true } : {}),
});Six of the eight — organizationId, environmentId, parentVersion, actor, state, dropStorage — are on the wire today with no declaration behind them. The guard at 5640 (if (!(p as any).deleteMetaItem)) is cast for the same reason the call is.
Why the declared member is not enough here, and why that is the trap
#11145 removed the publishMetaItem cast the moment the member was declared, because the cast there was load-bearing on member existence — measured as TS2339, not TS2353. This door is the opposite half: the member exists, so TS2339 is already gone, and what remains is genuinely a request-shape problem. Removing the cast here would surface TS2353 on six keys rather than compiling clean.
That difference matters for triage: a reader scanning for undeclared members finds this door declared and moves on, while its request surface is emptier than any other write door's. organizationId in particular is load-bearing for tenant scoping — the comment above the call site (~5690) records that passing no organization would reset the env-wide row for every tenant, i.e. the one member most worth having a contract is among the undeclared six.
What the decision is
The same one #11006 took for publish, on a bigger surface: declare the request members that are really part of the contract, and decide per member which are transport-level rather than protocol (environmentId is already ruled transport-level by #9741, 2026-08-18, and belongs in packages/rest's TransportScopedMetaRequest envelope, not in the schema). _skipSeedApply-style internal coordination keys, if any exist here, stay out on the same reasoning #11426 recorded for publish.
domain:spec decision; #11145's engine-lane PR deliberately did not touch it — the bounded in-place exemption does not apply, since the correct shape is not pinned by existing evidence. ⛔ Nothing about this door is addressed in that PR.
Related: #11006 (the ruling this mirrors) · #11426 (its spec landing) · #9741 / #9726 (the meta-read schemas' equivalent catch-up) · #9805 (the non-door helper literals) · ADR-0005 (reset-to-artifact-default semantics) · ADR-0076 D9
Activity
os-zhuang commentedon Aug 24, 2026
Triage: lands in
packages/spec(thedeleteMetaItemrequest schema —MetadataProtocolis declared inpackages/spec/src/api/protocol.zod.ts, verified onorigin/mainthis round) →domain:spec, type Task,pm:queue. Rationale: the REST reset door already sends 8 members; declaring the missing 6 is a declared-surface catch-up to a shipped verb, not a new capability — the exact precedent the metadata-protocol CHANGELOG records forgetMetaItemLayered("declared optional like itsgetMetaItemCached/deleteMetaItemsiblings: a declared-surface catch-up to a shipped verb").auditMetaItemon the same interface — same file, same catch-up shape, both already-ruled-pattern members); five-gate answer at claim, per-card acceptance = each member's call-site cast comes off. Path limb note: this touchespackages/spec/src/**⇒ the contract-review gate fires on path regardless of theClause-②: nocontent reading (declaring what is already sent/accepted changes no runtime accept/reject behaviour — but say so in the claim, don't leave it implied).Generated by Claude Code
os-support-ai commentedon Aug 25, 2026
Claim pointer: folded into the #11678 family dispatch — full claim (session, branch, file surface, five-gate answer, serial constraints) lives on the chain head: #11678, claim by
session_01K93P8PbH7kVjsAXkqzH1zY, branchclaude/issue-11678-metadata-protocol-doors. No branch of its own by design (family-dispatch convention). Per-member acceptance for THIS card:DeleteMetaItemRequestSchemagains the contract-level members of the eight the reset door sends, with a per-member protocol-vs-transport verdict recorded in the PR body —environmentIdstays OUT (ruled transport-level, #9741, 2026-08-18) and internal coordination keys stay out per #11426's reasoning; the delete/reset-door call-site casts come off (the TS2353 half this card names) — delivered as its own commit with aFixes #11679line in the family PR.Generated by Claude Code
docs(spec): re-anchor the dead tracker citations in api/ to the commi…
test(spec): the second api/ file group's test titles state each cited…