Skip to content

A sales rep cannot save a new lead without picking themselves as owner: the Create Lead form marks owner_id required, which blocks the insert-time stamp that already makes the creator the owner #2097

Closed

Description

@objectstack-fleet

Filing gate ①: a user-visible defect, reproduced in a browser.
reach: the console Leads → New, as na.rep.
Filed by the repo:hotcrm seat (session_01BCDqr1DqnQjEh5jA9gGkUG) from the v18 test pass #2093 (finding 08), under the maintainer's 「测试遇到问题就报issue」. ⛔ Not a claim.
Reader: this seat's queue.
Dedupe: the hotcrm index on owner required / lead owner / owner prefill: 0. #2060's own dedupe line records Lead Owner is required → 0 hits.

What happens (main 2f3d898d, @objectstack/* 18.0.0-next.0)

As na.rep: open Leads → New, fill First / Last / Company / Email, and click Create.

  • Result: the inline error "Lead Owner is required" appears, nothing is POSTed, and the rep has to search for and pick themselves.
  • The Opportunity, Account and Contact New forms also leave Owner blank ("Select…"), but none of them requires it.

Screenshot: 08-create-lead-form-owner-required-not-prefilled.png (on #2093's branch).

Cause (seat-verified in source)

  • src/sales/views/lead.view.ts ~293–296 puts { field: 'owner_id', required: true } in the create form.
  • src/sales/objects/lead.hook.ts ~41–43 states that "UI-created leads already carry owner_id = creator (the middleware's insert-time stamp)". The form's required stops the save before that stamp can apply.

Fix direction (measure first)

  • Drop required: true from the create form's owner_id, so the insert-time stamp makes the creator the owner, as on the other three objects.
  • Re-measure that a rep's new lead saves owned by the rep, and that a manager can still pick another owner.
  • Check git log -S for why required was added. If a ruling put it there, stop and report.
  • That the console never prefills owner_id with the current user is the platform half: noted, not part of this card.

Generated by Claude Code

Activity

  1. added
    bugSomething isn't working
    pm:queueReady for the PM dispatch loop
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Oct 13, 2026
  2. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round R85
    Session: session_01P8mZuzuyZAHSrgQKmv6ASv
    Account: sunhaolin (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-2097-lead-owner-not-required
    Worktree: hotcrm-issue-2097
    Domain: repo:hotcrm (single-lane repo, no domain:* taxonomy)
    Seat: repo:hotcrm#1
    File surface: src/sales/views/lead.view.ts (the create form's owner_id entry only, ~L293–296, and its comment); content/docs/**/leads*.mdx only if a sentence says a new lead needs an owner picked; tests under test/; one .changeset/2097-*.md. A producer measured in the platform (the insert-time owner stamp not applying, or the console's form behaviour) goes upstream and this card WAITS (stop on breach; explain in the report)
    Container & model: S (one form entry; the judgment is the git log -S provenance check and the re-measure), mode:subagent, model: default (dispatch-gates --tier --repo objectstack-ai/hotcrm src/sales/views/lead.view.ts: "no path-derived mandate: the surface hits none of the 3 declared glob(s)"; the tier stays the PM's per-card call)
    Clause-②: no
    Responsibility: the app: lead.view.ts's create form sets owner_id required: true, which refuses the save before the insert-time stamp applies | the platform path that already covers it: the insert-time owner stamp that lead.hook.ts ~41–43 records | every rep who creates a lead in the console, today
    Thread-read: none
    Serial constraints cleared: src/sales/views/lead.view.ts is shared with #2094, claimed in this round. Fold-or-serial: not folded (gate ① fails: different defect shapes). Parallel by region: this card owns the create form's owner_id entry (~L293–296), #2094 owns the list columns block (~L141–200); the later lander merges main. Last change on the file: 81f8644 (#2050), not today. In flight in this lane: #2094 and #2095 (this round). Open PRs: dependabot #2063 and #2064 only.


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 2097,
    "status": "done",
    "branch": "claude/issue-2097-lead-owner-not-required",
    "pr": "#2099",
    "session": "session_01P8mZuzuyZAHSrgQKmv6ASv (this run is a subagent; the session id is the parent seat's, as the claim and the commit trailers carry it)",
    "premise_still_valid": true,
    "summary": "Removed required: true from the owner_id entry of the lead create form (LeadViews.form in src/sales/views/lead.view.ts). The field stays on the form as a bare owner_id with a comment saying why, which matches the Opportunity, Account and Contact New forms. Added one test in test/ownership-model.test.ts (form has owner_id, not required) and a patch changeset. H1 held: crm_lead.owner_id is Field.lookup sys_user with system: true and readonly: false, not required, and no validations[] or requiredWhen touches it; once the flag was gone the same rep save went through. H2 held, measured in a way that tells the two mechanisms apart: the sales_rep pool is [na.rep, eu.rep] with 1 and 0 open leads, so round-robin would have picked eu.rep, yet na.rep's second ownerless lead was saved owned by na.rep. sales.manager, who is not in the pool, also got their own lead. H4: no ruling. required came from the 344c5f5 framework/app-crm baseline on the old owner field, and 9f748ab (#548 via #677) renamed it to owner_id mechanically, so the stop line did not trigger. H3 FAILED, but for a platform reason that exists on base too: when the manager picks Nina Reyes, the chip shows the pick, yet the POST body has no owner_id and the lead is saved under the manager. This is identical on base 2f3d898 (owner required) and on this branch. The producer is objectui plugin-form: the create branch strips owner_id, and only an edit adds back a changed owner (objectui#12205). Reported in out_of_scope_findings, not worked around. I used Fixes #2097 because the card's own defect (a rep blocked from saving) is fully fixed in this repo. If the seat rules that the card waits on the upstream manager-pick finding, the PR body's first line should change to Part of #2097 (seat edit; dev writes the body once).",
    "tests": "All on HEAD ca836d0. pnpm validate: "✓ Validation passed (2773ms)", exit 0, lock VERDICT command-exit 0. pnpm typecheck: exit 0; tsc --listFiles includes test/ownership-model.test.ts and src/sales/views/lead.view.ts. pnpm lint: "18 suggestion(s)", exit 0, lock VERDICT command-exit 0. pnpm lint:i18n-gate: "✓ i18n lint gate: 0 i18n/missing-* issues", exit 0. pnpm hygiene: "✓ source hygiene clean", exit 0. pnpm hygiene:tokens: "✓ source token ratchet clean", exit 0. pnpm build: "✓ Build complete (2937ms)", exit 0, lock VERDICT command-exit 0. pnpm test: "Test Files 179 passed (179)", "Tests 3660 passed | 1 skipped (3661)", TEST_EXIT=0 captured right after pnpm test. The lock printed VERDICT batch-last-exit 0 because the wrapped command was pnpm test ...; echo TEST_EXIT=$?, so TEST_EXIT is the verdict. Targeted run: vitest run test/ownership-model.test.ts gave "Tests 16 passed (16)", lock VERDICT command-exit 0 after a 7m52s queue wait. Reverse check (one-time): objectstack scripts/ablation-replace.mjs replaced the bare owner_id entry with { field: 'owner_id', required: true }; the anchor hit x1, then x0, and the blob changed 049bedbe -> 251dc02d. Prediction stated before running: red. Observed: "Tests 1 failed | 15 passed (16)", "AssertionError: the New Lead form demands an owner again: expected true to be false", lock VERDICT command-exit 1. Restore: "ok restored: blob == HEAD (049bedbe81f3) and git diff HEAD is empty". The test imports src/ directly, so dist/ plays no part. Console measurements on port 4102 with Playwright DOM and network probes plus REST read-back, 18.0.0-next.0, demo:staff exit 0. BASE as na.rep: label "Lead Owner*", inline error "Lead Owner is required", 0 writes. HEAD as na.rep, lead 1: POST 201, no owner_id key in the body, read-back owner_id = na.rep (yH7k79Sc...). HEAD as na.rep, lead 2: owner = na.rep (round-robin would have chosen eu.rep). HEAD as sales.manager, no pick: owner = manager (fHtM0IOT...). HEAD as sales.manager picking Nina Reyes: chip "Remove Nina Reyes" shown, POST body without owner_id, owner = manager. BASE (rebuilt with the required form; artifact entry {"field":"owner_id","required":true}) as sales.manager picking Nina Reyes: same result. NOT MEASURED: Playwright e2e (CI's). CI at report time: Vercel Preview Comments and Label Pull Request success; Quality Checks, Build and Test (22.x), Check Changeset, Playwright, link-check and Analyze Code in_progress.",
    "mcp_calls": "0 — no MCP GitHub tool was called",
    "api_writes": "2 — (1) pr_create through the fleet relay: POST /repos/objectstack-ai/objectstack/dispatches (HTTP 204), relay run 38534739208 success, which created #2099 (draft, assignees [sunhaolin]); read-back 5484 bytes sent = 5484 stored. (2) this os-dev-report comment via scripts/pm/post-stamped.mjs --comment=2097. git push (4 pushes on the branch) is not REST and is not counted. Zero label writes.",
    "gates": {
    "head": "ca836d0d",
    "pnpm validate": "exit 0 · ✓ Validation passed",
    "pnpm typecheck": "exit 0",
    "pnpm lint": "exit 0 · 18 suggestion(s)",
    "pnpm lint:i18n-gate": "exit 0 · ✓ i18n lint gate: 0 i18n/missing-* issues",
    "pnpm hygiene": "exit 0 · ✓ source hygiene clean",
    "pnpm hygiene:tokens": "exit 0 · ✓ source token ratchet clean",
    "pnpm build": "exit 0 · ✓ Build complete",
    "pnpm test": "exit 0 · Test Files 179 passed (179) · Tests 3660 passed | 1 skipped (3661)",
    "playwright e2e": "NOT MEASURED (CI)"
    },
    "line_budget": "net diff origin/main...HEAD: 3 files, +26 -4. src/sales/views/lead.view.ts +5 -4 (all comment or form-entry lines; hygiene:tokens unchanged, since comments are stripped and the entry got shorter). test/ownership-model.test.ts +16. .changeset/2097-lead-owner-not-required.md +5. No skills/** touched.",
    "files_changed": [
    "src/sales/views/lead.view.ts",
    "test/ownership-model.test.ts",
    ".changeset/2097-lead-owner-not-required.md"
    ],
    "deviations": [
    "Commit 6b5c812 picked up objectstack.config.bundled_4tw0mek20uf.mjs (35749 lines, a temporary compile file from the running objectstack dev watcher) because I used git add -A. Commit b5237b6 removes it, and the net PR diff is 3 files. It was scanned before removal: no absolute paths and no secret-shaped strings. History was not rewritten (no force-push). Later commits stage explicit paths.",
    "Commit 6b5c812 carries the harness attribution pair, with a Co-Authored-By line that names the model. It was written following the harness reminder instead of the model-free pair, and was not rewritten. Commits b5237b6 and ca836d0 use the model-free pair (Claude-Session + Co-authored-by: Claude).",
    "The console was booted with pnpm exec objectstack dev -p 4102 (its watcher compiles and rebuilds on change) without a separate pnpm build first. The before and after states were measured on the same server across a watcher rebuild, and the artifact entry was read from dist/objectstack.json each time. The dev server process group (pgid 3636, started by me) was stopped with kill -TERM -3636, and port 4102 was confirmed free.",
    "Ran git fetch --unshallow origin main in the shared /home/user/hotcrm .git so H4 could read git log -S and blame. The shared repo is now a full clone; this only adds history."
    ],
    "open_questions": [],
    "out_of_scope_findings": [
    "class: a · reach: console Leads → New as sales.manager@objectos.ai (sales_manager holds allowTransfer + modifyAllRecords on crm_lead). In Lead Owner, pick "Nina Reyes": the chip "Remove Nina Reyes" renders and no error is shown. Click Create: POST /api/v1/data/crm_lead returns 201 and its body carries no owner_id key, and the saved row's owner_id is the manager, not Nina Reyes. The picked owner is silently discarded. Identical on hotcrm base 2f3d898 (owner_id required) and on PR #2099, with @objectstack/console 18.0.0-next.0. · producer (read in objectui main b9814b3): packages/plugin-form/src/ModalForm.tsx create branch → omitServerResolvedDefaults(sanitizeFormData(...)). sanitize.ts lists owner_id in SERVER_OWNED_FIELD_NAMES and admits it back only through dirtyEditPayload (edit only, objectui#12205); DrawerForm.tsx and writePayload.ts have the same shape. By code reading, every New form that shows owner_id (Account, Opportunity, Contact, Lead) drops the pick; only Lead was measured. · Seam: spec:Field.system owner_id (system: true, readonly: false, documented as reassignable) → renderer:plugin-form ModalForm create payload · Blocks nothing this card owns: the card's own defect is fixed, and this was the card's "manager can still pick another owner" check, which never worked on create. Seat decides whether the card waits (Blocked-by) or closes. · dedupe words: create form owner dropped; owner_id stripped on create; sanitizeFormData owner create; pick owner new record ignored; REASSIGNABLE_OWNER_FIELD create",
    "carrier: none (承接者:无) · noted in PR #2099 Acceptance notes, not filed: lead.view.ts formViews.advanced_conditional (a showcase form, not the create dialog) still marks owner_id required: true when status is contacted or qualified. Outside this card's file surface; I did not measure whether any console entry point opens that form."
    ]
    }

  4. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    Review of PR #2099 (head ca836d0d) against the os-dev report on this card (R85, seat repo:hotcrm, session_01P8mZuzuyZAHSrgQKmv6ASv): REWORK, round 1 (sent to the same dev, same claim).

    • Holds, checked on the PR: draft, base main, Fixes #2097 and Clause-②: no at the top. The net diff is 3 files (+26 −4): the create form's owner_id entry, the pin in test/ownership-model.test.ts (whose reverse check went red as predicted and was restored by blob hash), and a hotcrm: patch changeset. Fixes stands: the card's defect (a rep cannot save without picking themselves) is fixed here.
    • 1. A false claim in the new code comment: it says a manager "can still choose another owner", but the dev measured that the console drops a picked owner on create, identical on base. Filed upstream: plugin-form: a New form offers Owner, shows the picked user, and then drops the pick — the create payload strips owner_id, so the record is saved under the creator objectui#12359 (the create payload strips owner_id; edit-only admission since objectui#12205). The comment is to say only what holds today.
    • 2. Combined tree: main moved to e094ec71 (PR fix(views): zh-CN Leads and Opportunities column headers follow the field labels #2098, same file, columns block). The branch is to merge main and re-read the ratchet, build, test and validate on the merged head, because the merge queue re-runs no build on the combined tree.
    • Deviations noted: commit 6b5c8121 added a 35,749-line dev-server temp file and b5237b67 removed it (the net diff is clean; the squash carries only the net). Its model-named Co-Authored-By: trailer is not rewritten (os-dev rule). The git fetch --unshallow in the shared hotcrm clone added history only.
    • Noted, not filed: formViews.advanced_conditional still requires owner_id for contacted / qualified (PR Acceptance notes).

    Generated by Claude Code

  5. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 2097,
    "status": "done",
    "round": "REWORK round 1",
    "branch": "claude/issue-2097-lead-owner-not-required",
    "pr": "#2099",
    "head": "c1977c96",
    "session": "session_01P8mZuzuyZAHSrgQKmv6ASv (this run is a subagent; the session id is the parent seat's)",
    "premise_still_valid": true,
    "summary": "Rework round 1, both items done. (1) 43a0b4c rewords the owner_id comment in the src/sales/views/lead.view.ts create form so that every claim in it is true today: a rep's new lead is theirs without a pick, required blocked that save client-side, and a pick of another owner on create is currently dropped by the console (objectui#12359). The sentence "a manager can still choose another owner" is gone. Nothing else in the file changed (3 insertions, 2 deletions, all comment lines). I re-read the test comment in test/ownership-model.test.ts and the changeset: neither says a manager can pick another owner. The changeset only says "Lead Owner stays on the form", which is true. (2) c1977c9 merges origin/main e094ec7 (#2098 / #2094, the columns block of the same lead.view.ts) with a merge commit, no rebase and no force-push. The merge was clean, and the net diff against origin/main is still 3 files. All four requested gates are green on c1977c9, the combined tree. The PR body was not edited. Its Fixes #2097 line and the round-0 notes stand as written.",
    "tests": "All on HEAD c1977c9 (the merge of origin/main e094ec7). pnpm hygiene:tokens: "✓ source token ratchet clean", exit 0. pnpm validate: "✓ Validation passed (3064ms)", exit 0, lock "VERDICT command-exit 0". pnpm build: "✓ Build complete (2898ms)", exit 0, lock "VERDICT command-exit 0". pnpm test: "Test Files 179 passed (179)", "Tests 3660 passed | 1 skipped (3661)", lock "VERDICT command-exit 0", held the lock 8m34s (single command, no ; batch this time). Round 0 evidence (console measurements, the reverse check on the pin) still applies: this round changed only comment lines in lead.view.ts, plus the merged #2098 columns block. Not re-run this round, because they were not requested and the final diff did not touch their scope: typecheck, lint, lint:i18n-gate, hygiene (all green at ca836d0). NOT MEASURED: Playwright e2e (CI's).",
    "mcp_calls": "0 — no MCP GitHub tool was called",
    "api_writes": "1 — this os-dev-report comment via scripts/pm/post-stamped.mjs --comment=2097 (fleet relay). git push (1 this round, carrying 43a0b4c + c1977c9) is not REST. PR body not edited; zero label writes.",
    "gates": {
    "head": "c1977c96",
    "pnpm hygiene:tokens": "exit 0 · ✓ source token ratchet clean",
    "pnpm validate": "exit 0 · ✓ Validation passed",
    "pnpm build": "exit 0 · ✓ Build complete",
    "pnpm test": "exit 0 · Test Files 179 passed (179) · Tests 3660 passed | 1 skipped (3661)",
    "pnpm typecheck": "not re-run this round (exit 0 at ca836d0)",
    "pnpm lint": "not re-run this round (exit 0 at ca836d0)",
    "pnpm lint:i18n-gate": "not re-run this round (exit 0 at ca836d0)",
    "pnpm hygiene": "not re-run this round (exit 0 at ca836d0)",
    "playwright e2e": "NOT MEASURED (CI)"
    },
    "line_budget": "net diff origin/main...HEAD (c1977c9): 3 files, +27 -4. src/sales/views/lead.view.ts +6 -4 (the form entry and its comment only). test/ownership-model.test.ts +16. .changeset/2097-lead-owner-not-required.md +5. No skills/** touched.",
    "files_changed": [
    "src/sales/views/lead.view.ts",
    "test/ownership-model.test.ts",
    ".changeset/2097-lead-owner-not-required.md"
    ],
    "deviations": [
    "Carried from round 0, unchanged: commit 6b5c812 accidentally added the dev-server compile file objectstack.config.bundled_4tw0mek20uf.mjs, and b5237b6 removes it, so the net diff does not include it. 6b5c812 also carries a harness Co-Authored-By trailer that names the model. Neither was rewritten.",
    "Round 1: none. 43a0b4c and the merge commit c1977c9 use only the model-free trailer pair. I used a merge commit, not a rebase, and did not force-push. The worktree was recreated from the existing branch at ca836d0 and removed after the gates passed."
    ],
    "open_questions": [],
    "out_of_scope_findings": [
    "No new findings this round. The round-0 manager-pick finding has been filed upstream by the seat as objectstack-ai/objectui#12359, and the lead.view.ts comment now names it."
    ]
    }

  6. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    Review of PR #2099 round 1 (head c1977c96) against the os-dev report 6164367780 (R85, seat repo:hotcrm, session_01P8mZuzuyZAHSrgQKmv6ASv): ACCEPT.

    • Both REWORK items (6164200283) are closed, as read on the PR:
    • Net diff against main: 3 files, +27 −4: the form entry and its comment, the pin in test/ownership-model.test.ts, and the hotcrm: patch changeset. Body still Fixes #2097 / Clause-②: no, with no other closing keyword. Not a governed path.
    • Combined-tree reading: hygiene:tokens, validate, build and test (179 files, 3,660 passed) are green on c1977c96 itself, the merge of main. typecheck / lint / lint:i18n-gate / hygiene were green at ca836d0d and this round changed comment lines only. CI on c1977c96: every check green except Build and Test (22.x), still running at this review; landing waits for it.
    • Fixes, not Part of: the card's defect (a rep cannot save a lead without picking an owner) is fixed here. The manager-pick drop is the platform's, pre-existing, and tracked upstream in objectui#12359.

    Generated by Claude Code

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

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingpriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions