From ff98ca8ff7f3f3e127179de6f9ced9cc1c4ab9e8 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 26 Aug 2026 20:27:59 +0000 Subject: [PATCH 1/3] =?UTF-8?q?wip(spec):=20retire=20CLICommandContributio?= =?UTF-8?q?nSchema/CLICommandContribution=20=E2=80=94=20source=20edits=20b?= =?UTF-8?q?efore=20regeneration=20(#12007)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cli-command-contribution-retired.md | 56 +++++++++++ ...li-command-contribution-retirement.test.ts | 93 +++++++++++++++++++ .../spec/src/kernel/cli-extension.test.ts | 68 +------------- packages/spec/src/kernel/cli-extension.zod.ts | 63 ++++++------- .../18.kernel__CLICommandContribution.ts | 28 ++++++ .../18.cli-command-contribution-retired.ts | 51 ++++++++++ .../src/type-alias-convention.pin.test.ts | 2 +- 7 files changed, 260 insertions(+), 101 deletions(-) create mode 100644 .changeset/cli-command-contribution-retired.md create mode 100644 packages/spec/src/kernel/cli-command-contribution-retirement.test.ts create mode 100644 packages/spec/src/migrations/entries/retired-defs/18.kernel__CLICommandContribution.ts create mode 100644 packages/spec/src/migrations/entries/semantic/18.cli-command-contribution-retired.ts diff --git a/.changeset/cli-command-contribution-retired.md b/.changeset/cli-command-contribution-retired.md new file mode 100644 index 0000000000..04f61d2fcf --- /dev/null +++ b/.changeset/cli-command-contribution-retired.md @@ -0,0 +1,56 @@ +--- +"@objectstack/spec": minor +--- + +feat(spec): retire the orphan `CLICommandContributionSchema` export — the manifest surface it described is a tombstone (#12007, ADR-0049) + + + +**BREAKING** export removal, landing after the v17.0.0 cut (the lockstep +launch-window convention ships it as `minor`; the prescription is registered +under protocol major 18 — `RETIRED_DEFS_BY_MAJOR[18]` +(`kernel/CLICommandContribution`) + the D3 semantic entry +`cli-command-contribution-retired` — where `os migrate meta` users will +look). + +`CLICommandContributionSchema` described a "CLI Command Contribution +declaration in the manifest" and claimed to be "retained for backward +compatibility and for describing command metadata in plugin manifests" — but +after #10724 tombstoned `manifest.contributes.commands`, no manifest surface +could legally carry these entries: the exported schema advertised a shape +whose only declared carrier rejects it. The manifest never referenced this +schema even before the tombstone (its inline `commands` item schema was an +independent duplicate), and it had zero consumers outside spec's own test and +generated artifacts, measured at the retirement's base commit with positive +controls in objectstack, objectui (pinned sha) and cloud — the exported +orphan-value-schema class (#3950: an exported schema with no consumer reads +as a capability). + +FROM → TO: + +- `CLICommandContributionSchema` / `CLICommandContribution` → *(removed — no + declarative replacement, because no declarative surface ever carried it)*. + CLI commands are registered through oclif's native plugin discovery: the + plugin package declares an `oclif` section in its own `package.json` — + `OclifPluginConfigSchema` / `OclifPluginConfig` (same module) describe that + live surface and survive unchanged. + +One-line fix: delete the import (nothing ever read the declaration); if you +describe a plugin's CLI commands, declare the `oclif` section in the plugin's +`package.json` — `OclifPluginConfigSchema` validates it. + +The retirement kit: + +- whole-def deletion (route 3 — no carrier key, no authored document, so no + tombstone and no D2 conversion; the #11825 / #8715 shape): + `kernel/CLICommandContribution` in `RETIRED_DEFS_BY_MAJOR[18]`, plus the D3 + semantic entry `cli-command-contribution-retired` +- pin test (`kernel/cli-command-contribution-retirement.test.ts`): zero + holders for both retired names on every public entry, survivors pinned + (`OclifPluginConfigSchema` / `OclifPluginConfig` — the live `package.json` + `oclif` surface) +- the module docblock's Commander.js migration prose is KEPT — it is cited by + the `contributes.commands` tombstone (full-file deletion was explicitly not + the shape) +- zero authored occurrences in objectstack, objectui or cloud (measured at + dispatch, re-verified at claim), so no in-repo source changes ride along diff --git a/packages/spec/src/kernel/cli-command-contribution-retirement.test.ts b/packages/spec/src/kernel/cli-command-contribution-retirement.test.ts new file mode 100644 index 0000000000..5aac56ad25 --- /dev/null +++ b/packages/spec/src/kernel/cli-command-contribution-retirement.test.ts @@ -0,0 +1,93 @@ +// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. + +import { describe, it, expect } from 'vitest'; + +import { + EXPORT_ENTRY_POINTS, + exportNamesOf, + holdersOf, +} from '../../scripts/lib/export-origins-testkit'; + +// ─── [#12007] kernel/ CLICommandContribution is RETIRED ───────────────────── +// +// ADR-0049 enforce-or-remove. `kernel/cli-extension.zod.ts` no longer declares +// `CLICommandContributionSchema` / `CLICommandContribution` — 1 emitted def, +// 2 exported names, 3 authorable-surface keys (`name`, `description`, +// `module`), the reference page's section with them. +// +// The measurement that decided it (re-verified at this retirement's base +// commit, 146f448a5, with positive controls — the full record lives in the +// retirement block inside the zod module): +// +// 1. CARRIER — after #10724, `manifest.contributes.commands` is a +// `retiredKey()` tombstone: no manifest surface could legally carry a +// command-contribution entry, so the exported schema advertised a shape +// whose only declared carrier rejects it. The manifest never referenced +// this schema even before the tombstone — its inline `commands` item +// schema was an independent duplicate. +// 2. STATIC — zero readers outside `packages/spec`'s own test and generated +// artifacts, in objectstack, objectui (at the pinned sha) and cloud +// (controls: `OclifPluginConfigSchema` and `@objectstack/spec` both +// resolve hits — the scans see real readers). +// 3. DOORS — no metadata-type binding, no stack collection, no manifest +// embed: no authored document could ever carry it. +// +// Route 3: with no carrier key there is nothing to tombstone and no seam for +// a D2 conversion — `RETIRED_DEFS_BY_MAJOR[18]` plus the D3 semantic entry +// `cli-command-contribution-retired` ARE the declaration. +// +// Form follows #11825 / #8715 / #4988: resolved symbol identity over every +// public entry via the build-time `export-origins/` artifact. +describe('[#12007] kernel/ CLICommandContribution retirement', () => { + /** The 2 names the retired def exported (1 schema const + 1 type). */ + const RETIRED_NAMES = [ + 'CLICommandContributionSchema', + 'CLICommandContribution', + ] as const; + + /** + * Names that must SURVIVE on `./kernel`: the LIVE half of the same module — + * `OclifPluginConfigSchema` describes the `oclif` section of a plugin's own + * `package.json`, the mechanism that actually registers CLI commands. + * Exactly what a too-wide "tidy the cli-extension module" sweep would take + * (full-file deletion was explicitly NOT the shape: the module docblock's + * Commander.js migration prose is cited by the `contributes.commands` + * tombstone). + */ + const MUST_SURVIVE_KERNEL = [ + 'OclifPluginConfigSchema', + 'OclifPluginConfig', + ] as const; + + it('every retired name has ZERO holders on any public entry; the survivors still stand', () => { + // Anti-vacuity: the baseline must cover the real surface. + for (const needed of ['.', './kernel']) { + expect(EXPORT_ENTRY_POINTS, `exports map must include ${needed}`).toContain(needed); + } + expect( + exportNamesOf('./kernel').length, + './kernel must export a non-trivial surface' + ).toBeGreaterThan(50); + + // ── ABSENCE (every entry, not just ./kernel) ────────────────────────── + for (const name of RETIRED_NAMES) { + expect(holdersOf(name), `${name} must have zero holders after #12007`).toEqual([]); + } + + // ── SURVIVAL ────────────────────────────────────────────────────────── + const kernelNames = exportNamesOf('./kernel'); + for (const name of MUST_SURVIVE_KERNEL) { + expect(kernelNames, `${name} must SURVIVE this retirement`).toContain(name); + } + }); + + it('the runtime barrel resolves without the retired schema and keeps the survivor', async () => { + const kernel = await import('./index'); + expect(kernel, 'CLICommandContributionSchema must not be exported after #12007') + .not.toHaveProperty('CLICommandContributionSchema'); + // Anti-vacuity: the barrel really resolved and still exports the live + // oclif surface plus an unrelated kernel anchor. + expect(kernel).toHaveProperty('OclifPluginConfigSchema'); + expect(kernel).toHaveProperty('ManifestSchema'); + }); +}); diff --git a/packages/spec/src/kernel/cli-extension.test.ts b/packages/spec/src/kernel/cli-extension.test.ts index 39951eb12e..7b118daf3e 100644 --- a/packages/spec/src/kernel/cli-extension.test.ts +++ b/packages/spec/src/kernel/cli-extension.test.ts @@ -1,69 +1,9 @@ import { describe, it, expect } from 'vitest'; -import { - CLICommandContributionSchema, - OclifPluginConfigSchema, -} from './cli-extension.zod'; - -describe('CLICommandContributionSchema', () => { - it('should accept valid command contribution', () => { - const result = CLICommandContributionSchema.parse({ - name: 'marketplace', - description: 'Manage marketplace applications', - }); - expect(result.name).toBe('marketplace'); - expect(result.description).toBe('Manage marketplace applications'); - }); - - it('should accept command with module path', () => { - const result = CLICommandContributionSchema.parse({ - name: 'deploy', - description: 'Deploy to cloud', - module: './dist/commands/deploy.js', - }); - expect(result.module).toBe('./dist/commands/deploy.js'); - }); - - it('should accept minimal command (name only)', () => { - const result = CLICommandContributionSchema.parse({ - name: 'sync', - }); - expect(result.name).toBe('sync'); - expect(result.description).toBeUndefined(); - expect(result.module).toBeUndefined(); - }); - - it('should accept hyphenated command names', () => { - const result = CLICommandContributionSchema.parse({ - name: 'cloud-sync', - }); - expect(result.name).toBe('cloud-sync'); - }); - - it('should reject invalid command names', () => { - const invalidNames = [ - 'Uppercase', - 'has spaces', - '123start', - '-leading-hyphen', - 'special_underscore', - 'dot.name', - '', - ]; - - invalidNames.forEach(name => { - expect(() => CLICommandContributionSchema.parse({ name })).toThrow(); - }); - }); - - it('should accept valid lowercase alphanumeric names', () => { - const validNames = ['a', 'abc', 'a1', 'my-command', 'plugin2']; - - validNames.forEach(name => { - expect(() => CLICommandContributionSchema.parse({ name })).not.toThrow(); - }); - }); -}); +import { OclifPluginConfigSchema } from './cli-extension.zod'; +// [#12007] The `CLICommandContributionSchema` block that used to sit here left +// with the retired export (ADR-0049 enforce-or-remove) — the rejection/holder +// pins live in `cli-command-contribution-retirement.test.ts`. describe('OclifPluginConfigSchema', () => { it('should accept valid oclif plugin config', () => { const result = OclifPluginConfigSchema.parse({ diff --git a/packages/spec/src/kernel/cli-extension.zod.ts b/packages/spec/src/kernel/cli-extension.zod.ts index 9d6f5eac06..7ee7fcf711 100644 --- a/packages/spec/src/kernel/cli-extension.zod.ts +++ b/packages/spec/src/kernel/cli-extension.zod.ts @@ -63,42 +63,32 @@ import { z } from 'zod'; * The `objectstack.config.ts` plugins array no longer determines CLI commands. */ -/** - * Schema for a CLI Command Contribution declaration in the manifest. - * - * This declarative metadata describes CLI commands contributed by a plugin. - * With the oclif migration, commands are auto-discovered from the plugin's - * commands directory. This schema is retained for backward compatibility - * and for describing command metadata in plugin manifests. - */ +// ─── [#12007] `CLICommandContributionSchema` / `CLICommandContribution` are +// RETIRED (ADR-0049 enforce-or-remove) ─────────────────────────────────────── +// +// The pair described a "CLI Command Contribution declaration in the manifest" +// and claimed to be "retained for backward compatibility and for describing +// command metadata in plugin manifests" — but after #10724 tombstoned +// `manifest.contributes.commands` (see `manifest.zod.ts`), no manifest surface +// could legally carry these entries: the exported schema advertised a shape +// whose only declared carrier rejects it. It was never referenced by +// `manifest.zod.ts` either — the manifest's inline `commands` item schema was +// an independent duplicate (now the tombstone). Zero consumers outside spec's +// own test and generated artifacts, measured with positive controls in +// objectstack, objectui (at the pinned sha) and cloud — the exported +// orphan-value-schema class (#3950: an exported schema with no consumer reads +// as a capability). +// +// Route 3: no carrier key, no authored document for a D2 conversion to +// rewrite, so no tombstone and no conversion — `RETIRED_DEFS_BY_MAJOR[18]` +// (`kernel/CLICommandContribution`) plus the D3 semantic entry +// `cli-command-contribution-retired` ARE the declaration. What ACTUALLY +// registers a CLI command is oclif's native plugin discovery: the plugin +// declares an `oclif` section in its own `package.json` — +// `OclifPluginConfigSchema` below describes that live surface and survives. +// The Commander.js migration record in the module docblock above is +// load-bearing (the `contributes.commands` tombstone cites it) and stays. import { lazySchema } from '../shared/lazy-schema'; -export const CLICommandContributionSchema = lazySchema(() => z.object({ - /** - * CLI command name. Must be a valid identifier: lowercase alphanumeric with hyphens. - * This becomes a top-level subcommand of the `os` CLI. - * - * @example "marketplace" - * @example "deploy" - * @example "cloud-sync" - */ - name: z.string() - .regex(/^[a-z][a-z0-9-]*$/, 'Command name must be lowercase alphanumeric with hyphens') - .describe('CLI command name'), - - /** Brief description shown in `os --help` output. */ - description: z.string().optional().describe('Command description for help text'), - - /** - * Module path that exports the oclif Command class(es). - * Relative to the plugin package root. With oclif, this is typically - * auto-discovered from the `commands` directory, but can be specified - * for documentation or manifest purposes. - * - * @example "./dist/commands/marketplace.js" - * @example "./dist/commands" - */ - module: z.string().optional().describe('Module path exporting oclif Command classes'), -})); /** * Schema for oclif plugin configuration in package.json. @@ -125,5 +115,6 @@ export const OclifPluginConfigSchema = lazySchema(() => z.object({ // ─── Types ─────────────────────────────────────────────────────────── -export type CLICommandContribution = z.input; +// [#12007] `CLICommandContribution` left with its schema — see the retirement +// block above. export type OclifPluginConfig = z.input; diff --git a/packages/spec/src/migrations/entries/retired-defs/18.kernel__CLICommandContribution.ts b/packages/spec/src/migrations/entries/retired-defs/18.kernel__CLICommandContribution.ts new file mode 100644 index 0000000000..d7a0a51a19 --- /dev/null +++ b/packages/spec/src/migrations/entries/retired-defs/18.kernel__CLICommandContribution.ts @@ -0,0 +1,28 @@ +// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. + +// #12007 — kernel/cli-extension.zod.ts +// `CLICommandContributionSchema` / `CLICommandContribution`, retired whole +// (ADR-0049 enforce-or-remove; triage graded 2026-08-25, the exported +// orphan-value-schema class — #3950). The pair described a "CLI Command +// Contribution declaration in the manifest" and claimed retention "for +// describing command metadata in plugin manifests" — but after #10724 +// tombstoned `manifest.contributes.commands`, no manifest surface could +// legally carry these entries: the exported schema advertised a shape whose +// only declared carrier rejects it. The manifest never referenced this schema +// even before the tombstone (its inline `commands` item schema was an +// independent duplicate). Zero consumers outside spec's own test and +// generated artifacts, measured at the retirement's base commit (146f448a5) +// with positive controls in objectstack, objectui (pinned sha) and cloud. +// What ACTUALLY registers CLI commands is oclif's native plugin discovery — +// `OclifPluginConfigSchema` (same module, live `package.json` `oclif` +// section) SURVIVES, as does the module docblock's Commander.js migration +// prose, which the `contributes.commands` tombstone cites. Route 3: no +// carrier key, no authored document for a D2 conversion to rewrite, so no +// tombstone and no conversion — this table plus the D3 semantic entry +// `cli-command-contribution-retired` ARE the declaration. +// +// Registered under 18, not 17: v17.0.0 was cut before this landed, so the +// removal ships on the 17.x line (launch-window convention: accept-set +// narrowings ride minor releases) and the prescription lives at the major +// boundary where `migrate meta` users look (the #8586 / PR #8702 precedent). +export const entry = 'kernel/CLICommandContribution'; diff --git a/packages/spec/src/migrations/entries/semantic/18.cli-command-contribution-retired.ts b/packages/spec/src/migrations/entries/semantic/18.cli-command-contribution-retired.ts new file mode 100644 index 0000000000..2739f84659 --- /dev/null +++ b/packages/spec/src/migrations/entries/semantic/18.cli-command-contribution-retired.ts @@ -0,0 +1,51 @@ +// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. + +import type { SemanticMigration } from '../../types.js'; + +export const entry: SemanticMigration = { + id: 'cli-command-contribution-retired', + surface: + 'kernel.cliCommandContribution (the orphan exported schema of ' + + '`cli-extension.zod.ts` — 1 def, 2 exported names: ' + + '`CLICommandContributionSchema` / `CLICommandContribution`)', + replacement: + '(removed — there is no declarative replacement, because no declarative ' + + 'surface ever carried it. CLI commands are registered through oclif\'s ' + + 'native plugin discovery: the plugin package declares an `oclif` ' + + 'section in its own `package.json` — `OclifPluginConfigSchema` in the ' + + 'same module describes that live surface and SURVIVES, as does the ' + + 'module docblock\'s Commander.js migration record, which the ' + + '`manifest.contributes.commands` tombstone cites)', + reason: + 'ADR-0049 enforce-or-remove; #12007, the exported orphan-value-schema ' + + 'class (#3950: an exported schema with no consumer reads as a ' + + 'capability). The schema described a "CLI Command Contribution ' + + 'declaration in the manifest" and claimed retention "for describing ' + + 'command metadata in plugin manifests" — but after #10724 tombstoned ' + + '`manifest.contributes.commands` (protocol 17), no manifest surface ' + + 'could legally carry these entries: the export advertised a shape whose ' + + 'only declared carrier rejects it. The manifest never referenced this ' + + 'schema even before the tombstone — its inline `commands` item schema ' + + 'was an independent duplicate. Zero consumers outside spec\'s own test ' + + 'and generated artifacts, measured at the retirement\'s base commit ' + + '(146f448a5) with positive controls in objectstack, objectui (pinned ' + + 'sha) and cloud. With no carrier key and no authored document there is ' + + 'nothing to tombstone and no seam for a D2 conversion: route 3, the ' + + '#11825 / #8715 shape — RETIRED_DEFS_BY_MAJOR plus this entry ARE the ' + + 'declaration.', + acceptanceCriteria: + 'No code imports `CLICommandContributionSchema` or ' + + '`CLICommandContribution` from `@objectstack/spec` or ' + + '`@objectstack/spec/kernel` — both are TS2305 after upgrade, on every ' + + 'public entry (pinned by resolved symbol identity in ' + + '`kernel/cli-command-contribution-retirement.test.ts`). No metadata ' + + 'document needs editing: the def was reachable from no metadata-type ' + + 'binding, stack collection or manifest embed — the only surface that ' + + 'ever claimed to carry command contributions ' + + '(`manifest.contributes.commands`) already rejects the key with the ' + + '#10724 prescription, which is unchanged by this retirement. ' + + '`OclifPluginConfigSchema` / `OclifPluginConfig` survive on `./kernel` ' + + '(same pin). ⚠️ Runtime behaviour is deliberately UNCHANGED: the CLI ' + + 'never resolved commands from this declaration — commands are ' + + 'oclif-auto-discovered, before and after.', +}; diff --git a/packages/spec/src/type-alias-convention.pin.test.ts b/packages/spec/src/type-alias-convention.pin.test.ts index 9c01585b12..58c534539b 100644 --- a/packages/spec/src/type-alias-convention.pin.test.ts +++ b/packages/spec/src/type-alias-convention.pin.test.ts @@ -849,7 +849,7 @@ export type Iso384 = Assert, z.i export type Iso718 = Assert, z.infer< typeof M78.ConnectorActionEffectSchema > >>; // kernel/cli-extension.zod.ts -export type Iso385 = Assert, z.infer< typeof M79.CLICommandContributionSchema > >>; +// Iso385 (`CLICommandContributionSchema`) left with the #12007 retirement. export type Iso386 = Assert, z.infer< typeof M79.OclifPluginConfigSchema > >>; // kernel/cluster.zod.ts From 74a3745942598e721161f898f4475aaf16f7141c Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 26 Aug 2026 20:38:29 +0000 Subject: [PATCH 2/3] wip(spec): regenerate artifacts for the CLICommandContribution retirement (#12007) --- content/docs/references/index.mdx | 10 +-- .../docs/references/kernel/cli-extension.mdx | 19 +---- ...07-unknown-key-strictness-ledger.counts.md | 2 +- packages/spec/api-surface/kernel.json | 2 - packages/spec/authorable-surface/kernel.json | 3 - packages/spec/export-origins/kernel.json | 2 - .../spec/json-schema.manifest/kernel.json | 1 - packages/spec/src/migrations/registry.ts | 73 +++++++++++++++++++ 8 files changed, 82 insertions(+), 30 deletions(-) diff --git a/content/docs/references/index.mdx b/content/docs/references/index.mdx index 1e5ab3d435..e23fc15613 100644 --- a/content/docs/references/index.mdx +++ b/content/docs/references/index.mdx @@ -1,6 +1,6 @@ --- title: Protocol Reference -description: Every schema published by @objectstack/spec — 1585 schemas across 14 protocol modules +description: Every schema published by @objectstack/spec — 1584 schemas across 14 protocol modules --- {/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} @@ -26,14 +26,14 @@ counts are sums of the rows they head. Regenerate with | [Data Protocol](/docs/references/data) | 29 | 166 | Objects, fields, queries, filters, datasources and drivers — the ObjectQL layer. | | [Identity Protocol](/docs/references/identity) | 5 | 27 | Users and accounts, organizations, positions, SCIM provisioning. | | [Integration Protocol](/docs/references/integration) | 1 | 27 | The single connector protocol (ADR-0097) — catalog descriptors and provider-bound instances. | -| [Kernel Protocol](/docs/references/kernel) | 31 | 172 | Plugin lifecycle and manifests, capabilities and security, metadata loading, service registry. | +| [Kernel Protocol](/docs/references/kernel) | 31 | 171 | Plugin lifecycle and manifests, capabilities and security, metadata loading, service registry. | | [QA Protocol](/docs/references/qa) | 1 | 8 | Declarative test suites — scenarios, steps, actions and assertions. | | [Security Protocol](/docs/references/security) | 5 | 27 | Permission sets, row-level security, sharing rules, tenancy posture. | | [Shared Protocol](/docs/references/shared) | 8 | 32 | Primitives used across every protocol — identifiers, HTTP, expressions, error maps, enums. | | [Studio Protocol](/docs/references/studio) | 3 | 35 | Studio designer metadata — the authoring surfaces for the protocols above. | | [System Protocol](/docs/references/system) | 36 | 288 | The runtime environment — logging, jobs, cache, metrics, notifications, i18n and compliance. | | [UI Protocol](/docs/references/ui) | 16 | 152 | Apps, pages, views, dashboards, reports, actions and themes — the ObjectUI layer. | -| **Total** | **199** | **1585** | 14 protocol modules | +| **Total** | **199** | **1584** | 14 protocol modules | --- @@ -215,13 +215,13 @@ The single connector protocol (ADR-0097) — catalog descriptors and provider-bo ## Kernel Protocol -**Source:** `packages/spec/src/kernel/` · **Import:** `@objectstack/spec/kernel` · **31 pages, 172 schemas** +**Source:** `packages/spec/src/kernel/` · **Import:** `@objectstack/spec/kernel` · **31 pages, 171 schemas** Plugin lifecycle and manifests, capabilities and security, metadata loading, service registry. | File | Schemas | | :--- | :--- | -| [`cli-extension.zod.ts`](/docs/references/kernel/cli-extension) | `CLICommandContribution`, `OclifPluginConfig` | +| [`cli-extension.zod.ts`](/docs/references/kernel/cli-extension) | `OclifPluginConfig` | | [`cluster.zod.ts`](/docs/references/kernel/cluster) | `ClusterCapabilityConfig`, `ClusterDriver`, `ClusterTenantIsolation`, `EventClusterOptions`, `EventDeliverySemantics`, `EventScope`, `MetadataChangeOperation`, `ServiceClusterAnnotations`, `ServiceClusterScope`, `ServiceLeaderStrategy` | | [`context.zod.ts`](/docs/references/kernel/context) | `KernelContext`, `PreviewModeConfig`, `RuntimeMode`, `TenantRuntimeContext` | | [`dependency-resolution.zod.ts`](/docs/references/kernel/dependency-resolution) | `DependencyResolutionResult`, `DependencyStatusEnum`, `RequiredAction`, `ResolvedDependency` | diff --git a/content/docs/references/kernel/cli-extension.mdx b/content/docs/references/kernel/cli-extension.mdx index 7ff473752d..e37bd5a816 100644 --- a/content/docs/references/kernel/cli-extension.mdx +++ b/content/docs/references/kernel/cli-extension.mdx @@ -71,26 +71,13 @@ The `objectstack.config.ts` plugins array no longer determines CLI commands. ## TypeScript Usage ```typescript -import { CLICommandContributionSchema, OclifPluginConfigSchema } from '@objectstack/spec/kernel'; -import type { CLICommandContribution, OclifPluginConfig } from '@objectstack/spec/kernel'; +import { OclifPluginConfigSchema } from '@objectstack/spec/kernel'; +import type { OclifPluginConfig } from '@objectstack/spec/kernel'; // Validate data -const result = CLICommandContributionSchema.parse(data); +const result = OclifPluginConfigSchema.parse(data); ``` ---- - -## CLICommandContribution - -### Properties - -| Property | Type | Required | Description | -| :--- | :--- | :--- | :--- | -| **name** | `string` | ✅ | CLI command name | -| **description** | `string` | optional | Command description for help text | -| **module** | `string` | optional | Module path exporting oclif Command classes | - - --- ## OclifPluginConfig diff --git a/docs/audits/2026-07-unknown-key-strictness-ledger.counts.md b/docs/audits/2026-07-unknown-key-strictness-ledger.counts.md index ce19699202..822d858d9e 100644 --- a/docs/audits/2026-07-unknown-key-strictness-ledger.counts.md +++ b/docs/audits/2026-07-unknown-key-strictness-ledger.counts.md @@ -261,7 +261,7 @@ directory rather than per file. | `cloud/` | 83 | | `identity/` | 32 | | `integration/` | 10 | -| `kernel/` | 273 | +| `kernel/` | 272 | | `qa/` | 6 | | `shared/` | 20 | | `system/` | 361 | diff --git a/packages/spec/api-surface/kernel.json b/packages/spec/api-surface/kernel.json index ab472c6de6..8ce5a68ead 100644 --- a/packages/spec/api-surface/kernel.json +++ b/packages/spec/api-surface/kernel.json @@ -13,8 +13,6 @@ "BreakingChange (type)", "BreakingChangeParsed (type)", "BreakingChangeSchema (const)", - "CLICommandContribution (type)", - "CLICommandContributionSchema (const)", "CONSUMER_INSTALLABLE_TYPES (const)", "CORE_PLUGIN_TYPES (const)", "CapabilityClassification (interface)", diff --git a/packages/spec/authorable-surface/kernel.json b/packages/spec/authorable-surface/kernel.json index 7ce51a0b06..5bbce3b588 100644 --- a/packages/spec/authorable-surface/kernel.json +++ b/packages/spec/authorable-surface/kernel.json @@ -20,9 +20,6 @@ "kernel/BreakingChange:removedIn", "kernel/BreakingChange:severity", "kernel/BreakingChange:type", - "kernel/CLICommandContribution:description", - "kernel/CLICommandContribution:module", - "kernel/CLICommandContribution:name", "kernel/ClusterCapabilityConfig:driver", "kernel/ClusterCapabilityConfig:driverOptions", "kernel/ClusterCapabilityConfig:heartbeatMs", diff --git a/packages/spec/export-origins/kernel.json b/packages/spec/export-origins/kernel.json index 0fa8a165d2..3911c719d1 100644 --- a/packages/spec/export-origins/kernel.json +++ b/packages/spec/export-origins/kernel.json @@ -13,8 +13,6 @@ "BreakingChange": "src/kernel/plugin-versioning.zod.ts#BreakingChange (type)", "BreakingChangeParsed": "src/kernel/plugin-versioning.zod.ts#BreakingChangeParsed (type)", "BreakingChangeSchema": "src/kernel/plugin-versioning.zod.ts#BreakingChangeSchema (const)", - "CLICommandContribution": "src/kernel/cli-extension.zod.ts#CLICommandContribution (type)", - "CLICommandContributionSchema": "src/kernel/cli-extension.zod.ts#CLICommandContributionSchema (const)", "CONSUMER_INSTALLABLE_TYPES": "src/kernel/plugin.zod.ts#CONSUMER_INSTALLABLE_TYPES (const)", "CORE_PLUGIN_TYPES": "src/kernel/plugin.zod.ts#CORE_PLUGIN_TYPES (const)", "CapabilityClassification": "src/kernel/platform-capabilities.ts#CapabilityClassification (interface)", diff --git a/packages/spec/json-schema.manifest/kernel.json b/packages/spec/json-schema.manifest/kernel.json index 7377645815..7f69207949 100644 --- a/packages/spec/json-schema.manifest/kernel.json +++ b/packages/spec/json-schema.manifest/kernel.json @@ -6,7 +6,6 @@ "kernel/ArtifactFileEntry", "kernel/ArtifactSignature", "kernel/BreakingChange", - "kernel/CLICommandContribution", "kernel/CapabilityConformanceLevel", "kernel/ClusterCapabilityConfig", "kernel/ClusterDriver", diff --git a/packages/spec/src/migrations/registry.ts b/packages/spec/src/migrations/registry.ts index 56f7102274..bac9d6d867 100644 --- a/packages/spec/src/migrations/registry.ts +++ b/packages/spec/src/migrations/registry.ts @@ -5432,6 +5432,53 @@ const step18: MigrationStep = { + 'reference under sharingModel: controlled_by_parent`. Stored metadata keeps loading ' + 'byte-identically (`safeParse` green, `required` unrewritten).', }, + { + id: 'cli-command-contribution-retired', + surface: + 'kernel.cliCommandContribution (the orphan exported schema of ' + + '`cli-extension.zod.ts` — 1 def, 2 exported names: ' + + '`CLICommandContributionSchema` / `CLICommandContribution`)', + replacement: + '(removed — there is no declarative replacement, because no declarative ' + + 'surface ever carried it. CLI commands are registered through oclif\'s ' + + 'native plugin discovery: the plugin package declares an `oclif` ' + + 'section in its own `package.json` — `OclifPluginConfigSchema` in the ' + + 'same module describes that live surface and SURVIVES, as does the ' + + 'module docblock\'s Commander.js migration record, which the ' + + '`manifest.contributes.commands` tombstone cites)', + reason: + 'ADR-0049 enforce-or-remove; #12007, the exported orphan-value-schema ' + + 'class (#3950: an exported schema with no consumer reads as a ' + + 'capability). The schema described a "CLI Command Contribution ' + + 'declaration in the manifest" and claimed retention "for describing ' + + 'command metadata in plugin manifests" — but after #10724 tombstoned ' + + '`manifest.contributes.commands` (protocol 17), no manifest surface ' + + 'could legally carry these entries: the export advertised a shape whose ' + + 'only declared carrier rejects it. The manifest never referenced this ' + + 'schema even before the tombstone — its inline `commands` item schema ' + + 'was an independent duplicate. Zero consumers outside spec\'s own test ' + + 'and generated artifacts, measured at the retirement\'s base commit ' + + '(146f448a5) with positive controls in objectstack, objectui (pinned ' + + 'sha) and cloud. With no carrier key and no authored document there is ' + + 'nothing to tombstone and no seam for a D2 conversion: route 3, the ' + + '#11825 / #8715 shape — RETIRED_DEFS_BY_MAJOR plus this entry ARE the ' + + 'declaration.', + acceptanceCriteria: + 'No code imports `CLICommandContributionSchema` or ' + + '`CLICommandContribution` from `@objectstack/spec` or ' + + '`@objectstack/spec/kernel` — both are TS2305 after upgrade, on every ' + + 'public entry (pinned by resolved symbol identity in ' + + '`kernel/cli-command-contribution-retirement.test.ts`). No metadata ' + + 'document needs editing: the def was reachable from no metadata-type ' + + 'binding, stack collection or manifest embed — the only surface that ' + + 'ever claimed to carry command contributions ' + + '(`manifest.contributes.commands`) already rejects the key with the ' + + '#10724 prescription, which is unchanged by this retirement. ' + + '`OclifPluginConfigSchema` / `OclifPluginConfig` survive on `./kernel` ' + + '(same pin). ⚠️ Runtime behaviour is deliberately UNCHANGED: the CLI ' + + 'never resolved commands from this declaration — commands are ' + + 'oclif-auto-discovered, before and after.', + }, { id: 'dashboard-header-modal-target-page-only', surface: @@ -8553,6 +8600,32 @@ export const RETIRED_DEFS_BY_MAJOR: Readonly> // narrowings ride minor releases) and the prescription lives at the major // boundary where `migrate meta` users look (the #8586 / PR #8702 precedent). 'kernel/AdvancedPluginLifecycleConfig', + // #12007 — kernel/cli-extension.zod.ts + // `CLICommandContributionSchema` / `CLICommandContribution`, retired whole + // (ADR-0049 enforce-or-remove; triage graded 2026-08-25, the exported + // orphan-value-schema class — #3950). The pair described a "CLI Command + // Contribution declaration in the manifest" and claimed retention "for + // describing command metadata in plugin manifests" — but after #10724 + // tombstoned `manifest.contributes.commands`, no manifest surface could + // legally carry these entries: the exported schema advertised a shape whose + // only declared carrier rejects it. The manifest never referenced this schema + // even before the tombstone (its inline `commands` item schema was an + // independent duplicate). Zero consumers outside spec's own test and + // generated artifacts, measured at the retirement's base commit (146f448a5) + // with positive controls in objectstack, objectui (pinned sha) and cloud. + // What ACTUALLY registers CLI commands is oclif's native plugin discovery — + // `OclifPluginConfigSchema` (same module, live `package.json` `oclif` + // section) SURVIVES, as does the module docblock's Commander.js migration + // prose, which the `contributes.commands` tombstone cites. Route 3: no + // carrier key, no authored document for a D2 conversion to rewrite, so no + // tombstone and no conversion — this table plus the D3 semantic entry + // `cli-command-contribution-retired` ARE the declaration. + // + // Registered under 18, not 17: v17.0.0 was cut before this landed, so the + // removal ships on the 17.x line (launch-window convention: accept-set + // narrowings ride minor releases) and the prescription lives at the major + // boundary where `migrate meta` users look (the #8586 / PR #8702 precedent). + 'kernel/CLICommandContribution', // #12340 — kernel/plugin-lifecycle-advanced.zod.ts // `DistributedStateConfigSchema`, retired whole (ADR-0049 enforce-or-remove). // From 2249f631fcbe0f0e4f269aedd6e0f600595ed93e Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 26 Aug 2026 21:26:16 +0000 Subject: [PATCH 3/3] =?UTF-8?q?test(spec):=20pin=20count=20838=20->=20837?= =?UTF-8?q?=20=E2=80=94=20Iso385=20left=20with=20the=20retired=20schema=20?= =?UTF-8?q?(#12007)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/spec/src/type-alias-convention.pin.test.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/spec/src/type-alias-convention.pin.test.ts b/packages/spec/src/type-alias-convention.pin.test.ts index 58c534539b..3631c0c08f 100644 --- a/packages/spec/src/type-alias-convention.pin.test.ts +++ b/packages/spec/src/type-alias-convention.pin.test.ts @@ -267,7 +267,7 @@ import type * as M170 from './ui/component.zod.js'; import type * as M183 from './api/sortability.zod.js'; // --------------------------------------------------------------------------- -// 838 isomorphic aliases: `z.input` === `z.infer`, so no `XParsed` is declared. +// 837 isomorphic aliases: `z.input` === `z.infer`, so no `XParsed` is declared. // // That number is machine-checked, not hand-kept. The runtime companion at the // bottom of this file recomputes the pin count from the source and asserts that @@ -1676,7 +1676,7 @@ describe('ADR-0122 type-alias convention', () => { // this title and the section header above the pin list — are now asserted // against the recomputed count below, so neither can go stale without a red // test naming it. - it('still declares all 838 isomorphic pins', () => { + it('still declares all 837 isomorphic pins', () => { // The truth of each pin is proved by tsc, not here — an `Assert>` // that stops holding is a compile error with the alias named. What tsc // cannot notice is a pin that was DELETED: removing the assertion removes @@ -2006,9 +2006,15 @@ describe('ADR-0122 type-alias convention', () => { // post-merge base after #11924's +3 landed first and took 859-861 — the // pin was renumbered to `Iso862`, the next free one, because ids are // claims about pins, not positions.) + // + // 838 -> 837 is #12007's retirement of `CLICommandContributionSchema` + // (kernel/cli-extension.zod.ts): its pin `Iso385` left with the schema — + // the alias no longer exists, so there is nothing to be isomorphic. -1 + // removed; the Iso number stays vacant (ids are claims about pins, not + // positions). const self = readFileSync(fileURLToPath(import.meta.url), 'utf8'); const pins = self.match(/^export type Iso\d+ = Assert