Skip to content

v18 regression pass: walk HotCRM's main journeys on main 2f3d898d (18.0.0-next.0) against df5cbb99 (17.7.0), plus one in-place 17.7.0 → 18 upgrade of a database, and report every defect the upgrade caused #2093

Closed

Description

@objectstack-fleet

Filing gate ③: a task the maintainer set. The maintainer, verbatim, in the repo:hotcrm seat's session chat (session_01BCDqr1DqnQjEh5jA9gGkUG), right after the upgrade landed: 「暂时只处理 v18升级之后导致的bug」. No upgrade-caused bug was on the board when that was said: a closed-and-open read of every hotcrm issue created after the merge (2026-10-13T12:40Z) found 0. The bugs have to be found before they can be handled, so this card finds them.
Filed by the repo:hotcrm seat. Reader: this seat claims and dispatches it in the same act.
Dedupe: the seat's full hotcrm issue index (796 issues, all states) matched on regression / browser pass / v18 / 18.0 / upgrade. Nearest: #2058 (closed), the full browser pass of 4.0.1 over the feature inventory, whose journey list this card reuses; #2060 / #2073 (open), that pass's defect lists. None compares 17.7.0 with 18.

What "caused by the upgrade" means here

A defect counts when it works on df5cbb99 (the last main on @objectstack/* 17.7.0, with #2087 / #2089 / #2090 in) and fails on 2f3d898d (the same app on 18.0.0-next.0, PR #2091). Both are measured the same way, on fresh databases. Broken on both = pre-existing; it is noted, not chased, under the maintainer's focus.

Legs

  1. Fresh-database A/B, both commits. Walk the business journeys of QA: full browser pass of HotCRM 4.0.1 (main 1d7148bf) over all 161 feature-inventory rows — three cloud testers, screenshots, defects filed as cards (maintainer task 2026-10-10) #2058's feature-inventory rows that matter most:
  2. In-place upgrade: boot df5cbb99 on a database file, seed, pnpm demo:staff, make a handful of writes, stop. Then boot 2f3d898d on the same file. This is the path a hosted install takes. Record:

Deliverable

A findings list, no code: each finding with its repro, the base vs head evidence, and a classification (caused by the upgrade / pre-existing / not reproduced). For each upgrade-caused defect it names the producer: this app, or an @objectstack/* package. The seat files each upgrade-caused defect as its own card, in hotcrm or upstream (an upstream one gets a hotcrm pm:blocked + Blocked-by: card per AGENTS.md §2), and the fixes are dispatched from there.


Generated by Claude Code

Activity

  1. added
    bugSomething isn't working
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    priority:p1High: required for production / M2
    on Oct 13, 2026
  2. objectstack-fleet commented on Oct 13, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round R83
    Session: session_01BCDqr1DqnQjEh5jA9gGkUG
    Account: os-justin (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-2093-v18-regression-pass
    Worktree: hotcrm-issue-2093 (head 2f3d898d) and hotcrm-issue-2093-base (detached at df5cbb99)
    Domain: repo:hotcrm (single-lane repo, no domain:* taxonomy)
    Seat: repo:hotcrm#1
    File surface: none in the repo. This card measures and reports: no commit beyond the empty branch marker, and no PR. Scratch work stays in the scratchpad (stop on breach; explain in the report)
    Container & model: L (two commits × fresh databases, plus an in-place upgrade, in a browser), mode:subagent by the seat's judgment (the relay tools, the verify lock and Chromium are in this container; deviation from the L→mode:cloud default recorded), model: default (no repo paths, so no tier glob applies; the tier is the PM's per-card call)
    Clause-②: no
    Responsibility: n/a — a measurement card; each defect it finds gets its own card and its own answers
    Thread-read: none
    Serial constraints cleared: nothing in flight in this lane (0 pm:dispatched before this card). The card writes no tracked file, so no hot-file queue applies.


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 13, 2026

    @objectstack-fleet
    ContributorAuthor

    Scope change, the maintainer's words, verbatim, in the repo:hotcrm seat's session chat (session_01BCDqr1DqnQjEh5jA9gGkUG): 「测试不用对比 v17,测试遇到问题就报issue」

    Recorded by the repo:hotcrm seat, 2026-10-13T13:20Z. The in-flight dev on this card is told in the same act.

    What changes (the seat's reading, stated to the maintainer in the same chat):


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 13, 2026

    @objectstack-fleet
    ContributorAuthor

    Added by the maintainer, verbatim, in the same chat: 「测试遇到问题应该截图给我」. Recorded by the repo:hotcrm seat, 2026-10-13T13:22Z; the dev was told in the same act.


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 13, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 2093,
      "status": "done",
      "branch": "claude/issue-2093-v18-regression-pass",
      "pr": null,
      "session": "session_01BCDqr1DqnQjEh5jA9gGkUG (subagent of the repo:hotcrm seat; parent's session)",
      "premise_still_valid": true,
      "summary": "Measurement card, no code. Scope changed mid-run by the maintainer (recorded on the card at 13:20Z / 13:22Z): no v17 comparison, test v18 only, every problem counts, every finding screenshotted. Ran HotCRM main 2f3d898d (18.0.0-next.0, still the main tip at the end) on a fresh sqlite DB (`pnpm demo:reset`, `objectstack dev -p 4012 --no-watch --ui`, OS_AUTOMATION_SCHEDULED_WORK_ENABLED=true, `pnpm demo:staff` exit 0). Drove the journeys in Chromium as admin, sales_rep (na.rep / eu.rep), sales_manager, service_agent and service_manager, plus REST read-backs. Result: 13 findings, 1 of them already an open card (#2016). The core daily journeys pass: Convert Lead as manager, large-deal approval and rejection reaching the manager, account approval, quote with lines to accepted to contract draft to activated (billing hand-off), the case lifecycle (create, escalate, claim, close), the hourly SLA sweep, both anonymous forms, campaign enrollment, all 5 dashboards and 10 reports. Before the scope change, the base leg (df5cbb99) had been booted, seeded and staffed. The admin dashboard DOM probe matched head on all 5 dashboards. Both legs were then dropped and the base worktree removed. The screenshots (14 PNGs; finding 11 has two) are committed and pushed on the branch under qa/2026-10-13-v18-pass/ (head 83746c7a). That is screenshots only, per the maintainer's widening of the claim's file surface. No source change and no PR. Findings were sent to the seat in 5 batches during the run.",
      "files_changed": [
        "qa/2026-10-13-v18-pass/*.png (14 screenshots, no source; maintainer-widened surface)"
      ],
      "tests": "No code, so no test suite was run. Instruments: Playwright 1.63 + /opt/pw-browsers/chromium against :4012, REST read-backs as each persona, and server-log line counts. Dashboards: DOM probe (.recharts-* marks greater than 0) plus POST /api/v1/analytics/dataset/query statuses. admin: exec 13, sales 21, activity 13, service 14, crm_overview 17 marks, all 200. mgr: the same in en-US and zh-CN. na.rep: 4 of 5 draw, and service_dashboard shows 0 marks because the rep holds no case read. service_agent: 4x/4x/1x/4x 403 (finding 09). Reports: all 10 open as admin with rows (200). Scheduled: the hourly tick fired case_sla_monitor (selected 32, acted 16; all 16 overdue open cases flagged; newly escalated ones reassigned to service.manager) and task_due_reminder (completed). Deviations: the build ran under os-verify-lock (`pnpm demo:reset`, VERDICT command-exit 0, both legs). The dev servers and Playwright did not use the lock (not build/test). One background-moved command (a nav sweep that outgrew the 10-minute foreground cap) was killed by its own PIDs and re-run in the foreground, narrowed.",
      "mcp_calls": "0",
      "api_writes": "1 REST write: POST issues/2093/comments (this os-dev-report, via scripts/pm/post-stamped.mjs as objectstack-fleet[bot]). git push x6 on claude/issue-2093-v18-regression-pass (the empty claim marker, then 5 screenshot commits 54fbfcbc, c859284c, 0425ebf2, f99218e0, 83746c7a; not REST). Reads only otherwise: gh api GET for issues/2093, its comments (twice) and issues/2016. Local-server writes (records, approvals) went only to the throwaway :4011/:4012 dev databases.",
      "journeys": [
        "legs: fresh-DB A/B base df5cbb99 DROPPED by the scope change (it had been booted, seeded and staffed; the admin dashboard probe matched head on 5/5 before the drop); in-place 17.7 to 18 upgrade leg DROPPED by the scope change (not started); objectstack#23256 is therefore NOT MEASURED",
        "app shell and nav (admin, mgr, na.rep, service_agent): PASS; nav sweep 0 errors for mgr and rep; agent sees no-access dashboards (finding 09)",
        "Convert Lead as manager (UI screen flow, with opportunity): PASS; account, contact and opp created and linked; account approval opened",
        "Convert Lead as sales_rep: FAIL, existing #2016 (finding 05)",
        "Lead create via New form (rep): FAIL-UX, owner required and not prefilled (finding 08); REST create PASS",
        "Web-to-Lead /_console/f/contact-us (anonymous): submit PASS (201); routing flow FAILS (finding 01); zh-CN sections English (finding 13)",
        "Web-to-Case /_console/f/support (anonymous): PASS (201, ownerless into triage by design; agent Claim Case PASS); zh-CN sections English (finding 13)",
        "Opportunity through stages, rep (REST) to closed_won: PASS; won alert and closed-won billing hand-off completed. Stage-path click is display-only; the inline editor opens but saving it was not driven: NOT MEASURED",
        "Large-deal approval (180K, rep) reaching sales.manager inbox; approve in UI: PASS; reject path: PASS; rep notified both ways",
        "Account approval reaching approver (rep-created and conversion-created): PASS",
        "Quote: Generate Quote screen flow (rep) PASS; 2 lines with rollup (async, settles to 115000) PASS; Presented to Accepted via Edit form PASS; contract draft CTR-0005 auto-drafted PASS; opp closed_won PASS; contract Activated with billing hand-off PASS",
        "Case lifecycle (agent): New form PASS; Escalate Case PASS (reassigned to service.manager, task to account owner by design); Claim Case PASS; Close Case screen flow PASS (closed, resolution, closed_date)",
        "Scheduled flows (hourly tick, OS_AUTOMATION_SCHEDULED_WORK_ENABLED=true): case_sla_monitor PASS, task_due_reminder PASS; notifications stored without organization (finding 07); daily crons (forecast_snapshot, opportunity_stagnation, quote/contract expiration, contract_renewal, campaign_completion) NOT MEASURED, reason: no tick in the window, and a REST start is refused by design (objectstack#22310)",
        "Campaign enrollment screen flow (mgr): PASS (4 to 10 members); selection-bar Add to Campaign PASS; header Add to Campaign FAIL-UX (finding 11); bulk confirm shows ids (finding 12)",
        "Activities: Schedule Follow-up PASS, Log a Call PASS, Clone Opportunity PASS, Update Stage bulk (aggregate) PASS, KB Helpful PASS",
        "Dashboards (5) DOM probe: admin, mgr (en-US and zh-CN), rep PASS; service_agent no-access tiles (finding 09)",
        "Reports (10) open: admin PASS; service_agent Pipeline Coverage raw refusal (finding 10)",
        "Global search Cmd+K: PASS (rep, Acme)",
        "zh-CN (mgr): nav, forms, dashboards, record pages Chinese PASS; list headers (02), screen titles (06), public forms (13) FAIL; ja-JP and es-ES spot-check confirm 02",
        "CSV import, forecasts manual override, opportunity status-change and qualification gates: NOT MEASURED (time-box; both gates are off by default by design)"
      ],
      "open_questions": [],
      "out_of_scope_findings": [
        "01 Web-to-Lead: every anonymous contact-us submission ends in a FAILED lead_assignment run and no one is alerted · class: a · reach: /_console/f/contact-us submit (201), then sys_automation_run status failed at notify_std: 'notify: at least one recipient is required, but every recipient value expression evaluated to nothing: `record.owner_id`' · producer: hotcrm src/sales/flows/lead-assignment.flow.ts (notify_hot / notify_std recipients cel record.owner_id, with no decision for an ownerless lead; lead.hook.ts L72-74 says this flow routes such leads) · actual (v18 2f3d898d): lead created with owner_id null, next_followup_date stamped, run failed; mgr and agent can read it, reps get 404 · repro: sign out, submit contact-us, open Setup / Automation Runs / lead_assignment · notify_std · screenshot: qa/2026-10-13-v18-pass/01-web-to-lead-lead-assignment-run-fails.png · dedupe: web-to-lead, lead_assignment, notify_std, recipient required, ownerless lead",
        "05 Convert Lead as sales_rep fails: Field write denied [annual_revenue] on crm_account · EXISTING open card #2016, comment there and do not refile · class: a · reach: Convert Lead button, resume returns 400 FLOW_FAILED 'Node create_account failed: create_record(crm_account) failed: [Security] Field write denied: not permitted to edit [annual_revenue]', with the raw engine text in the dialog · producer: hotcrm src/sales/flows/lead-conversion.flow.ts + src/sales/profiles/sales-rep.profile.ts (per #2016) · actual: reproduces identically on 18.0.0-next.0; the manager path passes · screenshot: qa/2026-10-13-v18-pass/05-rep-convert-lead-annual-revenue-denied.png · dedupe: rep convert lead, annual_revenue, field write denied",
        "09 Service agent Home and 4 Insights entries render 'You don't have access' tiles; dashboards and reports are not gated by persona · class: a · reach: sign in as service.agent, Home = executive_dashboard; 4x 403 POST /api/v1/analytics/dataset/query on Home, 4x Sales Performance, 1x Sales Activity, 4x CRM Overview, 1x Pipeline Coverage (rep and mgr: 0) · producer: hotcrm src/sales/apps/crm.app.ts (the executive dashboard is Home for every persona; dashboard and report nav items carry no visibility gate) with the platform half: dashboard and report nav items are not gated by dataset object access the way object items are · screenshot: qa/2026-10-13-v18-pass/09-service-agent-home-dashboard-no-access-widgets.png · dedupe: service agent home dashboard, no access widget, dashboard nav visibility",
        "11 Leads header 'Add to Campaign' with 0 or 2+ rows selected is a silent no-op (campaign picked, Confirm, dialog closes, no request, no message); with 1 row it dispatches but shows no result either · class: a · reach: Leads list header button; no POST /api/v1/actions/crm_lead/create_campaign, 0 members created (read-back) · producer: @objectstack console (the single-record list_toolbar script dispatch never shows its 'select exactly one row' refusal or the result; lead.actions.ts L233-239 documents the refusal as client-side) and hotcrm src/sales/actions/lead.actions.ts L240 (the single-record action placed in list_toolbar next to the same-named bulk button) · screenshot: qa/2026-10-13-v18-pass/11a-toolbar-add-to-campaign-two-rows-before-confirm.png, qa/2026-10-13-v18-pass/11b-toolbar-add-to-campaign-after-confirm-nothing-happens.png · dedupe: add to campaign toolbar, list_toolbar action no-op, select exactly one row",
        "08 Create Lead form blocks save with 'Lead Owner is required' and never prefills the current user (the only create form that requires the owner) · class: a · reach: Leads / New as na.rep, fill name/company/email, Create shows an inline error and POSTs nothing · producer: hotcrm src/sales/views/lead.view.ts L293-296 ({ field: owner_id, required: true }); the console not prefilling owner_id is the platform half · actual: Opportunity, Account and Contact New forms also leave Owner blank but do not require it; the server stamps the creator anyway (lead.hook.ts L41-43) · screenshot: qa/2026-10-13-v18-pass/08-create-lead-form-owner-required-not-prefilled.png · dedupe: lead owner required, owner prefill, create lead form",
        "02 zh-CN (and ja-JP, es-ES): list views show English column headers; Leads 9 of 9 data columns, Opportunities 'Account' · class: a · reach: Leads list in zh-CN shows Name, Company, Email, Status, Score, Source, Need Type, Est. Amount, Owner while the page is Chinese; 11 other lists are fully translated · producer: hotcrm src/sales/views/lead.view.ts L141-200 and src/sales/views/opportunity.view.ts (an explicit column label shadows the translated field label) together with @objectstack/spec translation schema: _views.VIEW admits label, description, emptyState and bulkActions, with no per-column key · screenshot: qa/2026-10-13-v18-pass/02-zh-cn-lead-list-english-column-headers.png · dedupe: zh-CN list column header, view column label untranslated",
        "13 zh-CN anonymous Web-to-Lead and Web-to-Case forms show English section titles, help texts and placeholder although the pack translates the sections; the signed-in New Lead dialog renders them in Chinese · class: a · reach: /_console/f/contact-us and /_console/f/support with locale zh-CN: 'Tell us about yourself', 'About your company', 'How can we help?', 'A sales representative will get back to you within one business day.', 'Briefly describe what you are looking for...' · producer: @objectstack public form renderer / GET /api/v1/forms/SLUG (does not apply _sections translations on the anonymous path; form helpText and placeholder may have no translation key, the same family as 02); the pack keys are in zh-CN objects.pipeline.ts L196-198 and objects.service.ts L126 · screenshot: qa/2026-10-13-v18-pass/13-zh-cn-public-web-to-lead-form-english-sections.png · dedupe: public form translation, web-to-lead zh-CN, form section untranslated",
        "10 A report the user cannot read shows a raw server refusal instead of the no-access panel dashboard widgets use · class: a · reach: service.agent opens Insights / Pipeline Coverage, 403 POST /api/v1/analytics/dataset/query, red box 'Analytics query refused: this user may not read the data behind dataset opportunity_metrics. (server said: [Analytics] Access denied: reading crm_opportunity is not permitted for this user.)' · producer: @objectstack console report renderer (403 handling); hotcrm only declares src/sales/reports/opportunity.report.ts · screenshot: qa/2026-10-13-v18-pass/10-report-raw-analytics-refusal-text.png · dedupe: report access denied raw error, analytics query refused",
        "07 Notifications emitted by system-context runs are stored with organization_id NULL; the platform WARN says reports and cleanup will not see them · class: a · reach: hourly case_sla_monitor tick; sys_notification case_sla_breach 16/16, urgent_task 11/12 and approval.requested 5/5 have org NULL, while user-driven topics carry it; server WARN '[notify] no organization in scope for topic case_sla_breach … will carry organization_id = NULL'; sys_inbox_message rows do carry the org · producer: @objectstack (notify from a schedule-tick / system run and the approval node's approval.requested emit; service-messaging / service-automation / plugin-approvals) · screenshot: qa/2026-10-13-v18-pass/07-system-run-notifications-null-organization.png (Setup record; the evidence is the counts) · dedupe: notify no organization in scope, sys_notification organization_id null",
        "06 zh-CN: three screen flows show the flow label as the screen title instead of translating the step · class: a · reach: zh-CN Convert Lead dialog reads 线索转化流程 twice (EN: Lead Conversion Process / Conversion Details) · producer: hotcrm src/sales/translations/zh-CN/app.ts L613 (campaign_enrollment '将成员加入营销活动' for 'Enrollment Criteria'), L659 (lead_conversion '线索转化流程' for 'Conversion Details'), L710 (quote_generation '从商机生成报价单' for 'Quote Details'); es-ES and ja-JP not checked · screenshot: qa/2026-10-13-v18-pass/06-zh-cn-convert-screen-title-repeats-flow-label.png · dedupe: zh-CN screen title, flow screen translation",
        "12 The per-row bulk-action confirm step lists the affected records as raw ids · class: a · reach: Leads selection bar Add to Campaign / Next shows 'Affected records (2): NZlnBCoFRGzxCw4O, Y-5E63TwqDGmfwfW'; the aggregate path (mass_update_stage) lists record names correctly · producer: @objectstack console per-row bulk runner for bare-string bulkActions; hotcrm declares bulkActions ['create_campaign'] in src/sales/views/lead.view.ts · screenshot: qa/2026-10-13-v18-pass/12-bulk-action-confirm-lists-raw-record-ids.png · dedupe: bulk action affected records ids",
        "03 Formula text fields render in a monospace font (Leads Name column = crm_lead.full_name formula; FULL NAME on the lead record) · class: a · reach: Leads list and lead record page · producer: @objectstack console formula cell and field renderer; hotcrm only declares Field.formula (src/sales/objects/lead.object.ts L74) · screenshot: qa/2026-10-13-v18-pass/03-formula-name-column-monospace.png · dedupe: formula field monospace, full_name font",
        "04 Ops: every page load by a non-admin writes 16 '[Security] Access denied' WARN lines to the server log · class: a · reach: any page as sales.manager; the header activity feed GET /api/v1/data/sys_activity?top=20&sort=-timestamp returns 200 and alone adds 16 denials (sys_record_share, sys_email, sys_approval_action, sys_approval_approver, sys_approval_request, sys_user_position, sys_sharing_rule, sys_migration capability) · producer: @objectstack (sys_activity read fan-out in the data/security layer; isolated by replaying each GET of a record page) · screenshot: qa/2026-10-13-v18-pass/04-activity-feed-access-denied-log-flood.png (UI surface; the evidence is the log counts) · dedupe: sys_activity, access denied warn, log flood"
      ]
    }

    Generated by Claude Code

  6. objectstack-fleet commented on Oct 13, 2026

    @objectstack-fleet
    ContributorAuthor

    Verdict on the os-dev report 6148430430 — ACCEPT. This measurement card is delivered, and every finding is filed. Closing completed. repo:hotcrm seat, session_01BCDqr1DqnQjEh5jA9gGkUG, 2026-10-13T14:58Z.

    What ran: main 2f3d898d (@objectstack/* 18.0.0-next.0) on a fresh database, with scheduled work enabled and demo staff, driven in Chromium as admin, sales rep, sales manager, service agent and service manager. Per the maintainer's mid-run change (「测试不用对比 v17,测试遇到问题就报issue」), there was no v17 leg. Every finding was screenshotted (「测试遇到问题应该截图给我」) and sent to the maintainer in the session. The PNGs stay on this card's branch claude/issue-2093-v18-regression-pass (qa/2026-10-13-v18-pass/), which the filed cards link to, so ⛔ do not delete the branch.

    Passed:

    • Convert Lead as a manager;
    • the large-deal approval and its rejection; account approval;
    • quote → lines → accepted → contract draft → activated (billing hand-off);
    • the case lifecycle (create, escalate, claim, close);
    • the hourly SLA sweep (32 selected / 16 acted);
    • both anonymous forms submitting;
    • campaign enrollment (screen flow and selection bar);
    • all 5 dashboards and 10 reports as admin, manager and rep;
    • global search, the nav sweep, follow-up, call logging, clone and bulk stage update.

    The 13 findings, and where each one went:

    # finding filed / carried
    01 web-to-lead lead_assignment fails on an ownerless lead #2060 item 6 (comment 6147243065)
    02 zh-CN list column headers English (Leads, Opportunities) #2094
    03 text formula renders monospace #2095
    04 sys_activity read floods the log with access denials objectstack-ai/objectstack#23279
    05 rep Convert Lead: annual_revenue write denied #2016 (comment 6147445336)
    06 zh-CN screen-flow titles repeat the flow label #2096
    07 system-run notifications stored with no organization objectstack-ai/objectstack#23284
    08 Create Lead form requires the owner and does not prefill it #2097
    09 service agent's Home and Insights show no-access tiles #2060 item 5 (comment 6148066497)
    10 report renders the raw analytics refusal objectstack-ai/objectui#12330
    11 toolbar single-record action is a silent no-op objectstack-ai/objectui#12331
    12 per-row bulk confirm lists raw ids (#12119's fix missed this path) objectstack-ai/objectui#12332 (+ narrowing 6148401640)
    13 anonymous form sections untranslated (a regression of objectui#8813) objectstack-ai/objectui#12333

    Not measured (time-box, or by design): CSV import; the forecast manual override; the daily crons (no tick in the window; a REST start is refused by design); the in-place 17 → 18 upgrade, dropped by the scope change, so objectstack-ai/objectstack#23256 stays unmeasured on an upgraded database.


    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:p1High: required for production / M2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions