Repository navigation
Commit f289f2b
Fixes #19098
Fixes #20270
Clause-②: no (narrowing)
Executes maintainer ruling `5856790152` on #19098 (batch #227 item 5,
**letter C**, maintainer 「同意」, confirmed `5856865990`): `os generate
schema` is retired, not repaired. No file is generated in its place, and
nothing in `packages/spec` moves (ruling item 4).
## What changed
**`packages/cli/src/commands/generate.ts`**
- `RETIRED_GENERATORS` gains `schema` in the `os g agent` shape. The
refusal reads "`os g schema` was retired" and cites the maintainer
ruling. It names `os validate` (the real parse:
`ObjectStackDefinitionSchema.safeParse`), and names the per-type schemas
`@objectstack/spec` publishes at
`node_modules/@objectstack/spec/json-schema/CATEGORY/TYPE.json`, which
carry the published projection plus `x-dropped-refinements`. It exits 1.
- The ruling's id lives in the ledger's code comment, not in the
refusal. Text an author is shown carries no tracker number (AGENTS.md;
`check:doc-authoring`'s cross-package prose-id leg ratchets `#NNN`
tokens in `packages/**` strings, and `generate.ts` has no ledger row).
- **Deleted, not left dead:** `runSchemaGeneration`, with its three
`z.toJSONSchema(ObjectStackDefinitionSchema…)` rungs and both ladder
notices; `KNOWN_UNSUPPORTED_JSON_SCHEMA_PATTERNS`;
`isKnownUnsupportedJsonSchema`; and the `case 'schema'` route.
- Nothing else was schema-only. `-o`, `--dry-run` and `--format` serve
`types`, `client` and `migration`. `z` and `ObjectStackDefinitionSchema`
were dynamic imports inside the deleted function. `zod` stays a
dependency, used by `compile`, `validate` and `format`. The `type`
argument's help text derives from `GENERATORS` and never listed
`schema`.
- **The ledger door moved (PM mechanism assumption 2, measured and
falsified).** The lookup sat inside `runMetadataGeneration`, which runs
only after two earlier steps: the sub-command `switch` (where `schema`
returned first) and the NAME requirement (where a nameless call
stopped). So a `schema` entry alone could never be reached from `os
generate schema`.
- BEFORE, at BASE `0d3ec4713` on the dev runner, `os g agent` with no
name printed `Missing required argument` and exited 1.
- The lookup now runs first in `Generate.run`, through
`refuseRetiredGenerator`, as an own-key read (the package's
`Object.prototype.hasOwnProperty.call` idiom).
- Consequences, both pinned. `os g agent` with no name now prints the
agent retirement. `os g constructor NAME` used to print "`os g
constructor` was retired — undefined" and crash with `TypeError:
retired.detail is not iterable`. It now falls through to the ordinary
checks: exit 1, "No file naming convention is declared for type:
constructor".
**Tests**
- `packages/cli/test/generate-schema-retired.e2e.test.ts` (new) is the
retirement pin, in the `agent` precedent's shape: a real child process
through `bin/run-dev.js` plus tsx, with assertions on stdout content and
the exit status. It covers:
- `os generate schema` (no name) and `os g schema -o custom.schema.json`
both exit 1 and write nothing (directory listing `[]`);
- "was retired", with neither "Unknown type:" nor "Missing required
argument";
- "maintainer ruling", `os validate`, and
`@objectstack/spec/json-schema/`;
- the alias output is byte-equal to the documented spelling's;
- `os g agent` (no name) answers the agent retirement;
- `os g constructor thing` is not taken for a retired type;
- control: `os g object customer --dry-run` still previews.
- `packages/cli/test/generate-schema-writes-json-schema.e2e.test.ts`
(the #17873 pin, groups (a) to (e)) is **deleted**. Every assertion in
it was about the document the ruling withdrew: the file exists, parses,
declares its draft, the four members' fragments, and the input
direction. Nothing in it survives the retirement.
- Other tests that exercised the command: none. `git grep` for `generate
schema`, `runSchemaGeneration`, `objectstack.schema.json` and
`isKnownUnsupportedJsonSchema` over `packages/cli/src` and
`packages/cli/test` finds only the deleted file. The ladder PR (#17903)
added no pin of its own beyond that file.
- `packages/cli/test/generate-refuses-retired-generator.test.ts` (new,
patch round 1) is the per-PR guard for the door. It spawns the CLI and
is not named `.e2e`, so it runs in the queue's `integration` project. It
pins:
- `os generate schema` and `os g schema -o custom.schema.json`: exit 1,
nothing written, the retirement answered (neither "Missing required
argument" nor "Unknown type:"), naming the ruling, `os validate` and
`@objectstack/spec/json-schema/`;
- `os g constructor thing`: an own-key miss (exit 1, not "was retired",
no `TypeError`, nothing written);
- control: `os g object customer --dry-run` exits 0 and previews exactly
what the exported object template emits.
- `packages/cli/test/generate-agent-retired.e2e.test.ts` (#20270, its
own commit `a0cec66e9`): the live-generator control asserted `import *
as Data from '@objectstack/spec/data'`, which the object template
stopped emitting in `0bd11261e`, so this nightly case was red on main.
It now asserts the template's current shape, `ObjectSchema` among the
named imports from `@objectstack/spec/data` plus the
`ObjectSchema.create({` call, never one exact import line. The case is
neither skipped nor quarantined.
**Docs (ruling item 2).** The sweep is `git grep -n "generate schema" --
content/docs`, run at BASE:
| hit | disposition |
|:--|:--|
| `content/docs/api/data-flow.mdx:200`, the JSON Schema row
("Autocomplete and validation for `objectstack.config.ts` (via `os
generate schema`)") | **removed** |
| `content/docs/references/api/plugin-rest-api.mdx:107` | kept: a
substring of "Auto-generate schemas", the REST plugin's
`generateSchemas` option, in an auto-generated reference; it is not the
command |
| `content/docs/references/api/plugin-rest-api.mdx:282` | kept: same |
- One docs edit goes beyond the grep-found set, declared here. The
Mermaid node `D[JSON Schema]` and its two edges, in the same section
directly above the row, pictured the removed row's output ("Build Time:
generate, then JSON Schema, then feed IDE Autocomplete"). They are
removed, and `TypeScript Types` now feeds `IDE Autocomplete` alone.
- The page's front matter is untouched. #20170 landed its title-rule
hunk on it, and the merge was clean.
- `content/docs/deployment/cli.mdx` (patch round 1) gains a warn-type
Callout, "`os generate schema` is retired", in the `os generate` section
beside the `os g agent` one, the same shape as the two prior CLI
retirements. It points at `os validate` (linked to the page's own `os
validate` heading) and at the per-type schemas `@objectstack/spec`
publishes. The refusal's `Docs:` link lands on this page. The page never
listed a `schema` sub-type, so nothing else on it changes.
- Also swept, with nothing to change:
- `packages/cli/README.md` carries only the generic `os generate` row;
- `skills/` has 0 hits;
- `content/docs/protocol/diagram.mdx:243-255` (see Acceptance notes).
**Changeset** `.changeset/19098-retire-generate-schema.md`:
- `@objectstack/cli: minor`, with a **BREAKING** banner and `Clause-②:
no (narrowing)`;
- the ADR-0087 marker in the `os g agent` wording (`not-required
(no-migration-prescription)`);
- reach outside the repository stated as NOT MEASURED (no telemetry);
- the refusal's pointer given as the migration: delete the call and any
editor mapping of `objectstack.schema.json`, run `os validate`, and
point editors at the per-type schemas.
## Verification, patch round 1 (at HEAD `2cb9e9613` unless stated)
- **Merge.** `origin/main` `17bd31877` merged by merge as `9f702ee94`
(`scripts/pm/os-regen-merge.sh`). No incoming file is one of this PR's.
- **Derived gates.** `node scripts/pm/dispatch-gates.mjs --repo
objectstack-ai/objectstack --commands` derived 93 commands: round 0's 92
plus `pnpm check:cli-examples-parity`, from the `cli.mdx` edit. All 93
exited 0 at `2cb9e9613`. `--ran` with the recorded exit codes reads "93
derived, 93 run, 0 NOT-MEASURED, 0 UNRUN" (a derived zero).
- **Named gates:**
- `pnpm lint`: exit 0 (118 s);
- `node scripts/check-issue-citations.mjs --base origin/main`
(`ae8e3ca01`): exit 0;
- `pnpm check:docs-audit-scope` and `node
scripts/docs-audit/check-affected-docs.mjs`: exit 0 each;
- `pnpm check:docs-transcript-drift` and `pnpm
check:cli-examples-parity`: exit 0 each;
- `pnpm --filter @objectstack/cli typecheck`: `VERDICT command-exit 0`,
with the new pin inside the `tsconfig.test.json` program
(`--listFilesOnly`: 1 hit).
- **Per-PR pin.** `pnpm --filter @objectstack/cli exec vitest run
--project integration --maxWorkers=2
test/generate-refuses-retired-generator.test.ts`: 7/7. It sits in the
queue's `integration` population (54 to 55 files) and is absent from the
nightly population. The partition pin
`test/vitest-tiers-partition.test.ts` passes 22/22.
- **Nightly.** `OS_TEST_TIERS=nightly pnpm --filter @objectstack/cli
exec vitest run --project integration --maxWorkers=2
test/generate-schema-retired.e2e.test.ts
test/generate-agent-retired.e2e.test.ts`: 2 files, 19/19. That includes
"the generators that were not retired still work", the #20270 case.
- **Shape proof for #20270.** The two new assertions accept the current
emission: through the exported template, the `ObjectSchema` import
matches and the `create` call matches. They reject the pre-#20195
emission taken from `0bd11261e^`: neither matches.
- **Ablations on the per-PR file.** These ran on committed state
`a2dda36c2`. `generate.ts` and the per-PR file are byte-identical at
`2cb9e9613`.
| leg | mutation | on-disk proof | per-PR pin result | restore |
|:--|:--|:--|:--|:--|
| A | `schema` ledger key renamed to `schema_ablated` | anchor 1 to 0;
blob `62cb7ec8b8ed` to `7a1f27dd8cfb`; grep `schema-entry=0
ablated-entry=1` | **2 failed**, 5 passed: "is the retirement, not a
missing name and not an unknown type"; "names the ruling, `os validate`
and the per-type schemas" | blob equals HEAD `62cb7ec8b8ed`, `git diff
HEAD` empty |
| B | own-key read reverted to `RETIRED_GENERATORS[args.type]` | anchor
1 to 0; blob to `26ec87322f84`; grep `own-key=0 bracket=1` | **1
failed**, 6 passed: the `os g constructor thing` case | same |
After both legs, the restored per-PR run passed 7/7.
- **History.** The #20270 fix is its own commit, `a0cec66e9`. A first
push, `a2dda36c2`, had carried a first version of it together with the
per-PR pin and the callout. Rewriting that pushed commit was refused by
the session's permission classifier, so the split line was merged with
the pushed head instead (`2cb9e9613`, whose tree is identical to
`a0cec66e9`'s). Nothing pushed was discarded.
## Verification, round 0 (at HEAD `c1036ebb9` unless stated)
- **Derived gates.** `node scripts/pm/dispatch-gates.mjs --repo
objectstack-ai/objectstack --commands` derived 92 commands, and all 92
exited 0 at `c1036ebb9`. `--ran` with the recorded exit codes reads "92
derived, 92 run, 0 NOT-MEASURED, 0 UNRUN" (a derived zero).
- `check-adr-0087-registration --base origin/main` reads
`[BREAKING+clause-②-narrowing] not-required
(no-migration-prescription)`.
- `check-changeset-no-major` reads "no `major` bump". Its level axis
reads the PR body, so it is judged in CI.
- **`pnpm lint`** (repo-wide, `eslint . --no-inline-config`): exit 0,
130 s.
- **`pnpm --filter @objectstack/cli typecheck`**: `VERDICT command-exit
0`. That is `tsc --noEmit` plus `check:test-typecheck`, and the new pin
is inside the `tsconfig.test.json` program (`--listFilesOnly`: 1 hit).
- **Board check.** `node scripts/check-issue-citations.mjs --base
origin/main` (`a9fb83ef0`) exits 0: 73 citations judged, 71 resolve, 2
cross-repo.
- **`unit` layer**, run at merge commit `5c7c5bee3`:
- `pnpm --filter @objectstack/cli exec vitest run --project unit
--maxWorkers=2` ran 229 files: 227 passed and 2 failed as prerequisite
refusals ("packages/cli is not built").
- After the CLI build, those 2 files passed (29 tests).
- `c1036ebb9` differs from `5c7c5bee3` only in the new pin, which is not
in the unit population.
- **Integration tier.** The retirement pin is `*.e2e.test.ts` like the
`agent` precedent, so it is **nightly-tier**: the per-PR queue run does
not select it.
- Run locally as `OS_TEST_TIERS=nightly pnpm --filter @objectstack/cli
exec vitest run --project integration --maxWorkers=2` over the new pin
plus `generate-agent-retired`, `generate-skill` and
`generate-object-namespace-prefix`.
- Result: 38 passed and 1 failed. The failure is the pre-existing stale
control in `generate-agent-retired.e2e.test.ts` (see Acceptance notes);
the new pin is 10/10.
- **Reach checks** on the dev runner, BEFORE at BASE and AFTER at HEAD:
- `os generate schema -o out.json` went from exit 0 and a 3,335,734-byte
file written to exit 1, the refusal, and nothing written;
- `os g agent` went from "Missing required argument" to the agent
retirement;
- `os g constructor foo` went from a `TypeError` crash to the ordinary
refusal.
**Ablation.** This is a one-shot proof, run against the committed state
`c1036ebb9` through `scripts/ablation-replace.mjs` under a script-level
`trap` restore. The subject resolves from `src/` via tsx, so no dist is
involved.
| leg | mutation | on-disk proof | pin result | restore |
|:--|:--|:--|:--|:--|
| A | `schema` ledger key renamed to `schema_ablated` (the lookup misses
it) | anchor 1 to 0; blob `62cb7ec8b8ed` to `7a1f27dd8cfb`; grep
`schema-entry=0 ablated-entry=1` | **4 failed**, 6 passed: "was
RETIRED", "names the ruling", `os validate`, per-type schemas | blob
equals HEAD `62cb7ec8b8ed`; `git diff HEAD` empty |
| B | own-key read reverted to `RETIRED_GENERATORS[args.type]` | anchor
1 to 0; blob to `26ec87322f84`; grep `own-key=0 bracket=1` | **1
failed**, 9 passed: the `constructor` own-keys assertion | same |
In leg A the exit-1 and writes-nothing assertions stayed green, because
the missing-name path also exits 1 without writing. That is exactly why
the pin asserts the refusal's content, as the `agent` precedent does.
## Acceptance notes
1. Now repaired here (#20270, commit `a0cec66e9`): the live-generator
control in `packages/cli/test/generate-agent-retired.e2e.test.ts`
asserted `import * as Data from '@objectstack/spec/data'`, which the
object template stopped emitting in `0bd11261e`.
- Triage's note-2 sweep covered all 73 nightly-tier files under
`packages/cli` for pre-#20195 template text (`import * as Data from
'@objectstack/spec/data'`, `Data.ServiceObject`). That line was the only
nightly hit; the control, the same sweep at `9f702ee94`, finds it.
- Two per-PR files carry the old shape on purpose and are not changed:
`scaffold-emission-typechecks.test.ts` (a tsc canary fixture) and
`scaffold-object-declaration-shape.test.ts` (it refuses the pre-ruling
literal).
2. `.changeset/sour-moons-smile.md`, pending and unreleased, records the
#17903 ladder repair this PR deletes. It is left unchanged.
- Rewriting it here is the case `check-empty-changeset.mjs` classes as a
DELIBERATE CORRECTION (#18160, ruling D on #17712). The gate goes red on
any modification or deletion of a changeset from the merge base, and its
remedy is "do NOT restore it -- say so on the PR and get it confirmed".
- The seat answered the open question with A: leave the file. The new
changeset tells the reader that this retirement supersedes that repair,
and the release owner may drop the file at compilation.
3. The docblock at `packages/spec/scripts/lib/refinement-projection.ts`
(the "Producers outside `packages/spec`'s own artifacts" bullet) still
names the CLI's `os generate` as a direct `z.toJSONSchema` producer. It
goes stale once this lands, but `packages/spec` is untouched by ruling
item 4.
4. The `GENERATORS[type]` lookup in `runMetadataGeneration` is still an
inherited-key read. So `os g constructor NAME` answers "No file naming
convention is declared for type: constructor" rather than "Unknown
type". The answer is misleading but does not crash, and it is not
changed here.
5. Reach outside this repository is NOT MEASURED (no telemetry). Inside
it there is no reader and no editor mapping of
`objectstack.schema.json`.
6. `content/docs/protocol/diagram.mdx:243-255` carries a `D[JSON
Schema]` node feeding IDE autocomplete, and a row "Generated JSON Schema
files for IDE validation". It does not name the command, and the plural
"files" reads as the per-type schemas `@objectstack/spec` still
publishes, so it is left unchanged.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01UYBdGBzWSrAMzpW8ah3GbP)_
---------
Co-authored-by: Claude <noreply@anthropic.com>
1 parent 733822c commit f289f2b
8 files changed
Lines changed: 534 additions & 404 deletions
File tree
- .changeset
- content/docs
- api
- deployment
- packages/cli
- src/commands
- test
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
181 | 181 | | |
182 | 182 | | |
183 | 183 | | |
184 | | - | |
185 | 184 | | |
186 | | - | |
187 | | - | |
| 185 | + | |
188 | 186 | | |
189 | 187 | | |
190 | 188 | | |
| |||
198 | 196 | | |
199 | 197 | | |
200 | 198 | | |
201 | | - | |
202 | 199 | | |
203 | 200 | | |
204 | 201 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1461 | 1461 | | |
1462 | 1462 | | |
1463 | 1463 | | |
| 1464 | + | |
| 1465 | + | |
| 1466 | + | |
| 1467 | + | |
| 1468 | + | |
| 1469 | + | |
| 1470 | + | |
| 1471 | + | |
| 1472 | + | |
| 1473 | + | |
| 1474 | + | |
| 1475 | + | |
| 1476 | + | |
| 1477 | + | |
| 1478 | + | |
| 1479 | + | |
| 1480 | + | |
| 1481 | + | |
1464 | 1482 | | |
1465 | 1483 | | |
1466 | 1484 | | |
| |||
0 commit comments