weaver-work-cli 0.1.33 → 0.1.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/dist/chunks/{archive-FVFY6GZN.js → archive-XBVH7JU7.js} +2 -2
  2. package/dist/chunks/{archive-oa-NW3OD4UV.js → archive-oa-MZM3EKFQ.js} +2 -2
  3. package/dist/chunks/{asset-7QJKMIDV.js → asset-4XO7UOUW.js} +2 -2
  4. package/dist/chunks/{attachment-content-OSAVA6K3.js → attachment-content-VXSWANAC.js} +3 -3
  5. package/dist/chunks/{blog-I7SDPNW4.js → blog-PGZKOPSC.js} +2 -2
  6. package/dist/chunks/{caizhilian-O37ZIQNY.js → caizhilian-BH4ZVGUN.js} +2 -2
  7. package/dist/chunks/{calendar-7KXE4ED3.js → calendar-MXEMTIO4.js} +2 -2
  8. package/dist/chunks/{chunk-VBCFFFGT.js → chunk-5DQEEGCC.js} +4 -1
  9. package/dist/chunks/{chunk-KAS45KNR.js → chunk-6LLJFKJE.js} +1 -1
  10. package/dist/chunks/{chunk-HEL5XTYI.js → chunk-BPE37FPB.js} +26 -4
  11. package/dist/chunks/{chunk-IHUYP6LO.js → chunk-F746NKNF.js} +1 -1
  12. package/dist/chunks/{chunk-MQ2I5AA3.js → chunk-HXJQI5NM.js} +2 -2
  13. package/dist/chunks/{chunk-ILMBNVSG.js → chunk-I6QGIBDM.js} +2 -2
  14. package/dist/chunks/{chunk-EEWPQE3O.js → chunk-JCSN3JGM.js} +2 -2
  15. package/dist/chunks/{chunk-D223PTXU.js → chunk-JNG42JKG.js} +29 -1
  16. package/dist/chunks/{chunk-6ATGWRZM.js → chunk-JUXVYKII.js} +4 -1
  17. package/dist/chunks/{chunk-GFPXQIY2.js → chunk-JYKABYCV.js} +2 -2
  18. package/dist/chunks/{chunk-Q6LWB5HX.js → chunk-NCOVUAZK.js} +2 -2
  19. package/dist/chunks/{chunk-WY74UBJ6.js → chunk-QHFANTX7.js} +900 -204
  20. package/dist/chunks/{chunk-WRRJ4GG2.js → chunk-QYGO5EE2.js} +2 -2
  21. package/dist/chunks/{chunk-RBGOMK4Y.js → chunk-T72N74ZT.js} +2 -2
  22. package/dist/chunks/{chunk-MEEFGWTM.js → chunk-TC6MZAO3.js} +84 -9
  23. package/dist/chunks/{chunk-OCU4RLHC.js → chunk-VPUTVEMC.js} +98 -34
  24. package/dist/chunks/{chunk-PRHJGPMA.js → chunk-VPXOPQJI.js} +2 -2
  25. package/dist/chunks/{chunk-NHA62QD7.js → chunk-WXFPWCXG.js} +3 -3
  26. package/dist/chunks/{chunk-2FLWXFVS.js → chunk-XMGSYD6S.js} +4 -4
  27. package/dist/chunks/{conflict-SFNEVJY5.js → conflict-JAB2LJEZ.js} +2 -2
  28. package/dist/chunks/contract-XI2EEIZU.js +9110 -0
  29. package/dist/chunks/{cowork-CKWYHXYB.js → cowork-SCPGLBA4.js} +44 -25
  30. package/dist/chunks/{ebuilder-form-KOLJRVZD.js → ebuilder-form-EYLHNOTA.js} +3 -3
  31. package/dist/chunks/{ehr-WFOC3B4D.js → ehr-EAP77IMT.js} +172 -9
  32. package/dist/chunks/{esb-LJZTN663.js → esb-2TGGXEE7.js} +4 -4
  33. package/dist/chunks/{fna-F7QRIIZC.js → fna-2X7ZE7BU.js} +13 -8
  34. package/dist/chunks/{host-VQ6JJXGQ.js → host-C6EL2RKL.js} +3 -3
  35. package/dist/chunks/{host-BCGUVEWX.js → host-I4NRK4MX.js} +3 -3
  36. package/dist/chunks/{host-DGE2TZD4.js → host-Q4LZGCRU.js} +3 -3
  37. package/dist/chunks/{host-BQBRHVR3.js → host-UEI5FGDM.js} +3 -3
  38. package/dist/chunks/{host-KXPTEWFS.js → host-XCLDDXKQ.js} +3 -3
  39. package/dist/chunks/{hrm-NI6XAKW5.js → hrm-YXERJM76.js} +3 -3
  40. package/dist/chunks/{im-7TRTF3KT.js → im-A4VZN2TQ.js} +3 -3
  41. package/dist/chunks/{invoice-AOXWJKYT.js → invoice-2Z6YPMIS.js} +3 -3
  42. package/dist/chunks/{jiuchuanhui-7NQWEZAW.js → jiuchuanhui-AR5GMKZB.js} +2 -2
  43. package/dist/chunks/{lazy-dispatch-RNS4EE4S.js → lazy-dispatch-QXW7P4X3.js} +4 -4
  44. package/dist/chunks/{mail-VDHJAB4O.js → mail-7GZ6CPBJ.js} +44 -23
  45. package/dist/chunks/{meeting-GA7XCNNP.js → meeting-3NMGA3MB.js} +74 -10
  46. package/dist/chunks/{okr-TQIRERPQ.js → okr-BZ6XUOAG.js} +2 -2
  47. package/dist/chunks/{plan-4RY4LN2P.js → plan-DR5CMUYP.js} +2 -2
  48. package/dist/chunks/{project-D6XT2OC5.js → project-6J63MK33.js} +2 -2
  49. package/dist/chunks/{registry-JHRIDQ3A.js → registry-KDD7DHNK.js} +4 -4
  50. package/dist/chunks/{registry-VOGKFFTR.js → registry-TKX2E7C7.js} +2 -2
  51. package/dist/chunks/{registry-QKMI43Q6.js → registry-VRTNC6UR.js} +8 -8
  52. package/dist/chunks/{room-recommend-D4EUOOWY.js → room-recommend-XCWRMB5P.js} +4 -4
  53. package/dist/chunks/{schedule-XPFBHPCV.js → schedule-IVBICP32.js} +4 -4
  54. package/dist/chunks/{workflow-HLBZRWIY.js → workflow-D74NFK3C.js} +11 -4
  55. package/dist/index.js +31 -26
  56. package/dist/internal/e10/fetch-timing.js +31 -0
  57. package/dist/internal/e10/request-runtime.js +5 -0
  58. package/dist/shortcuts/cowork/host.js +8 -0
  59. package/dist/shortcuts/cowork/operations/types.js +17 -2
  60. package/dist/shortcuts/ehr/operations/recruit-write.js +35 -0
  61. package/dist/shortcuts/ehr/operations/recruit.js +147 -0
  62. package/dist/shortcuts/fna/operations/expense-chart.js +19 -7
  63. package/dist/shortcuts/index.js +5 -0
  64. package/dist/shortcuts/mail/host.js +8 -0
  65. package/dist/shortcuts/mail/operations/types.js +17 -2
  66. package/dist/shortcuts/meeting/index.js +79 -1
  67. package/dist/shortcuts/meeting/manifest.js +10 -0
  68. package/dist/shortcuts/meeting/operations/eb/catalog.js +5 -0
  69. package/dist/shortcuts/meeting/operations/eb/conflict.js +6 -1
  70. package/dist/shortcuts/meeting/operations/eb/create-flow.js +1047 -134
  71. package/dist/shortcuts/meeting/operations/eb/factory.js +101 -7
  72. package/dist/shortcuts/meeting/operations/eb/room-recommend.js +36 -2
  73. package/dist/shortcuts/meeting/operations/eb-fallback.js +4 -0
  74. package/dist/shortcuts/meeting/operations/env.js +6 -0
  75. package/dist/shortcuts/meeting/operations/invitation.js +79 -20
  76. package/dist/shortcuts/workflow/endpoints.js +8 -3
  77. package/dist/shortcuts/workflow/operations/form.js +181 -34
  78. package/dist/shortcuts/workflow/operations.js +23 -1
  79. package/docs/ehr.md +1 -1
  80. package/docs/fna.md +2 -1
  81. package/package.json +1 -1
  82. package/skill-template/business-info.json +18 -0
  83. package/skill-template/domains/cowork.md +14 -0
  84. package/skills/weaver-e10-cowork/SKILL.md +101 -0
  85. package/skills/weaver-e10-cowork/references/cowork-read.md +90 -0
  86. package/skills/weaver-e10-cowork/references/cowork-write.md +131 -0
  87. package/skills/weaver-e10-cowork/references/safety-boundaries.md +45 -0
  88. package/skills/weaver-e10-jucailin/SKILL.md +21 -3
  89. package/skills/weaver-e10-jucailin/references/recruit-read.md +25 -0
  90. package/skills/weaver-e10-jucailin/references/recruit-write.md +13 -0
  91. package/skills/weaver-e10-jucailin/references/salary.md +15 -11
  92. package/skills/weaver-e10-mail/SKILL.md +12 -9
  93. package/skills/weaver-e10-meeting/SKILL.md +284 -34
  94. package/skills/weaver-e10-meeting/references/meeting-eb.md +131 -0
  95. package/skills/weaver-e10-meeting/references/meeting-invitation.md +28 -2
  96. package/skills/weaver-e10-meeting.zip +0 -0
  97. package/skills/weaver-e10-qiyecheng/SKILL.md +5 -2
  98. package/skills/weaver-e10-qiyecheng/references/catalog.md +2 -2
  99. package/skills/weaver-e10-qiyecheng/references/expense-chart.md +15 -1
  100. package/skills/weaver-e10-qiyecheng/references/source-manifest.json +22 -21
@@ -3,9 +3,9 @@ name: weaver-e10-meeting
3
3
  display_name: 泛微E10会议管理
4
4
  display_name_en: Weaver E10 Meeting Management
5
5
  description: "泛微 E10 会议管理:查会议、预约建会(推荐会议室、查冲突与空闲时段)、改期/改地点/改参会人、取消删除、流程建会、会议室查询与推荐、生成邀请函、读取会议附件、回执签到、纪要与决议任务、参会二维码。详见 description_zh。"
6
- description_zh: "泛微 E10 会议管理,帮您处理会议日常事务:[会议]-查询今天/本周/我的会议与会议详情,预约建会(自动推荐会议室、检测参会人会议冲突与日程空闲、冲突时给出当天可选时段),改期/换地点/改参会人、取消、删除;受限环境可走审批流程建会并自动出邀请函;[会议室]-查询会议室与占用,按人数/设备/常用程度智能推荐;[邀请函]-按会议真实数据生成邀请函文档;[资料]-读取会议与议题的附件、抽取文档正文;参会回执、签到与补签、纪要、议题、决议与决议任务;[二维码]-把文本渲染成参会码/签到码图片。认证与会话由 weaver-e10-shared 提供。"
6
+ description_zh: "泛微 E10 会议管理,帮您处理会议日常事务:[会议]-查询今天/本周/我的会议与会议详情,预约建会(自动推荐会议室、检测参会人会议冲突与日程空闲、冲突时给出当天可选时段),改期/换地点/改参会人、取消、删除;受限环境可走审批流程建会,提交后必出邀请函;[会议室]-查询会议室与占用,按人数/设备/常用程度智能推荐;[邀请函]-生成邀请函文档(有会议 id 用真实数据;没有也能按会议名+时间出预置函);[资料]-读取会议与议题的附件、抽取文档正文;参会回执、签到与补签、纪要、议题、决议与决议任务;[二维码]-把文本渲染成参会码/签到码图片。认证与会话由 weaver-e10-shared 提供。"
7
7
  description_en: "Weaver E10 meeting management: [Meetings] query today/week/my meetings and details, book meetings with automatic room recommendation, attendee conflict and calendar-availability checks (plus same-day alternative slots), reschedule / change room / change attendees, cancel, delete; flow-based booking with automatic invitation when the app only allows workflow creation; [Rooms] occupancy queries and smart recommendation by capacity, equipment and personal usage; [Invitation] generate invitation docx from real meeting data; [Content] list and read meeting/topic attachments and extract document text; receipts, sign-in, minutes, topics, decisions and decision tasks; [QR] render text into attendee/sign-in QR images. Auth and session are provided by weaver-e10-shared."
8
- version: 2.21.0
8
+ version: 2.39.2
9
9
  author: 泛微网络科技股份有限公司
10
10
  agent_created: true
11
11
  requires:
@@ -25,6 +25,92 @@ cliHelp: "weaver-work-cli meeting --help"
25
25
 
26
26
  本 Skill 通过 `weaver-work-cli meeting` 命令调用真实 operation,不绕过 CLI 直接拼接口。
27
27
 
28
+ ## ⛔ 建会动手前必读(照着做,别自己发挥)
29
+
30
+ 用户说「帮我约个会 / 预约明天和 XX 开会」时,**先按这个顺序做,不要一上来就问一堆**:
31
+
32
+ 0. **不确定 CLI 有没有某个能力 → `weaver-work-cli meeting ops`(纯文本)**,查具体能力用
33
+ `meeting ops --grep 关键词`(如 `--grep suggest`、`--grep 建会`)。
34
+ ⛔ **不准用 `meeting schema --json` 判断能力存在性**:完整 308KB、stdout 只回 20KB 预览,
35
+ `operations` 数组被截到前 10 条,排在后面的能力一定看不到;⛔ 更不准凭印象回用户"当前版本没有这个能力"
36
+ (2026-10-30 真机事故:据此说"没有建会建议时间操作",而 `meeting.eb.meeting.create.suggest` 一直存在)。
37
+
38
+ 0.5 **⛔ 时间和会议室只能由用户拍板,不许替他决定(2026-10-30 用户投诉「智能体自己就决定了」)**
39
+
40
+ CLI 用两个标记区分「用户确认过的」和「你猜的」:**`timeConfirmed` / `roomConfirmed`**。
41
+
42
+ - ✅ **只有这两种情况传 `true`**:
43
+ ① 用户**原话明确**给出了("明天 9 点到 10 点"、"用 502 茶室");
44
+ ② 用户**在选项里点选**后,把 `options[].value` **整体原样回传**(value 里自带该标记,别手动拼)。
45
+ - ⛔ **其他一切情况都不传**:用户只说"明天/上午/下午"、你从上下文推断、你觉得 9 点最合适、
46
+ 你觉得这间房最合适 —— **一律不传**。
47
+ 不传时**即使你填了** `begin_datetime` / `address`,CLI 也不会当成已定,而是返回时段/房间选项让用户点选。
48
+ - ⛔ **禁止把候选写成定论**。`NEEDS_SELECTION` 返回的 `options` 是**候选**,不是已选:
49
+ 不许说「时间:09:00–10:00」「地点:测试会议室1」这种既定语气,
50
+ 要问「这几个时段您选哪个」「这几间会议室您用哪间」。
51
+ - ⛔ **禁止绕过**:不许先自己调 `room.list` / `room.recommend` 挑一间,再带 `roomConfirmed: true` 硬塞;
52
+ 也不许因为"懒得再多问一轮"就直接传标记。用户没说过,就是没说过。
53
+
54
+ 1. **确认顺序固定:名称 → 时间 → 参会人 → 地点 → 流程(2026-10-30 用户明确纠正)**。
55
+ 流程只是审批载体,**不许在四要素定下来之前就问"用哪条流程"**。CLI 也是这个顺序:
56
+ 时间没确认先回 `slot`,地点没确认再回 `room`,四个都定了才回 `flow`;
57
+ `flow` 的 `options[].value` 里已带 `begin_datetime`/`end_datetime`/`address` 和两个确认标记,
58
+ 用户点选流程后**原样回传 value** 就直接进确认,不要再问一遍时间/地点。
59
+
60
+ 2. **没给具体几点 → 直接走 ① 的 `prepare` 且不传 `begin_datetime`**,它会返回「所有参会人空闲 **且**
61
+ 该时段有可用会议室」的时段选项,直接做成选项让用户挑;禁止问"安排在几点"。
62
+ 只有"只想看空闲、还不建会"时才单独调 `meeting.eb.meeting.create.suggest`。
63
+ - 每个时段选项的 `reason` 会写明「N 人全部空闲(会议回执 + 日程已核);M 间会议室可用:…」——
64
+ 这就是"人和房都空闲"的凭据,`options[].rooms` 是该时段真实的可用房间清单。
65
+ - ⚠️ 没传参会人时无法核验人是否空闲(只有房间),`warnings` 会说明,要如实转达;
66
+ 姓名查不到员工 id 的人也会单独列出"未核验",别当成"已确认空闲"。
67
+
68
+ 3. **没指定会议室 → 不要"问",要"给选项"**。`suggest` 返回里的 `rooms`、`prepare` 返回里的
69
+ `roomOptions` / `options` 自带候选(已按人数/常用/时段占用排序,默认 3 个)。
70
+ - ⛔ **禁止开放式提问**:不要说「会议地点是必填项,需要你指定一间 / 你想用哪间会议室」——
71
+ 这是把选择题变成填空题,等于没推荐(2026-10-30 真机:agent 自己另拉 `room.list` 列了 10 间,
72
+ 用户反馈"没有弹窗让我选择,直接输出中给到,不方便")。
73
+ - ✅ **必须做成选项控件**:`options[].label` 作标题、`reason` 作副标题,第一个标「推荐」。
74
+ - ⛔ **不要自己再去调 `meeting.eb.room.list` 拼候选** —— 排好序的 `options` 就在返回值里,
75
+ 另拉列表既丢排序又会把不合适(容量不够/已被占用)的房间混进来。
76
+ - 候选为空(该时段全被占用)→ 给「改时段 / 线上会议 / 地点待定」三个选项,仍不要让用户手填房间名。
77
+ 4. **不要问「参会人数」**。CLI 自动算 = `hrm_members` 人数 **+ 召集人自己**(已在上线账号里就不重复加),
78
+ 用于会议室容量过滤;`total_member` / `memberCount` 是可选参数,**只有用户明确说了"几个人"才传**。
79
+ ⛔ 不要自己推算人数、也不要因为"看起来只有 1 个参会人"就降级给人少的房间。
80
+ 5. **不要逐个问必填项**。会议名称没给就从上下文拟一个(如"十一月开发进度沟通会")让用户一次确认;
81
+ 其余缺什么**一次列完问**,禁止"先问人 → 再问类型"这种分轮追问。
82
+ 6. **流程建会不要传 `workflowId`**(自用固化,2026-10-30)。CLI 固定用当前登录环境的**固化流程候选**
83
+ - ⛔ **任何情况下都不要自己往 prepare 里填 `workflowId`**(除非用户原话点名"用 XX 流程")。
84
+ 2026-10-30 真机事故:用户只说"明天上午和易鹏开个会",agent 自己塞了 `workflowId`,
85
+ 于是它在回复里先把流程说死("按会议申请流程发起"),再回来问时间 —— 顺序是它自己弄反的。
86
+ 四要素没定完之前,**回复里连流程名 / 流程 id 都不要提**。
87
+ - 时间/地点闸门的返回里带 `workflowPending: true` = 流程还没定,别把它当成"流程已选好"。
88
+ (泛微生产 = 那两条建会流程),逐个探测"当前账号有没有发起权限",然后按结果分三种走:
89
+ - **只有 1 个有权限 → 直接发起**,不弹窗;`warnings` 会说明"只有 X 有权限,已直接用它"。
90
+ - **两个都有权限 → 返回 `selectionType: 'flow'`,弹窗让用户选**(每个 option 带流程名 + id + 字段清单)。
91
+ ✅ 这一步**一定在时间/地点确认之后**(四要素先定,见规则 1);`options[].value` 已带时间和地点的值,
92
+ **原样回传整个 value**(不是只回传 workflowId)就能直达确认。
93
+ ⛔ 禁止自己替用户挑(2026-10-29 事故:取第一个导致字段全填不进另一条)。
94
+ - **都没有权限 → 报 `flow_not_launchable`「当前账号没有发起建会流程的权限」**:如实告知用户
95
+ 找管理员开通发起权限、或请有权限的同事发起;⛔ 不许改走直连建会绕过流程管控。
96
+ - 用户**已经说过**用哪条流程(如"还是用会议申请流程")→ 直接带那个 `workflowId` 调一次 prepare,
97
+ 跳过这一步。
98
+ - ⛔ 不要因为"想确认用哪条流程"去读 `mt_new_wf` 或检索流程 —— 不传就是正确用法。
99
+ 7. **人 / 地点 / 类型必须走专用入参**(`address` / `hrm_members` / `caller` / `contacter` / `mt_type`),
100
+ 传名称或 id 都行、CLI 会补成 `{id,name}`;塞进 `extraFields` 会被服务端打回「请按名称选择」。
101
+ 8. **凡是 `status: 'NEEDS_SELECTION'`,一律用选项控件呈现,不要写成文本列表**(2026-10-30 用户反馈)。
102
+ CLI 返回的 `options[]` 每项都带 `key` / `label` / `value` / `reason`,`recommended` 是首选:
103
+ - **流程选择**(`selectionType: 'flow'`)→ 弹窗让用户选,选项标题用流程名。
104
+ - **会议室选择**(`selectionType: 'room'` / `'room_conflict'`)→ 同上,**默认只 3 个候选**,
105
+ 第一个标「推荐」,副标题写 `reason`(如"可容 10 人 · 有投影 · 你常用")。
106
+ - ⛔ **不要自己另调 `room.list` / `type.list` 拼一份更长的候选** —— 那份没排序、也没做容量与占用过滤,
107
+ 会把不合适(坐不下 / 该时段已被占)的房间混进来;用户真正要的是"你帮我挑好,我点一下"。
108
+ - ⛔ **不要把选项降级成一句话**:「请告诉我你要哪间」「会议地点是必填项,需要你指定一间」
109
+ 都是错的 —— 那是填空题,不是选择。
110
+ - 用户点了某个选项 → 把该 `value`(会议室是 `value.id`)作为对应入参重跑,不要自己猜。
111
+
112
+ 一句话:**能查的别问、能推的别让人填、要选的给选项卡**。让用户面对一堆空输入框 = 这次交互不合格。
113
+
28
114
  ## ⛔ 输出硬性规则(违反即交付不合格)
29
115
 
30
116
  1. **凡是给用户看的对象名称,一律是可点击链接**:会议 / 议题 / 纪要 / 会议室 / 签到 / 决议 的名字,
@@ -73,19 +159,97 @@ cliHelp: "weaver-work-cli meeting --help"
73
159
 
74
160
  ## 高优先级语义
75
161
 
76
- - 「今天的会议 / 下一个会」→ `meeting.list`(`filterDate` 客户端过滤;接口 body 过滤实测不生效,不要现场试 body)。
77
- - 「会议室占用 / 空闲 / 推荐」→ `meeting.room.list`(必须成对传 `beginDate`/`endDate`;`disabled=true` 已占用,不得推荐)。
78
- - 「预约会议 / 建会」→ 先 `meeting.create.prepare`(内部强制冲突检测),用户确认后 `meeting.create.apply`。
79
- - 「改期 / 换会议室 / 改参会人 / 变更会议」→ `meeting.change.prepare` → 确认后 `apply`。CLI 按会议状态**自动分流**:草稿走 `UPDATE`、正常会议走 `CHANGE`;权限由服务端判定并返回原文提示(如"您没有变更权限!"),必须原样转达用户。
80
- - 「取消会议 / 不开了」→ `meeting.cancel.prepare` → 确认后 `apply`。
81
- - 「删除会议记录」→ `meeting.delete.prepare` → 确认后 `apply`。
162
+ - 「今天的会议 / 下一个会」→ `meeting.eb.meeting.list`(`filterDate` 客户端过滤;接口 body 过滤实测不生效,不要现场试 body)。
163
+ - 「会议室占用 / 空闲 / 推荐」→ `meeting.eb.room.recommend`(按人数/常用/时段占用排序,带理由);
164
+ 只想看全部房间用 `meeting.eb.room.list`(`statusText=正常` 才是可用)。
165
+ - **⛔ 建会只走这三步,不要再加任何前置查询(不要查 baseSet、不要查 schema、不要先查会议室/冲突)**:
166
+ ```bash
167
+ # ① 预检:按「时间候选 → 会议室候选 → 冲突 → 流程」的顺序逐关推进,全部确认后才给确认摘要(不提交)
168
+ # 用户没说具体几点、没说哪间房 → **两个都不传**(连 begin_datetime 都不要填),
169
+ # CLI 自己返回「人空闲+会议室空闲」的时段选项;不用先调 suggest。
170
+ weaver-work-cli --json meeting run meeting.eb.meeting.create.flow.prepare \
171
+ --input-json '{"mt_name":"十一月开发进度沟通会","dateFrom":"2026-10-31","hrm_members":"<id,id>","mt_type":"<类型名>"}'
172
+
173
+ # 用户**明确**说了时间/房间(或刚在选项里点选过)→ 带上确认标记,一次通过:
174
+ weaver-work-cli --json meeting run meeting.eb.meeting.create.flow.prepare \
175
+ --input-json '{"mt_name":"十一月开发进度沟通会","begin_datetime":"2026-10-31 10:00","end_datetime":"2026-10-31 11:00","timeConfirmed":true,"address":"<房间 id>","roomConfirmed":true,"hrm_members":"<id,id>","mt_type":"<类型名>"}'
176
+ # ⛔ 没带 timeConfirmed / roomConfirmed 时,即使上面填了时间/房间,CLI 也不会当成已定,
177
+ # 会返回选项让用户点选 —— 这是故意设计的,别以为"填了就能过"。
178
+ # → status=NEEDS_SELECTION:selectionType 分四类,一律用选项控件让用户点
179
+ # slot = 没给 / 没确认 → 给时段选项,value 已带 begin_datetime/end_datetime/address/timeConfirmed,原样带回重跑 ①
180
+ # room = 没指定 / 没确认 → 房间选项(第一个带「推荐」;你传入的那间会标「(你指定的,待确认)」)
181
+ # room_conflict = **已确认**的房间被占 → 改空闲房间或改时段
182
+ # room_unavailable= 该时段无可用房间 → 改时段 / 线上会议 / 地点待定
183
+ # flow = **最后一步**:名称/时间/参会人/地点都确认了,两个建会流程**都有**发起权限 → 让用户选
184
+ # (只有 1 个有权限时 CLI 直接发起;都没有权限则报 flow_not_launchable)
185
+ # ✅ **顺序是「先四要素、最后选流程」**(2026-10-30 用户明确纠正):
186
+ # 时间没确认 → 先回 slot;地点没确认 → 再回 room;都定了才轮到 flow。
187
+ # 本轮返回里的 `confirmed` 就是已确认的四要素;`options[].value` 已带上
188
+ # begin/end/address + timeConfirmed/roomConfirmed —— 用户点选流程后
189
+ # **原样回传 value** 即直达 AWAITING_CONFIRMATION,不要再问一遍时间/地点。
190
+ # ⛔ 这几类回来时都**不是**"已定方案":不许把 options[0] 写进确认摘要当结论,必须先让用户点。
191
+ # → status=AWAITING_CONFIRMATION:这时时间和房间都已由用户确认过,拿到 continuation,给用户看摘要后进 ②
192
+
193
+ # ② 提交(confirm 必须 true;continuation 10 分钟内有效,别中间插别的调用拖过期)
194
+ weaver-work-cli --json meeting run meeting.eb.meeting.create.flow.apply \
195
+ --input-json '{"continuation":"<上一步的>","confirm":true,"waitSeconds":20}'
196
+ ```
197
+ - **不要**先 `meeting.eb.baseSet.get`:流程候选由 `prepare` 内部算(固化流程优先,未命中才回落 `mt_new_wf`),
198
+ 流程建会任何时候都允许;只有它返回 `conflict_rejected`(说明该环境反而禁流程)才改用
199
+ `meeting.eb.meeting.create.quick` 直连。
200
+ - **不要**为了确认参数去翻 `meeting schema` —— 上面三条命令的字段就是全部,照抄即可;
201
+ 真不够时用 `extraFields`(只放租户自建文本字段)。
202
+ - **⛔ 判断"CLI 有没有某能力"只看 `weaver-work-cli meeting ops`(纯文本、不压缩)**,
203
+ 绝不能用 `meeting schema --json` 的输出来下结论 —— 它完整 308KB、stdout 只回 20KB 预览,
204
+ `operations` 数组被截到前 10 条,**排在后面的能力一定看不到**(2026-10-30 真机事故:
205
+ 据此回复用户"当前 CLI 版本没有建会建议时间操作",实际 `meeting.eb.meeting.create.suggest` 一直存在)。
206
+ 查具体能力:`meeting ops --grep 关键词`(如 `--grep suggest` / `--grep 建会`)。
207
+ - **连时间都没给**:`begin_datetime` 可以不传,`prepare` 会直接返回 `selectionType: 'slot'` 的 3 个时段
208
+ (已按参会人空闲 + 会议室空闲挑过,`options[].value` 里带 `begin_datetime`/`end_datetime`/`address`),
209
+ 把 value 原样带回重跑 ① 即可 —— **一轮**就能把"时间+会议室"一起定下来。
210
+ - **字段是按 datakey 填的**:中文名匹配已做归一化(`开始时间(具体开始时间)` 能命中「开始时间」),
211
+ 解析出的「语义键 → 表单 datakey」缓存在 `~/.weaver-work-cli/meeting/cache/flow-fields-<workflowId>.json`,
212
+ 之后直接用 datakey,字段改名也不影响。要绕过名字匹配直接给值就用 `fieldValues`(键 = datakey):
213
+ `{"fieldValues":{"1325677252711735872":"十一月开发进度沟通会"}}`,
214
+ datakey 从 `preview.fieldMapping`(形如 `会议名称(请填写…)(1325677252711735872)`)里取。
215
+ - **⛔ 用户只说了"明天/下周三"、没给具体几点时,禁止弹空输入框让他自己填时间** —— 两条路都行:
216
+ **建会就走上面 ①(`prepare` 不传 `begin_datetime`,一步拿到时段选项)**,这是首选;
217
+ 只有用户"只想看看哪天有空、还不想建会"时,才单独调 `meeting.eb.meeting.create.suggest`(它确实存在):
218
+ ```bash
219
+ weaver-work-cli --json meeting run meeting.eb.meeting.create.suggest \
220
+ --input-json '{"dateFrom":"2026-10-31","hrm_members":"易鹏","durationMinutes":60,"maxSlots":3}'
221
+ ```
222
+ 返回的每个候选都是「**所有参会人都空闲**(会议回执 + 日程都核对过)**且该时段有会议室可用**」:
223
+ ```
224
+ T1 10-31 09:00~10:00 3 间会议室可用:测试会议室1、xxx
225
+ T2 10-31 10:00~11:00 2 间会议室可用:…
226
+ ```
227
+ 把 `label` 做成选项让用户挑一个(`value.begin/end/address` 直接可回填),选定后带时间走 prepare。
228
+ - 没候选时它会说明原因(人没共同空闲 / 人空闲但订不到会议室),**如实转达**,别自己编一个时间;
229
+ - 用户说了"上午/下午"这种粗粒度,也走它(`workStartHour`/`workEndHour` 约束),不要直接默认 9 点。
230
+ - ⛔ 这个操作调不通(返回 `unknown operation`)时**先跑 `meeting ops --grep suggest` 自查**,
231
+ 确认 CLI 装的是不是最新版;**不要**直接对用户说"没有这个能力" —— 建会主链路本来就不需要它。
232
+ - ⛔ **仅限「会议建会」这一件事:不要自己手搓 `workflow.*`**
233
+ (`workflow.search` / `workflow.createForm` / `workflow.createRequestDirect`)。
234
+ 会议建会流程由 `meeting.eb.meeting.create.flow.*` 内部处理(它自己也调 `workflow.createForm`),
235
+ 你手搓一遍只会拿到一张裸表单,丢掉字段映射、会议室联动、冲突检测、邀请函。
236
+ ✅ **其它流程照常用 workflow 模块** —— 请假、报销、待办、审批、流程查询等,
237
+ 那是 `weaver-e10-workflow` 的地盘,本 skill 不管、也不禁止。别因为这条就不敢用 workflow。
238
+ ⛔ **也不要为了"确定用哪个流程"去检索、或读 `mt_new_wf` 再自己挑一个**:不传 `workflowId` 就是正确用法。
239
+ ⛔ 直连 `create.prepare/quick` 在 `only_flow_create=1` 时会抛 `conflict_rejected`(应用管控,CLI 不绕过),
240
+ 所以**不要用它去"试试看"** —— 按上面第一行先判断,省一次白跑的调用。
241
+ - **⛔ 不要主动调 `meeting.env.detect`**:默认就是 EB,直接调 `meeting.eb.*` 即可。
242
+ 只有用户明确问"这是 EB 版还是标准版"时才 detect(且要带 `refresh: true` 实探,别读缓存)。
243
+ - 「改期 / 换会议室 / 改参会人 / 变更会议」→ `meeting.eb.meeting.change.prepare` → 确认后 `apply`。CLI 按会议状态**自动分流**:草稿走 `UPDATE`、正常会议走 `CHANGE`;权限由服务端判定并返回原文提示(如"您没有变更权限!"),必须原样转达用户。
244
+ - 「取消会议 / 不开了」→ `meeting.eb.meeting.change.prepare`(`operate_type=CANCEL`、`mt_status=4`)→ 确认后 `apply`。
245
+ - 「删除会议记录」→ `meeting.eb.meeting.delete.prepare` → 确认后 `apply`。
82
246
  - 「提前结束会议」→ **CLI 不支持**(服务端 `overMeeting` 为空实现,调用会假成功但不生效),如实告知用户并建议在系统页面操作。
