From 5a30844272382680bc2c32dbd60d1692e3d2e602 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 6 Sep 2026 05:04:40 +0000 Subject: [PATCH] skills(objectstack-data): the `tree` rows state the landed `reference` contract MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `refuseForeignTreeReference` (packages/spec/src/data/object.zod.ts) makes a `tree` field's `reference` optional and, when written, equal to the declaring object's own name — the `extend` target on an extension. Any other object is refused at parse with one issue at `fields..reference`. The published skill still listed `reference` as a bare key prop, so a client agent reading it had no way to know either half of the rule. Two rows, no new section: - `rules/field-types.md` — the Relational table's `tree` row now states optional-and-self-only and that a foreign object is refused at parse. - `rules/relationships.md` — the `tree` row's bare "Optional" cell now says what is optional and contrasts the refusal with the `master_detail` row's lint-warned cell in the same column. The token ratchet left `field-types.md` 27 bytes under its ceiling, so the row is paid for inside the same file: the Media section's "no per-field attachment config" note restated the top-of-file blockquote, which already refuses `fileAttachmentConfig` by name, above every table. That file now shrinks. The `Hierarchical: tree (Self-Reference)` example is unchanged — it already writes the object's own name (`reference: 'category'` on `category`). Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_019RfFHiRCSs3JXLK4cwcfox --- skills/objectstack-data/rules/field-types.md | 5 +---- skills/objectstack-data/rules/relationships.md | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/skills/objectstack-data/rules/field-types.md b/skills/objectstack-data/rules/field-types.md index 80bbe19a41..dcf4c2e45d 100644 --- a/skills/objectstack-data/rules/field-types.md +++ b/skills/objectstack-data/rules/field-types.md @@ -88,7 +88,7 @@ options: [ |:-----|:------------|:-----------| | `lookup` | Reference another object (independent) | `reference`, `lookupFilters`, `multiple`, `deleteBehavior` | | `master_detail` | Parent–child with lifecycle control | `reference`, `deleteBehavior` (`cascade`/`restrict` — `set_null` is refused) | -| `tree` | Hierarchical self-reference | `reference` | +| `tree` | Hierarchical self-reference | `reference` — optional; when written, this object's own name (any other object is refused at parse) | | `user` | Person picker — a lookup specialized to `sys_user` (assignee, watchers). Stored identically to `lookup` | `multiple` (collaborators), `defaultValue: 'current_user'` | > **`multiple: true` lookup ≠ junction object.** A multi-value lookup is stored @@ -106,9 +106,6 @@ options: [ | `video` | Video files | — | | `audio` | Audio files | — | -There is no per-field attachment config (size limits, allowed types, storage) — -storage concerns live outside the field schema. - ## Embedded (JSON sub-objects) Stored as JSON on the parent row — no separate table / FK: diff --git a/skills/objectstack-data/rules/relationships.md b/skills/objectstack-data/rules/relationships.md index 6fa8663bbe..e241b2d108 100644 --- a/skills/objectstack-data/rules/relationships.md +++ b/skills/objectstack-data/rules/relationships.md @@ -8,7 +8,7 @@ Guide for modeling relationships between objects using `lookup`, `master_detail` |:-----|:----------|:---------|:--------|:---------|:---------| | `lookup` | Independent | Optional by default | Independent | Supported via `summary` | "Related to" | | `master_detail` | Coupled (cascade delete) | Forced only under `controlled_by_parent`; else lint-warned | Inherits parent | Supported via `summary` | "Owned by" | -| `tree` | Self-reference | Optional | N/A | Not available | Hierarchical | +| `tree` | Self-reference | Optional — and so is `reference`, which when written must name this object itself; any other object is refused at parse, not lint-warned | N/A | Not available | Hierarchical | ## When to Use lookup vs master_detail