fix(examples): require the master on showcase field-zoo's f_master_detail - #14449
Merged
os-zhuang merged 3 commits intoSep 2, 2026
Merged
Conversation
…tail `showcase_field_zoo.f_master_detail` was the only `master_detail` declaration across the loadable authored corpora that did not set `required: true` — a detail record cannot exist without its master, and `objectstack validate` was warning about exactly this one field (`relationship/master-detail-required`). Both seeded zoo specimens already supply the value, so no data changes and nothing turns red; this is example hygiene, and it zeroes the migration list a future promotion of that rule from `warning` to `error` would produce. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
This was referenced Sep 2, 2026
…eld-zoo-master-detail-required
`showcase_field_zoo.f_master_detail` is now required, and this suite creates its zoo rows through the real REST write path supplying only `name` plus a temporal field. Every insert answered 400 "Master-Detail → Project is required", failing at `write f_time hm: expected 400 to be 201`. The suite now seeds its own master chain in `beforeAll` — `showcase_account`, then `showcase_project`, which declares a required lookup to the account, so the order is forced — and passes that id to each of the four zoo inserts. The epoch-rejection case gets it too, so the 400 it asserts is still about `f_time` rather than about a missing master. Created rather than read out of the showcase seed on purpose: this file's assertions rely on it owning every row it reads. Also corrects the comment that claimed the object "requires only `name`". Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
Contributor
📓 Docs Drift CheckNothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs. What this run could not see
Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
os-zhuang
marked this pull request as ready for review
September 2, 2026 08:25
os-zhuang
enabled auto-merge
September 2, 2026 08:25
os-zhuang
deleted the
claude/issue-13723-field-zoo-master-detail-required
branch
September 2, 2026 08:53
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 #13723
One line:
showcase_field_zoo.f_master_detailnow declaresrequired: true, matching how every othermaster_detailin the authored corpora spells it.Premise re-check on
origin/mainVerified at merge base
6aea1f559.examples/app-showcase/src/data/objects/field-zoo.object.ts:107read exactly as the card described, with norequired: true:Premise holds.
Census re-measurement
The card's claim — that this is the only
master_detailin any authored corpus withoutrequired: true— was re-measured rather than taken on trust. EveryField.masterDetail()declaration in the loadable authored corpora, flagged when its options object carries norequired: true:Output on the pre-fix tree — 7 declarations, exactly 1 missing:
A second sweep for the non-builder spelling (a bare
type: 'master_detail'field literal) across the same corpora returns nothing, so the builder scan above is the complete population. The census card #13699 is confirmed: this was the last one.Seed rows already comply
Both seeded zoo specimens supply the value, so this changes no data and turns nothing red —
examples/app-showcase/src/data/seed/index.ts, the two records of thefieldZooseed:Specimen — Full:f_master_detail: 'Website Relaunch'Specimen — Minimal:f_master_detail: 'Data Platform'Those are the only two records in that seed, so the object has no row that would newly fail the required check.
What actually moves
Ablation, on committed state: the fix restored from
HEAD~1into the worktree (mutation confirmed on disk by blob hash plus occurrence counts of both the injected and the removed text), the instrument re-run, then restored withgit checkout HEAD --and re-proved clean (git diff HEADempty, working-tree hash equal to theHEADblob).objectstack linttotalsrelationship/master-detail-requiredmaster_detail "showcase_field_zoo.f_master_detail" → showcase_project should be requiredatobjects[9].fields.f_master_detail.requiredDelta is exactly minus one, exactly that rule, exactly that field. Nothing else in the report moves.
One correction to the record, since it lands in the branch's commit message and is wrong there: that message names
objectstack validateas the command that was warning. It is not — the rule lives inpackages/lint/src/data-model-rules.tsand reaches the CLI throughobjectstack lint. Measured both ways:objectstack validateprints 33 warnings on the pre-fix and post-fix trees alike, byte-identical, so it never read this rule at all. The table above is the accurate reading.Consumer fix — the card's "turns nothing red" clause was wrong
CI caught a consumer the census did not look for. On head
e9c424e7,Dogfood Regression Gate (2/3)failed (run 33603420183, job 100162026771):Why the premise missed it: the card reasoned about the seed, and the seed really does comply — both zoo specimens set
f_master_detail. What neither the card nor my census re-measurement asked was who else writes zoo rows.temporal-storage-e2e.dogfood.test.tscreates its own fixtures through the real REST write path and supplied onlynameplus a temporal field, relying on a comment in that file which asserted the object "requires onlyname". Making the field required is exactly what refuses those inserts. A census over declarations cannot see a consumer that writes records; that is the gap, and it is worth naming rather than papering over.The fix is local to the call sites and does not weaken the field. The suite now seeds its own master chain in
beforeAll—showcase_account, thenshowcase_project(which itself declares a required lookup to the account, so the order is forced) — and passes that id to each of the four zoo inserts, including the epoch-rejection case, so the 400 that test asserts is still aboutf_timeand not about a missing master. Created rather than read out of the seed, deliberately: this file's assertions depend on it owning every row it reads.Files touched:
packages/qa/dogfood/test/temporal-storage-e2e.dogfood.test.ts— master chain seeded inbeforeAll;f_master_detailadded to the four inserts; the stale "requires onlyname" comment corrected.No other writer needed changing.
field-zoo-roundtrip.dogfood.test.tsalready resolvesf_master_detailthroughREFERENCE_TARGETS, which is why it stayed green;action-params-contract.dogfood.test.tsonly invokes actions. A sweep of every remainingshowcase_field_zooreference in the tree finds name-list assertions, comments, and one read-only page visit.No test was skipped, quarantined, or relaxed, and
showcase_field_zoo.f_master_detailremainsrequired: true.Verification
Re-run in full after the consumer fix, at head
b0e788ee3(which includes a merge oforigin/main). Every heavy command throughscripts/pm/os-verify-lock.sh, exit codes captured before any pipe, verdicts read from the lock's own VERDICT line.Reproduce-then-prove on the dogfood failure, run from committed state with a restore trap:
vitest run test/temporal-storage-e2e.dogfood.test.tsAssertionError: write f_time hm: expected 400 to be 201, engine logInsert operation failed {"object":"showcase_field_zoo","error":{"message":"Master-Detail → Project is required"}}; 1 file failed, 8 tests skippedThe mutation was confirmed on disk before the pre-fix run (blob
b0790b8eaagainst theHEADblob922bc1339, with occurrence counts of both the added and the removed text checked), and the restore afterwards was proved rather than assumed (git checkout HEAD --, thengit diff HEADempty,git status --porcelainempty, working-tree hash equal to theHEADblob).Then, on the fixed tree:
pnpm --filter @objectstack/dogfood exec vitest run --maxWorkers=2: exit 0, 129 files passed | 1 skipped (130), 1003 tests passed | 3 skipped (1006). This is the check that no other consumer was missed; nothing outside the one file needed touching.pnpm --filter @objectstack/dogfood typecheck— exit 0pnpm --filter @objectstack/example-showcase typecheck— exit 0vitest run --maxWorkers=2— exit 0, 26 files, 364 testspnpm --filter @objectstack/example-showcase validate— exit 0pnpm lint(eslint . --no-inline-config, whole repo, not narrowed) — exit 0Derived union re-run on the final head —
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, no paths, deriving its own change set: it now sees 2 paths and emits 32 commands, up from 17 before the dogfood file joined. 30 exit 0, pluspnpm check:nul-bytesexit 0.Two are NOT MEASURED locally rather than green, by their own exit code 3 and their own printed verdict — unchanged from the first round:
check-test-completeness— grades a savedturbo run testlog the derived family cannot hand it; it prints "the local reading for this gate is NOT MEASURED ... it is not a red".check:dual-build-cjs-loads— reads built output, and eight packages outside this card's dependency closure have nodist/: "PREREQUISITE NOT MET ... this is NOT a pass: nothing was measured."Changeset
None, deliberately.
examples/app-showcaseis"private": trueand publishes nothing, so this PR declares no release of its own and carriesskip-changeset— the same route taken by the most recent examples-only change to land (#14090 — an examples-only diff carryingskip-changesetand no changeset).🤖 Generated with Claude Code
https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
Generated by Claude Code
Generated by Claude Code