83
- - 「回执为否 / 请假」→ `meeting.receipt.update.prepare`(自动回查回执记录 id)→ 确认后 `apply`。
84
- - 「签到情况」→ `meeting.sign.list`(输出已签/未签统计;其 `signs[].id` 是**签到记录 id**,补签/清除要用它,不是会议 id)。
85
- - 「补签 / 帮他补上签到」→ 先 `meeting.sign.list` 定位记录 → `meeting.sign.mark.prepare` → 确认后 `apply`;「补签退」用 `meeting.sign.back.prepare`。二者会改写签到事实,必须用户明确确认。
86
- - 「清除签到记录 / 撤销签到」→ `meeting.sign.clear.prepare` → 确认后 `apply`。
247
+ - 「回执为否 / 请假」→ `meeting.eb.receipt.list` 定位记录 → `meeting.eb.receipt.update.prepare` → 确认后 `apply`。
248
+ - 「签到情况」→ `meeting.eb.sign.list`(输出已签/未签统计;其 `signs[].id` 是**签到记录 id**,补签/清除要用它,不是会议 id)。
249
+ - 「补签 / 帮他补上签到」→ 先 `meeting.eb.sign.list` 定位记录 → `meeting.eb.sign.mark`(走更新,**禁止用 `sign.create`**);二者会改写签到事实,必须用户明确确认。
250
+ - 「清除签到记录 / 撤销签到」→ `meeting.eb.sign.clear.prepare` → 确认后 `apply`。
87
251
  - 「我要签到 / 扫码签到」→ **CLI 不支持**(依赖现场二维码票据 qrticket 与设备 IP),引导用户现场扫码或走 H5 签到;**绝不代签**。
88
- - **默认就走 EB operations**(见「命令表(EB 版)」),不必先判断环境:今天的会议 → `meeting.eb.meeting.list`(先 count 再 list);建会 → 先读 `meeting.eb.baseSet.get` 判断是否需走流程,再 `meeting.eb.meeting.create.prepare`(**prepare 内部自动执行会议室/参会人冲突检测**:命中禁止提交 → `conflict_rejected` 直接停止;**仅提醒也会拦下来** —— 见下面「建会的四条护栏」,必须让用户拍板,不能自己决定继续);变更/取消 → `meeting.eb.meeting.change.prepare`(取消用 `operate_type=CANCEL`、`mt_status=4`);签到 → `meeting.eb.sign.list`;回执 → `meeting.eb.receipt.list`;纪要 → `meeting.eb.minute.list`;议题 → `meeting.eb.topic.list`;**补签 → `meeting.eb.sign.mark`(走更新,禁止用 `sign.create`)**;**会议决议 → `meeting.eb.decision.publish`(写决议 + 自动把会议标为已决议,一步到位,勿拆成两步)**;决议任务 → `meeting.eb.decisionTask.list` / `.update`;**改决议 → `meeting.eb.decision.update`**(改明细默认是追加,整组替换传 `detail1Mode:"cover"`)。
252
+ - **其它场景也一律走 EB operations**(见「命令表(EB 版)」),不必先判断环境:变更/取消 → `meeting.eb.meeting.change.prepare`;签到 → `meeting.eb.sign.list`;回执 → `meeting.eb.receipt.list`;纪要 → `meeting.eb.minute.list`;议题 → `meeting.eb.topic.list`;**会议决议 → `meeting.eb.decision.publish`(写决议 + 自动把会议标为已决议,一步到位,勿拆成两步)**;决议任务 → `meeting.eb.decisionTask.list` / `.update`;**改决议 → `meeting.eb.decision.update`**(改明细默认是追加,整组替换传 `detail1Mode:"cover"`)。
89
253
 
90
254
  ## 命令表(标准版:EB 降级后 / 显式指定时使用)
91
255
 
@@ -123,7 +287,7 @@ cliHelp: "weaver-work-cli meeting --help"
123
287
  | --- | --- | --- |
124
288
  | EB 会议列表 / 详情 | `meeting.eb.meeting.list` / `meeting.eb.meeting.detail` | [meeting-eb.md](references/meeting-eb.md) |
125
289
  | EB 建会 / 变更 / 删除 | `meeting.eb.meeting.create.prepare`→`apply` / `meeting.eb.meeting.change.prepare`→`apply` / `meeting.eb.meeting.delete.prepare`→`apply` | [meeting-eb.md](references/meeting-eb.md) |
126
- | EB 会议室列表 / 详情 | `meeting.eb.room.list` / `meeting.eb.room.detail` | [meeting-eb.md](references/meeting-eb.md) |
290
+ | EB 会议室列表 / 详情(`room_name` 可按名称查,部分词自动模糊兜底) | `meeting.eb.room.list` / `meeting.eb.room.detail` | [meeting-eb.md](references/meeting-eb.md) |
127
291
  | EB 会议室新建 / 更新 / 删除 | `meeting.eb.room.create` / `.update` / `.delete`(各 prepare→apply) | [meeting-eb.md](references/meeting-eb.md) |
128
292
  | EB 会议室占用列表 / 详情 | `meeting.eb.roomUsage.list` / `.detail` | [meeting-eb.md](references/meeting-eb.md) |
129
293
  | EB 占用新建 / 删除 | `meeting.eb.roomUsage.create` / `.delete`(prepare→apply) | [meeting-eb.md](references/meeting-eb.md) |
@@ -137,7 +301,7 @@ cliHelp: "weaver-work-cli meeting --help"
137
301
  | EB 议题类型列表 / 详情 / 更新 / 删除 | `meeting.eb.topicType.list` / `.detail` / `.update` / `.delete` | [meeting-eb.md](references/meeting-eb.md) |
138
302
  | **EB 创建议题**(`create_mt_topic`,必填 `topic_title`;挂会议传 `mt_id`) | **`meeting.eb.topic.create.prepare` → `apply`** | [meeting-eb.md](references/meeting-eb.md) |
139
303
  | EB 会议议题列表 / 详情 / 更新 / 删除 | `meeting.eb.topic.list` / `.detail` / `.update` / `.delete` | [meeting-eb.md](references/meeting-eb.md) |
140
- | EB 应用设置(`only_flow_create`/`open_mt_approve` 建会闸门与冲突策略的依据) | `meeting.eb.baseSet.get` | [meeting-eb.md](references/meeting-eb.md) |
304
+ | EB 应用设置(`only_flow_create`/`open_mt_approve` 建会闸门与冲突策略的依据)。**建会时不需要先查它** —— `create.flow.prepare` 内部会读;只在用户问"我们建会要不要走审批"时单独查 | `meeting.eb.baseSet.get` | [meeting-eb.md](references/meeting-eb.md) |
141
305
  | **EB 发布会议决议**(写决议 + 自动把会议标为已决议) | **`meeting.eb.decision.publish.prepare` → `apply`** | [meeting-eb.md](references/meeting-eb.md) |
142
306
  | EB 决议列表 / 详情 / 删除 | `meeting.eb.decision.list` / `.detail` / `.delete.prepare` → `apply` | [meeting-eb.md](references/meeting-eb.md) |
143
307
  | **EB 更新决议**(改概述文本;改明细默认是**追加**,要整组替换传 `detail1Mode:"cover"`;不会同步到已生成任务) | **`meeting.eb.decision.update.prepare` → `apply`** | [meeting-eb.md](references/meeting-eb.md) |
@@ -149,12 +313,13 @@ cliHelp: "weaver-work-cli meeting --help"
149
313
  | EB 补签 / 补签退(自动定位签到记录,走更新) | `meeting.eb.sign.mark.prepare` → `apply` | [meeting-eb.md](references/meeting-eb.md) |
150
314
  | EB 会议室 / 参会人冲突检测(只查不建) | `meeting.eb.conflict.room` / `.member` | [meeting-eb.md](references/meeting-eb.md) |
151
315
  | EB 详情页链接(会议/会议室/占用/签到/回执/纪要/议题/设置) | `meeting.link`(按 `type` 解析 objid 并缓存) | [meeting-eb.md](references/meeting-eb.md) |
152
- | **按会议真实数据生成邀请函 docx**(只生成、不发送;有议题自动填议程表) | **`meeting.invitation.render`** | [meeting-invitation.md](references/meeting-invitation.md) |
316
+ | **生成邀请函 docx**(只生成、不发送;有议题自动填议程表。**有 mtId 用会议真实数据;没有 mtId 传 mt_name+begin_datetime 也能出预置函**) | **`meeting.invitation.render`** | [meeting-invitation.md](references/meeting-invitation.md) |
153
317
  | **文本 → 二维码图片**(参会码/签到码/链接码;PNG/SVG,本地零依赖、离线可出图) | **`meeting.qrcode.render`** | 见下「二维码生成」 |
154
318
  | **参会人日程空闲**(查**日程应用**,不是会议表;自动过滤「会议日程」类型,id 动态解析不写死) | **`meeting.eb.schedule.free`** | 见下「日程空闲与会议室推荐」 |
155
319
  | **会议室推荐**(人数 + 地点/设备/类型要求 + 个人常用 + 时段占用;会议室/常用走缓存,占用实时查) | **`meeting.eb.room.recommend`** | 见下「日程空闲与会议室推荐」 |
156
- | **流程建会**(应用设置「只允许流程新建会议」时必须走这条;提交后自动出邀请函) | **`meeting.eb.meeting.create.flow.prepare` → `apply`** | 见下「流程建会」 |
157
- | **一步建会**(prepare+apply 合并,一次调用建完并出邀请函;多流程/需选择时自动退回选项) | **`meeting.eb.meeting.create.flow.quick`** | 见下「流程建会」 |
320
+ | **流程建会**(应用设置「只允许流程新建会议」时必须走这条;**提交完必出邀请函**——命中会议出完整版,审批中出预置版) | **`meeting.eb.meeting.create.flow.prepare` → `apply`** | 见下「流程建会」 |
321
+ | **推荐时间**(只看空闲、**还不建会**时用;建会直接在 ① 里不传 `begin_datetime`,不用它) | **`meeting.eb.meeting.create.suggest`** | 见下「流程建会」 |
322
+ | **一步建会**(prepare+apply 合并;同样必出邀请函,多流程/需选择时自动退回选项) | **`meeting.eb.meeting.create.flow.quick`** | 见下「流程建会」 |
158
323
  | **找所有人共同空闲的时段**(冲突时给可选项,别只说"撞了") | **`meeting.eb.conflict.availability`** | 见下「冲突了要给出可选项」 |
159
324
  | **上传本地文件拿附件 id**(给纪要 `doc_file`/`video_file` 用;秒传 + 超时自动复核) | **`meeting.attachment.upload`** | [meeting-minute-file.md](references/meeting-minute-file.md) |
160
325
  | **查附件清单拿 fileId**(会议附件 `mt_accessorys`、项目文件 `project_files`、议题资料 `related_materials`) | **`meeting.attachment.list`** | 见下「读附件内容」 |
@@ -194,6 +359,32 @@ cliHelp: "weaver-work-cli meeting --help"
194
359
  | **你指定了会议室** | **照样查它在该时段是否被占用**;被占用就拦下不提交,并给出替代候选 | `room_conflict` |
195
360
  | **没指定会议室** | 按人数/常用度/时段占用推荐空闲房间,交用户挑 | `room` |
196
361
  | **没指定且推荐不出** | 拦下,给三条出路(指定房间 / 线上会 / 地点待定) | `room_unavailable` |
362
+ - **选房阶段就能看到时间冲不冲突**:`selectionType: room` / `room_unavailable` 的返回里同样带
363
+ `memberConflicts`(会议冲突)和 `suggestedSlots`(全员空闲时段)—— prepare 是**并行算完才返回**的。
364
+ 所以"先让用户选房、选完再说时间撞了"是错的,**必须先告诉他时间冲不冲突,再让他选房**。
365
+ - **⛔ 看 `enrichFailures` 判断"到底查没查"**:返回里这个字段非空 = 某项增强检测**没跑成功**
366
+ (会议室推荐 / 会议室占用 / 参会人会议冲突 / 参会人日程空闲)。此时**绝对不能说"时间已确认空闲"**,
367
+ 没证据。正确说法:"这项没核验到(原因 X)",并原样转达原因。
368
+ 以前这些失败被 `.catch(() => null)` 静默吞掉,"没查"和"没冲突"长得一模一样,用户以为查过了
369
+ (2026-10-30 真机事故:会议室查不到卡在选房 → 冲突检测没跑 → 却答复"流程表单本身不做冲突检测")。
370
+ - **会议室台账缓存 24 小时,但「建会」链路强制拉最新**:`create.flow.prepare` / `create.flow.quick` /
371
+ `create.suggest` 内部都会强制刷新台账,所以刚导入/新建的会议室在建会时一定看得到。
372
+ 只有**纯查询**(`meeting.eb.room.recommend`)会走 24h 缓存(快);缓存超过 4 小时会在 warnings 提示
373
+ "数据可能过时",最近改过会议室就带 `refresh: true` 重查。候选为空时还会自动强制重拉一次
374
+ (`meta.cacheRetried: true`)。
375
+ ⛔ **不要因为"只有 1 间/查不到"就去断言系统里没有会议室** —— 先看 `meta.roomsTotal` 与 `cacheRetried`,
376
+ 必要时让用户跑 `meeting.eb.room.list` 确认真实条数(它**实时查库、不走缓存**)
377
+ (2026-10-30 真机:用户刚导入 100+ 间,纯查询推荐按旧缓存只报 1 间;实际 list 返回 155 间)。
378
+ - **`hrm_members` 要传员工 id**:姓名会被自动反查成 id,但**查不到就原样传下去**,
379
+ `conflict.member` 会报 `hrm_members 必须是数字 id`。用户只给姓名时,先
380
+ `hrm.employee.query --keyword <姓名>` 拿 id 再传。
381
+ - **`schedule.free` 的 `memberIds` 是数组、支持多人**(不是"只能查当前登录人"):
382
+ ```bash
383
+ weaver-work-cli --json meeting run meeting.eb.schedule.free \
384
+ --input-json '{"startDate":"2026-10-31 00:00","endDate":"2026-10-31 23:59","memberIds":["<id1>","<id2>"]}'
385
+ ```
386
+ 它同时核对**会议回执 + 日程应用**,并**自动过滤「会议日程」类型**避免重复计。
387
+ 所以"代查他人日程"可以做,别用"只能查自己"糊弄用户。
197
388
  - ⛔ **不要因为"用户指定了房间"就跳过冲突检测** —— CLI 两个都做,你也别自作主张只在没指定时才查。
198
389
  - 冲突返回里带 `conflicts`(占用明细:哪个会议、几点到几点)+ `options`(按空闲/人数/常用排序的替代房间)。
199
390
  正确反应:把"你指定的 X 在 10:00–11:00 已被占用"和候选一起给用户,**不要自己替他换房**。
@@ -203,30 +394,44 @@ cliHelp: "weaver-work-cli meeting --help"
203
394
  - ⛔ **`meeting.eb.room.list` 返回 0 条 ≠ 这个环境没有会议室**(2026-10-29 真机)。
