Skip to content

立项 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 #2004

Closed

Description

@objectstack-fleet

Filing gate: ③ a task the maintainer ordered directly. It was item 3 of the decision batch the repo:hotcrm seat presented in its chat (session_01ER8ntXZhYebyQ66aXWdjfT). The maintainer agreed on 2026-10-03 at about 23:0xZ, verbatim: 「决裁的三张同意」. That ruled option B, as recommended.

Follow-up to #1995 / PR #1996 (4807ed9e), the step-11 立项 gate, which ships off by default.

Who acts on it: the repo:hotcrm seat dispatches one dev.

The ruling

Done when

  • The will_bid term is gone from the 立项 branch in src/sales/objects/opportunity.hook.ts, and the refusal message no longer names "Will Bid".
  • test/opportunity-qualification-approval-gate.test.ts is updated: a will_bid edit is ALLOWED while 立项 is pending or rejected. Every other matrix row is unchanged.
  • The qualification docs page in 3 locales and the changeset text say the same thing.
  • pnpm verify is green. A boot with the gate armed in a local throwaway shows will_bid saving 200 while pending, and a stage move still 409.

Duplicate check

This narrows #1995's own scope, which is closed and merged. No other card covers it: the seat's grep of hotcrm issues for will_bid|立项 found only #1995, #1911 and REQ-0006 references.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 3, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round R73
    Session: session_01ER8ntXZhYebyQ66aXWdjfT
    Account: hotlong (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-2004-will-bid-before-qualification
    Worktree: hotcrm-issue-2004
    Domain: repo:hotcrm (single-lane repo, no domain:* taxonomy)
    Seat: repo:hotcrm#1
    File surface: src/sales/objects/opportunity.hook.ts (the 立项 branch only), test/opportunity-qualification-approval-gate.test.ts, content/docs/sales/opportunity-qualification{,.zh-Hans,.zh-Hant}.mdx, one .changeset/2004-*.md (stop on breach; explain in the report)
    Container & model: S, mode:subagent, model: default (dispatch-gates --tier --repo objectstack-ai/hotcrm answers "no path-derived mandate … the tier stays the PM's per-card judgment call")
    Clause-②: no. This is app metadata; it touches no published schema and no accept set.
    Thread-read: none
    Serial constraints cleared: three cards are dispatched together under the maintainer's 「决裁的三张同意」: #1992 (src/service/{objects/case.*,reports,datasets,dashboards,views,data}), #2003 (src/sales/pages/lead_detail.page.ts, src/service/pages/case_detail.page.ts) and #2004 (src/sales/objects/opportunity.hook.ts, the 立项 gate test, the qualification docs). Their files are disjoint. #1992 shrinks the sla group that #2003 decides hideEmpty for; each dev is told to measure on its own tree and name that coupling. No open PR exists.


    Generated by Claude Code

  2. objectstack-fleet commented on Oct 3, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 2004,
    "status": "done",
    "branch": "claude/issue-2004-will-bid-before-qualification",
    "pr": "#2006",
    "session": "session_01ER8ntXZhYebyQ66aXWdjfT (mode:subagent, so the parent PM seat's session; the commit's Claude-Session line carries it)",
    "premise_still_valid": true,
    "summary": "Option B as ruled. The 立项 branch of opportunity_lifecycle no longer holds will_bid. While 立项 is pending or rejected it refuses only a stage change (a direct close included) and a new requested_status. The comment says why: step 8 makes 是否投标 input to 立项, and step 11's 投标 is the act of bidding, which HotCRM does not model. The refusal sentence names only what was held, now joined with 'and'. In the gate test, HELD_ACTS drops its 2 will_bid rows. RELEASED_ACTS adds 6 ALLOWED cases (yes, no and a change, on pending and on rejected), plus one case: stage + will_bid in one write is refused and names Stage only. The matrix's bid-decision column flips 立项 to ok in its 3 armed rows; every other cell is unchanged. Docs: the qualification page and the automation page (3 locales each), the flow's served description and its comments. The unreleased 1995 changeset is aligned, and a patch changeset is added. Draft PR #2006 (Fixes #2004 on line 1, the claim's Clause-② line on line 2) is assigned to hotlong.",
    "tests": "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 47809fb and 'os-verify-lock: VERDICT command-exit 0'. The chain: 'Validation passed' · lint '1 warning(s), 18 suggestion(s)' · '0 i18n/missing-* issues' · 'source hygiene clean' · 'source token ratchet clean' · 'Build complete' · 'Test Files 177 passed (177)', 'Tests 3797 passed | 1 skipped (3798)'. HEAD 47809fb is the final commit and the PR head. The gate file alone: 'Tests 50 passed (50)', VERDICT command-exit 0. Ablations: ablation-replace.mjs, wrap mode. Each anchor went x1 to x0, the blob changed, and the marker was counted on disk inside each run. Each restore was proven (blob == HEAD c759d1de, git diff HEAD empty). The tests import src/ directly, so no build or dist leg applies. Predicted, then observed: re-inserting the will_bid term, 10 red, 10/50 exactly. Dropping 'rejected', 4 red, 4/50 exactly. Deleting the stage term, 8 red, 8/50 exactly. Removing the 'Requested Status' push, 5 red, 5/50 exactly. The first will_bid re-insert attempt was refused by the tool before anything ran (its replacement contained the anchor), was re-spelled, and was then run. Boots on 17.6.0, port 4822, NODE_ENV=development, a fresh DB each. Armed: a LOCAL detached throwaway of 47809fb, the default held-flipped to pending with ablation-replace --hold and built to a scratch path; the served defaultValue was 'pending', all 43 artifact fields were present, the flow description was the new text, and the throwaway was restored and proven. Born pending: will_bid true 200, false 200; stage move 409 RECORD_LOCKED ('... Stage can change once it is approved.'); requested_status 409; direct close 409; stage + will_bid 409, naming Stage only. Ticking the request opened 1 flow:opportunity_qualification_approval request, and will_bid saved 200 while it was open. After approve: will_bid, stage move, requested_status and direct close each 200. Reject leg (a second deal): verdict rejected, request unticked, will_bid 200 (stored true), stage move 409, requested_status 409. Gate off (this branch, not_required served) and main 9466837 ran the same driver; the transcripts are identical with ids and timestamps masked (all acts 200, 0 approval requests). All servers were stopped by their recorded PID trees. Token ratchet, src/sales rows verbatim. Before (main 9466837): 'business semantics 47 5,740 225,673 56,418 59,000' / 'interaction layer 25 3,373 111,870 27,968 31,000' / 'authored total 117 10,417 399,717 99,929 107,000'. After (47809fb): 'business semantics 47 5,739 225,550 56,388 59,000' / 'interaction layer 25 3,373 111,870 27,968 31,000' / 'authored total 117 10,416 399,594 99,899 107,000'; 'source token ratchet clean'. No ceiling touched. CI at report time: Quality Checks, Check Changeset, link-check and Label Pull Request were success; Build and Test (22.x), Typecheck and Build, Playwright and Analyze Code were in_progress. Not waited for.",
    "mcp_calls": "0 — no MCP tool was called",
    "api_writes": "3 REST writes, each as ONE fleet-write relay stroke (POST /repos/objectstack-ai/objectstack/dispatches from this container, executed as objectstack-fleet[bot]): (1) pr_create → POST /repos/objectstack-ai/hotcrm/pulls, draft forced (request fw-20261003T233423Z-18c870, run 37162209167; read-back: 8656 bytes sent, 8656 stored, identical) → #2006; (2) label-write.mjs --assign hotlong → POST /repos//issues/2006/assignees (fw-20261003T233458Z-f181df, run 37162237777; read-back MATCHES, labels untouched); (3) this os-dev-report → POST /repos//issues/2004/comments via post-stamped.mjs. Plus git push (not REST): 2 pushes, the empty-branch probe then 47809fb. No force-push, no ready flip, no auto-merge, no merge, no card assignee write.",
    "deviations": [
    "Files outside the claim's literal file surface: content/docs/administration/automation{,.zh-Hans,.zh-Hant}.mdx (one row and one paragraph each), src/sales/flows/opportunity-qualification-approval.flow.ts (the served description, the docstring and the lockRecord comment) and .changeset/1995-qualification-approval-gate.md (two sentences; still unreleased, since CHANGELOG.md tops out at 3.1.0). Each named the bid decision as held, and this change made that false. CONFLICT, named rather than silently resolved: the claim says 'stop on breach'. The dispatch's expected-change 3 says 'any admin tip that names Will Bid as held', and the os-dev contract says what this round makes false must be fixed. I followed the latter two and stated the breach in the PR's 'Outside the claim's file surface' section. The seat may want to amend the claim's file surface.",
    "The refusal sentence's join changed from ', ' to ' and ' (inside the 立项 branch), so the two-term case reads 'Stage and Requested Status can change once it is approved.'",
    "Boots ran with NODE_ENV=development, because plugin-auth seeds admin@objectos.ai only in development. The first armed boot, without it, could not sign in, so it was stopped by PID and rebooted on a fresh DB; nothing was measured on it.",
    "Beyond the order: a rejected-leg armed boot, and a main 9466837 boot compared line by line against the gate-off boot."
    ],
    "files_changed": [
    "src/sales/objects/opportunity.hook.ts",
    "test/opportunity-qualification-approval-gate.test.ts",
    "content/docs/sales/opportunity-qualification.mdx",
    "content/docs/sales/opportunity-qualification.zh-Hans.mdx",
    "content/docs/sales/opportunity-qualification.zh-Hant.mdx",
    "content/docs/administration/automation.mdx",
    "content/docs/administration/automation.zh-Hans.mdx",
    "content/docs/administration/automation.zh-Hant.mdx",
    "src/sales/flows/opportunity-qualification-approval.flow.ts",
    ".changeset/2004-will-bid-before-qualification.md (new, patch)",
    ".changeset/1995-qualification-approval-gate.md (two sentences)"
    ],
    "open_questions": [],
    "out_of_scope_findings": [
    "class: a · reach: a public door with a wrong answer: a fresh boot (NODE_ENV=development objectstack start, empty DB) of main 9466837 logs 23 [SeedLoader] failures, the same on this branch. 'Failed to write crm_campaign record #0 (name=Q3 Enterprise Email Nurture): Campaign cannot move to in_progress without both start_date and end_date', the same for 'Operations Platform Launch', then 21 crm_campaign_member rows fail with 'Campaign is required'. So the shipped demo data boots with 2 campaigns and 21 members missing. Evidence: src/marketing/data/marketing.seed.ts carries both dates as cel daysAgo/daysFromNow tokens, yet the campaign hook sees them absent at insert. The seam (app hook vs platform SeedLoader token resolution) is NOT MEASURED. · dedupe words: SeedLoader campaign in_progress start_date end_date; Campaign is required campaign_member seed; marketing.seed.ts cel daysAgo; demo data missing campaigns",
    "carrier: none (承接者:无) · noted, not filed: the comment above qualification_approval_status in src/sales/objects/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 was left alone, being outside the claim; recorded in the PR's Acceptance notes."
    ]
    }

  3. objectstack-fleet commented on Oct 3, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT: PR #2006 at 47809fba. The 立项 gate no longer holds Will Bid. repo:hotcrm seat, session_01ER8ntXZhYebyQ66aXWdjfT, 2026-10-03T23:40Z. Report: the dev's os-dev-report on this card.

    Probes taken by the seat itself:

    • Ancestry and checks: 94668373 is an ancestor of 47809fba, and git merge-tree against today's main f24c1965 (fix(record-pages): keep the lead's and case's empty to-fill sections on screen #2005) is clean. CI 10/10 success. Governed check: 0 of 11 paths, NOT governed; 156 lines.
    • Read line by line:
      • In the hook's 立项 branch, the will_bid term is gone and the comment says why: step 8 makes 是否投标 input to 立项, and step 11's 投标 is the act of bidding.
      • The refusal now names only Stage and/or Requested Status, joined with "and".
      • The step-14 block, APPROVAL_FIELDS and the flow's behaviour are unchanged. Only the flow's description and comments are edited.

    The dev's measurements, accepted:

    • Test matrix: HELD_ACTS loses its 2 will_bid rows. RELEASED_ACTS gains 6 ALLOWED cases, on pending and on rejected. A combined stage + will_bid write is refused and names only Stage.
    • Ablations, each predicted then observed: re-inserting the term turns 10/50 red, dropping rejected 4/50, dropping the stage term 8/50, dropping the Requested Status push 5/50. Every restore is proven.
    • Boot with the gate armed (local throwaway), born pending:
      • will_bid true/false saves with 200;
      • a stage move, requested_status and a direct close each get 409;
      • while a request is open, will_bid still saves with 200;
      • after approval, everything gets 200;
      • after a reject, will_bid gets 200 and a stage move 409.
    • Gate off: the transcript is identical to main's.
    • Gates: pnpm verify VERDICT command-exit 0 (177 files). Tokens: src/sales business semantics goes down 30.

    Outside the claim's surface, accepted as "fix what the change makes false":

    • the automation docs page in 3 locales;
    • the flow's served description and comments;
    • two sentences of the still-unreleased .changeset/1995-qualification-approval-gate.md.

    Each stated that the bid decision was held. This record serves as the claim amendment.

    Landing:

    • Authority: the maintainer's 「决裁的三张同意」 (option B for this item), and 「授权你执行pr合并」.
    • Path: ready → auto-merge → queue.

    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

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions