You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

26 KiB

客户模块(A4)后端 spec — 复核交接清单

用途:交付给一个全新的、无本会话上下文的会话做第二轮 grill / 独立复核。 上一轮共 19 个 grill 决策(D18–D29 + D4-rev1/rev2)已全部由用户拍板。本清单的目的不是报喜,而是把最可能被推翻的点提前摊开,供下一轮挑战。


0. 怎么读这份清单

  • 权威交付物.scratch/customer-module/map.md(决策索引 D1–D29,自包含)+ issues/NN-answer.md(各票详细决议,自包含)。
  • 原型出处D:\code\crm-需求梳理\lanhu-mcp\data\axure_extract_bade4454_screenshots\a4-*.txt(蓝湖 A4 页面已本地提取文本)。
  • 对称参照.scratch/opportunity-module/map.md(已完成的商机图,本图大量对称其范式)。
  • 领域上下文crm-customer/CONTEXT.mdcrm-lead/CONTEXT.mdcrm-opportunity/CONTEXT.md
  • 协作规范docs/agents/issue-tracker.mddocs/agents/triage-labels.md

复核建议:先读 map.md 的 Decisions 区(D1–D29,约 5 分钟),再逐个挑战下面「第 4 节薄弱点」。不要因为 map 里写了"已拍板"就跳过——这是本清单特意要求的。


1. 本图范围(D2)

(8 大块):客户核心(实体+查重+公海+总览+我的客户+三视图+新增/编辑+导入)、联系人(CRUD+全局搜索+电话查重)、客户交割、客户规则族(超期提醒 + 查重设置)。

留 seam(依赖未建):报备成功链路(方案卡已推送/A5 回调)→ 客户「重潜」阶段(D20 改票 B,本期潜在→重潜不触发);A5 项目模块 → 客户「已成交」阶段、「关联项目」详情页签、汇总卡「合同总额·累计回款」。

划出(Not-yet / Out-of-scope):战略协议、联系人图谱(职务二级联动)、客户查重列表+客户合并(A4-6)、企查查/OCR 外部服务内部实现(只定契约 seam)、OCR 快捷新增、联系人导入。


2. 已冻结的决策(D1–D29 速览)

# 决策要点 原型/出处
D1 spec-only,对称商机图;做完进 /implement
D2 作用域三档划分(见上)
D3 双轴建模:轴1 归属(owner 空=公海)正交 archive_status;轴2 阶段三态只前进 a4-2-1
D4-rev1 客户规则族只含「超期提醒 + 查重设置」;星级/阶段退回硬编码 a7-2-3
D4-rev2 查重设置 = crm-rule 全局单例可配置,本期只消费于新增/编辑内建查重 a7-2-3-查重
D5 联系人 = crm-customer 独立表 customer_contact,权限继承客户 a4-4
D6 内建查重口径(后被 D4-rev2 改为可配置) a4-3-3
D7 客户主表字段八区 + DataScope + 索引(无孤立单大写陷阱) a4-3-3
D8 超期提醒:crm-rule 单例配置 + 待发通知表 + Job 只落待发 a7-3-3
D9 三视图/公海/总览 = 逻辑视图,内置视图不入库 a4-1-1/a4-2-1
D10 分层查重 + CustomerDedupService + 企查查 seam a4-3-3
D11 阶段只前进 CAS(三态字段/机制保留);重潜触发本期 seam 化不实现(D20 改票 B) a4-4
D12 联系人 CRUD + 全局搜索;电话查重软提示(D26);来源字典(D27) a4-4
D13 详情 8 页签 + 跟进 append-only + 字段级 oplog;卡片占位(D28) a4-4
D14 建 crm-customer/CONTEXT.md;依赖方向 opp→customer
D15 交割两段式;直属总监(D22);完成判定(D23) a4-7
D16 导入三模式 + 异步 + 行级部分成功;多行默认(D24) a4-3-2/a4-3-5
D17 超期提醒规则表/Job 细节 a7-3-3
D17b 保存视图复用平台,3 scope_key;enter_pool_time 可排序(D29) a4-1-1
D18 customer_type = crm-dict 字典,18 值(含4甲方+14非甲方) a4-3-3 弹窗
D19 归档=删除(软删);去掉「已被合并」态;列表筛选 default 排除已归档 a4-2-1
D20 重潜本期不触发、只留 promote seam(等「提交并报备成功」链路,不用「已提交」凑合) a4-4-1
D21 相似判定 seam 化;一期最简 = MySQL ngram FULLTEXT;阈值从配置读 a7-2-3-查重
D22 直属销售总监 = 组织架构推导(dept.leader 向上找销售总监);不改 crm-auth a4-7-1
D23 交接单完成 = 自动(assignedCount==totalCount);无手动按钮 a4-7-1
D24 导入多行匹配同一客户默认「重复时不导入」(重复组全失败) a4-3-5
D25 超期提醒锚点 = 成为「有主」时刻;公海 NULL 不计时;领取时赋锚点 a7-3-3
D26 电话查重=可配置软提示(不建唯一索引);同客户内电话不重复为表单级校验 a7-3-3-2 查重设置
D27 contact_source 字典种子 = 组会/组局/转介绍/其他 a4-4-1
D28 汇总卡占位一律渲染 + 显"--"(不显 0,不留白) a4-4-1
D29 公海「进入公海时间」列保留 + 加入排序字段池 a4-1-1

3. 为什么我信不过自己——复核方法论

用户的担忧是对的。上一轮我犯过SOP 违规(票 02–11 未经 grill 就标记 resolved),后来被迫全部重开重问。因此第二轮复核请遵循:

  1. 每个决策都要能找到"证据":要么是原型页面(a4-*.txt 的原文文字),要么是用户当时明确说过的选型(如 Q8 的 18 值、Q16 的"全部电话")。找不到证据的就是我编的,请当误入标注出来。
  2. 每个"定稿"都可被推翻D20(重潜触发点=已提交…请重点挑战) D20 已于 20260902 复核翻案为 B(本期不触发、留 seam),见 §4.1、D22(组织架构推导在无组织数据/多领导时的降级行为我写的是"阻断",但用户可能预期"降级给普通接收人")。
  3. 决策之间的一致性:D8/D25(锚点)、D19/D3(归档)、D4-rev2/D6(查重口径)、D12/D26(电话唯一)、D4-rev1/D7(星级)——若两条决策互相打架,是我没对齐。

4. 我最担心的薄弱点(请下一轮重点挑战)

4.1 D20 重潜触发 —— 用户拍板 B(20260902):本期不触发、只留 seam,翻案

  • 我选了「保守」口径:方案卡状态到「已提交」就触发客户重潜。
  • 风险:原型 A4-4 的重潜定义其实写着「关联的任一方案卡提交并报备成功」。我因为「报备/推送链路本期不可达」而收窄成「已提交」。用户可能完全接受,也可能说"那就等报备成功再触发,本期不实现重潜"。
  • 请问:报备链路不可达时,是「用已提交凑合触发」还是「本期干脆不实现重潜、只留 seam」?
  • 第三轮 fresh 复核(20260902)a4-4-1(8-26 fresh)L359/L412 原文明文「任一方案卡提交并报备成功后 → 重潜客户」= 两个条件。用「已提交」单条件凑合会造出「提交了但报备没成功、客户却已重潜」的错误状态。
  • 已拍板(用户选 B,20260902):本期不自动触发潜在→重潜,客户阶段实际只有「潜在」;CustomerStagePort.promote seam(契约/只前进 CAS/幂等)全部保留,等报备成功链路(方案卡「已推送(3)」或 A5 回调)就绪再接入调用。不用「已提交」凑合。 map.md D20/D11 + 票 05-answer + CONTEXT.md 已同步。

4.2 D22 直属销售总监 —— 已确认(grill Q12 拍板 A),复核补全「调动/区域调整=下拉选」分支

  • 复核发现:票 08-answer L15/L23 已把口径写全 = 离职=组织架构推导自动定唯一总监(无/停用/多条→阻断提示管理员);岗位调动/区域调整=在本人启用的直属总监内下拉选(不阻断)
  • 原 HANDOFF 4.2 段只描述了「离职=推导阻断」这一半,漏了下半句。非决策遗漏,是记录不全。修正:阻断仅离职专属;调动/区域调整为可选下拉,不阻断。
  • 已确认(20260902):无需翻案,仅补齐 map.md D22 描述(补充「调动/区域调整=下拉选、离职才阻断」)。不改 crm-auth、不加 superior_user_id 维持原判。