204
395
  EB 会议室台账(`uf_mt_room_base`)里可能明明有数据 —— 按 id 读 `meeting.eb.room.detail` 读得到、
205
396
  按 objId 直查有行 —— 但列表接口 `query_meeting_room_list` / `query_meeting_room_count` 读不出来
206
- (应用侧视图/接口配置问题)。而表单上的「会议地点」是 Ebuilder 浏览按钮,取数来源取决于租户表单配置,
207
- 未必和台账列表同一条链路。
397
+ (应用侧视图/接口配置问题,2026-10-29 全天为 0 条、10-30 下午租户把「会议室名称」配成传入字段后恢复 155 条)。
398
+ 而表单上的「会议地点」是 Ebuilder 浏览按钮,取数来源取决于租户表单配置,未必和台账列表同一条链路。
208
399
  **所以不得据此断言"无可用会议室"**,正确说法是"会议室列表接口读不到",并给出三条出路:
209
400
  ① 让用户直接在表单「会议地点」里点选;② 沿用历史单据里的会议室(名称或 id);
210
401
  ③ 改线上会议(`allowNoRoom: true`)。
211
402
  **禁止**改用标准版 `meeting.room.list` 拿另一套会议室顶上(EB 环境会被 `env_mismatch` 拒绝)。
403
+ - **按名称查会议室用 `room_name`**(2026-10-30 新增)。服务端只做**精确匹配**:
404
+ `room_name=测试会议室1` → 1 条;传部分词(`测试`/`重庆`)服务端回 0 条 —— 但 CLI 会自动翻页扫全量、
405
+ 在客户端按「包含」重筛,所以**直接传部分词即可拿到模糊结果**(实测 155 条里查"重庆"命中 2 条,约 5 秒)。
406
+ 命中精确名时零额外开销;传 `noFallback:true` 可跳过这次扫描。
407
+ ⚠️ EB 的 `pageSize` 不生效(恒定回 10 条),要全量必须翻页 —— 这正是兜底做的事。
212
408
 
213
409
  ## 处理链:预约会议(高风险写,强制确认链)
214
410
 
215
- 1. **直接按 EB 走,不做前置环境判断**:`meeting.eb.meeting.create.prepare` 会**自行读取应用设置**并执行建会路径闸门(`only_flow_create=1` 或 `open_mt_approve=1` → 直接拒绝 `policy/conflict_rejected`,提示改用 `weaver-e10-workflow` 发起流程;读不到应用设置 → `conflict_check_failed`),**调用方不需要、也不得自行判断后继续建会**;只有返回 `env_fallback` 时才改用标准版 `meeting.create.prepare`(见 `details.standardOperation`);`env_unavailable` → 提示并停止。
411
+ 1. **建会直接进 `create.flow.prepare`,不查前置、不查 baseSet、不查 schema**(2026-10-30:有 agent 在这上面
412
+ 白跑了 6 次调用、90 秒)。`prepare` 内部会读 `mt_new_wf` 与冲突策略;它返回 `policy/conflict_rejected`
413
+ 才说明该环境禁流程建会,此时才改 `meeting.eb.meeting.create.quick` 直连(**不是**去 `weaver-e10-workflow` 手搓流程);
414
+ `env_fallback` 才改用标准版 `meeting.create.prepare`;`env_unavailable` → 提示并停止。
216
415
  2. **流程建会时,流程来源只有一个:应用设置 `mt_new_wf`。**
217
- - **⛔ 禁止用关键词检索流程**(`workflow.search`、`workflow: "会议"` 这类)。配置里已经给了流程 id,
416
+ - **⛔ 会议建会禁止用关键词检索流程**(`workflow.search`、`workflow: "会议"` 这类)。配置里已经给了流程 id,
218
417
  检索既无信息增量,又会把无关流程带进来当结论 —— **真实事故(2026-10-29)**:agent 用关键词「会议」
219
418
  检索出 11 个候选,「会议室预定流程-北方大区业务运营中心」排第一,用户当场质疑"我们配置的流程不包含这个"。
220
419
  配置已给 id 时,任何检索都是错的;只有"用户只说了流程名称、确实没有 id 来源"时才需要澄清。
221
420
  - **`mt_new_wf` 是逗号分隔多值时,禁止默认取第一个**。CLI 会逐个探测可发起性,多个可用就返回
222
421
  `NEEDS_SELECTION`(`options` 带流程名 + 各流程的字段名清单)→ 原样交给用户选。
223
422
  用户说"按上次那张 / 老规矩"时,才去查他的历史发起记录匹配流程名,匹配到就带**单个** `workflowId` 重跑。
224
- - 取表单一律用 `meeting.eb.meeting.create.flow.prepare`(内部按 `mt_new_wf` 调 `workflow.createForm`),
423
+ - 取表单一律用 `meeting.eb.meeting.create.flow.prepare`(内部按固化流程候选、未命中回落 `mt_new_wf` 调 `workflow.createForm`),
225
424
  **不要**自己拼 `workflow.createRequestDirect` / `workflow.createForm`。
226
- 3. **一次性问全,禁止分轮追问**:名称 / 时间(`yyyy-MM-dd HH:mm`)/ 会议室 / 参会人 / 会议类型。
227
- 缺哪几个就**一次把缺的全部列出来问**,不要"先问时间 → 再问人 → 再问房间"。
228
- 每多一轮追问就多一次模型推理(20–40 秒),用户体感"建个会要 2 分钟"基本都是这么来的(实测 CLI 全程只要 3 秒)。
229
- 用户一句话里已经给全的要素**不要再复述确认**,直接进下一步。
425
+ 3. **能自动推的绝不问用户;剩下要问的一次问全**
426
+ - **时间没说具体几点**(只说"明天/下周三/上午")→ **不要问,直接调 ① 的 `prepare` 且不传 `begin_datetime`**,
427
+ 它会返回「所有人都空闲 + 该时段有会议室」的时段选项(带会议室名,`value` 可直接回填)。
428
+ 这是 2026-10-30 用户明确要求的:没填时间就要推荐时间,不许弹空输入框让人手填。
429
+ 只有"只想看空闲、不建会"才单独用 `meeting.eb.meeting.create.suggest`。
430
+ - **会议室没指定** → **不要问,要给选项**(`prepare` 返回的 `options` / `roomOptions`,
431
+ 已排好序)。呈现规则见本节第 2 条:做成选项控件,禁止列成文本 + "需要你指定一间"。
432
+ - 其余真正缺的(会议名称 / 参会人 / 会议类型)**一次列完问**,不要"先问人 → 再问类型"。
433
+ 每多一轮追问就多一次模型推理(20–40 秒),用户体感"建个会要 2 分钟"基本都是这么来的(实测 CLI 全程只要 3 秒)。
434
+ - 用户一句话里已经给全的要素**不要再复述确认**,直接进下一步。
230
435
  4. **不要在 prepare 之前自己先去查会议室/类型/冲突** —— `prepare`/`quick` 内部已并行跑完(见上面「会议室不能默默留空」)。
231
436
  只有要给用户"换房 / 换时段"时才单独查:EB 走 `meeting.eb.room.recommend` / `meeting.eb.room.list` /
232
437
  `meeting.eb.type.list`;只有 `env_fallback` 之后才用标准版 `meeting.room.list` / `meeting.type.list`。
@@ -252,7 +457,17 @@ cliHelp: "weaver-work-cli meeting --help"
252
457
 
253
458
  ## 处理链:生成邀请函 docx(只读,不发送)
254
459
 
255
- 1. 直接走 `meeting.eb.meeting.list` 单查(**默认就是 EB**,不必先判断);只有返回 `env_fallback`(本环境是标准版)时,邀请函所需的 EB 字段取不到,如实告知用户即可。
460
+ **两种用法**(2026-10-30 起):
461
+
462
+ | 场景 | 入参 | 说明 |
463
+ |---|---|---|
464
+ | 会议已生成(有 id) | `mtId` | 按**会议真实数据**生成,字段最全 |
465
+ | 会议还没生成(流程审批中 / 只有申请单信息) | `mt_name` + `begin_datetime`(再补 `end_datetime`/`address`/`hrm_members`/`mt_desc`/`caller`…) | 按**申请单信息**预生成**预置函**,`dataSource=payload` |
466
+
467
+ ⛔ **邀请函本质是「预置函」**:由项目人员下载后自行修改、自行发送。所以**不要因为没有会议 id 就说"生成不了"**——
468
+ 给了 `mt_name` + `begin_datetime` 就能出。取不到的字段渲染成黄色高亮【待补充】,人工补即可。
469
+
470
+ 1. 有会议 id 走 `mtId`;没有就按上表第二种用法直接出,不必等会议生成。
256
471
  2. 定位会议 id:用户给了会议名 → 先用 `meeting.eb.meeting.list`(`mt_name` 模糊)让用户确认,**不要猜 id**。
257
472
  3. 问清「来访客户名称 / 客户单位」,作为 `extra.guest_org` 传入 —— **接口不返回该字段**,不传就会渲染成高亮【待补充】。
258
473
  4. 跑 `meeting.invitation.render`,把 `filePath` 与 `pendingFields` 原样告诉用户;有待补充字段时提示"文档里已黄色高亮标出,请补完再发出"。
@@ -521,7 +736,9 @@ weaver-work-cli --json meeting run meeting.attachment.extract --input-json '{"mt
521
736
  直接念给用户听:"11-10 当天 9:00-18:00 内没有所有人都空闲的 120 分钟时段,张三 09:00~11:30 有会…"。
522
737
  - **选项必须自解释**:`slotOptions` 的 `label` 形如 `11:30~15:30(会议当天) · 全部参会人空闲`(**一定要带"空闲"字样**,否则用户只看到两个时间点,不知道这是推荐还是随便给的);`roomOptions` 带容量与 `· 推荐`;多流程 `options` 带流程名。
