From 89d84d573f73cfe18e2367538d7043a75405ec71 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 26 Aug 2026 02:46:57 +0000 Subject: [PATCH] fix(spec): route the stored-envelope refusal to `os package publish` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The refusal an author meets when hand-writing a stored-envelope key onto an `api` declaration named `objectstack publish`, which resolves to no command — `os publish` was retired with the direct-to-environment path. Re-measured against the BUILT oclif Config on this tree (not against docs): 61 registered ids, the only two containing `publish` are `package publish` and `plugin publish`, no bare `publish` id and no `publish` topic. Same stale spelling corrected in the `publisher` doc comment of `cloud/package.zod.ts` and in `content/docs/api/declarative-endpoints.mdx` (the `objectstack validate` on that line is valid and is left alone). The gate's baselined-violation entry is self-retiring by design: fixing the string makes it stop reproducing and reds `check:cli-command-ids` until the row is deleted, so it goes in the same commit. Text only — no accept/reject behaviour change. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01E5LFCYBJ3q2s6yW6oMLxwy --- .changeset/spec-publish-command-spelling.md | 33 +++++++++++++++++++++ content/docs/api/declarative-endpoints.mdx | 2 +- packages/spec/src/api/endpoint.zod.ts | 2 +- packages/spec/src/cloud/package.zod.ts | 2 +- scripts/check-cli-command-ids.mjs | 21 ++++++------- 5 files changed, 45 insertions(+), 15 deletions(-) create mode 100644 .changeset/spec-publish-command-spelling.md diff --git a/.changeset/spec-publish-command-spelling.md b/.changeset/spec-publish-command-spelling.md new file mode 100644 index 0000000000..c5d3b2b250 --- /dev/null +++ b/.changeset/spec-publish-command-spelling.md @@ -0,0 +1,33 @@ +--- +"@objectstack/spec": patch +--- + +Route the stored-envelope refusal to a command that exists — `os package publish`, not the retired `objectstack publish` (#12223) + +An author who hand-writes one of the seven `STORED_ENVELOPE_KEYS` onto an `api` +declaration is refused, and the refusal tells them where publication state actually +comes from. It named a command that resolves to nothing: + +```text +before: Remove it — publication state is managed by `objectstack publish`, not authored. +after: Remove it — publication state is managed by `os package publish`, not authored. +``` + +`os publish` was the legacy direct-to-environment command, retired with the path that +wrote `sys_environment_revision`. Re-measured on this tree against the **built oclif +`Config`** rather than against docs — loading the CLI's plugin and reading the command +table oclif derives from `dist/commands/**`: **61** ids, of which the only two containing +`publish` are `package publish` and `plugin publish`. There is no bare `publish` id and no +`publish` topic, so the old spelling exits as an unknown command. The message's own +neighbouring sentence already names `publishPackage` as the writer, and +`packages/cli/src/commands/package/publish.ts` is the command that runs it. + +This is the shape #12177 deliberately left alone elsewhere inverted: those sentences are +*about* the removal and are correct as history, while this one is **present tense and +prescriptive** — text an AI author obeys at the moment its write is refused. + +Text only. No accept/reject behaviour changes: the same seven keys are refused on the same +declarations, with the same `unrecognized_keys` upgrade path; only the sentence an author +reads is corrected. The same stale spelling is fixed in the `publisher` doc comment of +`packages/spec/src/cloud/package.zod.ts`, which ships to consumers in the package's type +declarations. diff --git a/content/docs/api/declarative-endpoints.mdx b/content/docs/api/declarative-endpoints.mdx index f843e479dc..1552a8e159 100644 --- a/content/docs/api/declarative-endpoints.mdx +++ b/content/docs/api/declarative-endpoints.mdx @@ -86,7 +86,7 @@ export default defineStack({ }); ``` -Publish it (`objectstack publish`), and the two URLs answer. `objectstack validate` — and +Publish it (`os package publish`), and the two URLs answer. `objectstack validate` — and `os build` — run the same gates the publish path runs, so a declaration that would be refused is refused before you deploy. diff --git a/packages/spec/src/api/endpoint.zod.ts b/packages/spec/src/api/endpoint.zod.ts index c50922291e..ca728feba3 100644 --- a/packages/spec/src/api/endpoint.zod.ts +++ b/packages/spec/src/api/endpoint.zod.ts @@ -36,7 +36,7 @@ const STORED_BOOKKEEPING_GUIDANCE = 'This is the metadata layer\'s own storage bookkeeping, not endpoint vocabulary. It is written onto ' + 'the stored ROW by `register` / `publishPackage` and peeled off before this schema sees a body ' + '(#5309), so writing it on a declaration configures nothing. Remove it — publication state is ' - + 'managed by `objectstack publish`, not authored.'; + + 'managed by `os package publish`, not authored.'; /** * API Endpoint Schema diff --git a/packages/spec/src/cloud/package.zod.ts b/packages/spec/src/cloud/package.zod.ts index 1689a62eeb..b5679e5458 100644 --- a/packages/spec/src/cloud/package.zod.ts +++ b/packages/spec/src/cloud/package.zod.ts @@ -234,7 +234,7 @@ export const PackageSchema = lazySchema(() => z.object({ /** * Publisher provenance tier — surfaced as a trust badge in the Marketplace * and Studio. Defaults to `private` for org-scoped packages; the - * `objectstack publish` CLI sets it explicitly when promoting first-party + * `os package publish` command sets it explicitly when promoting first-party * or partner content. */ publisher: PackagePublisherSchema.default('private'), diff --git a/scripts/check-cli-command-ids.mjs b/scripts/check-cli-command-ids.mjs index bafd3ce58a..55cfbe5fb2 100644 --- a/scripts/check-cli-command-ids.mjs +++ b/scripts/check-cli-command-ids.mjs @@ -213,19 +213,16 @@ const FIXTURE_EXEMPTIONS = [ * follow in the owning lane, which is the same order `check-cli-test-child-env` shipped in * and for the same reason: sweeping without the gate restates a convention instead of * enforcing it. + * + * EMPTY, and that is the design working rather than a list nobody kept. The gate shipped + * with exactly one entry -- the `objectstack publish` refusal message in + * `packages/spec/src/api/endpoint.zod.ts` (#12223) -- and it retired ITSELF: fixing the + * string to `os package publish` made the entry stop reproducing, the `stale` check below + * RED, and deleting it the only way back to green. A baseline here cannot outlive its + * defect, so this list stays a record of work in flight and never becomes a silent + * exemption. Add to it only under the rule above: a real defect, filed and linked. */ -const BASELINED_VIOLATIONS = [ - { - file: 'packages/spec/src/api/endpoint.zod.ts', - text: 'objectstack publish', - why: 'STALE. `os publish` was retired with the direct-to-environment path (#11465 measured ' - + 'it against the built oclif Config: the registered publish ids are `package publish` and ' - + '`plugin publish`). This is a present-tense AUTHOR-FACING refusal message -- "publication ' - + 'state is managed by `objectstack publish`" -- so an author who trips it is sent to a ' - + 'command that does not exist. Correct spelling: `os package publish`.', - issue: '#12223', - }, -]; +const BASELINED_VIOLATIONS = []; const isExempt = (file, text) => FIXTURE_EXEMPTIONS.some((e) => e.file === file && e.text === text)