4.3 D4-rev1 把「星级/阶段设置」踢出客户规则族 —— 阶段 A口径 / 星级 已三点确认(20260826)

  • 阶段:第二轮复核拍板 A 口径 —— 客户阶段=固定三态(潜在→重潜→已成交),只前进不回退,不建 a7-2-3 客户阶段设置。D4-rev1 对阶段部分正确,保留
    • 依据:a4-4-1 详情页 3 次强调「阶段由业务结果驱动、阶段条不可点击修改、只前进不回退」,与 A 口径一致。
    • 注:a7-2-3 阶段设置 页与详情页内部矛盾(可增删/排序/迁移 vs 只前进不可配),已裁决按详情页(A 口径)走,设置页视为原型残留。
  • 星级 已确认原判成立(第二轮复核,用户拍板 20260826)。我上一轮引用「关系星级名称+描述由管理员自定义」是基于过时原型缓存a7-2-3_星级设置_.txt 为 2026-07-20 旧快照,仍是「潜在/高潜/合作/重点/战略 + name/desc 可配」老口径)。新原型已更新a4-3-3-1_新增客户信息.txt(2026-08-26)L91-106 显示客户星级、关系星级均为「一星~五星」两个普通下拉字段,无 name+desc 可配语义。用户三点确认:①客户星级/关系星级=两个 1~5 星字段;②D4-rev1「星级退回硬编码枚举 1~5」确认成立(非翻案);③星级彻底不进客户规则族a7-2-3 星级设置页当作不实现,同阶段设置页处理)。我上一轮「关系星级必须可配」的纠偏作废。

4.4 D26 联系人电话查重 —— 用户拍板 A(20260902):降级为可配置软提示,翻案

  • 用户拍板选了「全部电话唯一(含座机/短号)」——比我的推荐(仅手机号 11 位唯一)更强。
  • 风险:座机/短号撞号概率实际远低于手机号;但同一个公司多个联系人的座机可能共用一个总机号,这会误伤。强制唯一可能让"一个公司两个联系人都填了同一个座机总机"这种正常场景无法保存。
  • 请确认:是否真的对座机也做全局唯一?要不要豁免「座机且同客户」?
  • 第三轮 fresh 铁证(20260902,重新提取 8-26 原型 HTML)——D26「电话全局唯一」被查重设置页正面推翻:新版 a7-3-3-2_客户管理设置_客户查重设置_.txt(源 HTML 2026-08-26)逐条否定电话唯一约束
    • 总开关仅控制客户名称、联系电话的重复提醒」——电话查重是「提醒」不是「约束」;
    • 统一社会信用代码为系统强制规则,不受总开关影响,不提供关闭开关」——只有信用代码是唯一强制
    • 通用判断规则:「统一社会信用代码精确命中时,禁止创建客户;客户名称或联系电话任一命中时,提示疑似重复客户」——电话命中只提示、不阻断;
    • 「联系电话:支持单独开启或关闭;匹配方式固定为精确匹配;命中时提示疑似重复」——电话查重可被管理员整体关闭。
  • 结论:原型口径下电话查重 = 可开关的软提示(提示疑似重复,不禁止创建),与 D26 主张的「电话全局 DB 唯一索引 + 撞号即拒绝保存直接冲突。D26 是过度设计:把原型的软提示误升级为硬约束。
  • 座机豁免问题自动消解:既然电话查重本来就只是"提示疑似重复、不禁止","多个联系人共用总机座机导致无法保存"的误伤场景根本不存在——因为原型从不因电话撞号阻止保存。
  • 新增页佐证a4-3-3-1_新增客户信息.txt(8-26)§3.5「联系电话存在时…按电话值查重;电话值完全相同时禁止新建」仅约束同一表格内两行(同一客户内联系人不能填相同电话),不是跨客户全局唯一
  • 建议:D26 从「电话全局唯一索引」降级为「可配置的电话查重提示」(跟随 crm-rule 客户查重设置单例的"联系电话"开关),DB 层不建电话唯一约束;仅保留同客户内联系人电话不重复的表单级校验。待用户拍板改票 06 D26。
  • 已拍板(用户选 A,20260902):采纳建议。D26 改票:uk_contact_phone(phone) 唯一索引撤销;电话查重=可配置软提示(跟随 crm-rule 查重设置「联系电话」开关);仅保留同客户内联系人电话不重复的表单级校验。map.md D26/D12 已同步改口径。

