Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions .changeset/docs-multishape-variant-subtables.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
---
"@objectstack/spec": patch
---

fix(spec): reference pages carry every variant's `.describe()` text when a property opens more than one object shape (#12316)

The designed-and-measured remainder of #11601. #12309 gave a property that
opens exactly ONE nested object shape a `### Nested Shape:` table, and refused
a property whose type is a union of TWO OR MORE object shapes — there was no
single "the shape of this property" for a heading to name, and naming one
would have meant a variant index, i.e. a second addressing notation. Those rows
kept the collapsed signature cell, and the cell has no description column, so
their nested `.describe()` text stayed exactly as unreachable as #11601 found
it.

**The population, re-measured on `origin/main@7bd6447`.** 28 of the 8604
rendered property rows open two or more shapes, and **all 28** carry describe
text on at least one variant: `ui/App.navigation`,
`ui/NavigationArea.navigation` and `ui/NavigationContribution.items` with nine
variants each, `data/ConditionalValidation.then` / `.otherwise` and
`system/CRDTMergeResult.state` with five, `system/ChangeSet.operations` /
`.rollback` with seven, down to four two-variant rows. The census is unchanged
from the one #11601 recorded when it deferred them.

**What is rendered now.** One sub-table per variant, each under the same
`### Nested Shape:` heading in the same position — no new grammar, and no new
heading level, so the single-h1 invariant and the module-header numbering are
untouched. The accessor gains a SELECTOR segment, spliced in where the union
sits in the wrapper stack rather than appended to the finished path, so
`StateMachine.on[string][option 3][number]` reads left to right as *the record
value, its third option, an element of it* — the reading `[string][number]`
already had.

Two spellings, in preference order:

- **`[type='sidebar']`** where the union has a discriminant — a key every
shape-bearing variant pins to a *different* literal. It states what the
author writes to select that variant, in the same `formatLiteral` spelling
the Type cell prints two lines above, and it is stable: reordering the union
or adding a tenth variant moves no existing heading and breaks no existing
anchor. 22 of the 28 rows have one.
- **`[option 2]`** for the six that do not — deliberately the word the union
branch has printed under `### Union Options` since long before this, rather
than a bare `[2]`, which in a stack of `[number]`/`[string]` segments would
read as a tuple index into the property's own type. It counts position in the
union *including* arms that open no shape, so the number is checkable against
the `string | { … } | { … }[]` cell the table sits under.

The distinctness half of the discriminant test is load-bearing: a union whose
arms pin the same `const` has no discriminant by this rule, because answering
one would emit two identical headings — two identical anchors on one page, the
defect the `Schema.key` qualification exists to prevent.

Every bound #11601 set still holds. Depth stays at `SHAPE_DEPTH_LIMIT = 1` —
what was lifted is the multi-shape *refusal* at level 1, not the budget, so a
shape nested inside a variant is exactly as unreachable as it was inside a lone
shape. "Only where there is text to publish" is now decided **per variant**,
which is the same rule one level finer: `ui/FormView.submitBehavior` opens four
shapes and one carries prose, so it gets one table, not four. And a variant
table still relocates no vocabulary — it is a third position for those keys.

A property opening exactly one shape gains no selector segment, because the
stamp is conditioned on the union's own yield and not on the row's: all 1469
single-shape headings #11601 published are byte-identical. The regenerated tree
is **purely additive** — 15 files, **+1397 / -0** lines, no reordering.
36 changes: 36 additions & 0 deletions content/docs/references/ai/conversation.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -104,6 +104,42 @@ const result = CodeContentSchema.parse(data);
| **embedding** | `number[]` | optional | Vector embedding for semantic search |
| **metadata** | `Record<string, any>` | optional | |

### Nested Shape: `ConversationMessage.content[number][type='text']`

| Property | Type | Required | Description |
| :--- | :--- | :--- | :--- |
| **type** | `'text'` | ✅ | |
| **text** | `string` | ✅ | Text content |
| **metadata** | `Record<string, any>` | optional | |

### Nested Shape: `ConversationMessage.content[number][type='image']`

| Property | Type | Required | Description |
| :--- | :--- | :--- | :--- |
| **type** | `'image'` | ✅ | |
| **imageUrl** | `string` | ✅ | Image URL |
| **detail** | `Enum<'low' \| 'high' \| 'auto'>` | optional (default: `"auto"`) | |
| **metadata** | `Record<string, any>` | optional | |

### Nested Shape: `ConversationMessage.content[number][type='file']`

| Property | Type | Required | Description |
| :--- | :--- | :--- | :--- |
| **type** | `'file'` | ✅ | |
| **fileUrl** | `string` | ✅ | File attachment URL |
| **mimeType** | `string` | ✅ | MIME type |
| **fileName** | `string` | optional | |
| **metadata** | `Record<string, any>` | optional | |

