Skip to content

[finding] Seed data puts every ≥$100K opportunity into a pending approval — ~90% of open kanban cards are undraggable in a fresh demo database #1902

Description

@yinlianghui

Filing class: ① reproducible exhibit defect — landing: src/sales/data/ (the curated active opportunity pipeline)

Finding, not a claim on anyone's queue — filed by the video-production lane, which uses hotcrm as the carrier app for ObjectStack promo films. Not taking this on.

What we observed

In a freshly seeded database, opportunities at or above $100K are all created into a pending approval, which locks the record. On the Opportunity kanban that leaves the large majority of open cards undraggable — attempting to move one produces a RECORD_LOCKED rejection.

Measured on our instance: 23 opportunities total, 14 non-pending; of the cards visible on the open stages, only a small minority could actually be moved.

Why it mattered to us

Dragging a card between stages is the single interaction our promo film demonstrates. We had to scan the seed set to find a card that was both visually suitable and unlocked (Initech Cloud Migration, approval_status: not_required), and then pin the whole shoot to that one record.

⚠ We deliberately did not approve anything or alter the seed to unlock cards — changing the carrier's data to suit the film would misrepresent the product's default state.

Why it may be worth a look beyond us

Anyone opening a fresh demo database and trying the board hits the same wall, and the failure presents as "drag and drop doesn't work" rather than "this record is awaiting approval".

Environment

  • hotcrm main @ c716a2c (17.4.0), OS_PRODUCT_STAGE=ga

What would resolve it for us

Seed a meaningful number of open, unlocked opportunities across the live stages — or lower/vary the approval threshold in seed data so the board is demonstrable out of the box.

Context: promo-video ticket steedos-labs/video-studio#356 (private repo; the finding above is self-contained).

Activity

  1. objectstack-fleet commented on Sep 25, 2026

    @objectstack-fleet
    Contributor

    repo:hotcrm seat, session_01X8U3asekbiC7yWoEPWR4Dg · stock re-triage group 6 (maintainer-confirmed ten-card group; maintainer reply verbatim: 「同意」) · 2026-09-25T04:39Z

    Ruled B → pm:queue, p2

    The maintainer confirmed group 6 with this card's recommendation B: re-price the seeded active pipeline so that only 1–2 deals sit at or above LARGE_DEAL_AMOUNT (100,000) to exhibit the approval flow; the rest fall below it so the kanban is draggable out of the box. ⛔ Not A: no fabricated approved-approval records.

    Measured: 9 of the 10 open seeded deals are ≥ LARGE_DEAL_AMOUNT; both approval start conditions are true for them, and the approval nodes set lockRecord: true (src/sales/flows/opportunity-approval.flow.ts:122, :148). The counts match the card (23 / 14 / Initech). This contradicts the seed comment "Two cards in each active stage make the kanban immediately legible".

    ⚠️ Unverified: whether dashboard/forecast pipeline figures or docs quote these amounts (a git grep over content/ and test/ for the deal names/amounts found 0 hits) — the dispatch must re-check.


    Generated by Claude Code

  2. 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 Sep 25, 2026
  3. objectstack-fleet commented on Sep 25, 2026

    @objectstack-fleet
    Contributor

    Claim: PM loop round R64 (serial dispatch, maintainer instruction verbatim: 「串行派发」) · 2026-09-25T14:12Z
    Session: session_01X8U3asekbiC7yWoEPWR4Dg
    Branch: claude/issue-1902-seed-pipeline-pricing
    Worktree: hotcrm-issue-1902
    Domain: repo:hotcrm (single-lane repo — no domain:* taxonomy)
    Seat: repo:hotcrm#1
    File surface: the curated active-pipeline seed under src/sales/data/ (opportunity amounts / their line items, OPPORTUNITY_LINES), any revenue seed that derives from those amounts (src/revenue/data/), tests that pin the seeded amounts or approval counts, docs that quote the seeded figures, one .changeset/ (stop on breach; explain in the report)
    Container & model: M, mode:subagent, model: opus — default judgement tier, hand-picked (dispatch-gates --tier refuses hotcrm paths from the objectstack checkout)
    Clause-②: no
    Thread-read: 5826849592
    Serial constraints cleared: #1258 (PR #1959, src/sales/data/activity.seed.ts) is MERGED. #1828 (PR #1960, line-item hooks) is MERGED, so seeded line items now get runtime ordinals; the seed's own 1..n numbers are kept. Open: #1956 (src/revenue/objects/{quote,contract}.object.ts, profiles, docs administration/revenue/contracts*) and #1950 (epic, src/sales/objects/opportunity*); ⛔ this card edits neither. Ruling: maintainer confirmed option B in re-triage group 6 (comment 5826849592).

  4. objectstack-fleet commented on Sep 25, 2026

    @objectstack-fleet
    Contributor

    os-dev-report

    {
      "issue": 1902,
      "status": "done",
      "branch": "claude/issue-1902-seed-pipeline-pricing",
      "pr": "https://github.com/objectstack-ai/hotcrm/pull/1961",
      "session": "session_01X8U3asekbiC7yWoEPWR4Dg (subagent; parent's id, per the claim comment 5833851637 that names this branch)",
      "premise_still_valid": true,
      "summary": "Ruling B implemented. The seven curated active-pipeline deals were re-scoped at the source of truth (OPPORTUNITY_LINES in src/sales/data/sales.seed.ts; dealValue() still derives amount and expected_revenue), so each comes in under LARGE_DEAL_AMOUNT: Globex 500000 to 95000, Northwind 240000 to 86500, Lattice SSP 125000 to 53000, Vertex Analytics 320000 to 79000, Apex 275000 to 93000, Lattice Renewal 210000 to 87000, Vertex Enterprise Rollout 675000 to 94000. Exactly two open deals stay over the line, one per tier: Acme Platform Upgrade 150000 (manager review only) and Wayne Enterprise License 1200000 (manager, then director, over HIGH_VALUE_DEAL_AMOUNT). Those two were kept because other seed prose already quotes their amounts: the Acme account description says $150K, and the Wayne in_approval contract has contract_value 1200000. A seed-row pin in test/seed-consistency.test.ts names both deals and their tiers, and asserts that every active stage keeps a card under the line. The flow, the thresholds and quote/contract.object.ts are untouched. Fresh-DB measurement: before, 23 total / 14 non-pending, 10 open, 9 open at or above 100K, 9 locked by a pending approval, 1 draggable (Initech); after, 23 / 21, 10 open, 2 at or above 100K, 2 locked, 8 draggable, and each of the 5 active stages holds 2 cards. Browser drag check in headless Chromium on the Sales Pipeline view: dragging Northwind Grid Modernization from Prospecting to Qualification got PATCH 200, and the API read-back shows stage qualification. Control: dragging the locked Acme Platform Upgrade got PATCH 409 RECORD_LOCKED plus a toast, and its stage stayed proposal. Before the fix, the API PATCH on Northwind got RECORD_LOCKED. PM assumption checks: A1 confirmed (the lock mechanism and the card's counts reproduced exactly). A2 confirmed (amounts are derived from lines; the seed's own line numbers were not touched). A3: the only consumer I had to update is the Globex Manufacturing Suite Proposal quote in src/revenue/data/revenue.seed.ts (tax 38000 to 7220, re-derived at the 8% every non-Acme quote bills; description no longer mentions implementation services). Its quote lines follow automatically through QUOTE_LINES. content/**, src/docs/** and test/** have 0 hits for the deal names or amounts. forecast.seed.ts is hand-typed rather than derived, so I left it. Campaign derived metrics count won deals only, so they are unaffected. A4: two deals kept over the line, one exhibiting each tier.",
      "tests": "All at HEAD 521de4e5 (the only commit), each command run under os-verify-lock. pnpm validate exit 0; typecheck 0; lint 0 (5 warnings, 14 suggestions, pre-existing); lint:i18n-gate 0 ('0 i18n/missing-* issues'); hygiene 0 ('source hygiene clean'); hygiene:tokens 0 ('source token ratchet clean'); build 0; test 0 ('Test Files 173 passed (173) / Tests 3716 passed | 1 skipped (3717)'). Token ratchet before and after: every measured line is identical on base 1551914b and on HEAD. Only the excluded bucket moved (src/*/data is outside the ratchet by ruling, EXCLUDED_DIR_NAMES = translations, data): about 96,270 tokens before, about 96,254 after. Seed data being outside the ratchet is confirmed. Ablation of the new pin: ablation-replace changed the Lattice SSP SMB line quantity from 2 to 7 (126000). The anchor went from 1 hit to 0, the replacement from 0 to 1, and the blob changed. seed-consistency went red: 'x exactly two open deals sit at or above LARGE_DEAL_AMOUNT, one per approval tier', AssertionError expected [ ...(3) ] to deeply equal [ ...(2) ], 1 failed / 39 passed. Restored: blob equals HEAD and git diff HEAD is empty. vitest reads src directly, so no build or dist step applies. Control-byte scan over the changed files returned no matches (grep exit 1). Changed files: .changeset/seed-pipeline-draggable-kanban.md (hotcrm patch), src/sales/data/sales.seed.ts, src/revenue/data/revenue.seed.ts, test/seed-consistency.test.ts.",
      "mcp_calls": "0",
      "api_writes": "2 via the fleet-write relay (POST /repos/objectstack-ai/objectstack/dispatches, each executed as objectstack-fleet[bot]): pr_create, which made POST /repos/objectstack-ai/hotcrm/pulls (draft #1961), and this report comment, POST /repos/objectstack-ai/hotcrm/issues/1902/comments. Plus git push x2, which is not REST. Zero label writes: #1961 carries only the labeler's path labels (ci/cd, metadata), and a changeset is included, so skip-changeset does not apply. Zero issue or PR assignee writes.",
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: none (承接者:无) - noted, not filed: an existing demo DB is not re-priced in place. Line-item seeds upsert on (opportunity, product), so product lines a deal no longer carries would stay behind as orphans, and approval requests already open stay open. The changeset points to pnpm demo:reset. This path was not measured. Recorded in the PR's Acceptance notes.",
        "carrier: none (承接者:无) - noted, not filed: the current-month forecast snapshot in src/sales/data/forecast.seed.ts (pipeline_amount 760000) is a hand-typed positional demo figure. It never tracked the seeded open pipeline (3,775,000 before) and does not now (2,017,500 after). It is an observation, not a defect class. Recorded in the PR's Acceptance notes."
      ],
      "gates": {
        "validate": 0,
        "typecheck": 0,
        "lint": 0,
        "lint:i18n-gate": 0,
        "hygiene": 0,
        "hygiene:tokens": 0,
        "build": 0,
        "test": 0,
        "ci": "in_progress (not waited on, per contract)"
      },
      "counts": {
        "before": {
          "total": 23,
          "non_pending": 14,
          "open": 10,
          "open_ge_100k": 9,
          "open_locked_pending": 9,
          "draggable_open": 1
        },
        "after": {
          "total": 23,
          "non_pending": 21,
          "open": 10,
          "open_ge_100k": 2,
          "open_locked_pending": 2,
          "draggable_open": 8
        }
      },
      "files_changed": [
        ".changeset/seed-pipeline-draggable-kanban.md",
        "src/sales/data/sales.seed.ts",
        "src/revenue/data/revenue.seed.ts",
        "test/seed-consistency.test.ts"
      ],
      "deviations": [
        "The verify chain ran step by step (the same eight scripts, in order) so that each step's exit code was captured, rather than as one pnpm verify.",
        "The PR footer uses the role file's session-URL form instead of the harness attribution block, because the role file takes precedence.",
        "The commit subject carries (#1902) as a reference. It has no card trailer.",
        "Worktree removed after the PR opened. The branch tip on origin is 521de4e5."
      ]
    }

    Generated by Claude Code

  5. objectstack-fleet commented on Sep 25, 2026

    @objectstack-fleet
    Contributor

    PM review — ACCEPT → landing once CI converges · 2026-09-25T14:36Z

    Reviewer of record: repo:hotcrm seat, session_01X8U3asekbiC7yWoEPWR4Dg. Reviewed against GitHub.

    • PR fix(seed): price the active pipeline so the demo kanban is draggable #1961 at 521de4e5: Fixes #1902, a real changeset, 4 files (+92 −24): seeds, one test and the changeset. The flow, the thresholds and the object files are untouched.

    • Ruling B executed: seven active deals re-scoped at the source of truth (OPPORTUNITY_LINES; amounts stay derived). Exactly two stay over LARGE_DEAL_AMOUNT, one per approval tier:

      • Acme Platform Upgrade, 150,000 — manager review.
      • Wayne Enterprise License, 1,200,000 — manager, then director.

      Both amounts are already quoted by other seed prose.

    • Measured on a fresh DB:

      open ≥100K locked by a pending approval draggable
      before 10 9 9 1
      after 10 2 2 8

      Every active stage keeps 2 cards. Browser: Northwind dragged Prospecting → Qualification (PATCH 200). Control: the locked Acme gets 409 RECORD_LOCKED.

    • Pin: test/seed-consistency.test.ts names the two over-the-line deals. An ablation that pushes a third deal over the line turns it red.

    • Consumer updated: the Globex quote in src/revenue/data/revenue.seed.ts (tax re-derived). content/, test/ and docs: 0 hits for the deal names and amounts.

    • Acceptance notes (no carrier): an existing demo DB is not re-priced in place (pnpm demo:reset), and the hand-typed forecast snapshot never tracked the pipeline.

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

Metadata

Metadata

Assignees

No one assigned

    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