4.5 D18 customer_type 18 值——已证实,非编造(第二轮复核,证据在 a4-1-1

  • 原判断撤销:第一轮我 grep 只搜 a4-3-3-1 新增页,漏了 a4-1-1 公海列表,误判"部分编造"。
  • 决定性证据a4-1-1_客户公海列表.txt L45-63 是客户类型筛选下拉的完整展开枚举运营商 / 土建总包 / 机电总包 / 装修总包 / 教育局 / 投资(代建)公司 / 设计院 / 集成商 / 招标代理 / 咨询造价公司 / 甲方(企业用户)/ 甲方(普教)/ 甲方(中高职)/ 甲方(政府机关)/ 竞争同行 / 个人用户 / 操手 / 集成商(子客户) = 17 具体值 + 1"全部客户类型"占位 = 18 值
  • 与票 02 列表逐字一致(含"投资(代建)公司""集成商(子客户)")。消号,D18 成立
  • 第三轮 fresh 复核(20260902,重新提取 8-26 原型 HTML):新版 a4-1-1_客户公海列表_列表视图_.txt(源 HTML 时间戳 2026-08-26)里客户类型筛选下拉未展开,文本提取只捕获表格样例行的 4 个值(甲方(中高职)/甲方(企业用户)/甲方(政府机关)/甲方(普教)),全部落在旧 18 值集合内,无新增/删除迹象;a4-1-1 列表视图 data.js 仅含 甲方(中高职) 单元格值,18 值枚举不在页面级资源。新原型正面印证决策架构a4-3-3-1_新增客户信息.txt(8-26)需求文档「枚举与人员数据」明确「下拉枚举只加载后台配置的启用项」「已停用枚举可在编辑场景回显,新增时不可选」——即客户类型 = 后台配置字典,与 D18「crm-dict 字典分组、非硬编码」完全吻合。结论:D18 架构决策获新证据强化;18 个具体种子值来自 7-20 枚举、新原型未反证(样例值均在集合内),种子值列表仅影响初始化脚本、不影响架构。D18 保持。

4.6 D24 导入「重复时不导入」默认 —— 已确认(grill Q14 用户拍板 A),非缺陷

  • 我默认「重复时不导入」(重复组全失败)。但很多导入场景用户是想"更新老客户"的,默认不导入可能让大批行失败。
  • 请确认:默认到底该是「不导入」还是「更新」?还是按导入方式(仅新增/仅更新)各自定?
  • 已确认(grill Q14,用户拍板 A):文件内多行匹配同一客户,覆盖导入/重复时不导入 互斥,默认「重复时不导入」——重复组全部标失败不写入,用户看失败明细处理。覆盖模式作为可选项存在但不默认。

4.7 D21 ngram FULLTEXT —— 已确认可用(MySQL 8.4.8)

  • 一期最简用 MySQL ngram 分词器(token_size=2)。ngram parser 是 MySQL 5.7.6+ 功能,且对中文分词效果一般(会切出大量无意义二元组)。
  • 请确认:项目 MySQL 版本是否 ≥5.7.6?若偏低,ngram 不可用,得回退 LIKE + Levenshtein(或我提过的 Jaccard)。
  • 已确认(20260902):项目 MySQL = 8.4.8,≥5.7.6,ngram 分词器可用,无需回退。

4.8 D17b 保存视图复用平台 —— 已确认(user_saved_view 支持多 scope_key)

  • 我复用现有保存视图平台并假设它支持多 scope。请核对 crm-auth / 现有平台的 user_saved_view 表结构和 scope 机制,确认"公海/总览/我的客户"各存一套视图不会串。
  • 已确认(20260902)user_saved_view 平台支持多 scope_key(每入口各存一套),公海/总览/我的客户各自保存不串。

4.9 D9 视图「内置视图不入库」 —— 已确认(逻辑视图,内置硬编码)

  • 我写内置视图(如"我的客户-未跟进N天")硬编码不入库,用户自定义视图才入库。但这个边界(哪些算内置、哪些算自定义)我没问用户,是拍脑袋定的。
  • 请确认:哪些内置视图是必须的?用户能不能改/删内置?
  • 已确认(20260902):三个 workspace(公海/总览/我的客户)= 逻辑视图,靠 @DataScope + owner_user_id IS NULL + archive_status 过滤区分,不建独立表;内置视图(含常用检索)硬编码不入库,用户自定义视图才入库,边界成立。

5. 需要用户明确但我可能漏问的点

  1. 公海 vs 我的客户是否允许"重复看到同一客户":一个客户在公海,同时又被我领了,会不会同时在两个列表出现?(我默认:有主就只在我的客户,公海只出无主,二者互斥。)
    • 原型铁证已定向(20260902)a4-1-1_客户公海列表_列表视图_.txt(8-26)领取确认弹窗 L327/329 明文「领取后,该客户将归属当前账号,并从客户公海移除」;批量领取 L341-347 同理「领取后,以下客户将统一归属当前账号,并从客户公海移除」。
    • 结论§5.1 消号。公海与我客户互斥(领取=移出公海,归属有主)。D3(归属⊥归档双轴)+ D9(公海=owner IS NULL 逻辑视图)原判正确,维持。无需拍板。
    • 区分「关注」:公海列表有「关注/取消关注」(个人关注状态,如 L89 取消关注 / L129 关注),关注≠领取,不改变归属,客户仍在公海。「我关注的客户」是检索维度,可含公海客户,但不影响互斥模型。
  2. 客户能否被多个负责人共同跟?我默认单负责人(owner_user_id 单值)——但原型有"团队成员"页签,可能暗示多协作者。这是竞品常见分歧点,我没问。
    • 原型铁证已定向(20260902)a4-4-8_客户详情_团队成员_.txt(8-26)需求说明 11.1 角色与管理权限 明文「每个客户只允许 1 名负责人,其余成员均为协同人(如销售协同人、方案工程师等)」「协同人可查看对应客户的信息」。团队成员页签展示角色列(负责人/协同人)+ 添加成员(搜索多选、不可重复)+ 删除成员(二次确认、仅撤销后续访问权限、不影响历史记录)。
    • 结论§5.2 消号。客户单负责人(owner 单值)+ 多个协同人(团队成员表),协同人可见但非负责人。D3/D5/D7 单负责人原判正确,维持;「团队成员」页签 = 负责人+协同人列表,非多负责人。无需拍板。移除「多负责人」这一待确认项。
  3. 删除语义:D19 已归档=软删,但「归档」按钮 vs「彻底删除」——有没有彻底物理删除的入口?我默认没有(只有归档)。
    • 原型证据已梳理(20260902):客户「删除」= 逻辑删除deleted 标志),无前端直接"删除"入口、无物理删除。依据:
      • a4-4-1_客户详情_客户信息_.txt 操作区仅「归档」(L127)+「标记重点客户」,无"删除"按钮
      • a4-4-1_客户详情_已归档客户_.txt 提供「恢复」(L47)+ 归档条件(L325-335:有进行中商机/未完成项目/待审批流程/未履约合同/未结清款项→不允许归档;归档不填原因不审批直接执行;归档成功取消跟进提醒);
      • a4-6-3_客户合并.txt L323「合并成功后保留主客户,将其他已选客户标记为已合并并执行业务软删除,不做物理删除」;
      • a4-3-3-1_新增客户信息.txt L690 / a4-6-1 L315 查重范围 = 「全部未删除客户」→ 存在 deleted 逻辑删除标志。
    • 建议:D19 归档=软删(archive_status=已归档,可恢复原判维持);客户deleted 标志 = 系统级软删除(合并/数据治理用,非前端功能),前端不暴露"删除客户"入口。三态档案(有效/已归档/已被合并)+ deleted 软删标志并存,需确认 deleted 是否仅合并时由系统置 1(而非用户手动删)。此项需你拍板:客户删除入口是否彻底不做?
    • 已拍板(用户选 A,20260902)一期只做归档——不提供任何前端"删除客户"入口;用户侧只有归档(软删可恢复)+ 合并(源客户系统软删,且合并本体 Out-of-scope);deleted 标志仅系统在合并时置 1,不开放手动删除、无前端删除按钮;DB 不做物理删除。票 02-answer(archiveStatus 三值→两值去掉已被合并、deleted 补充说明)+ 票 01-answer 已同步。
  4. 导入时的邮箱/电话查重 已解决(D26 翻案 20260902):D26 电话不再唯一,导入时跨客户电话撞号=软提示疑似重复、不阻断(列明细,跟随查重设置开关);同一文件内同客户电话相同两行=该行失败。已回填票 09-answer。
  5. 操作日志保留时长:customer_oplog 字段级日志,有没有保留期/归档策略?我默认无限期。
    • 原型证据已定向(20260902)a4-4-8_客户详情_操作日志_.txt(8-26)只强调审计属性、未提保留时长——L250「日志生成后不可修改或删除」,L232「仅记录提交成功后的业务变更」,L188 操作类型固定枚举(新增/修改/归档/恢复/关联/取消关联/状态变更/负责人变更/添加成员/移除成员/合并/导入/导出/敏感信息查看/系统操作)+ L199 字段级「旧值→新值」。即原型把操作日志定位为 append-only 审计日志
    • 结论:保留时长原型无要求 = 技术决策(非规格缺口)。已拍板(用户选 A,20260902)customer_oplog 无限期保留——① 审计日志要求完整、不可删改(L250),保留期会截断审计链;② 字段级日志量可控(客户主记录操作频次低);③ 无清理逻辑最简、无运维负担。票 07-answer 已补保留策略行。