523
738
  - **一律用选项**:`roomOptions`(R1/R2/R3)、`slotOptions`(T1/T2/T3)、多流程时 `options`(W1/W2)都带 `key`+`label`+`value`,
524
- 直接做成选择项;选完把 `value` 回填(会议室 `address`、时段改 `begin_datetime/end_datetime`、流程带 `workflowId`)重新 prepare。
739
+ 直接做成选择项;选完把 `value` **整体**回填重新 prepare(时段 value 自带 `timeConfirmed: true`、
740
+ 房间 value 自带 `roomConfirmed: true`,别只挑 `begin_datetime` / `address` 单个字段抄,
741
+ 抄漏标记就会被再问一轮;流程带 `workflowId`)。
525
742
  - 想单独查时段(不建会):
526
743
  `weaver-work-cli --json meeting run meeting.eb.conflict.availability --input-json '{"rangeStart":"2026-10-30 00:00","rangeEnd":"2026-10-30 23:59","durationMinutes":120,"hrmMembers":"<id1>,<id2>"}'`
527
744
 
@@ -559,20 +776,51 @@ weaver-work-cli --json meeting run meeting.attachment.extract --input-json '{"mt
559
776
 
560
777
  应用设置勾了「只允许通过流程新建会议」(`only_flow_create=1`)或「会议提交需审批」
561
778
  (`open_mt_approve=1`)时,**直连 `create_meeting` 会被闸门拒绝**——这是应用管控,CLI 不绕过。
562
- 但这**不是停手**:改走流程即可,链路同样以「出邀请函」收尾。
779
+ 但这**不是停手**:改走流程即可。注意流程建会是**异步**的——提交后要等审批通过、会议真的生成,
780
+ 才有会议 id;**但邀请函不需要等**(见下面「邀请函是预置函」)。
563
781
 
564
782
  ```bash
565
- # ① 准备:按应用设置 mt_new_wf 载入建会流程表单,把会议字段按中文名映射(不提交)
783
+ # ① 准备:算流程候选 + 映射表单字段(不提交)
784
+ # 用户没明确给时间/房间 → 两个都不传,让 CLI 返回选项(见顶部规则 0.5)
785
+ weaver-work-cli --json meeting run meeting.eb.meeting.create.flow.prepare \
786
+ --input-json '{"mt_name":"周会","mt_desc":"排期","total_member":3}'
787
+ # 用户明确给过时间/房间 → 带确认标记
566
788
  weaver-work-cli --json meeting run meeting.eb.meeting.create.flow.prepare \
567
- --input-json '{"mt_name":"周会","begin_datetime":"2026-11-05 14:00","end_datetime":"2026-11-05 15:00","mt_desc":"排期","total_member":3,"address":"<会议室名称(ID)>"}'
789
+ --input-json '{"mt_name":"周会","begin_datetime":"2026-11-05 14:00","end_datetime":"2026-11-05 15:00","timeConfirmed":true,"address":"<会议室id>","roomConfirmed":true,"mt_desc":"排期","total_member":3}'
568
790
 
569
- # ② 提交:确认后提交审批;提交成功后会轮询会议表,会议生成即自动出邀请函
791
+ # ② 提交:确认后提交审批;**无论会议有没有生成,都会出邀请函**
570
792
  weaver-work-cli --json meeting run meeting.eb.meeting.create.flow.apply \
571
793
  --input-json '{"continuation":"<上一步 continuation>","confirm":true,"waitSeconds":20}'
572
794
  ```
573
795
 
796
+ - **✅ 邀请函是「预置函」,提交完必有**(2026-10-30 用户明确要求:项目人员下载后自己改、自己发,
797
+ 不该卡在"会议已生成"之后):
798
+ `apply` 提交后会轮询会议表(默认 20 秒,`waitSeconds` 可调),
799
+ - 命中会议 → `invitation.pending=false` + `filePath`(**完整数据版**);
800
+ - 没命中(多数是还在审批)→ `invitation.pending=true` + `preRendered=true` + `filePath`
801
+ —— 已按**申请单已知信息**预生成了一份,取不到的字段是【待补充】黄色高亮。
802
+ - ⛔ **不管哪种情况都有 `filePath`**。所以:**永远不要说"没有邀请函"**,
803
+ 正确说法是「邀请函已生成(路径 X)——这份是按申请单预生成的,会议还在审批中;
804
+ 审批通过后我可以按真实会议数据再生成一版完整字段的」。
805
+ - **刷新为完整版**:审批通过后 `meeting.eb.meeting.list` 找到该会议 id →
806
+ `meeting.invitation.render --mtId <id>`(只生成、不发送)。
807
+ - ⛔ **不要因为"会议还在审批"就重复 `apply`** —— 会重复建单/重复建会。
808
+ - **小e 环境(返回 `status=BROWSER_FILL`)同样必有邀请函**:这种环境下 `workflow.createRequest`
809
+ **一个写请求都不发**,建会改由宿主浏览器页面填单,因此 apply 拿不到 `requestId` / `meetingId`——
810
+ 这**不是失败**。CLI 会返回 `status=BROWSER_FILL` + `contextId` + `finalMarkdown`(那段 `<browsertool>` 表单)
811
+ + `invitation.filePath`(按申请单预生成的预置函)。正确做法:把 `finalMarkdown` 内容原样作为本轮回复正文
812
+ (从 `<browsertool>` 到 `</browsertool>`、不包代码块),并告诉用户邀请函已生成在哪个路径;
813
+ ⛔ 不要说"流程没提交成功 / 没有邀请函",也不要因为"没有 requestId"重复 `apply`。
574
814
  - 字段按**中文名**匹配(会议名称/开始时间/结束时间/会议内容/会议地点/参会人员/参会人数/召集人/联系人/备注),
575
815
  映射不到的原样进 `warnings` 并列出表单现有字段名——**租户改过字段名时看这条**,别硬编码 fieldId。
816
+ - **⛔ 别把「人 / 地点 / 类型」塞进 `extraFields`**(2026-10-30 真机:agent 这么干,被服务端打回
817
+ "请按名称选择"):会议地点、参会人员、召集人、联系人、会议类型都有**专用入参**
818
+ (`address` / `hrm_members` / `caller` / `contacter` / `mt_type`),CLI 会把值补成浏览按钮要的
819
+ `{id, name}` 对象。塞进 `extraFields` 会按纯文本提交,必被打回。
820
+ `extraFields` 只用于租户自建字段(参会客户 / 联系方式这类纯文本)。
821
+ - **「会议类型」在很多租户的表单里是必填**:`create.flow.prepare` 的返回会列出表单全部字段名,
822
+ 缺必填时 `createRequest` 会报缺字段。**先 `meeting.eb.type.list` 拿到类型名/id 再传 `mt_type`**,
823
+ 不要等报错了才补。
576
824
  - **浏览按钮字段必须传对象 `{"id":"…","name":"…"}`**(实测):
577
825
  会议地点(会议室)、参会人员(数组)、召集人 / 联系人(单人)传**纯 id 或纯姓名都会被当"名称"去匹配**,
578
826
  匹配不到就返回 `status: NEEDS_CONFIRMATION`("无法唯一解析的选项")——这不是流程走不通,是值格式不对。
@@ -594,11 +842,13 @@ weaver-work-cli --json meeting run meeting.eb.meeting.create.flow.apply \
594
842
  CLI **不会**替你取第一个(2026-10-29 修的就是这个:旧版把数组拼成 `"a,b"` 当单个 id,下游取了第一个能载入的,
595
843
  结果字段全填不进另一条流程的表单,用户以为"系统只支持一条")。只有**用户明确点名**某条流程后才传单个 id。
596
844
  - **流程 id 的权威链(唯一):入参 `workflowId`(用户已选定)> 应用设置 `mt_new_wf`。**
597
- - **⛔ 禁止用关键词检索流程**。不要用 `workflow.search`、也不要传 `workflow: "会议"` 去"探明有哪些建会流程"。
845
+ - **⛔ 会议建会**禁止用关键词检索流程。不要用 `workflow.search`、也不要传 `workflow: "会议"`
846
+ 去"探明有哪些建会流程"。
598
847
  **真实事故(2026-10-29)**:agent 用关键词「会议」检索,返回 11 个候选,
599
848
  把「会议室预定流程-北方大区业务运营中心」排在第一并抛给用户,用户当场质疑"我们配置的流程不包含这个"。
600
849
  配置里已经给出 id,检索没有任何信息增量,只会引入干扰项。
601
850
  (只有"用户只报了流程名称、确实拿不到 id"时才需要澄清,且要用名称精确定位、不要用宽泛关键词。)
851
+ ✅ 这条**只管会议建会流程**;查待办、查审批、发起请假报销等,正常用 `workflow.*`。
602
852
  - **默认不要传 `workflowId`**:让 CLI 自己读 `mt_new_wf` 并处理多值(探测 + `NEEDS_SELECTION`)。
603
853
  **⛔ 更不要自己先读应用设置、再 split、再挑一个传进去** —— 这正是 2026-10-29 "明明配了 2 个流程却只用 1 个"
604
854
  的成因:agent 自行取第一个,CLI 完全无从察觉,也就无法纠正。把选择权留在 CLI/用户手里,不要提前决定。
@@ -52,6 +52,29 @@
52
52
  > 未传 `sign_time` / `signback_time` / `sign_out_status` 时按"补签"语义**自动补当前时间**(带秒)并写入 `warnings`,
53
53
  > 实际写入值在 `preview.after` 里可见;要指定时间请显式传 `sign_time`(`yyyy-MM-dd HH:mm:ss`,带秒)。
54
54
 
