Repository navigation
docs(automation): 按 flow 源码写实内置流程表两行,并修 opportunity_won_alert 的 description (#851) - #870
Merged
Merged
Conversation
…lows
The built-in flow table billed `opportunity_won_alert` as notifying "the owner
and their manager" and `case_escalation` as "reassign to a senior agent, notify,
create a follow-up task". Read node by node against the flows:
- opportunity_won_alert has one notify node, recipients ['{record.owner_id}'] —
the owner alone, no manager addressing anywhere. Its own `description` carried
the same claim, which is what the table had copied; both are corrected.
- case_escalation's update_record writes is_escalated / escalation_reason /
escalated_date / status and never owner_id — no reassignment. The escalation
notice already said so: "It remains assigned to you."
- The follow-up task IS real, but it belongs to the `case_status_side_effects`
hook (case.hook.ts), not to the flow, and it lands on the ACCOUNT owner, not a
senior agent. The row keeps the task and corrects who receives it.
All three locales. The words readers arrive looking for — manager, senior agent,
follow-up task — are stated as not-done rather than deleted. No flow behaviour,
node, condition or recipient changed.
Fixes #851
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VHrPAGEgFDoHjphqYG4BMa
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
yinlianghui
marked this pull request as ready for review
August 6, 2026 01:07
This was referenced Aug 6, 2026
src/docs/crm_sales.md 两处仍称「通知负责人及其经理」,两条 flow 都只发负责人 —— 且该文件随 ADR-0046 打进 dist/objectstack.json
#875
Closed
Closed
Closed
docs(service): write the index page's 《Where to find things》 list to the real navigation (#927)
#932
Merged
This was referenced Aug 6, 2026
Closed
yinlianghui
added a commit
to yinlianghui/hotcrm
that referenced
this pull request
Aug 10, 2026
…the real navigation (objectstack-ai#927) (objectstack-ai#932) The section that tells a new user where to click named four items; three of them did not survive a read of `src/apps/crm.app.ts`, and the one real item the group does carry was missing. Measured against `src/apps/crm.app.ts:131-140`, `group_service` has exactly three children: `nav_case` (Cases), `nav_knowledge` (Knowledge) and `nav_service_dashboard`, whose label is **Service Overview** — not "Service Dashboard". `crm_task` has no entry in this group at all: its two nav items are `nav_my_tasks` (My Tasks) and `nav_all_tasks` (All Tasks), both under `group_work` / **My Work** (`:84` / `:93`). And no metadata anywhere carries the name *Service Board*: the kanban is the view `case_workflow` with `label: 'Service Workflow'` (`src/views/case.view.ts:72-75`), reached from the **Workflow** tab in the case list's view switcher (`:59`) and never from the sidebar. So the list now names the three real items with their real labels, adds the Knowledge entry it had been dropping, and keeps the two names readers will arrive with — Tasks and Service Board — pointing at where those things actually live, per the objectstack-ai#870 / objectstack-ai#877 / objectstack-ai#885 / objectstack-ai#894 / objectstack-ai#913 / objectstack-ai#924 convention of naming what does not exist rather than deleting it silently. Product questions are left open on purpose (objectstack-ai#595 / objectstack-ai#596): whether the kanban should become its own nav item, and whether Tasks belongs under Service, are not decided here — only the current shape is recorded. All three locales, same lines. `src/` untouched. Claude-Session: https://claude.ai/code/session_01VHrPAGEgFDoHjphqYG4BMa Co-authored-by: Claude <noreply@anthropic.com>
yinlianghui
added a commit
to yinlianghui/hotcrm
that referenced
this pull request
Aug 10, 2026
…to the real navigation (objectstack-ai#943) (objectstack-ai#953) The section that tells a reader where to click named four things; three of them do not survive a read of `src/apps/crm.app.ts`, and the one that does was labelled with a name the app never shows. Measured against `src/apps/crm.app.ts` on `origin/main` (b7791ca, platform 17.0.0-rc.3), the app has seven groups — Sales, My Work, Activity, Marketing, Service, Insights, Approvals — and none of them is **Products**. The catalog's only sidebar entry anywhere is `nav_product`, labelled **Products**, under `group_marketing` (`:126`); `grep -rn "crm_product" src/apps/` returns that one line. So the page now sends a reader arriving with the name "Products group" to Marketing instead of to a place that does not exist, and links the Marketing overview page that objectstack-ai#938 / PR objectstack-ai#942 just brought in line. `group_approvals` (`:159-171`) has exactly one child: `nav_approval_requests`, whose label is **Inbox** (`:165`) — not *Approval Requests*, which no metadata in this repo carries. The other two listed items are re-judged individually rather than deleted silently, per the objectstack-ai#870 / objectstack-ai#877 / objectstack-ai#885 / objectstack-ai#894 / objectstack-ai#913 / objectstack-ai#924 / objectstack-ai#932 / objectstack-ai#942 convention: - **Action History** — no nav item of that name exists. The data behind it does: @objectstack/plugin-approvals registers `sys_approval_action` (enumerated from the installed package, alongside `sys_approval`, `sys_approval_approver`, `sys_approval_delegation`, `sys_approval_request`, `sys_approval_token`), and nothing in this app's navigation opens it. The page says exactly that. - **Processes** — deleted on purpose, and the source records why at `:166-169`: no `sys_approval_process` object exists in any installed plugin, so the old item's `requiresObject` guard hid it on every install, forever. The enumeration above confirms the absence, so the reason is written into the page. The one true claim survives unchanged: **Contracts** is under **Sales** (`nav_contract`, `:60`), and it is the app's only sidebar route to a contract. Two further facts from source are recorded with it: `group_marketing` and `group_approvals` declare no `expanded` key while Sales, My Work, Activity and Service set `expanded: true`, and `GroupNavItemSchema.expanded` defaults to `false` — so both groups are collapsed on load, which is the failure mode that sends a reader looking for the catalog away empty-handed. And the zh-Hans page names the label a simplified-Chinese user actually sees, 待我审批 (`src/translations/zh-CN.ts:1219`), next to the source label. Product questions stay open on purpose (objectstack-ai#595 / objectstack-ai#596): whether Products deserves its own group and whether Approvals should gain an audit-trail item are product decisions, not documentation ones. Only the current shape is recorded. All three locales, same lines; zh internal links carry no anchor. `src/` untouched. Fixes objectstack-ai#943 Claude-Session: https://claude.ai/code/session_01VHrPAGEgFDoHjphqYG4BMa Co-authored-by: Claude <noreply@anthropic.com>
yinlianghui
added a commit
to yinlianghui/hotcrm
that referenced
this pull request
Aug 10, 2026
… real app (objectstack-ai#960) (objectstack-ai#968) The first table a new user reads, whose entire job is "here is what the sidebar holds", had drifted in every one of its eight rows. Measured against `src/apps/crm.app.ts` on `origin/main` (4705aed, platform 17.0.0-rc.3), the app's `navigation` is one pinned top-level entry plus seven groups: `nav_home` (Home, :34), `group_sales` (:42), `group_work` (My Work, :69), `group_activity` (Activity, :103), `group_marketing` (:120), `group_service` (:131), `group_insights` (Insights, :144) and `group_approvals` (:160). Row by row, the old table said: - **Sales** — the group is real, but it carries nine children, not six. The table dropped Account Workbench (:52), Pipeline (:55) and Sales Performance (:61). - **Service** — real; the entry the table called *Knowledge Base* is labelled **Knowledge** (:138), and **Service Overview** (:139) was missing. Both names were already written to source on `service/index` by objectstack-ai#927 / PR objectstack-ai#932 and objectstack-ai#937 / PR objectstack-ai#947, so the two pages contradicted each other. - **Marketing** — real, but its children are Campaigns (:125) and Products (:126). *Campaign Members* is not a navigation entry at all: `grep -rn "crm_campaign_member" src/apps/` returns nothing. - **Products** — no such group. The catalog's only sidebar entry is `nav_product` under `group_marketing`, the same finding objectstack-ai#938 / PR objectstack-ai#942 and objectstack-ai#943 / PR objectstack-ai#953 already wrote to two other pages. - **Activities** — no such group; the real one is **Activity**, and `crm_task` is not in it. Its two entries are My Tasks (:84) and All Tasks (:93), both under **My Work** — which the table never mentioned at all, though it is the group a rep uses every day. - **Analytics** — no such group; the real one is **Insights**, and no entry anywhere is labelled *Dashboards* or *Reports*. - **AI** — no such group anywhere in the repo, and no entry labelled *Copilot* or *Knowledge Bases*. `src/apps/` contains one file; neither name appears in it. - **Approvals** — real, with exactly one child, labelled **Inbox** (:165). *Approval Requests* and *Action History* carry no metadata in this repo; objectstack-ai#943 / PR objectstack-ai#953 recorded the same two names on the revenue page. So the table now lists the pinned Home entry and all seven groups with their real children in source order, and every retired name is re-pointed rather than deleted silently, per the objectstack-ai#870 / objectstack-ai#877 / objectstack-ai#885 / objectstack-ai#894 / objectstack-ai#913 / objectstack-ai#924 / objectstack-ai#932 / objectstack-ai#942 / objectstack-ai#953 convention. Two further facts from source ride along: `group_marketing`, `group_insights` and `group_approvals` declare no `expanded` key while Sales, My Work, Activity and Service set `expanded: true`, and `GroupNavItemSchema.expanded` defaults to `false`, so those three are collapsed on load — the failure mode that makes a reader conclude something is absent. And the zh pages name the labels a simplified-Chinese user actually sees (待我审批, 知识库, 我的工作 — `src/translations/zh-CN.ts:1195-1219`), which is also why the old English *Knowledge Base* read plausibly for so long. Nothing checked any of it: `os validate` and `pnpm lint` walk authored metadata and never open `content/docs`. `test/docs-quick-tour-navigation.test.ts` now compares the table to `CrmApp.navigation` group-for-group and child-for-child in all three locales, pins the bold-is-real / italic-is-phantom typography the sibling pages already use, and pins the source facts the prose rests on. Restoring the old table turns 15 of its 21 assertions red in the predicted direction. Product questions stay open on purpose (objectstack-ai#595 / objectstack-ai#596): whether Products or AI deserve their own groups is a product decision, not a documentation one. Only the current shape is recorded. All three locales, same section; zh internal links carry no anchor. `src/` untouched. Fixes objectstack-ai#960 Claude-Session: https://claude.ai/code/session_01VHrPAGEgFDoHjphqYG4BMa Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #851
按 PM 裁定的 #840/#841 口径「写实当前行为」修 automation 页 flow 表两行 ×3 语言 +
opportunity-won-alert.flow.ts的description串。flow 行为零改动。前提复核:一半成立,一半被证伪
派单要求逐节点重读两条 flow 源码为据。结果如下 —— issue 的三项指控里两项成立,第三项(「不建任务」)不成立,这直接改变了 Case Escalation 那一行该怎么写。
成立 ①:赢单提醒不发给经理
src/flows/opportunity-won-alert.flow.ts全流程start → notify_management → end,唯一 notify 节点:recipients['{record.owner_id}']channels['inbox', 'email']无
manager_id、无 position/team 目标。该节点 73–75 行注释自陈原因:{record.owner_id.manager}在原始触发快照上无法穿透 lookup,会插值成字面量undefined,消息发给幽灵用户。编译产物复核(
dist/objectstack.json):flow 自身
description原文'On closed_won opportunities over $100K: notify owner + manager.'同错 —— 表行不是抄错,是忠实抄了 src 里同样不实的描述,两处一并写实。成立 ②:案例升级不改派
src/flows/case-escalation.flow.ts节点链start → get_record → update_record → notify → end。产物复核:update_record不含owner_id。第 93–96 行注释开头即No owner reassignment:;notify 正文自己就写 "It remains assigned to you."。src/profiles/service-agent.profile.ts:33-35独立佐证:"the agent holds no transfer grant oncrm_case… escalation still cannot move a case off its owner (#548; case reassignment remains the deferred half of that decision)"。issue 的事实节从
dist/objectstack.json的节点表读出「无create_record节点 → 不建任务」。节点表看不见 hook,这一步是误归因。flow 确实没有
create_record节点,而且是刻意删掉的 ——src/flows/case-escalation.flow.ts:100-104写明:src/objects/case.hook.ts:136-152的case_status_side_effects(afterUpdate)在status转入escalated且案例挂了客户时,插入一条crm_task:priority: 'urgent'、type: 'follow_up'、due_date= 次日、owner_id= 该客户的负责人。test/hooks-runtime-service.test.ts:92有一条现成的通过用例把这条链路钉死了:断言
task.priority === 'urgent'、task.owner_id === 'rep1'(= account.owner_id)、task.related_to_case、task.due_date === daysFromNow(1)。src/profiles/service-agent.profile.ts:26-29与content/docs/administration/sharing-and-security.mdx:164("tasks only (so an escalation can hand work to the account owner)")再次独立佐证。结论:若照 issue 与派单细则的字面写「不建任务」,会把一句真话改成假话 —— 反而比原文更不准。所以本行的写法是:保留跟进任务,改正它归谁(客户负责人,不是资深客服),并明说不改派。这是「写实当前行为」的直接结果,不是对裁定的偏离。
另外:
case-escalation.flow.ts的 description 无需改派单说「其 flow 文件 description 若同错一并写实」—— 逐条核过,没同错:
case_escalationAutomatically escalate high-priority casescase_escalation_on_createEscalate cases created critical (insert-time twin of case_escalation)故
src/flows/case-escalation.flow.ts零改动。本 PR 的src/**改动面只有一行 description。改文
表行(en / zh-Hans / zh-Hant 同步)
Large Deal Won Alert / 大额商机赢单提醒 / 大額商機贏單提醒
When an opportunity over $100K turns *Closed Won*, notify the owner and their managerWhen an opportunity over $100K turns *Closed Won*, notify the owner — the owner alone, not their manager…时,通知负责人 —— 只通知负责人本人,不通知其经理…時,通知負責人 —— 只通知負責人本人,不通知其經理Case Escalation Process / 案例升级流程 / 案例升級流程
When a case turns *Critical*, reassign to a senior agent, notify, create a follow-up taskWhen a case turns *Critical*, flag it escalated and notify its owner — the case is not reassigned to a senior agent, it stays with its owner; escalating also opens an urgent follow-up task for the account owner当案例变为 *Critical* 时,标记为已升级并通知其负责人 —— 不会重新分配给资深客服,案例仍归原负责人;升级同时会给客户负责人创建一条紧急跟进任务當案例變為 *Critical* 時,標記為已升級並通知其負責人 —— 不會重新指派給資深客服,案例仍歸原負責人;升級同時會給客戶負責人建立一條緊急跟進任務术语沿用站内既有译法(
客户负责人/客戶負責人= account owner,见content/docs/administration/sharing-and-security.zh-Hans.mdx:150);破折号沿用本表既有的——写法。description 串
src/flows/opportunity-won-alert.flow.ts'On closed_won opportunities over $100K: notify owner + manager.''On closed_won opportunities over $100K: notify the owner — the owner alone, not their manager.'产物落位复核(
pnpm build后读dist/objectstack.json):不静默删名 & #595 边界
「经理」「改派(资深客服)」「跟进任务」都是读者可能带着找来的词,三个都留在文本里,写成当前不做 / 当前归谁,而不是删掉让读者以为页面漏写了。
文本只描述今天的行为,不预判 #595(SLA policy matrix: … escalation that reassigns,尚开放的产品提案)的结论 —— 既不写「将来会改派」,也不写「永远不会」。让升级真的改派是行为变更,属 #595 的独立实现单,届时文档随之再更新。
守卫盲区(如实报,含反向验证)
test/automation-docs-coverage.test.ts派生校验的是行集 / 触发面 / 两个数词,「它做什么」这一列是纯散文,不在派生范围内。预期改前改后全绿 —— 但比起断言,直接测了:Test Files 1 passed (1) / Tests 20 passed (20)Test Files 1 passed (1) / Tests 20 passed (20)同一套规则在真值相反的两份散文上都给绿,盲区是测出来的而不是推出来的。本 PR 不加守卫(派单明确禁止);这条散文列目前无自动化守卫,是已知且被接受的状态(#854 已证同一盲区)。
test/metadata-references.test.ts未钉 flow description 原文(grep 确认全仓只有两个 flow 文件自身含这些串),故 description 改动未触红任何测试,无需同批同步。验证
全量套件,共享锁
flock -w 7200 /tmp/os-heavy-verify.lock+NODE_OPTIONS=--max-old-space-size=4096:pnpm validatepnpm typecheckpnpm buildpnpm test --maxWorkers=2Test Files 66 passed (66) / Tests 1587 passed | 1 skipped (1588)pnpm lint13 warning(s), 14 suggestion(s),均为既有pnpm hygiene✓ no raw control bytes in first-party files/✓ source hygiene clean控制字节自扫(
grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f]')覆盖全部 5 个改动文件:零命中。边界遵守
src/**仅opportunity-won-alert.flow.ts一行description;case-escalation.flow.ts零改动。git diff显示三个 doc 文件各只有 ±2 行。releases/;未升级@objectstack/*;changeset 站内路径用反引号。顺带发现(已另立单,未在本 PR 修)
#869 —— 两条 flow 的节点 label 仍写着未发生的行为:
'Notify Management'(opportunity-won-alert.flow.ts:71,实际只发负责人)、'Assign to Senior Agent'(case-escalation.flow.ts:87,实际不写owner_id);外加opportunity-won-alert.flow.ts:10-12的文件头 JSDoc 仍留着本 PR 刚从 description 改掉的那句「notify the owner and their manager」。三处都在派单边界(「除 description 外src/**零改动」)之外,故未动。节点 label 是随产物发布的 authored metadata,与本 PR 修的表行属同族问题;节点id承重(edges[]按 id 引用),不可顺手改 —— 已在 #869 里写明。Generated by Claude Code