7. 本轮复核结论(20260902,fresh 原型第三轮)

复核方式:对 4 个 7-20 过期快照页(a7-3-3-2 查重设置 / a7-3-3-1 超期提醒 / a4-4-1 客户信息 / a4-1-1 公海列表)用本机 Lanhu Python MCP 重新提取 8-26 fresh 文本,逐项对照。

§4 九个薄弱点 —— 全部闭环

结论 拍板
4.1 D20 重潜触发 翻案:原型=「提交并报备成功」两条件,原判「已提交」错误 用户选 B:本期不触发、只留 seam
4.2 D22 直属总监 确认(补全「调动/区域调整=下拉选」,仅离职才阻断) 维持
4.3 星级/阶段 确认(阶段 A 口径 / 星级两点确认) 维持
4.4 D26 电话查重 翻案:原型查重设置页证明电话=软提示非唯一 用户选 A:可配置软提示、不建唯一索引
4.5 D18 18 值 消号强化:后端字典架构获 fresh 印证 维持
4.6 D24 重复导入默认 确认(非缺陷) 维持
4.7 D21 ngram 确认(MySQL 8.4.8) 维持
4.8 D17b 保存视图 确认(多 scope_key 不串) 维持
4.9 D9 内置视图不入库 确认(逻辑视图) 维持

§5 五个漏问点 —— 全部闭环(新增 2 个拍板)

  1. 公海/我客户互斥 —— 消号(领取即移出公海,原型 L327-347)
  2. 多负责人 —— 消号(单负责人 + 多协同人,原型 a4-4-8 明文「每个客户只允许 1 名负责人,其余均为协同人」)
  3. 客户删除入口 —— 拍板 A(一期只做归档):无前端删除按钮,deleted 仅系统合并置位
  4. 导入电话查重 —— 已随 D26 解决(软提示)
  5. oplog 保留时长 —— 拍板 A(无限期保留):审计日志不设保留期

本次修正的字段口径(D19 拍板后的遗留同步)

  • archive_status 收敛为 有效1 / 已归档2 两值(去掉「已被合并」,合并 Out-of-scope)
  • 已归档 = 删除语义(软删),不做独立 tab/子页,列表加 archive_status 筛选(默认排除)
  • 已同步:crm-customer/CONTEXT.md(L8/27-28/36/40/56)+ 票 01-answer / 02-answer + map.md D19/D9 + 各 research 子票加顶部废弃注记

结论全部 29 项决策 + 4 个复核翻案(D20/D26)+ 2 个新增拍板(§5.3 删除 / §5.5 oplog)已定稿,spec 冻结,可进入实现阶段。

6. 交付状态

  • map.md:D1–D29 全部记录,Frontier = 空,spec 冻结标记。
  • issues/NN-answer.md × 11:全部 Status: resolved,各⚠挂号/待确认小节已销号。
  • issues/NN-<slug>.md × 11:research/task 子票,全部 Status: resolved
  • crm-customer/CONTEXT.md + CONTEXT-MAP.md 行:已建。
  • 未动任何 Java 源码(git status 里的 Opportunity.java 变更与本 effort 无关,是既有改动)。

下一步:交给新会话按第 3、4 节方法复核。若复核对 4.1–4.9 有改动,改对应决策编号 + 重开相应票(如 D20 改 → 重开票 05),而非覆盖原决策(遵循编号+修正链约定)。