55
+ ## 会议室列表:按名称查询(2026-10-30)
56
+
57
+ `meeting.eb.room.list` 支持 `room_name`(以及 `status` / `place` / `org_id` / `hrm_ids`)过滤,
58
+ 条件走 body 的 `datajson.mainTable`,count 与 list 用**同一份**条件。
59
+
60
+ ```bash
61
+ # 精确名 → 服务端直接命中,1 次请求
62
+ weaver-work-cli --json meeting run meeting.eb.room.list --input-json '{"room_name":"测试会议室1"}'
63
+
64
+ # 部分词 → 服务端精确匹配不到(0 条),CLI 自动翻页扫全量并按「包含」重筛
65
+ weaver-work-cli --json meeting run meeting.eb.room.list --input-json '{"room_name":"重庆"}'
66
+ ```
67
+
68
+ ⚠️ 三个实测事实(e-cology 生产,2026-10-30):
69
+
70
+ 1. **服务端是精确匹配,不是 like**:`room_name=测试会议室1` → 1 条;`room_name=测试` → 服务端 0 条。
71
+ 所以传部分词时 CLI 会兜底翻页扫描(结果带 `progress.page.fallback = {pages, scanned}`),
72
+ 实测 155 条扫完约 5 秒。传 `noFallback:true` 可跳过扫描(精确匹配不到就直接 0 条)。
73
+ 2. **`pageSize` 服务端不生效,恒定回 10 条** —— 要全量只能翻页(兜底就是这么做的)。
74
+ ⛔ 别把"本页 10 条"当成"总共 10 间"。
75
+ 3. **列表 0 条不等于没有会议室**:2026-10-29 全天该接口为 0 条(应用侧视图配置问题),
76
+ 10-30 下午租户把「会议室名称」配成传入字段后恢复到 155 条。
77
+
55
78
  ## 常用命令
56
79
 
57
80
  Windows PowerShell:
@@ -758,3 +781,111 @@ video_taskResult 为空 且 parse_content 为空 → 未触
758
781
 
759
782
  实测遇到两次(`update_mt_decision_task` 首次调用、EB 列表接口),**重试即成功**,且数据未被写坏。
760
783
  判定方法:报这个错时先 `list` 回查;没写进去再重试一次,**不要连试三次以上**。
784
+
785
+ ## 流程建会字段:datakey(fieldId)固化
786
+
787
+ **为什么**:NEW 建会流程(`1325677244111462606`)的表单字段名带提示语 ——
788
+ `会议名称(请填写会议的具体名称)`、`开始时间(具体开始时间)`、`结束时间(具体结束时间)`。
789
+ 按中文名**精确**匹配会全部落空,表现为 prepare 显示成功、但名称/时间实际没填进去(2026-10-30 真机踩到)。
790
+ 现在两级兜底:① 归一化匹配(去掉括号提示语再比);② 解析结果按 workflowId 缓存成 datakey,之后直接用 id。
791
+
792
+ **泛微生产(www.e-cology.com.cn / t7akvdnf84)·「会议申请流程(NEW)」实测 datakey**:
793
+
794
+ | 语义键 | 表单字段 | datakey |
795
+ | --- | --- | --- |
796
+ | 会议名称 | 会议名称(请填写会议的具体名称) | 1325677252711735872 |
797
+ | 开始时间 | 开始时间(具体开始时间) | 1325677252711735890 |
798
+ | 结束时间 | 结束时间(具体结束时间) | 1325677252711735891 |
799
+ | 会议地点 | 会议地点 | 1325677252711735881 |
800
+ | 参会人员 | 参会人员 | 1325677252711735882 |
801
+
802
+ 按 datakey 直接给值(绕过任何名字匹配,用 `fieldValues`):
803
+
804
+ ```bash
805
+ weaver-work-cli --json meeting run meeting.eb.meeting.create.flow.prepare --input-json '{
806
+ "fieldValues": {
807
+ "1325677252711735872": "十一月开发进度沟通会",
808
+ "1325677252711735890": "2026-10-31 10:00",
809
+ "1325677252711735891": "2026-10-31 11:00",
810
+ "1325677252711735881": {"id":"1325772901753847972","name":"测试会议室1"},
811
+ "1325677252711735882": [{"id":"4980990112251498198","name":"卜伟领"}]
812
+ }
813
+ }'
814
+ ```
815
+
816
+ ⚠️ 浏览按钮类字段(会议地点 / 参会人员 / 召集人 / 联系人 / 会议类型)的值必须是 `{id,name}` 对象或数组,
817
+ 纯文本会被服务端打回「请按名称选择」。
818
+
819
+ 缓存文件:`~/.weaver-work-cli/meeting/cache/flow-fields-<workflowId>.json`。字段改名后仍按 datakey 填;
820
+ 流程被重建、datakey 变了,删掉该文件让它重新解析即可。
821
+
822
+ ## 查「CLI 到底有哪些能力」
823
+
824
+ ```bash
825
+ weaver-work-cli meeting ops # 全部 135 项,纯文本、不压缩、按能力分组
826
+ weaver-work-cli meeting ops --grep suggest # 按名字/摘要搜(不区分大小写)
827
+ weaver-work-cli meeting ops --capability eb.meeting # 按分组看(支持前缀,如 --capability eb)
828
+ ```
829
+
830
+ ⛔ **不要用 `meeting schema --json` 判断能力存在性**:完整结果 308KB,stdout 只回 20KB 预览,
831
+ `operations` 数组被截到前 10 条,排在后面的 operation 一定看不到。
832
+ 2026-10-30 真机事故就是这么来的——agent 在 schema 预览里没找到 `meeting.eb.meeting.create.suggest`,
833
+ 于是回复用户「当前 CLI 版本没有建会建议时间操作」,而该 operation 一直存在且可用。
834
+
835
+ ## 时间和会议室:必须由用户确认(timeConfirmed / roomConfirmed)
836
+
837
+ `create.flow.prepare` / `quick` 用两个标记区分「用户定的」和「agent 猜的」:
838
+
839
+ | 标记 | 传 true 的**唯一**两种情形 |
840
+ |---|---|
841
+ | `timeConfirmed` | ① 用户原话明确给出时间("明天 9 点到 10 点");② 用户在时段选项里点选后把 `options[].value` 整体原样回传 |
842
+ | `roomConfirmed` | ① 用户原话明确指定某间会议室;② 用户在房间选项里点选后把 `options[].value` 整体原样回传 |
843
+
844
+ 不传(或 false)时:
845
+ - 即使传了 `begin_datetime`,也返回 `selectionType: 'slot'`(3 个时段选项),**不会**进确认摘要;
846
+ - 即使传了 `address`,也返回 `selectionType: 'room'`,把「你指定的那间」标成
847
+ `(你指定的,待确认)`排第一位,其余候选照常列在后面;
848
+ - `room_conflict`(占用拦截)只在 `roomConfirmed: true` 时才触发——没确认的房间不拦,只列出来。
849
+
850
+ 这样设计的原因:2026-10-30 用户投诉「会议室没有推荐让我选择,时间没有推荐让我选择,智能体自己就决定了」。
851
+ 旧行为里,agent 只要填了值 CLI 就照收,用户看到的是既成事实。
852
+
853
+ 排查口诀:**选项回来的 `value` 要整体回传**(里面自带标记);只抄 `begin_datetime` / `address`
854
+ 单个字段会丢掉确认标记,于是被再问一轮。这不是 bug。
855
+
856
+ ## 闸门顺序:四要素先定,流程最后(2026-10-30 用户纠正)
857
+
858
+ `create.flow.prepare` 的顺序是固定的,**不要试图跳步**:
859
+
860
+ ```
861
+ 名称(mt_name,必填) → 时间(slot) → 地点(room / room_conflict / room_unavailable) → 流程(flow) → 确认(AWAITING_CONFIRMATION)
862
+ ```
863
+
864
+ - 时间没确认(没带 `timeConfirmed`)时**不会出现 flow 选择**,先给时段;
865
+ 地点没确认(没带 `roomConfirmed`)时同样不会出现 flow 选择,先给房间。
866
+ - 到 `selectionType: 'flow'` 这一步,四要素已经全部确认,返回里带 `confirmed`
867
+ (`mt_name` / `begin_datetime` / `end_datetime` / `address` / `addressName` / `hrm_members`),
868
+ 每条 `options[].value` 也带着 `begin_datetime` / `end_datetime` / `address` + 两个确认标记。
869
+ **用户点选后把 value 整个回传**,下一轮直接 `AWAITING_CONFIRMATION`,不会再问时间/地点。
870
+ - 为什么要这样:用户原话「流程只是审批载体,应该先确认时间、人、地点、名称,再选流程」。
871
+ 流程选择放到最后,用户在前三步就已经知道这会开不开得成,最后只是挑个审批口径。
872
+
873
+ ## 时段候选到底核验了什么
874
+
875
+ `selectionType: 'slot'` 的每个候选都必须同时满足两件事,缺一不列:
876
+
877
+ 1. **人空闲**:`findCommonFreeSlots` 先拉该时段所有会议候选 + 批量回执(`query_meeting_receipt_list`),
878
+ 再叠加日程(ESB 动作流,**已过滤「会议日程」类型**,避免与会议回执重复计),
879
+ 内存里按 30 分钟切槽判重叠 —— 任一参会人有占用就跳过该槽。
880
+ 2. **会议室空闲**:每个「人空闲」的槽再并行跑 `room.recommend`(排除封存、容量不足、该时段被占用),
881
+ **一间可用房都没有的槽会被直接剔除**(不会出现"时间有了但没房间"的假选项)。
882
+
883
+ 所以 `options[].reason` 里那句「N 人全部空闲(会议回执 + 日程已核);M 间会议室可用:…」是**核验结论**,
884
+ `options[].rooms` 是该时段真实的可用房间清单(含容量与推荐理由)。
885
+
886
+ 边界(会写在 `warnings` 里,必须如实转达):
887
+ - **没传参会人** → 只核验了房间,人没核验;
888
+ - **姓名查不到员工 id** → 该人**未核验**(不会算进"全部空闲");
889
+ - **ESB 日程调用失败** → 退化为只看会议回执,`scheduleItems` 为空可判断;
890
+ - 被剔除的槽在 `skippedSlots` 里("人空闲但没房间"),可以据此解释为什么候选少。
891
+