Skip to content

feat(opportunity): the 立项 gate leaves Will Bid open — it holds only a stage change and a new won/lost request (#2004) - #2006

Merged
objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/issue-2004-will-bid-before-qualification
Oct 3, 2026
Merged

objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/issue-2004-will-bid-before-qualification

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #2004
Clause-②: no. This is app metadata; it touches no published schema and no accept set.

The maintainer's ruling on this card (「决裁的三张同意」, option B): REQ-0006 step 8 has the rep fill 是否投标 (Will Bid) as input to 立项, which the approver reads. So the 立项 gate no longer holds will_bid. While 立项 is pending or rejected, it still refuses exactly two user acts: a stage change (a direct close included) and a new requested_status. This follows up the step-11 gate from #1995 / PR #1996.

What changed

  • src/sales/objects/opportunity.hook.ts, the 立项 branch only.
    • The will_bid term is gone.
    • The comment block lists two held acts and says why Will Bid is released. Step 8 makes it input to 立项, and step 11's 投标 is the act of bidding, which HotCRM does not model.
    • The refusal sentence names only what was held. With two possible terms it now joins them with "and".
  • test/opportunity-qualification-approval-gate.test.ts.
    • HELD_ACTS drops its two will_bid rows. The three remaining rows (stage move, direct close, won/lost request) are unchanged.
    • New RELEASED_ACTS: recording Will Bid as yes, as no, and changing it. Each is ALLOWED on a deal awaiting 立项 and on a deal refused 立项, so 6 cases.
    • One new case: a write carrying a stage move beside Will Bid is refused RECORD_LOCKED / 409, and the sentence names Stage, not Will Bid.
    • In the matrix, the bid decision column flips from 立项 to ok in the three rows where 立项 is pending or rejected. Every other cell and every other row is unchanged.
  • The qualification page (3 locales). It changes the intro bullet and the "what waits" paragraph. Will Bid moves into what can be worked, with the reason. It also changes the Approved row, the bold held sentence, "those three" to "those two", the off-by-default callout and two rep tips. One tip now says to fill in Will Bid before asking for 立项.
  • The automation page (3 locales). The flow's row and the Approvals paragraph no longer name the bid decision.
  • src/sales/flows/opportunity-qualification-approval.flow.ts. The flow's description is served to the admin automation list (checked on the boot below). It and the docstring no longer name the bid decision as held, and the lockRecord comment counts two acts.
  • Changesets.
    • A patch changeset: .changeset/2004-will-bid-before-qualification.md.
    • .changeset/1995-qualification-approval-gate.md is still unreleased: CHANGELOG.md tops out at 3.1.0. Two of its sentences said Will Bid is held, so they are edited. Without that edit, the release that ships the gate would describe it wrongly.

Verification

  • pnpm verify. OS_VERIFY_LOCK_SLOT=hotcrm-issue-2004 bash scripts/pm/os-verify-lock.sh -c 'git rev-parse --short HEAD && pnpm verify' printed 47809fba and os-verify-lock: VERDICT command-exit 0.
  • The gate file alone: Tests 50 passed (50).

Ablations

  • Every ablation used ablation-replace.mjs in wrap mode. Each anchor went from x1 to x0, the blob changed, and the marker was counted on disk inside the run.
  • Each restore was proven: the blob equals HEAD (c759d1de) and git diff HEAD is empty.
  • The tests import src/ directly, so no build or dist/ leg applies.
  • The direction was predicted before each run, and each run went red exactly as predicted.
ablation on the 立项 branch predicted observed
re-insert the will_bid term 10 red: the 6 released cases, the "names only" case, and the matrix's pending, rejected and both-on-before rows 10 of 50, exactly those
drop rejected from the condition 4 red: the 3 held acts on a rejected deal, plus the matrix's rejected row 4 of 50, exactly those
delete the stage term 8 red: stage move and direct close on both shapes, the "names only" case, and the 3 armed matrix rows 8 of 50, exactly those
remove the Requested Status push 5 red: the won/lost request on both shapes, and the 3 armed matrix rows 5 of 50, exactly those

The first attempt at the re-insert ablation was refused by the tool before anything ran, because the replacement contained its own anchor. The anchor was re-spelled and the run above followed.

Boots (fresh 17.6.0, port 4822, NODE_ENV=development, a fresh database each)

  • The armed artifact came from a LOCAL, never-pushed, detached throwaway worktree of 47809fba.
    • The verdict field's default (defaultValue, and the option default) was flipped to pending through ablation-replace --hold, then built to a scratch path.
    • The throwaway was restored afterwards and proven: blob equals HEAD, and git diff HEAD is empty.
    • The served metadata was checked against that build: qualification_approval_status.defaultValue was pending, all 43 fields were present, and the flow description was the new text.
  • Armed, while pending. A new deal was born pending.
    • will_bid true → 200, then false → 200.
    • A stage move → 409 RECORD_LOCKED: This deal needs qualification approval first: tick Request Qualification Approval. Stage can change once it is approved.
    • requested_status → 409 (… Requested Status can change once it is approved.). A direct close → 409.
    • Stage and Will Bid in one write → 409, and the sentence named only Stage. The stage stayed prospecting.
  • Armed, request open. Ticking the request opened exactly one flow:opportunity_qualification_approval request. will_bid saved 200 while it was open.
  • Armed, after approval. Approved through /api/v1/approvals/requests/{id}/approve, the verdict became approved. will_bid, a stage move, requested_status and a direct close each answered 200.
  • Armed, after rejection (a second deal). Rejected through /reject, the verdict became rejected and the request was unticked. will_bid saved 200 (stored true). A stage move and requested_status each got 409, and the stage stayed prospecting.
  • Gate off: the same as main.
    • This branch's real default, built from the restored throwaway, was served not_required.
    • main 94668373 was built and booted the same way.
    • The same driver ran on both, and the two transcripts are identical once ids and timestamps are masked. A deal is born not_required. Will Bid, a stage move, requested_status and a direct close each answer 200, and 0 approval requests exist. The last write is refused only by the closed-deal freeze, on both.
  • Every server was stopped by its recorded PID tree, and the throwaway worktree was removed.

Token ratchet (src/sales)

scope main 9466837 this branch 47809fb ceiling
business semantics 56,418 56,388 59,000
interaction layer 27,968 27,968 31,000
authored total 99,929 99,899 107,000

No ceiling was touched.

Outside the claim's file surface

The claim lists the hook, the gate test, the qualification page and one 2004 changeset. This PR also touches the files below. Each one stated that Will Bid is held, and this change made that false. The dispatch names "any admin tip that names Will Bid as held" in scope.

Acceptance notes

  • Boundary, unchanged. Insert is not judged, and system writes are not judged, as feat(opportunity): the 立项 (qualification) approval gate, off by default (REQ-0006 step 11) #1996 drew it. Will Bid's release is for user writes on update, which were the only writes the term ever held.
  • Left as is: the comment above qualification_approval_status in opportunity.object.ts says "a stage move, Will Bid and a direct close work exactly as they do without it" while the gate is off. That is still true, so it is not edited, being outside the claim.
  • Unrelated, the same on main: each of the three boots logged the same 23 [SeedLoader] failures. Two crm_campaign rows were refused with Campaign cannot move to in_progress without both start_date and end_date, though the seed carries both as cel dates, and 21 crm_campaign_member rows then failed with Campaign is required. It is reported to the seat, not handled here.

Generated by Claude Code

…stage change and a new won/lost request

REQ-0006 step 8 has the rep fill 是否投标 as input to 立项, for the approver
to read. Holding Will Bid until approval had the approver decide without it.
Step 11's 投标 is the act of bidding, which HotCRM does not model.

- opportunity_lifecycle: the will_bid term leaves the 立项 branch; the comment
  says why, and the refusal sentence names only what was held.
- The gate test: Will Bid is allowed while pending and while rejected; the
  matrix's bid-decision column reads ok in every row; every other row is
  unchanged.
- Docs (qualification and automation pages, 3 locales), the flow's
  description, and the unreleased 1995 changeset say the same; a patch
  changeset.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ER8ntXZhYebyQ66aXWdjfT
@vercel

vercel Bot commented Oct 3, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
hotcrm Ignored Ignored Oct 3, 2026 11:34pm UTC

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation ci/cd CI plumbing and the verification pipeline metadata Declarative metadata — schema, security posture, UI surfaces backend Server-side behaviour — hooks, flows, actions labels Oct 3, 2026
@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 3, 2026 23:41
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 3, 2026
Merged via the queue into main with commit 4054ec2 Oct 3, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend Server-side behaviour — hooks, flows, actions ci/cd CI plumbing and the verification pipeline documentation Improvements or additions to documentation metadata Declarative metadata — schema, security posture, UI surfaces

Projects

None yet

Development

Successfully merging this pull request may close these issues.

立项 gate: let the rep record Will Bid before 立项 is approved — it is input to the approval (REQ-0006 step 8), not one of the acts step 11 holds

2 participants