docs(content): a tree field does not require reference — two pages said it did - #14890
Merged
os-sam merged 1 commit intoSep 3, 2026
Merged
Conversation
…s said it did `reference` is required for `lookup` and `master_detail` only. Three surfaces already agree on that and two docs pages disagreed with all three: - `packages/spec/src/data/field.zod.ts:1064-1065` (the `reference` docblock) names `lookup` and `master_detail` as the types the superRefine enforces it for. - `packages/spec/src/data/field.zod.ts:1073` (`.describe()`) says "Target object name (snake_case) for lookup/master_detail fields". - `packages/lint/src/data-model-rules.ts:103` — `RELATIONSHIP_TYPES = new Set(['lookup', 'master_detail'])`, consumed at :499 and :577 by `relationship/missing-reference`. `tree` is not in the set. A reference-less `tree` is a shape the spec's own tests construct and assert defined behaviour for — `field-value.test.ts:69` (`referenceTargetOf` returns undefined) and `filter-dotted-head.test.ts:31` (still classified `relation`) — so no gate rejects one and none should: the docs were asserting a requirement nothing enforces. A default-self-reference reading is falsified too, by `examples/app-showcase/src/data/objects/field-zoo.object.ts:108`, where a `tree` field points at `showcase_category` rather than at its own object. Two cells, both stating the same claim: - `content/docs/deployment/troubleshooting.mdx:78` drops `tree` from the symptom line. The Cause line at :80 stays true for the two remaining types. - `content/docs/data-modeling/validation-rules.mdx:542` — the "Quick Validation Summary" table's second column is `Required Props` (:517), and the `tree` row listed `reference` there. It becomes an em dash, matching the `user` row beside it, which is likewise a reference-carrying type with no required prop. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017RbbUMnxkUnWhE4j94v8FE
Collaborator
|
Landing provenance (seat, 08:16Z) — ready + auto-merge (squash) from here.
Generated by Claude Code |
os-sam
marked this pull request as ready for review
September 3, 2026 08:15
os-sam
enabled auto-merge
September 3, 2026 08:15
os-sam
deleted the
claude/issue-13928-troubleshooting-tree-reference-line
branch
September 3, 2026 10:16
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #13928
Two docs cells said a
treefield requires areference. Nothing enforces that, and the spec's own tests construct a reference-lesstreeand assert defined behaviour for it. Both cells now say what the other surfaces already said.Before / after
content/docs/deployment/troubleshooting.mdx:78— the card's line::80("Relational fields require areferenceproperty pointing to the target object.") is untouched — it stays true for the two remaining types.content/docs/data-modeling/validation-rules.mdx:542— the second page, see "Second page" below:That table's second column header is
Required Props(:517), so the old cell was the same claim in table form. The em dash matches theuserrow directly above it (:540) — likewise a reference-carrying type with no required prop — and is the same U+2014 byte the rest of the column uses.Why — the triage census, quoted
Triage comment 5486903425 ran the card's census and tabulated four surfaces, three agreeing and one outlier. Quoted verbatim, untranslated:
All three agreeing surfaces re-read on
origin/main2263ca4d6before editing:packages/spec/src/data/field.zod.ts:1064-1065— "Used bylookupandmaster_detailfield types … Thereferenceproperty is required for these types … the superRefine below enforces it".packages/spec/src/data/field.zod.ts:1073—.describe('Target object name (snake_case) for lookup/master_detail fields. …').packages/lint/src/data-model-rules.ts:103—const RELATIONSHIP_TYPES = new Set(['lookup', 'master_detail']);, consumed at:499and:577byrelationship/missing-reference.treeis not in the set.And the two readings that make "required" and "default self-reference" untenable rather than merely unenforced:
packages/spec/src/data/field-value.test.ts:69andpackages/spec/src/data/filter-dotted-head.test.ts:31construct atreewith noreferenceand assert defined behaviour, so a gate demanding one would red the spec's own test surface.examples/app-showcase/src/data/objects/field-zoo.object.ts:108—f_tree: { type: 'tree', reference: 'showcase_category' }points at another object, so "defaults to self" is wrong for a shipped example.Second page:
validation-rules.mdx:542The dispatch's H2 anticipated a second page in the same sentence family and allowed fixing it here only if it is the same one-line claim. It is: the
Required Propscell fortree, stating the identical requirement in a table instead of a sentence. The PM's H2 grep missed it because the row carries no "require" wording of its own — the requirement lives in the column header.Four conditions for taking it in place, measured rather than assumed:
userrow and by the three agreeing surfaces above. No judgement call was left open.GET /pulls/{n}/files, 60/60 readable, 0 hits on either path). Nearest neighbour is PR perf(datasource): size the primary SQL pool from OS_DATABASE_POOL_MAX #14776, which touches a differentcontent/docs/deployment/page. Neither page has churned onmainsinceb1581b044.node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commandsre-derived at HEAD returns the same 29 commands for the two-path change set that the PM derived for the one-path change set. The second page added no family.H2 control grep
The zero was verified with a control before it was believed. Control:
master_detailacrosscontent/docs/**+skills/**returns 40 files, includingskills/objectstack-data/SKILL.md— so the grep surface really covers both trees and a zero there means something.Sweeping every table row keyed on
`tree`across both trees returns six rows. Onlyvalidation-rules.mdx:542asserts the requirement. The twoskills/**rows are left alone and nothing governed is touched:content/docs/data-modeling/validation-rules.mdx:542Required Propsskills/objectstack-data/rules/field-types.md:91Key Configreferenceis the relevant knob, not a requirementskills/objectstack-data/rules/relationships.md:11RequiredOptional— agrees with the status quocontent/docs/data-modeling/field-type-decision-tree.mdx:176When to Usecontent/docs/ui/views.mdx:92skills/objectstack-ui/SKILL.md:48A "require / must have / mandatory / missing" sweep near
`tree`across both trees returns nothing relevant either.Gates
Re-derived on the actual changed paths at the final commit —
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands, which takes its own change set from the merge base (2263ca4d6, three-dot) and confirmed--repoagainst this checkout'sorigin. 29 commands, all run at5df44f134, exit code captured before any pipe:check-doc-frontmatter— "2 content root(s) verified … content/docs 404, content/blog 3";check-docs-single-h1— "404 page(s) under content/docs/ carry no body-level#heading";check-doc-anchors— "295 internal #fragment link(s) across 409 source file(s) all resolve to a real heading";check:docs— "229 generated files in sync with packages/spec";check:doc-security-posture— "27 ObjectSchema.create example(s) in 226 marked block(s) across 236 prose file(s) in 2 root(s) carry an os validate-clean security posture";check:skill-examples— "256 prose examples type-check across 3 surface(s)";check:doc-authoring— "393 files clean".node scripts/check-test-completeness.mjsexits 3 with "PREREQUISITE NOT MET — this gate grades a savedturbo run testlog, and no log was named", and its own text prescribes the reading: "running the family locally, record this gate as NOT MEASURED. ⛔ It is not a red, and there is nothing here to fix." CI tees the log and passes the path, so CI is unaffected.Four gates first came back prerequisite-blocked on unbuilt packages (
check:doc-formula-expressions,check:doc-security-posture,check:docs,check:skill-examples) rather than being reported as NOT MEASURED:@objectstack/lint,@objectstack/formula,@objectstack/specand@objectstack/client-reactwere built under the shared verify lock (scripts/pm/os-verify-lock.sh, VERDICTcommand-exit 0on both runs) and all four then measured green.Changeset
None, deliberately —
skip-changesetis on this PR. The rule is "publishes nothing from any released package", and this diff is twocontent/docs/**cells:apps/docs, the only workspace that consumescontent/docs, isprivate: true.content/docs: the solepackage.jsoninpackages/that mentions the path isplugin-webhooks, and the mention is prose inside itsdescription; itsfilesis["dist","README.md","CHANGELOG.md"].content/docs-only commits onmain(89a156af8,db7f3e492,365a740a8,a69dfde80,4485f7dad,63fb473a9,167bcb2e1) each carry zero.changeset/files.The
Check Changesetjob's own exemption text names the label as "the author's explicit opt-out", meaning "this PR declares no release of its own" — which is what this is.Deliberately not in this PR
packages/lint(RELATIONSHIP_TYPES) — unchanged; it is one of the three surfaces this PR converges the docs onto.packages/spec/src/data/field.zod.ts— unchanged; two other cards are writing that file this round.treebeing judgedrelationand materialisingdeleteBehaviormakes sense — is not answered here. This docs fix holds whichever way that lands. Method precedent for the census: [spec]FieldSchemaaccepts alookup/master_detailwith noreferencetarget, though its own TSDoc calls the key required #13632 / PR fix(spec): require a non-empty reference on lookup/master_detail fields #13927.Self-referencingdescriptor in the samevalidation-rules.mdxrow is a different claim from the requirement one and is left as-is; it is reported to the PM as an out-of-scope finding, sincefield-zoo.object.ts:108makes "self-referencing" over-narrow rather than false, and the wording is spread over five surfaces including two governedskills/**files.🤖 Generated with Claude Code
https://claude.ai/code/session_017RbbUMnxkUnWhE4j94v8FE
Generated by Claude Code