### Nested Shape: `ConversationMessage.content[number][type='code']`

| Property | Type | Required | Description |
| :--- | :--- | :--- | :--- |
| **type** | `'code'` | ✅ | |
| **text** | `string` | ✅ | Code snippet |
| **language** | `string` | optional (default: `"text"`) | |
| **metadata** | `Record<string, any>` | optional | |

### Nested Shape: `ConversationMessage.functionCall`

| Property | Type | Required | Description |
Expand Down
18 changes: 18 additions & 0 deletions content/docs/references/ai/knowledge-source.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -87,6 +87,24 @@ const result = FileKnowledgeSourceSchema.parse(data);
| **refresh** | `{ onRecordChange?: boolean; cron?: string }` | optional (default: `{}`) | |
| **aiExposed** | `boolean` | optional (default: `true`) | |

### Nested Shape: `KnowledgeSource.source[kind='object']`

| Property | Type | Required | Description |
| :--- | :--- | :--- | :--- |
| **kind** | `'object'` | ✅ | |
| **object** | `string` | ✅ | Short object name to index |
| **contentFields** | `string[]` | ✅ | Fields contributing to document content |
| **metadataFields** | `string[]` | optional (default: `[]`) | |
| **where** | `Record<string, any>` | optional | |

### Nested Shape: `KnowledgeSource.source[kind='file']`

| Property | Type | Required | Description |
| :--- | :--- | :--- | :--- |
| **kind** | `'file'` | ✅ | |
| **prefix** | `string` | ✅ | Storage prefix |
| **mimeTypes** | `string[]` | optional (default: `[]`) | |

### Nested Shape: `KnowledgeSource.embedding`

| Property | Type | Required | Description |
Expand Down
36 changes: 36 additions & 0 deletions content/docs/references/automation/state-machine.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -159,6 +159,24 @@ Type: `string`
| **states** | `Record<string, { type: Enum<'atomic' \| 'compound' \| 'parallel' \| 'final' \| 'history'>; entry?: (string \| object)[]; exit?: (string \| object)[]; on?: Record<string, string \| object \| object[]>; … }>` | optional | |
| **meta** | `{ label?: string; description?: string; color?: string; aiInstructions?: string }` | optional | |

### Nested Shape: `StateMachine.on[string][option 2]`

| Property | Type | Required | Description |
| :--- | :--- | :--- | :--- |
| **target** | `string` | optional | Target State ID |
| **cond** | `string \| { type: string; params?: Record<string, any> }` | optional | Condition (Guard) required to take this path |
| **actions** | `(string \| { type: string; params?: Record<string, any> })[]` | optional | Actions to execute during transition |
| **description** | `string` | optional | Human readable description of this rule |

### Nested Shape: `StateMachine.on[string][option 3][number]`

| Property | Type | Required | Description |
| :--- | :--- | :--- | :--- |
| **target** | `string` | optional | Target State ID |
| **cond** | `string \| { type: string; params?: Record<string, any> }` | optional | Condition (Guard) required to take this path |
| **actions** | `(string \| { type: string; params?: Record<string, any> })[]` | optional | Actions to execute during transition |
| **description** | `string` | optional | Human readable description of this rule |


---

Expand All@@ -177,6 +195,24 @@ Type: `string`
| **states** | `Record<string, [StateNode](#statenode)>` | optional | |
| **meta** | `{ label?: string; description?: string; color?: string; aiInstructions?: string }` | optional | |

### Nested Shape: `StateNode.on[string][option 2]`

| Property | Type | Required | Description |
| :--- | :--- | :--- | :--- |
| **target** | `string` | optional | Target State ID |
| **cond** | `string \| { type: string; params?: Record<string, any> }` | optional | Condition (Guard) required to take this path |
| **actions** | `(string \| { type: string; params?: Record<string, any> })[]` | optional | Actions to execute during transition |
| **description** | `string` | optional | Human readable description of this rule |

### Nested Shape: `StateNode.on[string][option 3][number]`

| Property | Type | Required | Description |
| :--- | :--- | :--- | :--- |
| **target** | `string` | optional | Target State ID |
| **cond** | `string \| { type: string; params?: Record<string, any> }` | optional | Condition (Guard) required to take this path |
| **actions** | `(string \| { type: string; params?: Record<string, any> })[]` | optional | Actions to execute during transition |
| **description** | `string` | optional | Human readable description of this rule |

### Nested Shape: `StateNode.always[number]`

| Property | Type | Required | Description |
Expand Down
Loading
Loading