Met while landing the one-line docs fix on #13928 (PR #14890); filed unassigned for triage. No severity claim, and this is not the residual that #13928's triage fenced off (that one asks whether a reference-less tree judged relation and materialising deleteBehavior makes sense — still unanswered, still separate).
The shape
#13928 settled whether a tree field's reference is required: it is not, it is optional, and both docs cells asserting otherwise are corrected in PR #14890. What that card did not ask, and triage did not rule on, is what a tree field's reference means when it is present. Four surfaces answer differently, and none of them is enforced:
| surface |
what it says a tree reference is |
packages/spec/src/kernel/functional-completeness.ts:311-318 (hasDetectableParentField) |
nothing — the tree arm is def.type === 'tree' alone. The reference === own test exists only on the lookup / master_detail arm, so a tree field is accepted as this object's parent pointer whatever its reference says, or with none at all. Its docblock states it mirrors objectui's detectParentField (packages/plugin-tree/src/ObjectTree.tsx) deliberately, "Mirrored, not tightened". |
packages/spec/src/data/object.form.ts:191 |
a free "Target object name" — the designer shows the reference input for data.type in ['lookup','master_detail','tree'] with the same help text for all three, i.e. any object. |
docs prose, 4 places — content/docs/data-modeling/validation-rules.mdx:542 ("Self-referencing; no automatic cycle check"), content/docs/data-modeling/field-type-decision-tree.mdx:176 ("Self-referencing hierarchy", example category → category), skills/objectstack-data/rules/field-types.md:91 ("Hierarchical self-reference"), skills/objectstack-data/rules/relationships.md:11 ("Self-reference") |
the object's own name |
examples/app-showcase/src/data/objects/field-zoo.object.ts:108 |
neither, and it says so in its own label: f_tree: { type: 'tree', label: 'Tree (self/category)', reference: 'showcase_category' } on the object showcase_field_zoo (:21). The label hedges self/category; the value points at a different object. |
So the one shipped declaration of the type disagrees with the four prose surfaces that describe it, the predicate that consumes it reads neither, and nothing rejects either shape. A renderer would treat that f_tree as showcase_field_zoo's parent pointer while its reference names showcase_category.
Why it is worth a card rather than a note
The claim is load-bearing for AI-authored metadata: an agent reading skills/objectstack-data/rules/field-types.md writes reference: THIS_OBJECT_NAME, an agent reading the designer help text writes any object name, and both parse. Whichever is intended, the other spelling is authored silently today.
Not proposed here
Which answer is right, and whether the fix is prose, a gate, or a spec narrowing — that is the triage decision, and it interacts with the fenced residual on #13928. Note two of the five prose surfaces are under skills/**, a governed surface, so any prose alignment there is a separate lane.
Dedupe
Enumerated all 504 open issues via GET /repos/objectstack-ai/objectstack/issues?state=open&per_page=100 (pages 1-6, short page reached at 66, PRs excluded) and grepped titles and bodies locally: self[- ]?referen|自指 returns only #13928 itself; validation-rules.mdx returns zero; the control term troubleshooting.mdx returns two real rows, so the grep was live.
Refs
#13928 / PR #14890 (the requirement half, settled) · hasDetectableParentField docblock (the consuming predicate)
Generated by Claude Code
Generated by Claude Code
Met while landing the one-line docs fix on #13928 (PR #14890); filed unassigned for triage. No severity claim, and this is not the residual that #13928's triage fenced off (that one asks whether a reference-less
treejudgedrelationand materialisingdeleteBehaviormakes sense — still unanswered, still separate).The shape
#13928 settled whether a
treefield'sreferenceis required: it is not, it is optional, and both docs cells asserting otherwise are corrected in PR #14890. What that card did not ask, and triage did not rule on, is what atreefield'sreferencemeans when it is present. Four surfaces answer differently, and none of them is enforced:referenceispackages/spec/src/kernel/functional-completeness.ts:311-318(hasDetectableParentField)treearm isdef.type === 'tree'alone. Thereference === owntest exists only on thelookup/master_detailarm, so atreefield is accepted as this object's parent pointer whatever itsreferencesays, or with none at all. Its docblock states it mirrors objectui'sdetectParentField(packages/plugin-tree/src/ObjectTree.tsx) deliberately, "Mirrored, not tightened".packages/spec/src/data/object.form.ts:191referenceinput fordata.type in ['lookup','master_detail','tree']with the same help text for all three, i.e. any object.content/docs/data-modeling/validation-rules.mdx:542("Self-referencing; no automatic cycle check"),content/docs/data-modeling/field-type-decision-tree.mdx:176("Self-referencing hierarchy", examplecategory → category),skills/objectstack-data/rules/field-types.md:91("Hierarchical self-reference"),skills/objectstack-data/rules/relationships.md:11("Self-reference")examples/app-showcase/src/data/objects/field-zoo.object.ts:108f_tree: { type: 'tree', label: 'Tree (self/category)', reference: 'showcase_category' }on the objectshowcase_field_zoo(:21). The label hedgesself/category; the value points at a different object.So the one shipped declaration of the type disagrees with the four prose surfaces that describe it, the predicate that consumes it reads neither, and nothing rejects either shape. A renderer would treat that
f_treeasshowcase_field_zoo's parent pointer while itsreferencenamesshowcase_category.Why it is worth a card rather than a note
The claim is load-bearing for AI-authored metadata: an agent reading
skills/objectstack-data/rules/field-types.mdwritesreference: THIS_OBJECT_NAME, an agent reading the designer help text writes any object name, and both parse. Whichever is intended, the other spelling is authored silently today.Not proposed here
Which answer is right, and whether the fix is prose, a gate, or a spec narrowing — that is the triage decision, and it interacts with the fenced residual on #13928. Note two of the five prose surfaces are under
skills/**, a governed surface, so any prose alignment there is a separate lane.Dedupe
Enumerated all 504 open issues via
GET /repos/objectstack-ai/objectstack/issues?state=open&per_page=100(pages 1-6, short page reached at 66, PRs excluded) and grepped titles and bodies locally:self[- ]?referen|自指returns only #13928 itself;validation-rules.mdxreturns zero; the control termtroubleshooting.mdxreturns two real rows, so the grep was live.Refs
#13928 / PR #14890 (the requirement half, settled) ·
hasDetectableParentFielddocblock (the consuming predicate)Generated by Claude Code
Generated by Claude Code