You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(cli)!: refuse a generate name outside the charset spec declares for an object name (#17408)
* feat(cli)!: refuse a generate name outside spec's object-name charset
`os generate <type> <name>` accepted any name at all until #16724 taught it
to refuse names whose emitted TypeScript does not parse. It now also refuses,
ahead of that check and ahead of every derivation, any name the object-`name`
declaration in `@objectstack/spec` rejects — maintainer ruling, decision batch
#82, option A: a gate, no sanitiser, no third charset.
The judge is the schema itself (`ObjectSchema.shape.name`), so the charset is
asked rather than transcribed, and the refusal quotes the schema's own message
so the rule the author is shown is the rule that judged them.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DapQyvYrFb1MxSYe7BL2nt
* test(cli): measure the parse-check layer through a name that reaches it
The #16726 charset gate answers first for `foo.bar`, so #16541's pin now
measures its own subject through `class` — inside the charset, refused by the
compiler — and keeps every `foo.bar` assertion that is still about the command.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DapQyvYrFb1MxSYe7BL2nt
* chore(changeset): record the ADR-0087 disposition for the generate name gate
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DapQyvYrFb1MxSYe7BL2nt
---------
Co-authored-by: Claude <noreply@anthropic.com>
feat(cli)!: `os generate` refuses a metadata name outside the charset `packages/spec` declares for an object `name`, before it derives anything from it (#16726)
6
+
7
+
Maintainer ruling, decision batch #82 (2026-09-08), option A — **a gate, not a sanitiser**. `os generate <type> <name>` used to accept any name at all; since #16724 it has refused names whose emitted TypeScript does not parse. It now also refuses, ahead of that check and ahead of every derivation, any name the object-`name` declaration in `@objectstack/spec` rejects. The refusal names the value and quotes the schema's own rule, and writes nothing.
8
+
9
+
⛔ Nothing is rewritten. The rejected alternative was to derive a legal identifier the way `os create` does, which decouples the name the author wrote from the name that gets emitted with nothing announcing it — the failure mode that multiplies silently when metadata is written in bulk. So the name you author and the name that lands in the file are always the same string.
10
+
11
+
**What this narrows:** kebab-case (`order-line`), uppercase (`Order`), dotted (`foo.bar`) and digit-initial (`2fast`) names were accepted before and are refused now — `order-line` used to generate `order_line.object.ts` binding `orderLine`. Write the snake_case name directly (`os g object order_line`). ⛔ No new charset was minted and no flag bypasses the gate; #16724's parse check is unchanged and stays as the backstop behind it (`class` passes the charset and is still refused for `object`, because `const class:` is not a declaration).
12
+
13
+
<!-- adr-0087: not-required (no-migration-prescription) Nothing authorable or stored moves. No `packages/spec` key, no Zod schema, no authored metadata property and no stored `sys_metadata` shape changes its spelling, type or legality — the charset this gate applies is the one spec ALREADY declares for an object `name`, read rather than redeclared — so `objectstack migrate meta` has nothing to visit, `spec-changes.json` has nothing to project and the upgrade guide has no row to gain. What moves is which ARGUMENT a scaffolding command accepts at authoring time; a name it now refuses was never a legal object `name` in the first place, so no metadata written from an accepted name needs conversion, and files already scaffolded from a refused name are untouched by this change. The remedy is to type a name spec accepts, delivered by the command's own loud refusal at the terminal and by this changelog — the source-code / invocation-side audience the ledger explicitly does not serve (ADR-0087 D8). The other four categories are closed on facts: `@objectstack/cli` publishes to npm (not `unpublished`); no ADR-0087 id is minted in this diff (not `registered`) and none pre-dates the base that would cover it (not `already-registered`); no exported declaration changes shape at all — the gate is a file-local function absent from the package entry — so neither `runtime-interface-only` nor `type-surface-only` has a subject. -->
0 commit comments