Filed by the domain:spec execution seat 2, session session_01UDXER3sdqfeVYpEWZs5mZx, 2026-09-22T11:19Z. ⛔ Unlabelled and unrouted — an execution seat files, triage grades and routes. Suggested lane: domain:services (the emitter lives in packages/services/service-datasource), ⚠️ but see the lane-split warning below: the door the user actually walks through is a packages/cli command.
What it emits, measured at origin/main
packages/services/service-datasource/src/external-datasource-service.ts:931 renders the annotated-object-literal shape:
`import type { ServiceObject } from '@objectstack/spec/data';`,
``,
`const ${definition.name} : ServiceObject = {`,
…
`};`,
``,
`export default ${definition.name};`,
Ruling 5644350230 (director seat, decision batch #122 item 1, maintainer 「同意」 2026-09-12) makes ObjectSchema.create({ … }) the one authorised shape for a *.object.ts. This emitter writes the other one.
⭐ It really is a *.object.ts, and the package says so itself
This is the fact that separates this card from a stylistic one, and it is quoted rather than inferred:
reading at origin/main |
what it says |
packages/services/service-datasource/src/external-datasource-service.ts:857 |
the function's own docblock: 「Render a reviewable *.object.ts source string for an object draft」 |
packages/cli/src/commands/datasource/introspect.ts:18 |
「draft (*.object.ts) from a remote table (ADR-0015)」 |
packages/cli/src/commands/datasource/introspect.ts:26 |
the published example: os datasource introspect warehouse --table fact_orders --out objects/wh_order.object.ts |
packages/services/service-datasource/src/external-datasource-service.ts:507 |
the error text tells the user to 「commit the generated *.object.ts instead」 |
⇒ the emitted bytes are destined for a committed *.object.ts in a user's repo, by the tool's own documented workflow. Once #19720 lands ruling item ②, a repo that runs the gate refuses exactly the file os datasource introspect just told the user to commit.
⭐⭐ This package has been in this exact position before — read that precedent FIRST
packages/services/service-datasource/CHANGELOG.md:1422 records a prior round where this same generator produced 「a *.object.ts the platform's own validator refuses, on two independent counts」, and :1391 records the same class again. ⇒ the taker should read those entries before writing anything: the repair shape is already established in this package, and so is the failure mode of repairing only what was named.
⚠️ The emitter also carries two authored comment blocks that must survive any rewrite, both of which exist because a previous draft was refused: the REMOTE_PRIMARY_KEY_COMMENT block at :896-902 (a composite key some drivers under-report, #10997/#11000) and the namespaceTodo block at :919-923 (ADR-0028 unprefixed-name warning). Neither is decoration; each is a prior defect's tombstone.
⚠️ The lane may split, exactly as ruling item 4 describes
Ruling item 4:
The taker declares the file surface; if it crosses packages/cli and packages/spec / scripts, the cli half is a sibling PR by the domain:cli seat, ⛔ not a rider across lanes.
The emitter is packages/services; the command that invokes it, its help text and its published example are packages/cli/src/commands/datasource/introspect.ts. Whether the example line and the --out guidance need to move with the shape is the taker's declaration to make, and if it does, that half is the domain:cli seat's sibling PR — ⛔ not a rider. Triage should decide whether to route this as one card with a declared split or two.
Pins to re-check, ⛔ not a claim that they all move
packages/services/service-datasource/src/__tests__/external-object-draft-os-build.test.ts — its docblock at :6 states the contract: 「generateObjectDraft renders a *.object.ts a human is meant to review and」 … ⇒ it asserts the emitted bytes survive a real build, so it is the pin most likely to encode the shape.
- Anything else under that package's
__tests__ asserting on the emitted source text.
What this card does NOT claim
⛔ It does not claim a landing order against #19720. Measured by the seat for #17418: check:keyed-text-bounds selects its population by filename suffix over the repo tree (112 *.object.ts files on origin/main, zero under packages/cli or packages/services), and the strings here are template literals inside a .ts file, so this repo's own gate never reads them in any shape. ⇒ #19720 lands independently, and this card is the user-facing half: until it lands, os datasource introspect keeps handing users a file the platform refuses.
Provenance
Found by the os-dev agent on card #17418 while censusing ruling item ③, raised as its open question Q1, and answered option A by this seat: each emitter outside packages/cli becomes its own card in the lane that owns its package, because ruling item 4's lane split routes them to neither the spec seat nor the cli seat. ⛔ Option B (ride #19720) is precisely the cross-lane rider item 4 forbids by name; ⛔ option C (leave them) contradicts the ruling, which makes the factory the one authorised shape for a *.object.ts and this writes one. Sibling cards: #17418 / PR #19720 (items ② and ③), #19722 (item ①, packages/cli), and one more filed alongside this for packages/metadata.
Duplicate-search words
generateObjectDraft, os datasource introspect, ServiceObject annotated literal, ruling 5644350230 item 3, ObjectSchema.create emitter
Generated by Claude Code
Filed by the⚠️ but see the lane-split warning below: the door the user actually walks through is a
domain:specexecution seat 2, sessionsession_01UDXER3sdqfeVYpEWZs5mZx, 2026-09-22T11:19Z. ⛔ Unlabelled and unrouted — an execution seat files, triage grades and routes. Suggested lane:domain:services(the emitter lives inpackages/services/service-datasource),packages/clicommand.What it emits, measured at
origin/mainpackages/services/service-datasource/src/external-datasource-service.ts:931renders the annotated-object-literal shape:Ruling
5644350230(director seat, decision batch #122 item 1, maintainer 「同意」 2026-09-12) makesObjectSchema.create({ … })the one authorised shape for a*.object.ts. This emitter writes the other one.⭐ It really is a
*.object.ts, and the package says so itselfThis is the fact that separates this card from a stylistic one, and it is quoted rather than inferred:
origin/mainpackages/services/service-datasource/src/external-datasource-service.ts:857*.object.tssource string for an object draft」packages/cli/src/commands/datasource/introspect.ts:18*.object.ts) from a remote table (ADR-0015)」packages/cli/src/commands/datasource/introspect.ts:26os datasource introspect warehouse --table fact_orders --out objects/wh_order.object.tspackages/services/service-datasource/src/external-datasource-service.ts:507⇒ the emitted bytes are destined for a committed
*.object.tsin a user's repo, by the tool's own documented workflow. Once #19720 lands ruling item ②, a repo that runs the gate refuses exactly the fileos datasource introspectjust told the user to commit.⭐⭐ This package has been in this exact position before — read that precedent FIRST
packages/services/service-datasource/CHANGELOG.md:1422records a prior round where this same generator produced 「a*.object.tsthe platform's own validator refuses, on two independent counts」, and:1391records the same class again. ⇒ the taker should read those entries before writing anything: the repair shape is already established in this package, and so is the failure mode of repairing only what was named.REMOTE_PRIMARY_KEY_COMMENTblock at:896-902(a composite key some drivers under-report, #10997/#11000) and thenamespaceTodoblock at:919-923(ADR-0028 unprefixed-name warning). Neither is decoration; each is a prior defect's tombstone.Ruling item 4:
The emitter is
packages/services; the command that invokes it, its help text and its published example arepackages/cli/src/commands/datasource/introspect.ts. Whether the example line and the--outguidance need to move with the shape is the taker's declaration to make, and if it does, that half is thedomain:cliseat's sibling PR — ⛔ not a rider. Triage should decide whether to route this as one card with a declared split or two.Pins to re-check, ⛔ not a claim that they all move
packages/services/service-datasource/src/__tests__/external-object-draft-os-build.test.ts— its docblock at:6states the contract: 「generateObjectDraftrenders a*.object.tsa human is meant to review and」 … ⇒ it asserts the emitted bytes survive a real build, so it is the pin most likely to encode the shape.__tests__asserting on the emitted source text.What this card does NOT claim
⛔ It does not claim a landing order against #19720. Measured by the seat for #17418:
check:keyed-text-boundsselects its population by filename suffix over the repo tree (112*.object.tsfiles onorigin/main, zero underpackages/cliorpackages/services), and the strings here are template literals inside a.tsfile, so this repo's own gate never reads them in any shape. ⇒ #19720 lands independently, and this card is the user-facing half: until it lands,os datasource introspectkeeps handing users a file the platform refuses.Provenance
Found by the
os-devagent on card #17418 while censusing ruling item ③, raised as its open question Q1, and answered option A by this seat: each emitter outsidepackages/clibecomes its own card in the lane that owns its package, because ruling item 4's lane split routes them to neither the spec seat nor the cli seat. ⛔ Option B (ride #19720) is precisely the cross-lane rider item 4 forbids by name; ⛔ option C (leave them) contradicts the ruling, which makes the factory the one authorised shape for a*.object.tsand this writes one. Sibling cards: #17418 / PR #19720 (items ② and ③), #19722 (item ①,packages/cli), and one more filed alongside this forpackages/metadata.Duplicate-search words
generateObjectDraft,os datasource introspect,ServiceObject annotated literal,ruling 5644350230 item 3,ObjectSchema.create emitterGenerated by Claude Code