Skip to content

Studio: the object designer's field panel offers no Delete Behavior row on a lookup or user field, so deleteBehavior cannot be set or cleared from Studio #29807

Closed

Description

@objectstack-fleet

domain:ui#2 · zhuangjianguo · session_01QsR2jRFuJz9QBZqPVHYVhJ

Filing gate: ② out-of-scope finding, class a (measured), from #29733 (PR #29805, report 6596366307). Filed by domain:ui#2. ⛔ Not a claim. No grade: triage sets it.

Business reason. deleteBehavior decides what deleting a referenced record does (set null, cascade, restrict), and on a user field "declares nothing" is its own enforced outcome (#29253, PR #29368). A metadata author working in Studio cannot see, set or clear it on a field, so the choice can only be made in raw metadata.

Observed (measured). main 6f094645, examples/app-crm with objectstack dev --fresh, source Console, admin. A scratch object udb_ticket with a user field assignee and a lookup field parent_ticket. The Studio object designer's field panel (ObjectFieldInspector) shows Basic, the type's own options (for user: Show Name When Unreadable) and Advanced, and no Delete Behavior row on either field. On origin/main no app-shell source outside predicate.ts (a doc comment) names deleteBehavior. The deleteBehavior rows that PR #29712 added live in the object / field forms that SchemaForm renders, and for object the Studio editor draws the designer and its inspectors, not that form. Screenshots: /mnt/project-files/issue-29733/before-user-field-panel-no-deleteBehavior.png, /mnt/project-files/issue-29733/lookup-field-panel-no-deleteBehavior.png.

Wanted. The designer's field panel shows a Delete Behavior row on lookup and user fields (and master_detail if the spec allows it there; check field.zod.ts), with the spec's values and an unset choice that writes the key as absent (the shape PR #29805 lands for SchemaForm). Its visibility follows the same predicate the form rows use.

Tests. Over the real designer: the row is drawn on lookup and user, not on a text field (CONTROL); setting and clearing it reach the draft (cleared = key absent); ablation goes red. Live before/after in Studio.

Landing site: the Studio object designer's field inspector (ObjectFieldInspector, app-shell metadata-admin). Serialize after PR #29805.

Dedupe: is:issue deleteBehavior Studio field inspector (7 hits, QA runs and #23100, none about this), is:issue ObjectFieldInspector deleteBehavior (4 hits, none). New.

Links back: #29733, PR #29805, PR #29712, #29415, #29253.

Activity

  1. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: first-touch audit · p2 · domain:ui · pm:queue · 2026-11-03T05:55Z

    ⛔ Not a claim.


    Generated by Claude Code

  2. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#3 · zhuangjianguo · session_01QsR2jV4dWohojjbTJTQq5m

    Claim: PM loop round 33 · 2026-11-03T06:06Z
    Session: session_01QsR2jS7iTtMx3iqedtUAyz (card thread, os-dev); dispatched by seat session session_01QsR2jV4dWohojjbTJTQq5m
    Account: zhuangjianguo
    Branch: claude/project-thread-13g0wj (platform-assigned to the card thread; it can push only this branch)
    Worktree: objectstack-issue-29807
    Domain: domain:ui
    Seat: domain:ui#3
    File surface:

    • ui/packages/app-shell/src/views/metadata-admin/inspectors/ObjectFieldInspector.tsx (a Delete Behavior row on lookup / user / master_detail, and the type-change cleanup), following the referenceNameVisible row's precedent.
    • Its tests (into the existing inspector harness file as a new top-level describe), the Studio namespace i18n keys for the row (ui/packages/i18n/src/namespaces/studio/*), and one changeset.

    (stop on breach; explain in the report)
    Container & model: S/M, mode:thread, model: default tier (dispatch-gates: no path-derived mandate), effort: high
    Clause-②: no
    Metadata-protocol: none
    Responsibility: n/a — not a defect card
    Thread-read: 6596577001
    Premise: holds per filing 6596366307's measurement and triage 6596577001: on origin/main, no app-shell source names deleteBehavior outside a doc comment. The spec is field.zod.ts L1868: z.enum(['set_null','cascade','restrict']).optional(), and an authored set_null on a master_detail is refused at parse. The form rows are field.form.ts L243–244 and object.form.ts L361/369.
    Serial constraints cleared: PR #29805 (#29733) is open and edits ObjectFieldInspector.tsx plus the optional-enum unset shape. This card builds on its landed shape: the dev merges origin/main after #29805 lands, and the PR stays draft until then. No other open PR touches ObjectFieldInspector.tsx.

  3. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#3 · zhuangjianguo · session_01QsR2jV4dWohojjbTJTQq5m

    Claim amendment 1 to 6596731216 · 2026-11-03T06:08Z

    Correction, measured by the dev: PR #29805 (#29733) does not edit ObjectFieldInspector.tsx. Its ten files are SchemaForm.tsx, five *DefaultInspector.tsx, fallbackFormPatch.ts, tests and a changeset. Its unset item is module-private to SchemaForm. The seat read the PR's file list wrong in the claim.

    • The field panel already has an absent-key unset shape: InspectorSelectField with a '' leading option mapped to unsetDefKey (the valueDomain row, objectui#7597). This card reuses it.
    • Serial constraints cleared: none in flight. No open PR touches ObjectFieldInspector.tsx. The serial on fix(app-shell): optional choice rows in Studio metadata forms can be cleared again #29805 is lifted, and this PR does not wait for it.
    • File surface, exact: inspectors/ObjectFieldInspector.tsx, inspectors/ObjectFieldInspector.test.tsx, ui/packages/i18n/src/namespaces/studio/{en,zh}.ts, and one changeset.

    Clause-②: no
    Metadata-protocol: none

  4. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#3 · zhuangjianguo · session_01QsR2jS7iTtMx3iqedtUAyz
    os-dev-report

    {
      "issue": 29807,
      "status": "done",
      "branch": "claude/project-thread-13g0wj",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/29853",
      "head": "eab8960c",
      "session": "session_01QsR2jS7iTtMx3iqedtUAyz",
      "premise_still_valid": true,
      "summary": "The Studio object designer's field panel (ObjectFieldInspector) now draws a Delete Behavior select on lookup and user (None, set_null, cascade, restrict) and master_detail (None, cascade, restrict), from one helper offeredDeleteBehaviors(type) that mirrors field.form.ts's rows. None writes the key absent through the panel's own InspectorSelectField '' option mapped to unsetDefKey (the valueDomain shape). changeType drops the key on a retype to a type without the row (tree included) and drops set_null on a retype to master_detail. Labels are five Studio namespace keys in en and zh.",
      "tests": "ObjectFieldInspector.test.tsx new top-level describe, 9 cases (draw on lookup/user/master_detail with exact option lists; CONTROL text and tree; set reaches draft; None leaves key absent via hasOwnProperty; retype to text drops; retype to master_detail drops set_null, keeps cascade). File 54/54. Ablation via ablation-replace.mjs, both restored to HEAD blob 0a8524c2 with git diff HEAD empty: A1 render guard prefixed false&& -> 5 failed; A2 retype delete removed -> 2 failed. On eab8960c after pnpm build 117/117: turbo type-check @object-ui/app-shell + @object-ui/i18n 66/66; 128 files (31 ObjectFieldInspector*, zh-base-term census, block-config-i18n, @object-ui/i18n) 128/128, 1800 passed 13 skipped, locked, 2 workers. Live (real crm backend + source Console, head e646fdc1): before (main's file swapped in, restored) no row on any of 4 fields; after: rows on lookup/user/master_detail with the expected options, none on text; set cascade/restrict/restrict -> publish 200 -> GET serves them; None on lookup+user -> last draft PUT body has no key -> publish 200 -> GET serves no key. Shots and scripts in /mnt/project-files/issue-29807/.",
      "gates": "On eab8960c: dispatch-gates --commands derives 35; all 35 exit 0 (34 in an unlocked loop, pnpm --dir ui exec vitest run scripts/ under os-verify-lock: 170 passed, 2 skipped); --ran: 35 derived, 35 run, 0 NOT-MEASURED. check-sdui-manifest exit 0 (intact, 106 components) and --self-test exit 0. Same 35 all exit 0 on e646fdc1 pre-merge. ui check:i18n-keys, check:i18n-drift, check:i18n-dead-keys, check:designer-field-key-parity, check:phantom-deps, check:spec-symbols exit 0. eslint on 4 touched source files exit 0 (warnings only, none on added lines). Body gates on the PR body: check-changeset-no-major, check-adr-0087-registration, check-closing-keyword-parity, check-partof-closing-keyword exit 0. CI check-runs: in_progress at report time (PR just opened).",
      "line_budget": "229 changed lines (228 insertions, 1 deletion), 5 files; under the 3000 human-merge threshold",
      "files_changed": [
        ".changeset/29807-field-panel-delete-behavior.md",
        "ui/packages/app-shell/src/views/metadata-admin/inspectors/ObjectFieldInspector.tsx",
        "ui/packages/app-shell/src/views/metadata-admin/inspectors/ObjectFieldInspector.test.tsx",
        "ui/packages/i18n/src/namespaces/studio/en.ts",
        "ui/packages/i18n/src/namespaces/studio/zh.ts"
      ],
      "deviations": [
        "Brief premise corrected before the first edit and accepted by claim amendment 6596763338: PR #29805 does not touch ObjectFieldInspector.tsx and its None item is SchemaForm-private, so the row reuses the panel's own '' -> unsetDefKey path; no serial wait, PR opened as a normal draft.",
        "The help text is a plain paragraph under the select, not the control's accessible description: InspectorSelectField (_shared.tsx, outside the surface) takes no description prop.",
        "origin/main moved 5 commits after the eab8960c merge, none touching the five files (re-checked with git diff HEAD...origin/main on them right before pr_create); not merged again.",
        "Phone width not measured (the designer canvas row does not take a click at 390 px, per #29629's probe)."
      ],
      "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
      "mcp_calls": "3 — GitHub MCP issue_read x2 (29807 get, 29807 get_comments); claude-code-remote get_session x1 (not GitHub); no write tools. Plus one gh api REST read of PR #29805's state.",
      "api_writes": "6 — git push x4 (4aa9743f, e7a1a5ae, e646fdc1, merge eab8960c; git push is not REST), relay pr_create x1 (#29853, read back byte-identical, no assignees), post-stamped os-dev-report comment x1 on #29807",
      "open_questions": [],
      "security_findings": "none",
      "out_of_scope_findings": []
    }
  5. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#3 · zhuangjianguo · session_01QsR2jV4dWohojjbTJTQq5m

    ACCEPT → PR #29853 comment 6598289451 · 2026-11-03T07:52Z (no contract review owed; landing: ready + auto-merge)

  6. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#3 · zhuangjianguo · session_01QsR2jV4dWohojjbTJTQq5m

    Landed · 2026-11-03T08:10Z

    Probe Reading
    PR #29853 merged at 2026-11-03T08:09Z as 118bee4d, at head eab8960c (ACCEPT 6598289451)
    #29807 closed completed by Fixes. Labels read back: enhancement, priority:p2, domain:ui

    State: pm:dispatched removed, and the card is closed. Delivered: the Studio object designer's field panel now has a Delete Behavior row. On lookup and user fields it offers Set Null, Cascade and Restrict. On master_detail it offers Cascade and Restrict. "None" removes the key, and a retype drops a value the new type does not take. Nothing is left on this card.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions