From 2f9c654e1b494075dbc78676ea67444650083fcf Mon Sep 17 00:00:00 2001 From: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com> Date: Sun, 28 Jun 2026 02:28:15 +0800 Subject: [PATCH] feat(spec): remove first batch of dead metadata props (#2377, A2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cleanly-verifiable, unique-named dead props with zero footprint outside spec: - field: caseSensitive, maxRating - object: partitioning (+PartitioningConfigSchema), defaultDetailForm Liveness ledgers (field/object) updated; api-surface regenerated (drops PartitioningConfig type only). softDelete + measures.certified deferred (set in non-spec test fixtures); overloaded-name candidates deferred (see #2377). Verified: full spec suite green; check:api-surface ✓; liveness gate ✓; no non-spec usage of the four removed props. Co-Authored-By: Claude Opus 4.8 --- .changeset/v11-a2-trivial-deadprops.md | 14 +++++++++++++ packages/spec/api-surface.json | 2 -- packages/spec/liveness/field.json | 10 --------- packages/spec/liveness/object.json | 12 ----------- packages/spec/src/data/field.zod.ts | 2 -- packages/spec/src/data/object.zod.ts | 29 -------------------------- 6 files changed, 14 insertions(+), 55 deletions(-) create mode 100644 .changeset/v11-a2-trivial-deadprops.md diff --git a/.changeset/v11-a2-trivial-deadprops.md b/.changeset/v11-a2-trivial-deadprops.md new file mode 100644 index 0000000000..7e43480fdc --- /dev/null +++ b/.changeset/v11-a2-trivial-deadprops.md @@ -0,0 +1,14 @@ +--- +"@objectstack/spec": minor +--- + +Remove a first batch of dead (unenforced, unauthored) metadata properties (#2377, ADR-0049). + +Verified set 0× / read 0× across framework + objectui + cloud + hotcrm + templates, with no test footprint outside `@objectstack/spec`: + +- **field**: `caseSensitive`, `maxRating` +- **object**: `partitioning` (+ `PartitioningConfigSchema`), `defaultDetailForm` + +Liveness ledgers (field/object) updated; api-surface regenerated (drops `PartitioningConfig`/`PartitioningConfigSchema` only). Folded into the 11 line (`minor`). + +The remaining #2377 candidates are deliberately not in this batch: overloaded names (`tags`/`active`/`versioning`/`dependencies`/`index`/…) need per-occurrence handling, and `softDelete` / `measures.certified` turned out to be set in non-spec test fixtures (analytics, mcp) — both deferred. See the issue for the full split. diff --git a/packages/spec/api-surface.json b/packages/spec/api-surface.json index e7192caa67..f55cb6d72f 100644 --- a/packages/spec/api-surface.json +++ b/packages/spec/api-surface.json @@ -347,8 +347,6 @@ "ObjectOwnershipEnum (const)", "ObjectSchema (const)", "OperatorKey (type)", - "PartitioningConfig (type)", - "PartitioningConfigSchema (const)", "PoolConfig (type)", "PoolConfigSchema (const)", "QueryAST (type)", diff --git a/packages/spec/liveness/field.json b/packages/spec/liveness/field.json index 9e9c8f5d38..37d7b6ac02 100644 --- a/packages/spec/liveness/field.json +++ b/packages/spec/liveness/field.json @@ -192,12 +192,6 @@ "status": "live", "note": "objectui LookupField — opt-in inline quick-create (dataSource.create from typed text) (reads allowCreate || allow_create)." }, - "maxRating": { - "status": "dead", - "evidence": "RatingField reads `max` (RatingField.tsx:13) — dead + redundant with max", - "authorWarn": true, - "authorHint": "The rating renderer reads `max`, not `maxRating` — set `max` instead; `maxRating` is ignored." - }, "columnName": { "status": "dead", "evidence": "resolveColumnName (spec system-names.ts:182) has ZERO call sites; SQL driver hardcodes column = field key", @@ -246,10 +240,6 @@ "status": "dead", "evidence": "no consumer" }, - "caseSensitive": { - "status": "dead", - "evidence": "no consumer" - }, "inlineTitle": { "status": "live", "evidence": "objectui: packages/app-shell/src/providers/MetadataProvider.tsx + plugin-form/deriveMasterDetail.ts", diff --git a/packages/spec/liveness/object.json b/packages/spec/liveness/object.json index d1fa2a8553..f4cf3c6976 100644 --- a/packages/spec/liveness/object.json +++ b/packages/spec/liveness/object.json @@ -201,12 +201,6 @@ "authorWarn": true, "authorHint": "No record-versioning engine reads this block — setting it stores nothing and snapshots no history. Remove it (use Field.trackHistory for field-level history)." }, - "partitioning": { - "status": "dead", - "evidence": "aspirational; no runtime", - "authorWarn": true, - "authorHint": "No table-partitioning is applied from this block. Remove it — it has no runtime effect." - }, "softDelete": { "status": "dead", "evidence": "no runtime; duplicates the (also dead) enable.trash", @@ -219,12 +213,6 @@ "authorWarn": true, "authorHint": "No search-engine config is consumed. Remove it — records remain queryable via the normal data API regardless." }, - "defaultDetailForm": { - "status": "dead", - "evidence": "documented fallback chain unimplemented", - "authorWarn": true, - "authorHint": "The detail form is chosen by the view layer; this field's documented fallback chain is unimplemented and ignored. Remove it." - }, "recordName": { "status": "dead", "evidence": "superseded by a field of type:'autonumber' + autonumberFormat (engine.ts:757)", diff --git a/packages/spec/src/data/field.zod.ts b/packages/spec/src/data/field.zod.ts index 08f4b8dd3c..70e1c812de 100644 --- a/packages/spec/src/data/field.zod.ts +++ b/packages/spec/src/data/field.zod.ts @@ -509,7 +509,6 @@ export const FieldSchema = lazySchema(() => z.object({ // addressFormat, color colorFormat/allowAlpha/presetColors, slider showValue/marks, // barcode/qr barcodeFormat/qrErrorCorrection/displayValue/allowScanning. language: z.string().optional().describe('Programming language for syntax highlighting (e.g., javascript, python, sql)'), - maxRating: z.number().optional().describe('Maximum rating value (default: 5)'), step: z.number().optional().describe('Step increment for slider (default: 1)'), // Currency field config @@ -582,7 +581,6 @@ export const FieldSchema = lazySchema(() => z.object({ system: z.boolean().optional().describe('Auto-injected system/audit field (e.g. created_at, updated_by, organization_id). Tools that surface system fields separately from author-declared business fields should branch on this flag.'), sortable: z.boolean().optional().default(true).describe('Whether field is sortable in list views'), inlineHelpText: z.string().optional().describe('Help text displayed below the field in forms'), - caseSensitive: z.boolean().optional().describe('Whether text comparisons are case-sensitive'), /** * Auto-number display format. Literal text interleaved with `{...}` tokens: * diff --git a/packages/spec/src/data/object.zod.ts b/packages/spec/src/data/object.zod.ts index ca085aa5fc..395f0e0188 100644 --- a/packages/spec/src/data/object.zod.ts +++ b/packages/spec/src/data/object.zod.ts @@ -197,32 +197,6 @@ export const VersioningConfigSchema = lazySchema(() => z.object({ versionField: z.string().default('version').describe('Field name for version number/timestamp'), })); -/** - * Partitioning Strategy Schema - * Configures table partitioning for performance at scale - * - * @example Range partitioning by date (monthly) - * { - * enabled: true, - * strategy: 'range', - * key: 'created_at', - * interval: '1 month' - * } - */ -export const PartitioningConfigSchema = lazySchema(() => z.object({ - enabled: z.boolean().describe('Enable table partitioning'), - strategy: z.enum(['range', 'hash', 'list']).describe('Partitioning strategy: range (date ranges), hash (consistent hashing), list (predefined values)'), - key: z.string().describe('Field name to partition by'), - interval: z.string().optional().describe('Partition interval for range strategy (e.g., "1 month", "1 year")'), -}).refine((data) => { - // If strategy is 'range', interval must be provided - if (data.strategy === 'range' && !data.interval) { - return false; - } - return true; -}, { - message: 'interval is required when strategy is "range"', -})); /** * Object Field Group Schema — MVP (data-layer protocol) @@ -540,7 +514,6 @@ const ObjectSchemaBase = z.object({ versioning: VersioningConfigSchema.optional().describe('Record versioning and history tracking configuration'), // Partitioning strategy - partitioning: PartitioningConfigSchema.optional().describe('Table partitioning configuration for performance'), /** * Logic & Validation (Co-located) @@ -620,7 +593,6 @@ const ObjectSchemaBase = z.object({ * same metadata drives both the public collection form and the operator's * edit panel. */ - defaultDetailForm: z.string().optional().describe('Name of the default FormView for record detail / edit screens'), /** * Search Engine Config @@ -915,7 +887,6 @@ export type TenancyConfig = z.infer; export type ObjectAccessConfig = z.infer; export type SoftDeleteConfig = z.infer; export type VersioningConfig = z.infer; -export type PartitioningConfig = z.infer; /** * Resolved CRUD affordance matrix for an object — what generic