Skip to content

objectstack-data skill teaches deleteBehavior:'set_null' on master_detail — wrong before #9689, a parse-time rejection after it #11409

Description

@os-steve

Filing unassigned — recording, not claiming. Found while implementing #9689 (parse-time rejection of deleteBehavior: 'set_null' authored on a master_detail; PR #11406).

The defect

The published objectstack-data skill teaches AI authors to write exactly the combination #9689 makes a named parse-time rejection:

  • skills/objectstack-data/rules/relationships.md:157-159 — the master-detail deleteBehavior table offers set_null ("Set child reference to null | Manager → Employees") as a legal choice. This was already wrong before FieldSchema accepts deleteBehavior: 'set_null' on a master_detail, and the engine silently resolves it to cascade #9689: the engine has always resolved every non-restrict value on a master_detail to cascade (measured and pinned in packages/objectql/src/engine-cascade-delete.test.ts), so the row promised keep-the-children and delivered delete-the-children. The "Manager → Employees" example is doubly wrong — that relationship (children must survive the parent) wants a lookup, never a master_detail.
  • skills/objectstack-data/rules/relationships.md:165deleteBehavior: 'cascade', // or 'restrict' or 'set_null' in the master-detail code sample.
  • skills/objectstack-data/rules/relationships.md:405 — best practice Add Changesets and GitHub Actions automation #4: "deleteBehavior on master_detail — Always specify cascade/restrict/set_null".
  • skills/objectstack-data/rules/field-types.md:72 — master_detail row: "deleteBehavior (cascade/restrict/set_null)".

After #9689 lands, an AI following this skill authors a field that fails publish with a 422 — the skill manufactures exactly the AI-authored metadata error the parse-time rejection exists to catch.

Fix shape (small, subtractive)

Remove set_null from the master-detail option set in all four spots; the table row's example belongs under lookup (where set_null is real and stays legal, #9625 escalation caveats included). Net negative or zero line delta — no expansion. The rejection message in FieldSchema is the source of truth for the wording ("a detail row cannot outlive its master; use a lookup if children must survive the parent").

Note: skills/** is a governed surface (Prime Directive #14): human-merge only, must be its own PR — which is why this is filed rather than folded into #9689's PR (a mixed diff would fork the whole PR into governance).

Refs: #9689 (the ruling and the rejection), #9625 (the engine pin), #9907 (precedent: a skill teaching pre-tightening behavior).


Generated by Claude Code

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions