Skip to content

Two official scaffolders and two published docs disagree on how a .object.ts may be written — ObjectSchema.create() factory vs plain annotated literal #17418

Description

@baozhoutao

Ruled: 5644350230 · letter A · 2026-09-12T07:02Z — director seat, decision batch #122 item 1, maintainer 「同意」.
Items ② and ③ LANDED on main in PR #19720 (merge commit 42339e2f48, one parent, 2026-09-22T13:07Z); ⛔ this card stays open because the body opens 「Part of」, so item ① keeps a carrier.

Blocked-by: #19722

⛔ Item ① (packages/cli/src/commands/init.ts TEMPLATES + content/docs/deployment/cli.mdx:1323, and generate.ts which the ruling under-names) is the cli half, and ruling item 4 makes it a sibling PR by the domain:cli seat, ⛔ not a rider across lanes. ⇒ nothing here is dispatchable by the domain:spec seat until #19722 lands.


Filed by the #16195 implementer, per that card's instruction to file this finding (unlabelled, for triage) if the "is the factory shape this repo's settled authorised shape" question could be read clearly while doing that card. It could not be resolved outright, but concrete published evidence on both sides was found, which is what follows.

Measured on origin/main d57611dfd3

The gate only reads the factory shape. check:keyed-text-bounds recognises ObjectSchema.create({ … }) (CREATE_CALL regex in scripts/check-keyed-text-bounds.mjs) — every one of the 112 *.object.ts files it currently parses is that shape.

os init's own emitter writes the other shape, a plain annotated object literal — documented explicitly in content/docs/deployment/cli.mdx:1323: "Creates a typed TypeScript file using Data.ServiceObject, UI.View, Automation.Flow, etc." Confirmed live by generating a template (TEMPLATES in packages/cli/src/commands/init.ts):

import * as Data from '@objectstack/spec/data';

const myAppItem: Data.ServiceObject = {
  name: 'my_app_item',
  fields: {},
  sharingModel: 'private',
};

export default myAppItem;

Evidence gathered this round, both directions

For the factory shape as "the" pattern:

  • content/docs/data-modeling/schema-design.mdx:11-19 — published, user-facing: "Every object definition follows this pattern:" followed by an ObjectSchema.create({…}) example. Not phrased as "one option" — phrased as the pattern.
  • packages/create-objectstack's own bundled template (packages/create-objectstack/src/templates/blank/src/objects/note.object.ts) — a second, independent official scaffolder (npx create-objectstack, the standalone entry point) — also emits the factory shape.
  • Every ADR code example found this round that shows an object declaration (docs/adr/0007, 0066, 0100, 0103) uses the factory shape.

For the literal shape as intentional, not accidental:

  • content/docs/deployment/cli.mdx:1323 documents os init/os g emitting the Data.*-typed literal as the described, current behaviour of a still-maintained, still-documented command — not flagged anywhere as deprecated or as a shape migration in progress.
  • packages/cli/src/commands/init.ts's TEMPLATES is actively synced for version-policy correctness (scripts/sync-scaffold-emission-policy.mjs, which keeps create-objectstack's bundled template's pnpm/typescript ranges in lockstep with it) — i.e. it is treated as a maintained source of truth for scaffolding, not legacy code nobody touches.

What was not found

No ADR, ledger, or ruling comment titled or framed as "which shape may a .object.ts declaration take" — nothing that resolves the disagreement one way or the other. The evidence above shows the disagreement is real, documented on both sides, and not a one-file fluke — not which side should win.

Why this deserves its own answer (from #16195, adopted here)

The second is not merely a cleanup: it would mean the repo's own gate and the repo's own scaffolder currently disagree about how an object file may be written, which is a question worth answering deliberately rather than as a side effect.

Two live resolutions, at least:

  • teach check:keyed-text-bounds (and any other .object.ts-shape-sensitive tooling) the plain-literal declaration shape, so a scaffolded object file is judged rather than refused; or
  • change os init's emitter (TEMPLATES / writeTemplateSrcFiles) to emit the factory shape, matching create-objectstack, schema-design.mdx, and every gate-readable example in the tree.

Neither is this card's to choose. Not scoped further — routing and domain assignment are triage's.


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions